30
1 EXTERNAL INTERFACE TO SIMULINK by Robert M. Edwards Summer Faculty US Nuclear Regulatory Commission August 22, 2003 Contents: 1. Introduction ………………………………………………………………………………1 2. Execution of a SIMULINK model from the MATLAB command line……………….2 3. Execution of a SIMULINK model from a C Program…………………………………8 4. Execution of a SIMULINK model from FORTRAN…………………………………...9 5. Execution of a SIMULINK model from the Modular Modeling System (MMS)…….9 6. Execution of a SIMULINK model from TRACE……………………………………..14 7. Conclusion ………………………………………………………………………………21 Appendix A: simulink_demo.m script file ……………………………………………22 Appendix B: eng_simulink_demo.c program listing…………………………………24 Appendix C: FORTRAN eng_simulink_demo.f ……………………………………..27 1. Introduction: SIMULINK, a MATLAB option, provides a high-level block-programming language for dynamic simulation of systems of ordinary differential equations, discrete-time models, and hybrid continuous-time and discrete-time systems. Extensive control related blocks and the State Flow option are available to represent complex analog, digital and hybrid control systems. A standard feature of MATLAB is its capability to be called from an external program, and compatibility is provided for several C compilers and the Compaq Visual FORTRAN compiler version 6.6. The MATLAB documentation provides and describes elementary examples of how to call MATLAB from a program and to execute command line operations. Full control of a SIMULINK model is available from the MATLAB command line. The MATLAB external interface provides procedures for a program to put data into the MATLAB workspace, execute commands, and retrieve MATLAB results back to the program workspace. This document provides the additional examples of how to execute a SIMULINK model from a program and how to preserve SIMULINK state information for repeated execution of the model over an extended start-and-stop cycle spanning an indefinite period of accumulated simulation time. The ultimate example at the end of this report demonstrates a FORTRAN interface to both SIMULINK and the TRAC/RELAP Enhanced Computational Engine (TRACE). This ultimate example demonstrates the feasibility of developing a detailed control systems model in SIMULINK and interfacing it with a detailed systems model of a plant.

External Interface to SIMULINK

Embed Size (px)

Citation preview

Page 1: External Interface to SIMULINK

1

EXTERNAL INTERFACE TO SIMULINK

by

Robert M. Edwards

Summer Faculty

US Nuclear Regulatory Commission

August 22, 2003

Contents:

1. Introduction ………………………………………………………………………………1

2. Execution of a SIMULINK model from the MATLAB command line……………….2

3. Execution of a SIMULINK model from a C Program…………………………………8

4. Execution of a SIMULINK model from FORTRAN…………………………………...9

5. Execution of a SIMULINK model from the Modular Modeling System (MMS)…….9

6. Execution of a SIMULINK model from TRACE……………………………………..14

7. Conclusion ………………………………………………………………………………21

Appendix A: simulink_demo.m script file ……………………………………………22

Appendix B: eng_simulink_demo.c program listing…………………………………24

Appendix C: FORTRAN eng_simulink_demo.f ……………………………………..27

1. Introduction:

SIMULINK, a MATLAB option, provides a high-level block-programming language for

dynamic simulation of systems of ordinary differential equations, discrete-time models, and hybrid

continuous-time and discrete-time systems. Extensive control related blocks and the State Flow

option are available to represent complex analog, digital and hybrid control systems. A standard

feature of MATLAB is its capability to be called from an external program, and compatibility is

provided for several C compilers and the Compaq Visual FORTRAN compiler version 6.6. The

MATLAB documentation provides and describes elementary examples of how to call MATLAB

from a program and to execute command line operations. Full control of a SIMULINK model is

available from the MATLAB command line.

The MATLAB external interface provides procedures for a program to put data into the

MATLAB workspace, execute commands, and retrieve MATLAB results back to the program

workspace. This document provides the additional examples of how to execute a SIMULINK model

from a program and how to preserve SIMULINK state information for repeated execution of the

model over an extended start-and-stop cycle spanning an indefinite period of accumulated simulation

time. The ultimate example at the end of this report demonstrates a FORTRAN interface to both

SIMULINK and the TRAC/RELAP Enhanced Computational Engine (TRACE). This ultimate

example demonstrates the feasibility of developing a detailed control systems model in SIMULINK

and interfacing it with a detailed systems model of a plant.

Page 2: External Interface to SIMULINK

2

2. Execution of a SIMULINK model from the MATLAB command line

SIMULINK models may be executed from the MATLAB command line, and SIMULINK has

the useful feature of making the states of the model available at the end of a simulation and can

receive initial states that override any initial values in the SIMULINK model diagram. The

MATLAB command to execute a SIMULINK simulation is sim, and its online help is listed below:

SIM Simulate a Simulink model

SIM('model') will simulate your Simulink model using all simulation

parameter dialog settings including Workspace I/O options.

The SIM command also takes the following parameters. By default

time, state, and output are saved to the specified left hand side

arguments unless OPTIONS overrides this. If there are no left hand side

arguments, then the simulation parameters dialog Workspace I/O settings

are used to specify what data to log.

[T,X,Y] = SIM('model',TIMESPAN,OPTIONS,UT)

[T,X,Y1,...,Yn] = SIM('model',TIMESPAN,OPTIONS,UT)

T : Returned time vector.

X : Returned state in matrix or structure format.

The state matrix contains continuous states followed by

discrete states.

Y : Returned output in matrix or structure format.

For block diagram models this contains all root-level

outport blocks.

Y1,...,Yn : Can only be specified for block diagram models, where n

must be the number of root-level outport blocks. Each

outport will be returned in the Y1,...,Yn variables.

'model' : Name of a block diagram model.

TIMESPAN : One of:

TFinal,

[TStart TFinal], or

[TStart OutputTimes TFinal].

OutputTimes are time points which will be returned in

T, but in general T will include additional time points.

OPTIONS : Optional simulation parameters. This is a structure

created with SIMSET using name value pairs.

UT : Optional extern input. UT = [T, U1, ... Un]

where T = [t1, ..., tm]' or UT is a string containing a

function u=UT(t) evaluated at each time step. For

table inputs, the input to the model is interpolated

from UT.

Specifying any right hand side argument to SIM as the empty matrix, [],

will cause the default for the argument to be used.

Only the first parameter is required. All defaults will be taken from the

block diagram, including unspecified options. Any optional arguments

specified will override the settings in the block diagram.

See also SLDEBUG, SIMSET.

Overloaded methods

help idmodel/sim.m

Page 3: External Interface to SIMULINK

3

The simset command is used to override the simulation parameters and initial states defined in

the block diagram model. The simset command without any arguments returns the available settings,

and their formats, that can be set:

Solver: [ 'VariableStepDiscrete' |

'ode45' | 'ode23' | 'ode113' | 'ode15s' | 'ode23s' |

'FixedStepDiscrete' |

'ode5' | 'ode4' | 'ode3' | 'ode2' | 'ode1' ]

RelTol: [ positive scalar {1e-3} ]

AbsTol: [ positive scalar {1e-6} ]

Refine: [ positive integer {1} ]

MaxStep: [ positive scalar {auto} ]

MinStep: [ [positive scalar, nonnegative integer] {auto} ]

InitialStep: [ positive scalar {auto} ]

MaxOrder: [ 1 | 2 | 3 | 4 | {5} ]

FixedStep: [ positive scalar {auto} ]

OutputPoints: [ {'specified'} | 'all' ]

OutputVariables: [ {'txy'} | 'tx' | 'ty' | 'xy' | 't' | 'x' | 'y' ]

SaveFormat: [ {'Array'} | 'Structure' | 'StructureWithTime']

MaxDataPoints: [ non-negative integer {0} ]

Decimation: [ positive integer {1} ]

InitialState: [ vector {[]} ]

FinalStateName: [ string {''} ]

Trace: [ comma separated list of 'minstep', 'siminfo', 'compile',

'compilestats' {''}]

SrcWorkspace: [ {'base'} | 'current' | 'parent' ]

DstWorkspace: [ 'base' | {'current'} | 'parent' ]

ZeroCross: [ {'on'} | 'off' ]

To insure that a model’s states are saved, the following simset commands will create an

OPTIONS variable NEWOPT for use with the sim command of a simulation named test.mdl:

OPTIONS=simget('test'); %get the models default options and show what

%needs to be modified.

NEWOPT=simset(OPTIONS,'MaxDataPoints',0); %change to unlimited data points

NEWOPT=simset(NEWOPT,'OutputVariables','txy'); %add states to workspace I/O

NEWOPT=simset(NEWOPT,'FinalStateName','xFinal'); %add states to workspace I/O

NEWOPT=simset(NEWOPT,'InitialState',[]); %go with the original states

NEWOPT=simset(NEWOPT,'FixedStep','auto'); %choose variable step integration

NEWOPT=simset(NEWOPT,'Solver','ode45'); %choose good integration algo.

And when it is time to begin copying the final states of a simulation interval back to the initial

states of an extended simulation interval, the NEWOPT option is set as follows:

NEWOPT=simset(NEWOPT,'InitialState',xFinal); %pass along initial state

The simulink_demo.m script file demonstrates MATLAB commands to an elementary

SIMULINK model named test.mdl. The m-file is listed in Appendix A. All files are in the

rxbiglib/engine directory (d:\rxbiglib\engine on Roman’s windows 2000 machine.)

With the MATLAB working directory set to the location of these files, the script is invoked by

simply typing the name of the file. The script includes pauses for the user to study the commands

and comments as the script proceeds. The test.mdl SIMULINK model is shown in Figure 1:

Page 4: External Interface to SIMULINK

4

Figure 1: SIMULINK model test.mdl.

The model test has two states, the outputs of two simple analog integrators. The second

integrator is contained within the Subsystem block to demonstrate that the SIMULINK model can be

of arbitrary depth complexity. The top level diagram shows one input variable (In1), which must be

defined by the UT argument in the call to sim. Two output variables (Out1 and Out2) are indicated

in Figure 1 and are returned in the Y argument of sim. Ultimately, the inputs can represent the

response from an external systems code such as TRACE or the MMS, and the outputs can represent

the control algorithm response to manipulate control variables in the systems code. In this first

example m-file the input is simply sin(t), where t is the simulation time. The output of the first

integrator is sin(t)+1 and becomes the input to the second integrator. The second integrator thus

monotonically increases, and its state value must be preserved when the SIMULINK model is started

and stopped sequentially over the full length of an extended simulation-time interval. Although not

shown in Figure 1, the system states at each integration time step are returned in the X argument of

sim, and the times at each integration time step are returned in the T argument. The states at the end

of the simulation run are also returned in the variable name xFinal as requested by the simset option

settings in NEWOPT.

The simulink_demo.m script file first demonstrates a full 100 second simulation from time 0 to

time 100 and generates two plots presented in Figures 2 and 3.

The script file next demonstrates how to divide up the SIMULINK simulation into 100 one-

second simulations, where data exchanges could occur with a systems code. At the end of each one-

second time step, the script takes the final states at the end of the previous interval and passes them

on as initial states for the next interval. All the data from the 100 one-second simulations is

accumulated and plotted for comparison with the full 100 second simulation as shown in Figures 4

and 5.

Figures 4 and 5 actually show a somewhat smoother response than a single 100 second

simulation because the variable step integration algorithm (arbitrarily selected) is forced to hit the one

second intervals in the 100 one-second simulations. The script file then reruns the 100 second

Page 5: External Interface to SIMULINK

5

simulation with a maximum time step of 0.1 second to demonstrate that it too can have a somewhat

better representation of the sinusoidal input and responses as shown in Figures 6 and 7.

0 10 20 30 40 50 60 70 80 90 1000

20

40

60

80

100

120the states integral(u) and double integral(u)

Figure 2 above contains the two states, and Figure 3 below contains the two outputs.

0 10 20 30 40 50 60 70 80 90 100-20

0

20

40

60

80

100

120the outputs u and integral(u)

Page 6: External Interface to SIMULINK

6

0 10 20 30 40 50 60 70 80 90 100-20

0

20

40

60

80

100

120the states integral(u) and double integral(u)

Figure 4 above and Figure 5 below demonstrate that the state memory of a previous interval is

properly transferred to the next interval.

0 10 20 30 40 50 60 70 80 90 100-20

0

20

40

60

80

100

120the outputs u and integral(u)

Page 7: External Interface to SIMULINK

7

0 10 20 30 40 50 60 70 80 90 1000

20

40

60

80

100

120the states integral(u) and double integral(u) (small steps)

Figure 6 above and Figure 7 below demonstrate that a smoother 100 second simulation can be

achieved with a limit on maximum time step size.

0 10 20 30 40 50 60 70 80 90 100-20

0

20

40

60

80

100

120the outputs u and integral(u) (small steps)

Page 8: External Interface to SIMULINK

8

3. Execution of a SIMULINK model from a C Program

The eng_simulink_demo.c (and corresponding .exe) file demonstrate the same operation as the

script file except that it is done externally from the C program. A listing is provided in Appendix B.

Once a compiler is selected with the mex –setup command, the executable is created with the

MATLAB mex command (for an lcc compiler):

mex –f lccengmatopts.bat eng_simulink_demo.c

The command must be executed while in the rxbiglib/engine directory. The executable is

operated from the windows START/RUN menu. The program presents intermediate MATLAB

results using the windows message box feature which requires the user to click ok to continue (these

are like pauses). The message box feature is an important debugging tool to ensure that MATLAB

commands are correct. Unlike entering commands to a MATLAB command window, one does not

see the MATLAB response without the use of a message box.

The eng_simulink_demo program does the 100 one-second simulations similarly to the

simulink_demo script file. It includes the demonstration of how to put local C variables into the

inputs of the SIMULINK program. It also demonstrates how to retrieve MATLAB environment

variables back to the C program for processing. The ultimate response of the eng_simulink_demo

program produces the same plots shown in Figure 8 to demonstrate that it has performed just like the

script file, preserving state information across 100 one-second simulations:

0 10 20 30 40 50 60 70 80 90 100-20

0

20

40

60

80

100

120the outputs u and integral(u)

Figure 8 Results from the C program demonstrating preservation of state information over 100 one-

second simulations.

Page 9: External Interface to SIMULINK

9

The eng_simulink_demo.c program contains a conditional compilation based on the definition

(or lack of definition) of the string BOBS. BOBS must be defined for MATLAB release 13

compatibility and the location of the rxbiglib/engine directory. BOBS must not be defined for release

12 compatibility and the location of rxbiglib/engine on Roman’s win2k machine. One can examine

the listing to see the differences between release 12 and 13 calls to MATLAB C library functions.

4. Execution of a SIMULINK model from FORTRAN

The standalone FORTRAN code that parallels the C code version is listed in Appendix C for

MATLAB release 13. A version for MATLAB release 12 would have to modify commands similarly

to the conditional compilation in the C program of Appendix B. (The best way to perform such a

conversion is to examine the coding of the MATLAB supplied FORTRAN example fengdemo.f that

is supplied with each MATLAB release in the MATLAB\extern\examples\eng_mat directory.) The

FORTRAN example executes the same sequence of external SIMULINK functions that the C

example executes. The Compaq digital FORTRAN compiler (version 6.6) is required. The

MATLAB mex –setup command is used to select the compiler, and once selected, the command to

build the executable is:

mex –f df60engmatopts.bat eng_simulink_demo.f

5. Execution of a SIMULINK model from the Modular Modeling System (MMS)

In addition to Penn State’s control research using SIMULINK and MATLAB, substantial

research has used the Modular Modeling System, MMS (originated by EPRI, and subsequently

handled by B&W, Framatome, and now nHance Technologies.) The MMS provides an extensive

library of power plant components that are based on lumped-parameter models in contrast to TRACE

distributed parameter modeling. An MMS systems model is integrated with the Advanced

Continuous Simulation Language, which has built in facilities to schedule execution of discrete time

controllers at regular intervals. The standalone SIMULINK FORTRAN example was carved up and

placed in an example MMS model’s initial, discrete, and terminal sections. In this first example, the

functions of the standalone example are “joined” at the hip with the MMS model’s execution. A next

example, could pull a PI controller out of the MMS model and demonstrate its implementation in

SIMULINK. A TMI MMS primary system model was used in David Werkheiser’s MS thesis where

he implemented a portion of the B&W integrated control system (ICS) centered around the rod

control system, all within MMS. This model can be expanded with more BOP components suitable

for testing a complete ICS implemented in SIMULINK.

In principal, the same detailed digital-control algorithms and logics implemented in SIMULINK

could be tested with either TRACE or MMS. MMS may be more suitable for normal operational

transients whereas TRACE would have an advantage for study of control algorithm performance

leading to or during severe upset or accident conditions.

One aspect of TRACE execution that should be noted is that it is not routinely used to integrate

a model at a fixed execution frequency that would be representative of the needs to communicate

with a digital controller, e.g., 10 hz sampling for example. While, the maximum time step can be

readily limited to 0.1 seconds, special consideration to even-out the time steps to hit “even” 0.1

second intervals is required. Without this special consideration, simulation time might proceed, for

Page 10: External Interface to SIMULINK

10

example: 0.0, 0.05, 0.15, 0.22, 0.32, etc. Special consideration is needed to even out the TRACE

execution to communicate results at the required communication intervals of a digital controller; e.g.,

0, 0.1, 0.2, 0.3, 0.4, etc. The ACSL language employed by the MMS specifically addresses the

execution of discrete blocks at prescribed intervals and automatically adjusts the integration of the

continuous time model to hit required communication intervals.

An MMS/ACSL template file, modified to include external code in the initial, discrete and

terminal section is given below:

! include 'macfile.inc' ! comment out if no user-defined macros

Initial

include 'initfile.inc' ! comment out if no initialization at start command End ! of Initial

Dynamic

Constant tstop = 0.0, cint = 1.0

Termt (t.ge.tstop, '**** t>=tstop ****')

Derivative

Algorithm ialgder = 3 ! Euler

Nsteps nstpder = 10 ! initial time step = cint/nstpder

Maxterval maxtder = 100.0

Minterval mintder = 1.d-9

begin("noutil1")

!--------------------------------------------------------------------------------------------------

!model components are inserted here

!-------------------------------------------------------------------------------------------------- integer count

Constant count = 0

Procedural (= count)

count = count + 1

End ! of count procedural

finish()

End ! of Derivative

include 'discrbl.inc' ! uncomment if discrete blocks End ! of Dynamic

Terminal

include 'term.inc' ! uncomment if terminal calculations End ! of Terminal

End ! of Program.

The bolded items indicate places where ACSL Language code is inserted by the MMS model

builder. The MMS model builder inserts the code for a systems model in the

DYNAMIC/DERIVATIVE section of the template at “model components are inserted here”. An

MMS model definition can be created in a GUI interface as shown, for example, in Figure 9, and the

resulting code would be placed as indicated in the template.

Page 11: External Interface to SIMULINK

11

Figure 9: Example of an MMS GUI for defining a systems model.

Page 12: External Interface to SIMULINK

12

The carved-up SIMULINK FORTRAN example is placed through the indicated include

statements in the template. The carved-up FORTRAN contained in the include files are listed below:

'initfile.inc’ operations performed once at initialization integer engOpen, engGetVariable, mxCreateDoubleMatrix

integer mxGetPr

integer ep, TT, D, dummy

double precision time(11,2),data(2)

character*801 mbuffer

integer engPutVariable, engEvalString, engClose, engOutputBuffer

integer temp, status

CONSTANT time=0.0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0,...

1.0,2.0,3.0,4.0,5.0,6.0,7.0,8.0,9.0,10.0,11.0

Procedural

ep=engOpen('MATLAB')

dummy=engEvalString(ep, 'cd c:/users/rxbiglib/engine') .ne.0)

dummy=engEvalString(ep,'OPTIONS=simget(''test'');')

dummy=engEvalString(ep,'NEWOPT=simset(OPTIONS,''MaxDataPoints'',0);')

dummy=engEvalString(ep,'NEWOPT=simset(NEWOPT,''OutputVariables'',''txy'');')

dummy=engEvalString(ep,'NEWOPT=simset(NEWOPT,''FinalStateName'',''xFinal'');')

dummy=engEvalString(ep,'NEWOPT=simset(NEWOPT,''InitialState'',[]);')

dummy=engEvalString(ep,'NEWOPT=simset(NEWOPT,''FixedStep'',''auto'');')

dummy=engEvalString(ep,'NEWOPT=simset(NEWOPT,''Solver'',''ode45'')')

! first run the original model with its embedded initial states to the

! first 1 second interval.

!

! Create a variable from our time data 11 rows by 2 columns

!

INTEGER ik

TT = mxCreateDoubleMatrix(11, 2, 0)

do 20 iK=1,11

! /*note that FORTRAN Arrays follow MATLAB row-column syntax*/

20.. time(iK,2)=sin(time(ik,1))

call mxCopyReal8ToPtr(time, mxGetPr(TT), 22)

!

! Place the variable TT into the MATLAB workspace with name UTsubset

!

dummy=engPutVariable(ep, 'UTsubset', TT) .ne. 0)

!=======================================================================

! Run the simulation for 1 second with its built in initial conditions */

!==================================================

dummy=engEvalString(ep, '[tsubset,xsubset,ysubset]=sim(''test'',...

[0 1],NEWOPT,UTsubset);')

! initialze MATLAB arrays to hold the transient data

dummy=engEvalString(ep, 't=tsubset;x=xsubset;y=ysubset;')

end !Procedual

Page 13: External Interface to SIMULINK

13

'discrbl.inc' Operations performed at even intervals of 1 second DISCRETE DEMO

INTERVAL myDT=1.0

!

! NOW, loop through the remaining time, at each interval,

! but copy the final states of each interval to the initial states of the

! next

!

PROCEDURAL

if(T.GT.0) THEN

dummy=engEvalString(ep,'NEWOPT=simset(NEWOPT,''InitialState'',xFinal);')

dummy=engEvalString(ep,'UTsubset=[UTsubset(:,1)+1 sin(UTsubset(:,1)+1)]')

dummy=engEvalString(ep,'[tsubset,xsubset,ysubset]=.sim(''test'',[UTsubset(1,1) …

UTsubset(11,1)],NEWOPT,UTsubset);')

dummy=engEvalString(ep,'t=[t;tsubset];x=[x;xsubset];y=[y;ysubset];');

endif

END !PROCEDURAL

END !DISCRETE

'term.inc' Operations performed at the end of the simulation PROCEDURAL

dummy=engEvalString(ep, 'figure (3);plot(t,x);grid;...

title(''the states integral(u) and double integral(u)'')')

dummy=engEvalString(ep, 'figure (4);plot(t,y);grid;...

title(''the outputs u and integral(u)'')')

! an example of pulling data out of the matlab space for consumption locally

!

! D = engGetVariable(ep, 'xFinal')

! /*release 13 format */

! call mxCopyPtrToReal8(mxGetPr(D), data, 2)

!

! call mxDestroyArray(TT)

! call mxDestroyArray(D)

! status = engClose(ep)

!

if (status .ne. 0) then

! write(6,*) 'engClose failed'

! stop

endif

END ! of procedural

Page 14: External Interface to SIMULINK

14

6. Execution of a SIMULINK model from TRACE

This example modifies the TRACE example2a of its External Control Interface (ECI) documentation.

Example 2a demonstrates how an external FORTRAN program participates in a TRACE simulation. On

Roman’s computer, all files are rooted in the c:\trace directory. The interaction of TRACE and the control

example is specified in the tasklist file in the trace\example2a directory. The example program name is

control and is implemented with Compaq Digital Fortran, whose project is contained in the c:\trace\control

directory. A simple TRACE model of a heat exchanger is provided and the external control example reads the

value of time at each time step, calculates a flow ramp for one side of the heat exchanger, and deposits the

flow calculation into the TRACE simulation. The flow ramp is from 0 to 4252.18 in 20 seconds.

The control example was modified to additionally obtain a pressure variable, influenced by the

manipulated flow variable, and to execute a SIMULINK model of a PI control algorithm. The pressure

response to the flow ramp settles to 1.5534E7 and is shown in Figure 10, below:

0 20 40 60 80 100 120 140 1601.52

1.525

1.53

1.535

1.54

1.545

1.55

1.555x 10

7 pressure

Figure 10. TRACE ECI example2a response to flow ramp.

The SIMULINK PI control algorithm, shown below in Figure 11, contains a pressure setpoint, receives

the TRACE pressure as input 1, and computes a flow response to regulate TRACE pressure to the setpoint.

Figure 11. SIMULINK model trace_test interfaced to TRACE

Page 15: External Interface to SIMULINK

15

It was found that the PI algorithm could not handle the regulation to setpoint problem by itself.

However, the use of the PI algorithm’s output as an additive signal to the flow ramp was successful. The flow

and pressure responses with the SIMULINK interface are shown below in Figures 12 and 13:

0 20 40 60 80 100 120 140 160 1800

1000

2000

3000

4000

5000

6000total flow and flow contribution of the controller

flow

flowPI

Figure 12. SIMULINK additive flow signal flowPI and total flow.

0 20 40 60 80 100 120 140 160 1801.52

1.53

1.54

1.55

1.56

1.57

1.58x 10

7 pressure

Figure 13. SIMULINK-TRACE pressure regulation response to setpoint.

Page 16: External Interface to SIMULINK

16

There is considerable “ring” in the PI controller output and pressure response at the beginning of the

transient, shown below in Figures 14 and 15, which probably interferes with the ability of the PI controller to

handle the pressure regulation from 0 flow conditions.

-1 0 1 2 3 4

300

400

500

600

700

800

900

1000

total flow and flow contribution of the controller

flow

flowPI

Figure 14. SIMULINK-TRACE flow response from 0 to 4 seconds.

-0.5 0 0.5 1 1.5 2 2.5 3 3.5 4 4.5

1.525

1.53

1.535

1.54

1.545

1.55

1.555

1.56

1.565

1.57

x 107 pressure

Figure 15. SIMULINK-TRACE pressure response from 0 to 4 seconds.

Page 17: External Interface to SIMULINK

17

Pressure regulation is not the important aspect of this demonstration of an interface between TRACE

and SIMULINK. The example demonstrates that a SIMULINK program can be started and stopped

sequentially from an external FORTRAN program while retaining its memory of its previous states. In this

example, the SIMULINK state is the output of integral mode of the controller.

The modifications to the TRACE control example occur at five points in the coding: 1) the declaration

section, 2) an initialization section, 3) the definition of variables to be communicated with TRACE, 4)

simulation section, and 5) at the conclusion of the simulation. The listing of the entire control.f90 program is

best viewed or printed from within Microsoft Visual Studio.

The inserted code for the declaration section is listed below. The pressure variable was added to the

existing Real (sdk) declaration line. Unlike the standalone eng_simulink_demo.f program, it was found that

FORTRAN 90 requires the explicit definition of the interface to subroutines and functions used in the

MATLAB libraries.

REAL(sdk), TARGET :: flow, time, pressure

!===============================================================

!

integer*4 ep, T, UT, D, dummy, temp, status

character*601 buffer

DOUBLE PRECISION matdata, lasttime, lastpressure, UTlocal(2,2)

DOUBLE PRECISION flowPI

INTERFACE

FUNCTION engopen (C)

Integer*4 engopen

Character*(*) C

end function engopen

FUNCTION engEvalString (I,C)

Integer*4 engEvalString

Integer*4 I

Character*(*) C

end function engEvalString

FUNCTION engOutputBuffer (I,C)

Integer*4 engOutputBuffer

Integer*4 I

Character*(*) C

end function engOutputBuffer

FUNCTION mxCreateDoubleMatrix(I1, I2, I3)

Integer*4 mxCreateDoubleMatrix

Integer*4 I1,I2,I3

end function mxCreateDoubleMatrix

SUBROUTINE mxCopyReal8ToPtr(D, I1, I2)

Integer*4 I1,I2

Double Precision D

end subroutine mxCopyReal8ToPtr

FUNCTION engPutVariable(I1, C, I2)

Integer*4 engPutVariable

Integer*4 I1,I2

Character*(*) C

end function engPutVariable

FUNCTION mxGetPr(I)

Integer*4 mxGetPr

Integer*4 I

end function mxGetPr

FUNCTION engGetVariable(I,C)

Integer*4 engGetVariable

Integer*4 I

Character*(*) C

Page 18: External Interface to SIMULINK

18

end function engGetVariable

SUBROUTINE mxCopyPtrToReal8(I1, D, I2)

Integer*4 I1,I2

Double Precision D

end subroutine mxCopyPtrToReal8

SUBROUTINE mxDestroyArray(I)

Integer*4 I

end Subroutine mxDestroyArray

FUNCTION engClose(I)

Integer*4 engClose

Integer*4 I

end function engClose

END INTERFACE

The inserted code for the initialization section, just after the existing call to ExTransfer(‘Init’) , is

entered before the simulation begins and is listed below. The occurrences of print and read dialogues occur in

the child command window and are examples of how to debug MATLAB command sequences in this

environment.

CALL ExtTransfer('Init')

!===============================================================

!=========================================Initialization section

!

ep = engOpen('matlab')

!

if (ep .eq. 0) then

write(6,*) 'Can''t start MATLAB engine'

STOP

endif

dummy=engOutputBuffer(ep, buffer)

!

dummy=engEvalString(ep,'cd c:/users/rxbiglib/engine')

dummy=engEvalString(ep, 'pwd')

print *, buffer

print *, 'Type any number to continue'

read(*,*) temp

!

! Create pointers to MATLAB matricies' structures for copying

! FORTRAN data into MATLAB workspace

!

T = mxCreateDoubleMatrix(1, 1, 0)

D = mxCreateDoubleMatrix(1, 1, 0)

UT= mxCreateDoubleMatrix(2, 2, 0)

!

!Initialize MATLAB arrays to collect times and flows and pressures

!

dummy=engEvalString(ep, 't=[];flow=[];pressure=[];flowPI=[];')

!

!Initialize SIMULINK model trace_test simulation parameters

!

dummy=engEvalString(ep, 'OPTIONS=simget(''trace_test'');')

dummy=engEvalString(ep, 'NEWOPT=simset(OPTIONS,''MaxDataPoints'',0);')

dummy=engEvalString(ep, 'NEWOPT=simset(NEWOPT,''OutputVariables'',''txy'');')

dummy=engEvalString(ep, 'NEWOPT=simset(NEWOPT,''FinalStateName'',''xFinal'');')

dummy=engEvalString(ep, 'NEWOPT=simset(NEWOPT,''InitialState'',[]);')

dummy=engEvalString(ep, 'NEWOPT=simset(NEWOPT,''FixedStep'',''auto'');')

dummy=engEvalString(ep, 'NEWOPT=simset(NEWOPT,''Solver'',''ode45'')')

print *, buffer

print *, 'Type any number to continue'

read(*,*) temp

!

! Initialize the last time the simulink program called.

Page 19: External Interface to SIMULINK

19

lasttime=0.0

The inserted code for the definition of variables to be communicated with TRACE is contained in the

SetMissing subroutine. Examination of the TRACE input deck is needed to identify variables of interest to a

control program through the call to IsMissing.

aptr => pressure

CALL IsMissing('fluid','OldTime',2, 'pn','index',1,0,0,aptr)

The inserted code for the simulation section of the MassFlow subroutine, which is entered at each time

step, is listed below. This example has been programmed to build a pressure input table to linearly ramp the

pressure signal to the SIMULINK program over the last computational interval of TRACE from lasttime to the

current time. Strictly speaking, an analog control system providing a feedback signal to TRACE should

be integrated with the model equations. A SIMULINK model of a digital control system could sample and

hold its inputs and compute outputs for the next interval of a TRACE simulation. A digital controller would

execute at a fixed interval; e.g., every tenth of a second. A hopefully second order effect for possible

consideration of large distributed digital control systems is that, unlike operation with a systems simulation

code, not all process variables will arrive simultaneously, nor will all the outputs be applied at the same point

in time.

! call SIMULINK trace_test to compute new flow rate

!

! setup input table with the previous pressure and current pressure and

! put into matlab space under the name UTsubset

!

if(time.le.0.0) then

lastpressure=pressure

lasttime=time

endif

UTlocal(1,1)=lasttime

UTlocal(2,1)=time

UTlocal(1,2)=lastpressure

UTlocal(2,2)=pressure

call mxCopyReal8ToPtr(UTlocal(1,1), mxGetPr(UT), 4)

dummy=engPutVariable(ep, 'UTsubset', UT)

if(time.le.0.0) then dummy=engEvalString(ep, '[tsubset,xsubset,ysubset]=sim(''trace_test'',[0 0],NEWOPT,UTsubset);')

dummy=engEvalString(ep, 'ysubset')

print *, 'The output at time',time

print *, buffer

print *, 'Type any number to continue'

read(*,*) temp

else

dummy=engEvalString(ep, 'NEWOPT=simset(NEWOPT,''InitialState'',xFinal);') dummy=engEvalString(ep, '[tsubset,xsubset,ysubset]=sim(''trace_test'',[UTsubset(1,1) UTsubset(2,1)],NEWOPT,UTsubset);')

endif

!

! get the last output flow to pass into TRACE for the next interval

!

dummy=engEvalString(ep, 'lastoutput=ysubset(length(ysubset));')

D = engGetVariable(ep, 'lastoutput')

call mxCopyPtrToReal8(mxGetPr(D), flowPI, 1)

lasttime=time

lastpressure=pressure

flow = 4252.18_sdk*MIN(1.0_sdk, 0.05_sdk*time)+ flowPI

!

! put time and flow into MATLAB workspace and accummulate

! data for plot at the end

!

call mxCopyReal8ToPtr(time, mxGetPr(T), 1)

dummy=engPutVariable(ep, 'traceT', T)

call mxCopyReal8ToPtr(flow, mxGetPr(T), 1)

Page 20: External Interface to SIMULINK

20

dummy=engPutVariable(ep, 'traceF', T)

call mxCopyReal8ToPtr(Pressure, mxGetPr(T), 1)

dummy=engPutVariable(ep, 'traceP', T)

dummy=engEvalString(ep,'t=[t;traceT];flow=[flow;traceF];pressure=[pressure;traceP];')

dummy=engEvalString(ep,'flowPI=[flowPI;lastoutput];')

Finally, the code inserted at the conclusion of the TRACE simulation after the ENDDO TimeStepLoop

statement, generates MATLAB plots of the results:

ENDDO TimeStepLoop

!=============================================================================

!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

! end of job processing

dummy=engEvalString(ep,'figure(1);plot(t,flow,t,flowPI,''-.'');')

dummy=engEvalString(ep,'title(''total flow and flow contribution of the controller'');grid')

dummy=engEvalString(ep,'legend(''flow'',''flowPI'');')

dummy=engEvalString(ep,'figure(2);plot(t,pressure);title(''pressure'');grid')

if(dummy.ne.0) then

print *, buffer

print *, 'plot failed enter any number to continue'

read(*,*) temp

endif

!

! an example of pulling data of the matlab space for consumption locally

!

dummy=engEvalString(ep,'lenT=length(t)')

D = engGetVariable(ep, 'lenT')

! /*release 13 format */

call mxCopyPtrToReal8(mxGetPr(D), matdata, 1)

!

print *, 'number of data points, LOOK at the plots'

print *, matdata

print *, 'Type any number to continue'

read (*,*) temp

!

call mxDestroyArray(T)

call mxDestroyArray(D)

status = engClose(ep)

if (status .ne. 0) then

write(6,*) 'engClose failed'

print *, 'Type any number to continue'

read (*,*) temp

endif

Operational notes for Roman’s computer:

Although Roman doesn’t yet have visual studio and Compaq FORTRAN, a control executable was built

for his version of MATLAB release 12, where it has been modified for the path to his rxbiglib on his d: drive.

The control.f90 had to be modified for release 12 on Roman’s machine, and is in the file

c:\trace\control\control.f90 file. The release 13 version code, presented above, is contained in the file

c:\trace\control\control_matlab6p5.f90 file. The gains, and other programming, of the

d:\rxbiglib\engine\trace_test.mdl can still be modified as long as the basic input/output structure at the top

level diagram is not changed. Operation on Roman’s computer is as follows: Open up two command

windows (from programs/accessories menu). In one command window:

cd c:\trace

.\bin\driver

In the other command window:

cd c:\trace\example2a

..\bin\trace

Page 21: External Interface to SIMULINK

21

When the control program is started, a third command window (a child window) is

automatically created. Enter a number to the debugging outputs as they occur in this child window.

When you enter 1 to the last output, the figures and MATLAB command window will disappear.

The variables are accessible for additional processing and plots while the MATLAB command

window is open.

7. CONCLUSION

These series of external interface to SIMULINK examples demonstrate the feasibility of

constructing detailed models of control systems in the high-level block-programming language of

SIMULINK with all of its associated options, such as State Flow. The SIMULINK models of a

control system can be interfaced to systems codes such as TRACE or the MMS.

Things to watch for in expanded SIMULINK control applications are as follows:

1. The use of transport delay and memory blocks are often used in digital control systems

to “remember” the last value of a particular signal. These blocks require initial values.

If SIMULINK creates a discrete-time state for these blocks, then the coding of the

examples in this report should allow preservation of this state information. SIMULINK

lumps all the continuous-time and discrete-time states in its state vector. If SIMULINK

does not create discrete-time states for these blocks, then the external program can

remember the last outputs of these blocks and reset the initial values at the beginning of

the next simulation interval.

2. The “states” described by the State Flow option do not appear to be treated as discrete-

time states, but rather as “machine” states. Additional handshaking by the external

program may be required to remember the last machine state and restore them at the

beginning of a new simulation interval.

Page 22: External Interface to SIMULINK

22

APPENDIX A: simulink_demo.m script file % demo script file for calling a simulink block diagram sequentially

% while changing the inputs while preserving the state of the system.

% (Should be able to do the same programming sequence externally from

% Fortran or c)

%

% start in the directory with the model test.mdl that has the default

% simulationparameters, which are changed as necessary.

%

echo on;

OPTIONS=simget('test'); %get the models default options and show what

%needs to be modified.

NEWOPT=simset(OPTIONS,'MaxDataPoints',0); %change to unlimited data points

NEWOPT=simset(NEWOPT,'OutputVariables','txy'); %add states to workspace I/O

NEWOPT=simset(NEWOPT,'FinalStateName','xFinal'); %add states to workspace I/O

NEWOPT=simset(NEWOPT,'InitialState',[]); %go with the original states

NEWOPT=simset(NEWOPT,'FixedStep','auto'); %choose variable step

integration

NEWOPT=simset(NEWOPT,'Solver','ode45'); %choose good integration algo.

UTt=[0:0.1:100]; %setup a 1000 time points for an input vector

UT=[UTt' sin(UTt')]; %and create a sinusoidal input pattern

pause %now run the full simulation from 0 to 100 seconds

[t,x,y]=sim('test',[0 100],NEWOPT,UT);

figure (1);plot(t,x);grid;title('the states integral(u) and double integral(u)')

figure (2);plot(t,y);grid;title('the outputs u and integral(u)')

xFinal %the final states

% look at the scope block in the simulink model to see why the

% double integral(u) monotonically increases

pause %=======================================================================

% NOW, lets divide up the simulation into 100 equal

% parts that might be representative of the needs of an

% external progam to call and interact with the inputs

% at each step; but in this demo we're going to use the

% same ultimate input pattern to demonstrate retention

% of previous state information.

%

% first run the original model with its embedded initial states to the

% first 1 second interval.

%

UTsubset=[];

for k=1:10

UTsubset=[UTsubset;UT(k,:)];

echo off

end

echo on

[tsubset,xsubset,ysubset]=sim('test',[0 1],NEWOPT,UTsubset);

xFinal

pause

% NOW, loop through the remaining time points, but copy the final states to

% the initial states of each remaining interval

t=tsubset;x=xsubset;y=ysubset; %prepare to concantate interval outputs

for k=1:99

NEWOPT=simset(NEWOPT,'InitialState',xFinal); %pass along initial state

UTsubset=[];

for m=1:10

UTsubset=[UTsubset;UT(m+k*10,:)]; %the next 10 inputs

end

Page 23: External Interface to SIMULINK

23

[tsubset,xsubset,ysubset]=sim('test',[k k+1],NEWOPT,UTsubset);

t=[t;tsubset];x=[x;xsubset];y=[y;ysubset]; %accummulate proof

echo off

end

echo on

xFinal

pause

figure (3);plot(t,x);grid;title('the states integral(u) and double integral(u)')

figure (4);plot(t,y);grid;title('the outputs u and integral(u)')

xFinal %the final states

% look at the scope block in the simulink model to see the last

% second of the interval

pause %=======================================================================

%

% NOW comparing figures 1 and 3 AND 2 with 4 there seems to be a a bit

% more "ragedness" to the full job. Want proof? Change the test.mdl

% simulation parameters to fixed step RK with a step size of 0.1 second.

NEWOPT=simset(NEWOPT,'InitialState',[]); %restore the original states

NEWOPT=simset(NEWOPT,'FixedStep',0.1); %choose tiny fixed step

NEWOPT=simset(NEWOPT,'Solver','ode5'); %choose good integration also.

[t,x,y]=sim('test',[0 100],NEWOPT,UT);

figure (5);plot(t,x);grid;title('the states integral(u) and double integral(u)

(small steps)')

figure (6);plot(t,y);grid;title('the outputs u and integral(u) (small steps)')

echo off

Page 24: External Interface to SIMULINK

24

APPENDIX B. eng_simulink_demo.c program listing /*

* eng_simulink_demo.c

*

* This example implements the simulink_demo.m file demonstration of how to call

* SIMULINK from the MATLAB command line and splitting the simulation up to allow

* for potentially time varying inputs that may depend, for example, TRACE

* Simulation results. The outputs of the SIMULINK model may be routed to TRACE

* to optain the response of the plant.

*

* Modifies the engwindemo.c provided by MATLAB: Copyright 1984-2000 The MathWorks, Inc.

*/

/* $Revision: 1.8 $ */

#include <windows.h>

#include <stdlib.h>

#include <stdio.h>

#include <string.h>

#include "engine.h"

#include "math.h"

/* ============== MUST CHOOSE PLATFORM BY EDITING THE FOLLOWING LINE */

#define BOBS /* comment this line out for Roman's release 12 on his computer */

static double Areal[6] = { 1, 2, 3, 4, 5, 6 };

int PASCAL WinMain (HINSTANCE hInstance,

HINSTANCE hPrevInstance,

LPSTR lpszCmdLine,

int nCmdShow)

{

Engine *ep;

mxArray *T = NULL, *a = NULL, *d = NULL;

char buffer[801];

double *Dreal, *Dimag;

double time[2][11] = { 0,0.1,0.2,0.3,0.4,0.5,0.6,0.7,0.8,0.9,1, 1,2,3,4,5,6,7,8,9,10,11 };

double tbeg;

int i;

/*

* Start the MATLAB engine

*/

if (!(ep = engOpen(NULL))) {

MessageBox ((HWND)NULL, (LPSTR)"Can't start MATLAB engine",

(LPSTR) "Engwindemo.c", MB_OK);

exit(-1);

}

/*

* PART I

*

* first get into the right directory, bring up the simulation and

* set the simulation parameters the way we want them

*/

/*

* Use engOutputBuffer to capture MATLAB output

*/

engOutputBuffer(ep, buffer, 800);

/*

* the evaluate string returns the result into the

* output buffer.

*/

#ifdef BOBS

engEvalString(ep, "cd c:/users/rxbiglib/engine");/*this is the path for bob's notebook computer*/

#else

engEvalString(ep, "cd d:/rxbiglib/engine"); /*this is the path for roman's win2kmachine */

#endif

engEvalString(ep, "pwd");

MessageBox ((HWND)NULL, (LPSTR)buffer, (LPSTR) "MATLAB - cd", MB_OK); /*std windows library*/

engEvalString(ep, "OPTIONS=simget('test')");

engEvalString(ep, "NEWOPT=simset(OPTIONS,'MaxDataPoints',0);");

engEvalString(ep, "NEWOPT=simset(NEWOPT,'OutputVariables','txy');");

engEvalString(ep, "NEWOPT=simset(NEWOPT,'FinalStateName','xFinal');");

Page 25: External Interface to SIMULINK

25

engEvalString(ep, "NEWOPT=simset(NEWOPT,'InitialState',[]);");

engEvalString(ep, "NEWOPT=simset(NEWOPT,'FixedStep','auto');");

engEvalString(ep, "NEWOPT=simset(NEWOPT,'Solver','ode45')");

MessageBox ((HWND)NULL, (LPSTR)buffer, (LPSTR) "MATLAB - NEWOPT", MB_OK);

/*

% NOW, lets divide up the simulation into 100 additional equal

% parts that might be representative of the needs of an

% external progam to call and interact with the inputs

% at each step; but in this demo we're going to use the

% same ultimate input pattern as simulink_demo.m

% to demonstrate retention of previous state information.

%

% first run the original model with its embedded initial states to the

% first 1 second interval.

%

*/

/*

* Create a variable from our time data

*/

T = mxCreateDoubleMatrix(11, 2, mxREAL); /* 11 rows by 2 columns*/

i=0;

while(i<11) { /*note that it is best to think of C arrays as */

time[1][i]=sin(time[0][i]); /*reversed notation of MATLAB, the first index */

i++; /*is the column, second index is the row!!! */

} /*and if you look back at the initialization */

/*you will see that columns fill first !! */

memcpy((char *) mxGetPr(T), (char *) time, 22*sizeof(double)); /* std C routine */

#ifndef BOBS

mxSetName(T, "UTsubset"); /*this is the release 12 format (not release13)*/

engPutArray(ep, T);

#else

engPutVariable(ep, "UTsubset", T); /*release 13 incorporates name in the call */

#endif

/*========================================================================================*/

engEvalString(ep, "UTsubset");

MessageBox ((HWND)NULL, (LPSTR)buffer, (LPSTR) "first UTsubset", MB_OK);

/* Run the simulation for 1 second with its built in initial conditions */

engEvalString(ep, "[tsubset,xsubset,ysubset]=sim('test',[0 1],NEWOPT,UTsubset);");

engEvalString(ep, "xFinal");

MessageBox ((HWND)NULL, (LPSTR)buffer, (LPSTR) "states at 1 sec", MB_OK);

/*

% NOW, loop through the remaining time 99 seconds, one second at a time,

% but copy the final states of each intervaql to the initial states of the

% next

%

*/

engEvalString(ep, "t=tsubset;x=xsubset;y=ysubset;"); /*initialze MATLAB arrays */

tbeg=1; /*to collect data from all 100 sec*/

while(tbeg<100)

{

engEvalString(ep, "NEWOPT=simset(NEWOPT,'InitialState',xFinal);"); /*last final to initial

of next */

engEvalString(ep, "UTsubset=[UTsubset(:,1)+1 sin(UTsubset(:,1)+1)]"); /*modify input for next

interval*/

engEvalString(ep, "[tsubset,xsubset,ysubset]=sim('test',[UTsubset(1,1)

UTsubset(11,1)],NEWOPT,UTsubset);");

engEvalString(ep, "t=[t;tsubset];x=[x;xsubset];y=[y;ysubset];"); /*accummulate results

*/

tbeg=tbeg+1;

}

engEvalString(ep, "figure (3);plot(t,x);grid;title('the states integral(u) and double

integral(u)')");

engEvalString(ep, "figure (4);plot(t,y);grid;title('the outputs u and integral(u)')");

/* an example of pulling data of the matlab space for consumption in c programming

*/

#ifndef BOBS

d = engGetArray(ep, "xFinal"); /*release 12 format */

#else

d = engGetVariable(ep, "xFinal"); /*release 13 format */

#endif

Page 26: External Interface to SIMULINK

26

if (d == NULL) {

MessageBox ((HWND)NULL, (LPSTR)"Get Array Failed", (LPSTR)"Engwindemo.c", MB_OK);

}

else {

Dreal = mxGetPr(d); /* yes MATLAB variables can be complex */

Dimag = mxGetPi(d);

if (Dimag)

sprintf(buffer,"imaginary final output???????: %g+%gi",Dreal[0],Dimag[0]);

else

sprintf(buffer,"final outputs: %g,%g",Dreal[0],Dreal[1]);

MessageBox ((HWND)NULL, (LPSTR)buffer, (LPSTR)"states at 100 sec", MB_OK);

mxDestroyArray(d);

}

engEvalString(ep, "whos"); /*list out variables in the workspace, just for fun*/

MessageBox ((HWND)NULL, (LPSTR)buffer, (LPSTR) "MATLAB - whos", MB_OK);

/*

* We're done! Free memory, close MATLAB engine and exit.

*/

mxDestroyArray(T);

engClose(ep);

return(0);

}

Page 27: External Interface to SIMULINK

27

APPENDIX C. FORTRAN eng_simulink_demo.f C

C This example implements the simulink_demo.m file demonstration of how to call

C SIMULINK from the MATLAB command line and splitting the simulation up to allow

C for potentially time varying inputs that may depend, for example, TRACE

C Simulation results. The outputs of the SIMULINK model may be routed to TRACE

C to optain the response of the plant.

C

C Modifies the fengdemo.f MATLAB Example Copyright 1984-2000 The MathWorks, Inc.

C======================================================================

C $Revision: 1.9 $

program main

C-----------------------------------------------------------------------

C (pointer) Replace integer by integer*8 on the DEC Alpha

C 64-bit platform

C

integer engOpen, engGetVariable, mxCreateDoubleMatrix

integer mxGetPr

integer ep, T, D, dummy

C----------------------------------------------------------------------

C

C Other variable declarations here

double precision time(11,2),data(2)

character*801 buffer

integer engPutVariable, engEvalString, engClose, engOutputBuffer

integer temp, status

data time / 0.0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0,

1 1,2,3,4,5,6,7,8,9,10,11/

C

ep = engOpen('matlab ')

C

if (ep .eq. 0) then

write(6,*) 'Can''t start MATLAB engine'

stop

endif

dummy=engOutputBuffer(ep, buffer)

C

if (engEvalString(ep, 'cd c:/users/rxbiglib/engine') .ne.0) then

write(6,*) 'engEvalString failed on cd'

stop

endif

dummy=engEvalString(ep, 'pwd')

print *, buffer

print *, 'Type any number to continue'

read(*,*) temp

dummy=engEvalString(ep, 'OPTIONS=simget(''test'');')

C=======================================================================column 73

dummy=engEvalString(ep, 'NEWOPT=simset(OPTIONS,''MaxDataPoints'',0 silly old 72

column limitation

1);')

dummy=engEvalString(ep, 'NEWOPT=simset(NEWOPT,''OutputVariables'',

1''txy'');')

dummy=engEvalString(ep, 'NEWOPT=simset(NEWOPT,''FinalStateName'','

1'xFinal'');')

dummy=engEvalString(ep, 'NEWOPT=simset(NEWOPT,''InitialState'',[])

1;')

dummy=engEvalString(ep, 'NEWOPT=simset(NEWOPT,''FixedStep'',''auto

1'');')

dummy=engEvalString(ep, 'NEWOPT=simset(NEWOPT,''Solver'',''ode45''

1)')

print *, buffer

print *, 'Type any number to continue'

read(*,*) temp

C=======================================================================column 73

Page 28: External Interface to SIMULINK

28

C NOW, lets divide up the simulation into 100 additional equal

C parts that might be representative of the needs of an

C external progam to call and interact with the inputs

C at each step; but in this demo we're going to use the

C same ultimate input pattern as simulink_demo.m

C to demonstrate retention of previous state information.

C

C first run the original model with its embedded initial states to the

C first 1 second interval.

C

C Create a variable from our time data 11 rows by 2 columns

C

T = mxCreateDoubleMatrix(11, 2, 0)

do 20 i=1,11

C /*note that FORTRAN Arrays follow MATLAB row-column syntax*/

20 time(i,2)=sin(time(i,1))

call mxCopyReal8ToPtr(time, mxGetPr(T), 22)

C

C Place the variable T into the MATLAB workspace with name UTsubset

C

if (engPutVariable(ep, 'UTsubset', T) .ne. 0) then

C /*release 13 incorporates name in the call */

write(6,*) 'engPutVariable failed'

print *, 'Type any number to continue'

read(*,*) temp

stop

endif

dummy=engEvalString(ep, 'UTsubset')

print *, buffer

print *, 'Type any number to continue'

read(*,*) temp

C====================================================================================

C Run the simulation for 1 second with its built in initial conditions */

C=======================================================================column 73

dummy=engEvalString(ep, '[tsubset,xsubset,ysubset]=sim(''test'',[0

1 1],NEWOPT,UTsubset);')

dummy=engEvalString(ep, 'xFinal')

print *, 'The states after 1 second'

print *, buffer

print *, 'Type any number to continue'

read(*,*) temp

C

C NOW, loop through the remaining time 99 seconds, one second at a time,

C but copy the final states of each intervaql to the initial states of the

C next

C

C

dummy=engEvalString(ep, 't=tsubset;x=xsubset;y=ysubset;')

C /*initialze MATLAB arrays */

DO 100 I=1,99

dummy=engEvalString(ep, 'NEWOPT=simset(NEWOPT,''InitialState'',x

1Final);')

dummy=engEvalString(ep, 'UTsubset=[UTsubset(:,1)+1 sin(UTsubset(

1:,1)+1)]')

dummy=engEvalString(ep, '[tsubset,xsubset,ysubset]=sim(''test'',

1[UTsubset(1,1) UTsubset(11,1)],NEWOPT,UTsubset);')

dummy=engEvalString(ep, 't=[t;tsubset];x=[x;xsubset];y=[y;ysubse

1t];')

100 CONTINUE

dummy=engEvalString(ep, 'figure (3);plot(t,x);grid;title(''the sta

1tes integral(u) and double integral(u)'')')

dummy=engEvalString(ep, 'figure (4);plot(t,y);grid;title(''the out

1puts u and integral(u)'')')

C an example of pulling data of the matlab space for consumption in c programming

Page 29: External Interface to SIMULINK

29

C

D = engGetVariable(ep, 'xFinal')

C /*release 13 format */

call mxCopyPtrToReal8(mxGetPr(D), data, 2)

C========================================================================================

print *, 'the final states in FORTRAN, LOOK at the plots'

print *, data

print *, 'Type any number to continue'

read (*,*) temp

C

call mxDestroyArray(T)

call mxDestroyArray(D)

status = engClose(ep)

C

if (status .ne. 0) then

write(6,*) 'engClose failed'

stop

endif

C

stop

end

Page 30: External Interface to SIMULINK

30