The COUSUB, COUXX, and COUXX2 subroutines define a user-defined COUPLER (C++ or FORTRAN):
■COUSUB specifies the coupler constraint as a function of the displacements of the joints being coupled.
■COUXX returns to Adams Solver the first partial derivatives of the coupler constraint, with respect to each joint displacement.
■COUXX2 returns the matrix of second partial derivatives of the coupler constraint, with respect to the joint displacements.
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; Cousub for example. Doing this ensures that Adams Solver correctly distinguishes a C style subroutine from Fortran and calls with the appropriate interface. |
Use
Corresponding Command
Calling Sequence
SUBROUTINE COUSUB (id, time, par, npar, disp, ndisp, iflag, phi)
SUBROUTINE COUXX (id, time, par, npar, disp, ndisp, iflag, dfda)
SUBROUTINE COUXX2 (id, time, par, npar, disp, ndisp, iflag, dfda2)
Input Arguments
id | An integer variable that specifies the identifier of the COUPLER statement whose constraint function is being specified. |
time | A double-precision variable that contains the current simulation time. |
par | A double-precision array that contains the constants taken, in order, from the list of values provided with the USER argument in the COUPLER statement. |
npar | An integer variable containing the number of entries in the PAR array. |
disp | A double-precision array containing the instantaneous joint displacements. Translational displacements are in units of length and rotational displacements are in radians. |
ndisp | An integer variable that defines the size of the DISP array. This is equal to the number of joints being coupled in the COUPLER statement. |
iflag | An integer variable that Adams Solver sets to indicate why the routine is being called: When iflag is 0 Adams Solver calling to compute the value of the user-written variable. When iflag is set to 1 or 3 do any initializations that your subroutine requires. 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 can do any initializations when Adams Solver sets iflag to true, and compute the subroutine's value when Adams Solver sets iflag to false. |
Output Arguments
phi | A double-precision scalar that contains the value of the coupler constraint equation. The constraint equation must be specified in implicit form. For example, the equation must be in the form: f (disp) = 0. |
dfda | A double-precision array of length ndisp that contains the partial derivatives of phi with respect to disp. Therefore,  |
dfda2 | A double-precision array of dimensions ndisp that contains the second partials derivatives of phi with respect to disp. Therefore,  |
Extended Definition
The COUPLER statement is used to relate the motion of two or more joints. If the relationship between the motion in a set consisting of two or three joints is linear, the scale factors relating the motion can be directly specified in the dataset.
However, when the relationship between the joints is nonlinear in nature, the equation specifying this relationship must be specified in the user-written subroutines COUSUB, COUXX, and COUXX2. Therefore, if d1, d2, and d3 are displacement/rotations in three translational or revolute joints, the relationship between them may be written analytically as: ƒ1 (d1) + ƒ2(d2) + ƒ3(d3) = 0
COUSUB, COUXX, and COUXX2 must only be functions of the input variables specified above. You cannot call SYSFNC or SYSARY to access other system states.
FORTRAN - Prototype
A sample structure for COUSUB, COUXX, and COUXX2 is shown next. The comments explain the logical structure of each of the subroutines.
COUSUB
SUBROUTINE COUSUB (ID, TIME, PAR, NPAR, DISP, & NDISP, IFLAG, PHI)
C
C+----------------------------------------------------*
C
C Inputs:
C INTEGER ID DOUBLE PRECISION TIME DOUBLE PRECISION PAR(*) INTEGER NPAR DOUBLE PRECISION DISP(*) INTEGER NDISP LOGICAL IFLAGCC Outputs:
C DOUBLE PRECISION PHICC Local Variables:
C ... ...
C
C+----------------------------------------------------*
C Executable Code
C+----------------------------------------------------*
C
C IF (IFLAG) THEN
C
C+----------------------------------------------------*
C Initialization pass: Initialize necessaryC local variables
C+----------------------------------------------------*C ... ...
C ELSEC
C+----------------------------------------------------*
C Evaluation pass: Define Phi the
C coupler constraint
C+----------------------------------------------------*
C ... ...
PHI = ...
C
ENDIF
C
C
RETURN
END
COUXX
SUBROUTINE COUXX (ID, TIME, PAR, NPAR, DISP,
& NDISP, IFLAG, DFDA)
C
C+----------------------------------------------------*
C
C Inputs:
C
INTEGER ID
DOUBLE PRECISION TIME
DOUBLE PRECISION PAR(*)
INTEGER NPAR
DOUBLE PRECISION DISP(*)
INTEGER NDISP
INTEGER IFLAG
C
C Outputs:
C
DOUBLE PRECISION DFDA(*)
C
C Local Variables:
C
...
...
C
C+----------------------------------------------------*
C
Executable Code
C+----------------------------------------------------*
C
C
IF (IFLAG) THEN
C
C+----------------------------------------------------*
C
Initialization pass: Initialize
C
necessary local variables
C+----------------------------------------------------*
C
...
...C
ELSE
C
C+----------------------------------------------------*
C
Evaluation pass: Define the partial
C
derivatives of the coupler constraint
C+----------------------------------------------------*
C
...
...
DFDA(1) = ...
DFDA(2) = ...
...
C
ENDIF
C
C
RETURN
END
COUXX2
SUBROUTINE COUXX2 (ID, TIME, PAR, NPAR, DISP,
& NDISP, IFLAG, DFDA2)
C
C+----------------------------------------------------*
C
C Inputs:
C
INTEGER ID
DOUBLE PRECISION TIME
DOUBLE PRECISION PAR(*)
INTEGER NPAR
DOUBLE PRECISION DISP(*)
INTEGER NDISP
LOGICAL IFLAG
C
C Outputs:
C
DOUBLE PRECISION DFDA2(NDISP)
C
C Local Variables:
C
...
...
C
C+----------------------------------------------------*
C
Executable Code
C+----------------------------------------------------*
C
C
IF (IFLAG) THEN
C
C+----------------------------------------------------*
C
Initialization pass: Initialize
C
necessary local variables
C+----------------------------------------------------*
C
...
...
C
ELSE
C
C+----------------------------------------------------*
C
Evaluation pass: Define the second partial
C
derivatives of the coupler constraint
C+----------------------------------------------------*
C
...
...
DFDA2(1) = ...
DFDA2(2) = ...
...
...
C
ENDIF
C
C
RETURN
END
C Style - Prototype
typedef void adams_c_COUSUB(const struct sAdamsCoupler* coupler, double TIME, double*, int IFLAG, double* PHI);
typedef void adams_c_COUXX(const struct sAdamsCoupler* coupler, double TIME, double*, int IFLAG, double* dFda);
typedef void adams_c_COUXX2(const struct sAdamsCoupler* coupler, double TIME, double*, int IFLAG, double* d2Fda2);
/*
* COUPLER -----------------------------------------------------------------
*/
struct sAdamsCoupler
{
int ID;
int NPAR;
const double* PAR;
int NJOINT;
int JOINTS[3];
char TYPE[3];
};
Examples
The mechanical system shown in Figure 1 consists of three rigid bodies and two joints; the first is a revolute joint and the second translational. The translational joint represents an actuator whose output displacement controls the angular motion in the revolute joint.
Let the displacement in the translational joint be defined as and the rotation in revolute joint as a.
Now assume that the variables s and a are related by the following equation:
s = 10 * Cos (a)
Figure 1. Simple Mechanical System Consisting of a Coupler
The dataset for this model is:
!Part/1, Ground
Marker/11
Marker/12
Part/2, Mass=10, Ip=10,10,10, Cm=21
Marker/21, Qp=0,-5,0, REU=90d,90d,0
Marker/22, REU=90d,0,0
Part/3, Mass=25, Ip=75,75,150, Cm=31
Marker/31, Qp=10,20,0, REU=90d,90d,0
Marker/32
Joint/1, Revolute, I=22, J=11
Joint/2, Translational, I=32, J=12
Motion/1, Joint=2, Function = 10*Time
Coupler/1, Joints=1,2, Function=User(10)
End
Subroutines COUSUB, COUXX, and COUXX2 for this model are:
COUSUB
SUBROUTINE COUSUB (ID, TIME, PAR, NPAR, DISP,
& NDISP, IFLAG, PHI)
C
C+----------------------------------------------------*
C
C Inputs:
C
INTEGER ID
DOUBLE PRECISION TIME
DOUBLE PRECISION PAR(*)
INTEGER NPAR
DOUBLE PRECISION DISP(*)
INTEGER NDISP
INTEGER IFLAG
C
C Outputs:
C
DOUBLE PRECISION PHI
C
C Local Variables:
C
DOUBLE PRECISION LENGTH, S, ALPHA
C
C+----------------------------------------------------*
C
Executable Code
C+----------------------------------------------------*
C
IF (IFLAG) THEN
C
C
there are no variables to initialize in this
C
example
C
ELSE
C
C+----------------------------------------------------*
C
Evaluation pass: Define Phi the coupler
C
constraint
C+----------------------------------------------------*
C
LENGTH = PAR(1)
ALPHA = DISP(1)
S = DISP(2)
PHI = S - LENGTH * COS(ALPHA)
C
ENDIF
C
RETURN
END
COUXX
SUBROUTINE COUXX (ID, TIME, PAR, NPAR, DISP,
& NDISP, IFLAG, DFDA)
C
C+----------------------------------------------------*
C
C Inputs:
C
INTEGER ID
DOUBLE PRECISION TIME
DOUBLE PRECISION PAR(*)
INTEGER NPAR
DOUBLE PRECISION DISP(*)
INTEGER NDISP
INTEGER IFLAG
C
C Outputs:
C
DOUBLE PRECISION DFDA(*)
C
C Local Variables:
C
DOUBLE PRECISION LENGTH, S, ALPHA
C
C+----------------------------------------------------*
C
Executable Code
C+----------------------------------------------------*C
IF (IFLAG) THEN
C
C
there are no variables to initialize in this example
C
ELSE
C
C+----------------------------------------------------*
C
Evaluation pass: Define the partial derivatives
C
of the coupler constraint
C+----------------------------------------------------*
C
LENGTH = PAR(1)
ALPHA = DISP(1)
S = DISP(2)
C
DFDA(1) = + LENGTH * SIN(ALPHA)
DFDA(2) = 1.0
C
ENDIF
C
RETURN
END
COUXX2
SUBROUTINE COUXX2 (ID, TIME, PAR, NPAR, DISP,
& NDISP, IFLAG, DFDA2)
C
C+----------------------------------------------------*
C Inputs:
C
INTEGER ID
DOUBLE PRECISION TIME
DOUBLE PRECISION PAR(*)
INTEGER NPAR
DOUBLE PRECISION DISP(*)
INTEGER NDISP
INTEGER IFLAG
C
C Outputs:
C
DOUBLE PRECISION DFDA2(NDISP)
C
C Local Variables:
C
DOUBLE PRECISION LENGTH, ALPHA, S
C
C+----------------------------------------------------*
C
Executable Code
C+----------------------------------------------------*
C
IF (IFLAG) THEN
C
C
no variables to initialize in this example.
C
ELSE
C
C+----------------------------------------------------*
C
Evaluation pass: Define the second partial
C derivatives of the coupler constraint
C+----------------------------------------------------*
C
LENGTH = PAR(1)
ALPHA = DISP(1)
S = DISP(2)
DFDA2(1) = LENGTH * COS(ALPHA)
DFDA2(2) = 0.0
C
ENDIF
C
RETURN
END