The GFOSUB evaluation subroutine computes a set of six force values applied by a GFORCE statement (C++ or FORTRAN). You can use a GFOSUB when the functions are too cumbersome or complex to enter as expressions in a GFORCE 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; Gfosub 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
SUBROUTINE GFOSUB(id, time, par, npar, dflag, iflag, result)
Input Arguments
id | An integer variable that provides the identifier of the GFORCE statement requesting information from GFOSUB. 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 containing the current simulation time. |
par | A double-precision array of constants taken in order from the USER parenthetical list of the GFORCE statement. |
npar | An integer variable that indicates the number of constants you specify in the USER parenthetical list. This variable provides the GFOSUB evaluation subroutine with the number of values stored in the par array. |
dflag | A logical variable that Adams Solver sets to true when it calls GFOSUB 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 Argument
result | A double-precision array that returns the six values of the GFORCE components. |
Extended Definition
The GFORCE statement with a function expression is usually adequate for defining functions that represent the three translational and three rotational vector components of a force at a point. However, if the force and torque expressions become lengthy and awkward, you can use a GFOSUB.
You can call utility subroutines, such as AKISPL, CUBSPL, SYSARY, and SYSFNC, from GFOSUB, to obtain information about system variables, user-defined variables, and splines.
The SYSARY and SYSFNC utility subroutines set up functional dependencies when the GFOSUB argument iflag is not zero. In order for Adams Solver to compute solutions efficiently, it must know the Solver states on which the GFORCES depend. Adams Solver determines these functional dependencies at the beginning of the simulation by calling GFOSUB with the argument iflag set to not zero. Adams Solver does this once for each GFORCE statement with a FUNCTION=USER() argument. During each call to GFOSUB, Adams Solver records the calls you make to SYSARY and SYSFNC. Adams Solver assumes that the GFORCE components depend on those Adams Solver states that are accessed through SYSARY and SYSFNC.
Using the DFLAG Variable
The use of the DFLAG variable with a GFOSUB is optional. It merely identifies that GFOSUB is being called to evaluate a partial derivative. One of the states on which the GFOSUB depends has been perturbed very slightly. In many situations, it is likely that major calculations in the GFOSUB are insensitive to small changes in state, and therefore, need not be recalculated.
In such situations, you can structure the GFOSUB not to redo these calculations. For example, assume you are using a GFOSUB to model tire and terrain interactions. The terrain is modeled as a set of triangular patches, and the tire forces as a GFOSUB. A labor-intensive calculation in the problem is to identify the patch that is in contact with the tire. Because pertubations of system states are always small when DFLAG is true, it is not necessary to recalculate the patch that is in contact with the tire.
Caution: | ■Euler angles calculated by SYSARY or SYSFNC subroutines may be discontinuous. To avoid discontinuity, use the RCNVRT utility subroutine to convert the rotational angles from Euler angles to some other rotational scheme that does not encounter discontinuity. ■When the iflag argument is not zero, you must make all the calls to SYSARY and SYSFNC as are made to compute the component values of the GFORCE statement. This ensures that Adams Solver has the proper functional dependencies. In general, failure to account for dependencies in the GFORCE components can make it difficult for Adams Solver to converge to a solution and/or can force Adams Solver to take small integration steps. It may increase simulation time dramatically. ■When the iflag argument is not zero, SYSARY and SYSFNC return zero values for system and user-defined variables. Computations that divide by these values will result in fatal errors. You should check for nonzero values, or ensure the iflag argument is set to zero, before dividing by these values. |
FORTRAN - Prototype
A sample structure for GFOSUB is shown next. The comments explain how the subroutine works.
SUBROUTINE GFOSUB(ID, TIME, PAR, NPAR, DFLAG,
& IFLAG, RESULT)
C
C === Type and dimension statements ===================
C
C - External variable definitions -----------
C
INTEGER ID
DOUBLE PRECISION TIME
DOUBLE PRECISION PAR( * )
INTEGER NPAR
LOGICAL DFLAG
INTEGER IFLAG
DOUBLE PRECISION RESULT( 6 )
C
C ID Identifier of calling GFORCE statement
C TIME Current time
C PAR Array containing passed parameters
C NPAR Number of passed parameters
C DFLAG Differencing flag
C IFLAG Initial pass flag
C RESULT Array (dimension 6) of computed GFORCE
C components returned to ADAMS
C
C - Local variable and parameter definitions -----
C
...
C
C === Executable code =================================
C
C Assign readable variable names to passed parameters
C
...
C
C Call SYSFNC and/or SYSARY to collect information for
C the following calculations. Note: if IFLAG is
C true, these calls are actually setting functional
C dependencies.
C
CALL SYSFNC (...)
C
C Check SYSFNC call through ERRMES utility routine
C
CALL ERRMES (...)
C
C Repeat for all required SYSFNC or SYSARY calls
C
...
C
IF (IFLAG) THEN
C
C - Subroutine initialization -------------
C
...
C
ENDIF
C
C - Evaluate GFORCE components -------------
C
C Your algorithms
C
...
C
C Assign values to the RESULT array
C
RESULT(1) = ...
RESULT(2) = ...
RESULT(3) = ...
RESULT(4) = ...
RESULT(5) = ...
RESULT(6) = ...
C
RETURN
END
C Style - Prototype
typedef void adams_c_GFOSUB(const struct sAdamsGforce* gfo, double TIME, int DFLAG, int IFLAG, double* RESULT);
/*
* GFORCE
*/
struct sAdamsGforce
{
int ID;
int NPAR;
const double* PAR;
int I;
int RM;
int JFLOAT;
};
Examples
For an example of this subroutine, see
gfosub.f