hexagon logo

ACOS numerical errors in Adams/Solver

I'm using vector operations to extract an angle during a simulation. The measurement consists of the dot product of two unit vectors which I then take the arc-cosine to extract the angle.
data_element create variable &
variable_name=.model_1.VAR_MdotX &
function= "UVX(MARKER_1)*UVX(MARKER_2)"
 
data_element create variable &
variable_name=.model_1.VAR_Angle &
function = "ACOS(VARVAL(VAR_MdotX))"
 
Occasionally in large (5000-10000) case Monte Carlo simulations I will get a handful of cases that fail in the middle of the simulation with errors like the following:
---- START: ERROR ----
  an invalid argument value occurred for function ACOS. Argument
  of ACOS must have an absolute value less than or equal to 1.
  The absolute value of the argument is 20.11355. The function is not
  defined for this value. If this is a numerical problem, consider
  using an expression involving ASIN, ATAN or ATAN2 instead.
 
I'm confused on why VAR_MdotX would ever evaluate to greater than 1 given that its the dot product of two unit vectors. Is storing MdotX in a separate state variable messing up the ACOS operation? I did this because MdotX is used elsewhere in the model for some other calculations.
 
Anyone have any thoughts on how to resolve/understand this issue?
 
  • Hi Michael,
     
    I have seen a minor bug where ASIN and ACOS functions ERROR out with expressions that evaluate to 1.0, which I reported for a fix. This ERROR message does not seem to end the simulation (in View or from CMD) and is just mistakenly generated.
     
    However, I am not sure how the error message that you are facing (w/ a value of 20.11355) has been caused. Can you please let me know if you are using Adams with Simulink OR whether you have any subroutines in the model?
     
    Thank you,
    Maziar Rostamian
    MSC Software
  • Hi Michael,
     
    You may get a better result if you use the UVX()*UVX() function directly inside the ACOS function, and not store it through another state variable.
     
    Regards,
    Henrik Skovbjerg
  • To further spin on Henrik's suggestion:
    By storing the intermediate results in a state variable, you have created exactly that; a state in the equation system. That means that this will be part of Adams solver routines, not only be subjected to error control but also to predictor behavior.
    When Adams attempts to take a step forward, it starts with predicting all states for the new time point t+dt based on the current and previous values of the states {t,t-dt,t-2dt...} (it also uses the state derivative at the current point). Then it feeds those predicted states into the equation system to see how far from zero the solution is (Adams uses implicit equation formulation; F-ma=0 basically). In this step it is easy for the predictor to "guess" an impossible value as it is a simple extrapolation at this stage. This is where you might see the impossible solution that might crash your run.
    By doing what Henrik suggests, putting the argument directly inside the ACOS function, you remove one state from the equation system and this intermediate result will never be extrapolated.
     
    PS. After the prediction phase, Adams solver uses a Newton-Raphson method to refine the solution and bring it close enough to zero to satisfy the error criteria.
  • Thanks everyone. @Henrik Skovbjerg​ 's suggestion eliminated the issue. Thanks @Jesper Slattengren​  for details on the underlying cause.
  • If you by some reason need that intermediate variable (use it in multiple places, measures or requests) you have to shield it. This is one way to do it:
    function = "ACOS(MAX(-1,MIN(1,VARVAL(VAR_MdotX))))"
    Similar thing when you divide with a variable value or perform other operations that has a limit on the inputs.
  • @Jesper Slattengren​  Thanks for that suggestion. The integrator seems to be okay with those MIN/MAX statements in my testing so far. I thought it might struggle a bit based on previous experience using MAX.
  • MIN and MAX are continuous functions but have discontinuous derivatives (in general, it is of course possible to feed arguments to them that makes them highly discontinuous.)
    But in this case it is not a problem as the MIN(MAX())) really makes sure that the derivatives are correct as a value outside of {-1,1} would make the system crash, so any prediction that would point outside this range is actually contained and evaluated to 1 (or -1)