VARSUB

The VARSUB evaluation subroutine computes an algebraic value for a VARIABLE statement (C++ or FORTRAN). VARSUB is optional. You only need it if you don't want to use a function expression in the VARIABLE statement.
 
Note:  
Use mixed case names for the Adams subroutine names when using the C style interface. For the default subroutine name capitalize the first letter and have the remaining letters lower case; Varsub for example. Doing this ensures that Adams Solver correctly distinguishes a C style subroutine from Fortran and calls with the appropriate interface.

Use

Corresponding Statement

Calling Sequence

CALL VARSUB(id, time, par, npar, dflag, iflag, value)

Input Arguments

id
An integer variable that contains the ID of the VARIABLE statement requesting information from VARSUB. From the identifier, Adams Solver automatically recognizes other information (such as the par argument) that is available in the corresponding statement.
time
A double-precision variable through which Adams Solver conveys the current simulation time.
par
A double-precision array of constants taken in order from the USER parenthetical list of the VARIABLE statement.
npar
An integer variable that indicates the number of constants you specify in the USER parenthetical list. The primary purpose of the npar argument is to provide VARSUB with the number of values stored in the par array.
dflag
A logical variable that Adams Solver sets to true when it calls VARSUB to evaluate the partial derivatives of the specified functions. Otherwise, Adams Solver sets the dflag argument to false.
iflag
An integer variable that Adams Solver sets to indicate why the routine is being called:
Adams Solver sets iflag to 3 when it needs the functional dependency of the user-defined variable. The functional dependencies are set with the same calls to the SYSARY and SYSFNC utility subroutines that are made to compute the value of the user-defined variable. If iflag is 0, Adams Solver computes the value of the user-written variable.
When your user-defined subroutine has static data that needs to be saved and restored to support the Adams Solver commands Save and Reload, then call the serialization functions for your data when iflag is set to 7, and the un-serialization functions when iflag is set to 9.
Note: In simple subroutines where serializing data is not needed, you can declare iflag as a logical variable. In this case you declare your dependencies when Adams Solver sets iflag to true, and compute the subroutine's value when Adams Solver sets iflag to false.

Output Arguments

 
value
A double-precision variable that returns the value of the variable.

Extended Definition

You can use the VARIABLE statement with the function expression to define most user-defined VARIABLE statements. However, if the expression becomes lengthy and awkward, you should use the FUNCTION=USER() argument in the VARIABLE statement, and write a VARSUB to define the VARIABLE statement.
You can call utility subroutines, such as AKISPL, CUBSPL, SYSARY, and SYSFNC, from VARSUB, to obtain information about system variables, user-defined variables, and splines (see AKISPL, CUBSPL, SYSARY, and SYSFNC).
The SYSARY and SYSFNC utility subroutines automatically set functional dependencies when the VARSUB argument iflag is not zero. To compute solutions efficiently, Adams Solver must know the other variables on which each user-defined variable depends. Adams Solver determines these functional dependencies at the beginning of the simulation by calling VARSUB with the argument iflag set to true. Adams Solver does this once for each VARIABLE statement with a FUNCTION=USER() argument. During each call to VARSUB, Adams Solver records which calls you make to SYSARY and SYSFNC. Adams Solver assumes the user-defined variable depends on those system and user-defined variables, and no others.
 
Tip:  
If the SYSARY or SYSFNC utility subroutines are called to access angular displacements, the values returned by them may contain discontinuities. To avoid the discontinuities, use the RCNVRT utility subroutine to convert the rotational angles from Euler angles to some other rotational representation that does not encounter a singularity.
 
Caution:  
When the iflag argument is true, you should make the same calls to SYSARY and SYSFNC as you do to compute the value of the user-defined VARIABLE statement. This ensures that Adams Solver has the proper functional dependencies. In general, Adams Solver may have difficulty converging to a solution and/or may take small integration steps if you fail to account for dependencies of the user-defined VARIABLE statement. These results usually cause large increases in execution time.
When the iflag argument is not zero, SYSARY and SYSFNC return zero values for system and user-defined variables. Computations that divide these values result in system errors when you execute Adams Solver. You should check for nonzero values or ensure that the iflag argument is set to zero before dividing by these values.
You must be careful when defining a VARIABLE statement dependent on another VARIABLE statement, or on other Adams Solver statements that contain functions. If you define a system of equations without a stable solution, the convergence may fail for the entire Adams Solver model. The following example refers to this type of VARIABLE statement:
VARIABLE/1,FUNCTION=VARVAL(1)+1  
When looked at as an algebraic equation, it looks like the following:
V=V+1
However, when Adams Solver tries to solve this equation using the Newton-Raphson iteration, the solution diverges and a message indicates that the corrector has failed to converge.

FORTRAN - Prototype

A sample structure for VARSUB is shown next. The comments explain how the subroutine works.
      SUBROUTINE VARSUB ( ID, TIME, PAR, NPAR, DFLAG,
     &                    IFLAG, VALUE )
C
C === Type and dimension statements ===================
C
C
C - External variable definitions ---------
C
      INTEGER                        ID
      DOUBLE PRECISION               TIME
      DOUBLE PRECISION               PAR( * )
      INTEGER                        NPAR
      LOGICAL                        DFLAG
      INTEGER                        IFLAG
      DOUBLE PRECISION               VALUE
C
C ID          Identifier of calling VARIABLE statement
C TIME        Current time
C PAR         Array of passed statement parameters
C NPAR        Number of passed parameters
C DFLAG       Differencing flag
C IFLAG       Initialization pass flag
C VALUE       The VARIABLE value returned to ADAMS
C
C - Local variable definitions -----------
C
      ...
C
C === Executable code =================================
C
C Assign parameters to readable variable names
C
      ...
C
C Call SYSFNC and/or SYSARY to collect information for
C calculations below. Note: if IFLAG is true, these
C calls are actually setting functional dependencies.
C
      CALL SYSFNC ( ... )
C
      CALL ERRMES ( ... )
C
C Repeat for all required SYSFN
C or SYSARY calls
C
      ...
C
      IF( IFLAG ) THEN
C
C - Subroutine initialization -----------
C
      ...
C
      ENDIF
C
C - Evaluate variable----------------
C
C Your algorithm
C
      ...
C
C Assign the returned value
C
      VALUE = ...
C
      RETURN
      END

C Style - Prototype

typedef void adams_c_VARSUB(const struct sAdamsVariable* variable, double TIME, int DFLAG, int IFLAG, double* RESULT);
/*
* VARIABLE
*/
struct sAdamsVariable
{
int ID;
int NPAR;
const double* PAR;
double IC;
};
 

Examples

For an example of this subroutine, see varsub.f.