opspec = addoutputspec(opspec,'bsm2_ol_lin/combiner_2',1);
avgeffluent = mean(effluent,1);
endeffluent = effluent(end,:);
opspec.Outputs(1).Known = ones(21,1);
opspec.Outputs(1).y = avgeffluent;
opspec = addoutputspec(opspec, 'bsm2_ol_lin/Dewatering',1);
avgeffluent = mean(effluent,1);
endeffluent = effluent(end,:);
opspec.Outputs(2).Known = ones(21,1);
opspec.Outputs(2).y = avgeffluent;
opspec.Inputs(i).Known = 1;
opspec.Inputs(1).u = Qbypass;
opspec.Inputs(2).u = Qbypassplant;
opspec.Inputs(3).u = QbypassAS;
opspec.Inputs(4).u = KLa1;
opspec.Inputs(5).u = KLa2;
opspec.Inputs(6).u = KLa3;
opspec.Inputs(7).u = KLa4;
opspec.Inputs(8).u = KLa5;
opspec.Inputs(9).u = carb1;
opspec.Inputs(10).u = carb2;
opspec.Inputs(11).u = carb3;
opspec.Inputs(12).u = carb4;
opspec.Inputs(13).u = carb5;
opspec.Inputs(14).u = Qintr;
opspec.Inputs(15).u = Qr;
opspec.Inputs(16).u = Qw;
opspec.Inputs(17).u = Qthickener2AS;
opspec.Inputs(18).u = Qstorage;
opspec.Inputs(19).u = Qstorage2AS;
[op1,opreport] = findop('bsm2_ol_lin',opspec);
io(1) = linio('bsm2_ol_lin/Qbypass_split', 1, 'input');
io(2) = linio('bsm2_ol_lin/Qbypass',1,'input');
io(3) = linio('bsm2_ol_lin/Qbypassplant',1,'input');
io(4) = linio('bsm2_ol_lin/QbypassAS',1,'input');
io(5) = linio('bsm2_ol_lin/KLa1',1,'input');
io(6) = linio('bsm2_ol_lin/KLa2',1,'input');
io(7) = linio('bsm2_ol_lin/KLa3',1,'input');
io(8) = linio('bsm2_ol_lin/KLa4',1,'input');
io(9) = linio('bsm2_ol_lin/KLa5',1,'input');
io(10) = linio('bsm2_ol_lin/carb1',1,'input');
io(11) = linio('bsm2_ol_lin/carb2',1,'input');
io(12) = linio('bsm2_ol_lin/carb3',1,'input');
io(13) = linio('bsm2_ol_lin/carb4',1,'input');
io(14) = linio('bsm2_ol_lin/carb5',1,'input');
io(15) = linio('bsm2_ol_lin/Qintr',1,'input');
io(16) = linio('bsm2_ol_lin/Qr',1,'input');
io(17) = linio('bsm2_ol_lin/Qw',1,'input');
io(18) = linio('bsm2_ol_lin/Qthickener2AS',1,'input');
io(19) = linio('bsm2_ol_lin/Qstorage',1,'input');
io(20) = linio('bsm2_ol_lin/Qstorage2AS',1,'input');
io(21) = linio('bsm2_ol_lin/combiner_2',1,'output');
io(22) = linio('bsm2_ol_lin/Dewatering',1,'output');
sys = linearize('bsm2_ol_lin',op1,io);
* The DAE2_combiner_bsm2.c is a C-file S-function level 2 for a speed-enhanced IAWQ AD Model No 1.
* In this model the traditional states of the ADM1 and ion states + Sh2
* from the last iteration of the pHsolver and Sh2solver are combined to create the overall output
* at time t for all variables rather than using values for the ion states and h2
* that are one iteration old (h2 may still be considered old as it is based on the old pH
* but this is really a question of the chicken and the egg).
* Dept. Industrial Electrical Engineering and Automation (IEA)
* Lund University, Sweden
#define S_FUNCTION_NAME DAE2_combiner_bsm2
#define S_FUNCTION_LEVEL 2
* The sizes information is used by Simulink to determine the S-function
* block's characteristics (number of inputs, outputs, states, etc.).
static void mdlInitializeSizes(SimStruct *S)
ssSetNumSFcnParams(S, 0); /* Number of expected parameters */
if (ssGetNumSFcnParams(S) != ssGetSFcnParamsCount(S)) {
return; /* Return if number of expected != number of actual parameters */
ssSetNumContStates(S, 0);
ssSetNumDiscStates(S, 0);
if (!ssSetNumInputPorts(S, 1)) return;
ssSetInputPortWidth(S, 0, 59); /*(S, port index, port width) */
ssSetInputPortDirectFeedThrough(S, 0, 1);
if (!ssSetNumOutputPorts(S, 1)) return;
ssSetOutputPortWidth(S, 0, 51);
ssSetNumSampleTimes(S, 1);
ssSetNumNonsampledZCs(S, 0);
ssSetOptions(S, SS_OPTION_EXCEPTION_FREE_CODE);
* mdlInitializeSampleTimes:
* This function is used to specify the sample time(s) for your
* S-function. You must register the same number of sample times as
* specified in ssSetNumSampleTimes.
static void mdlInitializeSampleTimes(SimStruct *S)
ssSetSampleTime(S, 0, CONTINUOUS_SAMPLE_TIME);
ssSetOffsetTime(S, 0, 0.0);
#undef MDL_INITIALIZE_CONDITIONS /* Change to #undef to remove function */
#if defined(MDL_INITIALIZE_CONDITIONS)
* mdlInitializeConditions:
* In this function, you should initialize the continuous and discrete
* states for your S-function block. The initial states are placed
* in the state vector, ssGetContStates(S) or ssGetRealDiscStates(S).
* You can also perform any other initialization activities that your
* S-function may require. Note, this routine will be called at the
* start of simulation and if it is present in an enabled subsystem
* configured to reset states, it will be call when the enabled subsystem
* restarts execution to reset the states.
static void mdlInitializeConditions(SimStruct *S)
#endif /* MDL_INITIALIZE_CONDITIONS */
#undef MDL_START /* Change to #undef to remove function */
* This function is called once at start of model execution. If you
* have states that should be initialized once, this is the place
static void mdlStart(SimStruct *S)
* In this function, you compute the outputs of your S-function
* block. Generally outputs are placed in the output vector, ssGetY(S).
static void mdlOutputs(SimStruct *S, int_T tid)
real_T *y = ssGetOutputPortRealSignal(S,0);
InputRealPtrsType u = ssGetInputPortRealSignalPtrs(S,0);
for (i = 0; i < 33; i++) {
y[33] = -log10(*u[51]); /* pH */
y[34] = *u[51]; /* SH+ */
y[35] = *u[52]; /* Sva- */
y[36] = *u[53]; /* Sbu- */
y[37] = *u[54]; /* Spro- */
y[38] = *u[55]; /* Sac- */
y[39] = *u[56]; /* SHCO3- */
y[40] = *u[9] - *u[56]; /* SCO2 */
y[41] = *u[57]; /* SNH3 */
y[42] = *u[10] - *u[57]; /* SNH4+ */
#undef MDL_UPDATE /* Change to #undef to remove function */
* This function is called once for every major integration time step.
* Discrete states are typically updated here, but this function is useful
* for performing any tasks that should only take place once per
static void mdlUpdate(SimStruct *S, int_T tid)
#undef MDL_DERIVATIVES /* Change to #undef to remove function */
#if defined(MDL_DERIVATIVES)
* In this function, you compute the S-function block's derivatives.
* The derivatives are placed in the derivative vector, ssGetdX(S).
static void mdlDerivatives(SimStruct *S)
#endif /* MDL_DERIVATIVES */
* In this function, you should perform any actions that are necessary
* at the termination of a simulation. For example, if memory was
* allocated in mdlStart, this is the place to free it.
static void mdlTerminate(SimStruct *S)
#ifdef MATLAB_MEX_FILE /* Is this file being compiled as a MEX-file? */
#include "simulink.c" /* MEX-file interface mechanism */
#include "cg_sfun.h" /* Code generation registration function */