Code Generation C Code - MapleSim Help

MapleSim Code Generation - C Code

 • A:-GetCompiledProc('ccodeonly'=true) (MapleSim[LinkModel][GetCompiledProc]) and the code generation app create C code that can be used to integrate a MapleSim system using a specified solver.
 • A:-GetCompiledProc('ccodeonly'=true) is available for any system (as long as one of the fixed step solvers is chosen in the solver option).
 • The mapping of system variables, inputs, outputs, and parameters to the ic, u, y, and p arrays, respectively, is provided in the code comments.
 • At the start of the generated code there is an error handling routine:

void SolverError(double t, char *errmsg)

 – Parameters:
 • t: time at which error occurred
 • errmsg: error message string
 – Purpose:
 • This routine is called by the code when derivative values become undefined or unsolvable, when constraint projection fails, when event iteration does not terminate, or when any model-specified 'terminate' conditions trigger.
 • This procedure is generated to either report errors back to Maple for ccodeonly=false, or to populate the error buffer and terminate integration when running the C function stand-alone for ccodeonly=true.
 • For ccodeonly=true, the interface to the driver is the ParamDriverC function:

long ParamDriverC(double t0, double dt, long npts, double *ic, double *p, double *out, char *errbuf, long internal)

 – Parameters:
 • t0: initial time
 • dt: fixed time step
 • npts: number of points for output
 • ic: input array of initial conditions (NULL to use defaults)
 • p: input array of parameter values (NULL to use defaults)
 • out: output array of computed values (npts x (nouts+1))
 • errbuf: pointer to buffer to use for error messages (char[1000])
 • internal: use 0 for ccodeonly=true
 • The nouts value is the number of outputs, and the data in the output array is organized as $t0, out1(t0), ..., outn(t0), t1, out1(t1), ...$
 • The return value of ParamDriverC is the number of point values populated in the output array, which will only be less than the number of points on input (npts) in the event of an error. If this value is less, then errbuf will be populated with the error that stopped the integration.

 • The remaining information on the internals of the implementation, or the lower level interface functions, is provided for the use of the generated code in another solver.

 • For the purpose of the code usage, a SolverStruct structure is created, to be passed to the various interface functions. The interface functions are as follows:

void SolverSetup(double t0, double *ic, double *u, double *p, double *y, double h, SolverStruct *S)

 – Parameters:
 • t0: initial time
 • ic: input array of initial conditions (NULL to use defaults)
 • u: input array of input values
 • p: input array of parameter values (NULL to use defaults)
 • y: output array of output values at initial point
 • h: step size to use for integration
 • S: 'SolverStruct' structure storing integration data
 – Purpose:
 • This routine initializes the integration data to what is specified, performs any initial point computations (projection, initial event iteration), and computes the outputs. Projection is used to converge to a consistent initial value set if the input initial conditions are different from the default initial data. Initial data may be altered (to accommodate constraints) for any variables that do not have their initial values designated as 'fixed' in the original model. Note: the inputs must be correctly set to the input values before this routine is called.

void SolverStep(SolverStruct *S)

 – Parameters:
 • S: 'SolverStruct' structure storing integration data
 – Purpose:
 • This routine performs the solver step, updating the time and states.

void SolverUpdate(double *u, SolverStruct *S)

 – Parameters:
 • u: input array of input values
 • S: 'SolverStruct' structure storing integration data
 – Purpose:
 • This routine performs any maintenance (projection, event iteration) that needs to be performed after SolverStep and the inputs are updated, but before the outputs are computed. Note: it is critical that the updated inputs be provided to this routine, as otherwise a single step time lag will be introduced into the integrator.

void SolverOutputs(double *y, SolverStruct *S)

 – Parameters:
 • y: output array of output values
 • S: 'SolverStruct' structure storing integration data
 – Purpose:
 • This routine computes the output values at the end of the current step.

void SolverTerminate(SolverStruct *S)

 – Parameters:
 • S: 'SolverStruct' structure storing integration data
 – Purpose:
 • This routine cleans up allocated data at the end of integration.

 • The following is a simple example that demonstrates the use of the lower level interface functions in an Euler integrator that outputs Maple format text data while performing an integration. It has one input (value = t), and four outputs.

int main(void)

{

SolverStruct S;

double u[1],y[4];

printf("result := [\n");

/* Initialize, use ic=NULL (default) and p=NULL (default) */

SolverSetup(NULL,u,NULL,y,0.010000,&S);

u[0]=t0;

/* Output */

printf("[%e,%e,%e,%e,%e],\n",S.w[0],y[0],y[1],y[2],y[3]);

/* Integration loop */

while(S.w[0]<10.000000-1e-10) {

/* Take a step with states */

SolverStep(&S);

/* Update inputs */

u[0]=S.w[0];

/* Resolve */

SolverUpdate(u,&S);

/* Output */

SolverOutputs(y,&S);

printf("[%e,%e,%e,%e,%e],\n",S.w[0],y[0],y[1],y[2],y[3]);

}

/* Clean up */

printf("NULL]:\n");

SolverTerminate(&S);

exit(0);

}

Examples

 > $A≔\mathrm{MapleSim}:-\mathrm{LinkModel}\left('\mathrm{filename}'=\mathrm{cat}\left(\mathrm{kernelopts}\left('\mathrm{toolboxdir}'=\mathrm{MapleSim}\right),"/data/examples/RLCcircuit.msim"\right)\right):$
 > $\mathrm{cCode}≔A:-\mathrm{GetCompiledProc}\left(\mathrm{path}=\mathrm{kernelopts}\left('\mathrm{homedir}'\right),\mathrm{ccodeonly}=\mathrm{true},\mathrm{solver}="Euler"\right)$
 ${\mathrm{cCode}}{≔}{"cMsimModel.c"}$ (1)
 > $\mathrm{FileTools}:-\mathrm{Exists}\left(\mathrm{cat}\left(\mathrm{kernelopts}\left('\mathrm{homedir}'\right),\mathrm{kernelopts}\left('\mathrm{dirsep}'\right),\mathrm{cCode}\right)\right)$
 ${\mathrm{true}}$ (2)