Port Legacy Code
Find the States
If a variable-step solver is being used, it is critical that
all continuous states are identified in the code and put into the
C S-function state vector for integration instead of being integrated
by the Fortran code. Likewise, all derivative calculations must be
made available separately to be called from the mdlDerivatives
method
in the C S-function. Without these steps, any Fortran code with continuous
states will not be compatible with variable-step solvers if the S-function
is registered as a continuous block with continuous states.
Telltale signs of implicit advancement are incremented variables
such as M=M+1
or X=X+0.05
. If
the code has many of these constructs and you determine that it is
impractical to recode the source so as not to “ratchet forward,”
you might need to try another approach using fixed-step solvers.
If it is impractical to find all the implicit states and to
separate out the derivative calculations for the Simulink® engine,
another approach can be used, but you are limited to using fixed-step
solvers. The technique here is to call the Fortran code from the mdlUpdate
method
so the Fortran code is only executed once per major simulation integration
step. Any block outputs must be cached in a work vector so that mdlOutputs
can
be called as often as needed and output the values from the work vector
instead of calling the Fortran routine again (causing it to inadvertently
advance time). See sfuntmpl_gate_fortran.c
for
an example that uses DWork vectors. See How to Use DWork Vectors for details on allocating data-typed
work vectors.
Sample Times
If the Fortran code has an implicit step size in its algorithm,
coefficients, etc., ensure that you register the proper discrete sample
time in the C S-function mdlInitializeSampleTimes
method
and only change the block's output values from the mdlUpdate
method.
Store Data
If you plan to have multiple copies of this S-function used in one Simulink model, you need to allocate storage for each copy of the S-function in the model. The recommended approach is to use DWork vectors (see DWork Vector Basics).
If you plan to have only one copy of the S-function in the model,
DWork vectors still provide the most advanced method for storing data.
However, another alternative is to allocate a block of memory using
the malloc
command and store the pointer to that
memory in a PWork vector (see Elementary Work Vectors). In this case, you must remember
to deallocate the memory using the free
command
in the S-function mdlTerminate
method.
Use Flints if Needed
Use flints (floating-point ints
) to keep
track of time. Flints (for IEEE-754 floating-point numerics) have
the useful property of not accumulating roundoff error when adding
and subtracting flints. Using flint variables in DOUBLE PRECISION
storage
(with integer values) avoids roundoff error accumulation that would
accumulate when floating-point numbers are added together thousands
of times.
DOUBLE PRECISION F : : F = F + 1.0 TIME = 0.003 * F
This technique avoids a common pitfall in simulations.
Considerations for Real Time
Since very few Fortran applications are used in a real-time environment, it is common to come across simulation code that is incompatible with a real-time environment. Common failures include unbounded (or large) iterations and sporadic but time-intensive side calculations. You must deal with these directly if you expect to run in real time.
Conversely, it is still perfectly good practice to have iterative or sporadic calculations if the generated code is not being used for a real-time application.