Linux GNU 11.4.0 Code Coverage Report


Directory: ./
Coverage: low: ≥ 0% medium: ≥ 75.0% high: ≥ 90.0%
Coverage Exec / Excl / Total
Lines: 86.8% 231 / 0 / 266
Functions: -% 0 / 0 / 0
Branches: -% 0 / 0 / 0

OMCompiler/Compiler/Template/CodegenC.tpl
Line Branch Exec Source
1 /*
2 * This file is part of OpenModelica.
3 *
4 * Copyright (c) 1998-2026, Open Source Modelica Consortium (OSMC),
5 * c/o Linköpings universitet, Department of Computer and Information Science,
6 * SE-58183 Linköping, Sweden.
7 *
8 * All rights reserved.
9 *
10 * THIS PROGRAM IS PROVIDED UNDER THE TERMS OF AGPL VERSION 3 LICENSE OR
11 * THIS OSMC PUBLIC LICENSE (OSMC-PL) VERSION 1.8.
12 * ANY USE, REPRODUCTION OR DISTRIBUTION OF THIS PROGRAM CONSTITUTES
13 * RECIPIENT'S ACCEPTANCE OF THE OSMC PUBLIC LICENSE OR THE GNU AGPL
14 * VERSION 3, ACCORDING TO RECIPIENTS CHOICE.
15 *
16 * The OpenModelica software and the OSMC (Open Source Modelica Consortium)
17 * Public License (OSMC-PL) are obtained from OSMC, either from the above
18 * address, from the URLs:
19 * http://www.openmodelica.org or
20 * https://github.com/OpenModelica/ or
21 * http://www.ida.liu.se/projects/OpenModelica,
22 * and in the OpenModelica distribution.
23 *
24 * GNU AGPL version 3 is obtained from:
25 * https://www.gnu.org/licenses/licenses.html#GPL
26 *
27 * This program is distributed WITHOUT ANY WARRANTY; without
28 * even the implied warranty of MERCHANTABILITY or FITNESS
29 * FOR A PARTICULAR PURPOSE, EXCEPT AS EXPRESSLY SET FORTH
30 * IN THE BY RECIPIENT SELECTED SUBSIDIARY LICENSE CONDITIONS OF OSMC-PL.
31 *
32 * See the full OSMC Public License conditions for more details.
33 *
34 */
35
36 // This file defines templates for transforming Modelica/MetaModelica code to C
37 // code. They are used in the code generator phase of the compiler to write
38 // target code.
39 //
40 // There are two root templates intended to be called from the code generator:
41 // translateModel and translateFunctions. These templates do not return any
42 // result but instead write the result to files. All other templates return
43 // text and are used by the root templates (most of them indirectly).
44 //
45 // To future maintainers of this file:
46 //
47 // - A line like this
48 // # var = ""
49 // declares a text buffer that you can later append text to. It can also be
50 // passed to other templates that in turn can append text to it. In the new
51 // version of Susan it should be written like this instead:
52 // let &var = buffer ""
53 //
54 // - A line like this
55 // ..., Text var, ...
56 // declares that a template takes a tmext buffer as input parameter. In the
57 // new version of Susan it should be written like this instead:
58 // ..., Text &var, ...
59 //
60 // - A line like this:
61 // ..., var, ...
62 // passes a text buffer to a template. In the new version of Susan it should
63 // be written like this instead:
64 // ..., &var, ...
65 //
66 // - Style guidelines:
67 //
68 // - Try (hard) to limit each row to 80 characters
69 //
70 // - Code for a template should be indented with 2 spaces
71 //
72 // - Exception to this rule is if you have only a single case, then that
73 // single case can be written using no indentation
74 //
75 // This single case can be seen as a clarification of the input to the
76 // template
77 //
78 // - Code after a case should be indented with 2 spaces if not written on the
79 // same line
80
81 package CodegenC
82
83 import interface SimCodeTV;
84 import interface SimCodeBackendTV;
85 import CodegenUtil.*;
86 import CodegenUtilSimulation.*;
87 import CodegenCFunctions.*;
88 import ExpressionDumpTpl.*;
89
90 /* public */ template translateModel(SimCode simCode)
91 "Generates C code and Makefile for compiling and running a simulation of a
92 Modelica model.
93 used in Compiler/SimCode/SimCodeMain.mo"
94 ::=
95 match simCode
96 case sc as SIMCODE(modelInfo=modelInfo as MODELINFO(__)) then
97 let()= System.tmpTickResetIndex(0,2) /* auxFunction index */
98 let()= System.tmpTickResetIndex(0,20) /*parfor index*/
99
100 let &literalsFile = buffer ""
101 let &literalsFile += redirectToFile('<%fileNamePrefix%>_literals.h')
102 let &literalsFile += simulationLiteralsFile(fileNamePrefix, literals)
103 let &literalsFile += closeFile()
104
105 let &functionsHeader = buffer ""
106 let &functionsHeader += redirectToFile('<%fileNamePrefix%>_functions.h')
107 let &functionsHeader += simulationFunctionsHeaderFile(fileNamePrefix, modelInfo.functions, recordDecls, sc.generic_loop_calls)
108 let &functionsHeader += closeFile()
109
110 let &includes = buffer ""
111 let &includes += redirectToFile('<%fileNamePrefix%>_includes.h')
112 let &includes += externalFunctionIncludes(sc.externalFunctionIncludes)
113 let &includes += closeFile()
114
115 let &records = buffer ""
116 let &records += redirectToFile('<%fileNamePrefix%>_records.c')
117 let &records += recordsFile(fileNamePrefix, recordDecls, true /*isSimulation*/)
118 let &records += closeFile()
119
120 // adpro: write the main .c file last! Make on windows does not seem to realize that
121 // the .c file is newer than the .o file if we have succesive simulate commands
122 // for the same model (i.e. see testsuite/linearize/simextfunction.mos).
123
124 // If ParModelica generate the kernels file too.
125 if acceptParModelicaGrammar() then
126 let &cl = buffer ""
127 let &cl += redirectToFile('<%fileNamePrefix%>_kernels.cl')
128 let &cl += simulationParModelicaKernelsFile(fileNamePrefix, modelInfo.functions)
129 let &cl += closeFile()
130 ""
131
132 //this top-level template always returns an empty result
133 //since generated texts are written to files directly
134 end match
135 end translateModel;
136
137 /* public */ template simulationHeaderFile(SimCode simCode)
138 "Generates code for main C file for simulation target.
139 used in Compiler/Template/CodegenFMU.tpl"
140 ::=
141 let modelNamePrefixStr = modelNamePrefix(simCode)
142 match simCode
143 case simCode as SIMCODE(modelInfo=MODELINFO(functions=functions, varInfo=varInfo as VARINFO(__))) then
144 let hpcomType = getConfigString(HPCOM_CODE)
145
146 <<
147 /* Simulation code for <%dotPath(modelInfo.name)%> generated by the OpenModelica Compiler <%getVersionNr()%>. */
148 #if !defined(<%modelNamePrefixStr%>__MODEL_H)
149 #define <%modelNamePrefixStr%>__MODEL_H
150
151 #if defined(__cplusplus)
152 extern "C" {
153 #endif
154
155 <%if boolOr(stringEq(hpcomType,"pthreads"), stringEq(hpcomType,"pthreads_spin")) then "#define GC_THREADS"%>
156 #include "openmodelica.h"
157 #include "openmodelica_func.h"
158 #include "simulation_data.h"
159 #include "simulation/simulation_info_json.h"
160 #include "simulation/simulation_runtime.h"
161 #include "util/omc_error.h"
162 #include "simulation/jacobian_util.h"
163 #include "simulation/simulation_omc_assert.h"
164 #include "simulation/solver/model_help.h"
165 #include "simulation/solver/delay.h"
166 #include "simulation/solver/linearSystem.h"
167 #include "simulation/solver/nonlinearSystem.h"
168 #include "simulation/solver/mixedSystem.h"
169 #include "simulation/solver/spatialDistribution.h"
170 #include "simulation/solver/synchronous.h"
171
172 #include <string.h>
173
174 #include "<%fileNamePrefix%>_functions.h"
175
176 <%variableDefinitions(modelInfo, timeEvents)%><%functions |> fn hasindex i0 => '#define <%CodegenCFunctions.functionName(fn,false)%>_index <%i0%>'; separator="\n"%>
177
178 extern void <%symbolName(modelNamePrefixStr,"callExternalObjectDestructors")%>(DATA *_data, threadData_t *threadData);
179 #if !defined(OMC_NUM_NONLINEAR_SYSTEMS) || OMC_NUM_NONLINEAR_SYSTEMS>0
180 <% if intGt(varInfo.numNonLinearSystems, 0) then 'extern void <%symbolName(modelNamePrefixStr,"initialNonLinearSystem")%>(int nNonLinearSystems, NONLINEAR_SYSTEM_DATA *data);' %>
181 #endif
182 #if !defined(OMC_NUM_LINEAR_SYSTEMS) || OMC_NUM_LINEAR_SYSTEMS>0
183 <% if intGt(varInfo.numLinearSystems, 0) then 'extern void <%symbolName(modelNamePrefixStr,"initialLinearSystem")%>(int nLinearSystems, LINEAR_SYSTEM_DATA *data);' %>
184 #endif
185 #if !defined(OMC_NUM_MIXED_SYSTEMS) || OMC_NUM_MIXED_SYSTEMS>0
186 <% if intGt(varInfo.numMixedSystems, 0) then 'extern void <%symbolName(modelNamePrefixStr,"initialMixedSystem")%>(int nMixedSystems, MIXED_SYSTEM_DATA *data);' %>
187 #endif
188 #if !defined(OMC_NO_STATESELECTION)
189 extern void <%symbolName(modelNamePrefixStr,"initializeStateSets")%>(int nStateSets, STATE_SET_DATA* statesetData, DATA *data);
190 #endif
191 extern int <%symbolName(modelNamePrefixStr,"functionAlgebraics")%>(DATA *data, threadData_t *threadData);
192 extern int <%symbolName(modelNamePrefixStr,"function_storeDelayed")%>(DATA *data, threadData_t *threadData);
193 extern int <%symbolName(modelNamePrefixStr,"function_storeSpatialDistribution")%>(DATA *data, threadData_t *threadData);
194 extern int <%symbolName(modelNamePrefixStr,"function_initSpatialDistribution")%>(DATA *data, threadData_t *threadData);
195 extern int <%symbolName(modelNamePrefixStr,"updateBoundVariableAttributes")%>(DATA *data, threadData_t *threadData);
196 extern int <%symbolName(modelNamePrefixStr,"functionInitialEquations")%>(DATA *data, threadData_t *threadData);
197 extern int <%symbolName(modelNamePrefixStr,"functionInitialEquations_lambda0")%>(DATA *data, threadData_t *threadData);
198 extern int <%symbolName(modelNamePrefixStr,"functionRemovedInitialEquations")%>(DATA *data, threadData_t *threadData);
199 extern int <%symbolName(modelNamePrefixStr,"updateBoundParameters")%>(DATA *data, threadData_t *threadData);
200 extern int <%symbolName(modelNamePrefixStr,"checkForAsserts")%>(DATA *data, threadData_t *threadData);
201 extern int <%symbolName(modelNamePrefixStr,"function_ZeroCrossingsEquations")%>(DATA *data, threadData_t *threadData);
202 extern int <%symbolName(modelNamePrefixStr,"function_ZeroCrossings")%>(DATA *data, threadData_t *threadData, double* gout);
203 extern int <%symbolName(modelNamePrefixStr,"function_updateRelations")%>(DATA *data, threadData_t *threadData, int evalZeroCross);
204 extern const char* <%symbolName(modelNamePrefixStr,"zeroCrossingDescription")%>(int i, int **out_EquationIndexes);
205 extern const char* <%symbolName(modelNamePrefixStr,"relationDescription")%>(int i);
206 extern double <%symbolName(modelNamePrefixStr,"function_nextTimeEvent")%>(DATA *data, threadData_t *threadData);
207 extern void <%symbolName(modelNamePrefixStr,"function_initSample")%>(DATA *data, threadData_t *threadData);
208 extern int <%symbolName(modelNamePrefixStr,"initialAnalyticJacobianG")%>(DATA* data, threadData_t *threadData, JACOBIAN *jacobian);
209 extern int <%symbolName(modelNamePrefixStr,"initialAnalyticJacobianA")%>(DATA* data, threadData_t *threadData, JACOBIAN *jacobian);
210 extern int <%symbolName(modelNamePrefixStr,"initialAnalyticJacobianADJ")%>(DATA* data, threadData_t *threadData, JACOBIAN *jacobian);
211 extern int <%symbolName(modelNamePrefixStr,"initialAnalyticJacobianB")%>(DATA* data, threadData_t *threadData, JACOBIAN *jacobian);
212 extern int <%symbolName(modelNamePrefixStr,"initialAnalyticJacobianC")%>(DATA* data, threadData_t *threadData, JACOBIAN *jacobian);
213 extern int <%symbolName(modelNamePrefixStr,"initialAnalyticJacobianD")%>(DATA* data, threadData_t *threadData, JACOBIAN *jacobian);
214 extern int <%symbolName(modelNamePrefixStr,"initialAnalyticJacobianF")%>(DATA* data, threadData_t *threadData, JACOBIAN *jacobian);
215 extern int <%symbolName(modelNamePrefixStr,"initialAnalyticJacobianH")%>(DATA* data, threadData_t *threadData, JACOBIAN *jacobian);
216 extern int <%symbolName(modelNamePrefixStr,"functionJacG_column")%>(DATA* data, threadData_t *threadData, JACOBIAN *thisJacobian, JACOBIAN *parentJacobian);
217 extern int <%symbolName(modelNamePrefixStr,"functionJacA_column")%>(DATA* data, threadData_t *threadData, JACOBIAN *thisJacobian, JACOBIAN *parentJacobian);
218 extern int <%symbolName(modelNamePrefixStr,"functionJacADJ_column")%>(DATA* data, threadData_t *threadData, JACOBIAN *thisJacobian, JACOBIAN *parentJacobian);
219 extern int <%symbolName(modelNamePrefixStr,"functionJacB_column")%>(DATA* data, threadData_t *threadData, JACOBIAN *thisJacobian, JACOBIAN *parentJacobian);
220 extern int <%symbolName(modelNamePrefixStr,"functionJacC_column")%>(DATA* data, threadData_t *threadData, JACOBIAN *thisJacobian, JACOBIAN *parentJacobian);
221 extern int <%symbolName(modelNamePrefixStr,"functionJacD_column")%>(DATA* data, threadData_t *threadData, JACOBIAN *thisJacobian, JACOBIAN *parentJacobian);
222 extern int <%symbolName(modelNamePrefixStr,"functionJacF_column")%>(DATA* data, threadData_t *threadData, JACOBIAN *thisJacobian, JACOBIAN *parentJacobian);
223 extern int <%symbolName(modelNamePrefixStr,"functionJacH_column")%>(DATA* data, threadData_t *threadData, JACOBIAN *thisJacobian, JACOBIAN *parentJacobian);
224 extern const char* <%symbolName(modelNamePrefixStr,"linear_model_frame")%>(void);
225 extern const char* <%symbolName(modelNamePrefixStr,"linear_model_datarecovery_frame")%>(void);
226 extern int <%symbolName(modelNamePrefixStr,"mayer")%>(DATA* data, modelica_real** res, short *);
227 extern int <%symbolName(modelNamePrefixStr,"lagrange")%>(DATA* data, modelica_real** res, short *, short *);
228 extern int <%symbolName(modelNamePrefixStr,"getInputVarIndicesInOptimization")%>(DATA* data, int* input_var_indices, int* loop_input_indices);
229 extern int <%symbolName(modelNamePrefixStr,"pickUpBoundsForInputsInOptimization")%>(DATA* data, modelica_real* min, modelica_real* max, modelica_real*nominal, modelica_boolean *useNominal, char ** name, modelica_real * start, modelica_real * startTimeOpt);
230 extern int <%symbolName(modelNamePrefixStr,"setInputData")%>(DATA *data);
231 extern int <%symbolName(modelNamePrefixStr,"getTimeGrid")%>(DATA *data, modelica_integer * nsi, modelica_integer**idx);
232 extern void <%symbolName(modelNamePrefixStr,"function_initSynchronous")%>(DATA * data, threadData_t *threadData);
233 extern void <%symbolName(modelNamePrefixStr,"function_updateSynchronous")%>(DATA * data, threadData_t *threadData, long base_idx);
234 extern int <%symbolName(modelNamePrefixStr,"function_equationsSynchronous")%>(DATA * data, threadData_t *threadData, long base_idx, long sub_idx);
235 extern void <%symbolName(modelNamePrefixStr,"read_simulation_info")%>(SIMULATION_INFO* simulationData);
236 extern void <%symbolName(modelNamePrefixStr,"read_input_fmu")%>(MODEL_DATA* modelData);
237 extern void <%symbolName(modelNamePrefixStr,"function_savePreSynchronous")%>(DATA *data, threadData_t *threadData);
238 extern int <%symbolName(modelNamePrefixStr,"inputNames")%>(DATA* data, char ** names);
239 extern int <%symbolName(modelNamePrefixStr,"dataReconciliationInputNames")%>(DATA* data, char ** names);
240 extern int <%symbolName(modelNamePrefixStr,"dataReconciliationUnmeasuredVariables")%>(DATA* data, char ** names);
241 extern int <%symbolName(modelNamePrefixStr,"initializeDAEmodeData")%>(DATA *data, DAEMODE_DATA*);
242 extern int <%symbolName(modelNamePrefixStr,"functionLocalKnownVars")%>(DATA* data, threadData_t* threadData);
243 extern int <%symbolName(modelNamePrefixStr,"symbolicInlineSystem")%>(DATA* data, threadData_t* threadData);
244
245 #include "<%fileNamePrefix%>_literals.h"
246
247 <%if Flags.getConfigBool(Flags.PARMODAUTO) then "#include \"ParModelica/auto/om_pm_interface.hpp\""%>
248
249 <%if stringEq(hpcomType,"pthreads_spin") then "#include \"util/omc_spinlock.h\""%>
250
251 <%if Flags.isSet(HPCOM) then "#define HPCOM"%>
252
253 #if defined(HPCOM) && !defined(_OPENMP)
254 #error "HPCOM requires OpenMP or the results are wrong"
255 #endif
256 #if defined(_OPENMP)
257 #include <omp.h>
258 #else
259 /* dummy omp defines */
260 #define omp_get_max_threads() 1
261 #endif
262
263 #if defined(__cplusplus)
264 }
265 #endif
266
267 #endif /* !defined(<%modelNamePrefixStr%>__MODEL_H) */
268
269 <%\n%>
270 >>
271 end match
272 end simulationHeaderFile;
273
274 1122 template simulationFile_mixAndHeader(SimCode simCode, String modelNamePrefix)
275 ::=
276 let &mixheader = buffer ""
277 let()= textFileConvertLines(simulationFile_mix(simCode,&mixheader), '<%modelNamePrefix%>_11mix.c')
278 let()= textFile(&mixheader, '<%modelNamePrefix%>_11mix.h')
279 ""
280 end simulationFile_mixAndHeader;
281
282 1204 template simulationFile_syn(SimCode simCode)
283 "Synchonous features"
284 ::= match simCode
285 case simCode as SIMCODE(__) then
286 <<
287 /* Synchronous systems */
288 <%simulationFileHeader(simCode.fileNamePrefix)%>
289 #if defined(__cplusplus)
290 extern "C" {
291 #endif
292
293 <%functionInitSynchronous(clockedPartitions, modelNamePrefix(simCode))%>
294
295 <%functionUpdateSynchronous(clockedPartitions, modelNamePrefix(simCode))%>
296
297 <%functionSystemsSynchronous(clockedPartitions, modelNamePrefix(simCode))%>
298
299 <%functionSavePreSynchronous(getSubPartitions(clockedPartitions), modelNamePrefix(simCode))%>
300
301 #if defined(__cplusplus)
302 }
303 #endif
304 <%\n%>
305 >>
306 end match
307 end simulationFile_syn;
308
309 1204 template functionSavePreSynchronous(list<SimCode.SubPartition> subPartitions, String modelNamePrefix)
310 ::=
311 let preVars = subPartitions |> subPartition =>
312 functionSavePreSynchronous1(subPartition); separator="\n"
313 <<
314 /* %v% = pre(%v%)*/
315 void <%symbolName(modelNamePrefix,"function_savePreSynchronous")%>(DATA *data, threadData_t *threadData)
316 {
317 <%preVars%>
318 }
319 >>
320 end functionSavePreSynchronous;
321
322 58 template functionSavePreSynchronous1(SimCode.SubPartition subPartition)
323 ::=
324 match subPartition
325 case SUBPARTITION(__) then functionSavePreSynchronous2(vars)
326 end functionSavePreSynchronous1;
327
328 58 template functionSavePreSynchronous2(list<tuple<SimCodeVar.SimVar, Boolean>> vars)
329 ::=
330 vars |> var => functionSavePreSynchronous3(var); separator = "\n"
331 end functionSavePreSynchronous2;
332
333 382 template functionSavePreSynchronous3(tuple<SimCodeVar.SimVar, Boolean> var)
334 ::=
335 let &sub = buffer ""
336 match var
337 case (simVar, previous) then
338 match simVar
339 case SIMVAR(arrayCref=SOME(c), aliasvar=NOALIAS()) then
340 '<%cref(c, &sub)%> = <%crefPre(c)%>;'
341 case SIMVAR(aliasvar=NOALIAS()) then
342 '<%cref(name, &sub)%> = <%crefPre(name)%>;'
343 end functionSavePreSynchronous3;
344
345 34 template isEventClock(DAE.ClockKind clock)
346 ::=
347 match clock
348 case EVENT_CLOCK(__) then boolStrC(true)
349 else boolStrC(false)
350 end isEventClock;
351
352 1204 template functionInitSynchronous(list<ClockedPartition> clockedPartitions, String modelNamePrefix)
353 "Synchonous features"
354 ::=
355 let body = clockedPartitions |> partition hasindex baseClockIdx =>
356
357 let &varDecls = buffer ""
358 let &varFrees = buffer ""
359 let &auxFunction = buffer ""
360 match partition
361 case CLOCKED_PARTITION(__) then
362 let baseClockStr = baseClockInit(baseClock, baseClockIdx, subPartitions, varDecls, varFrees, auxFunction)
363 <<
364 <%varDecls%>
365 <%auxFunction%>
366 <%baseClockStr%>
367 >>
368 <<
369 /* Initializes the clocks of model. */
370 void <%symbolName(modelNamePrefix,"function_initSynchronous")%>(DATA *data, threadData_t *threadData)
371 {
372 assertStreamPrint(threadData, data->modelData->nBaseClocks==<%listLength(clockedPartitions)%>, "Number of base clocks doesn't match number of clocks that are initialized! Code generation error!");
373 data->simulationInfo->baseClocks = calloc(<%listLength(clockedPartitions)%>, sizeof(BASECLOCK_DATA));
374
375 <%body%>
376 }
377 >>
378 end functionInitSynchronous;
379
380 45 template baseClockInit(ClockKind baseClock, Integer baseClockIdx, list<SimCode.SubPartition> subPartitions, Text &varDecls, Text &varFrees, Text &auxFunction)
381 ::=
382 let &preExp = buffer ""
383 let intervalCounter = match baseClock
384 case RATIONAL_CLOCK() then
385 if Expression.isConst(intervalCounter) then
386 daeExp(intervalCounter, contextOther, &preExp, &varDecls, &varFrees, &auxFunction)
387 else
388 '-1 /* Interval set in _updateSynchronous */'
389 case INFERRED_CLOCK() then
390 '1'
391 else
392 '-1'
393 let resolution = match baseClock
394 case RATIONAL_CLOCK() then
395 daeExp(resolution, contextOther, &preExp, &varDecls, &varFrees, &auxFunction)
396 else
397 '1'
398 let startInterval = match baseClock
399 case EVENT_CLOCK() then
400 daeExp(startInterval, contextOther, &preExp, &varDecls, &varFrees, &auxFunction)
401 else
402 '0'
403 let interval = match baseClock
404 case REAL_CLOCK() then
405 if Expression.isConst(interval) then
406 daeExp(interval, contextOther, &preExp, &varDecls, &varFrees, &auxFunction)
407 else
408 '-1 /* Interval set in _updateSynchronous */'
409 case INFERRED_CLOCK() then
410 '1'
411 else
412 '-1'
413 let computeInterval = match baseClock
414 case RATIONAL_CLOCK() then
415 if Expression.isConst(intervalCounter) then
416 <<
417 data->simulationInfo->baseClocks[<%baseClockIdx%>].interval = DIVISION((modelica_real)data->simulationInfo->baseClocks[<%baseClockIdx%>].intervalCounter, (modelica_real)data->simulationInfo->baseClocks[<%baseClockIdx%>].resolution, "base-clock[<%baseClockIdx%>].interval = intervalCounter/resolution");
418 >>
419 else
420 ''
421 let subClocksInfo = subPartitions |> subPartition hasindex subClockIdx =>
422 subPartitionStr(subPartition, baseClockIdx, subClockIdx); separator="\n"
423 let warning = match baseClock
424 case INFERRED_CLOCK() then
425 <<
426 warningStreamPrint(OMC_LOG_STDOUT, 0, "Inferred clock, using default clock \'Clock(intervalCounter=1, resolution=1)\'");
427 >>
428 else ''
429 <<
430 /* Base-Clock <%baseClockIdx%> */
431 <%warning%>
432 data->simulationInfo->baseClocks[<%baseClockIdx%>] = (BASECLOCK_DATA){
433 .resolution = <%resolution%>,
434 .intervalCounter = <%intervalCounter%>,
435 .interval = <%interval%>,
436 .nSubClocks = <%listLength(subPartitions)%>,
437 .isEventClock = <%isEventClock(baseClock)%>,
438 .stats = (CLOCK_STATS){<%startInterval%>, 0, -1}};
439 <%computeInterval%>
440 data->simulationInfo->baseClocks[<%baseClockIdx%>].subClocks = calloc(<%listLength(subPartitions)%>, sizeof(SUBCLOCK_DATA));
441 <%subClocksInfo%>
442
443 >>
444 end baseClockInit;
445
446 58 template subPartitionStr(SimCode.SubPartition subPartition, Integer baseClockIdx, Integer subClockIdx)
447 ::=
448 match subPartition
449 case SUBPARTITION(subClock = SUBCLOCK(__), holdEvents=holdEvents) then
450 let methodStr = match subClock.solver
451 case NONE() then ""
452 else "External"
453 <<
454 data->simulationInfo->baseClocks[<%baseClockIdx%>].subClocks[<%subClockIdx%>] = (SUBCLOCK_DATA) {
455 .shift = <%makeCRational(subClock.shift)%>,
456 .factor = <%makeCRational(subClock.factor)%>,
457 .solverMethod = "<%methodStr%>",
458 .holdEvents = <%boolStrC(holdEvents)%>,
459 .stats = (CLOCK_STATS) {0, 0, -1}};
460 >>
461 end subPartitionStr;
462
463 116 template makeCRational(Rational rational)
464 ::=
465 match rational
466 case RATIONAL(__) then
467 <<
468 makeRATIONAL(<%nom%>, <%denom%>)
469 >>
470 end makeCRational;
471
472 1204 template functionUpdateSynchronous(list<ClockedPartition> clockedPartitions, String modelNamePrefix)
473 ::=
474 let &varDecls = buffer ""
475 let &varFrees = buffer ""
476 let &auxFunction = buffer ""
477 let body = clockedPartitions |> partition hasindex i =>
478 match partition
479 case CLOCKED_PARTITION(__) then
480 let caseBody = updatePartition(i, baseClock, &varDecls, &varFrees, &auxFunction)
481 <<
482 case <%i%>:
483 <%caseBody%>
484 break;
485 >>; separator = "\n"
486 <<
487 <%auxFunction%>
488 /* Update base-clock. */
489 void <%symbolName(modelNamePrefix,"function_updateSynchronous")%>(DATA *data, threadData_t *threadData, long base_idx)
490 {
491 <%varDecls%>
492 modelica_boolean ret;
493 switch (base_idx) {
494 <%body%>
495 default:
496 throwStreamPrint(NULL, "Internal Error: unknown base partition %ld", base_idx);
497 break;
498 }
499 }
500 >>
501 end functionUpdateSynchronous;
502
503 45 template updatePartition(Integer i, DAE.ClockKind baseClock, Text &varDecls, Text &varFrees, Text &auxFunction)
504 "Update intervalCounter or interval of base-clock"
505 ::=
506 let &preExp = buffer ""
507
508 match baseClock
509 case RATIONAL_CLOCK() then
510 if Expression.isConst(intervalCounter) then
511 <<
512 /* Nothing to do */
513 >>
514 else
515 let intervalCounterStr = daeExp(intervalCounter, contextOther, &preExp, &varDecls, &varFrees, &auxFunction)
516 <<
517 <%preExp%>
518 data->simulationInfo->baseClocks[base_idx].intervalCounter = <%intervalCounterStr%>;
519 data->simulationInfo->baseClocks[base_idx].interval = DIVISION((modelica_real)data->simulationInfo->baseClocks[base_idx].intervalCounter, (modelica_real)data->simulationInfo->baseClocks[base_idx].resolution, "intervalCounter/resolution");
520 >>
521 case REAL_CLOCK() then
522 if Expression.isConst(interval) then
523 <<
524 /* Nothing to do */
525 >>
526 else
527 let interval_ = daeExp(interval, contextOther, &preExp, &varDecls, &varFrees, &auxFunction)
528 <<
529 <%preExp%>
530 data->simulationInfo->baseClocks[base_idx].interval = <%interval_%>;
531 >>
532 case INFERRED_CLOCK()
533 case SOLVER_CLOCK()
534 case EVENT_CLOCK() then
535 <<
536 /* Nothing to do */
537 >>
538 else 'ERROR in updatePartition'
539 end updatePartition;
540
541
542 44 template functionSystemsSynchronousSubClocks(list<SimCode.SubPartition> subPartitions, Integer base_idx, String modelNamePrefix)
543 ::=
544 let subCases = subPartitions |> subPartition hasindex sub_idx =>
545 match subPartition
546 case SUBPARTITION(__) then
547 let name = 'functionEquationsSynchronous_system_<%base_idx%>_<%sub_idx%>'
548 <<
549 case <%sub_idx%>:
550 ret = <%symbolName(modelNamePrefix, name)%>(data, threadData);
551 break;
552 >>
553 else ""
554 ; separator = "\n"
555
556 <<
557 case <%base_idx%>:
558 switch (sub_idx) {
559 <%subCases%>
560 default:
561 throwStreamPrint(NULL, "Internal Error: unknown sub-clock partition %ld", sub_idx);
562 ret = 1;
563 break;
564 }
565 break;
566 >>
567 end functionSystemsSynchronousSubClocks;
568
569
570 1204 template functionSystemsSynchronous(list<ClockedPartition> clockedPartitions, String modelNamePrefix)
571 ::=
572 let baseCases = clockedPartitions |> partition hasindex base_idx =>
573 match partition
574 case CLOCKED_PARTITION(subPartitions = (sub as _::_)) then
575 functionSystemsSynchronousSubClocks(subPartitions, base_idx, modelNamePrefix)
576 else // adrpo: generate a fake call if the subPartitions = {}
577 let name = 'functionEquationsSynchronous_system_<%base_idx%>_0'
578 <<
579 case 0: // this is a fake function call for CLOCKED_PARTITION(subPartitions = {})
580 ret = <%symbolName(modelNamePrefix, name)%>(data, threadData);
581 break;
582 >>
583 ; separator = "\n"
584
585 let systs = clockedPartitions |> partition hasindex base_idx =>
586 match partition
587 case CLOCKED_PARTITION(subPartitions = (sub as _::_)) then
588 let funcCall = subPartitions |> subPart hasindex sub_idx =>
589 match subPart
590 case SUBPARTITION(__) then
591 functionEquationsSynchronous(base_idx, sub_idx, vars, listAppend(equations, removedEquations), modelNamePrefix)
592 else ""
593 ; separator = "\n"
594 <<
595 <%funcCall%>
596 >>
597 else // adrpo: generate a fake function for subPartitions = {}
598 <<
599 int <%symbolName(modelNamePrefix, 'functionEquationsSynchronous_system_<%base_idx%>_0')%>(DATA *data, threadData_t *threadData)
600 {
601 int i;
602 // do nothing, this is a fake function for CLOCKED_PARTITION(subPartitions = {})
603 return 0;
604 }
605 >>
606 ; separator = "\n"
607
608 <<
609
610 <%systs%>
611
612 /* Clocked systems equations */
613 int <%symbolName(modelNamePrefix,"function_equationsSynchronous")%>(DATA *data, threadData_t *threadData, long base_idx, long sub_idx)
614 {
615 int ret;
616
617 switch (base_idx) {
618 <%baseCases%>
619 default:
620 throwStreamPrint(NULL, "Internal Error: unknown base-clock partition %ld", base_idx);
621 ret = 1;
622 break;
623 }
624
625 return ret;
626 }
627 >>
628
629 end functionSystemsSynchronous;
630
631 58 template functionEquationsSynchronous(Integer base_idx, Integer sub_idx, list<tuple<SimCodeVar.SimVar, Boolean>> vars, list<SimEqSystem> equations, String modelNamePrefix)
632 ::=
633 let &chunks = buffer ""
634 let calls = equations_call(equations, modelNamePrefix, contextSimulationDiscrete, '', true, &chunks)
635 <<
636 <%equations |> eq => equation_impl(base_idx, sub_idx, eq, contextOther, modelNamePrefix, false) ; separator="\n"%>
637
638 <%chunks%>
639 int <%symbolName(modelNamePrefix, 'functionEquationsSynchronous_system_<%base_idx%>_<%sub_idx%>')%>(DATA *data, threadData_t *threadData)
640 {
641 int i;
642
643 <%addRootsTempArray()%>
644
645 <%calls%>
646
647 return 0;
648 }
649 >>
650 end functionEquationsSynchronous;
651
652 1204 template simulationFile_exo(SimCode simCode)
653 "External Objects"
654 ::=
655 match simCode
656 case simCode as SIMCODE(__) then
657 <<
658 /* External objects file */
659 <%simulationFileHeader(simCode.fileNamePrefix)%>
660 #if defined(__cplusplus)
661 extern "C" {
662 #endif
663
664 <%functionCallExternalObjectDestructors(extObjInfo, modelNamePrefix(simCode))%>
665 #if defined(__cplusplus)
666 }
667 #endif<%\n%>
668 >>
669 /* adrpo: leave a newline at the end of file to get rid of the warning */
670 end match
671 end simulationFile_exo;
672
673 1204 template simulationFile_nls(SimCode simCode)
674 "Non Linear Systems"
675 ::=
676 match simCode
677 case simCode as SIMCODE(modelInfo=MODELINFO(varInfo=varInfo as VARINFO(__),nonLinearSystems=nonLinearSystems)) then
678 let modelNamePrefixStr = modelNamePrefix(simCode)
679 <<
680 /* Non Linear Systems */
681 <%simulationFileHeader(simCode.fileNamePrefix)%>
682 #include "<%simCode.fileNamePrefix%>_12jac.h"
683 #include "simulation/jacobian_util.h"
684 #include "simulation/arrayIndex.h"
685
686 #if defined(__cplusplus)
687 extern "C" {
688 #endif
689 <%functionNonLinearResidualsMultiFile(nonLinearSystems, Flags.getConfigInt(Flags.EQUATIONS_PER_FILE), simCode.fullPathPrefix, simCode.fileNamePrefix, "02nls", modelNamePrefixStr)%>
690
691 <%if intGt(varInfo.numNonLinearSystems, 0) then functionInitialNonLinearSystems(nonLinearSystems, modelNamePrefixStr)%>
692
693 #if defined(__cplusplus)
694 }
695 #endif<%\n%>
696 >>
697 /* adrpo: leave a newline at the end of file to get rid of the warning */
698 end match
699 end simulationFile_nls;
700
701 1204 template simulationFile_lsy(SimCode simCode)
702 "Linear Systems"
703 ::=
704 match simCode
705 case simCode as SIMCODE(modelInfo=MODELINFO(varInfo=varInfo as VARINFO(__),linearSystems=linearSystems)) then
706 <<
707 /* Linear Systems */
708 <%simulationFileHeader(simCode.fileNamePrefix)%>
709 #include "<%simCode.fileNamePrefix%>_12jac.h"
710 #include "simulation/arrayIndex.h"
711
712 #if defined(__cplusplus)
713 extern "C" {
714 #endif
715
716 /* linear systems */
717 <%functionSetupLinearSystems(linearSystems, modelNamePrefix(simCode))%>
718
719 <% if intGt(varInfo.numLinearSystems,0) then functionInitialLinearSystems(linearSystems, modelNamePrefix(simCode))%>
720
721 #if defined(__cplusplus)
722 }
723 #endif<%\n%>
724 >>
725 /* adrpo: leave a newline at the end of file to get rid of the warning */
726 end match
727 end simulationFile_lsy;
728
729 1204 template simulationFile_set(SimCode simCode)
730 "Initial State Set"
731 ::=
732 match simCode
733 case simCode as SIMCODE(__) then
734 <<
735 /* Initial State Set */
736 <%simulationFileHeader(simCode.fileNamePrefix)%>
737 #include "<%simCode.fileNamePrefix%>_11mix.h"
738 #include "<%simCode.fileNamePrefix%>_12jac.h"
739 #if defined(__cplusplus)
740 extern "C" {
741 #endif
742 <%functionInitialStateSets(simCode, stateSets, modelNamePrefix(simCode))%>
743
744 #if defined(__cplusplus)
745 }
746 #endif<%\n%>
747 >>
748 /* adrpo: leave a newline at the end of file to get rid of the warning */
749 end match
750 end simulationFile_set;
751
752 1204 template simulationFile_evt(SimCode simCode)
753 "Events: Sample, Zero Crossings, Relations, Discrete Changes"
754 ::=
755 match simCode
756 case simCode as SIMCODE(__) then
757 <<
758 /* Events: Sample, Zero Crossings, Relations, Discrete Changes */
759 <%simulationFileHeader(simCode.fileNamePrefix)%>
760 #if defined(__cplusplus)
761 extern "C" {
762 #endif
763
764 <%functionInitSample(timeEvents, modelNamePrefix(simCode))%>
765
766 <%functionZeroCrossing(zeroCrossings, equationsForZeroCrossings, modelNamePrefix(simCode))%>
767
768 <%functionRelations(relations, modelNamePrefix(simCode))%>
769
770 <%functionNextTimeEvent(relations, modelNamePrefix(simCode))%>
771
772 #if defined(__cplusplus)
773 }
774 #endif<%\n%>
775 >>
776 /* adrpo: leave a newline at the end of file to get rid of the warning */
777 end match
778 end simulationFile_evt;
779
780 1204 template simulationFile_inz(SimCode simCode)
781 "Initialization"
782 ::=
783 match simCode
784 case simCode as SIMCODE(modelInfo=MODELINFO(varInfo=varInfo as VARINFO(__))) then
785 <<
786 /* Initialization */
787 <%simulationFileHeader(simCode.fileNamePrefix)%>
788 #include "<%simCode.fileNamePrefix%>_11mix.h"
789 #include "<%simCode.fileNamePrefix%>_12jac.h"
790 #if defined(__cplusplus)
791 extern "C" {
792 #endif
793
794 <%functionInitialEquations(initialEquations, listLength(initialEquations), simCode.fileNamePrefix, simCode.fullPathPrefix, modelNamePrefix(simCode),
795 /* initial: only to be treated as first system if there is no lambda_0 system */ intEq(listLength(initialEquations_lambda0), 0))%>
796 <%functionInitialEquations_lambda0(initialEquations_lambda0, modelNamePrefix(simCode))%>
797 <%functionRemovedInitialEquations(removedInitialEquations, modelNamePrefix(simCode))%>
798
799 <%if intGt(varInfo.numMixedSystems,0) then functionInitialMixedSystems(initialEquations, initialEquations_lambda0, parameterEquations, allEquations, jacobianMatrices, modelNamePrefix(simCode))%>
800
801 #if defined(__cplusplus)
802 }
803 #endif<%\n%>
804 >>
805 /* adrpo: leave a newline at the end of file to get rid of the warning */
806 end match
807 end simulationFile_inz;
808
809 1204 template simulationFile_dly(SimCode simCode)
810 "Delay"
811 ::=
812 match simCode
813 case simCode as SIMCODE(__) then
814 <<
815 /* Delay */
816 <%simulationFileHeader(simCode.fileNamePrefix)%>
817 #if defined(__cplusplus)
818 extern "C" {
819 #endif
820
821 <%functionStoreDelayed(delayedExps, modelNamePrefix(simCode))%>
822
823 #if defined(__cplusplus)
824 }
825 #endif<%\n%>
826 >>
827 /* adrpo: leave a newline at the end of file to get rid of the warning */
828 end match
829 end simulationFile_dly;
830
831 1204 template simulationFile_spd(SimCode simCode)
832 "SpatialDistribution"
833 ::=
834 match simCode
835 case simCode as SIMCODE(__) then
836 <<
837 /* spatialDistribution */
838 <%simulationFileHeader(simCode.fileNamePrefix)%>
839 #if defined(__cplusplus)
840 extern "C" {
841 #endif
842
843 <%functionStoreSpatialDistribution(spatialInfo, modelNamePrefix(simCode))%>
844
845 <%functionInitSpatialDistribution(spatialInfo, modelNamePrefix(simCode))%>
846
847 #if defined(__cplusplus)
848 }
849 #endif<%\n%>
850 >>
851 /* adrpo: leave a newline at the end of file to get rid of the warning */
852 end match
853 end simulationFile_spd;
854
855 1204 template simulationFile_bnd(SimCode simCode)
856 "update bound parameters and variable attributes (start, nominal, min, max)"
857 ::=
858 match simCode
859 case simCode as SIMCODE(__) then
860 <<
861 /* update bound parameters and variable attributes (start, nominal, min, max) */
862 <%simulationFileHeader(simCode.fileNamePrefix)%>
863 #if defined(__cplusplus)
864 extern "C" {
865 #endif
866
867 <%functionUpdateBoundVariableAttributes(simCode, startValueEquations, nominalValueEquations, minValueEquations, maxValueEquations, modelNamePrefix(simCode))%>
868
869 <%functionUpdateBoundParameters(selectScalarLiteralAssignments(parameterEquations), filterScalarLiteralAssignments(parameterEquations), simCode.fileNamePrefix, simCode.fullPathPrefix, modelNamePrefix(simCode), simCode)%>
870
871 #if defined(__cplusplus)
872 }
873 #endif<%\n%>
874 >>
875 /* adrpo: leave a newline at the end of file to get rid of the warning */
876 end match
877 end simulationFile_bnd;
878
879 1204 template simulationFile_alg(SimCode simCode)
880 "Algebraic"
881 ::=
882 match simCode
883 case simCode as SIMCODE(__) then
884 <<
885 /* Algebraic */
886 <%simulationFileHeader(simCode.fileNamePrefix)%>
887
888 #ifdef __cplusplus
889 extern "C" {
890 #endif
891
892 <%functionAlgebraic(algebraicEquations, modelNamePrefix(simCode))%>
893
894 #ifdef __cplusplus
895 }
896 #endif<%\n%>
897 >>
898 /* adrpo: leave a newline at the end of file to get rid of the warning */
899 end match
900 end simulationFile_alg;
901
902 1204 template simulationFile_asr(SimCode simCode)
903 "Asserts"
904 ::=
905 match simCode
906 case simCode as SIMCODE(__) then
907 <<
908 /* Asserts */
909 <%simulationFileHeader(simCode.fileNamePrefix)%>
910 #if defined(__cplusplus)
911 extern "C" {
912 #endif
913
914 <%functionAssertsforCheck(algorithmAndEquationAsserts, modelNamePrefix(simCode))%>
915
916 #if defined(__cplusplus)
917 }
918 #endif<%\n%>
919 >>
920 /* adrpo: leave a newline at the end of file to get rid of the warning */
921 end match
922 end simulationFile_asr;
923
924 1204 template simulationFile_mix(SimCode simCode, Text &header)
925 "Mixed Systems"
926 ::=
927 match simCode
928 case simCode as SIMCODE(__) then
929 let modelNamePrefixStr = modelNamePrefix(simCode)
930 <<
931 /* Mixed Systems */
932 <%simulationFileHeader(simCode.fileNamePrefix)%>
933 #include "<%simCode.fileNamePrefix%>_11mix.h"
934 <%functionSetupMixedSystems(initialEquations, initialEquations_lambda0, parameterEquations, allEquations, jacobianMatrices, &header, modelNamePrefixStr)%><%\n%>
935 >>
936 /* adrpo: leave a newline at the end of file to get rid of the warning */
937 end match
938 end simulationFile_mix;
939
940 1204 template simulationFile_jac(SimCode simCode)
941 "Jacobians"
942 ::=
943 match simCode
944 case simCode as SIMCODE(__) then
945 <<
946 /* Jacobians <%listLength(jacobianMatrices)%> */
947 <%simulationFileHeader(simCode.fileNamePrefix)%>
948 #include "<%fileNamePrefix%>_12jac.h"
949 #include "simulation/jacobian_util.h"
950 #include "util/omc_file.h"
951 <%functionAnalyticJacobians(jacobianMatrices, modelNamePrefix(simCode), simCode.fileNamePrefix)%><%\n%>
952 >>
953 /* adrpo: leave a newline at the end of file to get rid of the warning */
954 end match
955 end simulationFile_jac;
956
957 1204 template simulationFile_jac_header(SimCode simCode)
958 "Jacobians"
959 ::=
960 match simCode
961 case simCode as SIMCODE(__) then
962 <<
963 /* Jacobians */
964 /* Immortal, like any literal array: omc_array_release also drops dim_size. */
965 static struct { mmc_uint_t rc; _index_t d[1]; } one_dim_lit = { OMC_RC_IMMORTAL, { 1 } };
966 #define one_dim (one_dim_lit.d)
967 static modelica_real nominal_data[1] = { 1.0 };
968 static modelica_real start_data[1] = { 0.0 };
969 static modelica_real min_data[1] = { -DBL_MAX };
970 static modelica_real max_data[1] = { DBL_MAX };
971 static const REAL_ATTRIBUTE dummyREAL_ATTRIBUTE = {
972 .unit = NULL,
973 .displayUnit = NULL,
974 .relativeQuantity = FALSE,
975 .min = {
976 .ndims = 1,
977 .dim_size = one_dim,
978 .data = (void*) min_data,
979 .flexible = FALSE
980 },
981 .max = {
982 .ndims = 1,
983 .dim_size = one_dim,
984 .data = (void*) max_data,
985 .flexible = FALSE
986 },
987 .fixed = FALSE,
988 .useNominal = FALSE,
989 .nominal = {
990 .ndims = 1,
991 .dim_size = one_dim,
992 .data = (void*) nominal_data,
993 .flexible = FALSE
994 },
995 .start = {
996 .ndims = 1,
997 .dim_size = one_dim,
998 .data = (void*) start_data,
999 .flexible = FALSE
1000 }
1001 };
1002
1003 <%symJacDefinition(jacobianMatrices, modelNamePrefix(simCode))%><%\n%>
1004 >>
1005 /* adrpo: leave a newline at the end of file to get rid of the warning */
1006 end match
1007 end simulationFile_jac_header;
1008
1009 1204 template simulationFile_opt(SimCode simCode)
1010 "Optimization"
1011 ::=
1012 match simCode
1013 case simCode as SIMCODE(__) then
1014 let modelNamePrefixStr = modelNamePrefix(simCode)
1015 <<
1016 /* Optimization */
1017 <%simulationFileHeader(simCode.fileNamePrefix)%>
1018 #include "<%fileNamePrefix%>_12jac.h"
1019 #include "simulation/arrayIndex.h"
1020
1021 #if defined(__cplusplus)
1022 extern "C" {
1023 #endif
1024 <%optimizationComponents(classAttributes, simCode, modelNamePrefixStr)%>
1025 #if defined(__cplusplus)
1026 }
1027 #endif<%\n%>
1028 >>
1029 /* adrpo: leave a newline at the end of file to get rid of the warning */
1030 end match
1031 end simulationFile_opt;
1032
1033 1204 template simulationFile_opt_header(SimCode simCode)
1034 "Jacobians"
1035 ::=
1036 match simCode
1037 case simCode as SIMCODE(__) then
1038 let modelNamePrefixStr = modelNamePrefix(simCode)
1039 <<
1040 #if defined(__cplusplus)
1041 extern "C" {
1042 #endif
1043 int <%symbolName(modelNamePrefixStr,"mayer")%>(DATA* data, modelica_real** res, short*);
1044 int <%symbolName(modelNamePrefixStr,"lagrange")%>(DATA* data, modelica_real** res, short *, short *);
1045 int <%symbolName(modelNamePrefixStr,"getInputVarIndicesInOptimization")%>(DATA* data, int* input_var_indices, int* loop_input_indices);
1046 int <%symbolName(modelNamePrefixStr,"pickUpBoundsForInputsInOptimization")%>(DATA* data, modelica_real* min, modelica_real* max, modelica_real*nominal, modelica_boolean *useNominal, char ** name, modelica_real * start, modelica_real * startTimeOpt);
1047 int <%symbolName(modelNamePrefixStr,"setInputData")%>(DATA *data);
1048 int <%symbolName(modelNamePrefixStr,"getTimeGrid")%>(DATA *data, modelica_integer * nsi, modelica_integer**idx);
1049 #if defined(__cplusplus)
1050 }
1051 #endif<%\n%>
1052 >>
1053 /* adrpo: leave a newline at the end of file to get rid of the warning */
1054 end match
1055 end simulationFile_opt_header;
1056
1057 1204 template simulationFile_lnz(SimCode simCode)
1058 "Linearization"
1059 ::=
1060 match simCode
1061 case simCode as SIMCODE(modelInfo = MODELINFO(varInfo = VARINFO(numStateVars = ns, numInVars = ni, numOutVars = no, numAlgVars = na))) then
1062 <<
1063 /* Linearization */
1064 <%simulationFileHeader(simCode.fileNamePrefix)%>
1065 #if defined(__cplusplus)
1066 extern "C" {
1067 #endif
1068
1069 <%
1070 if stringEq(Flags.getConfigString(LINEARIZATION_DUMP_LANGUAGE),"none") then
1071 <<
1072 const char *<%symbolName(modelNamePrefix(simCode),"linear_model_frame")%>()
1073 {
1074 errorStreamPrint(OMC_LOG_STDOUT, 0, "Linearization disabled. Use compiler flag `--linearizationDumpLanguage` to change target language.");
1075 return "";
1076 }
1077 const char *<%symbolName(modelNamePrefix(simCode),"linear_model_datarecovery_frame")%>()
1078 {
1079 errorStreamPrint(OMC_LOG_STDOUT, 0, "Linearization disabled. Use compiler flag `--linearizationDumpLanguage` to change target language.");
1080 return "";
1081 }
1082 >>
1083 else if intLt(Flags.getConfigInt(MAX_SIZE_LINEARIZATION), intAdd(intAdd(intAdd(ns,ni),no),na)) then
1084 <<
1085 const char *<%symbolName(modelNamePrefix(simCode),"linear_model_frame")%>()
1086 {
1087 errorStreamPrint(OMC_LOG_STDOUT, 0, "System too big. Use compiler flag `--maxSizeLinearization` to change threshold.");
1088 return "";
1089 }
1090 const char *<%symbolName(modelNamePrefix(simCode),"linear_model_datarecovery_frame")%>()
1091 {
1092 errorStreamPrint(OMC_LOG_STDOUT, 0, "System too big. Use compiler flag `--maxSizeLinearization` to change threshold.");
1093 return "";
1094 }
1095 >>
1096 else if Flags.getConfigBool(Flags.DAE_MODE) then
1097 <<
1098 const char *<%symbolName(modelNamePrefix(simCode),"linear_model_frame")%>()
1099 {
1100 errorStreamPrint(OMC_LOG_STDOUT, 0, "Linearization not available with `--daeMode`.");
1101 return "";
1102 }
1103 const char *<%symbolName(modelNamePrefix(simCode),"linear_model_datarecovery_frame")%>()
1104 {
1105 errorStreamPrint(OMC_LOG_STDOUT, 0, "Linearization not available with `--daeMode`.");
1106 return "";
1107 }
1108 >>
1109 else if stringEq(Flags.getConfigString(LINEARIZATION_DUMP_LANGUAGE),"modelica")
1110 then functionlinearmodel(modelInfo, modelNamePrefix(simCode))
1111 else if stringEq(Flags.getConfigString(LINEARIZATION_DUMP_LANGUAGE),"matlab")
1112 then functionlinearmodelMatlab(modelInfo, modelNamePrefix(simCode))
1113 else if stringEq(Flags.getConfigString(LINEARIZATION_DUMP_LANGUAGE),"julia")
1114 then functionlinearmodelJulia(modelInfo, modelNamePrefix(simCode))
1115 else if stringEq(Flags.getConfigString(LINEARIZATION_DUMP_LANGUAGE),"python")
1116 then functionlinearmodelPython(modelInfo, modelNamePrefix(simCode))
1117 else
1118 error(sourceInfo(), 'Unknown linearization language <%Flags.getConfigString(LINEARIZATION_DUMP_LANGUAGE)%>.')
1119 %>
1120
1121 #if defined(__cplusplus)
1122 }
1123 #endif<%\n%>
1124 >>
1125 /* adrpo: leave a newline at the end of file to get rid of the warning */
1126 end match
1127 end simulationFile_lnz;
1128
1129 3890 template defineSimVarArray(SimVar simVar, String arrayName)
1130 "Generates a define statement for a parameter."
1131 ::=
1132 let &sub = buffer ""
1133 match simVar
1134 case SIMVAR(arrayCref=SOME(c),aliasvar=NOALIAS()) then
1135 <<
1136 /* <%crefStrNoUnderscore(c)%> */
1137 // #define <%cref(c, &sub)%> data->simulationInfo->daeModeData-><%arrayName%>[<%index%>]
1138
1139 /* <%crefStrNoUnderscore(name)%> */
1140 // #define <%cref(name, &sub)%> data->simulationInfo->daeModeData-><%arrayName%>[<%index%>]
1141
1142 >>
1143 case SIMVAR(aliasvar=NOALIAS()) then
1144 <<
1145 /* <%crefStrNoUnderscore(name)%> */
1146 // #define <%cref(name, &sub)%> data->simulationInfo->daeModeData-><%arrayName%>[<%index%>]
1147
1148 >>
1149 end match
1150 end defineSimVarArray;
1151
1152 // TODO: This is probably not relevant anymore can be removed. We access residual and auxialry
1153 // variables of daemode using cref2simvar now. No need to define them.
1154 1114 template simulationFile_dae_header(SimCode simCode)
1155 "DAEmode header generation"
1156 ::=
1157 match simCode
1158 case simCode as SIMCODE(daeModeData=SOME(DAEMODEDATA(residualVars=residualVars,auxiliaryVars=auxiliaryVars))) then
1159 <<
1160 /* residual variable define for daeMode */
1161 <%residualVars |> var =>
1162 defineSimVarArray(var, "residualVars")
1163 ;separator="\n"%>
1164 /* auxiliary variable define for daeMode */
1165 <%auxiliaryVars |> var =>
1166 defineSimVarArray(var, "auxiliaryVars")
1167 ;separator="\n"%><%\n%>
1168 >>
1169 /* adrpo: leave a newline at the end of file to get rid of the warning */
1170 case simCode as SIMCODE(__) then
1171 <<
1172 #ifndef <%fileNamePrefix%>_16DAE_H
1173 #define <%fileNamePrefix%>_16DAE_H
1174 #endif<%\n%>
1175 >>
1176 end match
1177 end simulationFile_dae_header;
1178
1179 1196 template simulationFile_dae(SimCode simCode)
1180 "DAEmode equations generation"
1181 ::=
1182 match simCode
1183 case SIMCODE(modelInfo=MODELINFO(vars=SIMVARS(__)),
1184 daeModeData=SOME(DAEMODEDATA(daeEquations=daeEquations, sparsityPattern=sparsityPattern,
1185 algebraicVars=algebraicVars, residualVars=residualVars,
1186 auxiliaryVars=auxiliaryVars))) then
1187 let modelNamePrefixStr = modelNamePrefix(simCode)
1188 let initDAEmode =
1189 match sparsityPattern
1190 case SOME(JAC_MATRIX(sparsityMatrix=sparsityMatrix as SPARSITY(), matrixName=matrixName, seedVars=seedVars, crefsHT=crefsHT)) then
1191 '<%initializeDAEmodeDataResizable(listLength(residualVars), algebraicVars, listLength(auxiliaryVars), sparsityMatrix, numScalarElemsExp(seedVars), listLength(residualVars), createJacContext(matrixName, crefsHT), modelNamePrefixStr)%>'
1192 case SOME(JAC_MATRIX(sparsity=sparse, coloredCols=colorList, maxColorCols=maxColor)) then
1193 '<%initializeDAEmodeData(listLength(residualVars), algebraicVars, listLength(auxiliaryVars), sparse, colorList, maxColor, modelNamePrefixStr)%>'
1194 case NONE() then
1195 'int <%symbolName(modelNamePrefixStr,"initializeDAEmodeData")%>(DATA* data, DAEMODE_DATA* daeModeData){ return -1; }'
1196 end match
1197 <<
1198 /* DAE residuals */
1199 <%simulationFileHeader(fileNamePrefix)%>
1200 #include "simulation/solver/dae_mode.h"
1201
1202 #ifdef __cplusplus
1203 extern "C" {
1204 #endif
1205
1206 <%evaluateDAEResiduals(daeEquations, fileNamePrefix, fullPathPrefix, modelNamePrefixStr)%>
1207
1208 <%initDAEmode%>
1209
1210 #ifdef __cplusplus
1211 }
1212 #endif<%\n%>
1213 >>
1214 /* adrpo: leave a newline at the end of file to get rid of the warning */
1215 else
1216 let modelNamePrefixStr = modelNamePrefix(simCode)
1217 <<
1218 /* DAE residuals is empty */
1219 <%simulationFileHeader(fileNamePrefix(simCode))%>
1220 #ifdef __cplusplus
1221 extern "C" {
1222 #endif
1223 int <%symbolName(modelNamePrefixStr,"initializeDAEmodeData")%>(DATA* data, DAEMODE_DATA* daeModeData){ return -1; }
1224 #ifdef __cplusplus
1225 }
1226 #endif<%\n%>
1227 >>
1228 end match
1229 end simulationFile_dae;
1230
1231 1192 template simulationFile_inl(SimCode simCode)
1232 "DAEmode equations generation"
1233 ::=
1234 match simCode
1235 case SIMCODE(modelInfo=MODELINFO(vars=SIMVARS(__)),inlineEquations={}) then
1236 let modelNamePrefixStr = modelNamePrefix(simCode)
1237 <<
1238 /* Inline equation file is empty */
1239 <%simulationFileHeader(fileNamePrefix(simCode))%>
1240 #ifdef __cplusplus
1241 extern "C" {
1242 #endif
1243 int <%symbolName(modelNamePrefixStr,"symbolicInlineSystem")%>(DATA *data, threadData_t *threadData){
1244 <% if intEq(Flags.getConfigEnum(Flags.SYM_SOLVER),0) then
1245 <<
1246 return -1;
1247 >>
1248 %>
1249 <% if intGt(Flags.getConfigEnum(Flags.SYM_SOLVER),0) then
1250 <<
1251 return 0;
1252 >>
1253 %>
1254 }
1255 #ifdef __cplusplus
1256 }
1257 #endif<%\n%>
1258 >>
1259 case SIMCODE(modelInfo=MODELINFO(vars=SIMVARS(__)),inlineEquations=inlineEquations) then
1260 let modelNamePrefixStr = modelNamePrefix(simCode)
1261
1262 let funcNames = (inlineEquations |> eq => equationNames_(eq,contextSimulationNonDiscrete,modelNamePrefixStr))
1263 <<
1264 /* Inline equation file */
1265 <%simulationFileHeader(fileNamePrefix(simCode))%>
1266
1267 #ifdef __cplusplus
1268 extern "C" {
1269 #endif
1270
1271 <%(inlineEquations |> eq hasindex i0 =>
1272 equation_impl(-1, -1, eq, contextSimulationNonDiscrete, modelNamePrefixStr, false)
1273 ;separator="\n")%>
1274
1275 /* inline equations*/
1276 int <%symbolName(modelNamePrefixStr,"symbolicInlineSystem")%>(DATA *data, threadData_t *threadData){
1277 <%funcNames%>
1278
1279 return 0;
1280 }
1281
1282 #ifdef __cplusplus
1283 }
1284 #endif<%\n%>
1285 >>
1286 end simulationFile_inl;
1287
1288 1204 template simulationFile(SimCode simCode, String guid, String isModelExchangeFMU)
1289 "Generates code for main C file for simulation target."
1290 ::=
1291 match simCode
1292 case simCode as SIMCODE(modelInfo=MODELINFO(varInfo=varInfo as VARINFO(__), vars=vars as SIMVARS(__)), hpcomData=HPCOMDATA(__)) then
1293 let modelNamePrefixStr = modelNamePrefix(simCode)
1294 let mainInit = if boolOr(boolNot(stringEq("",isModelExchangeFMU)), Flags.isSet(HPCOM)) then
1295 <<
1296 mmc_init_nogc();
1297 omc_alloc_interface.init();
1298 >>
1299 else if stringEq(Config.simCodeTarget(),"JavaScript") then
1300 <<
1301 mmc_init_nogc();
1302 omc_alloc_interface.init();
1303 >>
1304 else
1305 <<
1306 OMC_INIT(0);
1307 omc_alloc_interface.init();
1308 >>
1309 let pminit = if Flags.getConfigBool(Flags.PARMODAUTO) then
1310 <<
1311 int num_threads = 0;
1312 if(omc_flag[FLAG_PARMODNUMTHREADS]) {
1313 num_threads = atoi(omc_flagValue[FLAG_PARMODNUMTHREADS]);
1314 }
1315 pm_model = PM_Model_create("<%fileNamePrefix%>", &data, threadData, num_threads);
1316 PM_Model_load_ODE_system(pm_model, functionODE_systems);
1317
1318 >>
1319 else ''
1320 let mainBody =
1321 <<
1322 <%symbolName(modelNamePrefixStr,"setupDataStruc")%>(&data, threadData);
1323 res = _main_initRuntimeAndSimulation(argc, newargv, &data, threadData);
1324 if(res == 0) {
1325 if (omc_flag[FLAG_MOO_OPTIMIZATION]) {
1326 res = _main_OptimizationRuntime(argc, newargv, &data, threadData);
1327 } else {
1328 <%pminit%>
1329 res = _main_SimulationRuntime(argc, newargv, &data, threadData);
1330 }
1331 }
1332 >>
1333 <<
1334 /* Main Simulation File */
1335
1336 #if defined(__cplusplus)
1337 extern "C" {
1338 #endif
1339
1340 <%simulationFileHeader(simCode.fileNamePrefix)%>
1341 #include "simulation/solver/events.h"
1342 #include "simulation/arrayIndex.h"
1343
1344 <% if stringEq("",isModelExchangeFMU) then
1345 <<
1346 /* FIXME these defines are ugly and hard to read, why not use direct function pointers instead? */
1347 #define prefixedName_performSimulation <%symbolName(modelNamePrefixStr,"performSimulation")%>
1348 #define prefixedName_updateContinuousSystem <%symbolName(modelNamePrefixStr,"updateContinuousSystem")%>
1349 #include <simulation/solver/perform_simulation.c.inc>
1350
1351 #define prefixedName_performQSSSimulation <%symbolName(modelNamePrefixStr,"performQSSSimulation")%>
1352 #include <simulation/solver/perform_qss_simulation.c.inc>
1353 >>
1354 %>
1355
1356 <% if Flags.getConfigBool(Flags.PARMODAUTO) then
1357 <<
1358 void* pm_model = NULL;
1359 >>
1360 %>
1361
1362 /* dummy VARINFO and FILEINFO */
1363 const VAR_INFO dummyVAR_INFO = omc_dummyVarInfo;
1364
1365 <%functionInput(simCode, modelInfo, modelNamePrefixStr)%>
1366
1367 <%functionDataInput(simCode, modelInfo, modelNamePrefixStr)%>
1368
1369 <%functionOutput(modelInfo, modelNamePrefixStr)%>
1370
1371 <%functionSetC(modelInfo, modelNamePrefixStr)%>
1372
1373 <%functionSetB(modelInfo, modelNamePrefixStr)%>
1374
1375 <%functionDAE(allEquations, modelNamePrefixStr)%>
1376
1377 <%functionLocalKnownVars(localKnownVars, modelNamePrefixStr)%>
1378
1379 <%functionODE(odeEquations,(match simulationSettingsOpt case SOME(settings as SIMULATION_SETTINGS(__)) then settings.method else ""), hpcomData.schedules, modelNamePrefixStr)%>
1380
1381 <%functionXXX_DAG(List.flatten(odeEquations), "ODE", modelNamePrefixStr)%>
1382
1383 /* forward the main in the simulation runtime */
1384 extern int _main_SimulationRuntime(int argc, char **argv, DATA *data, threadData_t *threadData);
1385 extern int _main_OptimizationRuntime(int argc, char **argv, DATA *data, threadData_t *threadData);
1386
1387 #include "<%simCode.fileNamePrefix%>_12jac.h"
1388 #include "<%simCode.fileNamePrefix%>_13opt.h"
1389
1390 <%fmiAliasIndexTables(simCode, modelInfo, modelNamePrefixStr)%>
1391
1392 <%functionUpdateStructuralParameters(vars.intParamVars, vars.inputVars, modelNamePrefixStr)%>
1393
1394 struct OpenModelicaGeneratedFunctionCallbacks <%symbolName(modelNamePrefixStr,"callback")%> = {
1395 <% if isModelExchangeFMU then "NULL" else '(int (*)(DATA *, threadData_t *, void *)) <%symbolName(modelNamePrefixStr,"performSimulation")%>'%>, /* performSimulation */
1396 <% if isModelExchangeFMU then "NULL" else '(int (*)(DATA *, threadData_t *, void *)) <%symbolName(modelNamePrefixStr,"performQSSSimulation")%>'%>, /* performQSSSimulation */
1397 <% if isModelExchangeFMU then "NULL" else '<%symbolName(modelNamePrefixStr,"updateContinuousSystem")%>'%>, /* updateContinuousSystem */
1398 <%symbolName(modelNamePrefixStr,"callExternalObjectDestructors")%>, /* callExternalObjectDestructors */
1399 <%if intEq(varInfo.numNonLinearSystems,0) then "NULL" else symbolName(modelNamePrefixStr,"initialNonLinearSystem")%>, /* initialNonLinearSystem */
1400 <%if intEq(varInfo.numLinearSystems,0) then "NULL" else symbolName(modelNamePrefixStr,"initialLinearSystem")%>, /* initialLinearSystem */
1401 <%if intEq(varInfo.numMixedSystems,0) then "NULL" else symbolName(modelNamePrefixStr,"initialMixedSystem")%>, /* initialMixedSystem */
1402 #if !defined(OMC_NO_STATESELECTION)
1403 <%symbolName(modelNamePrefixStr,"initializeStateSets")%>,
1404 #else
1405 NULL,
1406 #endif /* initializeStateSets */
1407 <%symbolName(modelNamePrefixStr,"initializeDAEmodeData")%>,
1408 <%symbolName(modelNamePrefixStr,"ODE_DAG")%>,
1409 <%symbolName(modelNamePrefixStr,"functionODE")%>,
1410 <%symbolName(modelNamePrefixStr,"functionAlgebraics")%>,
1411 <%symbolName(modelNamePrefixStr,"functionDAE")%>,
1412 <%symbolName(modelNamePrefixStr,"functionLocalKnownVars")%>,
1413 <%symbolName(modelNamePrefixStr,"input_function")%>,
1414 <%symbolName(modelNamePrefixStr,"input_function_init")%>,
1415 <%symbolName(modelNamePrefixStr,"input_function_updateStartValues")%>,
1416 <%symbolName(modelNamePrefixStr,"data_function")%>,
1417 <%symbolName(modelNamePrefixStr,"output_function")%>,
1418 <%symbolName(modelNamePrefixStr,"setc_function")%>,
1419 <%symbolName(modelNamePrefixStr,"setb_function")%>,
1420 <%symbolName(modelNamePrefixStr,"function_storeDelayed")%>,
1421 <%symbolName(modelNamePrefixStr,"function_storeSpatialDistribution")%>,
1422 <%symbolName(modelNamePrefixStr,"function_initSpatialDistribution")%>,
1423 <%symbolName(modelNamePrefixStr,"updateBoundVariableAttributes")%>,
1424 <%symbolName(modelNamePrefixStr,"functionInitialEquations")%>,
1425 <%if Config.replacedHomotopy() then 'NO_HOMOTOPY' else if Config.adaptiveHomotopy() then (if Config.globalHomotopy() then 'GLOBAL_ADAPTIVE_HOMOTOPY' else 'LOCAL_ADAPTIVE_HOMOTOPY') else (if Config.globalHomotopy() then 'GLOBAL_EQUIDISTANT_HOMOTOPY' else 'LOCAL_EQUIDISTANT_HOMOTOPY')%>,
1426 <%if intEq(listLength(initialEquations_lambda0), 0) then "NULL" else '<%symbolName(modelNamePrefixStr,"functionInitialEquations_lambda0")%>'%>,
1427 <%symbolName(modelNamePrefixStr,"functionRemovedInitialEquations")%>,
1428 <%symbolName(modelNamePrefixStr,"updateBoundParameters")%>,
1429 <%symbolName(modelNamePrefixStr,"checkForAsserts")%>,
1430 <%symbolName(modelNamePrefixStr,"function_ZeroCrossingsEquations")%>,
1431 <%symbolName(modelNamePrefixStr,"function_ZeroCrossings")%>,
1432 <%symbolName(modelNamePrefixStr,"function_updateRelations")%>,
1433 <%symbolName(modelNamePrefixStr,"zeroCrossingDescription")%>,
1434 <%symbolName(modelNamePrefixStr,"relationDescription")%>,
1435 <%symbolName(modelNamePrefixStr,"function_initSample")%>,
1436 <%symbolName(modelNamePrefixStr,"INDEX_JAC_A")%>,
1437 <%symbolName(modelNamePrefixStr,"INDEX_JAC_ADJ")%>,
1438 <%symbolName(modelNamePrefixStr,"INDEX_JAC_B")%>,
1439 <%symbolName(modelNamePrefixStr,"INDEX_JAC_C")%>,
1440 <%symbolName(modelNamePrefixStr,"INDEX_JAC_D")%>,
1441 <%symbolName(modelNamePrefixStr,"INDEX_JAC_F")%>,
1442 <%symbolName(modelNamePrefixStr,"INDEX_JAC_H")%>,
1443 <%symbolName(modelNamePrefixStr,"initialAnalyticJacobianA")%>,
1444 <%symbolName(modelNamePrefixStr,"initialAnalyticJacobianADJ")%>,
1445 <%symbolName(modelNamePrefixStr,"initialAnalyticJacobianB")%>,
1446 <%symbolName(modelNamePrefixStr,"initialAnalyticJacobianC")%>,
1447 <%symbolName(modelNamePrefixStr,"initialAnalyticJacobianD")%>,
1448 <%symbolName(modelNamePrefixStr,"initialAnalyticJacobianF")%>,
1449 <%symbolName(modelNamePrefixStr,"initialAnalyticJacobianH")%>,
1450 <%symbolName(modelNamePrefixStr,"functionJacA_column")%>,
1451 <%symbolName(modelNamePrefixStr,"functionJacADJ_column")%>,
1452 <%symbolName(modelNamePrefixStr,"functionJacB_column")%>,
1453 <%symbolName(modelNamePrefixStr,"functionJacC_column")%>,
1454 <%symbolName(modelNamePrefixStr,"functionJacD_column")%>,
1455 <%symbolName(modelNamePrefixStr,"functionJacF_column")%>,
1456 <%symbolName(modelNamePrefixStr,"functionJacH_column")%>,
1457 <%symbolName(modelNamePrefixStr,"JacA_DAG")%>,
1458 <%symbolName(modelNamePrefixStr,"linear_model_frame")%>,
1459 <%symbolName(modelNamePrefixStr,"linear_model_datarecovery_frame")%>,
1460 <%symbolName(modelNamePrefixStr,"mayer")%>,
1461 <%symbolName(modelNamePrefixStr,"lagrange")%>,
1462 <%symbolName(modelNamePrefixStr,"getInputVarIndicesInOptimization")%>,
1463 <%symbolName(modelNamePrefixStr,"pickUpBoundsForInputsInOptimization")%>,
1464 <%symbolName(modelNamePrefixStr,"setInputData")%>,
1465 <%symbolName(modelNamePrefixStr,"getTimeGrid")%>,
1466 <%symbolName(modelNamePrefixStr,"symbolicInlineSystem")%>,
1467 <%symbolName(modelNamePrefixStr,"function_initSynchronous")%>,
1468 <%symbolName(modelNamePrefixStr,"function_updateSynchronous")%>,
1469 <%symbolName(modelNamePrefixStr,"function_equationsSynchronous")%>,
1470 <%symbolName(modelNamePrefixStr,"inputNames")%>,
1471 <%symbolName(modelNamePrefixStr,"dataReconciliationInputNames")%>,
1472 <%symbolName(modelNamePrefixStr,"dataReconciliationUnmeasuredVariables")%>,
1473 <% if isModelExchangeFMU then symbolName(modelNamePrefixStr,"read_simulation_info") else "NULL" %>,
1474 <% if isModelExchangeFMU then symbolName(modelNamePrefixStr,"read_input_fmu") else "NULL" %>,
1475 <% match modelStructure case SOME(FMIMODELSTRUCTURE(continuousPartialDerivatives=SOME(__))) then symbolName(modelNamePrefixStr,"initialAnalyticJacobianFMIDER") else "NULL"%>,
1476 <% match modelStructure case SOME(FMIMODELSTRUCTURE(continuousPartialDerivatives=SOME(__))) then symbolName(modelNamePrefixStr,"functionJacFMIDER_column") else "NULL"%>,
1477 <% match modelStructure case SOME(FMIMODELSTRUCTURE(continuousPartialDerivatives=SOME(__))) then symbolName(modelNamePrefixStr,"INDEX_JAC_FMIDER") else "-1"%>,
1478 <% match modelStructure case SOME(FMIMODELSTRUCTURE(initialPartialDerivatives=SOME(__))) then symbolName(modelNamePrefixStr,"initialAnalyticJacobianFMIDERINIT") else "NULL"%>,
1479 <% match modelStructure case SOME(FMIMODELSTRUCTURE(initialPartialDerivatives=SOME(__))) then symbolName(modelNamePrefixStr,"functionJacFMIDERINIT_column") else "NULL"%>,
1480 <% match modelStructure case SOME(FMIMODELSTRUCTURE(initialPartialDerivatives=SOME(__))) then symbolName(modelNamePrefixStr,"INDEX_JAC_FMIDERINIT") else "-1"%>,
1481 <%fmiAliasIndexTableRefs(simCode, modelInfo, modelNamePrefixStr)%>,
1482 <%if hasStructuralUpdate(vars.intParamVars, vars.inputVars) then symbolName(modelNamePrefixStr,"updateStructuralParameters") else "NULL"%>, /* updateStructuralParameters */
1483 <%symbolName(modelNamePrefixStr,"function_nextTimeEvent")%>
1484 <%\n%>
1485 };
1486
1487 <%functionInitializeDataStruc(modelInfo, fileNamePrefix, guid, delayedExps, modelNamePrefixStr, isModelExchangeFMU)%>
1488
1489 static int rml_execution_failed()
1490 {
1491 fflush(NULL);
1492 fprintf(stderr, "Execution failed!\n");
1493 fflush(NULL);
1494 return 1;
1495 }
1496
1497 <% if stringEq("",isModelExchangeFMU) then
1498 <<
1499
1500 #if defined(__MINGW32__) || defined(_MSC_VER)
1501
1502 #if !defined(_UNICODE)
1503 #define _UNICODE
1504 #endif
1505 #if !defined(UNICODE)
1506 #define UNICODE
1507 #endif
1508
1509 #include <windows.h>
1510 char** omc_fixWindowsArgv(int argc, wchar_t **wargv)
1511 {
1512 char** newargv;
1513 /* Support for non-ASCII characters
1514 * Read the unicode command line arguments and translate it to char*
1515 */
1516 newargv = (char**)malloc(argc*sizeof(char*));
1517 for (int i = 0; i < argc; i++) {
1518 newargv[i] = omc_wchar_to_multibyte_str(wargv[i]);
1519 }
1520 return newargv;
1521 }
1522
1523 #define OMC_MAIN wmain
1524 #define OMC_CHAR wchar_t
1525 #define OMC_EXPORT __declspec(dllexport) extern
1526
1527 #else
1528 #define omc_fixWindowsArgv(N, A) (A)
1529 #define OMC_MAIN main
1530 #define OMC_CHAR char
1531 #define OMC_EXPORT extern
1532 #endif
1533
1534 #if defined(threadData)
1535 #undef threadData
1536 #endif
1537 /* call the simulation runtime main from our main! */
1538 #if defined(OMC_DLL_MAIN_DEFINE)
1539 OMC_EXPORT int omcDllMain(int argc, OMC_CHAR **argv)
1540 #else
1541 int OMC_MAIN(int argc, OMC_CHAR** argv)
1542 #endif
1543 {
1544 char** newargv = omc_fixWindowsArgv(argc, argv);
1545 /*
1546 Set the error functions to be used for simulation.
1547 The default value for them is 'functions' version. Change it here to 'simulation' versions
1548 */
1549 omc_assert = omc_assert_simulation;
1550 omc_assert_withEquationIndexes = omc_assert_simulation_withEquationIndexes;
1551
1552 omc_assert_warning_withEquationIndexes = omc_assert_warning_simulation_withEquationIndexes;
1553 omc_assert_warning = omc_assert_warning_simulation;
1554 omc_terminate = omc_terminate_simulation;
1555 omc_throw = omc_throw_simulation;
1556
1557 int res;
1558 DATA data;
1559 MODEL_DATA modelData;
1560 SIMULATION_INFO simInfo;
1561 data.modelData = &modelData;
1562 data.simulationInfo = &simInfo;
1563 measure_time_flag = <% if profileHtml() then "5" else if profileSome() then "1" else if profileAll() then "2" else "0" /* Would be good if this was not a global variable...*/ %>;
1564 compiledInDAEMode = <% if Flags.getConfigBool(Flags.DAE_MODE) then 1 else 0%>;
1565 compiledWithSymSolver = <% intSub(Flags.getConfigEnum(Flags.SYM_SOLVER), 0) %>;
1566 <%mainInit%>
1567 <%mainTop(mainBody,"https://trac.openmodelica.org/OpenModelica/newticket")%>
1568
1569 <%if Flags.isSet(HPCOM) then "terminateHpcOmThreads();" %>
1570 <%if Flags.getConfigBool(Flags.PARMODAUTO) then "dump_times(pm_model);" %>
1571 fflush(NULL);
1572 return res;
1573 }
1574
1575 #ifdef __cplusplus
1576 }
1577 #endif
1578
1579 <%\n%>
1580 >>
1581 %>
1582 >>
1583 /* adrpo: leave a newline at the end of file to get ridsymbolName(String fileNamePrefix of the warning */
1584 end match
1585 end simulationFile;
1586
1587 23211 template simulationFileHeader(String fileNamePrefix)
1588 "Generates header part of simulation file."
1589 ::=
1590 let daeHeader = if Flags.getConfigBool(Flags.DAE_MODE) then '#include "<%fileNamePrefix%>_16dae.h"'
1591 <<
1592 #include "<%fileNamePrefix%>_model.h"
1593 <%daeHeader%>
1594 >>
1595 end simulationFileHeader;
1596
1597 1204 template populateModelInfo(ModelInfo modelInfo, String fileNamePrefix, String guid, DelayedExpression delayed, String isModelExchangeFMU)
1598 "Generates information for data.modelInfo struct."
1599 ::=
1600 match modelInfo
1601 case MODELINFO(varInfo=VARINFO(__),vars=SIMVARS(__)) then
1602 <<
1603 OpenModelica_updateUriMapping(threadData, <%litRefBox()%>(_OMC_LIT_RESOURCES));
1604 data->modelData->modelName = "<%dotPath(name)%>";
1605 data->modelData->modelFilePrefix = "<%fileNamePrefix%>";
1606 data->modelData->modelFileName = "<%fileName%>";
1607 data->modelData->resultFileName = NULL;
1608 data->modelData->modelDir = "<%directory%>";
1609 data->modelData->modelGUID = "{<%guid%>}";
1610 <% match isModelExchangeFMU
1611 case "1.0" then
1612 <<
1613 data->modelData->initXMLData = NULL;
1614 data->modelData->modelDataXml.infoXMLData =
1615 #if defined(OMC_MINIMAL_METADATA)
1616 NULL;
1617 #else
1618 #include "<%fileNamePrefix%>_info.c"
1619 ;
1620 #endif
1621 data->modelData->modelDataXml.fileName = NULL;
1622 >>
1623 case "" then
1624 <<
1625 #if defined(OPENMODELICA_XML_FROM_FILE_AT_RUNTIME)
1626 data->modelData->initXMLData = NULL;
1627 data->modelData->modelDataXml.infoXMLData = NULL;
1628 #else
1629 #if defined(_MSC_VER) /* handle joke compilers */
1630 {
1631 /* for MSVC we encode a string like char x[] = {'a', 'b', 'c', '\0'} */
1632 /* because the string constant limit is 65535 bytes */
1633 static const char contents_init[] =
1634 #include "<%fileNamePrefix%>_init.c"
1635 ;
1636 static const char contents_info[] =
1637 #include "<%fileNamePrefix%>_info.c"
1638 ;
1639 data->modelData->initXMLData = contents_init;
1640 data->modelData->modelDataXml.infoXMLData = contents_info;
1641 }
1642 #else /* handle real compilers */
1643 data->modelData->initXMLData =
1644 #include "<%fileNamePrefix%>_init.c"
1645 ;
1646 data->modelData->modelDataXml.infoXMLData =
1647 #include "<%fileNamePrefix%>_info.c"
1648 ;
1649 #endif /* defined(_MSC_VER) */
1650 #endif /* defined(OPENMODELICA_XML_FROM_FILE_AT_RUNTIME) */
1651 /* Freed with the model data, like the one the resources branch builds. */
1652 data->modelData->modelDataXml.fileName = GC_strdup("<%fileNamePrefix%>_info.json");
1653 data->modelData->resourcesDir = NULL;
1654 >>
1655 else
1656 <<
1657 data->modelData->initXMLData = NULL;
1658 data->modelData->modelDataXml.infoXMLData = NULL;
1659 GC_asprintf(&data->modelData->modelDataXml.fileName, "%s/<%fileNamePrefix%>_info.json", data->modelData->resourcesDir);
1660 >>
1661 %>
1662 data->modelData->runTestsuite = <%if Testsuite.isRunning() then "1" else "0"%>;
1663 data->modelData->nStatesArray = <%varInfo.numStateVars%>;
1664 data->modelData->nDiscreteRealArray = <%varInfo.numDiscreteReal%>;
1665 data->modelData->nVariablesRealArray = <%nVariablesReal(varInfo)%>;
1666 data->modelData->nVariablesIntegerArray = <%varInfo.numIntAlgVars%>;
1667 data->modelData->nVariablesBooleanArray = <%varInfo.numBoolAlgVars%>;
1668 data->modelData->nVariablesStringArray = <%varInfo.numStringAlgVars%>;
1669 data->modelData->nParametersRealArray = <%varInfo.numParams%>;
1670 data->modelData->nParametersIntegerArray = <%varInfo.numIntParams%>;
1671 data->modelData->nParametersBooleanArray = <%varInfo.numBoolParams%>;
1672 data->modelData->nParametersStringArray = <%varInfo.numStringParamVars%>;
1673 data->modelData->nParametersReal = <%varInfo.numParams%>;
1674 data->modelData->nParametersInteger = <%varInfo.numIntParams%>;
1675 data->modelData->nParametersBoolean = <%varInfo.numBoolParams%>;
1676 data->modelData->nParametersString = <%varInfo.numStringParamVars%>;
1677 data->modelData->nAliasRealArray = <%varInfo.numAlgAliasVars%>;
1678 data->modelData->nAliasIntegerArray = <%varInfo.numIntAliasVars%>;
1679 data->modelData->nAliasBooleanArray = <%varInfo.numBoolAliasVars%>;
1680 data->modelData->nAliasStringArray = <%varInfo.numStringAliasVars%>;
1681 data->modelData->nInputVars = <%varInfo.numInVars%>;
1682 data->modelData->nOutputVars = <%varInfo.numOutVars%>;
1683 data->modelData->nZeroCrossings = <%varInfo.numZeroCrossings%>;
1684 data->modelData->nSamples = <%varInfo.numTimeEvents%>;
1685 data->modelData->nRelations = <%varInfo.numRelations%>;
1686 data->modelData->nMathEvents = <%varInfo.numMathEventFunctions%>;
1687 data->modelData->nExtObjs = <%varInfo.numExternalObjects%>;
1688 data->modelData->modelDataXml.modelInfoXmlLength = 0;
1689 data->modelData->modelDataXml.nFunctions = <%listLength(functions)%>;
1690 data->modelData->modelDataXml.nProfileBlocks = 0;
1691 data->modelData->modelDataXml.nEquations = <%varInfo.numEquations%>;
1692 data->modelData->nMixedSystems = <%varInfo.numMixedSystems%>;
1693 data->modelData->nLinearSystems = <%varInfo.numLinearSystems%>;
1694 data->modelData->nNonLinearSystems = <%varInfo.numNonLinearSystems%>;
1695 data->modelData->nStateSets = <%varInfo.numStateSets%>;
1696 data->modelData->nJacobians = <%varInfo.numJacobians%>;
1697 data->modelData->nOptimizeConstraints = <%varInfo.numOptimizeConstraints%>;
1698 data->modelData->nOptimizeFinalConstraints = <%varInfo.numOptimizeFinalConstraints%>;
1699 data->modelData->nDelayExpressions = <%match delayed case
1700 DELAYED_EXPRESSIONS(__) then maxDelayedIndex%>;
1701 data->modelData->nBaseClocks = <%nClocks%>;
1702 data->modelData->nSpatialDistributions = <%nSpatialDistributions%>;
1703 data->modelData->nSensitivityVars = <%listLength(vars.sensitivityVars)%>;
1704 data->modelData->nSensitivityParamVars = <%varInfo.numSensitivityParameters%>;
1705 data->modelData->nSetcVars = <%varInfo.numSetcVars%>;
1706 data->modelData->ndataReconVars = <%varInfo.numDataReconVars%>;
1707 data->modelData->nSetbVars = <%varInfo.numSetbVars%>;
1708 data->modelData->nRelatedBoundaryConditions = <%varInfo.numRelatedBoundaryConditions%>;
1709 data->modelData->linearizationDumpLanguage = <%
1710 if stringEq(Flags.getConfigString(LINEARIZATION_DUMP_LANGUAGE),"none") then 'OMC_LINEARIZE_DUMP_LANGUAGE_MODELICA'
1711 else if stringEq(Flags.getConfigString(LINEARIZATION_DUMP_LANGUAGE),"modelica") then 'OMC_LINEARIZE_DUMP_LANGUAGE_MODELICA'
1712 else if stringEq(Flags.getConfigString(LINEARIZATION_DUMP_LANGUAGE),"matlab") then 'OMC_LINEARIZE_DUMP_LANGUAGE_MATLAB'
1713 else if stringEq(Flags.getConfigString(LINEARIZATION_DUMP_LANGUAGE),"julia") then 'OMC_LINEARIZE_DUMP_LANGUAGE_JULIA'
1714 else if stringEq(Flags.getConfigString(LINEARIZATION_DUMP_LANGUAGE),"python") then 'OMC_LINEARIZE_DUMP_LANGUAGE_PYTHON'
1715 %>;
1716 >>
1717 end match
1718 end populateModelInfo;
1719
1720 1204 template functionInitializeDataStruc(ModelInfo modelInfo, String fileNamePrefix, String guid, DelayedExpression delayed, String modelNamePrefix, String isModelExchangeFMU)
1721 "Generates function in simulation file."
1722 ::=
1723 <<
1724 <%
1725 match modelInfo
1726 case MODELINFO(__) then
1727 <<
1728 <% sortedClasses |> c as CLASS(info=SOURCEINFO(fileName=fileName)) hasindex index0 =>
1729 let escName = Util.escapeModelicaStringToCString(name)
1730 let escDir = Util.escapeModelicaStringToCString(dirname(fileName))
1731 <<
1732 #define _OMC_LIT_RESOURCE_<%index0%>_name_data "<%escName%>"
1733 #define _OMC_LIT_RESOURCE_<%index0%>_dir_data "<%escDir%>"
1734 static const <%litDefString()%>(_OMC_LIT_RESOURCE_<%index0%>_name,<%unescapedStringLength(escName)%>,_OMC_LIT_RESOURCE_<%index0%>_name_data);
1735 static const <%litDefString()%>(_OMC_LIT_RESOURCE_<%index0%>_dir,<%unescapedStringLength(escDir)%>,_OMC_LIT_RESOURCE_<%index0%>_dir_data);
1736 <%\n%>
1737 >>
1738 %>
1739 static const <%litDefBox()%>(_OMC_LIT_RESOURCES,<%intMul(2,listLength(sortedClasses))%>,<%litArrayTag(intMul(2,listLength(sortedClasses)))%>) {<%
1740 sortedClasses |> c as CLASS(info=SOURCEINFO(fileName=fileName)) hasindex index0 =>
1741 '<%litRefString()%>(_OMC_LIT_RESOURCE_<%index0%>_name), <%litRefString()%>(_OMC_LIT_RESOURCE_<%index0%>_dir)' ; separator=", "
1742 %>}};
1743 >>
1744 %>
1745 void <%symbolName(modelNamePrefix,"setupDataStruc")%>(DATA *data, threadData_t *threadData)
1746 {
1747 assertStreamPrint(threadData,0!=data, "Error while initialize Data");
1748 threadData->localRoots[LOCAL_ROOT_SIMULATION_DATA] = data;
1749 data->callback = &<%symbolName(modelNamePrefix,"callback")%>;
1750 <%populateModelInfo(modelInfo, fileNamePrefix, guid, delayed, isModelExchangeFMU)%>
1751 }
1752 >>
1753 end functionInitializeDataStruc;
1754
1755 1204 template fmiAliasIndexTables(SimCode simCode, ModelInfo modelInfo, Text modelNamePrefixStr)
1756 "The alias tables the FMI value references resolve through; see
1757 OpenModelicaGeneratedFunctionCallbacks."
1758 ::=
1759 match modelInfo
1760 case MODELINFO(vars=SIMVARS(__), varInfo=VARINFO(__)) then
1761 <<
1762 <%fmiAliasIndexTable(simCode, modelNamePrefixStr, "Real", varInfo.numAlgAliasVars, vars.aliasVars)%>
1763 <%fmiAliasIndexTable(simCode, modelNamePrefixStr, "Integer", varInfo.numIntAliasVars, vars.intAliasVars)%>
1764 <%fmiAliasIndexTable(simCode, modelNamePrefixStr, "Boolean", varInfo.numBoolAliasVars, vars.boolAliasVars)%>
1765 <%fmiAliasIndexTable(simCode, modelNamePrefixStr, "String", varInfo.numStringAliasVars, vars.stringAliasVars)%>
1766 >>
1767 end fmiAliasIndexTables;
1768
1769 /* `n` is the scalar element count and the list is of array variables, so a
1770 non-scalarized alias array leaves the tail zero-initialized -- as the table
1771 this replaces did. */
1772 4816 template fmiAliasIndexTable(SimCode simCode, Text modelNamePrefixStr, String ty, Integer n, list<SimVar> aliasVars)
1773 ::=
1774 if boolAnd(SimCodeCodegenUtil.isFMUSimCode(simCode), intGt(n, 0)) then
1775 <<
1776 static const int <%symbolName(modelNamePrefixStr,'fmi<%ty%>AliasIndexes')%>[<%n%>] = {
1777 <%aliasVars |> v as SIMVAR(__) => fmiAliasIndex(simCode, aliasvar) ; separator=", " %>
1778 };<%\n%>
1779 >>
1780 end fmiAliasIndexTable;
1781
1782 2673 template fmiAliasIndex(SimCode simCode, AliasVariable v)
1783 ::=
1784 match v
1785 case NOALIAS(__) then error(sourceInfo(), "fmiAliasIndex expected an alias")
1786 case ALIAS(__) then SimCodeCodegenUtil.lookupVR(varName,simCode)
1787 /* -1 - vr, so that a negated alias of vr=0 is still negative */
1788 case NEGATEDALIAS(__) then intSub(-1, SimCodeCodegenUtil.lookupVR(varName,simCode))
1789 end fmiAliasIndex;
1790
1791 2408 template hasDimensionParameters(list<SimVar> intParamVars)
1792 ::= (intParamVars |> v => if isDimensionParameter(v) then "1")
1793 end hasDimensionParameters;
1794
1795 2408 template hasStructuralUpdate(list<SimVar> intParamVars, list<SimVar> inputVars)
1796 ::= if hasDimensionParameters(intParamVars) then "1" else (if hasSymbolicDims(inputVars) then "1")
1797 end hasStructuralUpdate;
1798
1799 1204 template functionUpdateStructuralParameters(list<SimVar> intParamVars, list<SimVar> inputVars, Text modelNamePrefixStr)
1800 "The size parameters $DIM_k of derived dimensions of resizable arrays (N-1),
1801 and the number of scalar inputs if an input is a resizable array.
1802 The runtime calls it after reading the init.xml, before it computes the sizes
1803 of the arrays and allocates them: only the start attributes of the parameters
1804 exist, possibly changed with -override, so they are what it reads and writes."
1805 ::=
1806 if hasStructuralUpdate(intParamVars, inputVars) then
1807 let body = (intParamVars |> v as SIMVAR(initialValue = SOME(e)) =>
1808 if isDimensionParameter(v) then
1809 '<%structuralParameterStart(v)%> = <%structuralParameterExp(e)%>; /* <%crefStrNoUnderscore(v.name)%> */'
1810 ;separator="\n")
1811 let inputs = if hasSymbolicDims(inputVars) then
1812 'data->modelData->nInputVars = <%structuralParameterExp(numScalarElemsBeforeExp(inputVars, listLength(inputVars)))%>;'
1813 <<
1814 static void <%symbolName(modelNamePrefixStr,"updateStructuralParameters")%>(DATA *data, threadData_t *threadData)
1815 {
1816 <%body%>
1817 <%inputs%>
1818 }
1819 >>
1820 end functionUpdateStructuralParameters;
1821
1822 18 template structuralParameterStart(SimVar var)
1823 "The start attribute of a scalar Integer parameter."
1824 ::=
1825 match var
1826 case SIMVAR(varKind = PARAM()) then
1827 '((modelica_integer*)(data->modelData->integerParameterData[<%index%>].attribute.start.data))[0]'
1828 else error(sourceInfo(), 'structuralParameterStart: no parameter')
1829 end structuralParameterStart;
1830
1831 12 template structuralParameterExp(Exp exp)
1832 "A dimension expression of Integer parameters in terms of their start attributes."
1833 ::=
1834 match exp
1835 case ICONST(__) then '((modelica_integer) <%integer%>)'
1836 case CREF(componentRef = cr) then
1837 match cref2simvar(cr, getSimCode())
1838 case v as SIMVAR(varKind = PARAM(), type_ = T_INTEGER(__)) then structuralParameterStart(v)
1839 else error(sourceInfo(), 'structuralParameterExp: <%CodegenUtil.crefStr(cr)%> is no Integer parameter')
1840 case BINARY(operator = ADD(__)) then '(<%structuralParameterExp(exp1)%> + <%structuralParameterExp(exp2)%>)'
1841 case BINARY(operator = SUB(__)) then '(<%structuralParameterExp(exp1)%> - <%structuralParameterExp(exp2)%>)'
1842 case BINARY(operator = MUL(__)) then '(<%structuralParameterExp(exp1)%> * <%structuralParameterExp(exp2)%>)'
1843 case UNARY(operator = UMINUS(__)) then '(-<%structuralParameterExp(exp)%>)'
1844 case CALL(path = IDENT(name = "max"), expLst = {e1, e2}) then
1845 let a = structuralParameterExp(e1)
1846 let b = structuralParameterExp(e2)
1847 '(<%a%> > <%b%> ? <%a%> : <%b%>)'
1848 case CALL(path = IDENT(name = "min"), expLst = {e1, e2}) then
1849 let a = structuralParameterExp(e1)
1850 let b = structuralParameterExp(e2)
1851 '(<%a%> < <%b%> ? <%a%> : <%b%>)'
1852 case CALL(path = IDENT(name = "div"), expLst = {e1, e2}) then '(<%structuralParameterExp(e1)%> / <%structuralParameterExp(e2)%>)'
1853 else error(sourceInfo(), 'structuralParameterExp: dimension expression <%ExpressionDumpTpl.dumpExp(exp,"\"")%> is not supported')
1854 end structuralParameterExp;
1855
1856 1204 template fmiAliasIndexTableRefs(SimCode simCode, ModelInfo modelInfo, Text modelNamePrefixStr)
1857 ::=
1858 match modelInfo
1859 case MODELINFO(varInfo=VARINFO(__)) then
1860 <<
1861 <%fmiAliasIndexTableRef(simCode, modelNamePrefixStr, "Real", varInfo.numAlgAliasVars)%>,
1862 <%fmiAliasIndexTableRef(simCode, modelNamePrefixStr, "Integer", varInfo.numIntAliasVars)%>,
1863 <%fmiAliasIndexTableRef(simCode, modelNamePrefixStr, "Boolean", varInfo.numBoolAliasVars)%>,
1864 <%fmiAliasIndexTableRef(simCode, modelNamePrefixStr, "String", varInfo.numStringAliasVars)%>
1865 >>
1866 end fmiAliasIndexTableRefs;
1867
1868 4816 template fmiAliasIndexTableRef(SimCode simCode, Text modelNamePrefixStr, String ty, Integer n)
1869 ::=
1870 if boolAnd(SimCodeCodegenUtil.isFMUSimCode(simCode), intGt(n, 0)) then symbolName(modelNamePrefixStr,'fmi<%ty%>AliasIndexes') else "NULL"
1871 end fmiAliasIndexTableRef;
1872
1873 ✗ template functionSimProfDef(SimEqSystem eq, Integer value, Text &reverseProf)
1874 "Generates function in simulation file."
1875 ::=
1876 match eq
1877 case SES_MIXED(__) then
1878 let &reverseProf += 'data->modelData->equationInfo_reverse_prof_index[<%value%>] = <%index%>;<%\n%>'
1879 <<
1880 #define SIM_PROF_EQ_<%index%> <%value%><%\n%>
1881 >>
1882 // no dynamic tearing
1883 case SES_LINEAR(lSystem=ls as LINEARSYSTEM(__), alternativeTearing=NONE()) then
1884 let &reverseProf += 'data->modelData->equationInfo_reverse_prof_index[<%value%>] = <%ls.index%>;<%\n%>'
1885 <<
1886 #define SIM_PROF_EQ_<%ls.index%> <%value%><%\n%>
1887 >>
1888 case SES_NONLINEAR(nlSystem=nls as NONLINEARSYSTEM(__), alternativeTearing=NONE()) then
1889 let &reverseProf += 'data->modelData->equationInfo_reverse_prof_index[<%value%>] = <%nls.index%>;<%\n%>'
1890 <<
1891 #define SIM_PROF_EQ_<%nls.index%> <%value%><%\n%>
1892 >>
1893 // dynamic tearing
1894 case SES_LINEAR(lSystem=ls as LINEARSYSTEM(__), alternativeTearing = SOME(at as LINEARSYSTEM(__))) then
1895 let &reverseProf += 'data->modelData->equationInfo_reverse_prof_index[<%value%>] = <%ls.index%>;<%\n%>'
1896 let &reverseProf += 'data->modelData->equationInfo_reverse_prof_index[<%value%>] = <%at.index%>;<%\n%>'
1897 <<
1898 #define SIM_PROF_EQ_<%ls.index%> <%value%><%\n%>
1899 #define SIM_PROF_EQ_<%at.index%> <%value%><%\n%>
1900 >>
1901 case SES_NONLINEAR(nlSystem=nls as NONLINEARSYSTEM(__), alternativeTearing = SOME(at as NONLINEARSYSTEM(__))) then
1902 let &reverseProf += 'data->modelData->equationInfo_reverse_prof_index[<%value%>] = <%nls.index%>;<%\n%>'
1903 let &reverseProf += 'data->modelData->equationInfo_reverse_prof_index[<%value%>] = <%at.index%>;<%\n%>'
1904 <<
1905 #define SIM_PROF_EQ_<%nls.index%> <%value%><%\n%>
1906 #define SIM_PROF_EQ_<%at.index%> <%value%><%\n%>
1907 >>
1908 end match
1909 end functionSimProfDef;
1910
1911 1204 template variableDefinitions(ModelInfo modelInfo, list<BackendDAE.TimeEvent> timeEvents)
1912 "Generates global data in simulation file."
1913 ::=
1914 if true then "" else
1915 let () = System.tmpTickReset(1000)
1916 match modelInfo
1917 case MODELINFO(varInfo=VARINFO(numStateVars=numStateVars, numAlgVars= numAlgVars, numDiscreteReal=numDiscreteReal, numOptimizeConstraints=numOptimizeConstraints, numOptimizeFinalConstraints=numOptimizeFinalConstraints), vars=SIMVARS(__)) then
1918 <<
1919 /* States */
1920 <%vars.stateVars |> var =>
1921 globalDataVarDefine(var, "realVars")
1922 ;separator="\n"%>
1923
1924 /* StatesDerivatives */
1925 <%vars.derivativeVars |> var =>
1926 globalDataVarDefine(var, "realVars")
1927 ;separator="\n"%>
1928
1929 /* Non Discrete Real Algebraic Vars */
1930 <%vars.algVars |> var =>
1931 globalDataVarDefine(var, "realVars")
1932 ;separator="\n"%>
1933
1934 /* Discrete Real Algebraic Vars */
1935 <%vars.discreteAlgVars |> var =>
1936 globalDataVarDefine(var, "realVars")
1937 ;separator="\n"%>
1938
1939 /* Nonlinear Constraints For Dyn. Optimization */
1940 <%vars.realOptimizeConstraintsVars |> var =>
1941 globalDataVarDefine(var, "realVars")
1942 ;separator="\n"%>
1943
1944 /* Nonlinear Final Constraints For Dyn. Optimization */
1945 <%vars.realOptimizeFinalConstraintsVars |> var =>
1946 globalDataVarDefine(var, "realVars")
1947 ;separator="\n"%>
1948
1949 /* Algebraic Parameter */
1950 <%vars.paramVars |> var =>
1951 globalDataParDefine(var, "realParameter")
1952 ;separator="\n"%>
1953
1954 /* External Objects */
1955 <%vars.extObjVars |> var =>
1956 globalDataParDefine(var, "extObjs")
1957 ;separator="\n"%>
1958
1959 /* Algebraic Integer Vars */
1960 <%vars.intAlgVars |> var =>
1961 globalDataVarDefine(var, "integerVars")
1962 ;separator="\n"%>
1963
1964 /* Algebraic Integer Parameter */
1965 <%vars.intParamVars |> var =>
1966 globalDataParDefine(var, "integerParameter")
1967 ;separator="\n"%>
1968
1969 /* Algebraic Boolean Vars */
1970 <%vars.boolAlgVars |> var =>
1971 globalDataVarDefine(var, "booleanVars")
1972 ;separator="\n"%>
1973
1974 /* Algebraic Boolean Parameters */
1975 <%vars.boolParamVars |> var =>
1976 globalDataParDefine(var, "booleanParameter")
1977 ;separator="\n"%>
1978
1979 /* Algebraic String Variables */
1980 <%vars.stringAlgVars |> var =>
1981 globalDataVarDefine(var, "stringVars")
1982 ;separator="\n"%>
1983
1984 /* Algebraic String Parameter */
1985 <%vars.stringParamVars |> var =>
1986 globalDataParDefine(var, "stringParameter")
1987 ;separator="\n"%>
1988
1989 >>
1990 end match
1991 end variableDefinitions;
1992
1993 ✗ template globalDataParDefine(SimVar simVar, String arrayName)
1994 "Generates a define statement for a parameter."
1995 ::=
1996 let &sub = buffer ""
1997 match simVar
1998 case SIMVAR(arrayCref=SOME(c),aliasvar=NOALIAS()) then
1999 <<
2000 /* <%crefStrNoUnderscore(c)%> */
2001 #define <%cref(c, &sub)%> data->simulationInfo-><%arrayName%>[<%index%>]
2002
2003 /* <%crefStrNoUnderscore(name)%> */
2004 #define <%cref(name, &sub)%> data->simulationInfo-><%arrayName%>[<%index%>]
2005 #define _<%cref(name, &sub)%>(i) <%cref(name, &sub)%>
2006
2007 >>
2008 case SIMVAR(aliasvar=NOALIAS()) then
2009 <<
2010 /* <%crefStrNoUnderscore(name)%> */
2011 #define <%cref(name, &sub)%> data->simulationInfo-><%arrayName%>[<%index%>]
2012 #define _<%cref(name, &sub)%>(i) <%cref(name, &sub)%>
2013
2014 >>
2015 end match
2016 end globalDataParDefine;
2017
2018 ✗ template globalDataVarDefine(SimVar simVar, String arrayName) "template globalDataVarDefine
2019 Generates a define statement for a varable in the global data section."
2020 ::=
2021 let &sub = buffer ""
2022 match simVar
2023 case SIMVAR(arrayCref=SOME(c),aliasvar=NOALIAS()) then
2024 <<
2025 /* <%crefStrNoUnderscore(c)%> */
2026 #define _<%cref(c, &sub)%>(i) data->localData[i]-><%arrayName%>[<%index%>]
2027 #define <%cref(c, &sub)%> _<%cref(c, &sub)%>(0)
2028 #define <%cref(crefPrefixPre(c), &sub)%> data->simulationInfo-><%arrayName%>Pre[<%index%>]
2029
2030 /* <%crefStrNoUnderscore(name)%> */
2031 #define _<%cref(name, &sub)%>(i) data->localData[i]-><%arrayName%>[<%index%>]
2032 #define <%cref(name, &sub)%> _<%cref(name, &sub)%>(0)
2033 #define <%cref(crefPrefixPre(name), &sub)%> data->simulationInfo-><%arrayName%>Pre[<%index%>]
2034
2035 >>
2036 case SIMVAR(aliasvar=NOALIAS()) then
2037 <<
2038 /* <%crefStrNoUnderscore(name)%> */
2039 #define _<%cref(name, &sub)%>(i) data->localData[i]-><%arrayName%>[<%index%>]
2040 #define <%cref(name, &sub)%> _<%cref(name, &sub)%>(0)
2041 #define <%cref(crefPrefixPre(name), &sub)%> data->simulationInfo-><%arrayName%>Pre[<%index%>]
2042 #define _<%cref(crefPrefixPre(name), &sub)%>(i) <%cref(crefPrefixPre(name), &sub)%>
2043
2044 >>
2045 end match
2046 end globalDataVarDefine;
2047
2048 ✗ template globalDataAliasVarArray(String _type, String _name, list<SimVar> items)
2049 "Generates array with variable names in global data section."
2050 ::=
2051 match items
2052 case {} then
2053 <<
2054 <%_type%> <%_name%>[1] = {{0,0,-1}};
2055 >>
2056 case items then
2057 <<
2058 <%_type%> <%_name%>[<%listLength(items)%>] = {
2059 <%items |> var as SIMVAR(__) => '{<%aliasVarNameType(aliasvar)%>,<%index%>}'; separator=",\n"%>
2060 };
2061 >>
2062 end match
2063 end globalDataAliasVarArray;
2064
2065 1204 template symJacDefinition(list<JacobianMatrix> JacobianMatrices, String modelNamePrefix) "template variableDefinitionsJacobians
2066 Generates defines for jacobian vars."
2067 ::=
2068 let symbolicJacsDefine = (JacobianMatrices |> jac as JAC_MATRIX() =>
2069 <<
2070 #define <%symbolName(modelNamePrefix,"INDEX_JAC_")%><%jac.matrixName%> <%jac.jacobianIndex%>
2071 int <%symbolName(modelNamePrefix,"functionJac")%><%jac.matrixName%>_column(DATA* data, threadData_t *threadData, JACOBIAN *thisJacobian, JACOBIAN *parentJacobian);
2072 int <%symbolName(modelNamePrefix,"initialResizableAnalyticJacobian")%><%jac.matrixName%>(DATA* data, threadData_t *threadData, JACOBIAN *jacobian);
2073 int <%symbolName(modelNamePrefix,"initialAnalyticJacobian")%><%jac.matrixName%>(DATA* data, threadData_t *threadData, JACOBIAN *jacobian);
2074 void <%symbolName(modelNamePrefix,"Jac")%><%jac.matrixName%>_DAG(DATA* data, threadData_t *threadData, JACOBIAN *jacobian);
2075 <%genericCallHeaders(jac.generic_loop_calls, createJacContext(jac.matrixName, jac.crefsHT))%>
2076 >>
2077 ;separator="\n\n";empty)
2078
2079 <<
2080 #if defined(__cplusplus)
2081 extern "C" {
2082 #endif
2083
2084 /* Jacobian Variables */
2085 <%symbolicJacsDefine%>
2086
2087 #if defined(__cplusplus)
2088 }
2089 #endif
2090 >>
2091 end symJacDefinition;
2092
2093 ✗ template aliasVarNameType(AliasVariable var)
2094 "Generates type of alias."
2095 ::=
2096 let &sub = buffer ""
2097 match var
2098 case NOALIAS() then
2099 <<
2100 0,0
2101 >>
2102 case ALIAS(__) then
2103 <<
2104 &<%cref(varName, &sub)%>,0
2105 >>
2106 case NEGATEDALIAS(__) then
2107 <<
2108 &<%cref(varName, &sub)%>,1
2109 >>
2110 end match
2111 end aliasVarNameType;
2112
2113 1204 template functionCallExternalObjectDestructors(ExtObjInfo extObjInfo, String modelNamePrefix)
2114 "Generates function in simulation file."
2115 ::=
2116 let &sub = buffer ""
2117 match extObjInfo
2118 case extObjInfo as EXTOBJINFO(__) then
2119 <<
2120 void <%symbolName(modelNamePrefix,"callExternalObjectDestructors")%>(DATA *data, threadData_t *threadData)
2121 {
2122 if(data->simulationInfo->extObjs)
2123 {
2124 <%listReverse(extObjInfo.vars) |> var as SIMVAR(varKind=ext as EXTOBJ(__)) => 'omc_<%underscorePath(ext.fullClassName)%>_destructor(threadData,<%cref(var.name, &sub)%>);' ;separator="\n"%>
2125 free(data->simulationInfo->extObjs);
2126 data->simulationInfo->extObjs = 0;
2127 }
2128 }
2129 >>
2130 end match
2131 end functionCallExternalObjectDestructors;
2132
2133 1204 template functionInput(SimCode simCode, ModelInfo modelInfo, String modelNamePrefix)
2134 "Generates function in simulation file.
2135 data->simulationInfo->inputVars holds one value per scalar input, the
2136 elements of an array input are stored consecutively."
2137 ::=
2138 let &sub = buffer ""
2139 match modelInfo
2140 case MODELINFO(vars=SIMVARS(inputVars=inputVars)) then
2141 <<
2142 int <%symbolName(modelNamePrefix,"input_function")%>(DATA *data, threadData_t *threadData)
2143 {
2144 <%inputVars |> var as SIMVAR(name=name) hasindex i0 =>
2145 let offset = inputOffset(inputVars, i0)
2146 match cref2simvar(name, simCode)
2147 case v as SIMVAR(type_=T_ARRAY()) then
2148 <<
2149 for (size_t k = 0; k < <%inputCount(v)%>; k++) {
2150 <%inputValue(v, 'k')%> = data->simulationInfo->inputVars[<%offset%> + k];
2151 }
2152 >>
2153 else
2154 '<%cref(name, &sub)%> = data->simulationInfo->inputVars[<%offset%>];'
2155 ;separator="\n"
2156 %>
2157
2158 return 0;
2159 }
2160
2161 int <%symbolName(modelNamePrefix,"input_function_init")%>(DATA *data, threadData_t *threadData)
2162 {
2163 <%inputVars |> SIMVAR(name=name) hasindex i0 =>
2164 let offset = inputOffset(inputVars, i0)
2165 match cref2simvar(name, simCode)
2166 case v as SIMVAR(aliasvar=NOALIAS()) then
2167 let ty = expTypeShort(type_)
2168 let start = '<%inputData(v)%>[<%index%>].attribute.start'
2169 <<
2170 for (size_t k = 0; k < <%inputCount(v)%>; k++) {
2171 data->simulationInfo->inputVars[<%offset%> + k] = <%ty%>_get(<%start%>, base_array_nr_of_elements(<%start%>) == 1 ? 0 : k);
2172 }
2173 >>
2174 else error(sourceInfo(), 'Cannot get attributes of alias variable <%CodegenUtil.crefStr(name)%>. Alias variables should have been replaced by the compiler before SimCode')
2175 ;separator="\n"
2176 %>
2177
2178 return 0;
2179 }
2180
2181 int <%symbolName(modelNamePrefix,"input_function_updateStartValues")%>(DATA *data, threadData_t *threadData)
2182 {
2183 <%inputVars |> SIMVAR(name=name) hasindex i0 =>
2184 let offset = inputOffset(inputVars, i0)
2185 match cref2simvar(name, simCode)
2186 case v as SIMVAR(aliasvar=NOALIAS()) then
2187 let ty = expTypeShort(type_)
2188 let start = '<%inputData(v)%>[<%index%>].attribute.start'
2189 <<
2190 <%ensureSizeFunction(ty)%>(&<%start%>, <%inputCount(v)%>);
2191 for (size_t k = 0; k < <%inputCount(v)%>; k++) {
2192 put_<%ty%>_element(data->simulationInfo->inputVars[<%offset%> + k], k, &<%start%>);
2193 }
2194 >>
2195 else
2196 error(sourceInfo(), 'Cannot get attributes of alias variable <%CodegenUtil.crefStr(name)%>. Alias variables should have been replaced by the compiler before SimCode')
2197 ;separator="\n"
2198 %>
2199
2200 return 0;
2201 }
2202
2203 int <%symbolName(modelNamePrefix,"inputNames")%>(DATA *data, char ** names){
2204 <%inputVars |> simVar as SIMVAR(__) hasindex i0 =>
2205 let offset = inputOffset(inputVars, i0)
2206 match cref2simvar(name, simCode)
2207 case v as SIMVAR(aliasvar=NOALIAS(), type_=T_ARRAY()) then
2208 if isSymbolicArrayVar(v) then inputNamesResizable(v, offset) else
2209 (arrayElementSubscripts(v) |> subscript hasindex k =>
2210 'names[<%intAdd(numScalarElemsBefore(inputVars, i0), k)%>] = (char *) "<%Util.escapeModelicaStringToCString(crefStrNoUnderscore(name))%>[<%subscript%>]";'
2211 ;separator="\n")
2212 case SIMVAR(aliasvar=NOALIAS()) then
2213 'names[<%offset%>] = (char *) <%inputData(simVar)%>[<%index%>].info.name;'
2214 else error(sourceInfo(), 'Cannot get attributes of alias variable <%CodegenUtil.crefStr(name)%>. Alias variables should have been replaced by the compiler before SimCode')
2215 ;separator="\n"
2216 %>
2217
2218 return 0;
2219 }
2220 >>
2221 end match
2222 end functionInput;
2223
2224 1172 template inputOffset(list<SimVar> inputVars, Integer i0)
2225 "The scalar offset of the i0-th input in data->simulationInfo->inputVars, an
2226 expression of the size parameters if an input is a resizable array."
2227 ::= if hasSymbolicDims(inputVars) then structuralParameterExp(numScalarElemsBeforeExp(inputVars, i0)) else numScalarElemsBefore(inputVars, i0)
2228 end inputOffset;
2229
2230 879 template inputCount(SimVar var)
2231 "The number of scalar elements of an input."
2232 ::= if isSymbolicArrayVar(var) then structuralParameterExp(simVarSizeExp(var)) else numScalarElemsVar(var)
2233 end inputCount;
2234
2235 ✗ template inputNamesResizable(SimVar var, Text offset)
2236 "The names of the elements of an input that is a resizable array, built at
2237 runtime in row-major order like arrayElementSubscripts, e.g. u[1,2]."
2238 ::=
2239 match var
2240 case SIMVAR(__) then
2241 let dims = (simVarDimExps(var) |> d => structuralParameterExp(d) ;separator=", ")
2242 let ndims = listLength(simVarDimExps(var))
2243 <<
2244 {
2245 const modelica_integer dims[<%ndims%>] = {<%dims%>};
2246 size_t n = 1, k, rest;
2247 int j, pos;
2248 long idx[<%ndims%>];
2249 char buf[1024];
2250 for (j = 0; j < <%ndims%>; j++) n *= (size_t) dims[j];
2251 for (k = 0; k < n; k++) {
2252 rest = k;
2253 for (j = <%ndims%> - 1; j >= 0; j--) { idx[j] = (long) (rest % (size_t) dims[j]) + 1; rest /= (size_t) dims[j]; }
2254 pos = snprintf(buf, sizeof(buf), "%s[", "<%Util.escapeModelicaStringToCString(crefStrNoUnderscore(name))%>");
2255 for (j = 0; j < <%ndims%> && pos < (int) sizeof(buf); j++) pos += snprintf(buf + pos, sizeof(buf) - pos, j ? ",%ld" : "%ld", idx[j]);
2256 if (pos < (int) sizeof(buf)) snprintf(buf + pos, sizeof(buf) - pos, "]");
2257 names[<%offset%> + k] = strdup(buf);
2258 }
2259 }
2260 >>
2261 end inputNamesResizable;
2262
2263 879 template inputData(SimVar var)
2264 "Static data array of an input variable."
2265 ::=
2266 match var
2267 case SIMVAR(varKind=PARAM()) then 'data->modelData-><%expTypeShort(type_)%>ParameterData'
2268 case SIMVAR(__) then 'data->modelData-><%expTypeShort(type_)%>VarsData'
2269 end inputData;
2270
2271 24 template inputValue(SimVar var, String k)
2272 "Value of element k of an array input variable."
2273 ::=
2274 match var
2275 case SIMVAR(varKind=PARAM()) then
2276 let ty = expTypeShort(type_)
2277 'data->simulationInfo-><%ty%>Parameter[data->simulationInfo-><%ty%>ParamsIndex[<%index%>] + <%k%>]'
2278 case SIMVAR(__) then
2279 let ty = expTypeShort(type_)
2280 'data->localData[0]-><%ty%>Vars[data->simulationInfo-><%ty%>VarsIndex[<%index%>] + <%k%>]'
2281 end inputValue;
2282
2283 287 template ensureSizeFunction(String ty)
2284 ::=
2285 match ty
2286 case "real"
2287 case "integer"
2288 case "boolean" then '<%ty%>_array_ensure_size'
2289 else error(sourceInfo(), 'Inputs of type <%ty%> are not supported.')
2290 end ensureSizeFunction;
2291
2292 1204 template functionDataInput(SimCode simCode, ModelInfo modelInfo, String modelNamePrefix)
2293 "Generates function in simulation file."
2294 ::=
2295 let &sub = buffer ""
2296 match modelInfo
2297 case MODELINFO(vars=SIMVARS(__)) then
2298 <<
2299 int <%symbolName(modelNamePrefix,"data_function")%>(DATA *data, threadData_t *threadData)
2300 {
2301 <%vars.dataReconinputVars |> SIMVAR(name=name, type_=T_REAL()) hasindex i0 =>
2302 '<%cref(name, &sub)%> = data->simulationInfo->datainputVars[<%i0%>];'
2303 ;separator="\n"
2304 %>
2305 return 0;
2306 }
2307
2308 int <%symbolName(modelNamePrefix,"dataReconciliationInputNames")%>(DATA *data, char ** names){
2309 <%vars.dataReconinputVars |> simVar as SIMVAR(__) hasindex i0 =>
2310 match cref2simvar(name, simCode)
2311 case SIMVAR(aliasvar=NOALIAS()) then
2312 'names[<%i0%>] = (char *) data->modelData-><%expTypeShort(type_)%>VarsData[<%index%>].info.name;'
2313 else error(sourceInfo(), 'Cannot get attributes of alias variable <%CodegenUtil.crefStr(name)%>. Alias variables should have been replaced by the compiler before SimCode')
2314 ;separator="\n"
2315 %>
2316
2317 return 0;
2318 }
2319
2320 int <%symbolName(modelNamePrefix,"dataReconciliationUnmeasuredVariables")%>(DATA *data, char ** names)
2321 {
2322 <%vars.dataReconSetBVars |> simVar as SIMVAR(__) hasindex i0 =>
2323 match cref2simvar(name, simCode)
2324 case SIMVAR(aliasvar=NOALIAS()) then
2325 'names[<%i0%>] = (char *) data->modelData-><%expTypeShort(type_)%>VarsData[<%index%>].info.name;'
2326 else error(sourceInfo(), 'Cannot get attributes of alias variable <%CodegenUtil.crefStr(name)%>. Alias variables should have been replaced by the compiler before SimCode')
2327 ;separator="\n"
2328 %>
2329
2330 return 0;
2331 }
2332 >>
2333 end match
2334 end functionDataInput;
2335
2336 1204 template functionOutput(ModelInfo modelInfo, String modelNamePrefix)
2337 "Generates function in simulation file."
2338 ::=
2339 let &sub = buffer ""
2340 match modelInfo
2341 case MODELINFO(vars=SIMVARS(__)) then
2342 <<
2343 int <%symbolName(modelNamePrefix,"output_function")%>(DATA *data, threadData_t *threadData)
2344 {
2345 <%vars.outputVars |> SIMVAR(name=name, type_=T_REAL()) hasindex i0 =>
2346 'data->simulationInfo->outputVars[<%i0%>] = <%cref(name, &sub)%>;'
2347 ;separator="\n"
2348 %>
2349
2350 return 0;
2351 }
2352 >>
2353 end match
2354 end functionOutput;
2355
2356
2357 1204 template functionSetC(ModelInfo modelInfo, String modelNamePrefix)
2358 "Generates function in simulation file."
2359 ::=
2360 let &sub = buffer ""
2361 match modelInfo
2362 case MODELINFO(vars=SIMVARS(__)) then
2363 <<
2364 int <%symbolName(modelNamePrefix,"setc_function")%>(DATA *data, threadData_t *threadData)
2365 {
2366 <%vars.dataReconSetcVars |> SIMVAR(name=name, type_=T_REAL()) hasindex i0 =>
2367 'data->simulationInfo->setcVars[<%i0%>] = <%cref(name, &sub)%>;'
2368 ;separator="\n"
2369 %>
2370
2371 return 0;
2372 }
2373 >>
2374 end match
2375 end functionSetC;
2376
2377 1204 template functionSetB(ModelInfo modelInfo, String modelNamePrefix)
2378 "Generates function in simulation file."
2379 ::=
2380 let &sub = buffer ""
2381 match modelInfo
2382 case MODELINFO(vars=SIMVARS(__)) then
2383 <<
2384 int <%symbolName(modelNamePrefix,"setb_function")%>(DATA *data, threadData_t *threadData)
2385 {
2386 <%vars.dataReconSetBVars |> SIMVAR(name=name, type_=T_REAL()) hasindex i0 =>
2387 'data->simulationInfo->setbVars[<%i0%>] = <%cref(name, &sub)%>;'
2388 ;separator="\n"
2389 %>
2390
2391 return 0;
2392 }
2393 >>
2394 end match
2395 end functionSetB;
2396
2397 1204 template functionInitSample(list<BackendDAE.TimeEvent> timeEvents, String modelNamePrefix)
2398 "Generates function initSample() in simulation file."
2399 ::=
2400 let &varDecls = buffer ""
2401 let &varFrees = buffer ""
2402 let &auxFunction = buffer ""
2403 let body = (timeEvents |> timeEvent =>
2404 match timeEvent
2405 case SAMPLE_TIME_EVENT(__) then
2406 let &preExp = buffer ""
2407 let &sub = buffer ""
2408 let forHead = match iter
2409 case SOME(iter_) then (iter_ |> it =>
2410 forIterator(it, contextZeroCross, &preExp, &varDecls, &varFrees, &auxFunction, &sub)
2411 ;separator="\n";empty)
2412 else ""
2413 let forBody = match iter
2414 case SOME(iter_) then <<int tmp = <%(iter_ |> it =>
2415 forIteratorBody(it, contextZeroCross, &preExp, &varDecls, &varFrees, &auxFunction, &sub)
2416 ;separator = "")%>0<%(iter_ |> it => ")";separator = "")%>;>>
2417 else ""
2418 let forTail = match iter
2419 case SOME(iter_) then (iter_ |> it => "}";separator="\n";empty)
2420 else ""
2421 let e1 = daeExp(startExp, contextOther, &preExp, &varDecls, &varFrees, &auxFunction)
2422 let e2 = daeExp(intervalExp, contextOther, &preExp, &varDecls, &varFrees, &auxFunction)
2423 <<
2424 <%forHead%>
2425 <%preExp%>
2426 <%forBody%>
2427 /* sample <%index%> */
2428 data->modelData->samplesInfo[i].index = <%index%>;
2429 data->modelData->samplesInfo[i].start = <%e1%>;
2430 data->modelData->samplesInfo[i].interval = <%e2%> /* (max real for single time events) */;
2431 i++;
2432 <%forTail%>
2433 >>
2434 else '')
2435 let res = <<
2436 /* Initializes the raw time events of the simulation using the now
2437 calcualted parameters. */
2438 void <%symbolName(modelNamePrefix,"function_initSample")%>(DATA *data, threadData_t *threadData)
2439 {
2440 long i=0;
2441 <%varDecls%>
2442 <%body%>
2443 }
2444 >>
2445 <<
2446 <%auxFunction%>
2447 <%res%>
2448 >>
2449 end functionInitSample;
2450
2451
2452 ✗ template functionInitialMixedSystems(list<SimEqSystem> initialEquations, list<SimEqSystem> initialEquations_lambda0, list<SimEqSystem> parameterEquations, list<SimEqSystem> allEquations, list<JacobianMatrix> jacobianMatrices, String modelNamePrefix)
2453 "Generates functions in simulation file."
2454 ::=
2455 let initbody = functionInitialMixedSystemsTemp(initialEquations)
2456 let initbody_lambda0 = functionInitialMixedSystemsTemp(initialEquations_lambda0)
2457 let parambody = functionInitialMixedSystemsTemp(parameterEquations)
2458 let body = functionInitialMixedSystemsTemp(allEquations)
2459 let jacobianbody = ((jacobianMatrices |> JAC_MATRIX(columns=clst) => (clst |> JAC_COLUMN(columnEqns=cEqns) => functionInitialMixedSystemsTemp(cEqns);separator="\n") ;separator="\n"))
2460 <<
2461 /* funtion initialize mixed systems */
2462 void <%symbolName(modelNamePrefix,"initialMixedSystem")%>(int nMixedSystems, MIXED_SYSTEM_DATA* mixedSystemData)
2463 {
2464 /* initial mixed systems */
2465 <%initbody%>
2466 /* initial_lambda0 mixed systems */
2467 <%initbody_lambda0%>
2468 /* parameter mixed systems */
2469 <%parambody%>
2470 /* model mixed systems */
2471 <%body%>
2472 /* jacobians mixed systems */
2473 <%jacobianbody%>
2474 }
2475 >>
2476 end functionInitialMixedSystems;
2477
2478 ✗ template functionInitialMixedSystemsTemp(list<SimEqSystem> allEquations)
2479 "Generates functions in simulation file."
2480 ::=
2481 (allEquations |> eqn => (match eqn
2482 case eq as SES_MIXED(__) then
2483 let size = listLength(discVars)
2484 <<
2485 assertStreamPrint(NULL, nMixedSystems > <%indexMixedSystem%>, "Internal Error: nMixedSystems mismatch!");
2486 mixedSystemData[<%indexMixedSystem%>].equationIndex = <%index%>;
2487 mixedSystemData[<%indexMixedSystem%>].size = <%size%>;
2488 mixedSystemData[<%indexMixedSystem%>].solveContinuousPart = updateContinuousPart<%index%>;
2489 mixedSystemData[<%indexMixedSystem%>].updateIterationExps = updateIterationExpMixedSystem<%index%>;
2490 >>
2491 )
2492 ;separator="\n\n")
2493 end functionInitialMixedSystemsTemp;
2494
2495
2496 1204 template functionSetupMixedSystems(list<SimEqSystem> initialEquations, list<SimEqSystem> initialEquations_lambda0, list<SimEqSystem> parameterEquations, list<SimEqSystem> allEquations, list<JacobianMatrix> jacobianMatrices, Text &header, String modelNamePrefixStr)
2497 "Generates functions in simulation file."
2498 ::=
2499 let initbody = functionSetupMixedSystemsTemp(initialEquations, &header,modelNamePrefixStr)
2500 let initbody_lambda0 = functionSetupMixedSystemsTemp(initialEquations_lambda0, &header,modelNamePrefixStr)
2501 let parambody = functionSetupMixedSystemsTemp(parameterEquations,&header,modelNamePrefixStr)
2502 let body = functionSetupMixedSystemsTemp(allEquations,&header,modelNamePrefixStr)
2503 let jacobianbody = ((jacobianMatrices |> JAC_MATRIX(columns=clst) => (clst |> JAC_COLUMN(columnEqns=cEqns) => functionSetupMixedSystemsTemp(cEqns,&header,modelNamePrefixStr);separator="\n") ;separator="\n"))
2504 <<
2505 /* initial mixed systems */
2506 <%initbody%>
2507 /* initial_lambda0 mixed systems */
2508 <%initbody_lambda0%>
2509 /* parameter mixed systems */
2510 <%parambody%>
2511 /* model mixed systems */
2512 <%body%>
2513 /* jacobians mixed systems */
2514 <%jacobianbody%>
2515 >>
2516 end functionSetupMixedSystems;
2517
2518 8778 template functionSetupMixedSystemsTemp(list<SimEqSystem> allEquations, Text &header, String modelNamePrefixStr)
2519 "Generates functions in simulation file."
2520 ::=
2521 let &sub = buffer ""
2522 (allEquations |> eqn => (match eqn
2523 case eq as SES_MIXED(__) then
2524 let contEqsIndex = equationIndex(cont)
2525 let solvedContinuous =
2526 match cont
2527 // no dynamic tearing
2528 case SES_LINEAR(lSystem=ls as LINEARSYSTEM(__), alternativeTearing=NONE()) then
2529 'data->simulationInfo->linearSystemData[<%ls.indexLinearSystem%>].solved'
2530 case SES_NONLINEAR(nlSystem=nls as NONLINEARSYSTEM(__), alternativeTearing=NONE()) then
2531 'data->simulationInfo->nonlinearSystemData[<%nls.indexNonLinearSystem%>].solved'
2532 // dynamic tearing
2533 case SES_LINEAR(lSystem=ls as LINEARSYSTEM(__), alternativeTearing = SOME(at as LINEARSYSTEM(__))) then
2534 <<
2535 data->simulationInfo->linearSystemData[<%ls.indexLinearSystem%>].solved'
2536 data->simulationInfo->linearSystemData[<%at.indexLinearSystem%>].solved'
2537 >>
2538 case SES_NONLINEAR(nlSystem=nls as NONLINEARSYSTEM(__), alternativeTearing = SOME(at as NONLINEARSYSTEM(__))) then
2539 <<
2540 data->simulationInfo->nonlinearSystemData[<%nls.indexNonLinearSystem%>].solved
2541 data->simulationInfo->nonlinearSystemData[<%at.indexNonLinearSystem%>].solved
2542 >>
2543 let &preDisc = buffer ""
2544 let &varDecls = buffer ""
2545 let &varFrees = buffer ""
2546 let &auxFunction = buffer ""
2547 let discExp = (discEqs |> SES_SIMPLE_ASSIGN(__) hasindex i0 =>
2548 let expPart = daeExp(exp, contextSimulationDiscrete, &preDisc, &varDecls, &varFrees, &auxFunction)
2549 <<
2550 <%cref(cref, &sub)%> = <%expPart%>;
2551 >>
2552 ;separator="\n")
2553 let &header += 'void updateContinuousPart<%index%>(DATA* data);<%\n%>void updateIterationExpMixedSystem<%index%>(DATA* data);<%\n%>'
2554 <<
2555 <%auxFunction%>
2556 void updateContinuousPart<%index%>(DATA* data)
2557 {
2558 <%symbolName(modelNamePrefixStr,"eqFunction")%>_<%contEqsIndex%>(data, threadData);
2559 data->simulationInfo->mixedSystemData[<%indexMixedSystem%>].continuous_solution = <%solvedContinuous%>;
2560 }
2561
2562 void updateIterationExpMixedSystem<%index%>(DATA* data)
2563 {
2564 <%varDecls%>
2565
2566 <%preDisc%>
2567 <%discExp%>
2568 }
2569 >>
2570 )
2571 ;separator="\n\n")
2572 end functionSetupMixedSystemsTemp;
2573
2574
2575 223 template functionInitialLinearSystems(list<SimEqSystem> linearSystems, String modelNamePrefix)
2576 "Generates functions in simulation file."
2577 ::=
2578 let &tempeqns = buffer ""
2579 let &tempeqns += (linearSystems |> eq as SES_LINEAR(alternativeTearing = SOME(__)) => 'int <%symbolName(modelNamePrefix,"eqFunction")%>_<%equationIndex(eq)%>(DATA* data, threadData_t* threadData);' ; separator = "\n")
2580 let &globalConstraintsFunctions = buffer ""
2581 let linearbody = functionInitialLinearSystemsTemp(linearSystems, modelNamePrefix, &globalConstraintsFunctions)
2582 <<
2583 /* Prototypes for the strict sets (Dynamic Tearing) */
2584 <%tempeqns%>
2585
2586 /* Global constraints for the casual sets */
2587 <%globalConstraintsFunctions%>
2588 /* function initialize linear systems */
2589 void <%symbolName(modelNamePrefix,"initialLinearSystem")%>(int nLinearSystems, LINEAR_SYSTEM_DATA* linearSystemData)
2590 {
2591 /* linear systems */
2592 <%linearbody%>
2593 }
2594 >>
2595 end functionInitialLinearSystems;
2596
2597 223 template functionInitialLinearSystemsTemp(list<SimEqSystem> linearSystems, String modelNamePrefix, Text &globalConstraintsFunctions)
2598 "Generates functions in simulation file."
2599 ::=
2600 (linearSystems |> eqn => (match eqn
2601 // Mixed system
2602 case eq as SES_MIXED(__) then functionInitialLinearSystemsTemp(fill(eq.cont,1), modelNamePrefix, "")
2603
2604 // No dynamic tearing
2605 case eq as SES_LINEAR(lSystem=ls as LINEARSYSTEM(__), alternativeTearing=NONE()) then
2606 match ls.jacobianMatrix
2607 case NONE() then
2608 <<
2609 assertStreamPrint(NULL, nLinearSystems > <%ls.indexLinearSystem%>, "Internal Error: nLinearSystems mismatch!");
2610 linearSystemData[<%ls.indexLinearSystem%>].equationIndex = <%ls.index%>;
2611 linearSystemData[<%ls.indexLinearSystem%>].size = <%listLength(ls.vars)%>;
2612 linearSystemData[<%ls.indexLinearSystem%>].nnz = <%listLength(ls.simJac)%>;
2613 linearSystemData[<%ls.indexLinearSystem%>].matrixFormat = <%linearSystemMatrixFormat(ls)%>;
2614 linearSystemData[<%ls.indexLinearSystem%>].method = 0; /* No symbolic Jacobian available */
2615 linearSystemData[<%ls.indexLinearSystem%>].strictTearingFunctionCall = NULL;
2616 linearSystemData[<%ls.indexLinearSystem%>].setA = setLinearMatrixA<%ls.index%>;
2617 linearSystemData[<%ls.indexLinearSystem%>].setb = setLinearVectorb<%ls.index%>;
2618 linearSystemData[<%ls.indexLinearSystem%>].initializeStaticLSData = initializeStaticLSData<%ls.index%>;
2619 >>
2620 case SOME(JAC_MATRIX(matrixName=name, jacobianIndex=jacIndex)) then
2621 <<
2622 assertStreamPrint(NULL, nLinearSystems > <%ls.indexLinearSystem%>, "Internal Error: indexlinearSystem mismatch!");
2623 linearSystemData[<%ls.indexLinearSystem%>].equationIndex = <%ls.index%>;
2624 linearSystemData[<%ls.indexLinearSystem%>].size = <%listLength(ls.vars)%>;
2625 linearSystemData[<%ls.indexLinearSystem%>].nnz = <%listLength(ls.simJac)%>;
2626 linearSystemData[<%ls.indexLinearSystem%>].matrixFormat = <%linearSystemMatrixFormat(ls)%>;
2627 linearSystemData[<%ls.indexLinearSystem%>].method = 1; /* Symbolic Jacobian available */
2628 linearSystemData[<%ls.indexLinearSystem%>].residualFunc = residualFunc<%ls.index%>;
2629 linearSystemData[<%ls.indexLinearSystem%>].strictTearingFunctionCall = NULL;
2630 linearSystemData[<%ls.indexLinearSystem%>].analyticalJacobianColumn = <%symbolName(modelNamePrefix,"functionJac")%><%name%>_column;
2631 linearSystemData[<%ls.indexLinearSystem%>].initialAnalyticalJacobian = <%symbolName(modelNamePrefix,"initialAnalyticJacobian")%><%name%>;
2632 linearSystemData[<%ls.indexLinearSystem%>].jacobianIndex = <%jacIndex%> /*jacInx*/;
2633 linearSystemData[<%ls.indexLinearSystem%>].setA = NULL; //setLinearMatrixA<%ls.index%>;
2634 linearSystemData[<%ls.indexLinearSystem%>].setb = NULL; //setLinearVectorb<%ls.index%>;
2635 linearSystemData[<%ls.indexLinearSystem%>].initializeStaticLSData = initializeStaticLSData<%ls.index%>;
2636 >>
2637 else
2638 error(sourceInfo(), ' No jacobian create for linear system <%ls.index%>.')
2639 end match
2640
2641 // Dynamic tearing
2642 case eq as SES_LINEAR(lSystem=ls as LINEARSYSTEM(__), alternativeTearing = SOME(at as LINEARSYSTEM(__))) then
2643 let &globalConstraintsFunctions += createGlobalConstraintsFunction(eq)
2644 match ls.jacobianMatrix
2645 case NONE() then
2646 <<
2647 assertStreamPrint(NULL, nLinearSystems > <%ls.indexLinearSystem%>, "Internal Error: nLinearSystems mismatch!");
2648 linearSystemData[<%ls.indexLinearSystem%>].equationIndex = <%ls.index%>;
2649 linearSystemData[<%ls.indexLinearSystem%>].size = <%listLength(ls.vars)%>;
2650 linearSystemData[<%ls.indexLinearSystem%>].nnz = <%listLength(ls.simJac)%>;
2651 linearSystemData[<%ls.indexLinearSystem%>].matrixFormat = <%linearSystemMatrixFormat(ls)%>;
2652 linearSystemData[<%ls.indexLinearSystem%>].method = 0; /* No symbolic Jacobian available */
2653 linearSystemData[<%ls.indexLinearSystem%>].strictTearingFunctionCall = NULL;
2654 linearSystemData[<%ls.indexLinearSystem%>].setA = setLinearMatrixA<%ls.index%>;
2655 linearSystemData[<%ls.indexLinearSystem%>].setb = setLinearVectorb<%ls.index%>;
2656 linearSystemData[<%ls.indexLinearSystem%>].initializeStaticLSData = initializeStaticLSData<%ls.index%>;
2657
2658 assertStreamPrint(NULL, nLinearSystems > <%at.indexLinearSystem%>, "Internal Error: nLinearSystems mismatch!");
2659 linearSystemData[<%at.indexLinearSystem%>].equationIndex = <%at.index%>;
2660 linearSystemData[<%at.indexLinearSystem%>].size = <%listLength(at.vars)%>;
2661 linearSystemData[<%at.indexLinearSystem%>].nnz = <%listLength(at.simJac)%>;
2662 linearSystemData[<%at.indexLinearSystem%>].matrixFormat = <%linearSystemMatrixFormat(at)%>;
2663 linearSystemData[<%at.indexLinearSystem%>].method = 0; /* No symbolic Jacobian available */
2664 linearSystemData[<%at.indexLinearSystem%>].strictTearingFunctionCall = <%symbolName(modelNamePrefix,"eqFunction")%>_<%ls.index%>;
2665 linearSystemData[<%at.indexLinearSystem%>].setA = setLinearMatrixA<%at.index%>;
2666 linearSystemData[<%at.indexLinearSystem%>].setb = setLinearVectorb<%at.index%>;
2667 linearSystemData[<%at.indexLinearSystem%>].initializeStaticLSData = initializeStaticLSData<%at.index%>;
2668 linearSystemData[<%at.indexLinearSystem%>].checkConstraints = checkConstraints<%at.index%>;
2669 >>
2670 case SOME(JAC_MATRIX(matrixName=name, jacobianIndex=jacIndex)) then
2671 let generatedJac2 = match at.jacobianMatrix case SOME(JAC_MATRIX(matrixName=name)) then '<%symbolName(modelNamePrefix,"functionJac")%><%name%>_column' case NONE() then 'NULL'
2672 let initialJac2 = match at.jacobianMatrix case SOME(JAC_MATRIX(matrixName=name))then '<%symbolName(modelNamePrefix,"initialAnalyticJacobian")%><%name%>' case NONE() then 'NULL'
2673 let jacIndex2 = match at.jacobianMatrix case SOME(JAC_MATRIX(jacobianIndex=jacindex)) then '<%jacindex%>' case NONE() then '-1'
2674 <<
2675 assertStreamPrint(NULL, nLinearSystems > <%ls.indexLinearSystem%>, "Internal Error: indexlinearSystem mismatch!");
2676 linearSystemData[<%ls.indexLinearSystem%>].equationIndex = <%ls.index%>;
2677 linearSystemData[<%ls.indexLinearSystem%>].size = <%listLength(ls.vars)%>;
2678 linearSystemData[<%ls.indexLinearSystem%>].nnz = <%listLength(ls.simJac)%>;
2679 linearSystemData[<%ls.indexLinearSystem%>].matrixFormat = <%linearSystemMatrixFormat(ls)%>;
2680 linearSystemData[<%ls.indexLinearSystem%>].method = 1; /* Symbolic Jacobian available */
2681 linearSystemData[<%ls.indexLinearSystem%>].residualFunc = residualFunc<%ls.index%>;
2682 linearSystemData[<%ls.indexLinearSystem%>].strictTearingFunctionCall = NULL;
2683 linearSystemData[<%ls.indexLinearSystem%>].analyticalJacobianColumn = <%symbolName(modelNamePrefix,"functionJac")%><%name%>_column;
2684 linearSystemData[<%ls.indexLinearSystem%>].initialAnalyticalJacobian = <%symbolName(modelNamePrefix,"initialAnalyticJacobian")%><%name%>;
2685 linearSystemData[<%ls.indexLinearSystem%>].jacobianIndex = <%jacIndex%>;
2686 linearSystemData[<%ls.indexLinearSystem%>].setA = NULL; //setLinearMatrixA<%ls.index%>;
2687 linearSystemData[<%ls.indexLinearSystem%>].setb = NULL; //setLinearVectorb<%ls.index%>;
2688 linearSystemData[<%ls.indexLinearSystem%>].initializeStaticLSData = initializeStaticLSData<%ls.index%>;
2689
2690 assertStreamPrint(NULL, nLinearSystems > <%at.indexLinearSystem%>, "Internal Error: indexlinearSystem mismatch!");
2691 linearSystemData[<%at.indexLinearSystem%>].equationIndex = <%at.index%>;
2692 linearSystemData[<%at.indexLinearSystem%>].size = <%listLength(at.vars)%>;
2693 linearSystemData[<%at.indexLinearSystem%>].nnz = <%listLength(at.simJac)%>;
2694 linearSystemData[<%at.indexLinearSystem%>].matrixFormat = <%linearSystemMatrixFormat(at)%>;
2695 linearSystemData[<%at.indexLinearSystem%>].method = 1; /* Symbolic Jacobian available */
2696 linearSystemData[<%at.indexLinearSystem%>].residualFunc = residualFunc<%at.index%>;
2697 linearSystemData[<%at.indexLinearSystem%>].strictTearingFunctionCall = <%symbolName(modelNamePrefix,"eqFunction")%>_<%ls.index%>;
2698 linearSystemData[<%at.indexLinearSystem%>].analyticalJacobianColumn = <%generatedJac2%>;
2699 linearSystemData[<%at.indexLinearSystem%>].initialAnalyticalJacobian = <%initialJac2%>;
2700 linearSystemData[<%at.indexLinearSystem%>].jacobianIndex = <%jacIndex2%>;
2701 linearSystemData[<%at.indexLinearSystem%>].setA = NULL; //setLinearMatrixA<%at.index%>;
2702 linearSystemData[<%at.indexLinearSystem%>].setb = NULL; //setLinearVectorb<%at.index%>;
2703 linearSystemData[<%at.indexLinearSystem%>].initializeStaticLSData = initializeStaticLSData<%at.index%>;
2704 linearSystemData[<%at.indexLinearSystem%>].checkConstraints = checkConstraints<%at.index%>;
2705 >>
2706
2707 // Error case
2708 else
2709 error(sourceInfo(), ' No jacobian create for linear system <%ls.index%> or <%at.index%>.')
2710 end match
2711 )
2712 ;separator="\n\n")
2713 end functionInitialLinearSystemsTemp;
2714
2715 1204 template functionSetupLinearSystems(list<SimEqSystem> linearSystems, String modelNamePrefix)
2716 "Generates functions in simulation file."
2717 ::=
2718 let &sub = buffer ""
2719 (linearSystems |> eqn => (match eqn
2720 case eq as SES_MIXED(__) then functionSetupLinearSystems(fill(eq.cont,1), modelNamePrefix)
2721 // no dynamic tearing
2722 case eq as SES_LINEAR(lSystem=ls as LINEARSYSTEM(__), alternativeTearing=NONE()) then
2723 match ls.jacobianMatrix
2724 case SOME(__) then
2725 let &varDeclsRes = buffer "" /*BUFD*/
2726 let &varFreesRes = buffer ""
2727 let &auxFunction = buffer ""
2728 let &tmp = buffer ""
2729 let xlocs = (ls.vars |> var as SIMVAR() hasindex i0 => '<%cref(name, &sub)%> = xloc[<%i0%>];' ;separator="\n")
2730 let prebody = (match ls.partOfJac
2731 case true then
2732 (ls.residual |> eq2 =>
2733 functionExtraResidualsPreBodyJacobian(eq2, &tmp, modelNamePrefix)
2734 ;separator="\n")
2735 case false then
2736 (ls.residual |> eq2 =>
2737 functionExtraResidualsPreBody(eq2, &tmp, modelNamePrefix)
2738 ;separator="\n")
2739 end match)
2740 let body = (ls.residual |> eq2 hasindex i0 => match eq2
2741 case SES_RESIDUAL(__) then equationResidual(exp, varDeclsRes, varFreesRes, auxFunction, index, res_index)
2742 case SES_FOR_RESIDUAL(__) then "case 1"
2743 ;separator="\n")
2744 let eqnbody =
2745 <<
2746 <% if profileSome() then 'SIM_PROF_ADD_NCALL_EQ(modelInfoGetEquation(&data->modelData->modelDataXml,<%ls.index%>).profileBlockIndex,1);' %>
2747 <%xlocs%>
2748 <%prebody%>
2749 <%body%>
2750 >>
2751 <<
2752 <%auxFunction%>
2753 <%tmp%>
2754
2755 void residualFunc<%ls.index%>(RESIDUAL_USERDATA* userData, const double* xloc, double* res, const int* iflag)
2756 {
2757 DATA *data = userData->data;
2758 threadData_t *threadData = userData->threadData;
2759 const int equationIndexes[2] = {1,<%ls.index%>};
2760 <% if ls.partOfJac then
2761 'JACOBIAN* parentJacobian = data->simulationInfo->linearSystemData[<%ls.indexLinearSystem%>].parentJacobian;'
2762 %>
2763 JACOBIAN* jacobian = NULL;
2764 <%varDeclsRes%>
2765 <%equation_withProfile(ls.index, eqnbody)%>
2766 _return: OMC_LABEL_UNUSED ;
2767 <%varFreesRes%>
2768 }
2769 OMC_DISABLE_OPT
2770 <%initializeStaticLSVars(ls.vars, ls.index)%>
2771 >>
2772 else
2773 let &varDecls = buffer "" /*BUFD*/
2774 let &varFrees = buffer ""
2775 let &auxFunction = buffer ""
2776 let MatrixA = (ls.simJac |> (row, col, eq) hasindex i0 => match eq
2777 case SES_RESIDUAL(__) then
2778 let &preExp = buffer "" /*BUFD*/
2779 let expPart = daeExp(exp, contextSimulationDiscrete, &preExp, &varDecls, &varFrees, &auxFunction)
2780 '<%preExp%>linearSystemData->setAElement(<%row%>, <%col%>, <%expPart%>, <%i0%>, linearSystemData, threadData);'
2781 case SES_FOR_RESIDUAL(__) then "case 2"
2782 ;separator="\n")
2783
2784 let &varDecls2 = buffer "" /*BUFD*/
2785 let &varFrees2 = buffer ""
2786 let vectorb = (ls.beqs |> exp hasindex i0 =>
2787 let &preExp = buffer "" /*BUFD*/
2788 let expPart = daeExp(exp, contextSimulationDiscrete, &preExp, &varDecls2, &varFrees2, &auxFunction)
2789 '<%preExp%>linearSystemData->setBElement(<%i0%>, <%expPart%>, linearSystemData, threadData);'
2790 ;separator="\n")
2791 <<
2792 <%auxFunction%>
2793 OMC_DISABLE_OPT
2794 void setLinearMatrixA<%ls.index%>(DATA* data, threadData_t* threadData, LINEAR_SYSTEM_DATA* linearSystemData)
2795 {
2796 const int equationIndexes[2] = {1,<%ls.index%>};
2797 <% if ls.partOfJac then 'JACOBIAN* parentJacobian = linearSystemData->parentJacobian;'%>
2798 <%varDecls%>
2799 <%equation_withProfile(ls.index, MatrixA)%>
2800 _return: OMC_LABEL_UNUSED ;
2801 <%varFrees%>
2802 }
2803 OMC_DISABLE_OPT
2804 void setLinearVectorb<%ls.index%>(DATA* data, threadData_t* threadData, LINEAR_SYSTEM_DATA* linearSystemData)
2805 {
2806 const int equationIndexes[2] = {1,<%ls.index%>};
2807 <% if ls.partOfJac then 'JACOBIAN* parentJacobian = linearSystemData->parentJacobian;'%>
2808 <%varDecls2%>
2809 <%equation_withProfile(ls.index, vectorb)%>
2810 _return: OMC_LABEL_UNUSED ;
2811 <%varFrees2%>
2812 }
2813 OMC_DISABLE_OPT
2814 <%initializeStaticLSVars(ls.vars, ls.index)%>
2815 >>
2816 end match
2817
2818 // dynamic tearing
2819 case eq as SES_LINEAR(lSystem=ls as LINEARSYSTEM(__), alternativeTearing = SOME(at as LINEARSYSTEM(__))) then
2820 match ls.jacobianMatrix
2821 case SOME(__) then
2822 // for strict tearing set
2823 let &sub = buffer ""
2824 let &varDeclsRes = buffer "" /*BUFD*/
2825 let &varFreesRes = buffer ""
2826 let &auxFunction = buffer ""
2827 let &tmp = buffer ""
2828 let xlocs = (ls.vars |> var as SIMVAR() hasindex i0 => '<%cref(var.name, &sub)%> = xloc[<%i0%>];' ;separator="\n")
2829 let prebody = (ls.residual |> eq2 =>
2830 functionExtraResidualsPreBody(eq2, &tmp, modelNamePrefix)
2831 ;separator="\n")
2832 let body = (ls.residual |> eq2 hasindex i0 => match eq2
2833 case SES_RESIDUAL(__) then equationResidual(exp, varDeclsRes, varFreesRes, auxFunction, index, res_index)
2834 case SES_FOR_RESIDUAL(__) then "case 3"
2835 ;separator="\n")
2836 // for casual tearing set
2837 let &varDeclsRes2 = buffer "" /*BUFD*/
2838 let &varFreesRes2 = buffer ""
2839 let &auxFunction2 = buffer ""
2840 let &tmp2 = buffer ""
2841 let xlocs2 = (at.vars |> var as SIMVAR() hasindex i0 => '<%cref(var.name, &sub)%> = xloc[<%i0%>];' ;separator="\n")
2842 let prebody2 = (at.residual |> eq2 =>
2843 functionExtraResidualsPreBody(eq2, &tmp2, modelNamePrefix)
2844 ;separator="\n")
2845 let body2 = (at.residual |> eq2 hasindex i0 => match eq2
2846 case SES_RESIDUAL(__) then equationResidual(exp, varDeclsRes2, varFreesRes2, auxFunction2, index, res_index)
2847 case SES_FOR_RESIDUAL(__) then "case 4"
2848 ;separator="\n")
2849 <<
2850 <%auxFunction%>
2851 <%tmp%>
2852
2853 void residualFunc<%ls.index%>(RESIDUAL_USERDATA* userData, const double* xloc, double* res, const int* iflag)
2854 {
2855 DATA *data = userData->data;
2856 threadData_t *threadData = userData->threadData;
2857 const int equationIndexes[2] = {1,<%ls.index%>};
2858 <% if ls.partOfJac then
2859 'JACOBIAN* parentJacobian = data->simulationInfo->linearSystemData[<%ls.indexLinearSystem%>].parentJacobian;'
2860 %>
2861 JACOBIAN* jacobian = NULL;
2862 <%varDeclsRes%>
2863 <% if profileAll() then 'SIM_PROF_TICK_EQ(<%ls.index%>);' %>
2864 <% if profileSome() then 'SIM_PROF_ADD_NCALL_EQ(modelInfoGetEquation(&data->modelData->modelDataXml,<%ls.index%>).profileBlockIndex,1);' %>
2865 <%xlocs%>
2866 <%prebody%>
2867 <%body%>
2868 <% if profileAll() then 'SIM_PROF_ACC_EQ(<%ls.index%>);' %>
2869 threadData->lastEquationSolved = <%ls.index%>;
2870 _return: OMC_LABEL_UNUSED ;
2871 <%varFreesRes%>
2872 }
2873 OMC_DISABLE_OPT
2874 <%initializeStaticLSVars(ls.vars, ls.index)%>
2875
2876 <%auxFunction2%>
2877 <%tmp2%>
2878
2879 void residualFunc<%at.index%>(RESIDUAL_USERDATA* userData, const double* xloc, double* res, const int* iflag)
2880 {
2881 DATA *data = userData->data;
2882 threadData_t *threadData = userData->threadData;
2883 const int equationIndexes[2] = {1,<%at.index%>};
2884 <% if ls.partOfJac then
2885 'JACOBIAN* parentJacobian = data->simulationInfo->linearSystemData[<%ls.indexLinearSystem%>].parentJacobian;'
2886 %>
2887 JACOBIAN* jacobian = NULL;
2888 <%varDeclsRes2%>
2889 <% if profileAll() then 'SIM_PROF_TICK_EQ(<%at.index%>);' %>
2890 <% if profileSome() then 'SIM_PROF_ADD_NCALL_EQ(modelInfoGetEquation(&data->modelData->modelDataXml,<%at.index%>).profileBlockIndex,1);' %>
2891 <%xlocs2%>
2892 <%prebody2%>
2893 <%body2%>
2894 <% if profileAll() then 'SIM_PROF_ACC_EQ(<%at.index%>);' %>
2895 threadData->lastEquationSolved = <%at.index%>;
2896 _return: OMC_LABEL_UNUSED ;
2897 <%varFreesRes2%>
2898 }
2899 OMC_DISABLE_OPT
2900 <%initializeStaticLSVars(at.vars, at.index)%>
2901 >>
2902 else
2903 // for strict tearing set
2904 let &varDecls = buffer "" /*BUFD*/
2905 let &varFrees = buffer ""
2906 let &auxFunction = buffer ""
2907 let MatrixA = (ls.simJac |> (row, col, eq) hasindex i0 => match eq
2908 case SES_RESIDUAL(__) then
2909 let &preExp = buffer "" /*BUFD*/
2910 let expPart = daeExp(exp, contextSimulationDiscrete, &preExp, &varDecls, &varFrees, &auxFunction)
2911 '<%preExp%>linearSystemData->setAElement(<%row%>, <%col%>, <%expPart%>, <%i0%>, linearSystemData, threadData);'
2912 case SES_FOR_RESIDUAL(__) then "case 5"
2913 ;separator="\n")
2914
2915 let &varDecls2 = buffer "" /*BUFD*/
2916 let &varFrees2 = buffer ""
2917 let vectorb = (ls.beqs |> exp hasindex i0 =>
2918 let &preExp = buffer "" /*BUFD*/
2919 let expPart = daeExp(exp, contextSimulationDiscrete, &preExp, &varDecls2, &varFrees2, &auxFunction)
2920 '<%preExp%>linearSystemData->setBElement(<%i0%>, <%expPart%>, linearSystemData, threadData);'
2921 ;separator="\n")
2922 // for casual tearing set
2923 let &varDecls3 = buffer "" /*BUFD*/
2924 let &varFrees3 = buffer ""
2925 let &auxFunction2 = buffer ""
2926 let MatrixA2 = (at.simJac |> (row, col, eq) hasindex i0 => match eq
2927 case SES_RESIDUAL(__) then
2928 let &preExp3 = buffer "" /*BUFD*/
2929 let expPart3 = daeExp(exp, contextSimulationDiscrete, &preExp3, &varDecls3, &varFrees3, &auxFunction2)
2930 '<%preExp3%>linearSystemData->setAElement(<%row%>, <%col%>, <%expPart3%>, <%i0%>, linearSystemData, threadData);'
2931 case SES_FOR_RESIDUAL(__) then "case 6"
2932 ;separator="\n")
2933
2934 let &varDecls4 = buffer "" /*BUFD*/
2935 let &varFrees4 = buffer ""
2936 let vectorb2 = (at.beqs |> exp hasindex i0 =>
2937 let &preExp4 = buffer "" /*BUFD*/
2938 let expPart4 = daeExp(exp, contextSimulationDiscrete, &preExp4, &varDecls4, &varFrees4, &auxFunction2)
2939 '<%preExp4%>linearSystemData->setBElement(<%i0%>, <%expPart4%>, linearSystemData, threadData);'
2940 ;separator="\n")
2941 <<
2942 <%auxFunction%>
2943 OMC_DISABLE_OPT
2944 void setLinearMatrixA<%ls.index%>(DATA* data, LINEAR_SYSTEM_DATA *linearSystemData)
2945 {
2946 const int equationIndexes[2] = {1,<%ls.index%>};
2947 <% if ls.partOfJac then 'JACOBIAN* parentJacobian = linearSystemData->parentJacobian;'%>
2948 <%varDecls%>
2949 <%MatrixA%>
2950 _return: OMC_LABEL_UNUSED ;
2951 <%varFrees%>
2952 }
2953 OMC_DISABLE_OPT
2954 void setLinearVectorb<%ls.index%>(DATA* data, LINEAR_SYSTEM_DATA* linearSystemData)
2955 {
2956 const int equationIndexes[2] = {1,<%ls.index%>};
2957 <% if ls.partOfJac then 'JACOBIAN* parentJacobian = linearSystemData->parentJacobian;'%>
2958 <%varDecls2%>
2959 <%vectorb%>
2960 _return: OMC_LABEL_UNUSED ;
2961 <%varFrees2%>
2962 }
2963 OMC_DISABLE_OPT
2964 <%initializeStaticLSVars(ls.vars, ls.index)%>
2965
2966 <%auxFunction2%>
2967 OMC_DISABLE_OPT
2968 void setLinearMatrixA<%at.index%>(DATA* data, LINEAR_SYSTEM_DATA* linearSystemData)
2969 {
2970 const int equationIndexes[2] = {1,<%at.index%>};
2971 <% if ls.partOfJac then 'JACOBIAN* parentJacobian = linearSystemData->parentJacobian;'%>
2972 <%varDecls3%>
2973 <%MatrixA2%>
2974 _return: OMC_LABEL_UNUSED ;
2975 <%varFrees3%>
2976 }
2977 OMC_DISABLE_OPT
2978 void setLinearVectorb<%at.index%>(DATA* data, LINEAR_SYSTEM_DATA* linearSystemData)
2979 {
2980 const int equationIndexes[2] = {1,<%at.index%>};
2981 <% if ls.partOfJac then 'JACOBIAN* parentJacobian = linearSystemData->parentJacobian;'%>
2982 <%varDecls4%>
2983 <%vectorb2%>
2984 _return: OMC_LABEL_UNUSED ;
2985 <%varFrees4%>
2986 }
2987 OMC_DISABLE_OPT
2988 <%initializeStaticLSVars(at.vars, at.index)%>
2989 >>
2990 end match
2991 )
2992 ;separator="\n\n")
2993 end functionSetupLinearSystems;
2994
2995 248 template functionInitialNonLinearSystems(list<SimEqSystem> nonlinearSystems, String modelNamePrefix)
2996 "Generates functions in simulation file."
2997 ::=
2998 let &tempeqns = buffer ""
2999 let &tempeqns += (nonlinearSystems |> eq as SES_NONLINEAR(alternativeTearing = SOME(__)) => 'int <%symbolName(modelNamePrefix,"eqFunction")%>_<%equationIndex(eq)%>(DATA* data, threadData_t* threadData);' ; separator = "\n")
3000 let &globalConstraintsFunctions = buffer ""
3001 let nlsbody = functionInitialNonLinearSystemsTemp(nonlinearSystems, modelNamePrefix, &globalConstraintsFunctions)
3002 <<
3003 /* Prototypes for the strict sets (Dynamic Tearing) */
3004 <%tempeqns%>
3005
3006 /* Global constraints for the casual sets */
3007 <%globalConstraintsFunctions%>
3008 /* function initialize non-linear systems */
3009 void <%symbolName(modelNamePrefix,"initialNonLinearSystem")%>(int nNonLinearSystems, NONLINEAR_SYSTEM_DATA* nonLinearSystemData)
3010 {
3011 <%nlsbody%>
3012 }
3013 >>
3014 end functionInitialNonLinearSystems;
3015
3016 1349 template functionInitialNonLinearSystemsTemp(list<SimEqSystem> nonlinearSystems, String modelPrefixName, Text &globalConstraintsFunctions)
3017 "Generates functions in simulation file."
3018 ::=
3019 (nonlinearSystems |> eqn => (match eqn
3020 case eq as SES_MIXED(__) then functionInitialNonLinearSystemsTemp(fill(eq.cont,1), modelPrefixName, &globalConstraintsFunctions)
3021 // no dynamic tearing
3022 case eq as SES_NONLINEAR(nlSystem=nls as NONLINEARSYSTEM(__), alternativeTearing=NONE()) then
3023 let system = generateNonLinearSystemData(nls, 0, modelPrefixName)
3024 <<
3025 <%system%>
3026 >>
3027 // dynamic tearing
3028 case eq as SES_NONLINEAR(nlSystem=nls as NONLINEARSYSTEM(__), alternativeTearing = SOME(at as NONLINEARSYSTEM(__))) then
3029 let system = generateNonLinearSystemData(nls, 0, modelPrefixName)
3030 let systemCasual = generateNonLinearSystemData(at, nls.index, modelPrefixName)
3031 let &globalConstraintsFunctions += createGlobalConstraintsFunction(eq)
3032 <<
3033 <%system%>
3034 <%systemCasual%>
3035 >>
3036 )
3037 ;separator="\n\n")
3038 end functionInitialNonLinearSystemsTemp;
3039
3040 1101 template generateNonLinearSystemData(NonlinearSystem system, Integer indexStrict, String modelPrefixName)
3041 "Generates nonlinear system data.
3042 indexStrict = 0: no dynamic tearing or strict set,
3043 else: casual set and indexStrict is the index of the corresponding strict set"
3044 ::=
3045 match system
3046 case nls as NONLINEARSYSTEM(__) then
3047 let size = listLength(nls.crefs)
3048 let generatedJac = match nls.jacobianMatrix case SOME(JAC_MATRIX(columns={})) then 'NULL' case SOME(JAC_MATRIX(matrixName=name)) then '<%symbolName(modelPrefixName,"functionJac")%><%name%>_column' case NONE() then 'NULL'
3049 let initialJac = match nls.jacobianMatrix
3050 case SOME(JAC_MATRIX(columns={})) then 'NULL'
3051 case SOME(JAC_MATRIX(matrixName=name, sparsityMatrix=SPARSITY())) then '<%symbolName(modelPrefixName,"initialResizableAnalyticJacobian")%><%name%>'
3052 case SOME(JAC_MATRIX(matrixName=name)) then '<%symbolName(modelPrefixName,"initialAnalyticJacobian")%><%name%>'
3053 case NONE() then 'NULL'
3054 let jacIndex = match nls.jacobianMatrix case SOME(JAC_MATRIX(columns={})) then '-1' case SOME(JAC_MATRIX(jacobianIndex=jacindex)) then '<%jacindex%> /*jacInx*/' case NONE() then '-1'
3055 let innerSystems = functionInitialNonLinearSystemsTemp(nls.eqs, modelPrefixName, "")
3056 let casualCall = if not intEq(indexStrict, 0) then '<%symbolName(modelPrefixName,"eqFunction")%>_<%indexStrict%>' else 'NULL'
3057 let constraintsCall = if not intEq(indexStrict, 0) then 'checkConstraints<%nls.index%>' else 'NULL'
3058 let residualCall = if intEq(indexStrict, 0) then
3059 'nonLinearSystemData[<%nls.indexNonLinearSystem%>].residualFunc = residualFunc<%nls.index%>;'
3060 else
3061 'nonLinearSystemData[<%nls.indexNonLinearSystem%>].residualFuncConstraints = residualFuncConstraints<%nls.index%>;'
3062 <<
3063 <%innerSystems%>
3064
3065 nonLinearSystemData[<%nls.indexNonLinearSystem%>].equationIndex = <%nls.index%>;
3066 nonLinearSystemData[<%nls.indexNonLinearSystem%>].size = <%size%>;
3067 nonLinearSystemData[<%nls.indexNonLinearSystem%>].matrixFormat = <%nonlinearSystemMatrixFormat(nls)%>;
3068 nonLinearSystemData[<%nls.indexNonLinearSystem%>].homotopySupport = <%boolStrC(nls.homotopySupport)%>;
3069 nonLinearSystemData[<%nls.indexNonLinearSystem%>].mixedSystem = <%boolStrC(nls.mixedSystem)%>;
3070 <%residualCall%>
3071 nonLinearSystemData[<%nls.indexNonLinearSystem%>].strictTearingFunctionCall = <%casualCall%>;
3072 nonLinearSystemData[<%nls.indexNonLinearSystem%>].analyticalJacobianColumn = <%generatedJac%>;
3073 nonLinearSystemData[<%nls.indexNonLinearSystem%>].initialAnalyticalJacobian = <%initialJac%>;
3074 nonLinearSystemData[<%nls.indexNonLinearSystem%>].jacobianIndex = <%jacIndex%>;
3075 nonLinearSystemData[<%nls.indexNonLinearSystem%>].initializeStaticNLSData = initializeStaticDataNLS<%nls.index%>;
3076 nonLinearSystemData[<%nls.indexNonLinearSystem%>].freeStaticNLSData = freeStaticDataNLS<%nls.index%>;
3077 nonLinearSystemData[<%nls.indexNonLinearSystem%>].getIterationVars = getIterationVarsNLS<%nls.index%>;
3078 nonLinearSystemData[<%nls.indexNonLinearSystem%>].checkConstraints = <%constraintsCall%>;
3079 nonLinearSystemData[<%nls.indexNonLinearSystem%>].updateSize = <%if nlsResizable(nls.crefs) then 'updateSizeNLS<%nls.index%>' else 'NULL'%>;
3080
3081 const int tmp_eqn_indices_<%nls.indexNonLinearSystem%>[<%listLength(nls.eqs)%>] = {<%nls.eqs |> eq => '<%equationIndex(eq)%>' ; separator = ", "%>};
3082 nonLinearSystemData[<%nls.indexNonLinearSystem%>].eqn_simcode_indices = malloc(<%listLength(nls.eqs)%> * sizeof(int));
3083 memcpy(nonLinearSystemData[<%nls.indexNonLinearSystem%>].eqn_simcode_indices, tmp_eqn_indices_<%nls.indexNonLinearSystem%>, <%listLength(nls.eqs)%> * sizeof(int));
3084 nonLinearSystemData[<%nls.indexNonLinearSystem%>].torn_plus_residual_size = <%listLength(nls.eqs)%>;
3085 >>
3086 end generateNonLinearSystemData;
3087
3088 3 template createGlobalConstraintsFunction(SimEqSystem system)
3089 "Creates a function which is called before each evaluation of the casual set to make sure that the constraints are not violated."
3090 ::=
3091 match system
3092 case SES_NONLINEAR(alternativeTearing = SOME(at as NONLINEARSYSTEM(__))) then
3093 let constraints = createGlobalConstraints(at.eqs)
3094 <<
3095 int checkConstraints<%at.index%>(DATA *data, threadData_t *threadData)
3096 {
3097 const int equationIndexes[2] = {1,<%at.index%>};
3098 <%equation_withProfile(at.index, constraints)%>
3099 return 1;
3100 }
3101
3102 >>
3103
3104 case SES_LINEAR(alternativeTearing = SOME(at as LINEARSYSTEM(__))) then
3105 let constraints = createGlobalConstraints(at.residual)
3106 <<
3107 int checkConstraints<%at.index%>(DATA *data, threadData_t *threadData)
3108 {
3109 const int equationIndexes[2] = {1,<%at.index%>};
3110 <%equation_withProfile(at.index, constraints)%>
3111 return 1;
3112 }
3113
3114 >>
3115 end createGlobalConstraintsFunction;
3116
3117 3 template createGlobalConstraints(list<SimEqSystem> innerEqns)
3118 "Creates a single constraint from SES_SIMPLE_ASSIGN_CONSTRAINTS which must not be violated to use the casual set."
3119 ::=
3120 (innerEqns |> innerEqn => (match innerEqn
3121 case innerEqn as SES_SIMPLE_ASSIGN_CONSTRAINTS(__) then
3122 (innerEqn.cons |> con => (match con
3123 case con as DAE.CONSTRAINT_DT(constraint = c, localCon = localCon) then
3124 let &preExp = buffer ""
3125 let &varDecls = buffer ""
3126 let &varFrees = buffer ""
3127 let &auxFunction = buffer ""
3128 let condition = daeExp(c, contextSimulationDiscrete, &preExp, &varDecls, &varFrees, &auxFunction)
3129 <<
3130 <%varDecls%>
3131 <%auxFunction%>
3132 <%preExp%>
3133 if (!<%condition%>){
3134 debugString(OMC_LOG_DT_CONS, "The following <%if localCon then "local" else "global"%> constraint is violated:\n<%dumpExp(c,"\"")%>");
3135 return 0;
3136 }
3137 >>
3138 )
3139 ;separator="\n")
3140 )
3141 ;separator="\n")
3142 end createGlobalConstraints;
3143
3144 33466 template functionExtraResidualsPreBody(SimEqSystem eq, Text &eqs, String modelNamePrefixStr)
3145 "Generates an equation."
3146 ::=
3147 let () = tmpTickReset(0)
3148 match eq
3149 case e as SES_RESIDUAL(__)
3150 then ""
3151 case e as SES_FOR_RESIDUAL(__)
3152 then ""
3153 case e as SES_GENERIC_RESIDUAL(__)
3154 then ""
3155 else
3156 let &eqs += equation_impl(-1, -1, eq, contextSimulationDiscrete, modelNamePrefixStr, false)
3157 <<
3158 /* local constraints */
3159 <%createLocalConstraints(eq)%>
3160 <%equation_call(eq, modelNamePrefixStr, contextSimulationDiscrete)%>
3161 <%errorCheck(contextSimulationDiscrete)%>
3162 >>
3163 end match
3164 end functionExtraResidualsPreBody;
3165
3166 69 template functionExtraResidualsPreBodyJacobian(SimEqSystem eq, Text &eqs, String modelNamePrefixStr)
3167 "Generates an equation."
3168 ::=
3169 let () = tmpTickReset(0)
3170 match eq
3171 case e as SES_RESIDUAL(__)
3172 then ""
3173 case e as SES_FOR_RESIDUAL(__)
3174 then ""
3175 case e as SES_GENERIC_RESIDUAL(__)
3176 then ""
3177 else
3178 let &eqs += equation_impl(-1, -1, eq, contextJacobian, modelNamePrefixStr, false)
3179 <<
3180 /* local constraints */
3181 <%createLocalConstraints(eq)%>
3182 <%equation_call(eq, modelNamePrefixStr, contextJacobian)%>
3183 <%errorCheck(contextJacobian)%>
3184 >>
3185 end match
3186 end functionExtraResidualsPreBodyJacobian;
3187
3188 4 template createLocalConstraints(SimEqSystem eq)
3189 "Generates an equation."
3190 ::=
3191 match eq
3192 case e as SES_SIMPLE_ASSIGN_CONSTRAINTS(__) then
3193 (e.cons |> con => (match con
3194 case con as DAE.CONSTRAINT_DT(constraint = c, localCon = true) then
3195 let &preExp = buffer ""
3196 let &varDecls = buffer ""
3197 let &varFrees = buffer ""
3198 let &auxFunction = buffer ""
3199 let condition = daeExp(c, contextSimulationDiscrete, &preExp, &varDecls, &varFrees, &auxFunction)
3200 <<
3201 <%varDecls%>
3202 <%auxFunction%>
3203 <%preExp%>
3204 if (!<%condition%>){
3205 debugString(OMC_LOG_DT_CONS, "The following local constraint is violated:\n<%dumpExp(c,"\"")%>");
3206 debugString(OMC_LOG_DT, "Local constraints of the casual tearing set are violated! Let's fail...");
3207 return 1;
3208 }
3209 >>
3210 )
3211 ;separator="\n")
3212 end match
3213 end createLocalConstraints;
3214
3215 1204 template functionNonLinearResidualsMultiFile(list<SimEqSystem> nonlinearSystems, Integer equationsPerFile, String fullPathPrefix, String fileNamePrefix, String partName, String modelNamePrefix)
3216 "Generates functions in simulation file."
3217 ::=
3218 functionNonLinearResidualsMultiFile2(SimCodeCodegenUtil.unbalancedEqSystemPartition(selectNLEqSys(nonlinearSystems), equationsPerFile), fullPathPrefix, fileNamePrefix, partName, modelNamePrefix)
3219 end functionNonLinearResidualsMultiFile;
3220
3221 247 template functionNonLinearResidualsMultiFile2(list<list<SimEqSystem>> nonlinearSystems, String fullPathPrefix, String fileNamePrefix, String partName, String modelNamePrefix)
3222 "Generates functions in simulation file."
3223 ::=
3224 match nonlinearSystems
3225 case {} then ""
3226 case {eqs} then
3227 let &prototypes = buffer ""
3228 functionNonLinearResiduals(eqs, modelNamePrefix, &prototypes)
3229 else
3230 let &prototypes = buffer ""
3231 let &file = buffer ""
3232 let &file +=
3233 (nonlinearSystems |> eqs =>
3234 let fileName = addFunctionIndex('<%fileNamePrefix%>_<%partName%>_part', ".c")
3235 redirectToFile(fullPathPrefix + fileName) +
3236 <<
3237 /* Non Linear Systems <%fullPathPrefix + fileName%> */
3238 <%simulationFileHeader(fileNamePrefix)%>
3239 #include "<%fileNamePrefix%>_12jac.h"
3240 #include "simulation/arrayIndex.h"
3241
3242 #if defined(__cplusplus)
3243 extern "C" {
3244 #endif
3245 <%functionNonLinearResiduals(eqs, modelNamePrefix, &prototypes)%>
3246 #if defined(__cplusplus)
3247 }
3248 #endif
3249 <%\n%>
3250 >>
3251 + closeFile()
3252 )
3253 prototypes + file
3254 end functionNonLinearResidualsMultiFile2;
3255
3256 1098 template getNLSPrototypes(Integer index)
3257 ::=
3258 <<
3259 void residualFunc<%index%>(RESIDUAL_USERDATA* userData, const double* xloc, double* res, const int* iflag);
3260 void initializeStaticDataNLS<%index%>(DATA* data, threadData_t *threadData, NONLINEAR_SYSTEM_DATA *inSystemData, modelica_boolean initSparsePattern, modelica_boolean initNonlinearPattern);
3261 void freeStaticDataNLS<%index%>(DATA* data, threadData_t *threadData, NONLINEAR_SYSTEM_DATA *inSystemData);
3262 void getIterationVarsNLS<%index%>(DATA* data, double *array);
3263 int updateSizeNLS<%index%>(DATA *data, threadData_t *threadData);
3264 >>
3265 end getNLSPrototypes;
3266
3267 1348 template functionNonLinearResiduals(list<SimEqSystem> nonlinearSystems, String modelNamePrefix, Text &prototypes)
3268 "Generates functions in simulation file."
3269 ::=
3270 (nonlinearSystems |> eqn => (
3271 let () = tmpTickReset(0)
3272 match eqn
3273 case eq as SES_MIXED(__) then functionNonLinearResiduals(fill(eq.cont,1),modelNamePrefix,prototypes)
3274 // no dynamic tearing
3275 case eq as SES_NONLINEAR(nlSystem=nls as NONLINEARSYSTEM(
3276 jacobianMatrix=SOME(JAC_MATRIX(matrixName=jacMatrixName,sparsityMatrix=sparsityMatrix,sparsity=sparsePattern,nonlinear=nonlinearPattern,nonlinearT=nonlinearPatternT,
3277 coloredCols=colorList,maxColorCols=maxColor,seedVars=seedVars,crefsHT=crefsHT))),
3278 alternativeTearing=NONE()) then
3279 let residualFunction = generateNonLinearResidualFunction(nls, modelNamePrefix, 0)
3280 let indexName = 'NLS<%nls.index%>'
3281 let useResizable = match sparsityMatrix case SPARSITY() then 'yes' else ''
3282 let newSparsity = generateResizableSparseData(indexName, 'NONLINEAR_SYSTEM_DATA', sparsityMatrix, numScalarElemsExp(seedVars), createJacContext(jacMatrixName, crefsHT))
3283 let sparseData = generateStaticSparseData(indexName, 'NONLINEAR_SYSTEM_DATA', sparsePattern, colorList, maxColor)
3284 let nonlinearData = generateStaticNonlinearData(indexName, 'NONLINEAR_SYSTEM_DATA', nonlinearPattern, nonlinearPatternT)
3285 let bodyStaticData = generateStaticInitialData(nls.crefs, indexName, useResizable)
3286 let updateIterationVars = getIterationVars(nls.crefs, indexName)
3287 let &prototypes += getNLSPrototypes(nls.index)
3288 <<
3289 <%residualFunction%>
3290 <%newSparsity%>
3291 <%sparseData%>
3292 <%nonlinearData%>
3293 <%bodyStaticData%>
3294 <%updateIterationVars%>
3295 >>
3296 case eq as SES_NONLINEAR(nlSystem=nls as NONLINEARSYSTEM(__),alternativeTearing=NONE()) then
3297 let residualFunction = generateNonLinearResidualFunction(nls, modelNamePrefix, 0)
3298 let indexName = 'NLS<%nls.index%>'
3299 let newSparsity = generateResizableEmptySparseData(indexName, 'NONLINEAR_SYSTEM_DATA')
3300 let sparseData = generateStaticEmptySparseData(indexName, 'NONLINEAR_SYSTEM_DATA')
3301 let nonlinearData = generateStaticEmptyNonlinearData(indexName, 'NONLINEAR_SYSTEM_DATA')
3302 let bodyStaticData = generateStaticInitialData(nls.crefs, indexName, '')
3303 let updateIterationVars = getIterationVars(nls.crefs, indexName)
3304 let &prototypes += getNLSPrototypes(nls.index)
3305 <<
3306 <%residualFunction%>
3307 <%newSparsity%>
3308 <%sparseData%>
3309 <%nonlinearData%>
3310 <%bodyStaticData%>
3311 <%updateIterationVars%>
3312 >>
3313 // dynamic tearing
3314 case eq as SES_NONLINEAR(nlSystem=nls as NONLINEARSYSTEM(
3315 jacobianMatrix=SOME(JAC_MATRIX(matrixName=jacMatrixName,sparsityMatrix=sparsityMatrix,sparsity=sparsePattern,nonlinear=nonlinearPattern,nonlinearT=nonlinearPatternT,coloredCols=colorList,maxColorCols=maxColor,seedVars=seedVars,crefsHT=crefsHT))),
3316 alternativeTearing = SOME(at as NONLINEARSYSTEM(
3317 jacobianMatrix=SOME(JAC_MATRIX(sparsity=sparsePattern2,coloredCols=colorList2,maxColorCols=maxColor2))))
3318 ) then
3319 // for strict tearing set
3320 let residualFunction = generateNonLinearResidualFunction(nls, modelNamePrefix, 0)
3321 let indexName = 'NLS<%nls.index%>'
3322 let newSparsity = generateResizableSparseData(indexName, 'NONLINEAR_SYSTEM_DATA', sparsityMatrix, numScalarElemsExp(seedVars), createJacContext(jacMatrixName, crefsHT))
3323 let sparseData = generateStaticSparseData(indexName, 'NONLINEAR_SYSTEM_DATA', sparsePattern, colorList, maxColor)
3324 let nonlinearData = generateStaticNonlinearData(indexName, 'NONLINEAR_SYSTEM_DATA', nonlinearPattern, nonlinearPatternT)
3325 let useResizable = match sparsityMatrix case SPARSITY() then 'yes' else ''
3326 let bodyStaticData = generateStaticInitialData(nls.crefs, indexName, useResizable)
3327 let updateIterationVars = getIterationVars(nls.crefs, indexName)
3328 // for casual tearing set
3329 let residualFunctionCasual = generateNonLinearResidualFunction(at, modelNamePrefix, 1)
3330 let indexName = 'NLS<%at.index%>'
3331 let sparseDataCasual = generateStaticSparseData(indexName, 'NONLINEAR_SYSTEM_DATA', sparsePattern, colorList, maxColor)
3332 let nonlinearDataCasual = generateStaticNonlinearData(indexName, 'NONLINEAR_SYSTEM_DATA', nonlinearPattern, nonlinearPatternT)
3333 let bodyStaticDataCasual = generateStaticInitialData(at.crefs, indexName, '')
3334 let updateIterationVarsCasual = getIterationVars(at.crefs, indexName)
3335 let &prototypes += getNLSPrototypes(nls.index)
3336 <<
3337 /* start residuals for dynamic tearing sets */
3338 /* strict tearing set */
3339 <%residualFunction%>
3340 <%newSparsity%>
3341 <%sparseData%>
3342 <%nonlinearData%>
3343 <%bodyStaticData%>
3344 <%updateIterationVars%>
3345 /* casual tearing set */
3346 <%residualFunctionCasual%>
3347 <%sparseDataCasual%>
3348 <%nonlinearDataCasual%>
3349 <%bodyStaticDataCasual%>
3350 <%updateIterationVarsCasual%>
3351 /* end residuals for dynamic tearing sets */
3352 >>
3353 case eq as SES_NONLINEAR(nlSystem=nls as NONLINEARSYSTEM(__),
3354 alternativeTearing = SOME(at as NONLINEARSYSTEM(__))
3355 ) then
3356 // for strict tearing set
3357 let residualFunction = generateNonLinearResidualFunction(nls, modelNamePrefix, 0)
3358 let indexName = 'NLS<%nls.index%>'
3359 let newSparsity = generateResizableEmptySparseData(indexName, 'NONLINEAR_SYSTEM_DATA')
3360 let sparseData = generateStaticEmptySparseData(indexName, 'NONLINEAR_SYSTEM_DATA')
3361 let bodyStaticData = generateStaticInitialData(nls.crefs, indexName, '')
3362 let updateIterationVars = getIterationVars(nls.crefs, indexName)
3363 // for casual tearing set
3364 let residualFunctionCasual = generateNonLinearResidualFunction(at, modelNamePrefix, 1)
3365 let indexName = 'NLS<%at.index%>'
3366 let sparseDataCasual = generateStaticEmptySparseData(indexName, 'NONLINEAR_SYSTEM_DATA')
3367 let bodyStaticDataCasual = generateStaticInitialData(at.crefs, indexName, '')
3368 let updateIterationVarsCasual = getIterationVars(at.crefs, indexName)
3369 let &prototypes += getNLSPrototypes(nls.index)
3370 <<
3371 /* start residuals for dynamic tearing sets */
3372 /* strict tearing set */
3373 <%residualFunction%>
3374 <%newSparsity%>
3375 <%sparseData%>
3376 <%bodyStaticData%>
3377 <%updateIterationVars%>
3378 /* casual tearing set */
3379 <%residualFunctionCasual%>
3380 <%sparseDataCasual%>
3381 <%bodyStaticDataCasual%>
3382 <%updateIterationVarsCasual%>
3383 /* end residuals for dynamic tearing sets */
3384 >>
3385 )
3386 ;separator="\n\n")
3387 end functionNonLinearResiduals;
3388
3389 1101 template generateNonLinearResidualFunction(NonlinearSystem system, String modelNamePrefix, Integer whichSet)
3390 "Generates residual function for nonlinear loops.
3391 whichSet = 0: Strict Set
3392 whichSet = 1: Casual Set"
3393 ::=
3394 let () = tmpTickReset(0)
3395 let &sub = buffer ""
3396 match system
3397 case nls as NONLINEARSYSTEM(__) then
3398 let &varDecls = buffer ""
3399 let &varFrees = buffer ""
3400 let &innerEqns = buffer ""
3401 let &dummyPrototypes = buffer ""
3402 let innerNLSSystems = functionNonLinearResiduals(nls.eqs, modelNamePrefix, dummyPrototypes)
3403 let backupOutputs = match nls.eqs
3404 case (alg as SES_INVERSE_ALGORITHM(__))::{} then
3405 let body = (alg.knownOutputCrefs |> cr hasindex i0 =>
3406 let &varDecls += '<%crefType(cr)%> OLD_<%i0%>;<%\n%>'
3407 'OLD_<%i0%> = <%cref(cr, &sub)%>;'
3408 ;separator="\n")
3409 <<
3410 /* backup outputs of the algorithm */
3411 <%body%>
3412 >>
3413 let restoreKnownOutputs = match nls.eqs
3414 case (alg as SES_INVERSE_ALGORITHM(__))::{} then
3415 let body = (alg.knownOutputCrefs |> cr hasindex i0 => '<%cref(cr, &sub)%> = OLD_<%i0%>;' ;separator="\n")
3416 <<
3417 /* restore previously known outputs of the algorithm */
3418 <%body%>
3419 >>
3420 let resizable = nlsResizable(nls.crefs)
3421 let xlocs = if resizable then nlsSetIterVars(nls.crefs, "xloc") else (nls.crefs |> cr hasindex i0 => '<%cref(cr, &sub)%> = xloc[<%i0%>];' ;separator="\n")
3422 let nlsSize = if resizable then 'data->simulationInfo->nonlinearSystemData[<%nls.indexNonLinearSystem%>].size' else listLength(nls.crefs)
3423 let prebody = (nls.eqs |> eq2 =>
3424 functionExtraResidualsPreBody(eq2, &innerEqns, modelNamePrefix)
3425 ;separator="\n")
3426 let body = match nls.eqs
3427 case (alg as SES_INVERSE_ALGORITHM(__))::{} then
3428 let init = (nls.crefs |> cr hasindex i0 => 'res[<%i0%>] = 0;' ;separator="\n")
3429 let known = (alg.knownOutputCrefs |> cr hasindex i0 => 'res[(int)fmod(<%i0%>, <%listLength(nls.crefs)%>)] += pow(OLD_<%i0%> - <%cref(cr, &sub)%>, 2);' ;separator="\n")
3430 <<
3431 <%init%>
3432 <%known%>
3433 >>
3434 else
3435 (nls.eqs |> eq2 hasindex i0 => match eq2
3436 case SES_RESIDUAL(__) then
3437 if resizable then equationResidualAt(exp, varDecls, varFrees, innerEqns, index, residualOffset(nls.eqs, i0))
3438 else equationResidual(exp, varDecls, varFrees, innerEqns, index, res_index)
3439 case SES_FOR_RESIDUAL(__) then
3440 let &preExp = buffer ""
3441 let &auxFunction = buffer ""
3442 let res_off = if resizable then residualOffset(nls.eqs, i0) else res_index
3443 let expPart = daeExp(exp, contextSimulationDiscrete, &preExp, &varDecls, &varFrees, &innerEqns)
3444 let forPart = (iterators |> iterator as SIM_ITERATOR_RANGE() =>
3445 let iter_ = contextCref(name, contextOther, &preExp, &varDecls, &varFrees, &auxFunction, &sub)
3446 let start_ = daeExp(start, contextSimulationDiscrete, &preExp, &varDecls, &varFrees, &auxFunction)
3447 let stop_ = daeExp(stop, contextSimulationDiscrete, &preExp, &varDecls, &varFrees, &auxFunction)
3448 let step_ = daeExp(step, contextSimulationDiscrete, &preExp, &varDecls, &varFrees, &auxFunction)
3449 let sub_iter_ = (sub_iter |> sub_i => subIterator(sub_i, iter_, contextSimulationDiscrete, &preExp, &varDecls, &varFrees, &auxFunction, &sub); separator="\n")
3450 <<for(int <%iter_%>=<%start_%>; <%iter_%><=<%stop_%>; <%iter_%>+=<%step_%>){
3451 <%sub_iter_%>
3452 >>
3453 ;separator="\n")
3454 let endForPart = (iterators |> iterator => "}")
3455 // A plain sum of each iterator's offset (old code) only gives a bijective
3456 // res[] index for a single iterator; with 2+ nested iterators it collapses
3457 // most (i1,i2,...) combinations onto the same slot and never writes the
3458 // rest of res[], leaving that part of the residual vector uninitialized.
3459 // Flatten properly, matching how array crefs are indexed elsewhere here.
3460 let indexShift = <<<%(iterators |> iterator => forIteratorBody(iterator, contextSimulationDiscrete, &preExp, &varDecls, &varFrees, &auxFunction, &sub) ;separator="")%>0<%(iterators |> iterator => ")" ;separator="")%>>>
3461 let assignment = (if isArrayType(typeof(exp))
3462 then '<%preExp%>copy_real_array_data_mem(<%expPart%>, res+<%res_off%>+(<%indexShift%>));'
3463 else '<%preExp%>res[<%res_off%>+(<%indexShift%>)] = <%expPart%>;')
3464 <<
3465 <% if profileAll() then 'SIM_PROF_TICK_EQ(<%index%>);' %>
3466 <%forPart%>
3467 <%assignment%>
3468 <%endForPart%>
3469 <% if profileAll() then 'SIM_PROF_ACC_EQ(<%index%>);' %>
3470 >>
3471 case SES_GENERIC_RESIDUAL(__) then
3472 let &preExp = buffer ""
3473 let &auxFunction = buffer ""
3474 let idx_len = listLength(scal_indices)
3475 let expPart = daeExp(exp, contextSimulationDiscrete, &preExp, &varDecls, &varFrees, &innerEqns)
3476 let iter_ = (iterators |> iterator as SIM_ITERATOR_RANGE() =>
3477 let iter = contextCref(name, contextOther, &preExp, &varDecls, &varFrees, &auxFunction, &sub)
3478 let start_ = daeExp(start, contextSimulationDiscrete, &preExp, &varDecls, &varFrees, &auxFunction)
3479 let stop_ = daeExp(stop, contextSimulationDiscrete, &preExp, &varDecls, &varFrees, &auxFunction)
3480 let step_ = daeExp(step, contextSimulationDiscrete, &preExp, &varDecls, &varFrees, &auxFunction)
3481 let sub_iter_ = (sub_iter |> sub_i => subIterator(sub_i, iter, contextSimulationDiscrete, &preExp, &varDecls, &varFrees, &auxFunction, &sub); separator="\n")
3482 <<
3483 const int <%iter%>_size = ((<%stop_%>) - (<%start_%>)) / (<%step_%>) + 1;
3484 int <%iter%>_loc = tmp % <%iter%>_size;
3485 int <%iter%> = (<%step_%>) * <%iter%>_loc + (<%start_%>);
3486 tmp /= <%iter%>_size;
3487 <%sub_iter_%>
3488 >>;separator="\n")
3489 let assignment = (if isArrayType(typeof(exp))
3490 then '<%preExp%>copy_real_array_data_mem(<%expPart%>, res+<%res_index%>+i_);'
3491 else '<%preExp%>res[<%res_index%>+i_] = <%expPart%>;')
3492 <<
3493 const int idx_lst_<%res_index%>[<%idx_len%>] = {<%(scal_indices |> idx => '<%idx%>';separator=", ")%>};
3494 for(int i_=0; i_<<%idx_len%>; i_++)
3495 {
3496 int tmp = idx_lst_<%res_index%>[i_];
3497 <%iter_%>
3498 <%assignment%>
3499 }
3500 >>
3501 ;separator="\n")
3502 let residualFunctionHeader =
3503 if intEq(whichSet, 0) then
3504 'void residualFunc<%nls.index%>(RESIDUAL_USERDATA* userData, const double* xloc, double* res, const int* iflag)'
3505 else
3506 'int residualFuncConstraints<%nls.index%>(RESIDUAL_USERDATA* userData, const double* xloc, double* res, const int* iflag)'
3507 let returnValue = if intEq(whichSet, 1) then 'return 0;'
3508 <<
3509 <%innerNLSSystems%>
3510
3511 /* inner equations */
3512 <%&innerEqns%>
3513
3514 <%if resizable then if intEq(whichSet, 0) then
3515 <<
3516 /* the size of the system for the actual sizes of the resizable arrays */
3517 int updateSizeNLS<%nls.index%>(DATA *data, threadData_t *threadData)
3518 {
3519 return <%(nls.crefs |> cr => nlsCount(cr) ;separator=" + ")%>;
3520 }
3521 >>%>
3522
3523 <%residualFunctionHeader%>
3524 {
3525 DATA *data = userData->data;
3526 threadData_t *threadData = userData->threadData;
3527 const int equationIndexes[2] = {1,<%nls.index%>};
3528 int i,j;<% if clockIndex then <<
3529 const int clockIndex = <%clockIndex%>;
3530 >> %>
3531 <%varDecls%>
3532 <% if profileAll() then 'SIM_PROF_TICK_EQ(<%nls.index%>);' %>
3533 <% if profileSome() then 'SIM_PROF_ADD_NCALL_EQ(modelInfoGetEquation(&data->modelData->modelDataXml,<%nls.index%>).profileBlockIndex,1);' %>
3534 /* iteration variables */
3535 for (i=0; i<<%nlsSize%>; i++) {
3536 if (!isfinite(xloc[i])) {
3537 <%if resizable then
3538 'errorStreamPrint(OMC_LOG_NLS, 0, "residualFunc<%nls.index%>: Iteration variable %d is %g.", i, xloc[i]);'
3539 else
3540 <<
3541 errorStreamPrint(OMC_LOG_NLS, 0, "residualFunc<%nls.index%>: Iteration variable `%s` is %g.",
3542 modelInfoGetEquation(&data->modelData->modelDataXml, <%nls.index%>).vars[i], xloc[i]);
3543 >>%>
3544 for (j=0; j<<%nlsSize%>; j++) {
3545 res[j] = NAN;
3546 }
3547 raiseStreamPrintWithEquationIndexes(threadData, omc_dummyFileInfo, equationIndexes, "residualFunc<%nls.index%> failed at time=%.15g.\nFor more information please use -lv LOG_NLS.", data->localData[0]->timeValue);
3548 OMC_ERROR_CHECK();
3549 }
3550 }
3551 <%xlocs%>
3552 /* backup outputs */
3553 <%backupOutputs%>
3554 /* pre body */
3555 <%prebody%>
3556 /* body */
3557 <%body%>
3558 /* restore known outputs */
3559 <%restoreKnownOutputs%>
3560 <% if profileAll() then 'SIM_PROF_ACC_EQ(<%nls.index%>);' %>
3561 threadData->lastEquationSolved = <%nls.index%>;
3562 _return: OMC_LABEL_UNUSED ;
3563 <%varFrees%>
3564 <%returnValue%>
3565 }
3566 >>
3567 end generateNonLinearResidualFunction;
3568
3569 244 template generateStaticEmptySparseData(String indexName, String systemType)
3570 "template generateStaticEmptySparseData
3571 This template generates source code for functions that initialize the sparse-pattern."
3572 ::=
3573 <<
3574 void initializeSparsePattern<%indexName%>(<%systemType%>* inSysData)
3575 {
3576 /* no sparsity pattern available */
3577 inSysData->sparsePattern = NULL;
3578 }
3579 >>
3580 end generateStaticEmptySparseData;
3581
3582
3583 175 template generateResizableEmptySparseData(String indexName, String systemType)
3584 "template generateResizableEmptySparseData
3585 This template generates source code for functions that initialize the sparse-pattern."
3586 ::=
3587 <<
3588 void initializeResizableSparsityPattern<%indexName%>(<%systemType%>* inSysData, threadData_t *threadData, DATA* data)
3589 {
3590 /* no sparsity pattern available */
3591 inSysData->sparsePattern = NULL;
3592 }
3593 >>
3594 end generateResizableEmptySparseData;
3595
3596 923 template generateResizableSparseData(String indexName, String systemType, Sparsity sparsity, String nCols, Context context)
3597 "template generateResizableSparseData
3598 This template generates source code for functions that initialize the sparse-pattern."
3599 ::=
3600 match sparsity
3601 case EMPTY() then
3602 <<
3603
3604 void initializeResizableSparsityPattern<%indexName%>(<%systemType%>* inSysData, threadData_t *threadData, DATA* data)
3605 {
3606 inSysData->sparsePattern = NULL;
3607 }
3608 >>
3609 case SPARSITY() then
3610 let &preExp = buffer ""
3611 let &varDecls = buffer ""
3612 let &varFrees = buffer ""
3613 let &auxFunction = buffer ""
3614 let &sub = buffer ""
3615 let countCode = (rows |> row => resizableSparsityRowCount(row, nCols, context, &preExp, &varDecls, &varFrees, &auxFunction, &sub) ;separator="\n")
3616 let fillCode = (rows |> row => resizableSparsityRowFill(row, nCols, context, &preExp, &varDecls, &varFrees, &auxFunction, &sub, 'inSysData->sparsePattern') ;separator="\n")
3617 let &varDecls += 'unsigned int local_row_base = 0;<%\n%>'
3618 <<
3619
3620 OMC_DISABLE_OPT
3621 void initializeResizableSparsityPattern<%indexName%>(<%systemType%>* inSysData, threadData_t *threadData, DATA* data)
3622 {
3623 unsigned int i, nnz;
3624 unsigned int col_counts[<%nCols%>];
3625 unsigned int col_fill[<%nCols%>];
3626 <%varDecls%>
3627
3628 <%preExp%>
3629 <%auxFunction%>
3630
3631 /* Phase 1: count non-zeros per column */
3632 memset(col_counts, 0, <%nCols%> * sizeof(unsigned int));
3633 <%countCode%>
3634
3635 /* Compute total nnz and allocate pattern */
3636 nnz = 0;
3637 for (i = 0; i < <%nCols%>; i++) nnz += col_counts[i];
3638 inSysData->sparsePattern = allocSparsePattern(<%nCols%>, nnz, 0);
3639 if (!inSysData->sparsePattern) return;
3640
3641 /* Compute leadindex as prefix sum of col_counts */
3642 inSysData->sparsePattern->leadindex[0] = 0;
3643 for (i = 0; i < <%nCols%>; i++)
3644 inSysData->sparsePattern->leadindex[i + 1] = inSysData->sparsePattern->leadindex[i] + col_counts[i];
3645
3646 /* Phase 2: fill row indices */
3647 memcpy(col_fill, inSysData->sparsePattern->leadindex, <%nCols%> * sizeof(unsigned int));
3648 <%fillCode%>
3649 <%varFrees%>
3650
3651 /* Compute coloring at runtime from the actual pattern (see initialResizableAnalyticJacobians).
3652 * nRows = inSysData->size (NLS equation count); nCols = number of seed directions. */
3653 computeColumnColoring(inSysData->sparsePattern, inSysData->size, <%nCols%>);
3654 }
3655
3656 void freeResizableSparsityPattern<%indexName%>(<%systemType%>* inSysData)
3657 {
3658 if (inSysData->sparsePattern) {
3659 freeSparsePattern(inSysData->sparsePattern);
3660 inSysData->sparsePattern = NULL;
3661 }
3662 }
3663 >>
3664 end generateResizableSparseData;
3665
3666
3667 926 template generateStaticSparseData(String indexName, String systemType, SparsityPattern sparsepattern, list<list<Integer>> colorList, Integer maxColor)
3668 "template generateStaticSparseData
3669 This template generates source code for functions that initialize the sparse-pattern."
3670 ::=
3671 match sparsepattern
3672 case {} then
3673 generateStaticEmptySparseData(indexName, systemType)
3674 case _ then
3675 let sp_size_index = lengthListElements(unzipSecond(sparsepattern))
3676 let sizeleadindex = listLength(sparsepattern)
3677 let colPtr = genSPCRSPtr(listLength(sparsepattern), sparsepattern, "colPtrIndex")
3678 let rowIndex = genSPCRSRows(lengthListElements(unzipSecond(sparsepattern)), sparsepattern, "rowIndex")
3679 let colorString = genSPColors(colorList, "inSysData->sparsePattern->colorCols")
3680 <<
3681
3682 OMC_DISABLE_OPT
3683 void initializeSparsePattern<%indexName%>(<%systemType%>* inSysData)
3684 {
3685 int i=0;
3686 <%colPtr%>
3687 <%rowIndex%>
3688 inSysData->sparsePattern = allocSparsePattern(<%sizeleadindex%>, <%sp_size_index%>, <%maxColor%>);
3689
3690 /* write lead index of compressed sparse column */
3691 memcpy(inSysData->sparsePattern->leadindex, colPtrIndex, (<%sizeleadindex%>+1)*sizeof(unsigned int));
3692
3693 for(i=2;i<<%sizeleadindex%>+1;++i)
3694 inSysData->sparsePattern->leadindex[i] += inSysData->sparsePattern->leadindex[i-1];
3695
3696 /* call sparse index */
3697 memcpy(inSysData->sparsePattern->index, rowIndex, <%sp_size_index%>*sizeof(unsigned int));
3698
3699 /* write color array */
3700 <%colorString%>
3701 }
3702 >>
3703 end match
3704 end generateStaticSparseData;
3705
3706 782 template generateStaticEmptyNonlinearData(String indexName, String systemType)
3707 "template generateStaticEmptyNonlinearData
3708 This template generates source code for functions that initialize the nonlinear-pattern."
3709 ::=
3710 <<
3711 void initializeNonlinearPattern<%indexName%>(<%systemType%>* inSysData)
3712 {
3713 /* no nonlinear pattern available */
3714 }
3715 >>
3716 end generateStaticEmptyNonlinearData;
3717
3718 926 template generateStaticNonlinearData(String indexName, String systemType, SimCode.NonlinearPattern nonlinearpattern, SimCode.NonlinearPattern nonlinearpatternT)
3719 "template generateStaticNonlinearData
3720 This template generates source code for functions that initialize the nonlinear-pattern."
3721 ::=
3722 match nonlinearpattern
3723 case {} then
3724 generateStaticEmptyNonlinearData(indexName, systemType)
3725 case _ then
3726 let number_vars = listLength(nonlinearpatternT)
3727 let number_eqns = listLength(nonlinearpattern)
3728 let number_nonlinear = lengthListElements(unzipSecond(nonlinearpattern))
3729 let index_var = genSPCRSPtr(listLength(nonlinearpatternT), nonlinearpatternT, "index_var")
3730 let index_eqn = genSPCRSPtr(listLength(nonlinearpatternT), nonlinearpatternT, "index_eqn")
3731 let columns = genSPCRSRows(lengthListElements(unzipSecond(nonlinearpatternT)), nonlinearpatternT, "columns")
3732 let rows = genSPCRSRows(lengthListElements(unzipSecond(nonlinearpattern)), nonlinearpattern, "rows")
3733 <<
3734 OMC_DISABLE_OPT
3735 void initializeNonlinearPattern<%indexName%>(<%systemType%>* inSysData)
3736 {
3737 int i=0;
3738 inSysData->nonlinearPattern = (NONLINEAR_PATTERN*) malloc(sizeof(NONLINEAR_PATTERN));
3739 inSysData->nonlinearPattern->numberOfVars = <%number_vars%>;
3740 inSysData->nonlinearPattern->numberOfEqns = <%number_eqns%>;
3741 inSysData->nonlinearPattern->numberOfNonlinear = <%number_nonlinear%>;
3742 inSysData->nonlinearPattern->indexVar = (unsigned int*) malloc((<%number_vars%>+1)*sizeof(unsigned int));
3743 inSysData->nonlinearPattern->indexEqn = (unsigned int*) malloc((<%number_eqns%>+1)*sizeof(unsigned int));
3744 inSysData->nonlinearPattern->columns = (unsigned int*) malloc(<%number_nonlinear%>*sizeof(unsigned int));
3745 inSysData->nonlinearPattern->rows = (unsigned int*) malloc(<%number_nonlinear%>*sizeof(unsigned int));
3746 /* initialize and accumulate index vectors */
3747 <%index_var%>
3748 <%index_eqn%>
3749 memcpy(inSysData->nonlinearPattern->indexVar, index_var, (<%number_vars%>+1)*sizeof(unsigned int));
3750 memcpy(inSysData->nonlinearPattern->indexEqn, index_eqn, (<%number_eqns%>+1)*sizeof(unsigned int));
3751 for(i=2;i<<%number_vars%>+1;++i)
3752 inSysData->nonlinearPattern->indexVar[i] += inSysData->nonlinearPattern->indexVar[i-1];
3753 for(i=2;i<<%number_eqns%>+1;++i)
3754 inSysData->nonlinearPattern->indexEqn[i] += inSysData->nonlinearPattern->indexEqn[i-1];
3755 /* initialize columns and rows */
3756 <%columns%>
3757 <%rows%>
3758 memcpy(inSysData->nonlinearPattern->columns, columns, <%number_nonlinear%>*sizeof(unsigned int));
3759 memcpy(inSysData->nonlinearPattern->rows, rows, <%number_nonlinear%>*sizeof(unsigned int));
3760 }
3761 >>
3762 end match
3763 end generateStaticNonlinearData;
3764
3765 1101 template generateStaticInitialData(list<ComponentRef> crefs, String indexName, String useResizableSparsity)
3766 "Generates initial function for nonlinear loops.
3767 useResizableSparsity: non-empty string = use resizable pattern init; empty = use static pattern init."
3768 ::=
3769 let systemType = 'NONLINEAR_SYSTEM_DATA'
3770 let bodyStaticData = (crefs |> cr hasindex i0 =>
3771 let cComment = '/* static nls data for <%crefStrNoUnderscore(cr)%> */'
3772 if nlsResizableCref(cr) then
3773 <<
3774 <%cComment%>
3775 for (k_ = 0; k_ < <%nlsCount(cr)%>; k_++) {
3776 sysData->nominal[i] = 1.0;
3777 sysData->min[i] = -DBL_MAX;
3778 sysData->max[i++] = DBL_MAX;
3779 }
3780 >>
3781 else
3782 match cref2simvar(crefRemovePrePrefix(cr), getSimCode())
3783 case SIMVAR(type_=T_REAL(__)) then
3784 let kind = match varKind
3785 case PARAM() then 'VAR_KIND_PARAMETER'
3786 else 'VAR_KIND_VARIABLE'
3787 end match
3788 if intLt(index, 0) then
3789 <<
3790 <%cComment%>
3791 /* Use default scaling/bounds for unresolved temporary indices (e.g. symbolic-adjoint loop vars). */
3792 sysData->nominal[i] = 1.0;
3793 sysData->min[i] = -DBL_MAX;
3794 sysData->max[i++] = DBL_MAX;
3795 >>
3796 else
3797 <<
3798 <%cComment%>
3799 sysData->nominal[i] = getNominalFromScalarIdx(data->simulationInfo, data->modelData, <%kind%>, <%crefIndexWithComment(cr)%>);
3800 sysData->min[i] = getMinFromScalarIdx(data->simulationInfo, data->modelData, VAR_TYPE_REAL, <%kind%>, <%crefIndexWithComment(cr)%>);
3801 sysData->max[i++] = getMaxFromScalarIdx(data->simulationInfo, data->modelData, VAR_TYPE_REAL, <%kind%>, <%crefIndexWithComment(cr)%>);
3802 >>
3803 case SIMVAR(type_=T_INTEGER(__)) then
3804 <<
3805 <%cComment%>
3806 sysData->nominal[i] = 1.0;
3807 sysData->min[i] = integer_get(<%crefAttributes(cr)%>.min, 0);
3808 sysData->max[i++] = integer_get(<%crefAttributes(cr)%>.max, 0);
3809 >>
3810 else
3811 <<
3812 <%cComment%>
3813 sysData->nominal[i] = 1.0;
3814 sysData->min[i] = -DBL_MAX;
3815 sysData->max[i++] = DBL_MAX;
3816 >>
3817
3818 ;separator="\n")
3819 let sparsityInitCall = if useResizableSparsity
3820 then 'initializeResizableSparsityPattern<%indexName%>(sysData, threadData, data);'
3821 else 'initializeSparsePattern<%indexName%>(sysData);'
3822 <<
3823
3824 OMC_DISABLE_OPT
3825 void initializeStaticData<%indexName%>(DATA* data, threadData_t *threadData, NONLINEAR_SYSTEM_DATA *sysData, modelica_boolean initSparsePattern, modelica_boolean initNonlinearPattern)
3826 {
3827 int i=0, k_=0;
3828 <%bodyStaticData%>
3829 /* initial sparse pattern */
3830 if (initSparsePattern) {
3831 <%sparsityInitCall%>
3832 }
3833 if (initNonlinearPattern) {
3834 initializeNonlinearPattern<%indexName%>(sysData);
3835 }
3836 }
3837
3838 OMC_DISABLE_OPT
3839 void freeStaticData<%indexName%>(DATA* data, threadData_t *threadData, NONLINEAR_SYSTEM_DATA *sysData)
3840 {
3841 freeSparsePattern(sysData->sparsePattern);
3842 sysData->sparsePattern = NULL;
3843 }
3844 >>
3845 end generateStaticInitialData;
3846
3847 5503 template nlsResizable(list<ComponentRef> crefs)
3848 "non-empty if an iteration variable of an algebraic loop is a whole resizable array"
3849 ::= (crefs |> cr => match cref2simvar(cr, getSimCode()) case v as SIMVAR(__) then if isWholeResizableArray(cr, v) then "1" ;separator="")
3850 end nlsResizable;
3851
3852 3545 template nlsResizableCref(ComponentRef cr)
3853 ::= match cref2simvar(cr, getSimCode()) case v as SIMVAR(__) then if isWholeResizableArray(cr, v) then "1"
3854 end nlsResizableCref;
3855
3856 36 template nlsCount(ComponentRef cr)
3857 "the number of scalar iteration variables of cr at runtime"
3858 ::=
3859 match cref2simvar(cr, getSimCode())
3860 case v as SIMVAR(__) then
3861 if isWholeResizableArray(cr, v) then
3862 let &preExp = buffer ""
3863 let &varDecls = buffer ""
3864 let &varFrees = buffer ""
3865 let &aux = buffer ""
3866 '(<%daeExp(simVarSizeExp(v), contextSimulationNonDiscrete, &preExp, &varDecls, &varFrees, &aux)%>)'
3867 else "1"
3868 else "1"
3869 end nlsCount;
3870
3871 12 template nlsSetIterVars(list<ComponentRef> crefs, String src)
3872 "the iteration variables from the vector src, whole resizable arrays element by element"
3873 ::=
3874 let &sub = buffer ""
3875 let body = (crefs |> cr =>
3876 match cref2simvar(cr, getSimCode())
3877 case v as SIMVAR(__) then
3878 if isWholeResizableArray(cr, v) then
3879 'for (k_ = 0; k_ < <%nlsCount(cr)%>; k_++) <%inputValue(v, 'k_')%> = <%src%>[o_++];'
3880 else '<%cref(cr, &sub)%> = <%src%>[o_++];'
3881 else '<%cref(cr, &sub)%> = <%src%>[o_++];'
3882 ;separator="\n")
3883 <<
3884 {
3885 int o_ = 0, k_ = 0;
3886 <%body%>
3887 }
3888 >>
3889 end nlsSetIterVars;
3890
3891 12 template nlsGetIterVars(list<ComponentRef> crefs, String dst)
3892 "the iteration variables into the vector dst, whole resizable arrays element by element"
3893 ::=
3894 let &sub = buffer ""
3895 let body = (crefs |> cr =>
3896 match cref2simvar(cr, getSimCode())
3897 case v as SIMVAR(__) then
3898 if isWholeResizableArray(cr, v) then
3899 'for (k_ = 0; k_ < <%nlsCount(cr)%>; k_++) <%dst%>[o_++] = <%inputValue(v, 'k_')%>;'
3900 else '<%dst%>[o_++] = <%cref(cr, &sub)%>;'
3901 else '<%dst%>[o_++] = <%cref(cr, &sub)%>;'
3902 ;separator="\n")
3903 <<
3904 {
3905 int o_ = 0, k_ = 0;
3906 <%body%>
3907 }
3908 >>
3909 end nlsGetIterVars;
3910
3911 8 template residualOffset(list<SimEqSystem> eqs, Integer i0)
3912 "the position of the i0-th equation of an algebraic loop in its residual vector at runtime"
3913 ::=
3914 let &preExp = buffer ""
3915 let &varDecls = buffer ""
3916 let &varFrees = buffer ""
3917 let &aux = buffer ""
3918 '(<%daeExp(residualOffsetExp(eqs, i0), contextSimulationNonDiscrete, &preExp, &varDecls, &varFrees, &aux)%>)'
3919 end residualOffset;
3920
3921 1101 template getIterationVars(list<ComponentRef> crefs, String indexName)
3922 "Generates iteration variables update."
3923 ::=
3924 let &sub = buffer ""
3925 let vars = if nlsResizable(crefs) then nlsGetIterVars(crefs, "array") else (crefs |> cr hasindex i0 =>
3926 'array[<%i0%>] = <%cref(cr, &sub)%>;'
3927 ;separator="\n")
3928 <<
3929
3930 OMC_DISABLE_OPT
3931 void getIterationVars<%indexName%>(DATA* data, double *array)
3932 {
3933 <%vars%>
3934 }
3935 >>
3936 end getIterationVars;
3937
3938 // =============================================================================
3939 // section for State Sets
3940 //
3941 // This section generates the followng c functions:
3942 // - void initializeStateSets(int nStateSets, STATE_SET_DATA* statesetData, DATA *data)
3943 // =============================================================================
3944
3945 1204 template functionInitialStateSets(SimCode simCode, list<SimCode.StateSet> stateSets, String modelNamePrefix)
3946 "Generates functions in simulation file to initialize the stateset data."
3947 ::=
3948 let body = (stateSets |> set hasindex i1 fromindex 0 => (match set
3949 case set as SES_STATESET(__) then
3950 let generatedJac = match jacobianMatrix case JAC_MATRIX(matrixName=name) then '<%symbolName(modelNamePrefix,"functionJac")%><%name%>_column'
3951 let initialJac = match jacobianMatrix case JAC_MATRIX(matrixName=name) then '<%symbolName(modelNamePrefix,"initialAnalyticJacobian")%><%name%>'
3952 let jacIndex = match jacobianMatrix case JAC_MATRIX(jacobianIndex=jacindex) then '<%jacindex%>'
3953 let statesvars = (states |> s hasindex i2 fromindex 0 => 'statesetData[<%i1%>].states[<%i2%>] = &<%crefVarInfo( s)%>;' ;separator="\n")
3954 let statescandidatesvars = (statescandidates |> cstate hasindex i2 fromindex 0 => 'statesetData[<%i1%>].statescandidates[<%i2%>] = &<%crefVarInfo( cstate)%>;' ;separator="\n")
3955 <<
3956 assertStreamPrint(NULL, nStateSets > <%i1%>, "Internal Error: nStateSets mismatch!");
3957 statesetData[<%i1%>].nCandidates = <%nCandidates%>;
3958 statesetData[<%i1%>].nStates = <%nStates%>;
3959 statesetData[<%i1%>].nDummyStates = <%nCandidates%>-<%nStates%>;
3960 statesetData[<%i1%>].states = (VAR_INFO**) calloc(<%nStates%>,sizeof(VAR_INFO));
3961 <%statesvars%>
3962 statesetData[<%i1%>].statescandidates = (VAR_INFO**) calloc(<%nCandidates%>,sizeof(VAR_INFO));
3963 <%statescandidatesvars%>
3964 statesetData[<%i1%>].A = &<%crefVarInfo( crA)%>;
3965 statesetData[<%i1%>].rowPivot = (modelica_integer*) calloc(<%nCandidates%>-<%nStates%>,sizeof(modelica_integer));
3966 statesetData[<%i1%>].colPivot = (modelica_integer*) calloc(<%nCandidates%>,sizeof(modelica_integer));
3967 statesetData[<%i1%>].J = (modelica_real*) calloc(<%nCandidates%>*(<%nCandidates%>-<%nStates%>),sizeof(modelica_real));
3968 statesetData[<%i1%>].analyticalJacobianColumn = <%generatedJac%>;
3969 statesetData[<%i1%>].initialAnalyticalJacobian = <%initialJac%>;
3970 statesetData[<%i1%>].jacobianIndex = <%jacIndex%>;
3971
3972 >>
3973 )
3974 ;separator="\n\n")
3975 <<
3976 /* funtion initialize state sets */
3977 void <%symbolName(modelNamePrefix,"initializeStateSets")%>(int nStateSets, STATE_SET_DATA* statesetData, DATA *data)
3978 {
3979 <%body%>
3980 }
3981 >>
3982 end functionInitialStateSets;
3983
3984 // =============================================================================
3985 // section for initialization
3986 //
3987 // This section generates the followng c functions:
3988 // - int updateBoundParameters(DATA *data)
3989 // - int updateBoundVariableAttributes(DATA *data)
3990 // - int functionInitialEquations(DATA *data)
3991 // - int functionInitialEquations_lambda0(DATA *data)
3992 // - int functionRemovedInitialEquations(DATA *data)
3993 // =============================================================================
3994
3995 1204 template functionUpdateBoundVariableAttributes(SimCode simCode, list<SimEqSystem> startValueEquations, list<SimEqSystem> nominalValueEquations, list<SimEqSystem> minValueEquations, list<SimEqSystem> maxValueEquations, String modelNamePrefix)
3996 "Generates function in simulation file."
3997 ::=
3998 let &sub = buffer ""
3999 <<
4000 <%(startValueEquations |> eq as SES_SIMPLE_ASSIGN(__) => equation_impl2(-1, -1, eq, contextOther, modelNamePrefix, /* Static? */ true, /* No optimization */ false, /* Initial? */ true) ; separator="\n")%>
4001 <%(nominalValueEquations |> eq as SES_SIMPLE_ASSIGN(__) => functionUpdateBoundVariableAttributesFunctions(eq, "nominal", contextOther, modelNamePrefix, /* Static? */ true, /* No optimization */ false) ; separator="\n") %>
4002 <%(minValueEquations |> eq as SES_SIMPLE_ASSIGN(__) => functionUpdateBoundVariableAttributesFunctions(eq, "min", contextOther, modelNamePrefix, /* Static? */ true, /* No optimization */ false) ; separator="\n") %>
4003 <%(maxValueEquations |> eq as SES_SIMPLE_ASSIGN(__) => functionUpdateBoundVariableAttributesFunctions(eq, "max", contextOther, modelNamePrefix, /* Static? */ true, /* No optimization */ false) ; separator="\n") %>
4004 OMC_DISABLE_OPT
4005 int <%symbolName(modelNamePrefix,"updateBoundVariableAttributes")%>(DATA *data, threadData_t *threadData)
4006 {
4007 /* min ******************************************************** */
4008 infoStreamPrint(OMC_LOG_INIT, 1, "updating min-values");
4009 <%(minValueEquations |> eq as SES_SIMPLE_ASSIGN(__) => equation_call(eq, modelNamePrefix, contextOther) ; separator="\n")%>
4010 messageClose(OMC_LOG_INIT);
4011
4012 /* max ******************************************************** */
4013 infoStreamPrint(OMC_LOG_INIT, 1, "updating max-values");
4014 <%(maxValueEquations |> eq as SES_SIMPLE_ASSIGN(__) => equation_call(eq, modelNamePrefix, contextOther) ; separator="\n")%>
4015 messageClose(OMC_LOG_INIT);
4016
4017 /* nominal **************************************************** */
4018 infoStreamPrint(OMC_LOG_INIT, 1, "updating nominal-values");
4019 <%(nominalValueEquations |> eq as SES_SIMPLE_ASSIGN(__) => equation_call(eq, modelNamePrefix, contextOther) ; separator="\n")%>
4020 messageClose(OMC_LOG_INIT);
4021
4022 /* start ****************************************************** */
4023 infoStreamPrint(OMC_LOG_INIT, 1, "updating primary start-values");
4024 <%(startValueEquations |> eq as SES_SIMPLE_ASSIGN(__) => equation_call(eq, modelNamePrefix, contextOther) ; separator="\n")%>
4025 messageClose(OMC_LOG_INIT);
4026
4027 return 0;
4028 }
4029 >>
4030 end functionUpdateBoundVariableAttributes;
4031
4032 668 template functionUpdateBoundVariableAttributesFunctions(SimEqSystem eq, String attribute, Context context, String modelNamePrefix, Boolean static, Boolean noOpt)
4033 "Generates an a function representing an equation for an attribute binding (e.g min, max ...)"
4034 ::=
4035 let OMC_NO_OPT = if noOpt then 'OMC_DISABLE_OPT<%\n%>' else (match eq case SES_LINEAR(__) then 'OMC_DISABLE_OPT<%\n%>')
4036 match eq
4037 case SES_SIMPLE_ASSIGN(exp=CALL(path=IDENT(name="fail")))
4038 case SES_SIMPLE_ASSIGN_CONSTRAINTS(exp=CALL(path=IDENT(name="fail"))) then
4039 '<%generateThrow()%><%\n%>'
4040
4041 case SES_SIMPLE_ASSIGN(__)
4042 case SES_SIMPLE_ASSIGN_CONSTRAINTS(__) then
4043
4044 let ix = equationIndex(eq) /*System.tmpTickIndex(10)*/
4045 let &varDecls = buffer ""
4046 let &varFrees = buffer ""
4047 let &auxFunction = buffer ""
4048 let body = functionUpdateBoundVariableAttributesFunctionsSimpleAssign(eq, attribute, context, &varDecls, &varFrees, &auxFunction)
4049
4050 <<
4051 /*
4052 <%dumpEqs(fill(eq,1))%>
4053 */
4054 <%OMC_NO_OPT%><% if static then "static "%>void <%symbolName(modelNamePrefix,"eqFunction")%>_<%ix%>(DATA *data, threadData_t *threadData)
4055 {
4056 const int equationIndexes[2] = {1,<%ix%>};
4057 <%&varDecls%>
4058 <%equation_withProfile(ix, body)%>
4059 _return: OMC_LABEL_UNUSED ;
4060 <%varFrees%>
4061 }
4062
4063 >>
4064
4065 else "NOT IMPLEMENTED EQUATION equation_"
4066 end functionUpdateBoundVariableAttributesFunctions;
4067
4068 668 template functionUpdateBoundVariableAttributesFunctionsSimpleAssign(SimEqSystem eq, String attribute, Context context,
4069 Text &varDecls, Text &varFrees, Text &auxFunction)
4070 "Generates an equation that is just a simple assignment for an attribute binding.
4071 The attribute type is given by the function argument 'attibute' (e.g min, max ...)"
4072 ::=
4073 match eq
4074 case SES_SIMPLE_ASSIGN(__)
4075 case SES_SIMPLE_ASSIGN_CONSTRAINTS(__) then
4076 let &sub = buffer ""
4077 let &preExp = buffer ""
4078 let expPart = daeExp(exp, context, &preExp, &varDecls, &varFrees, &auxFunction)
4079 let postExp = if isStartCref(cref) then
4080 <<
4081 <%cref(popCref(cref), &sub)%> = <%cref(cref, &sub)%>;
4082 <%if stringEq(isPrintableCrefType(popCref(cref)), "true") then
4083 <<
4084 infoStreamPrint(OMC_LOG_INIT_V, 0, "updated start value: %s(start=<%crefToPrintfArg(popCref(cref))%>)",
4085 <%crefVarInfo(popCref(cref))%>.name,
4086 (<%crefType(popCref(cref))%>) <%cref(popCref(cref), &sub)%>);
4087 >>
4088 %>
4089 >>
4090
4091 let ty = crefShortType(cref)
4092 // An array expression sets one value per array element, a scalar
4093 // expression (e.g. `each min = p`) the value of all elements.
4094 let attr = '<%crefAttributes(cref)%>.<%attribute%>'
4095 let len = if isArrayType(typeof(exp)) then 'base_array_nr_of_elements(<%expPart%>)' else '1'
4096 let setAttribute =
4097 <<
4098 if (base_array_nr_of_elements(<%attr%>) != <%len%>) {
4099 omc_array_release(&<%attr%>);
4100 simple_alloc_1d_<%ty%>_array(&<%attr%>, <%len%>);
4101 }
4102 <%if isArrayType(typeof(exp))
4103 then 'copy_<%ty%>_array_data_mem(<%expPart%>, (modelica_<%ty%>*) <%attr%>.data);'
4104 else 'put_<%ty%>_element(<%expPart%>, 0, &<%attr%>);'%>
4105 >>
4106 let updateEqs = match attribute
4107 case "nominal"
4108 case "min"
4109 case "max" then
4110 <<
4111 <%setAttribute%>
4112
4113 if (omc_useStream[OMC_LOG_INIT_V]) {
4114 char <%attribute%>_buffer[2048];
4115 <%ty%>_vector_to_string(&<%crefAttributes(cref)%>.<%attribute%>, <%crefVarDimension(cref)%>.numberOfDimensions == 0, <%attribute%>_buffer, 2048);
4116 infoStreamPrint(OMC_LOG_INIT_V, 0, "%s(<%attribute%>=%s)",
4117 <%crefVarInfo(cref)%>.name,
4118 <%attribute%>_buffer);
4119 }
4120 >>
4121 else
4122 error(sourceInfo(), 'Attribute <%attribute%> not handled by functionUpdateBoundVariableAttributesFunctionsSimpleAssign!')
4123
4124 <<
4125 <%modelicaLine(eqInfo(eq))%>
4126 <%preExp%>
4127 <%updateEqs%>
4128 <%postExp%>
4129 <%endModelicaLine()%>
4130 >>
4131 end functionUpdateBoundVariableAttributesFunctionsSimpleAssign;
4132
4133
4134 1204 template functionUpdateBoundParameters(list<SimEqSystem> simpleParameterEquations, list<SimEqSystem> parameterEquations, String fileNamePrefix, String fullPathPrefix, String modelNamePrefix, SimCode simCode)
4135 "Generates function in simulation file."
4136 ::=
4137 let &sub = buffer ""
4138 let &eqFuncs = buffer ""
4139 let &auxFunction = buffer ""
4140 let fncalls = functionEquationsMultiFiles(parameterEquations, listLength(parameterEquations),
4141 Flags.getConfigInt(Flags.EQUATIONS_PER_FILE), fileNamePrefix, fullPathPrefix, modelNamePrefix,
4142 "updateBoundParameters", "08bnd", &eqFuncs, /* Static? */ true, true /* No optimization */, /* initial? */ false)
4143 let extObjsSub = match simCode
4144 case SIMCODE(extObjInfo = extObjInfo as EXTOBJINFO(__)) then
4145 (extObjInfo.vars |> var as SIMVAR(varKind=ext as EXTOBJ(__)) =>
4146 'if (data->simulationInfo->extObjs && <%cref(var.name, &sub)%>) { omc_<%underscorePath(ext.fullClassName)%>_destructor(threadData,<%cref(var.name, &sub)%>); }'
4147 ; separator="\n")
4148 else ""
4149 end match
4150 <<
4151 <%eqFuncs%>
4152 OMC_DISABLE_OPT
4153 int <%symbolName(modelNamePrefix,"updateBoundParameters")%>(DATA *data, threadData_t *threadData)
4154 {
4155 <%sortSimpleAssignmentBasedOnLhs(simpleParameterEquations) |> eq as SES_SIMPLE_ASSIGN(__) =>
4156 <<
4157 <%cref(cref, &sub)%> = <%daeExpSimpleLiteral(exp)%>;
4158 <%match cref2simvar(cref, simCode)
4159 case SIMVAR(aliasvar=NOALIAS(), varKind=PARAM()) then
4160 'data->modelData-><%expTypeShort(type_)%>ParameterData[<%index%>].time_unvarying = 1;'
4161 case SIMVAR(aliasvar=NOALIAS()) then
4162 'data->modelData-><%expTypeShort(type_)%>VarsData[<%index%>].time_unvarying = 1;'
4163 else error(sourceInfo(), 'Cannot get attributes of alias variable <%CodegenUtil.crefStr(cref)%>. Alias variables should have been replaced by the compiler before SimCode')%>
4164 >> ; separator="\n" %>
4165 <%extObjsSub%>
4166 <%fncalls%>
4167 return 0;
4168 }
4169 >>
4170 end functionUpdateBoundParameters;
4171
4172 2408 template functionEquationsMultiFiles(list<SimEqSystem> inEqs, Integer numEqs, Integer equationsPerFile, String fileNamePrefix, String fullPathPrefix, String modelNamePrefix, String funcName, String partName, Text &eqFuncs, Boolean static, Boolean noOpt, Boolean init)
4173 ::=
4174 let () = System.tmpTickReset(0)
4175 let &file = buffer ""
4176 let multiFile = if intGt(numEqs, equationsPerFile) then "x"
4177 let fncalls = (List.balancedPartition(inEqs, equationsPerFile) |> eqs hasindex i0 =>
4178 let name = symbolName(modelNamePrefix,'<%funcName%>_<%i0%>')
4179 let &eqFuncs += 'void <%name%>(DATA *data, threadData_t *threadData);<%\n%>'
4180
4181 // To file
4182 let &file += ((if multiFile then
4183 (let fileName = addFunctionIndex('<%fileNamePrefix%>_<%partName%>_part', ".c")
4184 redirectToFile(fullPathPrefix + fileName) +
4185 <<
4186 <%simulationFileHeader(fileNamePrefix)%>
4187 #if defined(__cplusplus)
4188 extern "C" {
4189 #endif<%\n%>
4190 >>)) +
4191 (eqs |> eq => equation_impl2(-1, -1, eq, contextSimulationDiscrete, modelNamePrefix, static, noOpt, init) ; separator="\n") +
4192 (let &chunks = buffer ""
4193 let calls = equations_call(eqs, modelNamePrefix, contextOther, '', false, &chunks)
4194 <<
4195 <%\n%>
4196 <%chunks%>
4197 OMC_DISABLE_OPT
4198 void <%name%>(DATA *data, threadData_t *threadData)
4199 {
4200 <%calls%>
4201 }
4202 >>)
4203 +
4204 (if multiFile then
4205 (<<
4206
4207 #if defined(__cplusplus)
4208 }
4209 #endif
4210 >> +
4211 closeFile())))
4212
4213 // fncalls
4214 '<%name%>(data, threadData);<%\n%>'
4215
4216 )
4217
4218 let &eqFuncs += file
4219 fncalls
4220 end functionEquationsMultiFiles;
4221
4222 1204 template functionInitialEquations(list<SimEqSystem> initalEquations, Integer numInitialEquations, String fileNamePrefix, String fullPathPrefix, String modelNamePrefix, Boolean init)
4223 "Generates function in simulation file."
4224 ::=
4225 let () = System.tmpTickReset(0)
4226 let &eqfuncs = buffer ""
4227 let fncalls = functionEquationsMultiFiles(initalEquations, numInitialEquations, Flags.getConfigInt(Flags.EQUATIONS_PER_FILE),
4228 fileNamePrefix, fullPathPrefix, modelNamePrefix, "functionInitialEquations", "06inz", &eqfuncs, /* not static */ false,
4229 /* do optimize */ false, /* initial */ init)
4230
4231 <<
4232 <%eqfuncs%>
4233
4234 int <%symbolName(modelNamePrefix,"functionInitialEquations")%>(DATA *data, threadData_t *threadData)
4235 {
4236 data->simulationInfo->discreteCall = 1;
4237 <%fncalls %>
4238 data->simulationInfo->discreteCall = 0;
4239
4240 return 0;
4241 }
4242 >>
4243 end functionInitialEquations;
4244
4245 1166 template functionInitialEquations_lambda0(list<SimEqSystem> initalEquations_lambda0, String modelNamePrefix)
4246 "Generates function in simulation file."
4247 ::=
4248 match initalEquations_lambda0
4249 case {} then
4250 <<
4251
4252 /* No <%symbolName(modelNamePrefix,"functionInitialEquations_lambda0")%> function */
4253
4254 >>
4255 else
4256 let () = System.tmpTickReset(0)
4257 let eqfuncs = (initalEquations_lambda0 |> eq =>
4258 equation_impl(-1, -1, eq, contextSimulationDiscrete, modelNamePrefix, true) ;separator="\n")
4259 let &chunks = buffer ""
4260 let calls = equations_call(initalEquations_lambda0, modelNamePrefix, contextSimulationDiscrete, '', false, &chunks)
4261 <<
4262 <%eqfuncs%>
4263
4264 <%chunks%>
4265 int <%symbolName(modelNamePrefix,"functionInitialEquations_lambda0")%>(DATA *data, threadData_t *threadData)
4266 {
4267 data->simulationInfo->discreteCall = 1;
4268 <%calls%>
4269 data->simulationInfo->discreteCall = 0;
4270
4271 return 0;
4272 }
4273 >>
4274 end match
4275 end functionInitialEquations_lambda0;
4276
4277 28 template functionRemovedInitialEquationsBody(SimEqSystem eq, Text &varDecls, Text &varFrees, Text &eqs, String modelNamePrefix)
4278 "Generates an equation."
4279 ::=
4280 match eq
4281 case e as SES_RESIDUAL(__) then
4282 match exp
4283 case DAE.SCONST(__) then
4284 'res = 0;'
4285 else
4286 let &preExp = buffer ""
4287 let expPart = daeExp(exp, contextOther, &preExp, &varDecls, &varFrees, &eqs)
4288 <<
4289 <% if profileAll() then 'SIM_PROF_TICK_EQ(<%e.index%>);' %>
4290 <%preExp%>res = <%expPart%>;
4291 <% if profileAll() then 'SIM_PROF_ACC_EQ(<%e.index%>);' %>
4292 if(fabs(res) > 1e-5)
4293 {
4294 errorStreamPrint(OMC_LOG_INIT, 0, "The initialization problem is inconsistent due to the following equation: 0 != %g = <%dumpExp(exp,"\"")%>", res);
4295 return 1;
4296 }
4297 >>
4298 end match
4299 case SES_FOR_RESIDUAL(__) then "case 8"
4300 else
4301 let &eqs += equation_impl(-1, -1, eq, contextSimulationDiscrete, modelNamePrefix, true)
4302 equation_call(eq, modelNamePrefix, contextSimulationDiscrete)
4303 end match
4304 end functionRemovedInitialEquationsBody;
4305
4306 1204 template functionRemovedInitialEquations(list<SimEqSystem> removedInitalEquations, String modelNamePrefix)
4307 "Generates function in simulation file."
4308 ::=
4309 let &varDecls = buffer ""
4310 let &varFrees = buffer ""
4311 let &tmp = buffer ""
4312
4313 let body = (removedInitalEquations |> eq2 =>
4314 functionRemovedInitialEquationsBody(eq2, &varDecls, &varFrees, &tmp, modelNamePrefix)
4315 ;separator="\n")
4316
4317 <<
4318 <%tmp%>
4319 int <%symbolName(modelNamePrefix,"functionRemovedInitialEquations")%>(DATA *data, threadData_t *threadData)
4320 {
4321 const int *equationIndexes = NULL;
4322 double res = 0.0;
4323 <%varDecls%>
4324
4325 <%body%>
4326
4327 _return: OMC_LABEL_UNUSED ;
4328 <%varFrees%>
4329 return 0;
4330 }
4331 >>
4332 end functionRemovedInitialEquations;
4333
4334 1204 template functionStoreDelayed(DelayedExpression delayed, String modelNamePrefix)
4335 "Generates function in simulation file."
4336 ::=
4337 let &varDecls = buffer ""
4338 let &varFrees = buffer ""
4339 let &auxFunction = buffer ""
4340 let storePart = (match delayed case DELAYED_EXPRESSIONS(__) then (delayedExps |> (id, (e, d, delayMax)) =>
4341 let &preExp = buffer ""
4342 let eRes = daeExp(e, contextSimulationNonDiscrete, &preExp, &varDecls, &varFrees, &auxFunction)
4343 let delayExp = daeExp(d, contextSimulationNonDiscrete, &preExp, &varDecls, &varFrees, &auxFunction)
4344 let delayExpMax = daeExp(delayMax, contextSimulationNonDiscrete, &preExp, &varDecls, &varFrees, &auxFunction)
4345 <<
4346 equationIndexes[1] = <%id%>;
4347 <%preExp%>
4348 storeDelayedExpression(data, threadData, <%id%>, <%eRes%>, <%delayExp%>, <%delayExpMax%>);<%\n%>
4349 >>
4350 ))
4351 <<
4352 <%auxFunction%>
4353 int <%symbolName(modelNamePrefix,"function_storeDelayed")%>(DATA *data, threadData_t *threadData)
4354 {
4355 int equationIndexes[2] = {1,-1};
4356 <%varDecls%>
4357 <%storePart%>
4358
4359 _return: OMC_LABEL_UNUSED ;
4360 <%varFrees%>
4361 return 0;
4362 }
4363 >>
4364 end functionStoreDelayed;
4365
4366 1204 template functionStoreSpatialDistribution(SpatialDistributionInfo spatialInfo, String modelNamePrefix)
4367 "Generates function in simulation file."
4368 ::=
4369 let &varDecls = buffer ""
4370 let &varFrees = buffer ""
4371 let &auxFunction = buffer ""
4372 let storePart = (match spatialInfo case SPATIAL_DISTRIBUTION_INFO(__) then (spatialDistributions |> SPATIAL_DISTRIBUTION(index=index, in0=in0, in1=in1, pos=pos, dir=dir, condition=condition) =>
4373 let &preExp = buffer ""
4374 let in0T = daeExp(in0, contextSimulationNonDiscrete, &preExp, &varDecls, &varFrees, &auxFunction)
4375 let in1T = daeExp(in1, contextSimulationNonDiscrete, &preExp, &varDecls, &varFrees, &auxFunction)
4376 let posT = daeExp(pos, contextSimulationNonDiscrete, &preExp, &varDecls, &varFrees, &auxFunction)
4377 let dirT = daeExp(dir, contextSimulationNonDiscrete, &preExp, &varDecls, &varFrees, &auxFunction)
4378 // TODO @kabdelhak Use index of equation here, not the index of the spatial distribution
4379 let storeStmts =
4380 <<
4381 equationIndexes[1] = <%index%>;
4382 <%preExp%>
4383 storeSpatialDistribution(data, threadData, <%index%>, <%in0T%>, <%in1T%>, <%posT%>, <%dirT%>);
4384 >>
4385 // When the spatialDistribution() operator sits inside an if-branch its
4386 // evaluation is guarded by an event; the store must use the same guard,
4387 // otherwise the operator's buffer is mutated while it is inactive (#16099).
4388 match condition
4389 case SOME(cond) then
4390 let &condPreExp = buffer ""
4391 let condT = daeExp(cond, contextSimulationNonDiscrete, &condPreExp, &varDecls, &varFrees, &auxFunction)
4392 <<
4393 <%condPreExp%>
4394 if(<%condT%>)
4395 {
4396 <%storeStmts%>
4397 }<%\n%>
4398 >>
4399 else
4400 <<
4401 <%storeStmts%><%\n%>
4402 >>
4403 ))
4404 <<
4405 <%auxFunction%>
4406 int <%symbolName(modelNamePrefix,"function_storeSpatialDistribution")%>(DATA *data, threadData_t *threadData)
4407 {
4408 int equationIndexes[2] = {1,-1};
4409 <%varDecls%>
4410 <%storePart%>
4411
4412 _return: OMC_LABEL_UNUSED ;
4413 <%varFrees%>
4414 return 0;
4415 }
4416 >>
4417 end functionStoreSpatialDistribution;
4418
4419 1204 template functionInitSpatialDistribution(SpatialDistributionInfo spatialInfo, String modelNamePrefix)
4420 "Generates function in simulation file."
4421 ::=
4422 let &varDecls = buffer ""
4423 let &varFrees = buffer ""
4424 let &auxFunction = buffer ""
4425 let storePart = (match spatialInfo case SPATIAL_DISTRIBUTION_INFO(__) then (spatialDistributions |> SPATIAL_DISTRIBUTION(index=index, initPnts=initPnts, initVals=initVals, initSize=initSize) =>
4426 let &preExp = buffer ""
4427 let initPntsT = daeExp(initPnts, contextSimulationNonDiscrete, &preExp, &varDecls, &varFrees, &auxFunction)
4428 let initValsT = daeExp(initVals, contextSimulationNonDiscrete, &preExp, &varDecls, &varFrees, &auxFunction)
4429 <<
4430 <%preExp%>
4431 initSpatialDistribution(data, threadData, <%index%>, &<%initPntsT%>, &<%initValsT%>, <%initSize%>);<%\n%>
4432 >>
4433 ))
4434 <<
4435 <%auxFunction%>
4436 int <%symbolName(modelNamePrefix,"function_initSpatialDistribution")%>(DATA *data, threadData_t *threadData)
4437 {
4438 <%varDecls%>
4439 <%storePart%>
4440
4441 _return: OMC_LABEL_UNUSED ;
4442 <%varFrees%>
4443 return 0;
4444 }
4445 >>
4446 end functionInitSpatialDistribution;
4447
4448 //------------------------------------
4449 // Begin: Modified functions for HpcOm
4450 //------------------------------------
4451
4452 7 template functionXXX_systems_HPCOM(list<list<SimEqSystem>> eqs, String name, Text &loop, Text &varDecls, Text &varFrees, Option<tuple<Schedule,Schedule,Schedule>> hpcOmSchedulesOpt, String modelNamePrefixStr)
4453 ::=
4454 let funcs = (eqs |> eq hasindex i0 fromindex 0 => functionXXX_system_HPCOM(eq,name,i0,hpcOmSchedulesOpt, modelNamePrefixStr) ; separator="\n")
4455 match listLength(eqs)
4456 case 0 then //empty case
4457 let &loop +=
4458 <<
4459 /* no <%name%> systems */
4460 >>
4461 <<
4462 void terminateHpcOmThreads()
4463 {
4464
4465 }
4466 >>
4467 case 1 then //1 function
4468 let &loop +=
4469 <<
4470 function<%name%>_system0(data, threadData);
4471 >>
4472 funcs //just the one function
4473 case nFuncs then //2 and more
4474 let funcNames = eqs |> e hasindex i0 fromindex 0 => 'function<%name%>_system<%i0%>' ; separator=",\n"
4475 let &varDecls += 'int id;<%\n%>'
4476 let &loop +=
4477 <<
4478 for(id=0; id<<%nFuncs%>; id++) {
4479 function<%name%>_systems[id](data, threadData);
4480 }
4481 >>
4482 /* Text before the function head */
4483 <<
4484 <%funcs%>
4485 static void (*function<%name%>_systems[<%nFuncs%>])(DATA *, threadData_t *) = {
4486 <%funcNames%>
4487 };
4488 >>
4489 end functionXXX_systems_HPCOM;
4490
4491 6 template functionXXX_system_HPCOM(list<SimEqSystem> derivativEquations, String name, Integer n, Option<tuple<Schedule,Schedule,Schedule>> hpcOmSchedulesOpt, String modelNamePrefixStr)
4492 ::=
4493 let type = getConfigString(HPCOM_CODE)
4494 match hpcOmSchedulesOpt
4495 case SOME((hpcOmSchedule as EMPTYSCHEDULE(__),_,_)) then
4496 <<
4497 void terminateHpcOmThreads()
4498 {
4499 }
4500
4501 <%functionXXX_system(derivativEquations,name,n,modelNamePrefixStr)%>
4502 >>
4503 case SOME((hpcOmSchedule as TASKDEPSCHEDULE(__),_,_)) then
4504 let taskEqs = functionXXX_system0_HPCOM_TaskDep(hpcOmSchedule.tasks, derivativEquations, type, name, modelNamePrefixStr); separator="\n"
4505 <<
4506 void terminateHpcOmThreads()
4507 {
4508 }
4509
4510 /* using type: <%type%> */
4511 void function<%name%>_system<%n%>(DATA *data, threadData_t *threadData)
4512 {
4513 <%taskEqs%>
4514 }
4515 >>
4516 case SOME((hpcOmSchedule as LEVELSCHEDULE(__),_,_)) then
4517 let odeEqs = hpcOmSchedule.tasksOfLevels |> tasks => functionXXX_system0_HPCOM_Level(derivativEquations,name,tasks,type,modelNamePrefixStr); separator="\n"
4518 <<
4519 void terminateHpcOmThreads()
4520 {
4521 }
4522
4523 /* using type: <%type%> */
4524 void function<%name%>_system<%n%>(DATA *data, threadData_t *threadData)
4525 {
4526 int fail=0;
4527 omp_set_dynamic(0);
4528 #pragma omp parallel num_threads(<%getConfigInt(NUM_PROC)%>)
4529 {
4530 OMC_TRY_TOP()
4531 <%odeEqs%>
4532 OMC_CATCH_TOP(fail=1)
4533 }
4534 if (fail) {
4535 OMC_THROW_INTERNAL()
4536 }
4537 }
4538 >>
4539 case SOME((hpcOmSchedule as THREADSCHEDULE(__),_,_)) then
4540 let locks = hpcOmSchedule.outgoingDepTasks |> task => function_HPCOM_createLockByDepTask(task, "lock", type); separator="\n"
4541 let initlocks = hpcOmSchedule.outgoingDepTasks |> task => function_HPCOM_initializeLockByDepTask(task, "lock", type); separator="\n"
4542 let assignLocks = hpcOmSchedule.outgoingDepTasks |> task => function_HPCOM_assignLockByDepTask(task, "lock", type); separator="\n"
4543 match type
4544 case ("openmp") then
4545 let taskEqs = functionXXX_system0_HPCOM_Thread(derivativEquations,name,hpcOmSchedule.threadTasks, type, modelNamePrefixStr); separator="\n"
4546 <<
4547 void terminateHpcOmThreads()
4548 {
4549 }
4550
4551 /* using type: <%type%> */
4552 static int initialized = 0;
4553 void function<%name%>_system<%n%>(DATA *data, threadData_t *threadData)
4554 {
4555 omp_set_dynamic(0);
4556 //create locks
4557 <%locks%>
4558 if(!initialized)
4559 {
4560 <%initlocks%>
4561
4562 //set locks
4563 <%assignLocks%>
4564
4565 initialized = 1;
4566 }
4567
4568 <%taskEqs%>
4569 }
4570 >>
4571 case ("pthreads") then
4572 let threadDecl = arrayList(hpcOmSchedule.threadTasks) |> tt hasindex i0 fromindex 0 => functionXXX_system0_HPCOM_PThread_decl(i0); separator="\n"
4573 let threadFuncs = arrayList(hpcOmSchedule.threadTasks) |> tt hasindex i0 fromindex 0 => functionXXX_system0_HPCOM_PThread_func(derivativEquations, name, n, hpcOmSchedule.threadTasks, type, i0, modelNamePrefixStr); separator="\n"
4574 let threadFuncCalls = arrayList(hpcOmSchedule.threadTasks) |> tt hasindex i0 fromindex 0 => functionXXX_system0_HPCOM_PThread_call(name, n, i0); separator="\n"
4575 let threadStart = arrayList(hpcOmSchedule.threadTasks) |> tt hasindex i0 fromindex 0 => functionXXX_system0_HPCOM_PThread_start(i0); separator="\n"
4576
4577 let threadLocks = arrayList(hpcOmSchedule.threadTasks) |> tt hasindex i0 fromindex 0 => function_HPCOM_createLockByLockName(i0, "th_lock", type); separator="\n"
4578 let threadLocks1 = arrayList(hpcOmSchedule.threadTasks) |> tt hasindex i0 fromindex 0 => function_HPCOM_createLockByLockName(i0, "th_lock1", type); separator="\n"
4579 let threadLocksInit = arrayList(hpcOmSchedule.threadTasks) |> tt hasindex i0 fromindex 0 => function_HPCOM_initializeLockByLockName(i0, "th_lock", type); separator="\n"
4580 let threadLocksInit1 = arrayList(hpcOmSchedule.threadTasks) |> tt hasindex i0 fromindex 0 => function_HPCOM_initializeLockByLockName(i0, "th_lock1", type); separator="\n"
4581 let threadAssignLocks = arrayList(hpcOmSchedule.threadTasks) |> tt hasindex i0 fromindex 0 => function_HPCOM_assignLockByLockName(i0, "th_lock", type); separator="\n"
4582 let threadAssignLocks1 = arrayList(hpcOmSchedule.threadTasks) |> tt hasindex i0 fromindex 0 => function_HPCOM_assignLockByLockName(i0, "th_lock1", type); separator="\n"
4583 let threadReleaseLocks = arrayList(hpcOmSchedule.threadTasks) |> tt hasindex i0 fromindex 0 => function_HPCOM_releaseLockByLockName(i0, "th_lock", type); separator="\n"
4584
4585 <<
4586 // number of threads: <%arrayLength(hpcOmSchedule.threadTasks)%>
4587 static int finished; //set to 1 if the hpcom-threads should be destroyed
4588
4589 <%threadDecl%>
4590
4591 <%locks%>
4592
4593 <%threadLocks%>
4594 <%threadLocks1%>
4595
4596 void terminateHpcOmThreads()
4597 {
4598 finished = 1;
4599
4600 //Start the threads one last time
4601 <%threadReleaseLocks%>
4602 }
4603
4604 <%threadFuncs%>
4605
4606 /* using type: <%type%> */
4607 static int initialized = 0;
4608 void function<%name%>_system<%n%>(DATA *data, threadData_t *threadData)
4609 {
4610 if(!initialized)
4611 {
4612 <%initlocks%>
4613 <%threadLocksInit%>
4614 <%threadLocksInit1%>
4615
4616 //set locks
4617 <%assignLocks%>
4618
4619 <%threadAssignLocks%>
4620 <%threadAssignLocks1%>
4621
4622 <%threadFuncCalls%>
4623 initialized = 1;
4624 }
4625
4626 //Start the threads
4627 <%threadReleaseLocks%>
4628
4629 //"join"
4630 <%threadAssignLocks1%>
4631 }
4632 >>
4633 case ("pthreads_spin") then
4634 let threadDecl = arrayList(hpcOmSchedule.threadTasks) |> tt hasindex i0 fromindex 0 => functionXXX_system0_HPCOM_PThread_decl(i0); separator="\n"
4635 let threadFuncs = arrayList(hpcOmSchedule.threadTasks) |> tt hasindex i0 fromindex 0 => functionXXX_system0_HPCOM_PThread_func(derivativEquations, name, n, hpcOmSchedule.threadTasks, type, i0, modelNamePrefixStr); separator="\n"
4636 let threadFuncCalls = arrayList(hpcOmSchedule.threadTasks) |> tt hasindex i0 fromindex 0 => functionXXX_system0_HPCOM_PThread_call(name, n, i0); separator="\n"
4637 let threadStart = arrayList(hpcOmSchedule.threadTasks) |> tt hasindex i0 fromindex 0 => functionXXX_system0_HPCOM_PThread_start(i0); separator="\n"
4638
4639 let threadLocks = arrayList(hpcOmSchedule.threadTasks) |> tt hasindex i0 fromindex 0 => function_HPCOM_createLockByLockName(i0, "th_lock", "pthreads"); separator="\n"
4640 let threadLocks1 = arrayList(hpcOmSchedule.threadTasks) |> tt hasindex i0 fromindex 0 => function_HPCOM_createLockByLockName(i0, "th_lock1", "pthreads"); separator="\n"
4641 let threadLocksInit = arrayList(hpcOmSchedule.threadTasks) |> tt hasindex i0 fromindex 0 => function_HPCOM_initializeLockByLockName(i0, "th_lock", "pthreads"); separator="\n"
4642 let threadLocksInit1 = arrayList(hpcOmSchedule.threadTasks) |> tt hasindex i0 fromindex 0 => function_HPCOM_initializeLockByLockName(i0, "th_lock1", "pthreads"); separator="\n"
4643 let threadAssignLocks = arrayList(hpcOmSchedule.threadTasks) |> tt hasindex i0 fromindex 0 => function_HPCOM_assignLockByLockName(i0, "th_lock", "pthreads"); separator="\n"
4644 let threadAssignLocks1 = arrayList(hpcOmSchedule.threadTasks) |> tt hasindex i0 fromindex 0 => function_HPCOM_assignLockByLockName(i0, "th_lock1", "pthreads"); separator="\n"
4645 let threadReleaseLocks = arrayList(hpcOmSchedule.threadTasks) |> tt hasindex i0 fromindex 0 => function_HPCOM_releaseLockByLockName(i0, "th_lock", "pthreads"); separator="\n"
4646
4647 <<
4648 static int finished; //set to 1 if the hpcom-threads should be destroyed
4649
4650 <%threadDecl%>
4651
4652 <%locks%>
4653
4654 <%threadLocks%>
4655 <%threadLocks1%>
4656
4657 void terminateHpcOmThreads()
4658 {
4659 finished = 1;
4660
4661 //Start the threads one last time
4662 <%threadReleaseLocks%>
4663 }
4664
4665 <%threadFuncs%>
4666
4667 /* using type: <%type%> */
4668 static int initialized = 0;
4669 void function<%name%>_system<%n%>(DATA *data, threadData_t *threadData)
4670 {
4671 if(!initialized)
4672 {
4673 finished = 0;
4674
4675 <%initlocks%>
4676 <%threadLocksInit%>
4677 <%threadLocksInit1%>
4678
4679 //set locks
4680 <%assignLocks%>
4681
4682 <%threadAssignLocks%>
4683 <%threadAssignLocks1%>
4684
4685 <%threadFuncCalls%>
4686 initialized = 1;
4687 }
4688
4689 //Start the threads
4690 <%threadReleaseLocks%>
4691
4692 //"join"
4693 <%threadAssignLocks1%>
4694 }
4695 >>
4696
4697 end functionXXX_system_HPCOM;
4698
4699 ✗ template functionXXX_system0_HPCOM_Level(list<SimEqSystem> derivativEquations, String name, TaskList tasksOfLevel, String iType, String modelNamePrefixStr)
4700 ::=
4701 match(tasksOfLevel)
4702 case(PARALLELTASKLIST(__)) then
4703 let odeEqs = tasks |> task => functionXXX_system0_HPCOM_Level0Section(derivativEquations,name,task,iType,modelNamePrefixStr); separator="\n"
4704 <<
4705 #pragma omp sections
4706 {
4707 <%odeEqs%>
4708 }
4709 >>
4710 case(SERIALTASKLIST(__)) then
4711 let odeEqs = tasks |> task => functionXXX_system0_HPCOM_Level0(derivativEquations,name,task,iType,modelNamePrefixStr); separator="\n"
4712 <<
4713 #pragma omp master
4714 {
4715 <%odeEqs%>
4716 }
4717 #pragma omp barrier
4718 >>
4719 else
4720 <<
4721
4722 >>
4723 end functionXXX_system0_HPCOM_Level;
4724
4725 ✗ template functionXXX_system0_HPCOM_Level0(list<SimEqSystem> derivativEquations, String name, Task iTask, String iType, String modelNamePrefixStr)
4726 ::=
4727 <<
4728 <%function_HPCOM_Task(derivativEquations,name,iTask,iType,modelNamePrefixStr)%>
4729 >>
4730 end functionXXX_system0_HPCOM_Level0;
4731
4732 ✗ template functionXXX_system0_HPCOM_Level0Section(list<SimEqSystem> derivativEquations, String name, Task iTask, String iType, String modelNamePrefixStr)
4733 ::=
4734 <<
4735 #pragma omp section
4736 {
4737 int fail=0;
4738 OMC_TRY_TOP()
4739 <%function_HPCOM_Task(derivativEquations,name,iTask,iType,modelNamePrefixStr)%>
4740 OMC_CATCH_TOP(fail=1)
4741 if (fail) {
4742 OMC_THROW_INTERNAL()
4743 }
4744 }
4745 >>
4746 end functionXXX_system0_HPCOM_Level0Section;
4747
4748 ✗ template functionXXX_system0_HPCOM_TaskDep(list<tuple<Task,list<Integer>>> tasks, list<SimEqSystem> derivativEquations, String iType, String name, String modelNamePrefixStr)
4749 ::=
4750 let odeEqs = tasks |> t => functionXXX_system0_HPCOM_TaskDep0(t,derivativEquations, iType, name, modelNamePrefixStr); separator="\n"
4751 <<
4752
4753 int t[0];
4754 #pragma omp parallel
4755 {
4756 #pragma omp master
4757 {
4758 <%odeEqs%>
4759 }
4760 }
4761 >>
4762 end functionXXX_system0_HPCOM_TaskDep;
4763
4764 ✗ template functionXXX_system0_HPCOM_TaskDep0(tuple<Task,list<Integer>> taskIn, list<SimEqSystem> derivativEquations, String iType, String name, String modelNamePrefixStr)
4765 ::=
4766 match taskIn
4767 case ((task as CALCTASK(__),parents)) then
4768 let taskEqs = function_HPCOM_Task(derivativEquations, name, task, iType, modelNamePrefixStr); separator="\n"
4769 let parentDependencies = parents |> p => 't[<%p%>]'; separator = ","
4770 let depIn = if intGt(listLength(parents),0) then 'depend(in:<%parentDependencies%>)' else ""
4771 <<
4772 #pragma omp task <%depIn%> depend(out:t[<%task.index%>])
4773 {
4774 <%taskEqs%>
4775 }
4776 >>
4777 end functionXXX_system0_HPCOM_TaskDep0;
4778
4779 4 template functionXXX_system0_HPCOM_Thread(list<SimEqSystem> derivativEquations, String name, array<list<Task>> threadTasks, String iType, String modelNamePrefixStr)
4780 ::=
4781 let odeEqs = arrayList(threadTasks) |> tt => functionXXX_system0_HPCOM_Thread0(derivativEquations,name,tt,iType,modelNamePrefixStr); separator="\n"
4782 match iType
4783 case ("openmp") then
4784 <<
4785 if (omp_get_dynamic())
4786 omp_set_dynamic(0);
4787 #pragma omp parallel sections num_threads(<%arrayLength(threadTasks)%>)
4788 {
4789 <%odeEqs%>
4790 }
4791 >>
4792 case ("pthreads") then
4793 <<
4794 //not implemented
4795 >>
4796 case ("pthreads_spin") then
4797 <<
4798 //not implemented
4799 >>
4800
4801 end functionXXX_system0_HPCOM_Thread;
4802
4803 20 template functionXXX_system0_HPCOM_Thread0(list<SimEqSystem> derivativEquations, String name, list<Task> threadTaskList, String iType, String modelNamePrefixStr)
4804 ::=
4805 let threadTasks = threadTaskList |> tt => function_HPCOM_Task(derivativEquations,name,tt,iType,modelNamePrefixStr); separator="\n"
4806 match iType
4807 case ("openmp") then
4808 <<
4809 #pragma omp section
4810 {
4811 int fail=0;
4812 OMC_TRY_TOP()
4813 <%threadTasks%>
4814 OMC_CATCH_TOP(fail=1)
4815 if (fail) {
4816 OMC_THROW_INTERNAL()
4817 }
4818 }
4819 >>
4820 case ("pthreads") then
4821 <<
4822 <%threadTasks%>
4823 >>
4824 case ("pthreads_spin") then
4825 <<
4826 <%threadTasks%>
4827 >>
4828 end functionXXX_system0_HPCOM_Thread0;
4829
4830 1676 template function_HPCOM_Task(list<SimEqSystem> derivativEquations, String name, Task iTask, String iType, String modelNamePrefixStr)
4831 ::=
4832 match iTask
4833 case (task as CALCTASK(__)) then
4834 let odeEqs = task.eqIdc |> eq => equationNamesHPCOM_Thread_(eq,derivativEquations,contextSimulationNonDiscrete,modelNamePrefixStr); separator="\n"
4835 <<
4836 // Task <%task.index%>
4837 <%odeEqs%>
4838 // End Task <%task.index%>
4839 >>
4840 case (task as CALCTASK_LEVEL(__)) then
4841 let odeEqs = task.eqIdc |> eq => equationNamesHPCOM_Thread_(eq,derivativEquations,contextSimulationNonDiscrete,modelNamePrefixStr); separator="\n"
4842 <<
4843 <%odeEqs%>
4844 >>
4845 case(task as DEPTASK(outgoing=false)) then
4846 let assLck = function_HPCOM_assignLockByDepTask(task, "lock", iType); separator="\n"
4847 <<
4848 <%assLck%>
4849 >>
4850 case(task as DEPTASK(outgoing=true)) then
4851 let relLck = function_HPCOM_releaseLockByDepTask(task, "lock", iType); separator="\n"
4852 <<
4853 <%relLck%>
4854 >>
4855 end function_HPCOM_Task;
4856
4857 3035 template function_HPCOM_getLockNameByDepTask(Task depTask)
4858 ::=
4859 match(depTask)
4860 case(DEPTASK(sourceTask=CALCTASK(index=sourceIdx), targetTask=CALCTASK(index=targetIdx))) then
4861 '<%sourceIdx%>_<%targetIdx%>'
4862 else
4863 'invalidLockTask'
4864 end match
4865 end function_HPCOM_getLockNameByDepTask;
4866
4867 607 template function_HPCOM_initializeLockByDepTask(Task depTask, String lockPrefix, String iType)
4868 ::=
4869 let lockName = function_HPCOM_getLockNameByDepTask(depTask)
4870 <<
4871 <%function_HPCOM_initializeLockByLockName(lockName, lockPrefix, iType)%>
4872 >>
4873 end function_HPCOM_initializeLockByDepTask;
4874
4875 615 template function_HPCOM_initializeLockByLockName(String lockName, String lockPrefix, String iType)
4876 ::=
4877 match iType
4878 case ("openmp") then
4879 <<
4880 omp_init_lock(&<%lockPrefix%>_<%lockName%>);
4881 >>
4882 case ("pthreads") then
4883 <<
4884 pthread_mutex_init(&<%lockPrefix%>_<%lockName%>, NULL);
4885 >>
4886 case ("pthreads_spin") then
4887 <<
4888 pthread_spin_init(&<%lockPrefix%>_<%lockName%>, 0);
4889 >>
4890 end function_HPCOM_initializeLockByLockName;
4891
4892 607 template function_HPCOM_createLockByDepTask(Task depTask, String lockPrefix, String iType)
4893 ::=
4894 let lockName = function_HPCOM_getLockNameByDepTask(depTask)
4895 <<
4896 <%function_HPCOM_createLockByLockName(lockName, lockPrefix, iType)%>
4897 >>
4898 end function_HPCOM_createLockByDepTask;
4899
4900 615 template function_HPCOM_createLockByLockName(String lockName, String lockPrefix, String iType)
4901 ::=
4902 match iType
4903 case ("openmp") then
4904 <<
4905 static omp_lock_t <%lockPrefix%>_<%lockName%>;
4906 >>
4907 case ("pthreads") then
4908 <<
4909 static pthread_mutex_t <%lockPrefix%>_<%lockName%>;
4910 >>
4911 case ("pthreads_spin") then
4912 <<
4913 static pthread_spinlock_t <%lockPrefix%>_<%lockName%>;
4914 >>
4915 end function_HPCOM_createLockByLockName;
4916
4917 1214 template function_HPCOM_assignLockByDepTask(Task depTask, String lockPrefix, String iType)
4918 ::=
4919 let lockName = function_HPCOM_getLockNameByDepTask(depTask)
4920 <<
4921 <%function_HPCOM_assignLockByLockName(lockName, lockPrefix, iType)%>
4922 >>
4923 end function_HPCOM_assignLockByDepTask;
4924
4925 1226 template function_HPCOM_assignLockByLockName(String lockName, String lockPrefix, String iType)
4926 ::=
4927 match iType
4928 case ("openmp") then
4929 <<
4930 omp_set_lock(&<%lockPrefix%>_<%lockName%>);
4931 >>
4932 case ("pthreads") then
4933 <<
4934 pthread_mutex_lock(&<%lockPrefix%>_<%lockName%>);
4935 >>
4936 case ("pthreads_spin") then
4937 <<
4938 pthread_spin_lock(&<%lockPrefix%>_<%lockName%>);
4939 >>
4940 end function_HPCOM_assignLockByLockName;
4941
4942 607 template function_HPCOM_releaseLockByDepTask(Task depTask, String lockPrefix, String iType)
4943 ::=
4944 let lockName = function_HPCOM_getLockNameByDepTask(depTask)
4945 <<
4946 <%function_HPCOM_releaseLockByLockName(lockName, lockPrefix, iType)%>
4947 >>
4948 end function_HPCOM_releaseLockByDepTask;
4949
4950 615 template function_HPCOM_releaseLockByLockName(String lockName, String lockPrefix, String iType)
4951 ::=
4952 match iType
4953 case ("openmp") then
4954 <<
4955 omp_unset_lock(&<%lockPrefix%>_<%lockName%>);
4956 >>
4957 case ("pthreads") then
4958 <<
4959 pthread_mutex_unlock(&<%lockPrefix%>_<%lockName%>);
4960 >>
4961 case ("pthreads_spin") then
4962 <<
4963 pthread_spin_unlock(&<%lockPrefix%>_<%lockName%>);
4964 >>
4965 end function_HPCOM_releaseLockByLockName;
4966
4967 4 template functionXXX_system0_HPCOM_PThread_func(list<SimEqSystem> derivativEquations, String name, Integer n, array<list<Task>> threadTasks, String iType, Integer idx, String modelNamePrefixStr)
4968 ::=
4969 let taskEqs = functionXXX_system0_HPCOM_Thread0(derivativEquations, name, arrayGet(threadTasks,intAdd(idx,1)), iType, modelNamePrefixStr); separator="\n"
4970 let assLock = function_HPCOM_assignLockByLockName(idx, "th_lock", "pthreads"); separator="\n"
4971 let relLock = function_HPCOM_releaseLockByLockName(idx, "th_lock1", "pthreads"); separator="\n"
4972 <<
4973 void* function<%name%>_system<%n%>_thread_<%idx%>(void *arg)
4974 {
4975 DATA *data = (DATA*) arg;
4976 OMC_TRY_TOP()
4977 while(1)
4978 {
4979 <%assLock%>
4980
4981 if(finished)
4982 return NULL;
4983
4984 <%taskEqs%>
4985 <%relLock%>
4986 }
4987 OMC_CATCH_TOP(return NULL;) /* No exit status?? */
4988 }
4989 >>
4990 end functionXXX_system0_HPCOM_PThread_func;
4991
4992 4 template functionXXX_system0_HPCOM_PThread_call(String name, Integer n, Integer idx)
4993 ::=
4994 <<
4995 omc_pthread_create(&odeThread_<%idx%>, NULL, function<%name%>_system<%n%>_thread_<%idx%>, data);
4996 >>
4997 end functionXXX_system0_HPCOM_PThread_call;
4998
4999 4 template functionXXX_system0_HPCOM_PThread_decl(Integer idx)
5000 ::=
5001 <<
5002 static pthread_t odeThread_<%idx%>;
5003 >>
5004 end functionXXX_system0_HPCOM_PThread_decl;
5005
5006 4 template functionXXX_system0_HPCOM_PThread_start(Integer idx)
5007 ::=
5008 <<
5009 pthread_mutex_lock(&th_unlock_<%idx%>);
5010 >>
5011 end functionXXX_system0_HPCOM_PThread_start;
5012
5013 998 template equationNamesHPCOM_Thread_(Integer idx, list<SimEqSystem> derivativEquations, Context context, String modelNamePrefixStr)
5014 "Generates an equation.
5015 This template should not be used for a SES_RESIDUAL.
5016 Residual equations are handled differently."
5017 ::=
5018 match context
5019 case SIMULATION_CONTEXT(genDiscrete=true) then
5020 match getSimCodeEqByIndex(derivativEquations, idx)
5021 case SES_ALGORITHM(statements={}) then ""
5022 else
5023 let ix = equationIndex(getSimCodeEqByIndex(derivativEquations, idx))
5024 <<
5025 <%symbolName(modelNamePrefixStr,"eqFunction")%>_<%ix%>(data, threadData);
5026 >>
5027 else
5028 match getSimCodeEqByIndex(derivativEquations, idx)
5029 case SES_ALGORITHM(statements={}) then ""
5030 else
5031 let ix = equationIndex(getSimCodeEqByIndex(derivativEquations, idx))
5032 <<
5033 <%symbolName(modelNamePrefixStr,"eqFunction")%>_<%ix%>(data, threadData);
5034 >>
5035 end equationNamesHPCOM_Thread_;
5036
5037 //----------------------------------
5038 // End: Modified functions for HpcOm
5039 //----------------------------------
5040
5041 1204 template functionXXX_DAG(list<SimEqSystem> eqs, String name, String modelNamePrefix)
5042 ::=
5043 <<
5044 void <%symbolName(modelNamePrefix, name)%>_DAG(DATA* data, threadData_t* threadData)
5045 {
5046 const size_t eqMap[] = {<%eqs |> eq => equationIndexGeneral(eq); separator=", "%>};
5047 buildEvalDAG_<%name%>(data->modelData, sizeof(eqMap)/sizeof(size_t), eqMap);
5048 }
5049 >>
5050 end functionXXX_DAG;
5051
5052 1646 template functionXXX_system(list<SimEqSystem> eqs, String name, Integer n, String modelNamePrefix)
5053 ::=
5054 let &chunks = buffer ""
5055 let calls = equations_call(eqs, modelNamePrefix, contextSimulationNonDiscrete, 'data->simulationInfo->evalSelection', true, &chunks)
5056 <<
5057 /* forwarded equations */
5058 <%eqs |> eq => equationForward_(eq, contextSimulationNonDiscrete, modelNamePrefix); separator="\n"%>
5059
5060 <%chunks%>
5061 static void function<%name%>_system<%n%>(DATA *data, threadData_t *threadData)
5062 {
5063 <%calls%>
5064 }
5065 >>
5066 end functionXXX_system;
5067
5068 2400 template functionXXX_systems(list<list<SimEqSystem>> eqs, String name, Text &loop, Text &varDecls, Text &varFrees, String modelNamePrefixStr)
5069 ::=
5070 let funcs = (eqs |> eq hasindex i0 fromindex 0 => functionXXX_system(eq,name,i0,modelNamePrefixStr) ; separator="\n")
5071 match listLength(eqs)
5072 case 0 then //empty case
5073 let &loop +=
5074 <<
5075 /* no <%name%> systems */
5076 >>
5077 ""
5078 case 1 then //1 function
5079 let &loop +=
5080 <<
5081 function<%name%>_system0(data, threadData);
5082 >>
5083 funcs //just the one function
5084 case nFuncs then //2 and more
5085 let &varDecls += 'int id;<%\n%>'
5086 let &loop +=
5087 /* Text for the loop body that calls the equations */
5088 <<
5089 for (id = 0; id < <%nFuncs%>; id++) {
5090 function<%name%>_systems[id](data, threadData);
5091 }
5092 >>
5093 /* Text before the function head */
5094 <<
5095 <%funcs%>
5096 OMC_DISABLE_OPT
5097 static void (*const function<%name%>_systems[<%nFuncs%>])(DATA *, threadData_t *threadData) = {
5098 <%eqs |> e hasindex i0 fromindex 0 => 'function<%name%>_system<%i0%>'; separator=",\n"%>
5099 };
5100 >>
5101 end functionXXX_systems;
5102
5103
5104 12 template functionDAEModeEquationsMultiFiles(list<SimEqSystem> inEqs, Integer numEqs, Integer equationsPerFile, Context context, String fileNamePrefix, String fullPathPrefix, String modelNamePrefix, String funcName, String partName, Text &eqFuncs, Boolean static, Boolean noOpt, Boolean init)
5105 ::=
5106 let &file = buffer ""
5107 let &forwardEqs = buffer ""
5108 let multiFile = if intGt(numEqs, equationsPerFile) then "x"
5109 let fncalls = (List.balancedPartition(inEqs, equationsPerFile) |> eqs hasindex i0 =>
5110 // To file
5111 let &file += ((if multiFile then
5112 (let fileName = addFunctionIndex('<%fileNamePrefix%>_<%partName%>_part', ".c")
5113 redirectToFile(fullPathPrefix + fileName) +
5114 <<
5115 <%simulationFileHeader(fileNamePrefix)%>
5116 #if defined(__cplusplus)
5117 extern "C" {
5118 #endif<%\n%>
5119 >>)) +
5120 (eqs |> eq => (equation_impl2(-1, -1, eq, context, modelNamePrefix, static, noOpt, init); separator="\n")
5121 ) +
5122 <<
5123 >>
5124 +
5125 (if multiFile then
5126 (<<
5127
5128 #if defined(__cplusplus)
5129 }
5130 #endif
5131 >> +
5132 closeFile())))
5133
5134 let &forwardEqs +=
5135 if multiFile then
5136 ("\n/* --- forward equations --- */\n" +
5137 (eqs |> eq => equationForward_(eq, context, modelNamePrefix); separator="\n") +
5138 "\n\n")
5139
5140 // fncalls
5141 '<%(eqs |> eq => equationNames_(eq, context, modelNamePrefix); separator="\n")%>'
5142
5143 )
5144
5145
5146 let &eqFuncs += forwardEqs + file
5147 fncalls
5148 end functionDAEModeEquationsMultiFiles;
5149
5150 8 template createEquationsAndCalls(list<list<SimEqSystem>> systems, String name, Context context, String fileNamePrefix, String fullPathPrefix, String modelNamePrefix, Text eqCalls, Text eqFuncs)
5151 ::=
5152 let _ = (systems |> equations => (
5153 let fncalls = functionDAEModeEquationsMultiFiles(equations, listLength(equations),
5154 Flags.getConfigInt(Flags.EQUATIONS_PER_FILE), context, fileNamePrefix, fullPathPrefix, modelNamePrefix,
5155 "evaluateDAEResiduals", "16dae", &eqFuncs, /* Static? */ false, true /* No optimization */, /* initial? */ false)
5156 let &eqCalls += fncalls
5157 <<>>
5158 )
5159 )
5160 <<>>
5161 end createEquationsAndCalls;
5162
5163 833 template equationNamesArrayFormat(SimEqSystem eq, Context context, String name, Integer arrayIndex, Text &arrayEqs, Text &forwardEqs, String modelNamePrefixStr)
5164 "Generates an equation.
5165 This template should not be used for a SES_RESIDUAL.
5166 Residual equations are handled differently."
5167 ::=
5168 match context
5169 case SIMULATION_CONTEXT(genDiscrete=true) then
5170 match eq
5171 case SES_ALGORITHM(statements={}) then ""
5172 else
5173 let ix = equationIndex(eq)
5174 let &arrayEqs += '<%symbolName(modelNamePrefixStr,"eqFunction")%>_<%ix%>,<%\n%>'
5175 let &forwardEqs += 'extern void <%symbolName(modelNamePrefixStr,"eqFunction")%>_<%ix%>(DATA* data, threadData_t *threadData);<%\n%>'
5176 let body = 'function<%name%>_systems[<%arrayIndex%>](data);'
5177 equation_withProfile(ix, body)
5178 else
5179 match eq
5180 case SES_ALGORITHM(statements={}) then ""
5181 else
5182 let ix = equationIndex(eq)
5183 let &arrayEqs += '<%symbolName(modelNamePrefixStr,"eqFunction")%>_<%ix%>,<%\n%>'
5184 let &forwardEqs += 'extern void <%symbolName(modelNamePrefixStr,"eqFunction")%>_<%ix%>(DATA* data, threadData_t *threadData);<%\n%>'
5185 let body =
5186 <<
5187 // <%symbolName(modelNamePrefixStr,"eqFunction")%>_<%ix%>(data, threadData);
5188 function<%name%>_systems[<%arrayIndex%>](data);
5189 >>
5190 equation_withProfile(ix, body)
5191 end equationNamesArrayFormat;
5192
5193 1 template functionXXX_systems_arrayFormat(list<list<SimEqSystem>> eqlstlst, String name, Text &fncalls, Text &nrfuncs, Text &varDecls, Text &varFrees, String modelNamePrefixStr)
5194 ::=
5195 match eqlstlst
5196 case {}
5197 case {{}} then
5198 let &nrfuncs += "0"
5199 <<
5200 /* no <%name%> systems */
5201 static void (**function<%name%>_systems)(DATA *, threadData_t *) = NULL;
5202 >>
5203
5204 case {eqlst} then
5205 let &nrfuncs += listLength(eqlst)
5206 let &arrayEqs = buffer ""
5207 let &forwardEqs = buffer ""
5208 let &fncalls += (eqlst |> eq hasindex i0 => equationNamesArrayFormat(eq,contextSimulationNonDiscrete,name,i0,arrayEqs,forwardEqs,modelNamePrefixStr); separator="\n")
5209 <<
5210 /* forwarded equations */
5211 <%forwardEqs%>
5212
5213 static void (*function<%name%>_systems[<%nrfuncs%>])(DATA *, threadData_t *) = {
5214 <%arrayEqs%>
5215 };
5216
5217 >>
5218 else error(sourceInfo(), 'TODO more than ODE list in <%name%> systems')
5219 end functionXXX_systems_arrayFormat;
5220
5221 1204 template functionODE(list<list<SimEqSystem>> derivativEquations, Text method, Option<tuple<Schedule,Schedule,Schedule>> hpcOmSchedules, String modelNamePrefix)
5222 "Generates function in simulation file."
5223 ::=
5224 let () = System.tmpTickReset(0)
5225 let &nrfuncs = buffer ""
5226 let &varDecls2 = buffer ""
5227 let &varFrees2 = buffer ""
5228 let &varDecls = buffer ""
5229 let &varFrees = buffer ""
5230 let &fncalls = buffer ""
5231 let systems = if Flags.isSet(Flags.HPCOM) then
5232 (functionXXX_systems_HPCOM(derivativEquations, "ODE", &fncalls, &varDecls, &varFrees, hpcOmSchedules, modelNamePrefix))
5233 else if Flags.getConfigBool(Flags.PARMODAUTO) then
5234 (functionXXX_systems_arrayFormat(derivativEquations, "ODE", &fncalls, &nrfuncs, &varDecls, &varFrees, modelNamePrefix))
5235 else
5236 (functionXXX_systems(derivativEquations, "ODE", &fncalls, &varDecls, &varFrees, modelNamePrefix))
5237 /* let systems = functionXXX_systems(derivativEquations, "ODE", &fncalls, &varDecls) */
5238 let &tmp = buffer ""
5239 <<
5240 <%tmp%>
5241 <%systems%>
5242
5243 int <%symbolName(modelNamePrefix,"functionODE")%>(DATA *data, threadData_t *threadData)
5244 {
5245 #if !defined(OMC_MINIMAL_RUNTIME)
5246 <% if profileFunctions() then "" else "if (measure_time_flag) " %>rt_tick(SIM_TIMER_FUNCTION_ODE);
5247 #endif
5248
5249 <%varDecls%>
5250
5251 data->simulationInfo->callStatistics.functionODE++;
5252
5253 <%symbolName(modelNamePrefix,"functionLocalKnownVars")%>(data, threadData);
5254 <%if Flags.getConfigBool(Flags.PARMODAUTO) then 'PM_evaluate_ODE_system(pm_model);'
5255 else fncalls %>
5256
5257 #if !defined(OMC_MINIMAL_RUNTIME)
5258 <% if profileFunctions() then "" else "if (measure_time_flag) " %>rt_accumulate(SIM_TIMER_FUNCTION_ODE);
5259 #endif
5260
5261 return 0;
5262 }
5263 >>
5264 end functionODE;
5265
5266 1204 template functionAlgebraic(list<list<SimEqSystem>> algebraicEquations, String modelNamePrefix)
5267 "Generates function in simulation file."
5268 ::=
5269 let &varDecls = buffer ""
5270 let &varFrees = buffer ""
5271 let &fncalls = buffer ""
5272 let systems = functionXXX_systems(algebraicEquations, "Alg", &fncalls, &varDecls, &varFrees, modelNamePrefix)
5273 <<
5274 <%systems%>
5275 /* for continuous time variables */
5276 int <%symbolName(modelNamePrefix,"functionAlgebraics")%>(DATA *data, threadData_t *threadData)
5277 {
5278 <%varDecls%>
5279
5280 #if !defined(OMC_MINIMAL_RUNTIME)
5281 <% if profileFunctions() then "" else "if (measure_time_flag) " %>rt_tick(SIM_TIMER_ALGEBRAICS);
5282 #endif
5283 data->simulationInfo->callStatistics.functionAlgebraics++;
5284
5285 <%symbolName(modelNamePrefix,"function_savePreSynchronous")%>(data, threadData);
5286
5287 <%fncalls %>
5288
5289 #if !defined(OMC_MINIMAL_RUNTIME)
5290 <% if profileFunctions() then "" else "if (measure_time_flag) " %>rt_accumulate(SIM_TIMER_ALGEBRAICS);
5291 #endif
5292
5293 return 0;
5294 }
5295 >>
5296 end functionAlgebraic;
5297
5298 8 template evaluateDAEResiduals(list<list<SimEqSystem>> resEquations, String fileNamePrefix, String fullPathPrefix, String modelNamePrefix)
5299 "Generates function in simulation file."
5300 ::=
5301 let () = System.tmpTickReset(0)
5302 let &eqFuncs = buffer ""
5303 let &eqCalls = buffer ""
5304
5305 let systems = createEquationsAndCalls(resEquations, "DAERes", contextDAEmode, fileNamePrefix, fullPathPrefix, modelNamePrefix, &eqCalls, &eqFuncs)
5306 <<
5307 /*residual equations*/
5308 <%eqFuncs%>
5309
5310 /* for residuals DAE variables */
5311 OMC_DISABLE_OPT
5312 int <%symbolName(modelNamePrefix,"evaluateDAEResiduals")%>(DATA *data, threadData_t *threadData, int currentEvalStage)
5313 {
5314 int evalStages;
5315 data->simulationInfo->callStatistics.functionEvalDAE++;
5316
5317 #if !defined(OMC_MINIMAL_RUNTIME)
5318 <% if profileFunctions() then "" else "if (measure_time_flag) " %>rt_tick(SIM_TIMER_DAE);
5319 #endif
5320
5321 <%eqCalls%>
5322
5323 #if !defined(OMC_MINIMAL_RUNTIME)
5324 <% if profileFunctions() then "" else "if (measure_time_flag) " %>rt_accumulate(SIM_TIMER_DAE);
5325 #endif
5326
5327 return 0;
5328 }
5329 >>
5330 end evaluateDAEResiduals;
5331
5332 8 template genVarIndexes(list<SimVar> vars, String arrayName)
5333 "This template generates array with indexes of given variables."
5334 ::=
5335 let size = listLength(vars)
5336 let varIndexes = ( vars |> var =>
5337 (match var
5338 case SIMVAR(__) then
5339 '<%crefToIndex(name)%>'
5340 end match)
5341 ;separator=",")
5342 <<
5343 const int <%arrayName%>[<%size%>] = {<%varIndexes%>};
5344 >>
5345 end genVarIndexes;
5346
5347 7 template initializeDAEmodeData(Integer nResVars, list<SimVar> algVars, Integer nAuxVars, SparsityPattern sparsepattern, list<list<Integer>> colorList, Integer maxColor, String modelNamePrefix)
5348 "Generates initialization function for daeMode."
5349 ::=
5350 let nAlgVars = listLength(algVars)
5351 let sizeCols = listLength(sparsepattern)
5352 let sizeNNZ = lengthListElements(unzipSecond(sparsepattern))
5353 let colPtr = genSPCRSPtr(listLength(sparsepattern), sparsepattern, "colPtrIndex")
5354 let rowIndex = genSPCRSRows(lengthListElements(unzipSecond(sparsepattern)), sparsepattern, "rowIndex")
5355 let colorString = genSPColors(colorList, "daeModeData->sparsePattern->colorCols")
5356 let algIndexes = genVarIndexes(algVars, "algIndexes")
5357 <<
5358 /* initialize the daeMode variables */
5359 OMC_DISABLE_OPT
5360 int <%symbolName(modelNamePrefix,"initializeDAEmodeData")%>(DATA* data, DAEMODE_DATA* daeModeData)
5361 {
5362 /* sparse patterns */
5363 <%colPtr%>
5364 <%rowIndex%>
5365 <%algIndexes%>
5366 int i = 0;
5367
5368 daeModeData->nResidualVars = <%nResVars%>;
5369 daeModeData->nAlgebraicDAEVars = <%nAlgVars%>;
5370 daeModeData->nAuxiliaryVars = <%nAuxVars%>;
5371
5372 daeModeData->residualVars = (double*) malloc(sizeof(double)*<%nResVars%>);
5373 daeModeData->auxiliaryVars = (double*) malloc(sizeof(double)*<%nAuxVars%>);
5374
5375 /* set the function pointer */
5376 daeModeData->evaluateDAEResiduals = <%symbolName(modelNamePrefix,"evaluateDAEResiduals")%>;
5377
5378 /* prepare algebraic indexes */
5379 daeModeData->algIndexes = (int*) malloc(sizeof(int)*<%nAlgVars%>);
5380 memcpy(daeModeData->algIndexes, algIndexes, <%nAlgVars%>*sizeof(int));
5381 /* intialize sparse pattern */
5382 daeModeData->sparsePattern = allocSparsePattern(<%sizeCols%>, <%sizeNNZ%>, <%maxColor%>);
5383
5384 /* write lead index of compressed sparse column */
5385 memcpy(daeModeData->sparsePattern->leadindex, colPtrIndex, (1+<%sizeCols%>)*sizeof(int));
5386 /* makek CRS compatible */
5387 for(i=2;i<<%sizeCols%>+1;++i)
5388 daeModeData->sparsePattern->leadindex[i] += daeModeData->sparsePattern->leadindex[i-1];
5389 /* call sparse index */
5390 memcpy(daeModeData->sparsePattern->index, rowIndex, <%sizeNNZ%>*sizeof(int));
5391
5392 /* write color array */
5393 <%colorString%>
5394 return 0;
5395 }
5396 >>
5397 end initializeDAEmodeData;
5398
5399 1 template initializeDAEmodeDataResizable(Integer nResVars, list<SimVar> algVars, Integer nAuxVars, Sparsity sparsityMatrix, String nCols, Integer nRows, Context context, String modelNamePrefix)
5400 "Generates initialization function for daeMode using NBackEnd resizable sparsity pattern."
5401 ::=
5402 match sparsityMatrix
5403 case SPARSITY() then
5404 let nAlgVars = listLength(algVars)
5405 let algIndexes = genVarIndexes(algVars, "algIndexes")
5406 let &preExpC = buffer ""
5407 let &varDeclsC = buffer ""
5408 let &varFreesC = buffer ""
5409 let &auxFunctionC = buffer ""
5410 let &subC = buffer ""
5411 let countCode = (rows |> row => resizableSparsityRowCount(row, nCols, context, &preExpC, &varDeclsC, &varFreesC, &auxFunctionC, &subC) ;separator="\n")
5412 let &preExpF = buffer ""
5413 let &varDeclsF = buffer ""
5414 let &varFreesF = buffer ""
5415 let &auxFunctionF = buffer ""
5416 let &subF = buffer ""
5417 let fillCode = (rows |> row => resizableSparsityRowFill(row, nCols, context, &preExpF, &varDeclsF, &varFreesF, &auxFunctionF, &subF, 'daeModeData->sparsePattern') ;separator="\n")
5418 let &varDeclsF += 'unsigned int local_row_base = 0;<%\n%>'
5419 <<
5420 /* initialize the daeMode variables */
5421 OMC_DISABLE_OPT
5422 int <%symbolName(modelNamePrefix,"initializeDAEmodeData")%>(DATA* data, DAEMODE_DATA* daeModeData)
5423 {
5424 <%algIndexes%>
5425 unsigned int i, nnz;
5426 unsigned int col_counts[<%nCols%>];
5427 unsigned int col_fill[<%nCols%>];
5428 <%varDeclsC%><%varDeclsF%>
5429
5430 <%preExpC%><%preExpF%>
5431 <%auxFunctionC%><%auxFunctionF%>
5432
5433 daeModeData->nResidualVars = <%nResVars%>;
5434 daeModeData->nAlgebraicDAEVars = <%nAlgVars%>;
5435 daeModeData->nAuxiliaryVars = <%nAuxVars%>;
5436
5437 daeModeData->residualVars = (double*) malloc(sizeof(double)*<%nResVars%>);
5438 daeModeData->auxiliaryVars = (double*) malloc(sizeof(double)*<%nAuxVars%>);
5439
5440 /* set the function pointer */
5441 daeModeData->evaluateDAEResiduals = <%symbolName(modelNamePrefix,"evaluateDAEResiduals")%>;
5442
5443 /* prepare algebraic indexes */
5444 daeModeData->algIndexes = (int*) malloc(sizeof(int)*<%nAlgVars%>);
5445 memcpy(daeModeData->algIndexes, algIndexes, <%nAlgVars%>*sizeof(int));
5446
5447 /* initialize sparse pattern: two-pass CSC construction */
5448 memset(col_counts, 0, <%nCols%> * sizeof(unsigned int));
5449 <%countCode%>
5450
5451 nnz = 0;
5452 for (i = 0; i < <%nCols%>; i++) nnz += col_counts[i];
5453 daeModeData->sparsePattern = allocSparsePattern(<%nCols%>, nnz, 0);
5454
5455 daeModeData->sparsePattern->leadindex[0] = 0;
5456 for (i = 0; i < <%nCols%>; i++)
5457 daeModeData->sparsePattern->leadindex[i + 1] = daeModeData->sparsePattern->leadindex[i] + col_counts[i];
5458
5459 memcpy(col_fill, daeModeData->sparsePattern->leadindex, <%nCols%> * sizeof(unsigned int));
5460 <%fillCode%>
5461
5462 computeColumnColoring(daeModeData->sparsePattern, <%nRows%>, <%nCols%>);
5463 sortSparseColumns(daeModeData->sparsePattern, <%nCols%>);
5464
5465 _return: OMC_LABEL_UNUSED ;
5466 <%varFreesC%><%varFreesF%>
5467 return 0;
5468 }
5469 >>
5470 else
5471 <<
5472 int <%symbolName(modelNamePrefix,"initializeDAEmodeData")%>(DATA* data, DAEMODE_DATA* daeModeData){ return -1; }
5473 >>
5474 end initializeDAEmodeDataResizable;
5475
5476 1204 template functionDAE(list<SimEqSystem> allEquationsPlusWhen, String modelNamePrefix)
5477 "Generates function in simulation file.
5478 This is a helper of template simulationFile."
5479 ::=
5480 let &chunks = buffer ""
5481 let calls = equations_call(allEquationsPlusWhen, modelNamePrefix, contextSimulationDiscrete, '', false, &chunks)
5482 <<
5483 <%(allEquationsPlusWhen |> eq =>
5484 equation_impl(-1, -1, eq, contextSimulationDiscrete, modelNamePrefix, false); separator="\n")%>
5485
5486 <%chunks%>
5487 OMC_DISABLE_OPT
5488 int <%symbolName(modelNamePrefix,"functionDAE")%>(DATA *data, threadData_t *threadData)
5489 {
5490 int equationIndexes[1] = {0};<%/*reinits may use equation indexes, even though it has no equation...*/%>
5491 <%addRootsTempArray()%>
5492 #if !defined(OMC_MINIMAL_RUNTIME)
5493 <% if profileFunctions() then "" else "if (measure_time_flag) " %>rt_tick(SIM_TIMER_DAE);
5494 #endif
5495
5496 data->simulationInfo->needToIterate = 0;
5497 data->simulationInfo->discreteCall = 1;
5498 <%symbolName(modelNamePrefix,"functionLocalKnownVars")%>(data, threadData);
5499 <%calls%>
5500 data->simulationInfo->discreteCall = 0;
5501
5502 #if !defined(OMC_MINIMAL_RUNTIME)
5503 <% if profileFunctions() then "" else "if (measure_time_flag) " %>rt_accumulate(SIM_TIMER_DAE);
5504 #endif
5505 return 0;
5506 }
5507 >>
5508 end functionDAE;
5509
5510 1204 template functionLocalKnownVars(list<SimEqSystem> localKnownVars, String modelNamePrefix)
5511 "Generates function in simulation file.
5512 This is a helper of template simulationFile."
5513 ::=
5514 let &chunks = buffer ""
5515 let calls = equations_call(localKnownVars, modelNamePrefix, contextSimulationDiscrete, '', true, &chunks)
5516 <<
5517 <%(localKnownVars |> eq =>
5518 equation_impl(-1, -1, eq, contextSimulationDiscrete, modelNamePrefix, false)
5519 ;separator="\n")%>
5520
5521 <%chunks%>
5522 int <%symbolName(modelNamePrefix,"functionLocalKnownVars")%>(DATA *data, threadData_t *threadData)
5523 {
5524 <%calls%>
5525
5526 return 0;
5527 }
5528 >>
5529 end functionLocalKnownVars;
5530
5531 1204 template functionZeroCrossing(list<ZeroCrossing> zeroCrossings, list<SimEqSystem> equationsForZeroCrossings, String modelNamePrefix)
5532 "template functionZeroCrossing
5533 Generates function for ZeroCrossings in simulation file.
5534 This is a helper of template simulationFile."
5535 ::=
5536 let &auxFunction = buffer ""
5537 let forwardEqs = equationsForZeroCrossings |> eq => equationForward_(eq,contextSimulationNonDiscrete,modelNamePrefix); separator="\n"
5538
5539 let &varDecls2 = buffer ""
5540 let &varFrees2 = buffer ""
5541 let zeroCrossingsCode = zeroCrossingsTpl(zeroCrossings, &varDecls2, &varFrees2, &auxFunction)
5542
5543 let resDesc = (zeroCrossings |> ZERO_CROSSING(__) =>
5544 let &descStr = buffer '<%Util.escapeModelicaStringToCString(dumpExp(relation_,""))%>"'
5545 descriptionString(&descStr, iter) ;separator=",\n")
5546
5547 let desc = match zeroCrossings
5548 case {} then
5549 <<
5550 const char *<%symbolName(modelNamePrefix,"zeroCrossingDescription")%>(int i, int **out_EquationIndexes)
5551 {
5552 *out_EquationIndexes = NULL;
5553 return "empty";
5554 }
5555 >>
5556 else
5557 <<
5558 const char *<%symbolName(modelNamePrefix,"zeroCrossingDescription")%>(int i, int **out_EquationIndexes)
5559 {
5560 static const char *res[] = {<%resDesc%>};
5561 <%zeroCrossings |> ZERO_CROSSING(__) =>
5562 'static const int occurEqs<%index%>[] = {<%listLength(occurEquLst)%><%occurEquLst |> i => ',<%i%>'%>};' ; separator = "\n"%>
5563 static const int *occurEqs[] = {<%zeroCrossings |> ZERO_CROSSING(__) => occurEqsString(index, iter) ; separator = ","%>};
5564 *out_EquationIndexes = (int*) occurEqs[i];
5565 return res[i];
5566 }
5567 >>
5568
5569 let &chunks = buffer ""
5570 let calls = equations_call(equationsForZeroCrossings, modelNamePrefix, contextZeroCross, '', true, &chunks)
5571 <<
5572 <%desc%>
5573
5574 /* forwarded equations */
5575 <%forwardEqs%>
5576
5577 <%chunks%>
5578 int <%symbolName(modelNamePrefix,"function_ZeroCrossingsEquations")%>(DATA *data, threadData_t *threadData)
5579 {
5580 data->simulationInfo->callStatistics.functionZeroCrossingsEquations++;
5581
5582 <%calls%>
5583
5584 return 0;
5585 }
5586
5587 int <%symbolName(modelNamePrefix,"function_ZeroCrossings")%>(DATA *data, threadData_t *threadData, double *gout)
5588 {
5589 const int *equationIndexes = NULL;
5590
5591 <%varDecls2%>
5592 modelica_integer current_index = 0;
5593 modelica_integer start_index;
5594
5595 #if !defined(OMC_MINIMAL_RUNTIME)
5596 <% if profileFunctions() then "" else "if (measure_time_flag) " %>rt_tick(SIM_TIMER_ZC);
5597 #endif
5598 data->simulationInfo->callStatistics.functionZeroCrossings++;
5599
5600 <%zeroCrossingsCode%>
5601
5602 #if !defined(OMC_MINIMAL_RUNTIME)
5603 <% if profileFunctions() then "" else "if (measure_time_flag) " %>rt_accumulate(SIM_TIMER_ZC);
5604 #endif
5605
5606 _return: OMC_LABEL_UNUSED ;
5607 <%varFrees2%>
5608 return 0;
5609 }
5610 >>
5611 end functionZeroCrossing;
5612
5613 1646 template occurEqsString(Integer index, Option<list<SimIterator>> iter)
5614 ::=
5615 match iter
5616 case SOME(iter_) then (List.intRange(BackendDAE.getSimIteratorSize(iter_)) |> idx =>
5617 'occurEqs<%index%>';separator=",")
5618 else 'occurEqs<%index%>'
5619 end occurEqsString;
5620
5621 3334 template descriptionString(Text &descStr, Option<list<SimIterator>> iter)
5622 ::=
5623 match iter
5624 case SOME(iter_) then (List.intRange(BackendDAE.getSimIteratorSize(iter_)) |> idx =>
5625 '"[<%idx%>] <%descStr%>';separator=",\n")
5626 else <<"<%descStr%>>>
5627 end descriptionString;
5628
5629 1204 template zeroCrossingsTpl(list<ZeroCrossing> zeroCrossings, Text &varDecls, Text &varFrees, Text &auxFunction)
5630 "Generates code for zero crossings."
5631 ::=
5632 (zeroCrossings |> ZERO_CROSSING(__) =>
5633 zeroCrossingTpl(index, relation_, iter, &varDecls, &varFrees, &auxFunction)
5634 ;separator="\n";empty)
5635 end zeroCrossingsTpl;
5636
5637
5638
5639 1646 template zeroCrossingTpl(Integer index1, Exp relation, Option<list<SimIterator>> iter, Text &varDecls, Text &varFrees, Text &auxFunction)
5640 "Generates code for a zero crossing."
5641 ::=
5642 let &preExp = buffer ""
5643 let &sub = buffer ""
5644 let forHead = match iter
5645 case SOME(iter_) then (iter_ |> it =>
5646 forIterator(it, contextZeroCross, &preExp, &varDecls, &varFrees, &auxFunction, &sub)
5647 ;separator="\n";empty)
5648 else ""
5649 let forBody = match iter
5650 case SOME(iter_) then <<int tmp = <%(iter_ |> it =>
5651 forIteratorBody(it, contextZeroCross, &preExp, &varDecls, &varFrees, &auxFunction, &sub)
5652 ;separator = "")%>0<%(iter_ |> it => ")";separator = "")%>;>>
5653 else ""
5654 let tmp_ = match iter case SOME(iter_) then "+tmp" else ""
5655 let forTail = match iter
5656 case SOME(iter_) then (iter_ |> it => "}";separator="\n";empty)
5657 else ""
5658 // A RELATION's optionExpisASUB (see NBEvents.mo's asubTuple) records the for-loop
5659 // iterator a state-event condition was originally wrapped in, so CodegenCFunctions.tpl
5660 // can offset storedRelations[] per iteration. That iterator is only a genuine, in-scope
5661 // C variable here when THIS zero-crossing still has its own regenerated for-loop (iter
5662 // = SOME, via forHead above, using the very same iterator). When SimCode has already
5663 // fully unrolled this zero-crossing into an independent scalar occurrence (iter = NONE)
5664 // -- its own rel.index is then already correct on its own -- the stored iterator cref
5665 // has no corresponding loop variable to reference at all, and daeExp falls back to
5666 // printing the cref's bare (often source-level, e.g. "i") name, which doesn't compile
5667 // (see PNlib.Test2.mos and friends). Strip it in that case; rel.index alone matches the
5668 // pre-existing (working) behavior for a scalar occurrence.
5669 match SimCodeCodegenUtil.stripAsubIfNoIter(relation, isSome(iter))
5670 case exp as RELATION(__) then
5671 let e1 = daeExp(exp, contextZeroCross, &preExp, &varDecls, &varFrees, &auxFunction)
5672 <<
5673 start_index = current_index;
5674 <%forHead%>
5675 <%preExp%>
5676 <%forBody%>
5677 gout[start_index<%tmp_%>] = (<%e1%>) ? 1 : -1;
5678 current_index++;
5679 <%forTail%>
5680 >>
5681 case (exp1 as LBINARY(__)) then
5682 let e1 = daeExp(exp1, contextZeroCross, &preExp, &varDecls, &varFrees, &auxFunction)
5683 <<
5684 start_index = current_index;
5685 <%forHead%>
5686 <%preExp%>
5687 <%forBody%>
5688 gout[start_index<%tmp_%>] = (<%e1%>) ? 1 : -1;
5689 current_index++;
5690 <%forTail%>
5691 >>
5692 case (exp1 as LUNARY(__)) then
5693 let e1 = daeExp(exp1, contextZeroCross, &preExp, &varDecls, &varFrees, &auxFunction)
5694 <<
5695 start_index = current_index;
5696 <%forHead%>
5697 <%preExp%>
5698 <%forBody%>
5699 gout[start_index<%tmp_%>] = (<%e1%>) ? 1 : -1;
5700 current_index++;
5701 <%forTail%>
5702 >>
5703 case CALL(path=IDENT(name="sample"), expLst={_, start, interval}) then
5704 << >>
5705 case CALL(path=IDENT(name="integer"), expLst={exp1, idx}) then
5706 let e1 = daeExp(exp1, contextZeroCross, &preExp, &varDecls, &varFrees, &auxFunction)
5707 let indx = daeExp(idx, contextZeroCross, &preExp, &varDecls, &varFrees, &auxFunction)
5708 <<
5709 start_index = current_index;
5710 <%forHead%>
5711 <%preExp%>
5712 <%forBody%>
5713 gout[start_index<%tmp_%>] = (floor(<%e1%>) != floor(data->simulationInfo->mathEventsValuePre[<%indx%>])) ? 1 : -1;
5714 current_index++;
5715 <%forTail%>
5716 >>
5717 case CALL(path=IDENT(name="floor"), expLst={exp1, idx}) then
5718 let e1 = daeExp(exp1, contextZeroCross, &preExp, &varDecls, &varFrees, &auxFunction)
5719 let indx = daeExp(idx, contextZeroCross, &preExp, &varDecls, &varFrees, &auxFunction)
5720 <<
5721 start_index = current_index;
5722 <%forHead%>
5723 <%preExp%>
5724 <%forBody%>
5725 gout[start_index<%tmp_%>] = (floor(<%e1%>) != floor(data->simulationInfo->mathEventsValuePre[<%indx%>])) ? 1 : -1;
5726 current_index++;
5727 <%forTail%>
5728 >>
5729 case CALL(path=IDENT(name="ceil"), expLst={exp1, idx}) then
5730 let e1 = daeExp(exp1, contextZeroCross, &preExp, &varDecls, &varFrees, &auxFunction)
5731 let indx = daeExp(idx, contextZeroCross, &preExp, &varDecls, &varFrees, &auxFunction)
5732 <<
5733 start_index = current_index;
5734 <%forHead%>
5735 <%preExp%>
5736 <%forBody%>
5737 gout[start_index<%tmp_%>] = (ceil(<%e1%>) != ceil(data->simulationInfo->mathEventsValuePre[<%indx%>])) ? 1 : -1;
5738 current_index++;
5739 <%forTail%>
5740 >>
5741 case CALL(path=IDENT(name="mod"), expLst={exp1, exp2, idx}) then
5742 let e1 = daeExp(exp1, contextZeroCross, &preExp, &varDecls, &varFrees, &auxFunction)
5743 let e2 = daeExp(exp2, contextZeroCross, &preExp, &varDecls, &varFrees, &auxFunction)
5744 let indx = daeExp(idx, contextZeroCross, &preExp, &varDecls, &varFrees, &auxFunction)
5745 let tvar1 = tempDecl("modelica_real", &varDecls, &varFrees)
5746 let tvar2 = tempDecl("modelica_real", &varDecls, &varFrees)
5747 let &preExp += '<%tvar1%> = floor((<%e1%>) / (<%e2%>));<%\n%>'
5748 let &preExp += '<%tvar2%> = floor((data->simulationInfo->mathEventsValuePre[<%indx%>]) / (data->simulationInfo->mathEventsValuePre[<%indx%>+1]));<%\n%>'
5749 <<
5750 start_index = current_index;
5751 <%forHead%>
5752 <%preExp%>
5753 <%forBody%>
5754 gout[start_index<%tmp_%>] = <%tvar1%> != <%tvar2%> ? 1 : -1;
5755 current_index++;
5756 <%forTail%>
5757 >>
5758 case CALL(path=IDENT(name="div"), expLst={exp1, exp2, idx}) then
5759 let e1 = daeExp(exp1, contextZeroCross, &preExp, &varDecls, &varFrees, &auxFunction)
5760 let e2 = daeExp(exp2, contextZeroCross, &preExp, &varDecls, &varFrees, &auxFunction)
5761 let indx = daeExp(idx, contextZeroCross, &preExp, &varDecls, &varFrees, &auxFunction)
5762 <<
5763 start_index = current_index;
5764 <%forHead%>
5765 <%preExp%>
5766 <%forBody%>
5767 gout[start_index<%tmp_%>] = (trunc((<%e1%>)/(<%e2%>)) != trunc(data->simulationInfo->mathEventsValuePre[<%indx%>]/data->simulationInfo->mathEventsValuePre[<%indx%>+1])) ? 1 : -1;
5768 current_index++;
5769 <%forTail%>
5770 >>
5771 else
5772 error(sourceInfo(), ' UNKNOWN ZERO CROSSING for <%index1%>')
5773 end zeroCrossingTpl;
5774
5775 1204 template functionRelations(list<ZeroCrossing> relations, String modelNamePrefix) "template functionRelations
5776 Generates function in simulation file.
5777 This is a helper of template simulationFile."
5778 ::=
5779 let &auxFunction = buffer ""
5780 let &varDecls = buffer ""
5781 let &varFrees = buffer ""
5782 let relationsCode = relationsTpl(relations, contextZeroCross, &varDecls, &varFrees, &auxFunction)
5783 let relationsCodeElse = relationsTpl(relations, contextOther, &varDecls, &varFrees, &auxFunction)
5784
5785 let resDesc = (relations |> ZERO_CROSSING(__) =>
5786 let &descStr = buffer '<%Util.escapeModelicaStringToCString(dumpExp(relation_,""))%>"'
5787 descriptionString(&descStr, iter) ;separator=",\n")
5788
5789 let desc = match relations
5790 case {} then
5791 <<
5792 const char *<%symbolName(modelNamePrefix,"relationDescription")%>(int i)
5793 {
5794 return "empty";
5795 }
5796 >>
5797 else
5798 <<
5799 const char *<%symbolName(modelNamePrefix,"relationDescription")%>(int i)
5800 {
5801 const char *res[] = {<%resDesc%>};
5802 return res[i];
5803 }
5804 >>
5805
5806 <<
5807 <%auxFunction%>
5808 <%desc%>
5809
5810 int <%symbolName(modelNamePrefix,"function_updateRelations")%>(DATA *data, threadData_t *threadData, int evalforZeroCross)
5811 {
5812 const int *equationIndexes = NULL;
5813
5814 <%varDecls%>
5815 modelica_integer current_index = 0;
5816 modelica_integer start_index;
5817
5818 if(evalforZeroCross) {
5819 <%relationsCode%>
5820 } else {
5821 <%relationsCodeElse%>
5822 }
5823
5824 _return: OMC_LABEL_UNUSED ;
5825 <%varFrees%>
5826 return 0;
5827 }
5828 >>
5829 end functionRelations;
5830
5831 1204 template functionNextTimeEvent(list<ZeroCrossing> relations, String modelNamePrefix)
5832 "The earliest time after the current one at which a relation switches that
5833 timeEventTrigger recognizes, or DBL_MAX."
5834 ::=
5835 let &auxFunction = buffer ""
5836 let &varDecls = buffer ""
5837 let &varFrees = buffer ""
5838 let triggers = (relations |> ZERO_CROSSING(iter = NONE()) =>
5839 match timeEventTrigger(relation_)
5840 case SOME(trigger) then
5841 let &preExp = buffer ""
5842 let e = daeExp(trigger, contextOther, &preExp, &varDecls, &varFrees, &auxFunction)
5843 <<
5844 <%preExp%>
5845 tEvent = <%e%>;
5846 if (tEvent > tNow && tEvent < tNext) tNext = tEvent;
5847 >>
5848 ;separator="\n")
5849 <<
5850 <%auxFunction%>
5851 double <%symbolName(modelNamePrefix,"function_nextTimeEvent")%>(DATA *data, threadData_t *threadData)
5852 {
5853 <%if triggers then
5854 <<
5855 <%varDecls%>
5856 const double tNow = data->localData[0]->timeValue;
5857 double tEvent, tNext = DBL_MAX;
5858 <%triggers%>
5859 <%varFrees%>
5860 return tNext;
5861 >>
5862 else "return DBL_MAX;"%>
5863 }
5864 >>
5865 end functionNextTimeEvent;
5866
5867 2408 template relationsTpl(list<ZeroCrossing> relations, Context context, Text &varDecls, Text &varFrees, Text &auxFunction)
5868 "Generates code for zero crossings."
5869 ::=
5870 (relations |> ZERO_CROSSING(__) =>
5871 relationTpl(index, relation_, iter, context, &varDecls, &varFrees, &auxFunction)
5872 ;separator="\n";empty)
5873 end relationsTpl;
5874
5875 3376 template relationTpl(Integer index1, Exp relation, Option<list<SimIterator>> iter, Context context, Text &varDecls, Text &varFrees, Text &auxFunction)
5876 "Generates code for a zero crossing."
5877 ::=
5878 let &preExp = buffer ""
5879 let &sub = buffer ""
5880 let forHead = match iter
5881 case SOME(iter_) then (iter_ |> it =>
5882 forIterator(it, contextZeroCross, &preExp, &varDecls, &varFrees, &auxFunction, &sub)
5883 ;separator="\n";empty)
5884 else ""
5885 let forBody = match iter
5886 case SOME(iter_) then <<int tmp = <%(iter_ |> it =>
5887 forIteratorBody(it, contextZeroCross, &preExp, &varDecls, &varFrees, &auxFunction, &sub)
5888 ;separator = "")%>0<%(iter_ |> it => ")";separator = "")%>;>>
5889 else ""
5890 let tmp_ = match iter case SOME(iter_) then "+tmp" else ""
5891 let forTail = match iter
5892 case SOME(iter_) then (iter_ |> it => "}";separator="\n";empty)
5893 else ""
5894 // See zeroCrossingTpl above for why this strip is needed.
5895 match SimCodeCodegenUtil.stripAsubIfNoIter(relation, isSome(iter))
5896 case exp as RELATION(__) then
5897 let res = daeExp(exp, context, &preExp, &varDecls, &varFrees, &auxFunction)
5898 <<
5899 start_index = current_index;
5900 <%forHead%>
5901 <%preExp%>
5902 <%forBody%>
5903 data->simulationInfo->relations[start_index<%tmp_%>] = <%res%>;
5904 current_index++;
5905 <%forTail%>
5906 >>
5907
5908 else
5909 <<
5910 <%forHead%>
5911 /* UNKNOWN Relation for <%index1%> */
5912 current_index++;
5913 <%forTail%>
5914 >>
5915 end relationTpl;
5916
5917 4910 template crefToPrintfArg(ComponentRef cr)
5918 ::=
5919 match crefType(cr)
5920 case "modelica_real" then "%g"
5921 case "modelica_integer" then "\"OMC_INT_FORMAT\""
5922 case "modelica_boolean" then "%d"
5923 case "modelica_string" then "%s"
5924 else error(sourceInfo(), 'Do not know what printf argument to give <%CodegenUtil.crefStr(cr)%>')
5925 end match
5926 end crefToPrintfArg;
5927
5928 4876 template isPrintableCrefType(ComponentRef cr)
5929 "\"true\"/\"false\" for whether cr's type is one of the scalar modelica_* types
5930 crefToPrintfArg/crefVarInfo know how to print. External Object crefs (e.g.
5931 table handles like _tableID) are neither: they have no crefToPrintfArg format
5932 specifier and no modelData array slot for crefVarInfo to reference, so
5933 callers must skip debug-printing them entirely rather than just picking a
5934 fallback format string. Use with stringEq(..., \"true\") in an if condition,
5935 since templates always produce Text, never a real Boolean."
5936 ::=
5937 match crefType(cr)
5938 case "modelica_real" then "true"
5939 case "modelica_integer" then "true"
5940 case "modelica_boolean" then "true"
5941 case "modelica_string" then "true"
5942 else "false"
5943 end match
5944 end isPrintableCrefType;
5945
5946 441451 template crefType(ComponentRef cr) "template crefType
5947 Like cref but with cast if type is integer."
5948 ::=
5949 match cr
5950 case CREF_IDENT(__) then '<%expTypeModelica(identType)%>'
5951 case CREF_QUAL(__) then '<%crefType(componentRef)%>'
5952 else "crefType:ERROR"
5953 end match
5954 end crefType;
5955
5956 1399 template crefShortType(ComponentRef cr) "template crefType
5957 Like cref but with cast if type is integer."
5958 ::=
5959 match cr
5960 case CREF_IDENT(__) then '<%expTypeShort(identType)%>'
5961 case CREF_QUAL(__) then '<%crefShortType(componentRef)%>'
5962 else "crefType:ERROR"
5963 end match
5964 end crefShortType;
5965
5966 1204 template functionAssertsforCheck(list<SimEqSystem> algAndEqAssertsEquations, String modelNamePrefix) "template functionAssertsforCheck
5967 Generates function in simulation file.
5968 This is a helper of template simulationFile."
5969 ::=
5970 <<
5971 <%(algAndEqAssertsEquations |> eq =>
5972 equation_impl(-1, -1, eq, contextSimulationDiscrete, modelNamePrefix, false)
5973 ;separator="\n")%>
5974 /* function to check assert after a step is done */
5975 int <%symbolName(modelNamePrefix,"checkForAsserts")%>(DATA *data, threadData_t *threadData)
5976 {
5977 <%match algAndEqAssertsEquations
5978 case {} then ''
5979 else
5980 <<
5981 static const struct {long var; modelica_real lo, hi; void (*eq)(DATA*, threadData_t*);} asserts[<%listLength(algAndEqAssertsEquations)%>] = {
5982 <%algAndEqAssertsEquations |> eq => assertTableEntry(eq, modelNamePrefix); separator=",\n"%>
5983 };
5984 for (int i = 0; i < <%listLength(algAndEqAssertsEquations)%>; i++) {
5985 if (asserts[i].var >= 0) {
5986 const modelica_real v = data->localData[0]->realVars[<%simVarIndex("real", "Vars", "asserts[i].var")%>];
5987 if (v >= asserts[i].lo && v <= asserts[i].hi) continue;
5988 }
5989 asserts[i].eq(data, threadData);
5990 if (OMC_ERROR_RAISED()) break;
5991 }
5992 >>%>
5993
5994 return 0;
5995 }
5996 >>
5997 end functionAssertsforCheck;
5998
5999 7636 template assertTableEntry(SimEqSystem eq, String modelNamePrefix)
6000 "A checkForAsserts entry; the equation runs whenever the bounds do not hold."
6001 ::=
6002 let fn = '<%symbolName(modelNamePrefix,"eqFunction")%>_<%equationIndexGeneral(eq)%>'
6003 let bounds = match eq
6004 case SES_ALGORITHM(statements={STMT_ASSERT(cond=cond)}) then
6005 if boolAnd(Flags.getConfigBool(Flags.NEW_BACKEND), boolNot(Flags.getConfigBool(Flags.SIM_CODE_SCALARIZE))) then ''
6006 else match cond
6007 case r as RELATION(exp1=e as CREF(__), operator=GREATEREQ(__)) then
6008 if intEq(r.index, -1) then assertTableBounds(e, assertTableLiteral(r.exp2), 'INFINITY')
6009 case r as RELATION(exp1=e as CREF(__), operator=LESSEQ(__)) then
6010 if intEq(r.index, -1) then assertTableBounds(e, '-INFINITY', assertTableLiteral(r.exp2))
6011 case LBINARY(exp1=r1 as RELATION(exp1=e1 as CREF(__), operator=GREATEREQ(__)), operator=AND(__),
6012 exp2=r2 as RELATION(exp1=e2 as CREF(__), operator=LESSEQ(__))) then
6013 if boolAnd(intEq(r1.index, -1), boolAnd(intEq(r2.index, -1), stringEq(crefToIndex(e1.componentRef), crefToIndex(e2.componentRef)))) then
6014 assertTableBounds(e1, assertTableLiteral(r1.exp2), assertTableLiteral(r2.exp2))
6015 else ''
6016 else ''
6017 if bounds then '{<%bounds%>, <%fn%>}' else '{-1, 0.0, 0.0, <%fn%>}'
6018 end assertTableEntry;
6019
6020 7636 template assertTableBounds(DAE.Exp e, String lo, String hi)
6021 "var, lo, hi if the assert reads the variable as the table does."
6022 ::=
6023 if boolAnd(boolNot(stringEq(lo, "")), boolNot(stringEq(hi, ""))) then
6024 match e
6025 case CREF(ty=T_REAL(__)) then
6026 match cref2simvar(componentRef, getSimCode())
6027 case SIMVAR(aliasvar=NOALIAS(), index=index) then
6028 let &preExp = buffer ""
6029 let &varDecls = buffer ""
6030 let &varFrees = buffer ""
6031 let &auxFunction = buffer ""
6032 let &sub = buffer ""
6033 let access = contextCref(componentRef, contextSimulationDiscrete, &preExp, &varDecls, &varFrees, &auxFunction, &sub)
6034 if boolAnd(intGt(index, -1), boolAnd(stringEq(&sub, ""), intEq(System.stringFind(access, '(data->localData[0]->realVars[<%simVarIndex("real", "Vars", '<%index%>')%>]'), 0))) then
6035 '<%index%>, <%lo%>, <%hi%>'
6036 else ''
6037 else ''
6038 end assertTableBounds;
6039
6040 12941 template assertTableLiteral(DAE.Exp e)
6041 ::=
6042 match e
6043 case RCONST(__) then real
6044 case UNARY(operator=UMINUS(__), exp=RCONST(real=r)) then '(-<%r%>)'
6045 else ''
6046 end assertTableLiteral;
6047
6048 43 template functionlinearmodel(ModelInfo modelInfo, String modelNamePrefix) "template functionlinearmodel
6049 Generates function in simulation file."
6050 ::=
6051 match modelInfo
6052 case MODELINFO(varInfo=VARINFO(__), vars=SIMVARS(__)) then
6053 let matrixA = genMatrix("A", "n", "n", varInfo.numStateVars, varInfo.numStateVars)
6054 let matrixB = genMatrix("B", "n", "m", varInfo.numStateVars, varInfo.numInVars)
6055 let matrixC = genMatrix("C", "p", "n", varInfo.numOutVars, varInfo.numStateVars)
6056 let matrixD = genMatrix("D", "p", "m", varInfo.numOutVars, varInfo.numInVars)
6057 let matrixCz = genMatrix("Cz", "nz", "n", varInfo.numAlgVars, varInfo.numStateVars)
6058 let matrixDz = genMatrix("Dz", "nz", "m", varInfo.numAlgVars, varInfo.numInVars)
6059 let vectorX = genVector("x", "n", varInfo.numStateVars, 0)
6060 let vectorU = genVector("u", "m", varInfo.numInVars, 1)
6061 let vectorY = genVector("y", "p", varInfo.numOutVars, 2)
6062 let vectorZ = genVector("z", "nz", varInfo.numAlgVars, 2)
6063 let varNameX = getVarNameC(vars.stateVars, "x")
6064 let varNameU = getVarNameC(vars.inputVars, "u")
6065 let varNameY = getVarNameC(vars.outputVars, "y")
6066 let varNameZ = getVarNameC(vars.algVars, "z")
6067 //string def_proctedpart("\n Real x[<%varInfo.numStateVars%>](start=x0);\n Real u[<%varInfo.numInVars%>](start=u0);\n output Real y[<%varInfo.numOutVars%>];\n");
6068 <<
6069 const char *<%symbolName(modelNamePrefix,"linear_model_frame")%>()
6070 {
6071 return "model linearized_model \"<%modelNamePrefix%>\"\n"
6072 " parameter Integer n = <%varInfo.numStateVars%> \"number of states\";\n"
6073 " parameter Integer m = <%varInfo.numInVars%> \"number of inputs\";\n"
6074 " parameter Integer p = <%varInfo.numOutVars%> \"number of outputs\";\n"
6075 "\n"
6076 " parameter Real x0[n] = %s;\n"
6077 " parameter Real u0[m] = %s;\n"
6078 "\n"
6079 <%matrixA%>
6080 <%matrixB%>
6081 <%matrixC%>
6082 <%matrixD%>
6083 "\n"
6084 <%vectorX%>
6085 <%vectorU%>
6086 <%vectorY%>
6087 "\n"
6088 <%varNameX%>
6089 <%varNameU%>
6090 <%varNameY%>
6091 "equation\n"
6092 " der(x) = A * x + B * u;\n"
6093 " y = C * x + D * u;\n"
6094 "end linearized_model;\n";
6095 }
6096 const char *<%symbolName(modelNamePrefix,"linear_model_datarecovery_frame")%>()
6097 {
6098 return "model linearized_model \"<%modelNamePrefix%>\"\n"
6099 " parameter Integer n = <%varInfo.numStateVars%> \"number of states\";\n"
6100 " parameter Integer m = <%varInfo.numInVars%> \"number of inputs\";\n"
6101 " parameter Integer p = <%varInfo.numOutVars%> \"number of outputs\";\n"
6102 " parameter Integer nz = <%varInfo.numAlgVars%> \"data recovery variables\";\n"
6103 "\n"
6104 " parameter Real x0[n] = %s;\n"
6105 " parameter Real u0[m] = %s;\n"
6106 " parameter Real z0[nz] = %s;\n"
6107 "\n"
6108 <%matrixA%>
6109 <%matrixB%>
6110 <%matrixC%>
6111 <%matrixD%>
6112 <%matrixCz%>
6113 <%matrixDz%>
6114 "\n"
6115 <%vectorX%>
6116 <%vectorU%>
6117 <%vectorY%>
6118 <%vectorZ%>
6119 "\n"
6120 <%varNameX%>
6121 <%varNameU%>
6122 <%varNameY%>
6123 <%varNameZ%>
6124 "equation\n"
6125 " der(x) = A * x + B * u;\n"
6126 " y = C * x + D * u;\n"
6127 " z = Cz * x + Dz * u;\n"
6128 "end linearized_model;\n";
6129 }
6130 >>
6131 end match
6132 end functionlinearmodel;
6133
6134 ✗ template functionlinearmodelMatlab(ModelInfo modelInfo, String modelNamePrefix) "template functionlinearmodelMatlab
6135 Generates matlab functions in simulation file."
6136 ::=
6137 match modelInfo
6138 case MODELINFO(varInfo=VARINFO(__), vars=SIMVARS(__)) then
6139 let matrixA = genMatrixMatlab("A", "n", "n", varInfo.numStateVars, varInfo.numStateVars)
6140 let matrixB = genMatrixMatlab("B", "n", "m", varInfo.numStateVars, varInfo.numInVars)
6141 let matrixC = genMatrixMatlab("C", "p", "n", varInfo.numOutVars, varInfo.numStateVars)
6142 let matrixD = genMatrixMatlab("D", "p", "m", varInfo.numOutVars, varInfo.numInVars)
6143 //string def_proctedpart("\n Real x[<%varInfo.numStateVars%>](start=x0);\n Real u[<%varInfo.numInVars%>](start=u0);\n output Real y[<%varInfo.numOutVars%>];\n");
6144 <<
6145 const char *<%symbolName(modelNamePrefix,"linear_model_frame")%>()
6146 {
6147 return "function [A, B, C, D, stateVars, inputVars, outputVars] = linearized_model()\n"
6148 "%% <%modelNamePrefix%>\n"
6149 "%% der(x) = A * x + B * u\n"
6150 "%% y = C * x + D * u\n"
6151 " n = <%varInfo.numStateVars%>; %% number of states\n"
6152 " m = <%varInfo.numInVars%>; %% number of inputs\n"
6153 " p = <%varInfo.numOutVars%>; %% number of outputs\n"
6154 "\n"
6155 " x0 = %s;\n"
6156 " u0 = %s;\n"
6157 "\n"
6158 <%matrixA%>
6159 <%matrixB%>
6160 <%matrixC%>
6161 <%matrixD%>
6162 " stateVars = {<%getVarNameMatlab(vars.stateVars, "x0")%>};\n"
6163 " inputVars = {<%getVarNameMatlab(vars.inputVars, "u0")%>};\n"
6164 " outputVars = {<%getVarNameMatlab(vars.outputVars, "y0")%>};\n"
6165 " Ts = %g; %% stop time\n\n"
6166 "end";
6167 }
6168 const char *<%symbolName(modelNamePrefix,"linear_model_datarecovery_frame")%>()
6169 {
6170 errorStreamPrint(OMC_LOG_STDOUT, 0, "Linearization with data recovery not implemented for Matlab.");
6171 return "";
6172 }
6173 >>
6174 end match
6175 end functionlinearmodelMatlab;
6176
6177 ✗ template functionlinearmodelJulia(ModelInfo modelInfo, String modelNamePrefix) "template functionlinearmodelJulia
6178 Generates julia functions in simulation file."
6179 ::=
6180 match modelInfo
6181 case MODELINFO(varInfo=VARINFO(__), vars=SIMVARS(__)) then
6182 let matrixA = genMatrixJulia("A", "n", "n", varInfo.numStateVars, varInfo.numStateVars)
6183 let matrixB = genMatrixJulia("B", "n", "m", varInfo.numStateVars, varInfo.numInVars)
6184 let matrixC = genMatrixJulia("C", "p", "n", varInfo.numOutVars, varInfo.numStateVars)
6185 let matrixD = genMatrixJulia("D", "p", "m", varInfo.numOutVars, varInfo.numInVars)
6186 let matrixCz = genMatrixJulia("Cz", "nz", "n", varInfo.numAlgVars, varInfo.numStateVars)
6187 let matrixDz = genMatrixJulia("Dz", "nz", "m", varInfo.numAlgVars, varInfo.numInVars)
6188 //string def_proctedpart("\n Real x[<%varInfo.numStateVars%>](start=x0);\n Real u[<%varInfo.numInVars%>](start=u0);\n output Real y[<%varInfo.numOutVars%>];\n");
6189 <<
6190 const char *<%symbolName(modelNamePrefix,"linear_model_frame")%>()
6191 {
6192 return "function linearized_model()\n"
6193 " # <%modelNamePrefix%> #\n"
6194 " local n = <%varInfo.numStateVars%> # number of states\n"
6195 " local m = <%varInfo.numInVars%> # number of inputs\n"
6196 " local p = <%varInfo.numOutVars%> # number of outputs\n"
6197 "\n"
6198 " local x0 = %s\n"
6199 " local u0 = %s\n"
6200 "\n"
6201 <%matrixA%>
6202 <%matrixB%>
6203 <%matrixC%>
6204 <%matrixD%>
6205 " stateVars = [<%getVarNameJulia(vars.stateVars, "x0")%>]\n"
6206 " inputVars = [<%getVarNameJulia(vars.inputVars, "u0")%>]\n"
6207 " outputVars = [<%getVarNameJulia(vars.outputVars, "y0")%>]\n"
6208 " Ts = %g; #stop time\n\n"
6209 "\n"
6210 " return (n, m, p, x0, u0, A, B, C, D, stateVars, inputVars, outputVars)\n"
6211 "end";
6212 }
6213 const char *<%symbolName(modelNamePrefix,"linear_model_datarecovery_frame")%>()
6214 {
6215 errorStreamPrint(OMC_LOG_STDOUT, 0, "Linearization with data recovery not implemented for Julia.");
6216 return "";
6217 }
6218 >>
6219 end match
6220 end functionlinearmodelJulia;
6221
6222 ✗ template functionlinearmodelPython(ModelInfo modelInfo, String modelNamePrefix) "template functionlinearmodelPython
6223 Generates python functions in simulation file."
6224 ::=
6225 match modelInfo
6226 case MODELINFO(varInfo=VARINFO(__), vars=SIMVARS(__)) then
6227 let matrixA = genMatrixPython("A", "n", "n", varInfo.numStateVars, varInfo.numStateVars)
6228 let matrixB = genMatrixPython("B", "n", "m", varInfo.numStateVars, varInfo.numInVars)
6229 let matrixC = genMatrixPython("C", "p", "n", varInfo.numOutVars, varInfo.numStateVars)
6230 let matrixD = genMatrixPython("D", "p", "m", varInfo.numOutVars, varInfo.numInVars)
6231 let matrixCz = genMatrixPython("Cz", "nz", "n", varInfo.numAlgVars, varInfo.numStateVars)
6232 let matrixDz = genMatrixPython("Dz", "nz", "m", varInfo.numAlgVars, varInfo.numInVars)
6233 //string def_proctedpart("\n Real x[<%varInfo.numStateVars%>](start=x0);\n Real u[<%varInfo.numInVars%>](start=u0);\n output Real y[<%varInfo.numOutVars%>];\n");
6234 <<
6235 const char *<%symbolName(modelNamePrefix,"linear_model_frame")%>()
6236 {
6237 return "def linearized_model():\n"
6238 " # <%modelNamePrefix%>\n"
6239 " # der(x) = A * x + B * u\n"
6240 " # y = C * x + D * u\n"
6241 " n = <%varInfo.numStateVars%> # number of states\n"
6242 " m = <%varInfo.numInVars%> # number of inputs\n"
6243 " p = <%varInfo.numOutVars%> # number of outputs\n"
6244 "\n"
6245 " x0 = %s\n"
6246 " u0 = %s\n"
6247 "\n"
6248 <%matrixA%>
6249 <%matrixB%>
6250 <%matrixC%>
6251 <%matrixD%>
6252 " stateVars = [<%getVarNamePython(vars.stateVars, "x0")%>]\n"
6253 " inputVars = [<%getVarNamePython(vars.inputVars, "u0")%>]\n"
6254 " outputVars = [<%getVarNamePython(vars.outputVars, "y0")%>]\n"
6255 "\n"
6256 " return (n, m, p, x0, u0, A, B, C, D, stateVars, inputVars, outputVars)\n";
6257 }
6258 const char *<%symbolName(modelNamePrefix,"linear_model_datarecovery_frame")%>()
6259 {
6260 errorStreamPrint(OMC_LOG_STDOUT, 0, "Linearization with data recovery not implemented for Python.");
6261 return "";
6262 }
6263 >>
6264 end match
6265 end functionlinearmodelPython;
6266
6267 172 template getVarNameC(list<SimVar> simVars, String arrayName)
6268 "template getVarNameC
6269 Generates name for a variable inside a C string."
6270 ::=
6271 simVars |> var hasindex arrindex fromindex 1 => (match var
6272 case SIMVAR(__) then
6273 <<" Real '<%arrayName%>_<%Util.escapeModelicaStringToCString(escapeSingleQuoteIdent(crefStrNoUnderscore(name)))%>' = <%arrayName%>[<%arrindex%>];\n">>
6274 end match) ;separator="\n"
6275 end getVarNameC;
6276
6277 ✗ template getVarNameMatlab(list<SimVar> simVars, String arrayName) "template getVarName
6278 Generates name for a variable."
6279 ::=
6280 simVars |> var hasindex arrindex fromindex 1 => (match var
6281 case SIMVAR(__) then
6282 <<'<%crefStrMatlabSafe(name)%>'>>
6283 end match) ;separator=","
6284 end getVarNameMatlab;
6285
6286 ✗ template getVarNamePython(list<SimVar> simVars, String arrayName) "template getVarName
6287 Generates name for a variable."
6288 ::=
6289 simVars |> var hasindex arrindex fromindex 0 => (match var
6290 case SIMVAR(__) then
6291 <<'<%crefStrMatlabSafe(name)%>'>>
6292 end match) ;separator=","
6293 end getVarNamePython;
6294
6295 ✗ template getVarNameJulia(list<SimVar> simVars, String arrayName) "template getVarName
6296 Generates name for a variable."
6297 ::=
6298 simVars |> var hasindex arrindex fromindex 0 => (match var
6299 case SIMVAR(__) then
6300 <<\"<%crefStrMatlabSafe(name)%>\">>
6301 end match) ;separator=","
6302 end getVarNameJulia;
6303
6304 258 template genMatrix(String name, String row, String col, Integer rowI, Integer colI) "template genMatrix
6305 Generates Matrix for linear model"
6306 ::=
6307 match rowI
6308 case 0 then
6309 <<" parameter Real <%name%>[<%row%>, <%col%>] = zeros(<%row%>, <%col%>);%s\n\n">>
6310 case _ then
6311 match colI
6312 case 0 then
6313 <<" parameter Real <%name%>[<%row%>, <%col%>] = zeros(<%row%>, <%col%>);%s\n\n">>
6314 case _ then
6315 <<" parameter Real <%name%>[<%row%>, <%col%>] =\n\t[%s];\n\n">>
6316 end match
6317 end match
6318 end genMatrix;
6319
6320 ✗ template genMatrixMatlab(String name, String row, String col, Integer rowI, Integer colI) "template genMatrixMatlab
6321 Generates Matrix for linear model in Matlab code"
6322 ::=
6323 match rowI
6324 case 0 then
6325 <<" <%name%> = zeros(<%row%>, <%col%>);%s\n\n">>
6326 case _ then
6327 match colI
6328 case 0 then
6329 <<" <%name%> = zeros(<%row%>, <%col%>);%s\n\n">>
6330 case _ then
6331 <<" <%name%> =\t[%s];\n\n">>
6332 end match
6333 end match
6334 end genMatrixMatlab;
6335
6336 ✗ template genMatrixPython(String name, String row, String col, Integer rowI, Integer colI) "template genMatrixPython
6337 Generates Matrix for linear model in python code"
6338 ::=
6339 match rowI
6340 case 0 then
6341 <<" <%name%> = %s\n\n">>
6342 case _ then
6343 match colI
6344 case 0 then
6345 <<" <%name%> = %s\n\n">>
6346 case _ then
6347 <<" <%name%> = %s\n\n">>
6348 end match
6349 end match
6350 end genMatrixPython;
6351
6352 ✗ template genMatrixJulia(String name, String row, String col, Integer rowI, Integer colI) "template genMatrixJulia
6353 Generates Matrix for linear model in Julia code"
6354 ::=
6355 match rowI
6356 case 0 then
6357 <<" local <%name%> = zeros(<%row%>, <%col%>)%s\n">>
6358 case _ then
6359 match colI
6360 case 0 then
6361 <<" local <%name%> = zeros(<%row%>, <%col%>)%s\n">>
6362 case _ then
6363 <<" local <%name%> = [%s]\n\n">>
6364 end match
6365 end match
6366 end genMatrixJulia;
6367
6368 172 template genVector(String name, String num, Integer numI, Integer flag) "template genVector
6369 Generates variables Vectors for linear model"
6370 ::=
6371 match flag
6372 case 0 then
6373 match numI
6374 case 0 then
6375 <<" Real <%name%>[<%num%>];\n">>
6376 case _ then
6377 <<" Real <%name%>[<%num%>](start=<%name%>0);\n">>
6378 end match
6379 case 1 then
6380 match numI
6381 case 0 then
6382 <<" input Real <%name%>[<%num%>];\n">>
6383 case _ then
6384 <<" input Real <%name%>[<%num%>](start=<%name%>0);\n">>
6385 end match
6386 case 2 then
6387 match numI
6388 case 0 then
6389 <<" output Real <%name%>[<%num%>];\n">>
6390 case _ then
6391 <<" output Real <%name%>[<%num%>];\n">>
6392 end match
6393 end match
6394 end genVector;
6395
6396 1204 template functionAnalyticJacobians(list<JacobianMatrix> JacobianMatrices, String modelNamePrefix, String fileNamePrefix) "template functionAnalyticJacobians
6397 This template generates source code for all given jacobians."
6398 ::=
6399 let initialjacMats =
6400 (JacobianMatrices |> JAC_MATRIX() =>
6401 // NBackEnd jacobians carry sparsity in sparsityMatrix (SPARSITY) and use the resizable
6402 // initialization path. The runtime callback is initialAnalyticJacobianXXX, so generate
6403 // a thin wrapper that delegates to the already-generated initialResizableAnalyticJacobianXXX.
6404 let isResizable = match sparsityMatrix case SPARSITY() then 'yes' else ''
6405 if isResizable then
6406 <<
6407 int <%symbolName(modelNamePrefix,"initialAnalyticJacobian")%><%matrixName%>(DATA* data, threadData_t *threadData, JACOBIAN *jacobian)
6408 {
6409 return <%symbolName(modelNamePrefix,"initialResizableAnalyticJacobian")%><%matrixName%>(data, threadData, jacobian);
6410 }
6411 >>
6412 // Old-backend jacobians: adjoint uses transposed sparsity and row coloring,
6413 // normal uses regular sparsity and column coloring (reads from .bin or NOT_AVAILABLE).
6414 else if isAdjoint then
6415 initialAnalyticJacobians(
6416 columns,
6417 seedVars,
6418 matrixName,
6419 sparsityT,
6420 coloredRows,
6421 listLength(coloredRows),
6422 modelNamePrefix,
6423 fileNamePrefix,
6424 isAdjoint,
6425 isBidirectional,
6426 adjointJacobianIndex,
6427 adjointMatrixName)
6428 else
6429 initialAnalyticJacobians(
6430 columns,
6431 seedVars,
6432 matrixName,
6433 sparsity,
6434 coloredCols,
6435 maxColorCols,
6436 modelNamePrefix,
6437 fileNamePrefix,
6438 isAdjoint,
6439 isBidirectional,
6440 adjointJacobianIndex,
6441 adjointMatrixName)
6442 ;separator="\n")
6443
6444 let resizableSparsity = (JacobianMatrices |> JAC_MATRIX() =>
6445 initialResizableAnalyticJacobians(matrixName, columns, sparsityMatrix, numScalarElemsExp(seedVars), createJacContext(matrixName, crefsHT), isAdjoint, isBidirectional, adjointJacobianIndex, adjointMatrixName, modelNamePrefix) ;separator="\n")
6446
6447 let jacMats = (JacobianMatrices |> JAC_MATRIX() =>
6448 generateMatrix(columns, seedVars, matrixName, partitionIndex, crefsHT, modelNamePrefix) ;separator="\n\n")
6449 let jacGenericCalls = (JacobianMatrices |> JAC_MATRIX() =>
6450 genericCallBodies(generic_loop_calls, createJacContext(matrixName, crefsHT)) ;separator="\n")
6451 <<
6452 <%jacMats%>
6453
6454 <%resizableSparsity%>
6455
6456 <%initialjacMats%>
6457
6458 <%jacGenericCalls%>
6459 >>
6460 end functionAnalyticJacobians;
6461
6462 166 template resizableJacobianRows(list<JacobianColumn> columns, Sparsity sparsity, Context context)
6463 "Number of rows of a resizable Jacobian. numberOfResultVars counts a dimension
6464 that is only known at runtime as 1, then the rows are the elements of the
6465 variables the sparsity rows are solved for."
6466 ::=
6467 let nRows = (columns |> JAC_COLUMN() => numberOfResultVars; separator="\n")
6468 match context
6469 case JACOBIAN_CONTEXT(jacHT = jacHT as SOME(_)) then
6470 if hasSymbolicDims(jacobianResultVars(sparsity, jacHT)) then numScalarElemsExp(jacobianResultVars(sparsity, jacHT)) else nRows
6471 else nRows
6472 end resizableJacobianRows;
6473
6474 13375 template numScalarElemsExp(list<SimVar> vars)
6475 "Number of scalar elements of the SimVars. A C expression of the structural
6476 parameters if a dimension is only known at runtime (resizable arrays), where the
6477 parameters can still be changed with -override before the simulation."
6478 ::=
6479 if hasSymbolicDims(vars) then
6480 let &preExp = buffer ""
6481 let &varDecls = buffer ""
6482 let &varFrees = buffer ""
6483 let &auxFunction = buffer ""
6484 let terms = (vars |> v => numScalarElemsVarExp(v, &preExp, &varDecls, &varFrees, &auxFunction) ;separator=" + ")
6485 '((size_t)(<%terms%>))'
6486 else SimCodeCodegenUtil.numScalarElems(vars)
6487 end numScalarElemsExp;
6488
6489 128 template numScalarElemsVarExp(SimVar var, Text &preExp, Text &varDecls, Text &varFrees, Text &auxFunction)
6490 "Number of scalar elements of a SimVar as a C expression."
6491 ::=
6492 match var
6493 case SIMVAR(type_ = T_ARRAY(dims = dims)) then
6494 '(<%dims |> d => '(<%dimension(d, contextOther, &preExp, &varDecls, &varFrees, &auxFunction)%>)' ;separator=" * "%>)'
6495 else '1'
6496 end numScalarElemsVarExp;
6497
6498 10337 template initialResizableAnalyticJacobians(String matrixname, list<JacobianColumn> columns, Sparsity sparsity, String nCols, Context context, Boolean isAdjoint, Boolean isBidirectional, Integer adjointJacobianIndex, String adjointMatrixName, String modelNamePrefix)
6499 "Two-pass CSC construction: count nonzeros per column, allocate, then fill row indices."
6500 ::=
6501 match sparsity
6502 case EMPTY() then
6503 <<
6504 int <%symbolName(modelNamePrefix,"initialResizableAnalyticJacobian")%><%matrixname%>(DATA* data, threadData_t *threadData, JACOBIAN *jacobian)
6505 {
6506 return 1;
6507 }
6508 >>
6509 case SPARSITY() then
6510 let &preExp = buffer ""
6511 let &varDecls = buffer ""
6512 let &varFrees = buffer ""
6513 let &auxFunction = buffer ""
6514 let &sub = buffer ""
6515 let countCode = (rows |> row => resizableSparsityRowCount(row, nCols, context, &preExp, &varDecls, &varFrees, &auxFunction, &sub) ;separator="\n")
6516 let fillCode = (rows |> row => resizableSparsityRowFill(row, nCols, context, &preExp, &varDecls, &varFrees, &auxFunction, &sub, 'jacobian->sparsePattern') ;separator="\n")
6517 let &varDecls += 'unsigned int local_row_base = 0;<%\n%>'
6518 let sizeRows = resizableJacobianRows(columns, sparsity, context)
6519 // Adjoint metadata describes the primal CSC pattern using adjoint variable
6520 // names. Its outer dimension is the adjoint result count (primal columns),
6521 // and its inner dimension is the adjoint seed count (primal rows).
6522 let patternCols = if isAdjoint then '<%sizeRows%>' else '<%nCols%>'
6523 let patternRows = if isAdjoint then '<%nCols%>' else '<%sizeRows%>'
6524 let tmpvarsSize = (columns |> JAC_COLUMN() => numScalarElemsExp(columnVars); separator="\n")
6525 let constantEqns = (columns |> JAC_COLUMN() =>
6526 match constantEqns case {} then 'NULL' case _ then '<%symbolName(modelNamePrefix,"functionJac")%><%matrixname%>_constantEqns'
6527 ;separator="")
6528 let evalColumn = '<%symbolName(modelNamePrefix,"functionJac")%><%matrixname%>_column'
6529 let isRowEval = if isAdjoint then "1" else "0"
6530 let availability = if SimCodeCodegenUtil.jacobianColumnsAreEmpty(columns) then 'JACOBIAN_ONLY_SPARSITY' else 'JACOBIAN_AVAILABLE'
6531 <<
6532 int <%symbolName(modelNamePrefix,"initialResizableAnalyticJacobian")%><%matrixname%>(DATA* data, threadData_t *threadData, JACOBIAN *jacobian)
6533 {
6534 unsigned int i, nnz;
6535 unsigned int col_counts[<%patternCols%>];
6536 unsigned int col_fill[<%patternCols%>];
6537 <%varDecls%>
6538
6539 <%preExp%>
6540 <%auxFunction%>
6541
6542 initJacobian(jacobian, <%nCols%>, <%sizeRows%>, <%tmpvarsSize%>, NULL, <%evalColumn%>, <%constantEqns%>, NULL);
6543 jacobian->isRowEval = <%isRowEval%>;
6544
6545 /* Phase 1: count non-zeros per column */
6546 memset(col_counts, 0, <%patternCols%> * sizeof(unsigned int));
6547 <%countCode%>
6548
6549 /* Compute total nnz and allocate pattern */
6550 nnz = 0;
6551 for (i = 0; i < <%patternCols%>; i++) nnz += col_counts[i];
6552 jacobian->sparsePattern = allocSparsePattern(<%patternCols%>, nnz, 0);
6553 if (!jacobian->sparsePattern) return 1;
6554
6555 /* Compute leadindex as prefix sum of col_counts */
6556 jacobian->sparsePattern->leadindex[0] = 0;
6557 for (i = 0; i < <%patternCols%>; i++)
6558 jacobian->sparsePattern->leadindex[i + 1] = jacobian->sparsePattern->leadindex[i] + col_counts[i];
6559
6560 /* Phase 2: fill row indices */
6561 memcpy(col_fill, jacobian->sparsePattern->leadindex, <%patternCols%> * sizeof(unsigned int));
6562 <%fillCode%>
6563 <%varFrees%>
6564
6565 <%if isAdjoint then <<
6566 /* Adjoint evaluation traverses rows of the primal Jacobian. Convert the
6567 * generated primal CSC structure to CSR before computing row colors. */
6568 {
6569 SPARSE_PATTERN* cscPattern = jacobian->sparsePattern;
6570 jacobian->sparsePattern = cscToCsr(cscPattern, <%patternRows%>, <%patternCols%>);
6571 freeSparsePattern(cscPattern);
6572 if (!jacobian->sparsePattern) return 1;
6573 }
6574 >> %>
6575
6576 /* Compute coloring at runtime from the actual <%if isAdjoint then 'CSR (treated as CSC of the transpose)' else 'CSC'%> pattern.
6577 * The WHOLEDIM-based C loops over-approximate array equations as dense
6578 * blocks, so a compile-time coloring (derived from the exact symbolic
6579 * sparsity) would be invalid for the runtime pattern. Re-deriving it
6580 * here guarantees that no two same-color columns share a non-zero row. */
6581 computeColumnColoring(jacobian->sparsePattern, <%if isAdjoint then patternCols else patternRows%>, <%if isAdjoint then patternRows else patternCols%>);
6582
6583 <%if isBidirectional then <<
6584 /* Link the adjoint Jacobian to this forward Jacobian so that the integrators can
6585 * evaluate it bidirectionally. Whether that actually happens is decided at runtime
6586 * by initSymbolicOdeJacobian() based on the `-jacobian` flag. */
6587 {
6588 JACOBIAN* adjJac = &data->simulationInfo->analyticJacobians[<%adjointJacobianIndex%>];
6589 // initialize adjoint Jacobian with check for error and proceed to link it to the forward Jacobian
6590 if (<%symbolName(modelNamePrefix,"initialResizableAnalyticJacobian")%><%adjointMatrixName%>(data, threadData, adjJac)) return 1;
6591 jacobian->adjointJacobian = adjJac;
6592 initBidirectionalRecovery(jacobian);
6593 }
6594 >> %>
6595
6596 jacobian->availability = <%availability%>;
6597 return 0;
6598 }
6599 >>
6600 end initialResizableAnalyticJacobians;
6601
6602 1038 template resizableSparsityRowCount(SparsityRow row, String nCols, Context context, Text &preExp, Text &varDecls, Text &varFrees, Text &auxFunction, Text &sub)
6603 "Count phase: for each (row,col) pair in this SparsityRow, increment col_counts[col].
6604 For REGULAR 1D WHOLEDIM seeds (dep.kinds=[false], not rep) inside WHOLEDIM/multi-dim-WHOLEDIM sc,
6605 emits a single col_counts[v.index + _wr_k]++ (diagonal). All other cases use REDUCTION (full loop)."
6606 ::=
6607 match row
6608 // Explicitly bind 'dependencies' as 'deps' so it is accessible inside nested list iterators.
6609 // Susan does not propagate implicit record-field access into nested lambdas.
6610 case SPARSITY_ROW(dependencies=deps) then
6611 let forIter = (equation_iterators |> it => forIterator(it, context, &preExp, &varDecls, &varFrees, &auxFunction, &sub) ;separator="\n";empty)
6612 let forTail = (equation_iterators |> it => '}' ;separator="\n";empty)
6613 let bodyCode = (solved_crefs |> sc hasindex k =>
6614 // depsCode: dep-aware; for REGULAR 1D WHOLEDIM seeds uses resizableColCountRegular(_wr<%k%>).
6615 // Dep/rep condition checked inline; only valid where the outer _wr<%k%> loop variable is in scope.
6616 let depsCode = (deps |> (seed, dep, rep) =>
6617 match dep
6618 case DEPENDENCY(kinds=kinds) then
6619 if not rep then
6620 if not listEmpty(kinds) then
6621 if not listHead(kinds) then
6622 match crefSubs(seed)
6623 case {WHOLEDIM()} then resizableColCountRegular(seed, nCols, k, context, &preExp, &varDecls, &varFrees, &auxFunction)
6624 else resizableColCount(seed, nCols, context, &preExp, &varDecls, &varFrees, &auxFunction)
6625 else resizableColCount(seed, nCols, context, &preExp, &varDecls, &varFrees, &auxFunction)
6626 else resizableColCount(seed, nCols, context, &preExp, &varDecls, &varFrees, &auxFunction)
6627 else resizableColCount(seed, nCols, context, &preExp, &varDecls, &varFrees, &auxFunction)
6628 else resizableColCount(seed, nCols, context, &preExp, &varDecls, &varFrees, &auxFunction)
6629 ;separator="\n")
6630 // depsCodeReduced: always REDUCTION; used for SLICE sc (column alignment differs) and non-loop cases
6631 let depsCodeReduced = (deps |> (seed, _, _) => resizableColCount(seed, nCols, context, &preExp, &varDecls, &varFrees, &auxFunction) ;separator="\n")
6632 match crefSubs(sc)
6633 case {WHOLEDIM()} then
6634 match context
6635 case JACOBIAN_CONTEXT(jacHT=SOME(jacHT)) then
6636 match simVarFromHT(crefStripSubs(sc), jacHT)
6637 case SIMVAR() then
6638 if not listEmpty(equation_iterators) then
6639 // Row is already replicated by the outer equation_iterators for-loop (a
6640 // genuine for-equation over this WHOLEDIM slice) - do NOT unroll again
6641 // internally, that would visit each (row,col) pair sz times instead of
6642 // once. _wr<%k%> becomes the flattened 0-based offset of the current
6643 // outer-loop iteration, so any REGULAR-seed diagonal code referencing it
6644 // still resolves to the right column.
6645 let flatIdx = <<<%(equation_iterators |> it => forIteratorBody(it, context, &preExp, &varDecls, &varFrees, &auxFunction, &sub) ;separator="")%>0<%(equation_iterators |> it => ")" ;separator="")%>>>
6646 <<
6647 {
6648 unsigned int _wr<%k%> = (unsigned int)(<%flatIdx%>);
6649 <%depsCode%>
6650 }
6651 >>
6652 else
6653 let sz = dimension(listHead(crefDims(sc)), context, &preExp, &varDecls, &varFrees, &auxFunction)
6654 <<
6655 {
6656 unsigned int _wr<%k%>;
6657 for (_wr<%k%> = 0; _wr<%k%> < (unsigned int)(<%sz%>); _wr<%k%>++) {
6658 <%depsCode%>
6659 }
6660 }
6661 >>
6662 else depsCode
6663 else depsCode
6664 case {SLICE(exp=sliceExp)} then
6665 match context
6666 case JACOBIAN_CONTEXT(jacHT=SOME(jacHT)) then
6667 match simVarFromHT(crefStripSubs(sc), jacHT)
6668 case SIMVAR() then
6669 let sliceArr = daeExp(sliceExp, context, &preExp, &varDecls, &varFrees, &auxFunction)
6670 let nSlice = tempDecl("modelica_integer", &varDecls, &varFrees)
6671 let &preExp += '<%nSlice%> = size_of_dimension_base_array(<%sliceArr%>, 1);<%\n%>'
6672 <<
6673 {
6674 unsigned int _wr<%k%>;
6675 for (_wr<%k%> = 0; _wr<%k%> < (unsigned int)(<%nSlice%>); _wr<%k%>++) {
6676 <%depsCodeReduced%>
6677 }
6678 }
6679 >>
6680 else depsCodeReduced
6681 else depsCodeReduced
6682 else
6683 match listReverse(crefSubs(sc))
6684 case WHOLEDIM() :: {WHOLEDIM()} then
6685 // 2D array sc, both dims whole.
6686 match context
6687 case JACOBIAN_CONTEXT(jacHT=SOME(jacHT)) then
6688 match simVarFromHT(crefStripSubs(sc), jacHT)
6689 case SIMVAR() then
6690 if not listEmpty(equation_iterators) then
6691 // Both dims are ALREADY iterated by the outer equation_iterators
6692 // for-loop nest generated above (forIter/forTail) -- this is a
6693 // synthetic residual var (e.g. NBTearing's $RES_SIM_xxx) whose
6694 // WHOLEDIM dimensions mark "driven by the enclosing loop", not a
6695 // literal per-element subscript (that shape instead falls through to
6696 // the generic INDEX-subscript case below, via indexSubRecursive).
6697 // Do NOT unroll again internally with an extra loop keyed off only
6698 // sc's last dimension: that visits each row far more than once (and,
6699 // worse, computes a row index disconnected from the actual
6700 // per-iteration position), producing out-of-range rows and a
6701 // corrupted sparsity pattern (see the LSGreenH2Production.Plant
6702 // windTurbine NLS). flatIdx is sc's own flattened position from ALL
6703 // of its iterators, exactly like the single-WHOLEDIM case.
6704 let flatIdx = <<<%(equation_iterators |> it => forIteratorBody(it, context, &preExp, &varDecls, &varFrees, &auxFunction, &sub) ;separator="")%>0<%(equation_iterators |> it => ")" ;separator="")%>>>
6705 <<
6706 {
6707 unsigned int _wr<%k%> = (unsigned int)(<%flatIdx%>);
6708 <%depsCodeReduced%>
6709 }
6710 >>
6711 else
6712 // no enclosing for-equation iterators (e.g. a genuine dense array
6713 // equation): must match the fill template which generates two
6714 // nested loops.
6715 let szInner = dimension(List.last(crefDims(sc)), context, &preExp, &varDecls, &varFrees, &auxFunction)
6716 let szOuter = dimension(listHead(crefDims(sc)), context, &preExp, &varDecls, &varFrees, &auxFunction)
6717 <<
6718 {
6719 unsigned int _wo<%k%>;
6720 for (_wo<%k%> = 0; _wo<%k%> < (unsigned int)(<%szOuter%>); _wo<%k%>++) {
6721 unsigned int _wr<%k%>;
6722 for (_wr<%k%> = 0; _wr<%k%> < (unsigned int)(<%szInner%>); _wr<%k%>++) {
6723 <%depsCodeReduced%>
6724 }
6725 }
6726 }
6727 >>
6728 else depsCodeReduced
6729 else depsCodeReduced
6730 case WHOLEDIM() :: _ then
6731 match context
6732 case JACOBIAN_CONTEXT(jacHT=SOME(jacHT)) then
6733 match simVarFromHT(crefStripSubs(sc), jacHT)
6734 case SIMVAR() then
6735 if not listEmpty(equation_iterators) then
6736 // See the WHOLEDIM()::{WHOLEDIM()} case above for why this guard
6737 // is needed and what flatIdx computes.
6738 let flatIdx = <<<%(equation_iterators |> it => forIteratorBody(it, context, &preExp, &varDecls, &varFrees, &auxFunction, &sub) ;separator="")%>0<%(equation_iterators |> it => ")" ;separator="")%>>>
6739 <<
6740 {
6741 unsigned int _wr<%k%> = (unsigned int)(<%flatIdx%>);
6742 <%depsCode%>
6743 }
6744 >>
6745 else
6746 let sz = dimension(List.last(crefDims(sc)), context, &preExp, &varDecls, &varFrees, &auxFunction)
6747 <<
6748 {
6749 unsigned int _wr<%k%>;
6750 for (_wr<%k%> = 0; _wr<%k%> < (unsigned int)(<%sz%>); _wr<%k%>++) {
6751 <%depsCode%>
6752 }
6753 }
6754 >>
6755 else depsCode
6756 else depsCode
6757 else depsCodeReduced
6758 ;separator="\n")
6759 let scNames = (solved_crefs |> sc => System.stringReplace(System.stringReplace(crefStrNoUnderscore(sc), "/*", ""), "*/", "") ;separator=", ")
6760 if bodyCode then
6761 <<
6762 /* <%crefStrNoUnderscore(equation_name)%> [<%scNames%>] count */
6763 <%forIter%>
6764 <%bodyCode%>
6765 <%forTail%>
6766 >>
6767 else ''
6768 end resizableSparsityRowCount;
6769
6770 13 template resizableColCountRegular(ComponentRef seed, String nCols, Integer k, Context context, Text &preExp, Text &varDecls, Text &varFrees, Text &auxFunction)
6771 "Count phase for a REGULAR 1D whole-array seed: emit col_counts[v.index + _wr<%k%>]++ (one
6772 column aligned with the outer row-loop variable _wr<%k%>). Only call when dep.kinds=[false]
6773 and not rep — the caller is responsible for checking those conditions inline."
6774 ::=
6775 match context
6776 case JACOBIAN_CONTEXT(jacHT=SOME(jacHT)) then
6777 match simVarFromHT(crefStripSubs(seed), jacHT)
6778 case v as SIMVAR() then
6779 if intLt(v.index, 0) then ''
6780 else
6781 let seedComment = '/* <%System.stringReplace(System.stringReplace(crefStrNoUnderscore(seed), "/*", ""), "*/", "")%> */'
6782 <<
6783 <%seedComment%>
6784 col_counts[<%jacobianVarIndex(v, context)%> + _wr<%k%>]++;
6785 >>
6786 else resizableColCount(seed, nCols, context, &preExp, &varDecls, &varFrees, &auxFunction)
6787 else resizableColCount(seed, nCols, context, &preExp, &varDecls, &varFrees, &auxFunction)
6788 end resizableColCountRegular;
6789
6790 ✗ template allWholeSubs(list<Subscript> subs)
6791 "non empty if all subscripts are whole dimensions"
6792 ::=
6793 match subs
6794 case {} then 'true'
6795 case WHOLEDIM() :: rest then allWholeSubs(rest)
6796 else ''
6797 end allWholeSubs;
6798
6799 ✗ template wholeDimsSize(list<Dimension> dims, Context context, Text &preExp, Text &varDecls, Text &varFrees, Text &auxFunction)
6800 "product of the sizes of all dimensions"
6801 ::=
6802 (dims |> dim => '(unsigned int)(<%dimension(dim, context, &preExp, &varDecls, &varFrees, &auxFunction)%>)' ;separator=" * ")
6803 end wholeDimsSize;
6804
6805 5267 template resizableColCount(ComponentRef seed, String nCols, Context context, Text &preExp, Text &varDecls, Text &varFrees, Text &auxFunction)
6806 "Elements of a partially covered array have their own seed index, use it if the seed is stored exactly."
6807 ::=
6808 let seedComment = '/* <%System.stringReplace(System.stringReplace(crefStrNoUnderscore(seed), "/*", ""), "*/", "")%> */'
6809 match context
6810 case JACOBIAN_CONTEXT(jacHT=SOME(jacHT)) then
6811 match crefSubs(seed)
6812 case {} then resizableColCountBase(seed, nCols, context, &preExp, &varDecls, &varFrees, &auxFunction)
6813 else
6814 match simVarExactFromHT(seed, jacHT)
6815 case SOME(ev as SIMVAR()) then
6816 <<
6817 <%seedComment%>
6818 if (<%jacobianVarIndex(ev, context)%> >= 0 && <%jacobianVarIndex(ev, context)%> < (modelica_integer)(<%nCols%>)) { col_counts[<%jacobianVarIndex(ev, context)%>]++; }
6819 >>
6820 else resizableColCountBase(seed, nCols, context, &preExp, &varDecls, &varFrees, &auxFunction)
6821 else resizableColCountBase(seed, nCols, context, &preExp, &varDecls, &varFrees, &auxFunction)
6822 end resizableColCount;
6823
6824 3475 template resizableColCountBase(ComponentRef seed, String nCols, Context context, Text &preExp, Text &varDecls, Text &varFrees, Text &auxFunction)
6825 "Increment col_counts for one dependency cref."
6826 ::=
6827 let seedComment = '/* <%System.stringReplace(System.stringReplace(crefStrNoUnderscore(seed), "/*", ""), "*/", "")%> */'
6828 match context
6829 case JACOBIAN_CONTEXT(jacHT=SOME(jacHT)) then
6830 match simVarFromHT(crefStripSubs(seed), jacHT)
6831 case v as SIMVAR() then
6832 if intLt(v.index, 0) then
6833 // Negative virtual-index: partial-slice seed where first subscript > seedVars slot.
6834 // For INDEX-subscripted seeds (e.g. $SEED.module[i1].field) emit a C-level guard so
6835 // that only iterations where (v.index + offset >= 0) increment col_counts.
6836 // This correctly handles the single valid element (e.g. module[10]) while skipping
6837 // the out-of-bounds iterations; other subscript types are skipped entirely.
6838 match listReverse(crefSubs(seed))
6839 case INDEX() :: _ then
6840 let &offsetPreExp = buffer ""
6841 let offset = indexSubRecursive(listReverse(List.restOrEmpty(crefDims(seed))), listReverse(crefSubs(seed)), context, &offsetPreExp, &varDecls, &varFrees, &auxFunction)
6842 <<
6843 <%seedComment%>
6844 <%offsetPreExp%>
6845 if ((modelica_integer)(<%jacobianVarIndex(v, context)%>) + (modelica_integer)(<%offset%>) >= 0) { col_counts[<%jacobianVarIndex(v, context)%> + (<%offset%>)]++; }
6846 >>
6847 else ''
6848 else
6849 match crefSubs(seed)
6850 case {} then
6851 <<
6852 <%seedComment%>
6853 col_counts[<%jacobianVarIndex(v, context)%>]++;
6854 >>
6855 case {WHOLEDIM()} then
6856 let sz = dimension(listHead(crefDims(seed)), context, &preExp, &varDecls, &varFrees, &auxFunction)
6857 <<
6858 <%seedComment%>
6859 {
6860 unsigned int _wc<%v.index%>;
6861 for (_wc<%v.index%> = 0; _wc<%v.index%> < (unsigned int)(<%sz%>); _wc<%v.index%>++) {
6862 col_counts[<%jacobianVarIndex(v, context)%> + _wc<%v.index%>]++;
6863 }
6864 }
6865 >>
6866 case {SLICE(exp=sliceExp)} then
6867 let sliceArr = daeExp(sliceExp, context, &preExp, &varDecls, &varFrees, &auxFunction)
6868 let nSlice = tempDecl("modelica_integer", &varDecls, &varFrees)
6869 let &preExp += '<%nSlice%> = size_of_dimension_base_array(<%sliceArr%>, 1);<%\n%>'
6870 <<
6871 <%seedComment%>
6872 {
6873 unsigned int _sc<%v.index%>;
6874 for (_sc<%v.index%> = 0; _sc<%v.index%> < (unsigned int)(<%nSlice%>); _sc<%v.index%>++) {
6875 col_counts[<%jacobianVarIndex(v, context)%> + (((modelica_integer*)<%sliceArr%>.data)[_sc<%v.index%>] - 1)]++;
6876 }
6877 }
6878 >>
6879 case SLICE(exp=outerSliceExp) :: {WHOLEDIM()} then
6880 // outer SLICE (e.g. module[1:9]) + inner WHOLEDIM (fillSubscripts added [:] for array field)
6881 let sliceArr = daeExp(outerSliceExp, context, &preExp, &varDecls, &varFrees, &auxFunction)
6882 let nSlice = tempDecl("modelica_integer", &varDecls, &varFrees)
6883 let &preExp += '<%nSlice%> = size_of_dimension_base_array(<%sliceArr%>, 1);<%\n%>'
6884 let sz = dimension(List.last(crefDims(seed)), context, &preExp, &varDecls, &varFrees, &auxFunction)
6885 <<
6886 <%seedComment%>
6887 {
6888 unsigned int _so<%v.index%>;
6889 for (_so<%v.index%> = 0; _so<%v.index%> < (unsigned int)(<%nSlice%>); _so<%v.index%>++) {
6890 unsigned int _wo<%v.index%>;
6891 for (_wo<%v.index%> = 0; _wo<%v.index%> < (unsigned int)(<%sz%>); _wo<%v.index%>++) {
6892 col_counts[<%jacobianVarIndex(v, context)%> + (((modelica_integer*)<%sliceArr%>.data)[_so<%v.index%>] - 1) * (unsigned int)(<%sz%>) + _wo<%v.index%>]++;
6893 }
6894 }
6895 }
6896 >>
6897 case WHOLEDIM() :: {WHOLEDIM()} then
6898 // 2D array, both dims whole (e.g. module[:].T[:])
6899 let szInner = dimension(List.last(crefDims(seed)), context, &preExp, &varDecls, &varFrees, &auxFunction)
6900 let szOuter = dimension(listHead(crefDims(seed)), context, &preExp, &varDecls, &varFrees, &auxFunction)
6901 <<
6902 <%seedComment%>
6903 {
6904 unsigned int _wo2<%v.index%>;
6905 for (_wo2<%v.index%> = 0; _wo2<%v.index%> < (unsigned int)(<%szOuter%>); _wo2<%v.index%>++) {
6906 unsigned int _wc<%v.index%>;
6907 for (_wc<%v.index%> = 0; _wc<%v.index%> < (unsigned int)(<%szInner%>); _wc<%v.index%>++) {
6908 col_counts[<%jacobianVarIndex(v, context)%> + _wo2<%v.index%> * (unsigned int)(<%szInner%>) + _wc<%v.index%>]++;
6909 }
6910 }
6911 }
6912 >>
6913 case WHOLEDIM() :: WHOLEDIM() :: WHOLEDIM() :: _ then
6914 // 3 or more whole dims (e.g. element[:, :, :].T): all elements of the variable
6915 match allWholeSubs(crefSubs(seed))
6916 case "" then error(sourceInfo(), 'unsupported mix of whole and other subscripts in seed <%crefStrNoUnderscore(seed)%>')
6917 else
6918 let total = wholeDimsSize(crefDims(seed), context, &preExp, &varDecls, &varFrees, &auxFunction)
6919 <<
6920 <%seedComment%>
6921 {
6922 unsigned int _wa<%v.index%>;
6923 for (_wa<%v.index%> = 0; _wa<%v.index%> < (unsigned int)(<%total%>); _wa<%v.index%>++) {
6924 col_counts[<%jacobianVarIndex(v, context)%> + _wa<%v.index%>]++;
6925 }
6926 }
6927 >>
6928 else
6929 match listReverse(crefSubs(seed))
6930 case WHOLEDIM() :: outer_rev_subs then
6931 let sz = dimension(List.last(crefDims(seed)), context, &preExp, &varDecls, &varFrees, &auxFunction)
6932 let &outerPreExp = buffer ""
6933 let outer_off = match outer_rev_subs
6934 case {} then '0'
6935 else indexSubRecursive(List.restOrEmpty(listReverse(List.restOrEmpty(crefDims(seed)))), outer_rev_subs, context, &outerPreExp, &varDecls, &varFrees, &auxFunction)
6936 let col = tempDecl("modelica_integer", &varDecls, &varFrees)
6937 <<
6938 <%seedComment%>
6939 {
6940 unsigned int _wc<%v.index%>;
6941 for (_wc<%v.index%> = 0; _wc<%v.index%> < (unsigned int)(<%sz%>); _wc<%v.index%>++) {
6942 <%outerPreExp%>
6943 <%col%> = (modelica_integer)(<%jacobianVarIndex(v, context)%>) + (<%outer_off%>) * (modelica_integer)(<%sz%>) + (modelica_integer)_wc<%v.index%>;
6944 if (<%col%> >= 0 && <%col%> < (modelica_integer)(<%nCols%>)) {
6945 col_counts[<%col%>]++;
6946 }
6947 }
6948 }
6949 >>
6950 case SLICE(exp=sliceExp) :: outer_rev_subs then
6951 // inner SLICE (e.g. module[i].T[1:9]) - outer dims are INDEX subs
6952 let sliceArr = daeExp(sliceExp, context, &preExp, &varDecls, &varFrees, &auxFunction)
6953 let nSlice = tempDecl("modelica_integer", &varDecls, &varFrees)
6954 let &preExp += '<%nSlice%> = size_of_dimension_base_array(<%sliceArr%>, 1);<%\n%>'
6955 let sz = dimension(List.last(crefDims(seed)), context, &preExp, &varDecls, &varFrees, &auxFunction)
6956 let &outerPreExp = buffer ""
6957 let outer_off = match outer_rev_subs
6958 case {} then '0'
6959 else indexSubRecursive(List.restOrEmpty(listReverse(List.restOrEmpty(crefDims(seed)))), outer_rev_subs, context, &outerPreExp, &varDecls, &varFrees, &auxFunction)
6960 <<
6961 <%seedComment%>
6962 {
6963 unsigned int _sc<%v.index%>;
6964 for (_sc<%v.index%> = 0; _sc<%v.index%> < (unsigned int)(<%nSlice%>); _sc<%v.index%>++) {
6965 <%outerPreExp%>
6966 col_counts[<%jacobianVarIndex(v, context)%> + (<%outer_off%>) * (unsigned int)(<%sz%>) + (((modelica_integer*)<%sliceArr%>.data)[_sc<%v.index%>] - 1)]++;
6967 }
6968 }
6969 >>
6970 case INDEX(exp=innerIndexExp) :: {WHOLEDIM()} then
6971 // reversed [INDEX, WHOLEDIM] = original [WHOLEDIM, INDEX]: outer WHOLE, inner fixed INDEX
6972 let szOuter = dimension(listHead(crefDims(seed)), context, &preExp, &varDecls, &varFrees, &auxFunction)
6973 let szInner = dimension(List.last(crefDims(seed)), context, &preExp, &varDecls, &varFrees, &auxFunction)
6974 let &innerPreExp = buffer ""
6975 let innerIdx = daeSubscriptExp(innerIndexExp, context, &innerPreExp, &varDecls, &varFrees, &auxFunction)
6976 <<
6977 <%seedComment%>
6978 {
6979 unsigned int _wo<%v.index%>;
6980 for (_wo<%v.index%> = 0; _wo<%v.index%> < (unsigned int)(<%szOuter%>); _wo<%v.index%>++) {
6981 <%innerPreExp%>
6982 col_counts[<%jacobianVarIndex(v, context)%> + _wo<%v.index%> * (unsigned int)(<%szInner%>) + ((<%innerIdx%>) - 1)]++;
6983 }
6984 }
6985 >>
6986 case INDEX(exp=innerIndexExp) :: {SLICE(exp=outerSliceExp)} then
6987 // reversed [INDEX, SLICE] = original [SLICE, INDEX]: outer SLICE range, inner fixed INDEX
6988 let sliceArr = daeExp(outerSliceExp, context, &preExp, &varDecls, &varFrees, &auxFunction)
6989 let nSlice = tempDecl("modelica_integer", &varDecls, &varFrees)
6990 let &preExp += '<%nSlice%> = size_of_dimension_base_array(<%sliceArr%>, 1);<%\n%>'
6991 let szInner = dimension(List.last(crefDims(seed)), context, &preExp, &varDecls, &varFrees, &auxFunction)
6992 let &innerPreExp = buffer ""
6993 let innerIdx = daeSubscriptExp(innerIndexExp, context, &innerPreExp, &varDecls, &varFrees, &auxFunction)
6994 <<
6995 <%seedComment%>
6996 {
6997 unsigned int _so<%v.index%>;
6998 for (_so<%v.index%> = 0; _so<%v.index%> < (unsigned int)(<%nSlice%>); _so<%v.index%>++) {
6999 <%innerPreExp%>
7000 col_counts[<%jacobianVarIndex(v, context)%> + (((modelica_integer*)<%sliceArr%>.data)[_so<%v.index%>] - 1) * (unsigned int)(<%szInner%>) + ((<%innerIdx%>) - 1)]++;
7001 }
7002 }
7003 >>
7004 else
7005 let &offsetPreExp = buffer ""
7006 let offset = indexSubRecursive(listReverse(List.restOrEmpty(crefDims(seed))), listReverse(crefSubs(seed)), context, &offsetPreExp, &varDecls, &varFrees, &auxFunction)
7007 let col = tempDecl("modelica_integer", &varDecls, &varFrees)
7008 <<
7009 <%seedComment%>
7010 <%offsetPreExp%>
7011 <%col%> = (modelica_integer)(<%jacobianVarIndex(v, context)%>) + (<%offset%>);
7012 if (<%col%> >= 0 && <%col%> < (modelica_integer)(<%nCols%>)) { col_counts[<%col%>]++; }
7013 >>
7014 else '/* resizableColCount: seed not found in jacHT */'
7015 else ''
7016 end resizableColCountBase;
7017
7018 1038 template resizableSparsityRowFill(SparsityRow row, String nCols, Context context, Text &preExp, Text &varDecls, Text &varFrees, Text &auxFunction, Text &sub, String spPattern)
7019 "Fill phase: for each (row,col) pair, write spPattern->index[col_fill[col]++] = row.
7020 Uses resizableFillDepsForRow helper to avoid nested iteration over two record fields."
7021 ::=
7022 match row
7023 case SPARSITY_ROW() then
7024 let forIter = (equation_iterators |> it => forIterator(it, context, &preExp, &varDecls, &varFrees, &auxFunction, &sub) ;separator="\n";empty)
7025 let forTail = (equation_iterators |> it => '}' ;separator="\n";empty)
7026 let bodyCode = (solved_crefs |> sc hasindex k =>
7027 resizableFillDepsForRow(row, nCols, k, sc, context, &preExp, &varDecls, &varFrees, &auxFunction, &sub, spPattern)
7028 ;separator="\n")
7029 let scNames = (solved_crefs |> sc => System.stringReplace(System.stringReplace(crefStrNoUnderscore(sc), "/*", ""), "*/", "") ;separator=", ")
7030 if bodyCode then
7031 <<
7032 /* <%crefStrNoUnderscore(equation_name)%> [<%scNames%>] fill */
7033 <%forIter%>
7034 <%bodyCode%>
7035 <%forTail%>
7036 >>
7037 else ''
7038 end resizableSparsityRowFill;
7039
7040 1039 template resizableFillDepsForRow(SparsityRow row, String nCols, Integer k, ComponentRef sc, Context context, Text &preExp, Text &varDecls, Text &varFrees, Text &auxFunction, Text &sub, String spPattern)
7041 "Generate fill code for solved_cref sc (row index k) against all dependencies in row.
7042 Explicitly binds dependencies and equation_iterators in the SPARSITY_ROW pattern to keep them in scope through nested matches."
7043 ::=
7044 match row
7045 case SPARSITY_ROW(dependencies=deps, equation_iterators=iters) then
7046 // depsWholeDep: dep-aware fill; for REGULAR 1D WHOLEDIM seeds uses resizableColFillRegular
7047 // (single entry at _wr<%k%> offset). Dep/rep condition checked inline.
7048 // Only valid where _wr<%k%> is in scope (WHOLEDIM sc and multi-dim WHOLEDIM sc).
7049 let depsWholeDep = (deps |> (seed, dep, rep) =>
7050 match dep
7051 case DEPENDENCY(kinds=kinds) then
7052 if not rep then
7053 if not listEmpty(kinds) then
7054 if not listHead(kinds) then
7055 match crefSubs(seed)
7056 case {WHOLEDIM()} then resizableColFillRegular(seed, nCols, 'row_<%k%>', k, context, &preExp, &varDecls, &varFrees, &auxFunction, spPattern)
7057 else resizableColFill(seed, nCols, 'row_<%k%>', context, &preExp, &varDecls, &varFrees, &auxFunction, spPattern)
7058 else resizableColFill(seed, nCols, 'row_<%k%>', context, &preExp, &varDecls, &varFrees, &auxFunction, spPattern)
7059 else resizableColFill(seed, nCols, 'row_<%k%>', context, &preExp, &varDecls, &varFrees, &auxFunction, spPattern)
7060 else resizableColFill(seed, nCols, 'row_<%k%>', context, &preExp, &varDecls, &varFrees, &auxFunction, spPattern)
7061 else resizableColFill(seed, nCols, 'row_<%k%>', context, &preExp, &varDecls, &varFrees, &auxFunction, spPattern)
7062 ;separator="\n")
7063 // depsWholeReduced: always REDUCTION; used for SLICE sc where column ≠ _wr<%k%>.
7064 let depsWholeReduced = (deps |> (seed, _, _) => resizableColFill(seed, nCols, 'row_<%k%>', context, &preExp, &varDecls, &varFrees, &auxFunction, spPattern) ;separator="\n")
7065 match crefSubs(sc)
7066 case {WHOLEDIM()} then
7067 match context
7068 case JACOBIAN_CONTEXT(jacHT=SOME(jacHT)) then
7069 match simVarFromHT(crefStripSubs(sc), jacHT)
7070 case v as SIMVAR() then
7071 if not listEmpty(iters) then
7072 // sc's own row must be derived from sc's flattened position (via jacHT's
7073 // v.index), not a shared incrementing counter: a single equation can
7074 // produce several SparsityRow entries for the same for-loop (e.g. one for
7075 // der(x[i1]), another for the off-diagonal der(x[1+i1]) term) whose target
7076 // rows overlap, so a sequential counter double-books/overruns rows (see
7077 // simple_der_for.mos). flatIdx here is sc's OWN subscript expression
7078 // (e.g. i1-1 for x[i1], or (1+i1)-1 for x[1+i1]), matching how columns are
7079 // already correctly computed from v.index + offset.
7080 let flatIdx = <<<%(iters |> it => forIteratorBody(it, context, &preExp, &varDecls, &varFrees, &auxFunction, &sub) ;separator="")%>0<%(iters |> it => ")" ;separator="")%>>>
7081 <<
7082 {
7083 unsigned int _wr<%k%> = (unsigned int)(<%flatIdx%>);
7084 unsigned int row_<%k%> = <%jacobianVarIndex(v, context)%> + _wr<%k%>;
7085 <%depsWholeDep%>
7086 }
7087 >>
7088 else
7089 let sz = dimension(listHead(crefDims(sc)), context, &preExp, &varDecls, &varFrees, &auxFunction)
7090 <<
7091 {
7092 unsigned int _wr<%k%>;
7093 for (_wr<%k%> = 0; _wr<%k%> < (unsigned int)(<%sz%>); _wr<%k%>++) {
7094 unsigned int row_<%k%> = <%jacobianVarIndex(v, context)%> + _wr<%k%>;
7095 <%depsWholeDep%>
7096 }
7097 }
7098 >>
7099 else ''
7100 else ''
7101 case {SLICE(exp=sliceExp)} then
7102 match context
7103 case JACOBIAN_CONTEXT(jacHT=SOME(jacHT)) then
7104 match simVarFromHT(crefStripSubs(sc), jacHT)
7105 case v as SIMVAR() then
7106 let sliceArr = daeExp(sliceExp, context, &preExp, &varDecls, &varFrees, &auxFunction)
7107 let nSlice = tempDecl("modelica_integer", &varDecls, &varFrees)
7108 let &preExp += '<%nSlice%> = size_of_dimension_base_array(<%sliceArr%>, 1);<%\n%>'
7109 <<
7110 {
7111 unsigned int _wr<%k%>;
7112 for (_wr<%k%> = 0; _wr<%k%> < (unsigned int)(<%nSlice%>); _wr<%k%>++) {
7113 unsigned int row_<%k%> = <%jacobianVarIndex(v, context)%> + (unsigned int)(((modelica_integer*)<%sliceArr%>.data)[_wr<%k%>] - 1);
7114 <%depsWholeReduced%>
7115 }
7116 }
7117 >>
7118 else ''
7119 else ''
7120 case {} then
7121 match context
7122 case JACOBIAN_CONTEXT(jacHT=SOME(jacHT)) then
7123 match simVarFromHT(crefStripSubs(sc), jacHT)
7124 case v as SIMVAR() then
7125 let rowExpr = '<%jacobianVarIndex(v, context)%>'
7126 let fillCode = (deps |> (seed, _, _) => resizableColFill(seed, nCols, rowExpr, context, &preExp, &varDecls, &varFrees, &auxFunction, spPattern) ;separator="\n")
7127 <<
7128 <%fillCode%>
7129 >>
7130 else ''
7131 else ''
7132 else
7133 match listReverse(crefSubs(sc))
7134 case WHOLEDIM() :: {WHOLEDIM()} then
7135 // 2D array sc, both dims whole (e.g. module[:].T[:]).
7136 match context
7137 case JACOBIAN_CONTEXT(jacHT=SOME(jacHT)) then
7138 match simVarFromHT(crefStripSubs(sc), jacHT)
7139 case v as SIMVAR() then
7140 if not listEmpty(iters) then
7141 // Both dims are ALREADY iterated by the outer equation_iterators
7142 // for-loop nest (see the matching guard in resizableSparsityRowCount
7143 // for the full rationale: this is a synthetic residual var, e.g.
7144 // NBTearing's $RES_SIM_xxx, whose WHOLEDIM dims mark "driven by the
7145 // enclosing loop" -- a literal per-element subscript instead falls
7146 // through to the generic INDEX-subscript case below, via
7147 // indexSubRecursive). A `local_row_base` counter bumped by one
7148 // dimension's size on every outer-loop iteration overruns the true
7149 // row count and corrupts the sparsity pattern (see the
7150 // LSGreenH2Production.Plant windTurbine NLS); compute sc's own
7151 // flattened row directly from its iterators instead, exactly like
7152 // the single-WHOLEDIM-with-iterators case.
7153 let flatIdx = <<<%(iters |> it => forIteratorBody(it, context, &preExp, &varDecls, &varFrees, &auxFunction, &sub) ;separator="")%>0<%(iters |> it => ")" ;separator="")%>>>
7154 <<
7155 {
7156 unsigned int _wr<%k%> = (unsigned int)(<%flatIdx%>);
7157 unsigned int row_<%k%> = <%jacobianVarIndex(v, context)%> + _wr<%k%>;
7158 <%depsWholeReduced%>
7159 }
7160 >>
7161 else
7162 let szInner = dimension(List.last(crefDims(sc)), context, &preExp, &varDecls, &varFrees, &auxFunction)
7163 let szOuter = dimension(listHead(crefDims(sc)), context, &preExp, &varDecls, &varFrees, &auxFunction)
7164 <<
7165 {
7166 unsigned int _wo<%k%>;
7167 for (_wo<%k%> = 0; _wo<%k%> < (unsigned int)(<%szOuter%>); _wo<%k%>++) {
7168 unsigned int _wr<%k%>;
7169 for (_wr<%k%> = 0; _wr<%k%> < (unsigned int)(<%szInner%>); _wr<%k%>++) {
7170 unsigned int row_<%k%> = local_row_base + _wo<%k%> * (unsigned int)(<%szInner%>) + _wr<%k%>;
7171 <%depsWholeReduced%>
7172 }
7173 }
7174 local_row_base += (unsigned int)(<%szOuter%>) * (unsigned int)(<%szInner%>);
7175 }
7176 >>
7177 else ''
7178 else ''
7179 case WHOLEDIM() :: outer_rev_subs then
7180 match context
7181 case JACOBIAN_CONTEXT(jacHT=SOME(jacHT)) then
7182 match simVarFromHT(crefStripSubs(sc), jacHT)
7183 case v as SIMVAR() then
7184 if not listEmpty(iters) then
7185 // See the WHOLEDIM()::{WHOLEDIM()} case above for why this guard is
7186 // needed and what flatIdx computes.
7187 let flatIdx = <<<%(iters |> it => forIteratorBody(it, context, &preExp, &varDecls, &varFrees, &auxFunction, &sub) ;separator="")%>0<%(iters |> it => ")" ;separator="")%>>>
7188 <<
7189 {
7190 unsigned int _wr<%k%> = (unsigned int)(<%flatIdx%>);
7191 unsigned int row_<%k%> = <%jacobianVarIndex(v, context)%> + _wr<%k%>;
7192 <%depsWholeDep%>
7193 }
7194 >>
7195 else
7196 let sz = dimension(List.last(crefDims(sc)), context, &preExp, &varDecls, &varFrees, &auxFunction)
7197 <<
7198 {
7199 unsigned int _wr<%k%>;
7200 for (_wr<%k%> = 0; _wr<%k%> < (unsigned int)(<%sz%>); _wr<%k%>++) {
7201 unsigned int row_<%k%> = local_row_base + _wr<%k%>;
7202 <%depsWholeDep%>
7203 }
7204 local_row_base += (unsigned int)(<%sz%>);
7205 }
7206 >>
7207 else ''
7208 else ''
7209 case INDEX(exp=innerIndexExp) :: {WHOLEDIM()} then
7210 // reversed [INDEX, WHOLEDIM] = original [WHOLEDIM, INDEX]: outer WHOLE, inner fixed INDEX
7211 match context
7212 case JACOBIAN_CONTEXT(jacHT=SOME(jacHT)) then
7213 match simVarFromHT(crefStripSubs(sc), jacHT)
7214 case SIMVAR() then
7215 let szOuter = dimension(listHead(crefDims(sc)), context, &preExp, &varDecls, &varFrees, &auxFunction)
7216 <<
7217 {
7218 unsigned int _wo<%k%>;
7219 for (_wo<%k%> = 0; _wo<%k%> < (unsigned int)(<%szOuter%>); _wo<%k%>++) {
7220 unsigned int row_<%k%> = local_row_base + _wo<%k%>;
7221 <%depsWholeReduced%>
7222 }
7223 local_row_base += (unsigned int)(<%szOuter%>);
7224 }
7225 >>
7226 else ''
7227 else ''
7228 case INDEX(exp=innerIndexExp) :: {SLICE(exp=outerSliceExp)} then
7229 // reversed [INDEX, SLICE] = original [SLICE, INDEX]: outer SLICE range, inner fixed INDEX
7230 match context
7231 case JACOBIAN_CONTEXT(jacHT=SOME(jacHT)) then
7232 match simVarFromHT(crefStripSubs(sc), jacHT)
7233 case SIMVAR() then
7234 let sliceArr = daeExp(outerSliceExp, context, &preExp, &varDecls, &varFrees, &auxFunction)
7235 let nSlice = tempDecl("modelica_integer", &varDecls, &varFrees)
7236 let &preExp += '<%nSlice%> = size_of_dimension_base_array(<%sliceArr%>, 1);<%\n%>'
7237 <<
7238 {
7239 unsigned int _so<%k%>;
7240 for (_so<%k%> = 0; _so<%k%> < (unsigned int)(<%nSlice%>); _so<%k%>++) {
7241 unsigned int row_<%k%> = local_row_base + _so<%k%>;
7242 <%depsWholeReduced%>
7243 }
7244 local_row_base += (unsigned int)(<%nSlice%>);
7245 }
7246 >>
7247 else ''
7248 else ''
7249 else
7250 match context
7251 case JACOBIAN_CONTEXT(jacHT=SOME(jacHT)) then
7252 match simVarFromHT(crefStripSubs(sc), jacHT)
7253 case v as SIMVAR() then
7254 // Generic single-dimension INDEX subscript with an arbitrary expression
7255 // (e.g. der(x[1+i1]), the off-diagonal y' term of a for-equation like
7256 // der(x[i]) = der(x[i+1]) + ...). The row must be sc's own flattened
7257 // position (v.index + the evaluated index expression, exactly like columns
7258 // already compute their offset via indexSubRecursive/daeSubscript) -- not a
7259 // shared sequential counter, since a single equation can produce multiple
7260 // SparsityRow entries whose target rows overlap with other rows already
7261 // assigned by the same or another equation (see simple_der_for.mos).
7262 let &offsetPreExp = buffer ""
7263 let offset = indexSubRecursive(listReverse(List.restOrEmpty(crefDims(sc))), listReverse(crefSubs(sc)), context, &offsetPreExp, &varDecls, &varFrees, &auxFunction)
7264 let rowExpr = '<%jacobianVarIndex(v, context)%> + (unsigned int)(<%offset%>)'
7265 let fillCode = (deps |> (seed, _, _) => resizableColFill(seed, nCols, rowExpr, context, &preExp, &varDecls, &varFrees, &auxFunction, spPattern) ;separator="\n")
7266 <<
7267 <%offsetPreExp%>
7268 <%fillCode%>
7269 >>
7270 else ''
7271 else ''
7272 end resizableFillDepsForRow;
7273
7274
7275 13 template resizableColFillRegular(ComponentRef seed, String nCols, String rowExpr, Integer k, Context context, Text &preExp, Text &varDecls, Text &varFrees, Text &auxFunction, String spPattern)
7276 "Fill phase for a REGULAR 1D whole-array seed: emit a single diagonal entry
7277 spPattern->index[col_fill[v.index + _wr<%k%>]++] = row. Only call when dep.kinds=[false]
7278 and not rep — the caller is responsible for checking those conditions inline."
7279 ::=
7280 match context
7281 case JACOBIAN_CONTEXT(jacHT=SOME(jacHT)) then
7282 match simVarFromHT(crefStripSubs(seed), jacHT)
7283 case v as SIMVAR() then
7284 if intLt(v.index, 0) then ''
7285 else
7286 let seedComment = '/* <%System.stringReplace(System.stringReplace(crefStrNoUnderscore(seed), "/*", ""), "*/", "")%> */'
7287 <<
7288 <%seedComment%>
7289 <%spPattern%>->index[col_fill[<%jacobianVarIndex(v, context)%> + _wr<%k%>]++] = <%rowExpr%>;
7290 >>
7291 else resizableColFill(seed, nCols, rowExpr, context, &preExp, &varDecls, &varFrees, &auxFunction, spPattern)
7292 else resizableColFill(seed, nCols, rowExpr, context, &preExp, &varDecls, &varFrees, &auxFunction, spPattern)
7293 end resizableColFillRegular;
7294
7295 7604 template resizableColFill(ComponentRef seed, String nCols, String rowExpr, Context context, Text &preExp, Text &varDecls, Text &varFrees, Text &auxFunction, String spPattern)
7296 "Elements of a partially covered array have their own seed index, use it if the seed is stored exactly."
7297 ::=
7298 let seedComment = '/* <%System.stringReplace(System.stringReplace(crefStrNoUnderscore(seed), "/*", ""), "*/", "")%> */'
7299 match context
7300 case JACOBIAN_CONTEXT(jacHT=SOME(jacHT)) then
7301 match crefSubs(seed)
7302 case {} then resizableColFillBase(seed, nCols, rowExpr, context, &preExp, &varDecls, &varFrees, &auxFunction, spPattern)
7303 else
7304 match simVarExactFromHT(seed, jacHT)
7305 case SOME(ev as SIMVAR()) then
7306 <<
7307 <%seedComment%>
7308 if (<%jacobianVarIndex(ev, context)%> >= 0 && <%jacobianVarIndex(ev, context)%> < (modelica_integer)(<%nCols%>)) { <%spPattern%>->index[col_fill[<%jacobianVarIndex(ev, context)%>]++] = <%rowExpr%>; }
7309 >>
7310 else resizableColFillBase(seed, nCols, rowExpr, context, &preExp, &varDecls, &varFrees, &auxFunction, spPattern)
7311 else resizableColFillBase(seed, nCols, rowExpr, context, &preExp, &varDecls, &varFrees, &auxFunction, spPattern)
7312 end resizableColFill;
7313
7314 5146 template resizableColFillBase(ComponentRef seed, String nCols, String rowExpr, Context context, Text &preExp, Text &varDecls, Text &varFrees, Text &auxFunction, String spPattern)
7315 "Write one CSC fill entry: spPattern->index[col_fill[col]++] = row."
7316 ::=
7317 let seedComment = '/* <%System.stringReplace(System.stringReplace(crefStrNoUnderscore(seed), "/*", ""), "*/", "")%> */'
7318 match context
7319 case JACOBIAN_CONTEXT(jacHT=SOME(jacHT)) then
7320 match simVarFromHT(crefStripSubs(seed), jacHT)
7321 case v as SIMVAR() then
7322 if intLt(v.index, 0) then
7323 // Negative virtual-index: mirror of resizableColCount negative-index handling.
7324 // Emit a C-level runtime guard for INDEX-subscripted seeds so that only the
7325 // valid iteration (where v.index + offset >= 0) writes a fill entry.
7326 match listReverse(crefSubs(seed))
7327 case INDEX() :: _ then
7328 let &offsetPreExp = buffer ""
7329 let offset = indexSubRecursive(listReverse(List.restOrEmpty(crefDims(seed))), listReverse(crefSubs(seed)), context, &offsetPreExp, &varDecls, &varFrees, &auxFunction)
7330 <<
7331 <%seedComment%>
7332 <%offsetPreExp%>
7333 if ((modelica_integer)(<%jacobianVarIndex(v, context)%>) + (modelica_integer)(<%offset%>) >= 0) { <%spPattern%>->index[col_fill[<%jacobianVarIndex(v, context)%> + (<%offset%>)]++] = <%rowExpr%>; }
7334 >>
7335 else ''
7336 else
7337 match crefSubs(seed)
7338 case {} then
7339 <<
7340 <%seedComment%>
7341 <%spPattern%>->index[col_fill[<%jacobianVarIndex(v, context)%>]++] = <%rowExpr%>;
7342 >>
7343 case {WHOLEDIM()} then
7344 let sz = dimension(listHead(crefDims(seed)), context, &preExp, &varDecls, &varFrees, &auxFunction)
7345 <<
7346 <%seedComment%>
7347 {
7348 unsigned int _wc<%v.index%>;
7349 for (_wc<%v.index%> = 0; _wc<%v.index%> < (unsigned int)(<%sz%>); _wc<%v.index%>++) {
7350 <%spPattern%>->index[col_fill[<%jacobianVarIndex(v, context)%> + _wc<%v.index%>]++] = <%rowExpr%>;
7351 }
7352 }
7353 >>
7354 case {SLICE(exp=sliceExp)} then
7355 let sliceArr = daeExp(sliceExp, context, &preExp, &varDecls, &varFrees, &auxFunction)
7356 let nSlice = tempDecl("modelica_integer", &varDecls, &varFrees)
7357 let &preExp += '<%nSlice%> = size_of_dimension_base_array(<%sliceArr%>, 1);<%\n%>'
7358 <<
7359 <%seedComment%>
7360 {
7361 unsigned int _sc<%v.index%>;
7362 for (_sc<%v.index%> = 0; _sc<%v.index%> < (unsigned int)(<%nSlice%>); _sc<%v.index%>++) {
7363 <%spPattern%>->index[col_fill[<%jacobianVarIndex(v, context)%> + (((modelica_integer*)<%sliceArr%>.data)[_sc<%v.index%>] - 1)]++] = <%rowExpr%>;
7364 }
7365 }
7366 >>
7367 case SLICE(exp=outerSliceExp) :: {WHOLEDIM()} then
7368 // outer SLICE (e.g. module[1:9]) + inner WHOLEDIM (fillSubscripts added [:] for array field)
7369 let sliceArr = daeExp(outerSliceExp, context, &preExp, &varDecls, &varFrees, &auxFunction)
7370 let nSlice = tempDecl("modelica_integer", &varDecls, &varFrees)
7371 let &preExp += '<%nSlice%> = size_of_dimension_base_array(<%sliceArr%>, 1);<%\n%>'
7372 let sz = dimension(List.last(crefDims(seed)), context, &preExp, &varDecls, &varFrees, &auxFunction)
7373 <<
7374 <%seedComment%>
7375 {
7376 unsigned int _so<%v.index%>;
7377 for (_so<%v.index%> = 0; _so<%v.index%> < (unsigned int)(<%nSlice%>); _so<%v.index%>++) {
7378 unsigned int _wo<%v.index%>;
7379 for (_wo<%v.index%> = 0; _wo<%v.index%> < (unsigned int)(<%sz%>); _wo<%v.index%>++) {
7380 <%spPattern%>->index[col_fill[<%jacobianVarIndex(v, context)%> + (((modelica_integer*)<%sliceArr%>.data)[_so<%v.index%>] - 1) * (unsigned int)(<%sz%>) + _wo<%v.index%>]++] = <%rowExpr%>;
7381 }
7382 }
7383 }
7384 >>
7385 case WHOLEDIM() :: {WHOLEDIM()} then
7386 // 2D array, both dims whole (e.g. module[:].T[:])
7387 let szInner = dimension(List.last(crefDims(seed)), context, &preExp, &varDecls, &varFrees, &auxFunction)
7388 let szOuter = dimension(listHead(crefDims(seed)), context, &preExp, &varDecls, &varFrees, &auxFunction)
7389 <<
7390 <%seedComment%>
7391 {
7392 unsigned int _wo2<%v.index%>;
7393 for (_wo2<%v.index%> = 0; _wo2<%v.index%> < (unsigned int)(<%szOuter%>); _wo2<%v.index%>++) {
7394 unsigned int _wc<%v.index%>;
7395 for (_wc<%v.index%> = 0; _wc<%v.index%> < (unsigned int)(<%szInner%>); _wc<%v.index%>++) {
7396 <%spPattern%>->index[col_fill[<%jacobianVarIndex(v, context)%> + _wo2<%v.index%> * (unsigned int)(<%szInner%>) + _wc<%v.index%>]++] = <%rowExpr%>;
7397 }
7398 }
7399 }
7400 >>
7401 case WHOLEDIM() :: WHOLEDIM() :: WHOLEDIM() :: _ then
7402 // 3 or more whole dims (e.g. element[:, :, :].T): all elements of the variable
7403 match allWholeSubs(crefSubs(seed))
7404 case "" then error(sourceInfo(), 'unsupported mix of whole and other subscripts in seed <%crefStrNoUnderscore(seed)%>')
7405 else
7406 let total = wholeDimsSize(crefDims(seed), context, &preExp, &varDecls, &varFrees, &auxFunction)
7407 <<
7408 <%seedComment%>
7409 {
7410 unsigned int _wa<%v.index%>;
7411 for (_wa<%v.index%> = 0; _wa<%v.index%> < (unsigned int)(<%total%>); _wa<%v.index%>++) {
7412 <%spPattern%>->index[col_fill[<%jacobianVarIndex(v, context)%> + _wa<%v.index%>]++] = <%rowExpr%>;
7413 }
7414 }
7415 >>
7416 else
7417 match listReverse(crefSubs(seed))
7418 case WHOLEDIM() :: outer_rev_subs then
7419 let sz = dimension(List.last(crefDims(seed)), context, &preExp, &varDecls, &varFrees, &auxFunction)
7420 let &outerPreExp = buffer ""
7421 let outer_off = match outer_rev_subs
7422 case {} then '0'
7423 else indexSubRecursive(List.restOrEmpty(listReverse(List.restOrEmpty(crefDims(seed)))), outer_rev_subs, context, &outerPreExp, &varDecls, &varFrees, &auxFunction)
7424 let col = tempDecl("modelica_integer", &varDecls, &varFrees)
7425 <<
7426 <%seedComment%>
7427 {
7428 unsigned int _wc<%v.index%>;
7429 for (_wc<%v.index%> = 0; _wc<%v.index%> < (unsigned int)(<%sz%>); _wc<%v.index%>++) {
7430 <%outerPreExp%>
7431 <%col%> = (modelica_integer)(<%jacobianVarIndex(v, context)%>) + (<%outer_off%>) * (modelica_integer)(<%sz%>) + (modelica_integer)_wc<%v.index%>;
7432 if (<%col%> >= 0 && <%col%> < (modelica_integer)(<%nCols%>)) {
7433 <%spPattern%>->index[col_fill[<%col%>]++] = <%rowExpr%>;
7434 }
7435 }
7436 }
7437 >>
7438 case SLICE(exp=sliceExp) :: outer_rev_subs then
7439 // inner SLICE (e.g. module[i].T[1:9]) - outer dims are INDEX subs
7440 let sliceArr = daeExp(sliceExp, context, &preExp, &varDecls, &varFrees, &auxFunction)
7441 let nSlice = tempDecl("modelica_integer", &varDecls, &varFrees)
7442 let &preExp += '<%nSlice%> = size_of_dimension_base_array(<%sliceArr%>, 1);<%\n%>'
7443 let sz = dimension(List.last(crefDims(seed)), context, &preExp, &varDecls, &varFrees, &auxFunction)
7444 let &outerPreExp = buffer ""
7445 let outer_off = match outer_rev_subs
7446 case {} then '0'
7447 else indexSubRecursive(List.restOrEmpty(listReverse(List.restOrEmpty(crefDims(seed)))), outer_rev_subs, context, &outerPreExp, &varDecls, &varFrees, &auxFunction)
7448 <<
7449 <%seedComment%>
7450 {
7451 unsigned int _sc<%v.index%>;
7452 for (_sc<%v.index%> = 0; _sc<%v.index%> < (unsigned int)(<%nSlice%>); _sc<%v.index%>++) {
7453 <%outerPreExp%>
7454 <%spPattern%>->index[col_fill[<%jacobianVarIndex(v, context)%> + (<%outer_off%>) * (unsigned int)(<%sz%>) + (((modelica_integer*)<%sliceArr%>.data)[_sc<%v.index%>] - 1)]++] = <%rowExpr%>;
7455 }
7456 }
7457 >>
7458 case INDEX(exp=innerIndexExp) :: {WHOLEDIM()} then
7459 // reversed [INDEX, WHOLEDIM] = original [WHOLEDIM, INDEX]: outer WHOLE, inner fixed INDEX
7460 let szOuter = dimension(listHead(crefDims(seed)), context, &preExp, &varDecls, &varFrees, &auxFunction)
7461 let szInner = dimension(List.last(crefDims(seed)), context, &preExp, &varDecls, &varFrees, &auxFunction)
7462 let &innerPreExp = buffer ""
7463 let innerIdx = daeSubscriptExp(innerIndexExp, context, &innerPreExp, &varDecls, &varFrees, &auxFunction)
7464 <<
7465 <%seedComment%>
7466 {
7467 unsigned int _wo<%v.index%>;
7468 for (_wo<%v.index%> = 0; _wo<%v.index%> < (unsigned int)(<%szOuter%>); _wo<%v.index%>++) {
7469 <%innerPreExp%>
7470 <%spPattern%>->index[col_fill[<%jacobianVarIndex(v, context)%> + _wo<%v.index%> * (unsigned int)(<%szInner%>) + ((<%innerIdx%>) - 1)]++] = <%rowExpr%>;
7471 }
7472 }
7473 >>
7474 case INDEX(exp=innerIndexExp) :: {SLICE(exp=outerSliceExp)} then
7475 // reversed [INDEX, SLICE] = original [SLICE, INDEX]: outer SLICE range, inner fixed INDEX
7476 let sliceArr = daeExp(outerSliceExp, context, &preExp, &varDecls, &varFrees, &auxFunction)
7477 let nSlice = tempDecl("modelica_integer", &varDecls, &varFrees)
7478 let &preExp += '<%nSlice%> = size_of_dimension_base_array(<%sliceArr%>, 1);<%\n%>'
7479 let szInner = dimension(List.last(crefDims(seed)), context, &preExp, &varDecls, &varFrees, &auxFunction)
7480 let &innerPreExp = buffer ""
7481 let innerIdx = daeSubscriptExp(innerIndexExp, context, &innerPreExp, &varDecls, &varFrees, &auxFunction)
7482 <<
7483 <%seedComment%>
7484 {
7485 unsigned int _so<%v.index%>;
7486 for (_so<%v.index%> = 0; _so<%v.index%> < (unsigned int)(<%nSlice%>); _so<%v.index%>++) {
7487 <%innerPreExp%>
7488 <%spPattern%>->index[col_fill[<%jacobianVarIndex(v, context)%> + (((modelica_integer*)<%sliceArr%>.data)[_so<%v.index%>] - 1) * (unsigned int)(<%szInner%>) + ((<%innerIdx%>) - 1)]++] = <%rowExpr%>;
7489 }
7490 }
7491 >>
7492 else
7493 let &offsetPreExp = buffer ""
7494 let offset = indexSubRecursive(listReverse(List.restOrEmpty(crefDims(seed))), listReverse(crefSubs(seed)), context, &offsetPreExp, &varDecls, &varFrees, &auxFunction)
7495 let col = tempDecl("modelica_integer", &varDecls, &varFrees)
7496 <<
7497 <%seedComment%>
7498 <%offsetPreExp%>
7499 <%col%> = (modelica_integer)(<%jacobianVarIndex(v, context)%>) + (<%offset%>);
7500 if (<%col%> >= 0 && <%col%> < (modelica_integer)(<%nCols%>)) { <%spPattern%>->index[col_fill[<%col%>]++] = <%rowExpr%>; }
7501 >>
7502 else '/* resizableColFill: seed not found in jacHT */'
7503 else ''
7504 end resizableColFillBase;
7505
7506 ✗ template seedSizeAssignments(ComponentRef seed, Context context, Text &preExp, Text &varDecls, Text &varFrees, Text &auxFunction)
7507 ::=
7508 match context
7509 case JACOBIAN_CONTEXT(jacHT=SOME(jacHT)) then
7510 match simVarFromHT(crefStripSubs(seed), jacHT)
7511 case v as SIMVAR(varKind=BackendDAE.JAC_VAR())
7512 case v as SIMVAR(varKind=BackendDAE.JAC_TMP_VAR())
7513 case v as SIMVAR(varKind=BackendDAE.SEED_VAR()) then
7514 let dims = (List.zip(crefDims(seed), crefSubs(seed)) |> (dim, sub) hasindex i0 => dimensionSizeAssignment(dim, sub, v.index, i0, context, &preExp, &varDecls, &varFrees, &auxFunction) ;separator="*")
7515 let &preExp += 'number_of_entries += <%if stringEq(dims, '') then '1' else dims%>;<%\n%> /*<%jacSparsityIndex(crefStripSubs(seed), context)%>*/' // ToDo: multiply size of iterator here
7516 <<
7517
7518 >>
7519 else 'NOT FOUND'
7520 end seedSizeAssignments;
7521
7522 ✗ template dimensionSizeAssignment(Dimension dim, DAE.Subscript sub, Integer var_index, Integer dim_index, Context context, Text &preExp, Text &varDecls, Text &varFrees, Text &auxFunction)
7523 ::=
7524 let tmp_name = 's<%var_index%>_<%dim_index%>'
7525 let dim_exp = dimension(dim, context, &preExp, &varDecls, &varFrees, &auxFunction)
7526 let &varDecls += 'size_t <%tmp_name%> = <%dim_exp%>;<%\n%>'
7527 match sub
7528 case INDEX() then '1'
7529 else tmp_name
7530 end dimensionSizeAssignment;
7531
7532 10171 template initialAnalyticJacobians(list<JacobianColumn> jacobianColumn, list<SimVar> seedVars, String matrixname, SparsityPattern sparsepattern, list<list<Integer>> colorList, Integer maxColor, String modelNamePrefix, String fileNamePrefix, Boolean isAdjoint, Boolean isBidirectional, Integer adjointJacobianIndex, String adjointMatrixName)
7533 "template initialAnalyticJacobians
7534 This template generates source code for functions that initialize the sparse-pattern for a single jacobian.
7535 This is a helper of template functionAnalyticJacobians"
7536 ::=
7537 match sparsepattern
7538 case {} then
7539 <<
7540 int <%symbolName(modelNamePrefix,"initialAnalyticJacobian")%><%matrixname%>(DATA* data, threadData_t *threadData, JACOBIAN *jacobian)
7541 {
7542 jacobian->availability = JACOBIAN_NOT_AVAILABLE;
7543 return 1;
7544 }
7545 >>
7546 case _ then
7547 let sp_size_index = lengthListElements(unzipSecond(sparsepattern))
7548 let sizeleadindex = listLength(sparsepattern)
7549 let availability = if SimCodeCodegenUtil.jacobianColumnsAreEmpty(jacobianColumn) then 'JACOBIAN_ONLY_SPARSITY' else 'JACOBIAN_AVAILABLE'
7550 let sizeRows = (jacobianColumn |> JAC_COLUMN() => numberOfResultVars; separator="\n")
7551 let tmpvarsSize = (jacobianColumn |> JAC_COLUMN() => numScalarElemsExp(columnVars); separator="\n")
7552 let constantEqns = (jacobianColumn |> JAC_COLUMN() =>
7553 match constantEqns case {} then 'NULL' case _ then '<%symbolName(modelNamePrefix,"functionJac")%><%matrixname%>_constantEqns'
7554 ;separator="")
7555 let evalColumn = '<%symbolName(modelNamePrefix,"functionJac")%><%matrixname%>_column'
7556 let sizeCols = listLength(seedVars)
7557 let isRowEval = if isAdjoint then "1" else "0"
7558 <<
7559 OMC_DISABLE_OPT
7560 int <%symbolName(modelNamePrefix,"initialAnalyticJacobian")%><%matrixname%>(DATA* data, threadData_t *threadData, JACOBIAN *jacobian)
7561 {
7562 size_t count;
7563
7564 FILE* pFile = openSparsePatternFile(data, threadData, "<%fileNamePrefix%>_Jac<%matrixname%>.bin");
7565
7566 initJacobian(jacobian, <%sizeCols%>, <%sizeRows%>, <%tmpvarsSize%>, NULL, <%evalColumn%>, <%constantEqns%>, NULL);
7567 jacobian->sparsePattern = allocSparsePattern(<%sizeleadindex%>, <%sp_size_index%>, <%maxColor%>);
7568 jacobian->availability = <%availability%>;
7569 jacobian->isRowEval = <%isRowEval%>;
7570
7571 /* read lead index of compressed sparse column */
7572 count = omc_fread(jacobian->sparsePattern->leadindex, sizeof(unsigned int), <%sizeleadindex%>+1, pFile, FALSE);
7573 if (count != <%sizeleadindex%>+1) {
7574 throwStreamPrint(threadData, "Error while reading lead index list of sparsity pattern. Expected %d, got %zu", <%sizeleadindex%>+1, count);
7575 }
7576
7577 /* read sparse index */
7578 count = omc_fread(jacobian->sparsePattern->index, sizeof(unsigned int), <%sp_size_index%>, pFile, FALSE);
7579 if (count != <%sp_size_index%>) {
7580 throwStreamPrint(threadData, "Error while reading row index list of sparsity pattern. Expected %d, got %zu", <%sp_size_index%>, count);
7581 }
7582
7583 /* write color array */
7584 <%readSPColors(colorList, "jacobian->sparsePattern->colorCols", sizeleadindex)%>
7585
7586 omc_fclose(pFile);
7587
7588 <%if isBidirectional then <<
7589 /* Link the adjoint Jacobian to this forward Jacobian so that the integrators can
7590 * evaluate it bidirectionally. Whether that actually happens is decided at runtime
7591 * by initSymbolicOdeJacobian() based on the `-jacobian` flag. */
7592 {
7593 JACOBIAN* adjJac = &data->simulationInfo->analyticJacobians[<%adjointJacobianIndex%>];
7594 <%symbolName(modelNamePrefix,"initialAnalyticJacobian")%><%adjointMatrixName%>(data, threadData, adjJac);
7595 jacobian->adjointJacobian = adjJac;
7596 initBidirectionalRecovery(jacobian);
7597 }
7598 >> %>
7599
7600 return 0;
7601 }
7602 >>
7603 end match
7604 end initialAnalyticJacobians;
7605
7606 10337 template generateMatrix(list<JacobianColumn> jacobianColumn, list<SimVar> seedVars, String matrixname, Integer partIdx, Option<HashTableCrefSimVar.HashTable> jacHT, String modelNamePrefix)
7607 "This template generates source code for a single jacobian in dense format and sparse format.
7608 This is a helper of template functionAnalyticJacobians"
7609 ::=
7610 let nRows = (jacobianColumn |> JAC_COLUMN(numberOfResultVars=nRows) => nRows)
7611 match nRows
7612 case "0" then
7613 <<
7614 int <%symbolName(modelNamePrefix,"functionJac")%><%matrixname%>_column(DATA* data, threadData_t *threadData, JACOBIAN *jacobian, JACOBIAN *parentJacobian)
7615 {
7616 return 0;
7617 }
7618
7619 void <%symbolName(modelNamePrefix, "Jac")%><%matrixname%>_DAG(DATA* data, threadData_t* threadData, JACOBIAN* jacobian) { /* empty */ }
7620 >>
7621 case _ then
7622 match seedVars
7623 case {} then
7624 <<
7625 int <%symbolName(modelNamePrefix,"functionJac")%><%matrixname%>_column(DATA* data, threadData_t *threadData, JACOBIAN *jacobian, JACOBIAN *parentJacobian)
7626 {
7627 return 0;
7628 }
7629
7630 void <%symbolName(modelNamePrefix, "Jac")%><%matrixname%>_DAG(DATA* data, threadData_t* threadData, JACOBIAN* jacobian) { /* empty */ }
7631 >>
7632 case _ then
7633 let jacMats =
7634 (jacobianColumn |> JAC_COLUMN(columnEqns=eqs, constantEqns=constantEqns) =>
7635 functionJac(eqs, constantEqns, partIdx, createJacContext(matrixname, jacHT), modelNamePrefix)
7636 ;separator="\n")
7637 let jacDAG = (jacobianColumn |> JAC_COLUMN(columnEqns=eqs) => functionJac_DAG(eqs, matrixname, modelNamePrefix) ;separator="\n")
7638 <<
7639 <%jacMats%>
7640
7641 <%jacDAG%>
7642 >>
7643 end match
7644 end match
7645 end generateMatrix;
7646
7647 2100 template generateConstantEqns(list<SimEqSystem> constantEqns, String modelNamePrefix, Context context)
7648 ::=
7649 match context
7650 case JACOBIAN_CONTEXT() then
7651 let &chunks = buffer ""
7652 let calls = equations_call(constantEqns, modelNamePrefix, context, '', false, &chunks)
7653 <<
7654 <%chunks%>
7655 OMC_DISABLE_OPT
7656 int <%symbolName(modelNamePrefix,"functionJac")%><%name%>_constantEqns(DATA* data, threadData_t *threadData, JACOBIAN *jacobian, JACOBIAN *parentJacobian)
7657 {
7658 int index = <%symbolName(modelNamePrefix,"INDEX_JAC_")%><%name%>;
7659
7660 <%calls%>
7661
7662 return 0;
7663 }
7664 >>
7665 end generateConstantEqns;
7666
7667 2100 template functionJac(list<SimEqSystem> jacEquations, list<SimEqSystem> constantEqns, Integer base_idx, Context context, String modelNamePrefix)
7668 "This template generates functions for each column of a single jacobian.
7669 This is a helper of generateMatrix."
7670 ::=
7671 match context
7672 case JACOBIAN_CONTEXT() then
7673 let &chunks = buffer ""
7674 let calls = equations_call(jacEquations, modelNamePrefix, context, 'jacobian->evalSelection', true, &chunks)
7675 <<
7676 /* constant equations */
7677 <%(constantEqns |> eq hasindex sub_idx =>
7678 equation_impl(base_idx, sub_idx, eq, context, modelNamePrefix, false); separator="\n")%>
7679 /* dynamic equations */
7680 <%(jacEquations |> eq hasindex sub_idx =>
7681 equation_impl(base_idx, sub_idx, eq, context, modelNamePrefix, false); separator="\n")%>
7682
7683 <%generateConstantEqns(constantEqns, modelNamePrefix, context)%>
7684
7685 <%chunks%>
7686 int <%symbolName(modelNamePrefix,"functionJac")%><%name%>_column(DATA* data, threadData_t *threadData, JACOBIAN *jacobian, JACOBIAN *parentJacobian)
7687 {
7688 int index = <%symbolName(modelNamePrefix,"INDEX_JAC_")%><%name%>;
7689
7690 <%calls%>
7691
7692 return 0;
7693 }
7694 >>
7695 end functionJac;
7696
7697 2100 template functionJac_DAG(list<SimEqSystem> eqs, String name, String modelNamePrefix)
7698 ::=
7699 <<
7700 void <%symbolName(modelNamePrefix, "Jac")%><%name%>_DAG(DATA* data, threadData_t* threadData, JACOBIAN* jacobian)
7701 {
7702 const size_t eqMap[] = {<%eqs |> eq => equationIndexGeneral(eq); separator=", "%>};
7703 buildEvalDAG_Jac(jacobian, data->modelData, sizeof(eqMap)/sizeof(size_t), eqMap);
7704 }
7705 >>
7706 end functionJac_DAG;
7707
7708 // function for sparsity pattern generation
7709 1502 template genSPCRSPtr(Integer sizeColPtr, SparsityPattern sparsepattern, String constArrayName)
7710 "This template generates colPtr of the CRS format"
7711 ::=
7712 let colPtrindex = (sparsepattern |> (i, indexes) =>
7713 <<
7714 <%listLength(indexes)%>
7715 >>
7716 ;separator=",")
7717 <<
7718 const int <%constArrayName%>[1+<%sizeColPtr%>] = {0,<%colPtrindex%>};
7719 >>
7720 end genSPCRSPtr;
7721
7722 1502 template genSPCRSRows(Integer nonZeroElems, SparsityPattern sparsepattern, String constArrayName)
7723 "This template generates row of the CRS format"
7724 ::=
7725 let rowsIndex = ( sparsepattern |> (i, indexes) hasindex index0 =>
7726 ( indexes |> indexrow =>
7727 <<
7728 <%indexrow%>
7729 >>
7730 ;separator=",")
7731 ;separator=",")
7732 <<
7733 const int <%constArrayName%>[<%nonZeroElems%>] = {<%rowsIndex%>};
7734 >>
7735 end genSPCRSRows;
7736
7737 864 template genSPColors(list<list<Integer>> colorList, String arrayName)
7738 "This template generates row of the CRS format"
7739 ::=
7740 let colorArray = (colorList |> (indices) hasindex index0 =>
7741 let length = '<%listLength(indices)%>'
7742 let index = '<%intAdd(index0,1)%>'
7743 let ind_name = 'indices_<%index%>'
7744 <<
7745 /* color <%index%> with <%length%> columns */
7746 const int <%ind_name%>[<%length%>] = {<%(indices |> i_index =>
7747 '<%i_index%>' ;separator=", ")%>};
7748 for(i=0; i<<%length%>; i++)
7749 <%arrayName%>[<%ind_name%>[i]] = <%index%>;
7750 >>;separator="\n\n")
7751 <<
7752 <%colorArray%>
7753 >>
7754 end genSPColors;
7755
7756 1934 template readSPColors(list<list<Integer>> colorList, String arrayName, String maxIndex)
7757 "This template generates row of the CRS format"
7758 ::=
7759 let colorArray = (colorList |> (indices) hasindex index0 =>
7760 let length = '<%listLength(indices)%>'
7761 let index = '<%intAdd(index0,1)%>'
7762 <<
7763 /* color <%index%> with <%length%> columns */
7764 readSparsePatternColor(threadData, pFile, <%arrayName%>, <%index%>, <%length%>, <%maxIndex%>);
7765 >>;separator="\n")
7766 <<
7767 <%colorArray%>
7768 >>
7769 end readSPColors;
7770
7771 ✗ template equation_arrayFormat(SimEqSystem eq, String name, Context context, Integer arrayIndex, Text &eqArray, Text &eqfuncs, String modelNamePrefix, Boolean init)
7772 "Generates an equation.
7773 This template should not be used for a SES_RESIDUAL.
7774 Residual equations are handled differently."
7775 ::=
7776 match eq
7777 case SES_ALGORITHM(statements={}) then ""
7778 else
7779 (
7780 let ix = equationIndex(eq) /*System.tmpTickIndex(10)*/
7781 let &tmp = buffer ""
7782 let &varD = buffer ""
7783 let &varDFrees = buffer ""
7784 let &tempeqns = buffer ""
7785 let &OMC_DISABLE_OPT = buffer ""
7786 let() = System.tmpTickResetIndex(0,1) /* Boxed array indices */
7787 let disc = match context
7788 case SIMULATION_CONTEXT(genDiscrete=true) then 1
7789 else 0
7790 let x = match eq
7791 case e as SES_SIMPLE_ASSIGN(__)
7792 case e as SES_SIMPLE_ASSIGN_CONSTRAINTS(__)
7793 then equationSimpleAssign(e, context, &varD, &varDFrees, &tempeqns)
7794 case e as SES_ARRAY_CALL_ASSIGN(__)
7795 then equationArrayCallAssign(e, context, &varD, &varDFrees, &tempeqns)
7796 case e as SES_RESIZABLE_ASSIGN(__)
7797 then equationGenericAssign(e, context, &varD, &varDFrees, &tempeqns, modelNamePrefix)
7798 case e as SES_GENERIC_ASSIGN(__)
7799 then equationGenericAssign(e, context, &varD, &varDFrees, &tempeqns, modelNamePrefix)
7800 case e as SES_ENTWINED_ASSIGN(__)
7801 then equationEntwinedAssign(e, context, &varD, &varDFrees, &tempeqns, modelNamePrefix)
7802 case e as SES_IFEQUATION(__)
7803 then equationIfEquationAssign(e, context, &varD, &varDFrees, &tempeqns, modelNamePrefix, init)
7804 case e as SES_ALGORITHM(__)
7805 case e as SES_INVERSE_ALGORITHM(__)
7806 then equationAlgorithm(e, context, &varD, &varDFrees, &tempeqns)
7807 case e as SES_LINEAR(__)
7808 then
7809 let &OMC_DISABLE_OPT += 'OMC_DISABLE_OPT<%\n%>'
7810 equationLinear(e, context, &varD, &varDFrees)
7811 // no dynamic tearing
7812 case e as SES_NONLINEAR(nlSystem=nls as NONLINEARSYSTEM(__), alternativeTearing=NONE()) then
7813 let &tempeqns += (nls.eqs |> eq => 'void <%symbolName(modelNamePrefix,"eqFunction")%>_<%equationIndex(eq)%>(DATA*,threadData_t*);' ; separator = "\n")
7814 equationNonlinear(e, context, modelNamePrefix, init)
7815 // dynamic tearing
7816 case e as SES_NONLINEAR(nlSystem=nls as NONLINEARSYSTEM(__), alternativeTearing = SOME(at as NONLINEARSYSTEM(__))) then
7817 let &tempeqns += (nls.eqs |> eq => 'void <%symbolName(modelNamePrefix,"eqFunction")%>_<%equationIndex(eq)%>(DATA*,threadData_t*);' ; separator = "\n")
7818 let &tempeqns += '<%\n%>'
7819 let &tempeqns += (at.eqs |> eq => 'void <%symbolName(modelNamePrefix,"eqFunction")%>_<%equationIndex(eq)%>(DATA*,threadData_t*);' ; separator = "\n")
7820 equationNonlinear(e, context, modelNamePrefix, init)
7821 case e as SES_WHEN(__)
7822 then equationWhen(e, context, &varD, &varDFrees, &tempeqns)
7823 case e as SES_RESIDUAL(__)
7824 then "NOT IMPLEMENTED EQUATION SES_RESIDUAL"
7825 case e as SES_FOR_RESIDUAL(__)
7826 then "NOT IMPLEMENTED EQUATION SES_FOR_RESIDUAL"
7827 case e as SES_GENERIC_RESIDUAL(__)
7828 then "NOT IMPLEMENTED EQUATION SES_GENERIC_RESIDUAL"
7829 case e as SES_MIXED(__)
7830 then equationMixed(e, context, &eqfuncs, modelNamePrefix, init)
7831 else
7832 error(sourceInfo(), "NOT IMPLEMENTED EQUATION equation_")
7833
7834 let &eqArray += '<%symbolName(modelNamePrefix,"eqFunction")%>_<%ix%>, <%\n%>'
7835 let &varD += addRootsTempArray()
7836 let &eqfuncs +=
7837 <<
7838
7839 <%tempeqns%>
7840 /*
7841 <%dumpEqs(fill(eq,1))%>
7842 */
7843 <%OMC_DISABLE_OPT%>void <%symbolName(modelNamePrefix,"eqFunction")%>_<%ix%>(DATA *data, threadData_t *threadData)
7844 {
7845 const int equationIndexes[2] = {1,<%ix%>};
7846 <%&varD%>
7847 <%equation_withProfile(ix, x)%>
7848 _return: OMC_LABEL_UNUSED ;
7849 <%varDFrees%>
7850 }
7851 >>
7852 <<
7853 // <%symbolName(modelNamePrefix,"eqFunction")%>_<%ix%>(data, threadData);
7854 function<%name%>_systems[<%arrayIndex%>](data, threadData);
7855 >>
7856 )
7857 end equation_arrayFormat;
7858
7859 104695 template equation_impl(Integer base_idx, Integer sub_idx, SimEqSystem eq, Context context, String modelNamePrefix, Boolean init)
7860 "Generates an equation.
7861 This template should not be used for a SES_RESIDUAL.
7862 Residual equations are handled differently."
7863 ::=
7864 equation_impl2(base_idx, sub_idx, eq, context, modelNamePrefix, false, false, init)
7865 end equation_impl;
7866
7867 288269 template equation_impl2(Integer base_idx, Integer sub_idx, SimEqSystem eq, Context context, String modelNamePrefix, Boolean static, Boolean noOpt, Boolean init)
7868 "Generates an equation.
7869 This template should not be used for a SES_RESIDUAL.
7870 Residual equations are handled differently."
7871 ::=
7872 let OMC_NO_OPT = if noOpt then 'OMC_DISABLE_OPT<%\n%>' else (match eq case SES_LINEAR(__) then 'OMC_DISABLE_OPT<%\n%>')
7873 match eq
7874
7875 case SES_ALIAS(__) then 'extern void <%symbolName(modelNamePrefix,"eqFunction")%>_<%aliasOf%>(DATA *data, threadData_t *threadData);<%\n%>'
7876 case SES_ALGORITHM(statements={}) then ""
7877 else
7878 (
7879 let ix = equationIndex(eq) /*System.tmpTickIndex(10)*/
7880 let ix2 = match eq
7881 case SES_LINEAR(lSystem=LINEARSYSTEM(__), alternativeTearing = SOME(LINEARSYSTEM(__)))
7882 case SES_NONLINEAR(nlSystem=NONLINEARSYSTEM(__), alternativeTearing = SOME(NONLINEARSYSTEM(__)))
7883 then equationIndexAlternativeTearing(eq)
7884 else ""
7885 let &tmp = buffer ""
7886 let &varD = buffer ""
7887 let &varDFrees = buffer ""
7888 let &tempeqns = buffer ""
7889 let &tempeqns2 = buffer ""
7890 let() = System.tmpTickResetIndex(0,1) /* Boxed array indices */
7891 let disc = match context case SIMULATION_CONTEXT(genDiscrete=true) then 1 else 0
7892 let x = match eq
7893
7894 case e as SES_SIMPLE_ASSIGN(__)
7895 case e as SES_SIMPLE_ASSIGN_CONSTRAINTS(__)
7896 then equationSimpleAssign(e, context, &varD, &varDFrees, &tempeqns)
7897
7898 case e as SES_ARRAY_CALL_ASSIGN(__)
7899 then equationArrayCallAssign(e, context, &varD, &varDFrees, &tempeqns)
7900
7901 case e as SES_RESIZABLE_ASSIGN(__)
7902 then equationGenericAssign(e, context, &varD, &varDFrees, &tempeqns, modelNamePrefix)
7903
7904 case e as SES_GENERIC_ASSIGN(__)
7905 then equationGenericAssign(e, context, &varD, &varDFrees, &tempeqns, modelNamePrefix)
7906
7907 case e as SES_ENTWINED_ASSIGN(__)
7908 then equationEntwinedAssign(e, context, &varD, &varDFrees, &tempeqns, modelNamePrefix)
7909
7910 case e as SES_IFEQUATION(__)
7911 then equationIfEquationAssign(e, context, &varD, &varDFrees, &tempeqns, modelNamePrefix, init)
7912
7913 case e as SES_ALGORITHM(__)
7914 then equationAlgorithm(e, context, &varD, &varDFrees, &tempeqns)
7915
7916 case e as SES_INVERSE_ALGORITHM(__)
7917 then equationAlgorithm(e, context, &varD, &varDFrees, &tempeqns)
7918
7919 case e as SES_LINEAR(__)
7920 then equationLinear(e, context, &varD, &varDFrees)
7921
7922 case e as SES_NONLINEAR(nlSystem=nls as NONLINEARSYSTEM(__))
7923 then
7924 let &tempeqns += (nls.eqs |> eq => 'void <%symbolName(modelNamePrefix,"eqFunction")%>_<%equationIndex(eq)%>(DATA*, threadData_t*);' ; separator = "\n")
7925 equationNonlinear(e, context, modelNamePrefix, init)
7926
7927 case e as SES_WHEN(__)
7928 then equationWhen(e, context, &varD, &varDFrees, &tempeqns)
7929
7930 case e as SES_RESIDUAL(__)
7931 then "NOT IMPLEMENTED EQUATION SES_RESIDUAL"
7932
7933 case e as SES_FOR_RESIDUAL(__)
7934 then "NOT IMPLEMENTED EQUATION SES_FOR_RESIDUAL"
7935
7936 case e as SES_GENERIC_RESIDUAL(__)
7937 then "NOT IMPLEMENTED EQUATION SES_GENERIC_RESIDUAL"
7938
7939 case e as SES_MIXED(__)
7940 then
7941 let &eqs = buffer ""
7942 let res = equationMixed(e, context, &eqs, modelNamePrefix, init)
7943 eqs + res
7944
7945 case e as SES_FOR_LOOP(__)
7946 then equationForLoop(e, context, &varD, &varDFrees, &tempeqns)
7947
7948 else "NOT IMPLEMENTED EQUATION equation_"
7949
7950 let x2 = match eq
7951 case e as SES_LINEAR(lSystem=ls as LINEARSYSTEM(__), alternativeTearing = SOME(at as LINEARSYSTEM(__)))
7952 then equationLinearAlternativeTearing(e, context, &varD, &varDFrees)
7953
7954 case e as SES_NONLINEAR(nlSystem=nls as NONLINEARSYSTEM(__), alternativeTearing = SOME(at as NONLINEARSYSTEM(__)))
7955 then
7956 let &tempeqns2 += (at.eqs |> eq => 'void <%symbolName(modelNamePrefix,"eqFunction")%>_<%equationIndex(eq)%>(DATA*,threadData_t*);' ; separator = "\n")
7957 equationNonlinearAlternativeTearing(e, context, modelNamePrefix, init)
7958 else ""
7959
7960 let &varD += addRootsTempArray()
7961 let baseClockIndex_ = if intLt(base_idx, 0) then '' else 'const int baseClockIndex = <%base_idx%>;'
7962 let subClockIndex_ = if intLt(sub_idx, 0) then '' else 'const int subClockIndex = <%sub_idx%>;'
7963
7964 match eq
7965 // dynamic tearing
7966 case e as SES_LINEAR(lSystem=ls as LINEARSYSTEM(__), alternativeTearing = SOME(at as LINEARSYSTEM(__)))
7967 case e as SES_NONLINEAR(nlSystem=nls as NONLINEARSYSTEM(__), alternativeTearing = SOME(at as NONLINEARSYSTEM(__))) then
7968 <<
7969
7970 <%tempeqns%>
7971 /*
7972 <%dumpEqs(fill(eq,1))%>
7973 */
7974 <%OMC_NO_OPT%><% if static then "static "%>int <%symbolName(modelNamePrefix,"eqFunction")%>_<%ix%>(DATA *data, threadData_t *threadData)
7975 {
7976 <%baseClockIndex_%>
7977 <%subClockIndex_%>
7978 const int equationIndexes[2] = {1,<%ix%>};
7979 <%&varD%>
7980 <%equation_withProfile(ix, x)%>
7981 _return: OMC_LABEL_UNUSED ;
7982 <%varDFrees%>
7983 }
7984
7985 <%tempeqns2%>
7986 /*
7987 <%dumpEqsAlternativeTearing(fill(eq,1))%>
7988 */
7989 <%OMC_NO_OPT%><% if static then "static "%>void <%symbolName(modelNamePrefix,"eqFunction")%>_<%ix2%>(DATA *data, threadData_t *threadData)
7990 {
7991 <%baseClockIndex_%>
7992 <%subClockIndex_%>
7993 const int equationIndexes[2] = {1,<%ix2%>};
7994 <%&varD%>
7995 <%equation_withProfile(ix2, x2)%>
7996 _return: OMC_LABEL_UNUSED ;
7997 <%varDFrees%>
7998 }
7999 >>
8000
8001 // no dynamic tearing
8002 else
8003 match context
8004 case JACOBIAN_CONTEXT()
8005 then
8006 <<
8007
8008 <%tempeqns%>
8009 /*
8010 <%dumpEqs(fill(eq,1))%>
8011 */
8012 <%OMC_NO_OPT%><% if static then "static "%>void <%symbolName(modelNamePrefix,"eqFunction")%>_<%ix%>(DATA *data, threadData_t *threadData, JACOBIAN *jacobian, JACOBIAN *parentJacobian)
8013 {
8014 <%baseClockIndex_%>
8015 <%subClockIndex_%>
8016 const int equationIndexes[2] = {1,<%ix%>};
8017 <%&varD%>
8018 <%equation_withProfile(ix, x)%>
8019 _return: OMC_LABEL_UNUSED ;
8020 <%varDFrees%>
8021 }
8022 >>
8023 else
8024 <<
8025
8026 <%tempeqns%>
8027 /*
8028 <%dumpEqs(fill(eq,1))%>
8029 */
8030 <%OMC_NO_OPT%><% if static then "static "%>void <%symbolName(modelNamePrefix,"eqFunction")%>_<%ix%>(DATA *data, threadData_t *threadData)
8031 {
8032 <%baseClockIndex_%>
8033 <%subClockIndex_%>
8034 const int equationIndexes[2] = {1,<%ix%>};
8035 <%&varD%>
8036 <%equation_withProfile(ix, x)%>
8037 _return: OMC_LABEL_UNUSED ;
8038 <%varDFrees%>
8039 }
8040 >>
8041 )
8042 end equation_impl2;
8043
8044 31021 template equation_call(SimEqSystem eq, String modelNamePrefix, Context context)
8045 "Generates either a normal or jacobian equation depending on context.
8046 ToDo: add other cases?"
8047 ::=
8048 match eq
8049 case SES_ALGORITHM(statements={}) then ""
8050 else
8051 let args = match context
8052 case JACOBIAN_CONTEXT() then 'data, threadData, jacobian, parentJacobian'
8053 else 'data, threadData'
8054 <<
8055 <%symbolName(modelNamePrefix,"eqFunction")%>_<%equationIndexGeneral(eq)%>(<%args%>);
8056 >>
8057 end equation_call;
8058
8059 6503 template equations_call(list<SimEqSystem> eqs, String modelNamePrefix, Context context, String selection, Boolean optimize, Text &chunks)
8060 "Generates sequence of equation calls, in chunk functions of at most 500."
8061 ::=
8062 match eqs
8063 case {} then ''
8064 else
8065 let name = symbolName(modelNamePrefix, "eqFunction")
8066 let nFuncs = listLength(eqs)
8067 let args = match context
8068 case JACOBIAN_CONTEXT() then 'data, threadData, jacobian, parentJacobian'
8069 else 'data, threadData'
8070 let argsType = match context
8071 case JACOBIAN_CONTEXT() then 'DATA*, threadData_t*, JACOBIAN*, JACOBIAN*'
8072 else 'DATA*, threadData_t*'
8073 let params = match context
8074 case JACOBIAN_CONTEXT() then 'DATA *data, threadData_t *threadData, JACOBIAN *jacobian, JACOBIAN *parentJacobian'
8075 else 'DATA *data, threadData_t *threadData'
8076 // Stop at an equation that raised: the ones after it must not run and
8077 // report asserts of their own. Direct calls, since one indirect call site
8078 // with thousands of targets mispredicts; the cap bounds inlining.
8079 let calls = (List.partition(eqs, 500) |> part =>
8080 let chunk = '<%symbolName(modelNamePrefix, "eqChunk")%>_<%System.tmpTickIndex(2)%>'
8081 let &chunks +=
8082 <<
8083 <%if optimize then "" else "OMC_DISABLE_OPT\n"%>static void <%chunk%>(<%params%>)
8084 {
8085 do {
8086 <%part |> eq => '<%name%>_<%equationIndexGeneral(eq)%>(<%args%>); if (OMC_ERROR_RAISED()) break;'; separator="\n"%>
8087 } while (0);
8088 }
8089
8090 >>
8091 '<%chunk%>(<%args%>); if (OMC_ERROR_RAISED()) break;'
8092 ; separator="\n")
8093 let seq =
8094 <<
8095 do {
8096 <%calls%>
8097 } while (0);
8098 >>
8099 match selection
8100 case "" then seq
8101 else
8102 <<
8103 if (<%selection%>) {
8104 static void (*const eqFunctions[<%nFuncs%>])(<%argsType%>) = {
8105 <%eqs |> eq => '<%name%>_<%equationIndexGeneral(eq)%>'; separator=",\n"%>
8106 };
8107 for (int i = 0; i < <%selection%>->n; i++) {
8108 int id = <%selection%>->idx[i];
8109 eqFunctions[id](<%args%>);
8110 if (OMC_ERROR_RAISED()) break;
8111 }
8112 } else {
8113 <%seq%>
8114 }
8115 >>
8116 end equations_call;
8117
8118 234406 template equation_withProfile(String index, String body)
8119 ::=
8120 <<
8121 <% if profileAll() then 'SIM_PROF_TICK_EQ(<%index%>);' %>
8122 <%body%>
8123 <% if profileAll() then 'SIM_PROF_ACC_EQ(<%index%>);' %>
8124 threadData->lastEquationSolved = <%index%>;
8125 >>
8126 end equation_withProfile;
8127
8128 52198 template equationForward_(SimEqSystem eq, Context context, String modelNamePrefixStr)
8129 "Generates an equation.
8130 This template should not be used for a SES_RESIDUAL.
8131 Residual equations are handled differently."
8132 ::=
8133 match eq
8134 case SES_ALGORITHM(statements={}) then ""
8135 else
8136 let ix = equationIndexGeneral(eq)
8137 <<
8138 extern void <%symbolName(modelNamePrefixStr,"eqFunction")%>_<%ix%>(DATA* data, threadData_t *threadData);
8139 >>
8140 end equationForward_;
8141
8142 5180 template equationNames_(SimEqSystem eq, Context context, String modelNamePrefixStr)
8143 "Generates an equation.
8144 This template should not be used for a SES_RESIDUAL.
8145 Residual equations are handled differently."
8146 ::=
8147 match eq
8148 case SES_ALGORITHM(statements={}) then ""
8149 else
8150 let ix = equationIndexGeneral(eq)
8151 let body = '<%symbolName(modelNamePrefixStr,"eqFunction")%>_<%ix%>(data, threadData);'
8152 <<
8153 <% match context case DAE_MODE_CONTEXT() then simEqAttrEval(eq) %>
8154 <% match context case DAE_MODE_CONTEXT() then 'if ((evalStages & currentEvalStage) && !((currentEvalStage!=EVAL_DISCRETE)?(<%simEqAttrIsDiscreteKind(eq)%>):0)) {' else '{' %>
8155 <%equation_withProfile(ix, body)%>
8156 }
8157 >>
8158 end equationNames_;
8159
8160 180531 template equationSimpleAssign(SimEqSystem eq, Context context,
8161 Text &varDecls, Text &varFrees, Text &auxFunction)
8162 "Generates an equation that is just a simple assignment."
8163 ::=
8164 match eq
8165 case SES_SIMPLE_ASSIGN(exp=CALL(path=IDENT(name="fail")))
8166 case SES_SIMPLE_ASSIGN_CONSTRAINTS(exp=CALL(path=IDENT(name="fail"))) then
8167 '<%generateThrow()%><%\n%>'
8168 case SES_SIMPLE_ASSIGN(__)
8169 case SES_SIMPLE_ASSIGN_CONSTRAINTS(__) then
8170 let &sub = buffer ""
8171 let &preExp = buffer ""
8172 let expPart = daeExp(exp, context, &preExp, &varDecls, &varFrees, &auxFunction)
8173 let postExp = if isStartCref(cref) then
8174 // Special handling for pre variables
8175 let name = match cref
8176 case CREF_QUAL(componentRef = cr as CREF_QUAL( ident = "$PRE" )) then
8177 '<%crefVarInfo(popCref(cr))%>.name'
8178 else
8179 '<%crefVarInfo(popCref(cref))%>.name'
8180 end match
8181 <<
8182 <%if stringEq(crefType(cref), "modelica_string")
8183 then 'omc_string_store(&(<%cref(popCref(cref), &sub)%>), <%cref(cref, &sub)%>);'
8184 else '<%cref(popCref(cref), &sub)%> = <%cref(cref, &sub)%>;'%>
8185 <%if stringEq(isPrintableCrefType(popCref(cref)), "true") then
8186 <<
8187 infoStreamPrint(OMC_LOG_INIT_V, 0,
8188 "updated start value: %s(start=<%crefToPrintfArg(popCref(cref))%>)",
8189 <%name%>,
8190 (<%crefType(popCref(cref))%>) <%cref(popCref(cref), &sub)%>);
8191 >>
8192 %>
8193 >>
8194 let lhs = equationSimpleAssignLhs(cref, context, &preExp, &varDecls, &varFrees, &auxFunction, &sub)
8195 // A String variable's slot owns its reference (util/omc_string.h).
8196 let assign = if stringEq(crefType(cref), "modelica_string")
8197 then 'omc_string_store(&(<%lhs%>), <%expPart%>);'
8198 else '<%lhs%> = <%expPart%>;'
8199 <<
8200 <%modelicaLine(eqInfo(eq))%>
8201 <%preExp%>
8202 <%assign%>
8203 <%postExp%>
8204 <%endModelicaLine()%>
8205 >>
8206 end equationSimpleAssign;
8207
8208 180535 template equationSimpleAssignLhs(ComponentRef cref, Context context,
8209 Text &preExp, Text &varDecls, Text &varFrees, Text &auxFunction, Text &sub)
8210 "Generates the left hand side cref of a simple assignment.
8211 When sim code scalarization is disabled (new backend), array elements like
8212 arr[2] are not standalone simvars. They have to be addressed relative to the
8213 first element of the array using a flattened index, the same way the right
8214 hand side and variable subscripts are handled in daeExpCref*SimContext."
8215 ::=
8216 match context
8217 case FUNCTION_CONTEXT(__)
8218 case JACOBIAN_CONTEXT(__) then
8219 contextCref(cref, context, &preExp, &varDecls, &varFrees, &auxFunction, &sub)
8220 else
8221 // Note: $START crefs address the (array valued) start attribute and must
8222 // not be flattened here, they keep the regular handling.
8223 if boolAnd(boolAnd(Flags.getConfigBool(Flags.NEW_BACKEND), boolNot(Flags.getConfigBool(Flags.SIM_CODE_SCALARIZE))), boolNot(isStartCref(cref))) then
8224 match crefSubs(crefArrayGetFirstCref(cref))
8225 case {} then
8226 contextCref(cref, context, &preExp, &varDecls, &varFrees, &auxFunction, &sub)
8227 else
8228 let &idxSub = buffer '<%indexSubs(crefDims(cref), crefSubs(crefArrayGetFirstCref(cref)), context, &preExp, &varDecls, &varFrees, &auxFunction)%>'
8229 contextCref(crefStripSubs(cref), context, &preExp, &varDecls, &varFrees, &auxFunction, &idxSub)
8230 else
8231 contextCref(cref, context, &preExp, &varDecls, &varFrees, &auxFunction, &sub)
8232 end equationSimpleAssignLhs;
8233
8234 ✗ template equationForLoop(SimEqSystem eq, Context context, Text &varDecls, Text &varFrees, Text &auxFunction)
8235 "Generates an equation that is a for-loop."
8236 ::=
8237 match eq
8238 case SES_FOR_LOOP(__) then
8239 let &preExp = buffer ""
8240 let expPart = daeExp(exp, context, &preExp, &varDecls, &varFrees, &auxFunction)
8241 let crefPart = daeExp(crefExp(cref), context, &preExp, &varDecls, &varFrees, &auxFunction)
8242 //let bodyStr = daeExpIteratedCref(body)
8243 let start = dumpExp(startIt,"\"")
8244 let stop = dumpExp(endIt,"\"")
8245 let iterVar = daeExp(iter, context, &preExp, &varDecls, &varFrees, &auxFunction)
8246 <<
8247 <%modelicaLine(eqInfo(eq))%>
8248 modelica_integer $P<%dumpExp(iter,"\"")%> = 0; // the iterator
8249 // the for-equation
8250 for($P<%dumpExp(iter,"\"")%> = <%start%>; $P<%dumpExp(iter,"\"")%> != <%stop%>+1; $P<%dumpExp(iter,"\"")%>++)
8251 {
8252 <%crefPart%> += <%expPart%>;
8253 }
8254 <%endModelicaLine()%>
8255 >>
8256 end equationForLoop;
8257
8258
8259 982 template equationArrayCallAssign(SimEqSystem eq, Context context,
8260 Text &varDecls, Text &varFrees, Text &auxFunction)
8261 "Generates equation on form 'cref_array = call(...)'."
8262 ::=
8263 <<
8264 <%modelicaLine(eqInfo(eq))%>
8265 <%match eq
8266
8267 case eqn as SES_ARRAY_CALL_ASSIGN(lhs=lhs as CREF(__)) then
8268 let &preExp = buffer ""
8269 let expPart = daeExp(exp, context, &preExp, &varDecls, &varFrees, &auxFunction)
8270 if boolAnd(crefSubIsScalar(lhs.componentRef), isStartCref(lhs.componentRef)) then
8271 <<
8272 <%preExp%>
8273 <%startArrayScatter(lhs.componentRef, expTypeFromExpShort(eqn.exp), expPart, &varDecls, &varFrees)%>
8274 >>
8275 else if crefSubIsScalar(lhs.componentRef) then
8276 let lhsstr = daeExpCrefLhs(lhs, context, &preExp, &varDecls, &varFrees, &auxFunction, false)
8277 match expTypeFromExpShort(eqn.exp)
8278 case "boolean" then
8279 <<
8280 <%preExp%>
8281 if (!OMC_ERROR_RAISED()) boolean_array_copy_data(<%expPart%>, <%lhsstr%>);
8282 >>
8283 case "integer" then
8284 <<
8285 <%preExp%>
8286 if (!OMC_ERROR_RAISED()) integer_array_copy_data(<%expPart%>, <%lhsstr%>);
8287 >>
8288 case "real" then
8289 <<
8290 <%preExp%>
8291 if (!OMC_ERROR_RAISED()) real_array_copy_data(<%expPart%>, <%lhsstr%>);
8292 >>
8293 case "string" then
8294 <<
8295 <%preExp%>
8296 if (!OMC_ERROR_RAISED()) string_array_copy_data(<%expPart%>, <%lhsstr%>);
8297 >>
8298 else error(sourceInfo(), 'No runtime support for this sort of array call: <%dumpExp(eqn.exp,"\"")%>')
8299 else
8300 let assign = algStmtAssignArrWithRhsExpStr(lhs, expPart, context, &preExp, &varDecls, &varFrees, &auxFunction)
8301 <<
8302 <%preExp%>
8303 <%assign%>
8304 >>
8305 %>
8306 <%endModelicaLine()%>
8307 >>
8308 end equationArrayCallAssign;
8309
8310 2 template equationResidualAt(Exp exp, Text &varDecls, Text &varFrees, Text &auxFunction, Integer eq_index, Text res_index)
8311 "like equationResidual with the position in the residual vector as expression"
8312 ::=
8313 let &preExp = buffer ""
8314 let expPart = daeExp(exp, contextSimulationDiscrete, &preExp, &varDecls, &varFrees, &auxFunction)
8315 let assignment = (if isArrayType(typeof(exp))
8316 then '<%preExp%>copy_real_array_data_mem(<%expPart%>, res+<%res_index%>);'
8317 else '<%preExp%>res[<%res_index%>] = <%expPart%>;')
8318 equation_withProfile(eq_index, assignment)
8319 end equationResidualAt;
8320
8321 7627 template equationResidual(Exp exp, Text &varDecls, Text &varFrees, Text &auxFunction, Integer eq_index, Integer res_index)
8322 ::=
8323 let &preExp = buffer ""
8324 let expPart = daeExp(exp, contextSimulationDiscrete, &preExp, &varDecls, &varFrees, &auxFunction)
8325 let assignment = (if isArrayType(typeof(exp))
8326 then '<%preExp%>copy_real_array_data_mem(<%expPart%>, res+<%res_index%>);'
8327 else '<%preExp%>res[<%res_index%>] = <%expPart%>;')
8328 equation_withProfile(eq_index, assignment)
8329 end equationResidual;
8330
8331 408 template equationGenericAssign(SimEqSystem eq, Context context,
8332 Text &varDecls, Text &varFrees, Text &auxFunction, String modelNamePrefix)
8333 "Generate a call for a generic for-loop structure with an index-list."
8334 ::=
8335 let jac = match context case JACOBIAN_CONTEXT() then ", jacobian" else ""
8336 let sub_name = match context case JACOBIAN_CONTEXT(name = jac_name) then 'jac_<%jac_name%>_' else ""
8337 <<
8338 <%modelicaLine(eqInfo(eq))%>
8339 <%match eq
8340 case eqn as SES_RESIZABLE_ASSIGN() then
8341 let &preExp = buffer ""
8342 let &sub = buffer ""
8343 let forIter = (iters |> it => forIterator(it, context, &preExp, &varDecls, &varFrees, &auxFunction, &sub);separator="\n";empty)
8344 let forNames = (iters |> it => forIteratorName(it, context, &preExp, &varDecls, &varFrees, &auxFunction, &sub);separator=", ";empty)
8345 let forTail = (iters |> it => "}";separator="\n";empty)
8346 <<
8347 <%forIter%>
8348 <%preExp%>
8349 genericCall_<%sub_name%><%call_index%>(data, threadData<%jac%>, equationIndexes, <%forNames%>); /*<%symbolName(modelNamePrefix,"genericCall")%>*/
8350 <%forTail%>
8351 >>
8352 case eqn as SES_GENERIC_ASSIGN() then
8353 let idx_len = listLength(scal_indices)
8354 <<
8355 const int idx_lst[<%idx_len%>] = {<%(scal_indices |> idx => '<%idx%>';separator=", ")%>};
8356 for(int i=0; i<<%idx_len%>; i++)
8357 genericCall_<%sub_name%><%call_index%>(data, threadData<%jac%>, equationIndexes, idx_lst[i]); /*<%symbolName(modelNamePrefix,"genericCall")%>*/
8358 >>
8359 %>
8360 <%endModelicaLine()%>
8361 >>
8362 end equationGenericAssign;
8363
8364 2 template equationEntwinedAssign(SimEqSystem eq, Context context,
8365 Text &varDecls, Text &varFrees, Text &auxFunction, String modelNamePrefix)
8366 "Generate a call for entwined generic for-loop structures with an index-lists and a call order."
8367
8368 ::=
8369 <<
8370 <%modelicaLine(eqInfo(eq))%>
8371 <%match eq
8372
8373 case eqn as SES_ENTWINED_ASSIGN() then
8374 let call_num = listLength(single_calls)
8375 let call_order_len = listLength(call_order)
8376 <<
8377 int call_indices[<%call_num%>] = {<%(single_calls |> call => '0'; separator=", ")%>};
8378 const int call_order[<%call_order_len%>] = {<%(call_order |> idx => '<%idx%>'; separator=", ")%>};
8379 <%(single_calls |> call hasindex i0 => entwinedSingleCallIndices(call, context, &varDecls, &varFrees, &auxFunction, modelNamePrefix); separator="\n")%>
8380 for(int i=0; i<<%call_order_len%>; i++)
8381 {
8382 switch(call_order[i])
8383 {
8384 <%(single_calls |> call hasindex i0 => entwinedSingleCall(call, i0, context, &varDecls, &varFrees, &auxFunction, modelNamePrefix); separator="\n")%>
8385 default:
8386 throwStreamPrint(NULL, "Call index %d at pos %d unknown for: <%modelicaLine(eqInfo(eq))%>", call_order[i], i);
8387 break;
8388 }
8389 }
8390 >>
8391 %>
8392 <%endModelicaLine()%>
8393 >>
8394 end equationEntwinedAssign;
8395
8396 6 template entwinedSingleCallIndices(SimEqSystem eq, Context context,
8397 Text &varDecls, Text &varFrees, Text &auxFunction, String modelNamePrefix)
8398 ::=
8399 <<
8400 <%match eq
8401 case eqn as SES_GENERIC_ASSIGN() then
8402 let idx_len = listLength(scal_indices)
8403 <<
8404 const int idx_lst_<%call_index%>[<%idx_len%>] = {<%(scal_indices |> idx => '<%idx%>';separator=", ")%>};
8405 >>
8406 else ""
8407 %>
8408 >>
8409 end entwinedSingleCallIndices;
8410
8411 6 template entwinedSingleCall(SimEqSystem eq, Integer i0, Context context,
8412 Text &varDecls, Text &varFrees, Text &auxFunction, String modelNamePrefix)
8413 ::=
8414 <<
8415 <%match eq
8416 case eqn as SES_GENERIC_ASSIGN() then
8417 let jac = match context case JACOBIAN_CONTEXT() then ", jacobian" else ""
8418 let sub_name = match context case JACOBIAN_CONTEXT(name = jac_name) then 'jac_<%jac_name%>_' else ""
8419 <<
8420 case <%i0%>:
8421 genericCall_<%sub_name%><%call_index%>(data, threadData<%jac%>, equationIndexes, idx_lst_<%call_index%>[call_indices[<%i0%>]]);
8422 call_indices[<%i0%>]++;
8423 break;
8424 >>
8425 case eqn as SES_SIMPLE_ASSIGN(__) then
8426 <<
8427 case <%i0%>:
8428 <%equationSimpleAssign(eqn, context, &varDecls, &varFrees, &auxFunction)%>
8429 break;
8430 >>
8431 case eqn as SES_ARRAY_CALL_ASSIGN(__) then
8432 <<
8433 case <%i0%>:
8434 <%equationArrayCallAssign(eqn, context, &varDecls, &varFrees, &auxFunction)%>
8435 break;
8436 >>
8437 case eqn as SES_ALGORITHM(__) then
8438 <<
8439 case <%i0%>:
8440 <%equationAlgorithm(eqn, context, &varDecls, &varFrees, &auxFunction)%>
8441 break;
8442 >>
8443 case eqn as SES_WHEN(__) then
8444 <<
8445 case <%i0%>:
8446 <%equationWhen(eqn, context, &varDecls, &varFrees, &auxFunction)%>
8447 break;
8448 >>
8449 else
8450 error(sourceInfo(), 'entwinedSingleCall: unhandled equation type')
8451 %>
8452 >>
8453 end entwinedSingleCall;
8454
8455 34291 template equationAlgorithm(SimEqSystem eq, Context context, Text &varDecls, Text &varFrees, Text &auxFunction)
8456 "Generates an equation that is an algorithm."
8457 ::=
8458 match eq
8459 /* SES_INVERSE_ALGORITHM which is used by the non-linear solver */
8460 case alg as SES_INVERSE_ALGORITHM(insideNonLinearSystem=true)
8461 case SES_ALGORITHM(__) then
8462 (statements |> stmt =>
8463 algStatement(stmt, context, &varDecls, &varFrees, &auxFunction)
8464 ;separator="\n")
8465 /* Generates an equation that is an inverse algorithm
8466 without continuous variables, discrete variables are
8467 handled by the event iteration */
8468 case alg as SES_INVERSE_ALGORITHM(__) then
8469 let &sub = buffer ""
8470 let backupKnown = (alg.knownOutputCrefs |> cr hasindex i0 =>
8471 let &varDecls += '<%crefType(cr)%> OLD_<%i0%>;<%\n%>'
8472 'OLD_<%i0%> = <%cref(cr, &sub)%>;'
8473 ;separator="\n")
8474 let stmts = (statements |> stmt =>
8475 algStatement(stmt, context, &varDecls, &varFrees, &auxFunction)
8476 ;separator="\n")
8477 let restoreKnownVars = (alg.knownOutputCrefs |> cr hasindex i0 => '<%cref(cr, &sub)%> = OLD_<%i0%>;' ;separator="\n")
8478 <<
8479 /* backup outputs of the algorithm */
8480 <%backupKnown%>
8481 /* algrithm it self */
8482 <%stmts%>
8483 /* restore outputs of the algorithm */
8484 <%restoreKnownVars%>
8485 >>
8486 end equationAlgorithm;
8487
8488 1056 template equationLinear(SimEqSystem eq, Context context, Text &varDecls, Text &varFrees)
8489 "Generates a linear equation system."
8490 ::=
8491 match eq
8492 case e as SES_LINEAR(lSystem=ls as LINEARSYSTEM(__), alternativeTearing = at) then
8493 let returnval = match at case at as SOME(__) then 'return 1;' case at as NONE() then ''
8494 let returnval2 = match at case at as SOME(__) then 'return 0;' case at as NONE() then ''
8495 let auxFunctions = ""
8496 <<
8497 /* Linear equation system */
8498 int retValue;
8499 double aux_x[<%listLength(ls.vars)%>] = { <%ls.vars |> SIMVAR(__) hasindex i0 => '<%contextCrefOld(name, context, auxFunctions, 1)%>' ;separator=","%> };
8500 infoStreamPrint(OMC_LOG_DT, 0, "Solving linear system <%ls.index%> (STRICT TEARING SET if tearing enabled) at time = %18.10e", data->localData[0]->timeValue);
8501 <% if profileSome() then 'SIM_PROF_TICK_EQ(modelInfoGetEquation(&data->modelData->modelDataXml,<%ls.index%>).profileBlockIndex);' %>
8502 <% if ls.partOfJac then
8503 'data->simulationInfo->linearSystemData[<%ls.indexLinearSystem%>].parentJacobian = jacobian;'
8504 %>
8505
8506 retValue = <%if intEq(listLength(ls.vars), 1) then "solve_linear_system_small" else "solve_linear_system"%>(data, threadData, <%ls.indexLinearSystem%>, &aux_x[0]);
8507
8508 /* check if solution process was successful */
8509 if (retValue > 0){
8510 const int indexes[2] = {1,<%ls.index%>};
8511 raiseStreamPrintWithEquationIndexes(threadData, omc_dummyFileInfo, indexes, "Solving linear system <%ls.index%> failed at time=%.15g.\nFor more information please use -lv LOG_LS.", data->localData[0]->timeValue);
8512 OMC_ERROR_CHECK();
8513 <%returnval2%>
8514 }
8515 /* write solution */
8516 <%ls.vars |> SIMVAR(__) hasindex i0 => '<%contextCrefNoPrevExp(name, context, auxFunctions)%> = aux_x[<%i0%>];' ;separator="\n"%>
8517 <% if profileSome() then 'SIM_PROF_ACC_EQ(modelInfoGetEquation(&data->modelData->modelDataXml,<%ls.index%>).profileBlockIndex);' %>
8518
8519 <%returnval%>
8520 >>
8521 end equationLinear;
8522
8523
8524 ✗ template equationLinearAlternativeTearing(SimEqSystem eq, Context context, Text &varDecls, Text &varFrees)
8525 "Generates a linear equation system for the alternative tearing set."
8526 ::=
8527 match eq
8528 case e as SES_LINEAR(lSystem=ls as LINEARSYSTEM(__), alternativeTearing = SOME(at as LINEARSYSTEM(__))) then
8529 let auxFunctions = ""
8530 <<
8531 /* Linear equation system */
8532 int retValue;
8533
8534 infoStreamPrint(OMC_LOG_DT, 0, "Solving linear system <%at.index%> (CASUAL TEARING SET, strict: <%ls.index%>) at time = %18.10e", data->localData[0]->timeValue);
8535 <% if profileSome() then 'SIM_PROF_TICK_EQ(modelInfoGetEquation(&data->modelData->modelDataXml,<%at.index%>).profileBlockIndex);' %>
8536 if (data->simulationInfo->linearSystemData[<%at.indexLinearSystem%>].checkConstraints(data, threadData) == 1)
8537 {
8538 double aux_x[<%listLength(at.vars)%>] = { <%at.vars |> SIMVAR(__) hasindex i0 => '<%contextCrefNoPrevExp(name, context, auxFunctions)%>' ;separator=","%> };
8539 retValue = solve_linear_system(data, threadData, <%at.indexLinearSystem%>, &aux_x[0]);
8540 /* The casual tearing set found a solution */
8541 if (retValue == 0){
8542 /* write solution */
8543 <%at.vars |> SIMVAR(__) hasindex i0 => '<%contextCrefNoPrevExp(name, context, auxFunctions)%> = aux_x[<%i0%>];' ;separator="\n"%>
8544 <% if profileSome() then 'SIM_PROF_ACC_EQ(modelInfoGetEquation(&data->modelData->modelDataXml,<%at.index%>).profileBlockIndex);' %>
8545 }
8546 }
8547 else
8548 {
8549 infoStreamPrint(OMC_LOG_DT, 0, "Constraints of the casual tearing set are violated! Now the strict tearing set is used.");
8550 /* Global constraints are violated. Use the strict tearing set now. */
8551 data->simulationInfo->linearSystemData[<%at.indexLinearSystem%>].strictTearingFunctionCall(data, threadData);
8552 }
8553 >>
8554 end equationLinearAlternativeTearing;
8555
8556
8557 ✗ template equationMixed(SimEqSystem eq, Context context, Text &tmp, String modelNamePrefixStr, Boolean init)
8558 "Generates a mixed equation system."
8559 ::=
8560 match eq
8561 case eqn as SES_MIXED(__) then
8562 let &sub = buffer ""
8563 let &tmp += equation_impl(-1, -1, cont, context, modelNamePrefixStr, init)
8564 <<
8565 /* Continuous equation part */
8566 <% if profileSome() then 'SIM_PROF_TICK_EQ(modelInfoGetEquation(&data->modelData->modelDataXml,<%index%>).profileBlockIndex);' %>
8567 <%discVars |> SIMVAR(__) hasindex i0 => 'data->simulationInfo->mixedSystemData[<%eqn.indexMixedSystem%>].iterationVarsPtr[<%i0%>] = (modelica_boolean*)&<%cref(name, &sub)%>;' ;separator="\n"%>;
8568 <%discVars |> SIMVAR(__) hasindex i0 => 'data->simulationInfo->mixedSystemData[<%eqn.indexMixedSystem%>].iterationPreVarsPtr[<%i0%>] = (modelica_boolean*)&<%crefPre(name)%>;' ;separator="\n"%>;
8569 solve_mixed_system(data, <%indexMixedSystem%>);
8570 <% if profileSome() then 'SIM_PROF_ACC_EQ(modelInfoGetEquation(&data->modelData->modelDataXml,<%index%>).profileBlockIndex);' %>
8571 >>
8572 end equationMixed;
8573
8574
8575 1100 template equationNonlinear(SimEqSystem eq, Context context, String modelNamePrefix, Boolean init)
8576 "Generates a non linear equation system."
8577 ::=
8578 match eq
8579 case eq as SES_NONLINEAR(nlSystem=nls as NONLINEARSYSTEM(__), alternativeTearing = at) then
8580 <<
8581 int retValue;
8582 infoStreamPrint(OMC_LOG_DT, 0, "Solving nonlinear system <%nls.index%> (STRICT TEARING SET if tearing enabled) at time = %18.10e", data->localData[0]->timeValue);
8583 <% if profileSome() then
8584 <<
8585 SIM_PROF_TICK_EQ(modelInfoGetEquation(&data->modelData->modelDataXml,<%nls.index%>).profileBlockIndex);
8586 SIM_PROF_ADD_NCALL_EQ(modelInfoGetEquation(&data->modelData->modelDataXml,<%nls.index%>).profileBlockIndex,-1);
8587 >>
8588 %>
8589 /* get old value */
8590 <%if nlsResizable(nls.crefs) then nlsGetIterVars(nls.crefs, 'data->simulationInfo->nonlinearSystemData[<%nls.indexNonLinearSystem%>].nlsxOld') else
8591 (nls.crefs |> name hasindex i0 =>
8592 let &auxFunction = buffer ""
8593 let START = contextCrefNoPrevExp(name, context, &auxFunction)
8594 'data->simulationInfo->nonlinearSystemData[<%nls.indexNonLinearSystem%>].nlsxOld[<%i0%>] = <%START%>;'
8595 ;separator="\n")%>
8596 retValue = solve_nonlinear_system(data, threadData, <%nls.indexNonLinearSystem%>);
8597 /* check if solution process was successful */
8598 if (retValue > 0){
8599 const int indexes[2] = {1,<%nls.index%>};
8600 raiseStreamPrintWithEquationIndexes(threadData, omc_dummyFileInfo, indexes, "Solving non-linear system <%nls.index%> failed at time=%.15g.\nFor more information please use -lv LOG_NLS.", data->localData[0]->timeValue);
8601 OMC_ERROR_CHECK();
8602 <%match at case SOME(__) then 'return 0;'%>
8603 }
8604 /* write solution */
8605 <%if nlsResizable(nls.crefs) then nlsSetIterVars(nls.crefs, 'data->simulationInfo->nonlinearSystemData[<%nls.indexNonLinearSystem%>].nlsx') else
8606 (nls.crefs |> name hasindex i0 =>
8607 let &auxFunction = buffer ""
8608 '<%contextCrefNoPrevExp(name, context, &auxFunction)%> = data->simulationInfo->nonlinearSystemData[<%nls.indexNonLinearSystem%>].nlsx[<%i0%>];' ;separator="\n")%>
8609 <% if profileSome() then 'SIM_PROF_ACC_EQ(modelInfoGetEquation(&data->modelData->modelDataXml,<%nls.index%>).profileBlockIndex);' %>
8610 <%match at case SOME(__) then 'return 1;'%>
8611 >>
8612 end equationNonlinear;
8613
8614 3 template equationNonlinearAlternativeTearing(SimEqSystem eq, Context context, String modelNamePrefix, Boolean init)
8615 "Generates a non linear equation system for the alternative tearing set."
8616 ::=
8617 match eq
8618 case eq as SES_NONLINEAR(nlSystem = nls as NONLINEARSYSTEM(__), alternativeTearing = SOME(at as NONLINEARSYSTEM(__))) then
8619 <<
8620 int retValue;
8621 infoStreamPrint(OMC_LOG_DT, 0, "Solving nonlinear system <%at.index%> (CASUAL TEARING SET, strict: <%nls.index%>) at time = %18.10e", data->localData[0]->timeValue);
8622 <% if profileSome() then
8623 <<
8624 SIM_PROF_TICK_EQ(modelInfoGetEquation(&data->modelData->modelDataXml,<%at.index%>).profileBlockIndex);
8625 SIM_PROF_ADD_NCALL_EQ(modelInfoGetEquation(&data->modelData->modelDataXml,<%at.index%>).profileBlockIndex,-1);
8626 >>
8627 %>
8628
8629 if (data->simulationInfo->nonlinearSystemData[<%at.indexNonLinearSystem%>].checkConstraints(data, threadData) == 1)
8630 {
8631 /* get old value */
8632 <%at.crefs |> name hasindex i0 =>
8633 let &sub = buffer ""
8634 let START = cref(name, &sub)
8635 'data->simulationInfo->nonlinearSystemData[<%at.indexNonLinearSystem%>].nlsxOld[<%i0%>] = <%START%>;'
8636 ;separator="\n"%>
8637 retValue = solve_nonlinear_system(data, threadData, <%at.indexNonLinearSystem%>);
8638 /* The casual tearing set found a solution */
8639 if (retValue == 0){
8640 /* write solution */
8641 <%at.crefs |> name hasindex i0 =>
8642 let &sub = buffer ""
8643 '<%cref(name, &sub)%> = data->simulationInfo->nonlinearSystemData[<%at.indexNonLinearSystem%>].nlsx[<%i0%>];' ;separator="\n"%>
8644 <% if profileSome() then 'SIM_PROF_ACC_EQ(modelInfoGetEquation(&data->modelData->modelDataXml,<%at.index%>).profileBlockIndex);' %>
8645 }
8646 }
8647 else
8648 {
8649 infoStreamPrint(OMC_LOG_DT, 0, "Constraints of the casual tearing set are violated! Now the strict tearing set is used.");
8650 /* Global constraints are violated. Use the strict tearing set now. */
8651 data->simulationInfo->nonlinearSystemData[<%at.indexNonLinearSystem%>].strictTearingFunctionCall(data, threadData);
8652 }
8653 >>
8654 end equationNonlinearAlternativeTearing;
8655
8656 484 template equationWhen(SimEqSystem eq, Context context, Text &varDecls, Text &varFrees, Text &auxFunction)
8657 "Generates a when equation."
8658 ::=
8659 match eq
8660 case SES_WHEN(whenStmtLst = whenStmtLst, conditions=conditions, elseWhen=NONE()) then
8661 let &sub = buffer ""
8662 let helpIf = if not listEmpty(conditions) then (conditions |> e => '(<%cref(e, &sub)%> && !<%crefPre(e)%> /* edge */)';separator=" || ") else '0'
8663 let assign = whenOperators(whenStmtLst, context, &varDecls, &varFrees, auxFunction)
8664 <<
8665 if(<%helpIf%>)
8666 {
8667 <%modelicaLine(eqInfo(eq))%>
8668 <%assign%>
8669 <%endModelicaLine()%>
8670 }
8671 >>
8672 case SES_WHEN(whenStmtLst = whenStmtLst, conditions=conditions, elseWhen=SOME(elseWhenEq)) then
8673 let &sub = buffer ""
8674 let helpIf = if not listEmpty(conditions) then (conditions |> e => '(<%cref(e, &sub)%> && !<%crefPre(e)%> /* edge */)';separator=" || ") else '0'
8675 let assign = whenOperators(whenStmtLst, context, &varDecls, &varFrees, auxFunction)
8676 let elseWhen = equationElseWhen(elseWhenEq,context,varDecls, varFrees,&auxFunction)
8677 <<
8678 if(<%helpIf%>)
8679 {
8680 <%modelicaLine(eqInfo(eq))%>
8681 <%assign%>
8682 <%endModelicaLine()%>
8683 }
8684 <%elseWhen%>
8685 >>
8686 end equationWhen;
8687
8688 49 template equationElseWhen(SimEqSystem eq, Context context, Text &varDecls, Text &varFrees, Text &auxFunction)
8689 "Generates a else when equation."
8690 ::=
8691 let &sub = buffer ""
8692 match eq
8693 case SES_WHEN(whenStmtLst = whenStmtLst, conditions=conditions, elseWhen=NONE()) then
8694 let helpIf = (conditions |> e => '(<%cref(e, &sub)%> && !<%crefPre(e)%> /* edge */)';separator=" || ")
8695 let assign = whenOperators(whenStmtLst, context, &varDecls, &varFrees, auxFunction)
8696
8697 if not listEmpty(conditions) then
8698 <<
8699 else if(<%helpIf%>)
8700 {
8701 <%modelicaLine(eqInfo(eq))%>
8702 <%assign%>
8703 <%endModelicaLine()%>
8704 }
8705 >>
8706 case SES_WHEN(whenStmtLst = whenStmtLst, conditions=conditions, elseWhen=SOME(elseWhenEq)) then
8707 let helpIf = (conditions |> e => '(<%cref(e, &sub)%> && !<%crefPre(e)%> /* edge */)';separator=" || ")
8708 let assign = whenOperators(whenStmtLst, context, &varDecls, &varFrees, auxFunction)
8709 let elseWhen = equationElseWhen(elseWhenEq, context, varDecls, varFrees, auxFunction)
8710 let body = if not listEmpty(conditions) then
8711 <<
8712 else if(<%helpIf%>)
8713 {
8714 <%modelicaLine(eqInfo(eq))%>
8715 <%assign%>
8716 <%endModelicaLine()%>
8717 }
8718 >>
8719
8720 <<
8721 <%body%>
8722 <%elseWhen%>
8723 >>
8724 end equationElseWhen;
8725
8726 564 template whenOperators(list<WhenOperator> whenOps, Context context, Text &varDecls, Text &varFrees, Text &auxFunction)
8727 "Generates body statements for when equation."
8728 ::=
8729 let body = (whenOps |> whenOp =>
8730 match whenOp
8731 case ASSIGN(left = lhs as DAE.CREF(componentRef=left)) then whenAssign(lhs, typeof(right), right, context, &varDecls, &varFrees, &auxFunction)
8732 case ASSIGN(left = lhs as DAE.TUPLE(PR = expLst as firstexp::_), right = DAE.CALL(attr=CALL_ATTR(ty=T_TUPLE(types=ntys)))) then
8733 let &preExp = buffer ""
8734 let &postExp = buffer ""
8735 let lhsCrefs = (listRest(expLst) |> e => " ," + tupleReturnVariableUpdates(e, context, varDecls, varFrees, preExp, postExp, &auxFunction))
8736 // The tuple expressions might take fewer variables than the number of outputs. No worries.
8737 let lhsCrefs2 = lhsCrefs + List.fill(", NULL", intMax(0,intSub(listLength(ntys),listLength(expLst))))
8738 let call = daeExpCallTuple(right, lhsCrefs2, context, &preExp, &varDecls, &varFrees, &auxFunction)
8739 let callassign = algStmtAssignWithRhsExpStr(firstexp, call, context, &preExp, &postExp, &varDecls, &varFrees, &auxFunction)
8740 <<
8741 <%preExp%>
8742 <%callassign%>
8743 <%postExp%>
8744 >>
8745 case REINIT(__) then
8746 let &sub = buffer ""
8747 let &preExp = buffer ""
8748 let val = daeExp(value, contextSimulationDiscrete, &preExp, &varDecls, &varFrees, &auxFunction)
8749 let lhs = match crefTypeConsiderSubs(stateVar)
8750 case DAE.T_ARRAY(__) then
8751 'copy_real_array_data_mem(<%val%>, &<%cref(stateVar, &sub)%>);'
8752 else
8753 '<%cref(stateVar, &sub)%> = <%val%>;'
8754 <<
8755 <%preExp%>
8756 <%lhs%>
8757 infoStreamPrint(OMC_LOG_EVENTS, 0, "reinit <%crefStrNoUnderscore(stateVar)%> = <%crefToPrintfArg(stateVar)%>", <%cref(stateVar, &sub)%>);
8758 data->simulationInfo->needToIterate = 1;
8759 >>
8760 case TERMINATE(__) then
8761 let &preExp = buffer ""
8762 let msgVar = daeExp(message, contextSimulationDiscrete, &preExp, &varDecls, &varFrees, &auxFunction)
8763 <<
8764 <%preExp%>
8765 FILE_INFO info = {<%infoArgs(ElementSource.getElementSourceFileInfo(source))%>};
8766 omc_terminate(info, omc_string_data(<%msgVar%>));
8767 >>
8768 case ASSERT(source=SOURCE(info=info)) then
8769 assertCommon(condition, List.fill(message,1), level, contextSimulationDiscrete, &varDecls, &varFrees, &auxFunction, info)
8770 case NORETCALL(__) then
8771 let &preExp = buffer ""
8772 let expPart = daeExp(exp, contextSimulationDiscrete, &preExp, &varDecls, &varFrees, &auxFunction)
8773 <<
8774 <%preExp%>
8775 <% if isCIdentifier(expPart) then "" else '<%expPart%>;' %>
8776 >>
8777 ;separator="\n")
8778 <<
8779 <%body%>
8780 >>
8781 end whenOperators;
8782
8783 482 template whenAssign(Exp left, Type ty, Exp right, Context context, Text &varDecls, Text &varFrees, Text &auxFunction)
8784 "Generates assignment for when."
8785 ::=
8786 match ty
8787 case T_ARRAY(__) then
8788 let &preExp = buffer ""
8789 let expPart = daeExp(right, context, &preExp, &varDecls, &varFrees, &auxFunction)
8790 let assign = algStmtAssignArrWithRhsExpStr(left, expPart, context, &preExp, &varDecls, &varFrees, &auxFunction)
8791 <<
8792 <%preExp%>
8793 <%assign%>
8794 >>
8795 case T_COMPLEX(varLst = varLst, complexClassType=RECORD(__)) then
8796 error(sourceInfo(), 'No runtime support for this record assignment: <%dumpExp(left,"\"")%> = <%dumpExp(right,"\"")%>')
8797 // let &preExp = buffer ""
8798 // let exp = daeExp(right, context, &preExp, &varDecls, &auxFunction)
8799 // let tmp = tempDecl(expTypeModelica(ty),&varDecls)
8800 // <<
8801 // <%preExp%>
8802 // <%tmp%> = <%exp%>;
8803 // <% varLst |> var as TYPES_VAR(__) =>
8804 // match var.ty
8805 // case T_ARRAY(__) then
8806 // copyArrayData(var.ty, '<%tmp%>._<%var.name%>', appendStringCref(var.name,left), context, &preExp, &varDecls, &auxFunction)
8807 // else
8808 // let varPart = contextCref(appendStringCref(var.name,left), context, &preExp, &varDecls, &auxFunction)
8809 // '<%varPart%> = <%tmp%>._<%var.name%>;'
8810 // ; separator="\n"
8811 // %>
8812 // >>
8813 else
8814 let &preExp = buffer ""
8815 let varPart = daeExp(left, context, &preExp, &varDecls, &varFrees, &auxFunction)
8816 let exp = daeExp(right, context, &preExp, &varDecls, &varFrees, &auxFunction)
8817 <<
8818 <%preExp%>
8819 <%varPart%> = <%exp%>;
8820 >>
8821 end whenAssign;
8822
8823 8 template equationIfEquationAssign(SimEqSystem eq, Context context, Text &varDecls, Text &varFrees, Text &eqnsDecls, String modelNamePrefixStr, Boolean init)
8824 "Generates a if equation."
8825 ::=
8826 match eq
8827 case SES_IFEQUATION(ifbranches=ifbranches, elsebranch=elsebranch) then
8828 let &preExp = buffer ""
8829 let IfEquation = (ifbranches |> (e, eqns) hasindex index0 =>
8830 let condition = daeExp(e, context, &preExp, &varDecls, &varFrees, &eqnsDecls)
8831 let &eqnsDecls += ( eqns |> eqn => equation_impl(-1, -1, eqn, context, modelNamePrefixStr, init) ; separator="\n" )
8832 let conditionline = if index0 then 'else if(<%condition%>)' else 'if(<%condition%>)'
8833 <<
8834 <%conditionline%>
8835 {
8836 <%equations_call(eqns, modelNamePrefixStr, context, '', true, &eqnsDecls)%>
8837 }
8838 >>
8839 ;separator="\n")
8840 let &eqnsDecls += ( elsebranch |> eqn => equation_impl(-1, -1, eqn, context, modelNamePrefixStr, init) ; separator="\n" )
8841 <<
8842 <%preExp%>
8843 <%IfEquation%>else
8844 {
8845 <%equations_call(elsebranch, modelNamePrefixStr, context, '', true, &eqnsDecls)%>
8846 }
8847 >>
8848 end equationIfEquationAssign;
8849
8850 /* public */ template simulationLiteralsFile(String filePrefix, list<Exp> literals)
8851 "Generates the content of the C file for literals in the simulation case.
8852 used in Compiler/Template/CodegenFMU.tpl"
8853 ::=
8854 <<
8855 #ifdef __cplusplus
8856 extern "C" {
8857 #endif
8858
8859 <%literals |> literal hasindex i0 fromindex 0 =>
8860 (if typeinfo() then '/* <%Util.escapeModelicaStringToCString(dumpExp(literal,"\""))%> */<%\n%>') +
8861 literalExpConst(literal,i0)
8862 ; separator="\n"; empty %>
8863
8864 #ifdef __cplusplus
8865 }
8866 #endif<%\n%>
8867 >>
8868 /* adpro: leave a newline at the end of file to get rid of warnings! */
8869 end simulationLiteralsFile;
8870
8871 /* public */ template simulationFunctionsFile(String filePrefix, list<SimCodeFunction.Function> functions, list<SimGenericCall> genericCalls)
8872 "Generates the content of the C file for functions in the simulation case.
8873 used in Compiler/Template/CodegenFMU.tpl"
8874 ::=
8875 let()= textFile( "[\n" + (functions |> fn => match fn case fn as EXTERNAL_FUNCTION(__) then '"<%fn.extName%>"'; separator=",\n") + "\n]", '<%filePrefix%>_external_functions.json')
8876 <<
8877 #include "omc_simulation_settings.h"
8878 #include "<%filePrefix%>_functions.h"
8879 #ifdef __cplusplus
8880 extern "C" {
8881 #endif
8882
8883 #include "<%filePrefix%>_includes.h"
8884
8885 <%if acceptParModelicaGrammar() then
8886 <<
8887 /* the OpenCL Kernels file name needed in libParModelicaExpl.a */
8888 const char* omc_ocl_kernels_source = "<%filePrefix%>_kernels.cl";
8889 /* the OpenCL program. Made global to avoid repeated builds */
8890 extern cl_program omc_ocl_program;
8891 /* The default OpenCL device. If not set (=0) show the selection option.*/
8892 unsigned int default_ocl_device = <%getDefaultOpenCLDevice()%>;
8893 >>
8894 %>
8895
8896 <%functionBodies(functions,true)%>
8897 <%genericCallBodies(genericCalls, contextSimulationNonDiscrete)%>
8898
8899 #ifdef __cplusplus
8900 }
8901 #endif<%\n%>
8902 >>
8903 /* adpro: leave a newline at the end of file to get rid of warnings! */
8904 end simulationFunctionsFile;
8905
8906 ✗ template simulationParModelicaKernelsFile(String filePrefix, list<SimCodeFunction.Function> functions)
8907 "Generates the content of the C file for functions in the simulation case."
8908 ::=
8909
8910 /* Reset the parfor loop id counter to 1*/
8911 let()= System.tmpTickResetIndex(0,20) /* parfor index */
8912
8913 <<
8914 #include <ParModelica/explicit/openclrt/OCLRuntimeUtil.cl>
8915
8916 // ParModelica Parallel Function headers.
8917 <%functionHeadersParModelica(filePrefix, functions)%>
8918
8919 // Headers finish here.
8920
8921 <%functionBodiesParModelica(functions)%>
8922
8923
8924 >>
8925
8926 end simulationParModelicaKernelsFile;
8927
8928 /* public */ template simulationFunctionsHeaderFile(String filePrefix, list<SimCodeFunction.Function> functions, list<RecordDeclaration> recordDecls, list<SimGenericCall> genericCalls)
8929 "Generates the content of the C file for functions in the simulation case.
8930 used in Compiler/Template/CodegenFMU.tpl"
8931 ::=
8932 let &staticPrototypes = buffer ""
8933 <<
8934 #ifndef <%makeC89Identifier(filePrefix)%>__H
8935 #define <%makeC89Identifier(filePrefix)%>__H
8936 <%commonHeader(filePrefix)%>
8937 #include "simulation/simulation_runtime.h"
8938 #ifdef __cplusplus
8939 extern "C" {
8940 #endif
8941 <%\n%>
8942 <%recordDecls |> rd => recordDeclarationHeader(rd) ;separator="\n\n"%>
8943 <%\n%>
8944 <%functionHeaders(functions, true, staticPrototypes)%>
8945 <%genericCallHeaders(genericCalls, contextOther)%>
8946 #include "<%filePrefix%>_model.h"
8947 <%\n%>
8948 <%if staticPrototypes then
8949 <<
8950 /* default, do not make protected functions static */
8951 #if !defined(PROTECTED_FUNCTION_STATIC)
8952 #define PROTECTED_FUNCTION_STATIC
8953 #endif
8954 <%staticPrototypes%>
8955 >>
8956 %>
8957 <%\n%>
8958 #ifdef __cplusplus
8959 }
8960 #endif
8961 #endif<%\n%>
8962 >>
8963 /* adrpo: leave a newline at the end of file to get rid of the warning */
8964 end simulationFunctionsHeaderFile;
8965
8966 1122 template simulationMakefile(String target, SimCode simCode, list<String> extraFiles)
8967 "Generates the contents of the makefile for the simulation case."
8968 ::=
8969 match getGeneralTarget(target)
8970 case "msvc" then
8971 match simCode
8972 case SIMCODE(modelInfo=MODELINFO(varInfo=varInfo as VARINFO(__)), delayedExps=DELAYED_EXPRESSIONS(maxDelayedIndex=maxDelayedIndex), makefileParams=MAKEFILE_PARAMS(__), simulationSettingsOpt = sopt) then
8973 let dirExtra = if modelInfo.directory then '/LIBPATH:"<%modelInfo.directory%>"' //else ""
8974 let libsStr = (makefileParams.libs |> lib => lib ;separator=" ")
8975 let extraCflags = match sopt case SOME(s as SIMULATION_SETTINGS(__)) then
8976 match s.method case "dassljac" then "/D_OMC_JACOBIAN "
8977 <<
8978 # Makefile generated by OpenModelica
8979 # Platform: <%makefileParams.platform%>
8980 #
8981 # For nmake. share/omc/scripts/Compile.bat sets the toolchain up and can
8982 # override CC/CXX (OMC_TOOLCHAIN=clang-cl).
8983
8984 CC=cl
8985 CXX=cl
8986 EXEEXT=.exe
8987 DLLEXT=.dll
8988 OMHOME=<%makefileParams.omhome%>
8989 OMLIB=$(OMHOME)/lib/<%Config.targetTriple()%>/omc
8990
8991 # /MD the OpenModelica libraries link the DLL C runtime; /std:c17 the runtime
8992 # headers use C99/C11; /wd4068 the sources carry #pragma GCC; IMPORT_INTO the
8993 # runtime's global data arrives as dllimport.
8994 OMC_CFLAGS_OPTIMIZATION=/O2
8995 CFLAGS=/nologo /MD /std:c17 $(OMC_CFLAGS_OPTIMIZATION) /fp:except /wd4068 /DOM_HAVE_PTHREADS /DIMPORT_INTO <%extraCflags%><%match sopt case SOME(s as SIMULATION_SETTINGS(__)) then '<%s.cflags%> ' /* From the simulate() command */%>
8996 CPPFLAGS=<%makefileParams.includes ; separator=" "%> /I"$(OMHOME)/include/omc/c" /I"$(OMHOME)/include/omc" /I. /DOPENMODELICA_XML_FROM_FILE_AT_RUNTIME<% if Flags.isSet(Flags.OMC_RELOCATABLE_FUNCTIONS) then " /DOMC_GENERATE_RELOCATABLE_CODE"%> /DOMC_MODEL_PREFIX=<%modelNamePrefix(simCode)%> /DOMC_NUM_MIXED_SYSTEMS=<%varInfo.numMixedSystems%> /DOMC_NUM_LINEAR_SYSTEMS=<%varInfo.numLinearSystems%> /DOMC_NUM_NONLINEAR_SYSTEMS=<%varInfo.numNonLinearSystems%> /DOMC_NDELAY_EXPRESSIONS=<%maxDelayedIndex%> /DOMC_NVAR_STRING=<%varInfo.numStringAlgVars%><% if Config.simCodeRustRuntime() then " /DOMC_RUST_SIMULATION_RUNTIME"%>
8997 RUNTIME_LIBS=<%makefileParams.runtimelibs%>
8998 LDFLAGS=/link /STACK:16777216 /LIBPATH:"$(OMLIB)" <%dirExtra%> <%libsStr%> $(RUNTIME_LIBS)
8999
9000 FILEPREFIX=<%fileNamePrefix%>
9001 MAINFILE=$(FILEPREFIX).c
9002 CFILES=<%fileNamePrefix%>_functions.c <%fileNamePrefix%>_records.c \
9003 <%fileNamePrefix%>_01exo.c <%fileNamePrefix%>_02nls.c <%fileNamePrefix%>_03lsy.c <%fileNamePrefix%>_04set.c <%fileNamePrefix%>_05evt.c <%fileNamePrefix%>_06inz.c <%fileNamePrefix%>_07dly.c \
9004 <%fileNamePrefix%>_08bnd.c <%fileNamePrefix%>_09alg.c <%fileNamePrefix%>_10asr.c <%fileNamePrefix%>_11mix.c <%fileNamePrefix%>_12jac.c <%fileNamePrefix%>_13opt.c <%fileNamePrefix%>_14lnz.c \
9005 <%fileNamePrefix%>_15syn.c <%fileNamePrefix%>_16dae.c <%fileNamePrefix%>_17inl.c <%fileNamePrefix%>_18spd.c <%extraFiles |> extraFile => extraFile ;separator=" "%>
9006 GENERATEDFILES=$(MAINFILE) $(FILEPREFIX).makefile $(FILEPREFIX)_literals.h $(FILEPREFIX)_functions.h $(CFILES)
9007
9008 omc_main_target:
9009 <%\t%>$(CC) /MP $(CFLAGS) $(CPPFLAGS) /Fe$(FILEPREFIX)$(EXEEXT) $(MAINFILE) $(CFILES) $(LDFLAGS)
9010
9011 omc_dll_target:
9012 <%\t%>$(CC) /MP /LD /DOMC_DLL_MAIN_DEFINE $(CFLAGS) $(CPPFLAGS) /Fe$(FILEPREFIX)$(DLLEXT) $(MAINFILE) $(CFILES) $(LDFLAGS)
9013
9014 clean:
9015 <%\t%>@del /q *.obj $(FILEPREFIX).pdb $(FILEPREFIX).ilk 2>NUL
9016
9017 bundle:
9018 <%\t%>@tar -cvf $(FILEPREFIX)_Files.tar $(GENERATEDFILES)
9019 >>
9020 end match
9021 case "gcc" then
9022 match simCode
9023 case SIMCODE(modelInfo=MODELINFO(varInfo=varInfo as VARINFO(__)), delayedExps=DELAYED_EXPRESSIONS(maxDelayedIndex=maxDelayedIndex), makefileParams=MAKEFILE_PARAMS(__), simulationSettingsOpt = sopt) then
9024 let dirExtra = if modelInfo.directory then '-L"<%modelInfo.directory%>"' //else ""
9025 let libsStr = (makefileParams.libs |> lib => lib ;separator=" ")
9026 let libsPos1 = if not dirExtra then libsStr //else ""
9027 let libsPos2 = if dirExtra then libsStr // else ""
9028 let ParModelicaExpLibs = if acceptParModelicaGrammar() then '-lParModelicaExpl -lOpenCL' // else ""
9029 let ExtraStack = if boolOr(stringEq(makefileParams.platform, "win32"),stringEq(makefileParams.platform, "win64")) then '--stack,16777216,'
9030 let ExtraUnicodeFlag = if boolOr(stringEq(makefileParams.platform, "win32"),stringEq(makefileParams.platform, "win64")) then '-municode'
9031 let linkBinDirWindows = if boolOr(stringEq(makefileParams.platform, "win32"),stringEq(makefileParams.platform, "win64")) then '-L"<%makefileParams.omhome%>/bin"'
9032 let extraCflags = match sopt case SOME(s as SIMULATION_SETTINGS(__)) then
9033 match s.method case "dassljac" then "-D_OMC_JACOBIAN "
9034
9035 <<
9036 # Makefile generated by OpenModelica
9037 # Platform: <%makefileParams.platform%>
9038
9039 CC=<%if acceptParModelicaGrammar() then 'g++' else '<%makefileParams.ccompiler%>'%>
9040 CXX=<%makefileParams.cxxcompiler%>
9041 LINK=<%makefileParams.linker%>
9042 EXEEXT=<%makefileParams.exeext%>
9043 DLLEXT=<%makefileParams.dllext%>
9044 CFLAGS_BASED_ON_INIT_FILE=<%extraCflags%>
9045 # define OMC_CFLAGS_OPTIMIZATION env variable to your desired optimization level to override this
9046 OMC_CFLAGS_OPTIMIZATION=-O2
9047 DEBUG_FLAGS=<% if boolOr(Testsuite.isRunning(), Flags.isSet(Flags.GEN_DEBUG_SYMBOLS)) then "-O0" else "$(OMC_CFLAGS_OPTIMIZATION)"%><% if Flags.isSet(Flags.GEN_DEBUG_SYMBOLS) then " -g" %>
9048 CFLAGS=<%ExtraUnicodeFlag%> $(CFLAGS_BASED_ON_INIT_FILE) $(DEBUG_FLAGS) <%makefileParams.cflags%> <%match sopt case SOME(s as SIMULATION_SETTINGS(__)) then '<%s.cflags%> ' /* From the simulate() command */%>
9049 <% if stringEq(Config.simCodeTarget(),"JavaScript") then 'OMC_EMCC_PRE_JS=<%makefileParams.omhome%>/lib/<%Config.targetTriple()%>/omc/emcc/pre.js<%\n%>'
9050 %>CPPFLAGS=<%makefileParams.includes ; separator=" "%> -I"<%makefileParams.omhome%>/include/omc/c" -I"<%makefileParams.omhome%>/include/omc" -I. -DOPENMODELICA_XML_FROM_FILE_AT_RUNTIME<% if stringEq(Config.simCodeTarget(),"JavaScript") then " -DOMC_EMCC"%><% if Flags.isSet(Flags.OMC_RELOCATABLE_FUNCTIONS) then " -DOMC_GENERATE_RELOCATABLE_CODE"%> -DOMC_MODEL_PREFIX=<%modelNamePrefix(simCode)%> -DOMC_NUM_MIXED_SYSTEMS=<%varInfo.numMixedSystems%> -DOMC_NUM_LINEAR_SYSTEMS=<%varInfo.numLinearSystems%> -DOMC_NUM_NONLINEAR_SYSTEMS=<%varInfo.numNonLinearSystems%> -DOMC_NDELAY_EXPRESSIONS=<%maxDelayedIndex%> -DOMC_NVAR_STRING=<%varInfo.numStringAlgVars%><% if Config.simCodeRustRuntime() then " -DOMC_RUST_SIMULATION_RUNTIME"%>
9051 # define OMC_LDFLAGS_LINK_TYPE env variable to "static" to override this
9052 OMC_LDFLAGS_LINK_TYPE=dynamic
9053 RUNTIME_LIBS=<%makefileParams.runtimelibs%>
9054 LDFLAGS=<%
9055 if stringEq(Config.simCodeTarget(),"JavaScript") then <<-L'<%makefileParams.omhome%>/lib/<%Config.targetTriple()%>/omc/emcc' -lblas -llapack -lexpat -lSimulationRuntimeC -s TOTAL_MEMORY=805306368 -s OUTLINING_LIMIT=20000 --pre-js $(OMC_EMCC_PRE_JS)>>
9056 else <<-L"<%makefileParams.omhome%>/lib/<%Config.targetTriple()%>/omc" -L"<%makefileParams.omhome%>/lib" -Wl,<%ExtraStack%>-rpath,"<%makefileParams.omhome%>/lib/<%Config.targetTriple()%>/omc" <%linkBinDirWindows%> -Wl,-rpath,"<%makefileParams.omhome%>/lib" <%ParModelicaExpLibs%> <%makefileParams.ldflags%> $(RUNTIME_LIBS) >>
9057 %>
9058 DIREXTRA=<%stringReplace(dirExtra,"#","\\#") /* make strips everything after # */%>
9059 MAINFILE=<%fileNamePrefix%>.c
9060 MAINOBJ=<%fileNamePrefix%>.o
9061 CFILES=<%fileNamePrefix%>_functions.c <%fileNamePrefix%>_records.c \
9062 <%fileNamePrefix%>_01exo.c <%fileNamePrefix%>_02nls.c <%fileNamePrefix%>_03lsy.c <%fileNamePrefix%>_04set.c <%fileNamePrefix%>_05evt.c <%fileNamePrefix%>_06inz.c <%fileNamePrefix%>_07dly.c \
9063 <%fileNamePrefix%>_08bnd.c <%fileNamePrefix%>_09alg.c <%fileNamePrefix%>_10asr.c <%fileNamePrefix%>_11mix.c <%fileNamePrefix%>_12jac.c <%fileNamePrefix%>_13opt.c <%fileNamePrefix%>_14lnz.c \
9064 <%fileNamePrefix%>_15syn.c <%fileNamePrefix%>_16dae.c <%fileNamePrefix%>_17inl.c <%fileNamePrefix%>_18spd.c <%extraFiles |> extraFile => ' \<%\n%> <%extraFile%>'%>
9065
9066 OFILES=$(CFILES:.c=.o)
9067 GENERATEDFILES=$(MAINFILE) <%fileNamePrefix%>.makefile <%fileNamePrefix%>_literals.h <%fileNamePrefix%>_functions.h $(CFILES)
9068
9069 .PHONY: omc_main_target clean bundle
9070
9071 # This is to make sure that <%fileNamePrefix%>_*.c are always compiled.
9072 .PHONY: $(CFILES)
9073
9074 omc_main_target: $(MAINOBJ) <%fileNamePrefix%>_functions.h <%fileNamePrefix%>_literals.h $(OFILES)
9075 <%\t%><% if Flags.getConfigBool(Flags.PARMODAUTO) then '$(CXX)' else '$(CC)'%> -I. -o <%fileNamePrefix%>$(EXEEXT) $(MAINOBJ) $(OFILES) $(DIREXTRA) <%libsPos1%> <%libsPos2%> $(CFLAGS) $(CPPFLAGS) $(LDFLAGS)
9076 <% if stringEq(Config.simCodeTarget(),"JavaScript") then '<%\t%>rm -f <%fileNamePrefix%>'%>
9077 <% if stringEq(Config.simCodeTarget(),"JavaScript") then '<%\t%>ln -s <%fileNamePrefix%>_node.js <%fileNamePrefix%>'%>
9078 <% if stringEq(Config.simCodeTarget(),"JavaScript") then '<%\t%>chmod +x <%fileNamePrefix%>_node.js'%>
9079
9080 omc_dll_target: $(MAINOBJ) <%fileNamePrefix%>_functions.h <%fileNamePrefix%>_literals.h $(OFILES)
9081 <%\t%>$(CC) -DOMC_DLL_MAIN_DEFINE -o $(MAINOBJ) -c $(MAINFILE) $(DIREXTRA) <%libsPos1%> <%libsPos2%> $(CFLAGS) $(CPPFLAGS) $(LDFLAGS)
9082 <%\t%><% if Flags.getConfigBool(Flags.PARMODAUTO) then '$(CXX)' else '$(CC)'%> -shared -I. -o <%fileNamePrefix%>$(DLLEXT) $(MAINOBJ) $(OFILES) $(DIREXTRA) <%libsPos1%> <%libsPos2%> $(CFLAGS) $(CPPFLAGS) $(LDFLAGS)
9083
9084 clean:
9085 <%\t%>@rm -f <%fileNamePrefix%>_records.o $(MAINOBJ)
9086
9087 bundle:
9088 <%\t%>@tar -cvf <%fileNamePrefix%>_Files.tar $(GENERATEDFILES)
9089 >>
9090 end match
9091 else
9092 error(sourceInfo(), 'Target <%target%> is not handled!')
9093 end simulationMakefile;
9094
9095 ✗ template crefM(ComponentRef cr)
9096 "Generates Modelica equivalent name for component reference."
9097 ::=
9098 match cr
9099 case CREF_IDENT(ident = "xloc") then CodegenUtil.crefStr(cr)
9100 case CREF_IDENT(ident = "time") then "time"
9101 else "P" + crefToMStr(cr)
9102 end crefM;
9103
9104 4953 template simEqAttrIsDiscreteKind(SimEqSystem eq)
9105 ::=
9106 match eq
9107 case SES_RESIDUAL(__)
9108 case SES_FOR_RESIDUAL(__)
9109 case SES_GENERIC_RESIDUAL(__)
9110 case SES_SIMPLE_ASSIGN(__)
9111 case SES_SIMPLE_ASSIGN_CONSTRAINTS(__)
9112 case SES_ARRAY_CALL_ASSIGN(__)
9113 case SES_RESIZABLE_ASSIGN(__)
9114 case SES_GENERIC_ASSIGN(__)
9115 case SES_ENTWINED_ASSIGN(__)
9116 case SES_IFEQUATION(__)
9117 case SES_ALGORITHM(__)
9118 case SES_LINEAR(__)
9119 case SES_NONLINEAR(__)
9120 case SES_MIXED(__)
9121 case SES_WHEN(__)
9122 case SES_FOR_LOOP(__)
9123 then eqAttributeIsDiscreteKind(eqAttr)
9124 else ''
9125 end simEqAttrIsDiscreteKind;
9126
9127 4990 template eqAttributeIsDiscreteKind(EquationAttributes eqAtt)
9128 ::=
9129 match eqAtt
9130 case EQUATION_ATTRIBUTES(kind=kind) then '<%eqIsDiscreteKind(kind)%>'
9131 else ''
9132 end eqAttributeIsDiscreteKind;
9133
9134 4979 template eqIsDiscreteKind(EquationKind eqKind)
9135 ::=
9136 match eqKind
9137 case DISCRETE_EQUATION() then '1'
9138 else '0'
9139 end eqIsDiscreteKind;
9140
9141 4953 template simEqAttrEval(SimEqSystem eq)
9142 ::=
9143 match eq
9144 case SES_RESIDUAL(__)
9145 case SES_FOR_RESIDUAL(__)
9146 case SES_GENERIC_RESIDUAL(__)
9147 case SES_SIMPLE_ASSIGN(__)
9148 case SES_SIMPLE_ASSIGN_CONSTRAINTS(__)
9149 case SES_ARRAY_CALL_ASSIGN(__)
9150 case SES_RESIZABLE_ASSIGN(__)
9151 case SES_GENERIC_ASSIGN(__)
9152 case SES_ENTWINED_ASSIGN(__)
9153 case SES_IFEQUATION(__)
9154 case SES_ALGORITHM(__)
9155 case SES_LINEAR(__)
9156 case SES_NONLINEAR(__)
9157 case SES_MIXED(__)
9158 case SES_WHEN(__)
9159 case SES_FOR_LOOP(__)
9160 then eqAttributesEval(eqAttr)
9161 else ''
9162 end simEqAttrEval;
9163
9164 4990 template eqAttributesEval(EquationAttributes eqAtt)
9165 ::=
9166 match eqAtt
9167 case EQUATION_ATTRIBUTES(evalStages=evalStages) then '<%eqEval(evalStages)%>'
9168 else ''
9169 end eqAttributesEval;
9170
9171 4990 template eqEval(EvaluationStages eqEval)
9172 ::=
9173 match eqEval
9174 case EVALUATION_STAGES(__) then
9175 let dy = if dynamicEval then '+1' else ''
9176 let al = if algebraicEval then '+2' else ''
9177 let zc = if zerocrossEval then '+4' else ''
9178 let di = if discreteEval then '+8' else ''
9179 <<evalStages = 0<%dy%><%al%><%zc%><%di%>;>>
9180 end eqEval;
9181
9182 /*****************************************************************************
9183 * SECTION: GENERATE OPTIMIZATION IN SIMULATION FILE
9184 *****************************************************************************/
9185
9186 1170 template optimizationComponents( list<DAE.ClassAttributes> classAttributes ,SimCode simCode, String modelNamePrefixStr)
9187 "Generates C for Objective Functions."
9188 ::=
9189 match classAttributes
9190 case {} then
9191 let fail = 'throwStreamPrint(NULL, "The model was not compiled with -g=Optimica and the corresponding goal function. The optimization solver cannot be used.");<%\n%>return 0;'
9192 <<
9193 int <%symbolName(modelNamePrefixStr,"mayer")%>(DATA* data, modelica_real** res,short *i) {
9194 <%fail%>
9195 }
9196 int <%symbolName(modelNamePrefixStr,"lagrange")%>(DATA* data, modelica_real** res, short * i1, short*i2) {
9197 <%fail%>
9198 }
9199 int <%symbolName(modelNamePrefixStr,"getInputVarIndicesInOptimization")%>(DATA* data, int* input_var_indices, int* loop_input_indices) {
9200 <%fail%>
9201 }
9202 int <%symbolName(modelNamePrefixStr,"pickUpBoundsForInputsInOptimization")%>(DATA* data, modelica_real* min, modelica_real* max, modelica_real*nominal, modelica_boolean *useNominal, char ** name, modelica_real * start, modelica_real * startTimeOpt) {
9203 <%fail%>
9204 }
9205 int <%symbolName(modelNamePrefixStr,"setInputData")%>(DATA *data) {
9206 <%fail%>
9207 }
9208 int <%symbolName(modelNamePrefixStr,"getTimeGrid")%>(DATA *data, modelica_integer * nsi, modelica_integer**idx) {
9209 <%fail%>
9210 }
9211 >>
9212 else
9213 (classAttributes |> classAttribute => optimizationComponents1(classAttribute, simCode, modelNamePrefixStr); separator="\n")
9214 end optimizationComponents;
9215
9216 34 template optimizationComponents1(ClassAttributes classAttribute, SimCode simCode, String modelNamePrefixStr)
9217 "Generates C for class attributes of objective function."
9218 ::=
9219 match classAttribute
9220 case OPTIMIZATION_ATTRS(__) then
9221 let &sub = buffer ""
9222 let &varDecls = buffer ""
9223 let &varFrees = buffer ""
9224 let &preExp = buffer ""
9225 let &varDecls1 = buffer ""
9226 let &preExp1 = buffer ""
9227 let &auxFunction = buffer ""
9228
9229 let objectiveFunction = match objetiveE
9230 case SOME(exp) then
9231 let setMayerIndex = if stringEq(crefToIndex(createDifferentiatedCrefName(makeUntypedCrefIdent(BackendDAE.optimizationMayerTermName), makeUntypedCrefIdent("dummyVarC"), "C")), "-2") then '' else
9232 <<
9233 *index_Dres = <%crefToIndex(createDifferentiatedCrefName(makeUntypedCrefIdent(BackendDAE.optimizationMayerTermName), makeUntypedCrefIdent("dummyVarC"), "C"))%>;
9234 return 0;
9235 >>
9236 <<
9237 *res = &<%cref(makeUntypedCrefIdent(BackendDAE.optimizationMayerTermName), &sub)%>;
9238 <%setMayerIndex%>
9239 >>
9240
9241 let startTimeOpt = match startTimeE
9242 case SOME(exp) then
9243 let startTimeOptExp = daeExp(exp, contextOther, &preExp, &varDecls, &varFrees, &auxFunction)
9244 <<
9245 *startTimeOpt = <%startTimeOptExp%>;
9246 >>
9247
9248 let objectiveIntegrand = match objectiveIntegrandE
9249 case SOME(exp) then
9250 let setLagrangeIndex = if stringEq(crefToIndex(createDifferentiatedCrefName(makeUntypedCrefIdent(BackendDAE.optimizationLagrangeTermName), makeUntypedCrefIdent("dummyVarB"), "B")), "-2") then '' else
9251 <<
9252 *index_DresB = <%crefToIndex(createDifferentiatedCrefName(makeUntypedCrefIdent(BackendDAE.optimizationLagrangeTermName), makeUntypedCrefIdent("dummyVarB"), "B"))%>;
9253 *index_DresC = <%crefToIndex(createDifferentiatedCrefName(makeUntypedCrefIdent(BackendDAE.optimizationLagrangeTermName), makeUntypedCrefIdent("dummyVarC"), "C"))%>;
9254 return 0;
9255 >>
9256 <<
9257 *res = &<%cref(makeUntypedCrefIdent(BackendDAE.optimizationLagrangeTermName), &sub)%>;
9258 <%setLagrangeIndex%>
9259 >>
9260
9261 let setInput = match simCode
9262 case simCode as SIMCODE(__) then
9263 match modelInfo
9264 case MODELINFO(vars=SIMVARS(__)) then
9265 <<
9266 <%vars.inputVars |> SIMVAR(__) hasindex i0 =>
9267 'data->simulationInfo->inputVars[<%i0%>] = <%cref(name, &sub)%>;'
9268 ;separator="\n"
9269 %>
9270 >>
9271
9272 let getTG = match simCode
9273 case simCode as SIMCODE(__) then
9274 match modelInfo
9275 case MODELINFO(vars=SIMVARS(__)) then
9276 <<
9277 *nsi=(-1 <%vars.paramVars |> SIMVAR(varKind=OPT_TGRID(__)) => '+1'
9278 ;separator=" "%>);
9279 *idx = (modelica_integer*) malloc((*nsi+1)*sizeof(modelica_integer));
9280 <%vars.paramVars |> SIMVAR(varKind=OPT_TGRID(__)) hasindex i0 =>
9281 '(*idx)[<%i0%>] = data->simulationInfo->realParamsIndex[<%index%>];'
9282 ;separator="\n"
9283 %>
9284 >>
9285
9286 let inputBounds = match simCode
9287 case simCode as SIMCODE(__) then
9288 match modelInfo
9289 case MODELINFO(vars=SIMVARS(__)) then
9290 // This assumes, that all variables are of type T_REAL
9291 <<
9292 <%vars.inputVars |> SIMVAR(type_=T_REAL()) hasindex i0 =>
9293 let kind = match varKind
9294 case PARAM() then 'VAR_KIND_PARAMETER'
9295 else 'VAR_KIND_VARIABLE'
9296 end match
9297 <<
9298 start[<%i0%>] = getStartFromScalarIdx(data->simulationInfo, data->modelData, VAR_TYPE_REAL, <%kind%>, <%crefIndexWithComment(name)%>);
9299 min[<%i0%>] = getMinFromScalarIdx(data->simulationInfo, data->modelData, VAR_TYPE_REAL, <%kind%>, <%crefIndexWithComment(name)%>);
9300 max[<%i0%>] = getMaxFromScalarIdx(data->simulationInfo, data->modelData, VAR_TYPE_REAL, <%kind%>, <%crefIndexWithComment(name)%>);
9301 nominal[<%i0%>] = getNominalFromScalarIdx(data->simulationInfo, data->modelData, <%kind%>, <%crefIndexWithComment(name)%>);
9302 useNominal[<%i0%>] = <%crefAttributes(name)%>.useNominal;
9303 name[<%i0%>] =(char *) <%crefVarInfo(name)%>.name;
9304 >>
9305 ;separator="\n"%>
9306 >>
9307
9308 let inputIndices = match simCode
9309 case simCode as SIMCODE(__) then
9310 match modelInfo
9311 case MODELINFO(vars=SIMVARS(__)) then
9312 <<
9313 <%vars.inputVars |> SIMVAR(__) hasindex i0 =>
9314 'input_var_indices[<%i0%>] = <%crefIndexWithComment(name)%>;'
9315 ;separator="\n"%>
9316 <%vars.inputVars |> SIMVAR(__) hasindex i0 =>
9317 'loop_input_indices[<%i0%>] = <%match varKind
9318 case OPT_LOOP_INPUT(replaceExp=cr) then crefIndexWithComment(cr)
9319 else "-1"%>;'
9320 ;separator="\n"%>
9321 >>
9322 <<
9323 <%auxFunction%>
9324 /* objectiveFunction */
9325 int <%symbolName(modelNamePrefixStr,"mayer")%>(DATA* data, modelica_real** res, short * index_Dres)
9326 {
9327 <%varDecls%>
9328 <%preExp%>
9329 <%objectiveFunction%>
9330 return -1;
9331 }
9332 /* objectiveIntegrand */
9333 int <%symbolName(modelNamePrefixStr,"lagrange")%>(DATA* data, modelica_real** res, short * index_DresB, short *index_DresC)
9334 {
9335 <%varDecls1%>
9336 <%preExp1%>
9337 <%objectiveIntegrand%>
9338 return -1;
9339 }
9340
9341 /* fill buffer with optimization input indices */
9342 int <%symbolName(modelNamePrefixStr,"getInputVarIndicesInOptimization")%>(DATA* data, int* input_var_indices, int* loop_input_indices)
9343 {
9344 <%inputIndices%>
9345 return 0;
9346 }
9347
9348 /* opt vars */
9349 int <%symbolName(modelNamePrefixStr,"pickUpBoundsForInputsInOptimization")%>(DATA* data, modelica_real* min, modelica_real* max, modelica_real*nominal, modelica_boolean *useNominal, char ** name, modelica_real * start, modelica_real* startTimeOpt)
9350 {
9351 <%inputBounds%>
9352 *startTimeOpt = data->simulationInfo->startTime - 1.0;
9353 <%startTimeOpt%>
9354 return 0;
9355 }
9356
9357 int <%symbolName(modelNamePrefixStr,"setInputData")%>(DATA *data)
9358 {
9359 <%setInput%>
9360 return 0;
9361 }
9362 int <%symbolName(modelNamePrefixStr,"getTimeGrid")%>(DATA *data, modelica_integer * nsi, modelica_integer**idx){
9363 <%getTG%>
9364 return 0;
9365 }
9366 >>
9367 else error(sourceInfo(), 'Unknown Constraint List')
9368 end optimizationComponents1;
9369
9370 ✗ template functionXXX_systemPartial(list<SimEqSystem> derivativEquations, String name, Integer n, String modelNamePrefixStr, ModelInfo modelInfo)
9371 ::=
9372 let code = match modelInfo
9373 case MODELINFO(vars=SIMVARS(derivativeVars=ders)) then
9374 (ders |> SIMVAR(__) hasindex i0 => equationNames_Partial(SimCodeCodegenUtil.computeDependencies(derivativEquations,name),modelNamePrefixStr,i0,CodegenUtil.crefStr(name)) ; separator="\n")
9375 <<
9376 static void <%modelNamePrefixStr%>_function<%name%><%n%>(DATA *data, threadData_t *threadData, int i)
9377 {
9378 switch (i) {
9379 <%code%>
9380 }
9381 }
9382 >>
9383 end functionXXX_systemPartial;
9384
9385
9386 ✗ template functionXXX_systemsPartial(list<list<SimEqSystem>> eqs, String name, Text &loop, Text &varDecls, Text &varFrees, String modelNamePrefixStr, ModelInfo modelInfo)
9387 ::=
9388 let funcs = (eqs |> eq hasindex i0 fromindex 0 => functionXXX_systemPartial(eq,name,i0,modelNamePrefixStr,modelInfo) ; separator="\n")
9389 match listLength(eqs)
9390 case 0 then //empty case
9391 let &loop +=
9392 <<
9393 /* no <%name%> systems */
9394 >>
9395 ""
9396 case 1 then //1 function
9397 let &loop +=
9398 <<
9399 <%modelNamePrefixStr%>_function<%name%>0(data, threadData,i);
9400 >>
9401 funcs //just the one function
9402 case nFuncs then //2 and more
9403 let funcNames = eqs |> e hasindex i0 fromindex 0 => 'function<%name%>_system<%i0%>' ; separator=",\n"
9404 let &varDecls += 'int id;<%\n%>'
9405
9406 let &loop +=
9407 /* Text for the loop body that calls the equations */
9408 <<
9409 for(id=0; id<<%nFuncs%>; id++) {
9410 function<%name%>_systems[id](data, threadData);
9411 }
9412 >>
9413 /* Text before the function head */
9414 <<
9415 <%funcs%>
9416 static void (*function<%name%>_systems[<%nFuncs%>])(DATA *data, threadData_t *threadData) = {
9417 <%funcNames%>
9418 };
9419 >>
9420 end functionXXX_systemsPartial;
9421
9422 ✗ template equationNames_Partial(list<SimEqSystem> eqs, String modelNamePrefixStr, Integer i0, String cref_der)
9423 "Generates an equation.
9424 This template should not be used for a SES_RESIDUAL.
9425 Residual equations are handled differently."
9426 ::=
9427 let odeEqs = eqs |> eq => equationNames_(eq,contextSimulationNonDiscrete,modelNamePrefixStr); separator="\n"
9428 <<
9429 case <%i0%>:
9430 // Assigning <%cref_der%>
9431 <%odeEqs%>
9432 break;
9433 >>
9434 end equationNames_Partial;
9435
9436 11541 template genericCallBodies(list<SimGenericCall> genericCalls, Context context)
9437 "Generates the body for a set of generic calls."
9438 ::=
9439 let jac = match context case JACOBIAN_CONTEXT() then ", JACOBIAN *jacobian" else ""
9440 let sub_name = match context case JACOBIAN_CONTEXT(name = jac_name) then 'jac_<%jac_name%>_' else ""
9441 (genericCalls |> call =>
9442 let comment = escapeCComments(simGenericCallString(call))
9443 let &sub = buffer ""
9444 let &preExp = buffer ""
9445 let &varDecls = buffer ""
9446 let &varFrees = buffer ""
9447 let &auxFunction = buffer ""
9448
9449 match call
9450 case SINGLE_GENERIC_CALL() then
9451 let body_ = genericCallLhsRhs(lhs, rhs, context, &preExp, &varDecls, &varFrees, &auxFunction)
9452 let iter_ = if resizable then (iters |> iter => resizableIterator(iter, context, &preExp, &varDecls, &varFrees, &auxFunction, &sub); separator = "\n") else (iters |> iter => genericIterator(iter, context, &preExp, &varDecls, &varFrees, &auxFunction, &sub); separator = "\n")
9453 let idx_ = if resizable then (iters |> it => 'modelica_integer <%forIteratorName(it, context, &preExp, &varDecls, &varFrees, &auxFunction, &sub)%>';separator=", ";empty) else "int idx"
9454 let idx_copy = if resizable then "" else "int tmp = idx;"
9455 <<
9456 /*
9457 <%comment%>
9458 */
9459 <%auxFunction%>
9460 void genericCall_<%sub_name%><%index%>(DATA *data, threadData_t *threadData<%jac%>, const int equationIndexes[2], <%idx_%>)
9461 {
9462 <%idx_copy%>
9463 <%varDecls%>
9464 <%iter_%>
9465 <%preExp%>
9466 <%body_%>;
9467 _return: OMC_LABEL_UNUSED ;
9468 <%varFrees%>
9469 }
9470 >>
9471
9472 case IF_GENERIC_CALL() then
9473 let iter_ = if resizable then (iters |> iter => resizableIterator(iter, context, &preExp, &varDecls, &varFrees, &auxFunction, &sub); separator = "\n") else (iters |> iter => genericIterator(iter, context, &preExp, &varDecls, &varFrees, &auxFunction, &sub); separator = "\n")
9474 let branches_ = (branches |> branch => genericBranch(branch, context, &preExp, &varDecls, &varFrees, &auxFunction, &sub); separator = " else ")
9475 let idx_ = if resizable then (iters |> it => 'modelica_integer <%forIteratorName(it, context, &preExp, &varDecls, &varFrees, &auxFunction, &sub)%>';separator=", ";empty) else "int idx"
9476 let idx_copy = if resizable then "" else "int tmp = idx;"
9477 <<
9478 /*
9479 <%comment%>
9480 */
9481 <%auxFunction%>
9482 void genericCall_<%sub_name%><%index%>(DATA *data, threadData_t *threadData<%jac%>, const int equationIndexes[2], <%idx_%>)
9483 {
9484 <%idx_copy%>
9485 <%varDecls%>
9486 <%iter_%>
9487 <%preExp%>
9488 <%branches_%>
9489 _return: OMC_LABEL_UNUSED ;
9490 <%varFrees%>
9491 }
9492 >>
9493
9494 case WHEN_GENERIC_CALL() then
9495 let iter_ = if resizable then (iters |> iter => resizableIterator(iter, context, &preExp, &varDecls, &varFrees, &auxFunction, &sub); separator = "\n") else (iters |> iter => genericIterator(iter, context, &preExp, &varDecls, &varFrees, &auxFunction, &sub); separator = "\n")
9496 let branches_ = (branches |> branch => genericBranch(branch, context, &preExp, &varDecls, &varFrees, &auxFunction, &sub); separator = " else ")
9497 let idx_ = if resizable then (iters |> it => 'modelica_integer <%forIteratorName(it, context, &preExp, &varDecls, &varFrees, &auxFunction, &sub)%>';separator=", ";empty) else "int idx"
9498 let idx_copy = if resizable then "" else "int tmp = idx;"
9499 <<
9500 /*
9501 <%comment%>
9502 */
9503 <%auxFunction%>
9504 void genericCall_<%sub_name%><%index%>(DATA *data, threadData_t *threadData<%jac%>, const int equationIndexes[2], <%idx_%>)
9505 {
9506 <%idx_copy%>
9507 <%varDecls%>
9508 <%iter_%>
9509 <%preExp%>
9510 <%branches_%>
9511 _return: OMC_LABEL_UNUSED ;
9512 <%varFrees%>
9513 }
9514 >>
9515 ; separator="\n\n")
9516 end genericCallBodies;
9517
9518 319 template genericCallLhsRhs(DAE.Exp lhs, DAE.Exp rhs, Context context, Text &preExp, Text &varDecls, Text &varFrees, Text &auxFunction)
9519 ::= match lhs
9520 case CREF(componentRef=cr, ty = T_ARRAY()) then
9521 let rhs_ = daeExp(rhs, context, &preExp, &varDecls, &varFrees, &auxFunction)
9522 let start_ = if isStartCref(cr) then algStmtAssignArrWithRhsExpStr(makeCrefExp(popCref(cr), crefTypeFull(cr)), rhs_, context, &preExp, &varDecls, &varFrees, &auxFunction) else ""
9523 // the start attribute has to be large enough before a view on it is created
9524 let &preExp += if isStartCref(cr) then startArrayEnsureSize(cr) + "\n" else ""
9525 <<
9526 <%algStmtAssignArrWithRhsExpStr(lhs, rhs_, context, &preExp, &varDecls, &varFrees, &auxFunction)%>
9527 <%start_%>
9528 >>
9529 case CREF(componentRef=cr) then
9530 let lhs_ = daeExp(lhs, context, &preExp, &varDecls, &varFrees, &auxFunction)
9531 let rhs_ = daeExp(rhs, context, &preExp, &varDecls, &varFrees, &auxFunction)
9532 let start_ = if isStartCref(cr) then genericCallLhsRhs(makeCrefExp(popCref(cr), crefTypeFull(cr)), rhs, context, &preExp, &varDecls, &varFrees, &auxFunction) else ""
9533 <<
9534 <%lhs_%> = <%rhs_%>;
9535 <%start_%>
9536 >>
9537 else
9538 let lhs_ = daeExp(lhs, context, &preExp, &varDecls, &varFrees, &auxFunction)
9539 let rhs_ = daeExp(rhs, context, &preExp, &varDecls, &varFrees, &auxFunction)
9540 <<
9541 <%lhs_%> = <%rhs_%>;
9542 >>
9543 end genericCallLhsRhs;
9544
9545 7 template genericBranch(SimBranch branch, Context context, Text &preExp, Text &varDecls, Text &varFrees, Text &auxFunction, Text &sub)
9546 ::= match branch
9547 case SIM_BRANCH() then
9548 let condition_ = match condition
9549 case SOME(cond) then <<if(<%daeExp(cond, context, &preExp, &varDecls, &varFrees, &auxFunction)%>)>>
9550 else ""
9551 // the pre-statements of a body (e.g. a function call and its error check) must run in
9552 // the branch, not before the whole if chain where they would run for every branch
9553 let body_ = (body |> (lhs, rhs) =>
9554 let &bodyPre = buffer ""
9555 let lhs_ = daeExp(lhs, context, &bodyPre, &varDecls, &varFrees, &auxFunction)
9556 let rhs_ = daeExp(rhs, context, &bodyPre, &varDecls, &varFrees, &auxFunction)
9557 <<
9558 <%bodyPre%>
9559 <%lhs_%> = <%rhs_%>;
9560 >>
9561 ; separator="\n")
9562 <<
9563 <%condition_%>{
9564 <%body_%>
9565 }
9566 >>
9567 case SIM_BRANCH_STMT() then
9568 let condition_ = match condition
9569 case SOME(cond) then <<if(<%daeExp(cond, context, &preExp, &varDecls, &varFrees, &auxFunction)%>)>>
9570 else ""
9571 let body_ = (body |> stmt => algStatement(stmt, context, &varDecls, &varFrees, &auxFunction); separator="\n")
9572 <<
9573 <%condition_%>{
9574 <%body_%>
9575 }
9576 >>
9577 end genericBranch;
9578
9579 23 template genericIterator(SimIterator iter, Context context, Text &preExp, Text &varDecls, Text &varFrees, Text &auxFunction, Text &sub)
9580 ::= match iter
9581 case SIM_ITERATOR_RANGE() then
9582 let iter_ = contextCref(name, contextOther, &preExp, &varDecls, &varFrees, &auxFunction, &sub)
9583 let start_ = daeExp(start, context, &preExp, &varDecls, &varFrees, &auxFunction)
9584 let step_ = daeExp(step, context, &preExp, &varDecls, &varFrees, &auxFunction)
9585 let size_ = daeExp(size, context, &preExp, &varDecls, &varFrees, &auxFunction)
9586 let sub_iter_ = (sub_iter |> sub_i => subIterator(sub_i, iter_, context, &preExp, &varDecls, &varFrees, &auxFunction, &sub); separator="\n")
9587 <<
9588 int <%iter_%>_loc = tmp % (<%size_%>);
9589 int <%iter_%> = (<%step_%>) * <%iter_%>_loc + (<%start_%>);
9590 tmp /= (<%size_%>);
9591 <%sub_iter_%>
9592 >>
9593 case SIM_ITERATOR_LIST() then
9594 let iter_ = contextCref(name, contextOther, &preExp, &varDecls, &varFrees, &auxFunction, &sub)
9595 let sub_iter_ = (sub_iter |> sub_i => subIterator(sub_i, iter_, context, &preExp, &varDecls, &varFrees, &auxFunction, &sub); separator="\n")
9596 let arr = (lst |> elem => '<%elem%>'; separator=", ")
9597 <<
9598 static const int <%iter_%>_lst[<%size%>] = {<%arr%>};
9599 int <%iter_%>_loc = tmp % <%size%>;
9600 int <%iter_%> = <%iter_%>_lst[<%iter_%>_loc];
9601 tmp /= <%size%>;
9602 <%sub_iter_%>
9603 >>
9604 end genericIterator;
9605
9606 397 template resizableIterator(SimIterator iter, Context context, Text &preExp, Text &varDecls, Text &varFrees, Text &auxFunction, Text &sub)
9607 ::= match iter
9608 case SIM_ITERATOR_RANGE() then
9609 let iter_ = contextCref(name, contextOther, &preExp, &varDecls, &varFrees, &auxFunction, &sub)
9610 let sub_iter_ = (sub_iter |> sub_i => subIterator(sub_i, iter_, context, &preExp, &varDecls, &varFrees, &auxFunction, &sub); separator="\n")
9611 <<
9612 <%sub_iter_%>
9613 >>
9614 case SIM_ITERATOR_LIST() then
9615 let iter_ = contextCref(name, contextOther, &preExp, &varDecls, &varFrees, &auxFunction, &sub)
9616 let sub_iter_ = (sub_iter |> sub_i => subIterator(sub_i, iter_, context, &preExp, &varDecls, &varFrees, &auxFunction, &sub); separator="\n")
9617 <<
9618 <%sub_iter_%>
9619 >>
9620 end resizableIterator;
9621
9622 602 template forIterator(SimIterator iter, Context context, Text &preExp, Text &varDecls, Text &varFrees, Text &auxFunction, Text &sub)
9623 ::= match iter
9624 case SIM_ITERATOR_RANGE() then
9625 let iter_ = contextCref(name, contextOther, &preExp, &varDecls, &varFrees, &auxFunction, &sub)
9626 let start_ = daeExp(start, context, &preExp, &varDecls, &varFrees, &auxFunction)
9627 let step_ = daeExp(step, context, &preExp, &varDecls, &varFrees, &auxFunction)
9628 let stop_ = daeExp(stop, context, &preExp, &varDecls, &varFrees, &auxFunction)
9629 // sub_iter: dependent iterators whose values are selected by the outer range iterator.
9630 // Emit them inside the loop body so expressions referencing them compile correctly.
9631 let subIterDecls = (sub_iter |> si => subIterator(si, iter_, context, &preExp, &varDecls, &varFrees, &auxFunction, &sub); separator="\n")
9632 <<
9633 for(modelica_integer <%iter_%>=<%start_%>; in_range_integer(<%iter_%>, <%start_%>, <%stop_%>); <%iter_%>+=<%step_%>){
9634 <%if subIterDecls then subIterDecls%>
9635 >>
9636 case SIM_ITERATOR_LIST() then
9637 let iter_ = contextCref(name, contextOther, &preExp, &varDecls, &varFrees, &auxFunction, &sub)
9638 let arr = (lst |> elem => '<%elem%>'; separator=", ")
9639 // Pass the 0-based loop counter (iter__=0..N-1) as '<%iter_%>_+1' so subIterator's
9640 // name_arr[parent_iter-1] resolves to name_arr[iter__], selecting the right element.
9641 let subIterDecls = (sub_iter |> si => subIterator(si, '<%iter_%>_+1', context, &preExp, &varDecls, &varFrees, &auxFunction, &sub); separator="\n")
9642 <<
9643 static const int <%iter_%>_lst[<%size%>] = {<%arr%>};
9644 for(int <%iter_%>_=0; <%iter_%>_<<%size%>; <%iter_%>_++){
9645 modelica_integer <%iter_%> = <%iter_%>_lst[<%iter_%>_];
9646 <%if subIterDecls then subIterDecls%>
9647 >>
9648 end forIterator;
9649
9650 124 template forIteratorBody(SimIterator iter, Context context, Text &preExp, Text &varDecls, Text &varFrees, Text &auxFunction, Text &sub)
9651 ::= match iter
9652 case SIM_ITERATOR_RANGE() then
9653 let iter_ = contextCref(name, contextOther, &preExp, &varDecls, &varFrees, &auxFunction, &sub)
9654 let start_ = daeExp(start, context, &preExp, &varDecls, &varFrees, &auxFunction)
9655 let step_ = daeExp(step, context, &preExp, &varDecls, &varFrees, &auxFunction)
9656 let size_ = daeExp(size, context, &preExp, &varDecls, &varFrees, &auxFunction)
9657 <<
9658 (<%iter_%>-(<%start_%>))/(<%step_%>)+(<%size_%>)*(
9659 >>
9660 case SIM_ITERATOR_LIST() then
9661 let iter_ = contextCref(name, contextOther, &preExp, &varDecls, &varFrees, &auxFunction, &sub)
9662 <<
9663 <%iter_%>_+<%size%>*(
9664 >>
9665 end forIteratorBody;
9666
9667 1240 template forIteratorName(SimIterator iter, Context context, Text &preExp, Text &varDecls, Text &varFrees, Text &auxFunction, Text &sub)
9668 ::= match iter
9669 case SIM_ITERATOR_RANGE() then contextCref(name, contextOther, &preExp, &varDecls, &varFrees, &auxFunction, &sub)
9670 case SIM_ITERATOR_LIST() then contextCref(name, contextOther, &preExp, &varDecls, &varFrees, &auxFunction, &sub)
9671 end forIteratorName;
9672
9673
9674 11541 template genericCallHeaders(list<SimGenericCall> genericCalls, Context context)
9675 "Generates the header for a set of generic calls."
9676 ::=
9677 let jac = match context case JACOBIAN_CONTEXT() then ", JACOBIAN *jacobian" else ""
9678 let sub_name = match context case JACOBIAN_CONTEXT(name = jac_name) then 'jac_<%jac_name%>_' else ""
9679 (genericCalls |> call => match call
9680 case SINGLE_GENERIC_CALL()
9681 case IF_GENERIC_CALL()
9682 case WHEN_GENERIC_CALL() then
9683 let &sub = buffer ""
9684 let &preExp = buffer ""
9685 let &varDecls = buffer ""
9686 let &varFrees = buffer ""
9687 let &auxFunction = buffer ""
9688 let idx_ = if resizable then (iters |> it => 'modelica_integer <%forIteratorName(it, context, &preExp, &varDecls, &varFrees, &auxFunction, &sub)%>';separator=", ";empty) else "int idx"
9689 <<void genericCall_<%sub_name%><%index%>(DATA *data, threadData_t *threadData<%jac%>, const int equationIndexes[2], <%idx_%>);>>;
9690 separator="\n\n")
9691 end genericCallHeaders;
9692
9693 annotation(__OpenModelica_Interface="codegen_c");
9694 end CodegenC;
9695
9696 // vim: filetype=susan sw=2 sts=2
9697