MFOSUB

MFOSUB is an evaluation subroutine that computes the modal force corresponding to an MFORCE statement (C++ or FORTRAN). MFOSUB is optional. You need it only if you don't want to use a function expression in the MFORCE statement, or if you need the added capabilities of the USER form of the MFORCE 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; Mfosub 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

You invoke the MFOSUB by using either the FUNCTION or FORCE option in the MFORCE statement. The MFOSUB output arguments are interpreted differently depending on the form used.  Adams Solver (C++) can invoke the MFOSUB using either form. Adams Solver (FORTRAN) can only invoke the MFOSUB using FUNCTION.   

Calling Sequence

SUBROUTINE MFOSUB (id, time, par, npar, dflag, iflag,$
modloads, nmodes, ncases,$
scale, case, loadvec)

Input Arguments

 
id
An integer variable that provides the identifier of the MFORCE statement that is requesting information from the MFOSUB.
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 MFORCE statement.
npar
An integer variable that indicates the number of constants specified in the USER parenthetical list. The primary purpose of npar is to enable MFOSUB to correctly dimension the par array.
dflag
A logical variable that Adams Solver sets to true when calling MFOSUB to evaluate the partial derivatives of the specified functions. Otherwise, Adams Solver sets dflag 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.
modloads
A double-precision array containing the values of the modal load cases that are defined for the FLEX_BODY and that the MFORCE is acting on. The modload array has the dimensions modload (6+nmodes, ncases).
nmodes
An integer variable that indicates the number of modes in the associated FLEX_BODY. The value of nmodes provides MFOSUB with a way to correctly dimension the modloads and loadvec arrays.
ncases
An integer variable that indicates the number of load cases available in the associated FLEX_BODY. The value of ncases provides MFOSUB with a means to correctly dimension the modloads array. If ncases=0, then the contents of modloads are undefined because no user-defined load cases are available for the FLEX_BODY.

Output Arguments

 
scale
A double-precision array of dimension scale(ncases + 1). A double-precision single variable is also applicable.
If MFOSUB is called with the FUNCTION form:
If case > 0, then this output argument contains the scale factor that is to be applied to the modal load vector. The value of scale can depend on the values Adams Solver calls from SYSFNC and SYSARY (see SYSARY and SYSFNC). If case = -1, then the output arguments contain the series of scale factors, scale(n + 1) to be applied to nth modal load vector and they can depend on time only, where n is 1 to ncases. scale(1) contains the global scale factor that can depend on the values Adams Solver calls from SYSFNC and SYSARY.
If MFOSUB is called with the FORCE form:
Adams Solver ignores this output argument.
case
An integer, in the range -1 to ncases.
If MFOSUB is called with the FUNCTION form:
This output argument denotes a user-defined modal load case that is multiplied by the scale output argument to produce the modal load on the FLEX_BODY. If case = 0, then Adams Solver looks for a modal load case in the loadvec array. If case = -1, then multiple scale factors for each modal load vector can be defined by the scale output arguments.
If MFOSUB is called with the FORCE form:
This output argument must be set to zero and Adams Solver extracts the modal load directly from the loadvec array.
loadvec
A double-precision array of dimension loadvec(6+nmodes) that MFOSUB generates itself or generates based on the load cases it receives from the modloads array.
If MFOSUB is called with the FUNCTION form:
If the output variable case is zero, Adams Solver computes the modal force by multiplying the output array loadvec by the output variable scale. The values of loadvec can be a function of time, but not a function of the model response. For example, they must not depend on values obtained by calling SYSFNC and SYSARY. If case>0, then Adams Solver ignores the contents of loadvec.
If MFOSUB is called with the FORCE form:
Adams Solver applies the contents of the loadvec array directly to the FLEX_BODY without scaling it. Each component of loadvec can depend on time and model response. That is, you can use the values obtained from SYSFNC and SYSARY to compute entries in the loadvec array.

Examples

A sample for MFOSUB is shown next. In this example, MFOSUB is invoked using the FUNCTION form and uses load case 3 and scales it with 10.
     SUBROUTINE MFOSUB(ID, TIME, PAR, NPAR, DFLAG, IFLAG,
    $                  MODLOADS, NMODES, NCASES,
    $                  SCALE, CASE, LOADVEC)
C
     INTEGER          ID, NPAR, NMODES, NCASES
     LOGICAL          DFLAG
     LOGICAL          ERRFLG
     INTEGER          IFLAG
       DOUBLE PRECISION TIME, PAR(NPAR), MODLOADS(6+NMODES, NCASES)
C
     INTEGER          CASE
     DOUBLE PRECISION SCALE, LOADVEC(6+NMODES)
C
     CASE = 3
     SCALE = 10.
     
     ERRFLG = NCASES.LT.CASE
     CALL ERRMES(ERRFLG, 'Trying to use an invalid load case.',
    &            ID, 'STOP' )
     RETURN
     END
 
For an example of this subroutine see mfosub.f.
In this next example, the MFOSUB is called with the FORCE form of the MFORCE statement. The MFOSUB applies a critical modal damping force to the FLEX_BODY identified by the first entry in the USER parenthetical list. Note that the user-written subroutine assumes the generalized mass matrix is the identity matrix.
SUBROUTINE MFOSUB(ID, TIME, PAR, NPAR, DFLAG, IFLAG, MODLOADS,
    &                  NMODS, NCASES, SCALE, CASE, LOADVEC)
C
     IMPLICIT NONE
C
C... ARGUMENTS:
C
     INTEGER           ID
     INTEGER           NPAR
     INTEGER           NMODS
     INTEGER           NCASES
     LOGICAL           DFLAG
     INTEGER          IFLAG
     DOUBLE PRECISION  TIME
     DOUBLE PRECISION  PAR(NPAR)
     DOUBLE PRECISION  MODLOADS(6+NMODS, NCASES)
C
C... RETURNS
C
     INTEGER           CASE
     DOUBLE PRECISION  SCALE, LOADVEC(6+NMODS)
C
C... PARAMETERSC
     INTEGER           MAXN
     PARAMETER        (MAXN   = 100    )
     DOUBLE PRECISION  ZERO
     PARAMETER        (ZERO   = 0.0D+00)
     DOUBLE PRECISION  ONE
     PARAMETER        (ONE    = 1.0D+00)
     DOUBLE PRECISION  TWO
     PARAMETER        (TWO    = 2.0D+00)
     DOUBLE PRECISION  PI
     PARAMETER        (PI     = 3.141592653589793D+00)      
C
C... LOCALSC
     LOGICAL ERRFLG
     INTEGER I, NQ, FBYID
     INTEGER MNUM(MAXN)
     DOUBLE PRECISION GSTF, GMAS
     DOUBLE PRECISION MFRQ(MAXN), QDOT(MAXN)
C
C=====================  EXECUTABLE CODE ==============================
C      FBYID = NINT(PAR(1))
C
C... GET MODE NUMBERS AND FREQUENCIES FOR ALL ACTIVE MODES
C
     CALL MODINF (FBYID, MNUM, MFRQ, ERRFLG)
     CALL ERRMES(ERRFLG, 'FAILED CALL TO MODINF', ID, 'STOP')
C
C... GET TIME DERIVATIVE OF MODAL COORDINDATES
     CALL SYSARY('QDOT', FBYID, 1, QDOT, NQ, ERRFLG)
     CALL ERRMES(ERRFLG, 'FAILED CALL TO SYSARY', ID, 'STOP')
C
C... CASE MUST BE SET TO ZEROC     
     CASE = 0CC...  BUILD MODAL LOAD AND RETURN IN LOADVEC ARRAY
C              
     DO I = 1, 6
        LOADVEC(I) = ZERO
     END DO
C
     DO I = 1, NMODS
        GMAS = ONE
        GSTF = (TWO * PI * MFRQ(I)) ** 2
        LOADVEC(I+6) = -TWO * DSQRT(GSTF * GMAS) * QDOT(I)
     END DO
C
     RETURN
     END
 
For an example of this subroutine see mfosub2.f.

C Style - Prototype

typedef void adams_c_MFOSUB(const struct sAdamsMforce* mforce, double TIME, int DFLAG, int IFLAG, const double* MODLOADS, int NMODES, int NCASES, double* SCALE, int* CASE, double* LOADVEC);
 
/*
* MFORCE
*/
struct sAdamsMforce
{
struct sAdamsFlexBody FlexBody;
int ID;
int NPAR;
const double* PAR;
int JFLOAT;
};