The CBKSUB subroutine is an optional user-written subroutine that Adams Solver C++ calls at a predefined set of events during the code execution. The CBKSUB only passes input values announcing the type of event, the current simulation time, and a data array.
An event can be seen as a milestone reached during the code execution. An event is triggered when certain conditions occur, for example, a SENSOR triggers or an error condition is detected. Most of the time a milestone is reached naturally by the code, for example, a simulation command is about to be executed, a corrector iteration is about to start and so on.
The CBKSUB is a true callback function designed for advanced users only.
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; Cbksub for example. Doing this ensures that Adams Solver correctly distinguishes a C style subroutine from Fortran and calls with the appropriate interface. |
Use
FORTRAN Calling Sequence
include 'slv_cbksub_util.inc'
SUBROUTINE CBKSUB ( time, event, data )
include 'slv_cbksub.inc'
DOUBLE PRECISION time
INTEGER event, data(3)
C Calling Sequence
include "slv_cbksub.h"
include "slv_cbksub_util.h"
void Cbksub( const struct sAdamsCbksub *cbk, double time, int event, int *data )
C++ Calling Sequence
include "slv_cbksub.h"
include "slv_cbksub_util.h"
extern "C" void Cbksub( const struct sAdamsCbksub *cbk, double time, int event, int *data )
Input Arguments
data | An integer array with context dependent values. The values depend on the type of event. |
event | An integer value identifying the type of event for which the call is being made. As of now 39 events have been implemented. |
time | The current simulation time. |
cbk | Structure containing callback data (see below) |
| struct sAdamsCbksub { int ID; int NPAR; const double* PAR; void *reserved; }; |
Output Argument
The CBKSUB does not have output arguments. |
Extended Definition
Currently, only the Adams Solver C++ supports the CBKSUB.
The overhead (CPU time) is negligible.
Providing this subroutine is optional.
All utility subroutines are allowed to be called from within the CBKSUB except ADAMS_DECLARE_THREADSAFE, ANALYS, DATOUT, GTCMAT, MODIFY, PUT_SPLINE and UCOVAR. Calling any of these subroutines makes the behavior of the Adams Solver C++ undefined. No guards have been implemented.
None of the user-written subroutines are allowed to be called. The forbidden set includes CFFSUB, CNFSUB, CONSUB, COUSUB, COUXX, COUXX2, CURSUB, DIFSUB, DMPSUB, FIESUB, GFOSUB, GSE_DERIV, GSE_UPDATE, GSE_OUTPUT, GSE_SAMP, MFSUB, MOTSUB, RELSUB, REQSUB, SAVSUB, SENSUB, SEVSUB, SFOSUB, SPLINE_READ, SURSUB, TIRSUB, VARSUB, VFOSUB and VTOSUB. Calling forbidden subroutines makes the behavior of the Adams Solver C++ undefined. No guards have been implemented.
Both SYSFNC and SYSARY are allowed to be called from within the CBKSUB. Notice however, that no dependencies are registered. This feature makes possible to compute some desired quantities without creating dependencies. Usually, users will compute and cache values at specific events.
Events
Forty four (44) events have been implemented. Below is the list of current supported events.
1=ev_INITIALIZE | Triggered right after the library containing user-written subroutines has been loaded. The data set defining the model has not been processed. Input array data is undefined. |
2=ev_TERMINATE | Triggered before the model is going to be deleted. All user-written subroutines will be called for the last time. First entry of input array data contains the solver status. Other entries are undefined. |
3=ev_SENSOR | Triggered after a SENSOR has triggered. First entry of input array data is the ID of the SENSOR. Second entry is an integer defining the type of SENSOR: 1=sn_CODGEN 2=sn_DT 3=sn_HALT 4=sn_PRINT 5=sn_RESTART 6=sn_RETURN 7=sn_STEPSIZE 8=sn_YYDUMP 9=sn_EVALUATE The third entry of input array data is ignored. Notice the SENSOR must have an action associated with it (for example, HALT). If the SENSOR has no action, no event will be triggered. |
4=ev_ITERATION_BEG | Triggered before the Jacobian and/or right-hand side evaluation is about to start. First entry of input array data is the current simulation mode. Second entry is the current analysis mode. The third entry is 1 if a Jacobian evaluation is requested, 0 otherwise. |
5=ev_ITERATION_END | Triggered after the Jacobian and/or right-hand side evaluation is finished. First entry of input array data is the current simulation mode. Second entry is the current analysis mode. The third entry is ignored. |
6=ev_BODY_ROTATION | Triggered before a body rotation is to take place. First entry of input array data is the current simulation mode. Second entry is the current analysis mode. The third entry is ignored. |
7=ev_OUTPUT_STEP_REQ | Triggered to request output generation. First entry of input array data is the current simulation mode. Second entry is the current analysis mode. The third entry is ignored. |
8=ev_OUTPUT_STEP_BEG | Triggered when output generation is about to start. First entry of input array data is the current simulation mode. Second entry is the current analysis mode. The third entry is ignored. |
9=ev_OUTPUT_STEP_END | Triggered after output generation is finished. First entry of input array data is the current simulation mode. Second entry is the current analysis mode. The third entry is ignored. |
10=ev_TIME_STEP_BEG | Triggered at the beginning of a time step. First entry of input array data is the current simulation mode. Second entry is the current analysis mode. The third entry is ignored. |
11=ev_TIME_STEP_FAILE | Triggered when the integration error can not be achieved and a reduction of the time step is to be performed. First entry of input array data is the current simulation mode. Second entry is the current analysis mode. The third entry is ignored. |
12=ev_TIME_STEP_END | Triggered at the end of a successful time step. First entry of input array data is the current simulation mode. Second entry is the current analysis mode. The third entry is ignored. |
13=ev_MODEL_INPUT_BEG | Triggered right before the model will be read. Input array data is undefined. |
14=ev_MODEL_INPUT_END | Triggered right after the model has been read. Input array data is undefined. |
15=ev_DIS_IC_BEG | Triggered when a displacement initial conditions is about to start. First entry of input array data is the current simulation mode. Second entry is the current analysis mode. The third entry is ignored. |
16=ev_DIS_IC_END | Triggered after a displacement initial conditions has ended. First entry of input array data is the current simulation mode. Second entry is the current analysis mode. The third entry is ignored. |
17=ev_VEL_IC_BEG | Triggered when a velocity initial conditions is about to start. First entry of input array data is the current simulation mode. Second entry is the current analysis mode. The third entry is ignored. |
18=ev_VEL_IC_END | Triggered after a velocity initial conditions has ended. First entry of input array data is the current simulation mode. Second entry is the current analysis mode. The third entry is ignored. |
19=ev_ACC_IC_BEG | Triggered when an acceleration initial conditions is about to start. First entry of input array data is the current simulation mode. Second entry is the current analysis mode. The third entry is ignored. |
20=ev_ACC_IC_END | Triggered after an acceleration initial conditions has ended. First entry of input array data is the current simulation mode. Second entry is the current analysis mode. The third entry is ignored. |
21=ev_STATICS_BEG | Triggered when a static simulation is about to start. First entry of input array data is the current simulation mode. Second entry is the current analysis mode. The third entry is ignored. |
22=ev_STATICS_END | Triggered when a static simulation has ended. First entry of input array data is the current simulation mode. Second entry is the current analysis mode. The third entry is zero (0) if the statics simulation was successful or one (1) if the static simulation failed. |
23=ev_STEADY_STATE_BEG | Triggered when a steady-state simulation is about to start. First entry of input array data is the current simulation mode. Second entry is the current analysis mode. The third entry is ignored. |
24=ev_STEAD_STATE_END | Triggered when a steady-state simulation has ended. First entry of input array data is the current simulation mode. Second entry is the current analysis mode. The third entry is ignored. |
25=ev_KINEMATICS_BEG | Triggered when a kinematics simulation is about to start. First entry of input array data is the current simulation mode. Second entry is the current analysis mode. The third entry is ignored. |
26=ev_KINEMATICS_END | Triggered when a kinematics simulation has ended. First entry of input array data is the current simulation mode. Second entry is the current analysis mode. The third entry is ignored. |
27=ev_DYNAMICS_BEG | Triggered when a dynamics simulation is about to start. First entry of input array data is the current simulation mode. Second entry is the current analysis mode. The third entry is ignored. |
28=ev_DYNAMICS_END | Triggered when a dynamics simulation has ended. First entry of input array data is the current simulation mode. Second entry is the current analysis mode. The third entry is ignored. |
29=ev_LINEAR_BEG | Triggered when a linear simulation is about to start. First entry of input array data is the current simulation mode. Second entry is the current analysis mode. The third entry is ignored. |
30=ev_LINEAR_END | Triggered when a linear simulation has ended. First entry of input array data is the current simulation mode. Second entry is the current analysis mode. The third entry is ignored. |
31=ev_QSTATICS_BEG | Triggered when a quasi-statics simulation is about to start. First entry of input array data is the current simulation mode. Second entry is the current analysis mode. The third entry is ignored. |
32=ev_QSTATICS_END | Triggered when a quasi-statics simulation has ended. First entry of input array data is the current simulation mode. Second entry is the current analysis mode. The third entry is ignored. |
33=ev_SAVE_BEG | Triggered when a SAVE job is about to start. Input array data is undefined. |
34=ev_SAVE_END | Triggered when a SAVE job has ended. Input array data is undefined. |
35=ev_RELOAD_BEG | Triggered when a RELOAD job is about to start. Input array data is undefined. |
36=ev_RELOAD_END | Triggered when a RELOAD job has ended. Input array data is undefined. |
37=ev_TRAN_SIM_BEG | Triggered when a transient simulation is about to start. Input array data is undefined. |
38=ev_TRAN_SIM_END | Triggered when a transient simulation has ended. Input array data is undefined. |
39=ev_COMMAND | Triggered when Adams Solver C++ is about to start processing a command. First entry of input array data is an integer identifying the command (see Table 2 below). The second entry is a 1 if the command is requested by a CONSUB, 0 otherwise. |
40=ev_MODEL_CHANGE | Triggered when processing a command that changes the model. Input array data is undefined. |
41=ev_FORCE_RECONC_BEG | Triggered when the solver is about to evaluate forces before a simulation job. Input array data is undefined. After this event is triggered, a set of ev_ITERATION_BEG and ev_ITERATION_END may be called. Input array data is undefined. |
42=ev_FORCE_RECONC_END | Triggered when the solver finished evaluating forces. Input array data is undefined. |
43=ev_PRIVATE_EVENT1 | Triggered by internal work being done by the solver. Your CBKSUB must ignore this event. Input array data is undefined. |
44=ev_PRIVATE_EVENT2 | Triggered by internal work being done by the solver. Your CBKSUB must ignore this event. Input array data is undefined. |
Simulation mode, analysis mode
Most of the events shown above provide the current simulation mode and analysis mode stored in the input array data. The current simulation mode is the main simulation being executed as a response to a simulation command. The value of the simulation mode is the same value obtained making calls to the GETMOD utility subroutine or the value computed with the MODE function.
The analysis mode is a temporary numerical solution required to honor the simulation requested by the user. For example, when Adams Solver C++ starts a dynamic simulation it first checks whether an initial conditions is required. If the initial-conditions job is required, an ev_ITERATION_BEG event will provide “Dynamics” and “Initial conditions” as the simulation mode and analysis mode respectively if the iteration is performed from within the temporary initial-conditions job.
Table 1 below shows the simulation/analysis modes provided in the input array
data.
Table 1 Simulation/analysis modes.
0=am_UNDEFINED | Undefined. |
1=am_KINEMATICS | Kinematics simulation. |
2=am_RESERVED | Not used. |
3=am_INITIAL_CONDITIONS | Initial conditions. |
4=am_DYNAMICS | Dynamics simulation. |
5=am_STATICS | Statics simulation. |
6=am_QUASI_STATICS | Quasi-statics simulation. |
7=am_LINEAR | Linearization, eigensolution, state-matrices. |
8=am_STEADY_STATE | Steady-state simulation. |
9=am_COMPLIANCE | Compliance computation. |
Table 2 Command identifiers.
1=cm_ACCGRAV |
2=cm_ACTIVATE |
3=cm_ARRAY |
4=cm_BEAM |
5=cm_BUSHING |
6=cm_CONTROL |
7=cm_COUPLER |
8=cm_CPAPAR |
9=cm_DEACTIVATE |
10=cm_DEBUG |
11=cm_DIFF |
12=cm_ENVIRONMENT |
13=cm_EQUILIBRIUM |
14=cm_FIELD |
15=cm_FILE |
16=cm_FLEX_BODY |
17=cm_FRICTION |
18=cm_GCON |
19=cm_GEAR |
20=cm_GFORCE |
21=cm_GSTIFF |
22=cm_HELP |
23=cm_HOTLINE |
24=cm_IC |
25=cm_INFO |
26=cm_INTEGRATOR |
27=cm_JOINT |
28=cm_JPRIM |
29=cm_KINEMATICS |
30=cm_LINEAR |
31=cm_LPARAM |
32=cm_LSOLVER |
33=cm_LTABLEPARAM |
34=cm_MARKER |
35=cm_MENU |
36=cm_MOTION |
37=cm_OUTPUT |
38=cm_PART |
39=cm_PREFERENCES |
40=cm_RELOAD |
41=cm_REQUEST |
42=cm_RETURN |
43=cm_SAVE |
44=cm_SENSOR |
45=cm_SFORCE |
46=cm_SHOW |
47=cm_SIMULATE |
48=cm_SPLINE |
49=cm_SPRINGDAMPER |
50=cm_STOP |
51=cm_STRING |
52=cm_TIME |
53=cm_VARIABLE |
54=cm_VFORCE |
55=cm_VTORQUE |
56=cm_WSTIFF |
Tip: | All integers defining events, SENSOR types, simulation/analysis modes, and command types are defined in file slv_cbksub.inc which is included in the software distribution. File slv_cbksub_utils.inc has usefuld routines. File slv_cbksub.h and slv_cbksub_utils.h are also provided for C/C++ coding. Using either C/C++ or FORTRAN, we strongly suggest using the enumerations defined in the above include files (*.h, *.inc) because the integer values defining an event may change from release to release. |
Calling sequence in dynamic simulations
This section describes a simplified CBKSUB call sequence during a dynamic simulation. The call sequence for other simulations is similar.
When executing a dynamic simulation, Adams Solver C++ divides the time span between the current simulation time and the final simulation time into a number of so called "output steps". The state of the system is advanced up to the end of each output step at which a request for output generation is triggered from within the innermost code layer. However, to reach the end of each output step, the solver may require to perform a set of smaller "time steps" in order to reach the end of the current output step.
Figure 1 and
Figure 2 depict a simplified version of the overall program flow showing the calls to the CBKSUB subroutine.
Highlights related to
Figure 1 are the following. First, the block labeled "Process SIM/DYN command" stands for the code where the input parameters of the simulation command are read. The command information is used to determine the number of output steps required to be made by the solver. Also notice that in case an initial conditions job is required, no details of the calling sequence to the CBKSUB are presented.
Finally, the block corresponding to the function
output_step() is presented in
Figure 2.
The flowchart presented in
Figure 2 consists of two loops. The outer loop controls the number of "time steps" made by the dynamic integration until an "output step" is reached. The inner loop controls the number of corrector iterations required to advance the state of the simulation.
Figure 1 and
Figure 2 are simplified versions of the calling sequence of the CBKSUB subroutine. For the sake of clarity, several calls have been omitted.
Figure 1 Calling sequence of CBKSUB during a dynamic simulation (1).
Figure 2 Calling sequence of CBKSUB during a dynamic simulation (2).
Example
Basic strategy
Let’s assume an Adams model has a set of VFORCEs defined by VFOSUB subroutines. Let’s assume the function expression for these VFORCEs is very complex and requires several SYSFNC or SYSARY calls in order to properly compute the magnitude of each component. For example, the x component of the forces couold have this expression:
where

is a non linear function and

and

are measurable states of the model that can be computed with the help of SYSFNC and SYSARY calls. If the computation of

is common to all VFORCEs then it is possible to cache the value of

at the beginning of each corrector iteration and then return the value:
At every subsequent VFOSUB call. This can be done safely by creating a CBKSUB where the ITERATION_BEG event is monitored to compute the cache value and set an internal flag ON. Both the cache and the flag will be defined in a COMMON block which the VFOSUBs share. For all other events, the flag is turned OFF.
Running without a CBKSUB
Listings
nocallback.acf, nocallback.adm and nocallback.f (see Appendix) correspond to a simple model with a VFOSUB. The model is a spring-mass system shown in
Figure 3. A VFOSUB computes the value of DX(16,1,1) and applies it to one of the masses. A dynamic simulation is run for 5.0 seconds.
Figure 3 Simple model used for comparisons.
A partial listing of the message file is shown below.
command: FILE/MODEL=ttcs/nocallback, OUTPUT_PREFIX=results/nocallback
--------------------------------------------------------------------------------------
| Model Title |
|====================================================================================|
| |
| Test model without a CBKSUB |
| |
-------------------------------------------------------------------------------------
command:
command: integrator/error=1.e-04
command: sim/dyn, end=5, step=200
Begin Simulation
****** Performing Dynamic Simulation using Gstiff I3 Integrator ******
The system is modelled with INDEX-3 DAEs.
The integrator is GSTIFF, CORRECTOR = original
Integration error = 1.000000E-04
Simulation Step Function Cumulative Integration CPU
Time Size Evaluations Steps Taken Order time
___________ ___________ ___________ ___________ _________ ________
0.00000E+00 1.25000E-03 0 0 1 0.02
5.00000E-01 1.87099E-02 96 45 5 0.05
1.00000E+00 2.34734E-02 176 85 5 0.06
1.50000E+00 1.25000E-02 242 115 5 0.06
2.00000E+00 2.50000E-02 310 149 6 0.06
…
Running with a CBKSUB
Listings yescallback.acf, yescallback.adm and yescallback.f correspond to the same model shown above. However, this time a CBKSUB is included. The CBKSUB prints a message at every event announcing the event, the simulation mode, the analysis mode, and the current time when available.
The CBKSUB is interested only in the ev_ITERATION_BEG event at which a FLAG is raisde and a cache VALUE is computed to be used in the subsequent VFOSUB calls. The same dynamic simulation is run and
Figure 4 shows the plots of the results comparing the runs with and without a CBKSUB. A partial listing of the message file when using a CBKSUB is shown below. Notice the CBKSUB prints a a message every time an iteration begins.
command: FILE/MODEL=ttcs/yescallback, OUTPUT_PREFIX=results/yescallback
---------------------------------------------------------------------------
| Model Title |
|==========================================================================|
| |
| Test model with a CBKSUB user-written subroutine | | | |
----------------------------------------------------------------------------
command:
command: integrator/error=1.e-04
command: sim/dyn, end=5, step=200
Begin Simulation
****** Performing Dynamic Simulation using Gstiff I3 Integrator ******
The system is modelled with INDEX-3 DAEs.
The integrator is GSTIFF, CORRECTOR = original
Integration error = 1.000000E-04
Event ev_ITERATION_BEG am_DYNAMICS am_INITIAL_CONDITI 0.000E+00
Event ev_ITERATION_BEG am_DYNAMICS am_INITIAL_CONDITI 0.000E+00
Event ev_ITERATION_BEG am_DYNAMICS am_INITIAL_CONDITI 0.000E+00
Event ev_ITERATION_BEG am_DYNAMICS am_INITIAL_CONDITI 0.000E+00
Event ev_ITERATION_BEG am_DYNAMICS am_DYNAMICS 0.125E-02
...
Figure 4 Comparison of results with and without CBKSUB.
Discussion
The fundamental question concerns the quality of the results. For the particular example presented above, the results with and without a CBKSUB will differ depending on the error tolerance set by the INTEGRATOR statement/command. In this case, using an error tolerance of 1.0E-04 shows indistinguisable results. If usinng a default INTEGRATION settings (error tolerance 1.0E-03) some differences appear but below the prescribed integration error nonetheless.
In general, using the strategy presented above ought to provide correct results (errors are under the prescribed integration error tolerance). However, the speed of convergence may be affected.
Appendix
nocallback.adm
Test model without a CBKSUB
!
!-------------------------------- SYSTEM UNITS ------------------------------
!
UNITS/
, FORCE = NEWTON
, MASS = KILOGRAM
, LENGTH = METER
, TIME = SECOND
!
!----------------------------------- PARTS ----------------------------------
!
!----------------------------------- Ground ---------------------------------
!
! adams_view_name='ground'
PART/1
, GROUND
!
! adams_view_name='MARKER_1'
MARKER/1
, PART = 1
, QP = 0, 0.5, 0
!
! adams_view_name='MARKER_2'
MARKER/2
, PART = 1
, QP = 0, 3.5, 0
!
! adams_view_name='MARKER_6'
MARKER/6
, PART = 1
, QP = 0, 3.2, 0
, REULER = 0D, 90D, 0D
!
! adams_view_name='MARKER_8'
MARKER/8
, PART = 1
, QP = 0, 1, 0
, REULER = 180D, 90D, 180D
!
! adams_view_name='MARKER_10'
MARKER/10
, PART = 1
, QP = 0, 0.5, 0
!
! adams_view_name='MARKER_13'
MARKER/13
, PART = 1
, QP = 0, 3.5, 0
!
! adams_view_name='MARKER_17'
MARKER/17
, PART = 1
, FLOATING
!
!------------------------------------ Part ----------------------------------
!
! adams_view_name='PART_2'
PART/2
, MASS = 1.0
, CM = 15
, IP = 1.0, 1.0, 1.0
!
! adams_view_name='MARKER_3'
MARKER/3
, PART = 2
, QP = 0, 1.6, 0
!
! adams_view_name='MARKER_7'
MARKER/7
, PART = 2
, QP = 0, 1, 0
, REULER = 180D, 90D, 180D
!
! adams_view_name='MARKER_9'
MARKER/9
, PART = 2
, QP = 0, 1.6, 0
!
! adams_view_name='MARKER_12'
MARKER/12
, PART = 2
, QP = 0, 1.6, 0
!
! adams_view_name='cm'
MARKER/15
, PART = 2
, QP = 0, 1.6, 0
, REULER = 0D, 90D, 0D
!
! adams_view_name='ELLIPSOID_1'
GRAPHICS/7
, ELLIPSOID
, CM = 3
, XSCALE = 0.2828427124
, YSCALE = 0.2828427124
, ZSCALE = 0.2828427124
!
!------------------------------------ Part ----------------------------------
!
! adams_view_name='PART_3'
PART/3
, MASS = 1.0
, CM = 16
, IP = 1.0, 1.0, 1.0
!
! adams_view_name='MARKER_4'
MARKER/4
, PART = 3
, QP = 0, 2.7, 0
!
! adams_view_name='MARKER_5'
MARKER/5
, PART = 3
, QP = 0, 3.2, 0
, REULER = 0D, 90D, 0D
!
! adams_view_name='MARKER_11'
MARKER/11
, PART = 3
, QP = 0, 2.7, 0
!
! adams_view_name='MARKER_14'
MARKER/14
, PART = 3
, QP = 0, 2.7, 0
!
! adams_view_name='cm'
MARKER/16
, PART = 3
, QP = 0, 2.7, 0
, REULER = 90D, 90D, 0D
!
! adams_view_name='ELLIPSOID_2'
GRAPHICS/8
, ELLIPSOID
, CM = 4
, XSCALE = 0.2828427124
, YSCALE = 0.2828427124
, ZSCALE = 0.2828427124
!
!------------------------------ DYNAMIC GRAPHICS ----------------------------
!
! adams_view_name='SPRING_1.I_graphic'
GRAPHICS/1
, FORCE
, ETYPE = SFORCE
, EID = 1
, EMARKER = 9
!
! adams_view_name='SPRING_1.J_graphic'
GRAPHICS/2
, FORCE
, ETYPE = SFORCE
, EID = 1
, EMARKER = 10
!
! adams_view_name='SPRING_2.I_graphic'
GRAPHICS/3
, FORCE
, ETYPE = SFORCE
, EID = 2
, EMARKER = 11
!
! adams_view_name='SPRING_2.J_graphic'
GRAPHICS/4
, FORCE
, ETYPE = SFORCE
, EID = 2
, EMARKER = 12
!
! adams_view_name='SPRING_3.I_graphic'
GRAPHICS/5
, FORCE
, ETYPE = SFORCE
, EID = 3
, EMARKER = 13
!
! adams_view_name='SPRING_3.J_graphic'
GRAPHICS/6
, FORCE
, ETYPE = SFORCE
, EID = 3
, EMARKER = 14
!
! adams_view_name='SPRING_1.spring_graphic'
GRAPHICS/9
, SPDP
, I = 9
, J = 10
, COILS = 10
, DA = 0.22
!
! adams_view_name='SPRING_2.spring_graphic'
GRAPHICS/11
, SPDP
, I = 11
, J = 12
, COILS = 10
, DA = 0.22
!
! adams_view_name='SPRING_3.spring_graphic'
GRAPHICS/13
, SPDP
, I = 13
, J = 14
, COILS = 10
, DA = 0.16
!
!-------------------------------- CONSTRAINTS -------------------------------
!
! adams_view_name='JOINT_1'
JOINT/1
, TRANSLATIONAL
, I = 5
, J = 6
!
! adams_view_name='JOINT_2'
JOINT/2
, TRANSLATIONAL
, I = 7
, J = 8
!
!----------------------------------- FORCES ---------------------------------
!
! adams_view_name='SPRING_1.sforce'
SFORCE/1
, TRANSLATIONAL
, I = 9
, J = 10
, FUNCTION = - 100.0*(dm(9,10)-1.0)
, - 0.0*vr(9,10)
, + 0.0
!
! adams_view_name='SPRING_2.sforce'
SFORCE/2
, TRANSLATIONAL
, I = 11
, J = 12
, FUNCTION = - 100.0*(dm(11,12)-1.0)
, - 0.0*vr(11,12)
, + 0.0
!
! adams_view_name='SPRING_3.sforce'
SFORCE/3
, TRANSLATIONAL
, I = 13
, J = 14
, FUNCTION = - 100.0*(dm(13,14)-1.0)
, - 0.0*vr(13,14)
, + 0.0
!
! adams_view_name='SFORCE_4'
SFORCE/4
, TRANSLATIONAL
, I = 15
, J = 1
, FUNCTION = 4.0
!
! adams_view_name='VFORCE_1'
VFORCE/1
, I = 16
, J = 17
, RM = 16
, FUNCTION = USER(1)
!
!----------------------------- ANALYSIS SETTINGS ----------------------------
!
RESULTS/
, XRF
!
END
nocallback.acf
nocallback
nocallback
integrator/error=1.e-04
sim/dyn, end=5, step=200
stop
nocallback.f
C----------------------------------------------------------------------
C Test model without a CBKSUB
C----------------------------------------------------------------------
C
C----------------------------------------------------------------------
C VFOSUB
C----------------------------------------------------------------------
SUBROUTINE VFOSUB(id, time, par, npar, dflag, iflag, result)
C
C Vforce function expression
IMPLICIT NONE
INTEGER id
DOUBLE PRECISION time
DOUBLE PRECISION par(*)
INTEGER npar
LOGICAL dflag
INTEGER iflag
DOUBLE PRECISION result(3)
C
C Local variable and parameter definitions
LOGICAL errflg
CHARACTER*80 mesage
INTEGER IPAR(3)
INTEGER NV
DOUBLE PRECISION DATINF(6)
INTEGER FLAG
DOUBLE PRECISION VALUE
C
C Program starts
ERRFLG = .FALSE.
IPAR(1) = 16
IPAR(2) = 1
IPAR(3) = 1
mesage='Error while reading from SYSARY in VFOSUB'
CALL SYSARY('DISP', IPAR, 3, DATINF, NV, errflg)
IF (errflg) CALL STOPERR(101, mesage)
result(1) = -DATINF(2)*30
result(2) = 0.0D0
result(3) = 0.0D0
C
RETURN
END
C
C----------------------------------------------------------------------
C STOPERR
C----------------------------------------------------------------------
SUBROUTINE STOPERR(id, mesage)
C
C Routine to call ADAMS Error Message routine and end program simulation
LOGICAL errflg
CHARACTER*(*) mesage
CHARACTER*4 endflg
INTEGER id
errflg=.TRUE.
endflg='STOP'
CALL ERRMES(errflg, mesage, id, endflg)
RETURN
END
yescallback.adm
Test model with a CBKSUB user-written subroutine
!
!-------------------------------- SYSTEM UNITS ---------------------------------
!
UNITS/
, FORCE = NEWTON
, MASS = KILOGRAM
, LENGTH = METER
, TIME = SECOND
!
!----------------------------------- PARTS -------------------------------------
!
!----------------------------------- Ground ------------------------------------
!
! adams_view_name='ground'
PART/1
, GROUND
!
! adams_view_name='MARKER_1'
MARKER/1
, PART = 1
, QP = 0, 0.5, 0
!
! adams_view_name='MARKER_2'
MARKER/2
, PART = 1
, QP = 0, 3.5, 0
!
! adams_view_name='MARKER_6'
MARKER/6
, PART = 1
, QP = 0, 3.2, 0
, REULER = 0D, 90D, 0D
!
! adams_view_name='MARKER_8'
MARKER/8
, PART = 1
, QP = 0, 1, 0
, REULER = 180D, 90D, 180D
!
! adams_view_name='MARKER_10'
MARKER/10
, PART = 1
, QP = 0, 0.5, 0
!
! adams_view_name='MARKER_13'
MARKER/13
, PART = 1
, QP = 0, 3.5, 0
!
! adams_view_name='MARKER_17'
MARKER/17
, PART = 1
, FLOATING
!
!------------------------------------ Part -------------------------------------
!
! adams_view_name='PART_2'
PART/2
, MASS = 1.0
, CM = 15
, IP = 1.0, 1.0, 1.0
!
! adams_view_name='MARKER_3'
MARKER/3
, PART = 2
, QP = 0, 1.6, 0
!
! adams_view_name='MARKER_7'
MARKER/7
, PART = 2
, QP = 0, 1, 0
, REULER = 180D, 90D, 180D
!
! adams_view_name='MARKER_9'
MARKER/9
, PART = 2
, QP = 0, 1.6, 0
!
! adams_view_name='MARKER_12'
MARKER/12
, PART = 2
, QP = 0, 1.6, 0
!
! adams_view_name='cm'
MARKER/15
, PART = 2
, QP = 0, 1.6, 0
, REULER = 0D, 90D, 0D
!
! adams_view_name='ELLIPSOID_1'
GRAPHICS/7
, ELLIPSOID
, CM = 3
, XSCALE = 0.2828427124
, YSCALE = 0.2828427124
, ZSCALE = 0.2828427124
!
!------------------------------------ Part -------------------------------------
!
! adams_view_name='PART_3'
PART/3
, MASS = 1.0
, CM = 16
, IP = 1.0, 1.0, 1.0
!
! adams_view_name='MARKER_4'
MARKER/4
, PART = 3
, QP = 0, 2.7, 0
!
! adams_view_name='MARKER_5'
MARKER/5
, PART = 3
, QP = 0, 3.2, 0
, REULER = 0D, 90D, 0D
!
! adams_view_name='MARKER_11'
MARKER/11
, PART = 3
, QP = 0, 2.7, 0
!
! adams_view_name='MARKER_14'
MARKER/14
, PART = 3
, QP = 0, 2.7, 0
!
! adams_view_name='cm'
MARKER/16
, PART = 3
, QP = 0, 2.7, 0
, REULER = 90D, 90D, 0D
!
! adams_view_name='ELLIPSOID_2'
GRAPHICS/8
, ELLIPSOID
, CM = 4
, XSCALE = 0.2828427124
, YSCALE = 0.2828427124
, ZSCALE = 0.2828427124
!
!------------------------------ DYNAMIC GRAPHICS -------------------------------
!
! adams_view_name='SPRING_1.I_graphic'
GRAPHICS/1
, FORCE
, ETYPE = SFORCE
, EID = 1
, EMARKER = 9
!
! adams_view_name='SPRING_1.J_graphic'
GRAPHICS/2
, FORCE
, ETYPE = SFORCE
, EID = 1
, EMARKER = 10
!
! adams_view_name='SPRING_2.I_graphic'
GRAPHICS/3
, FORCE
, ETYPE = SFORCE
, EID = 2
, EMARKER = 11
!
! adams_view_name='SPRING_2.J_graphic'
GRAPHICS/4
, FORCE
, ETYPE = SFORCE
, EID = 2
, EMARKER = 12
!
! adams_view_name='SPRING_3.I_graphic'
GRAPHICS/5
, FORCE
, ETYPE = SFORCE
, EID = 3
, EMARKER = 13
!
! adams_view_name='SPRING_3.J_graphic'
GRAPHICS/6
, FORCE
, ETYPE = SFORCE
, EID = 3
, EMARKER = 14
!
! adams_view_name='SPRING_1.spring_graphic'
GRAPHICS/9
, SPDP
, I = 9
, J = 10
, COILS = 10
, DA = 0.22
!
! adams_view_name='SPRING_2.spring_graphic'
GRAPHICS/11
, SPDP
, I = 11
, J = 12
, COILS = 10
, DA = 0.22
!
! adams_view_name='SPRING_3.spring_graphic'
GRAPHICS/13
, SPDP
, I = 13
, J = 14
, COILS = 10
, DA = 0.16
!
!-------------------------------- CONSTRAINTS -------------------------------
!
! adams_view_name='JOINT_1'
JOINT/1
, TRANSLATIONAL
, I = 5
, J = 6
!
! adams_view_name='JOINT_2'
JOINT/2
, TRANSLATIONAL
, I = 7
, J = 8
!
!----------------------------------- FORCES ---------------------------------
!
! adams_view_name='SPRING_1.sforce'
SFORCE/1
, TRANSLATIONAL
, I = 9
, J = 10
, FUNCTION = - 100.0*(dm(9,10)-1.0)
, - 0.0*vr(9,10)
, + 0.0
!
! adams_view_name='SPRING_2.sforce'
SFORCE/2
, TRANSLATIONAL
, I = 11
, J = 12
, FUNCTION = - 100.0*(dm(11,12)-1.0)
, - 0.0*vr(11,12)
, + 0.0
!
! adams_view_name='SPRING_3.sforce'
SFORCE/3
, TRANSLATIONAL
, I = 13
, J = 14
, FUNCTION = - 100.0*(dm(13,14)-1.0)
, - 0.0*vr(13,14)
, + 0.0
!
! adams_view_name='SFORCE_4'
SFORCE/4
, TRANSLATIONAL
, I = 15
, J = 1
, FUNCTION = 4.0
!
! adams_view_name='VFORCE_1'
VFORCE/1
, I = 16
, J = 17
, RM = 16
, FUNCTION = USER(1)
!
!------------------------------ DATA STRUCTURES -----------------------------
!
CBKSUB/1
, PRIORITY = 1
, FUNCTION = USER(0)\
, ROUTINE = yescallback::
!
!----------------------------- ANALYSIS SETTINGS ----------------------------
!
RESULTS/
, XRF
!
END
yescallback.acf
yescallback
yescallback
integrator/error=1.e-04
sim/dyn, end=5, step=200
stop
yescallback.f
C----------------------------------------------------------------------
C Test model with a CBKSUB user-written subroutine
C----------------------------------------------------------------------
include 'slv_cbksub_util.inc'
C
C----------------------------------------------------------------------
C VFOSUB
C----------------------------------------------------------------------
SUBROUTINE VFOSUB(id, time, par, npar, dflag, iflag, result)
C
C Vforce function expression
IMPLICIT NONE
INTEGER id
DOUBLE PRECISION time
DOUBLE PRECISION par(*)
INTEGER npar
LOGICAL dflag
INTEGER iflag
DOUBLE PRECISION result(3)
C
C Local variable and parameter definitions
LOGICAL errflg
CHARACTER*80 mesage
INTEGER IPAR(3)
INTEGER NV
DOUBLE PRECISION DATINF(6)
INTEGER FLAG
DOUBLE PRECISION VALUE
C
C Common data
C VALUE is the cache computed by the CBKSUB soubroutine
C FLAG=0 means no cache.
C FLAG=1 means cache is available.
COMMON/ FORCES/ VALUE, FLAG
C
C If the solver is numerically differencing or no cache is available,
C return the value computed using SYSARY.
C Do not change the value of FLAG because this may be a call made by
C the evaluator of output results.
IF(dflag.eq..TRUE..OR.FLAG.EQ.0) THEN
errflg = .FALSE.
IPAR(1) = 16
IPAR(2) = 1
IPAR(3) = 1
mesage='Error while reading from SYSARY in VFOSUB'
CALL SYSARY('DISP', IPAR, 3, DATINF, NV, errflg)
IF (errflg) CALL STOPERR(101, mesage)
result(1) = -DATINF(2)*30
result(2) = 0.0D0
result(3) = 0.0D0
return
END IF
C
C Cached VALUE is available
result(1) = VALUE
result(2) = 0.0D0
result(3) = 0.0D0
C
RETURN
END
C
C----------------------------------------------------------------------
C STOPERR
C----------------------------------------------------------------------
SUBROUTINE STOPERR(id, mesage)
C
C Routine to call ADAMS Error Message routine and end program simulation
LOGICAL errflg
CHARACTER*(*) mesage
CHARACTER*4 endflg
INTEGER id
errflg=.TRUE.
endflg='STOP'
CALL ERRMES(errflg, mesage, id, endflg)
RETURN
END
C
C----------------------------------------------------------------------
C CBKSUB
C----------------------------------------------------------------------
SUBROUTINE CBKSUB(time, event, data)
C
include 'slv_cbksub.inc'
C
C Input parameters
DOUBLE PRECISION time
INTEGER event, data(3)
C
C Event and mode names
CHARACTER*16 EVTNAME
CHARACTER*18 ANLYMOD
C
C Used in the SYSARY call
INTEGER IPAR(3)
INTEGER NV
LOGICAL ERRFLG
DOUBLE PRECISION DATINF(6)
CHARACTER*200 MESSAGE
INTEGER FLAG
DOUBLE PRECISION VALUE
C
C Common data
C VALUE is the cache computed by the CBKSUB soubroutine
C FLAG = 0 means no cache.
C FLAG = 1 means cache is available.
COMMON/ FORCES/ VALUE, FLAG
C
C Set the flag to 'no cache available'
FLAG = 0
C
C Compute cache if this is an ev_ITERATION_BEG event
IF( event.eq.ev_ITERATION_BEG ) THEN
C
C This is a ev_ITERATION_BEG event.
WRITE(MESSAGE,'(A,A,A,A,A,A,e10.3)') 'Event ', EVTNAME(event),
* ' ', ANLYMOD(data(1)), ' ', ANLYMOD(data(2)), time
CALL USRMES(.TRUE.,MESSAGE, 0, 'INFO')
C
C Call SYSARY and update the cache
FLAG = 1
IPAR(1) = 16
IPAR(2) = 1
IPAR(3) = 1
CALL SYSARY('DISP', IPAR, 3, DATINF, NV, ERRFLG)
VALUE = -DATINF(2)*30
ENDIF
C
RETURN
END