|On this page…|
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.csfuntmpl_gate_fortran.c for an example that uses DWork vectors. See How to Use DWork Vectors for details on allocating data-typed work vectors.
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.
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 (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.
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.