Skip to content

Commit eab61fd

Browse files
authored
[C] Real array nominal attribute (OpenModelica#14771)
* New reverse mapping from scalarized to array variables. * New function `getNominalFromScalarIdx` * Changed `modelica_real nominal` to `real_array nominal`. * Made function `real_vector_to_string` safer.
1 parent b650d21 commit eab61fd

39 files changed

Lines changed: 1039 additions & 265 deletions

OMCompiler/Compiler/Template/CodegenC.tpl

Lines changed: 92 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -639,6 +639,8 @@ template simulationFile_nls(SimCode simCode)
639639
<%simulationFileHeader(simCode.fileNamePrefix)%>
640640
#include "<%simCode.fileNamePrefix%>_12jac.h"
641641
#include "simulation/jacobian_util.h"
642+
#include "simulation/arrayIndex.h"
643+
642644
#if defined(__cplusplus)
643645
extern "C" {
644646
#endif
@@ -663,6 +665,8 @@ template simulationFile_lsy(SimCode simCode)
663665
/* Linear Systems */
664666
<%simulationFileHeader(simCode.fileNamePrefix)%>
665667
#include "<%simCode.fileNamePrefix%>_12jac.h"
668+
#include "simulation/arrayIndex.h"
669+
666670
#if defined(__cplusplus)
667671
extern "C" {
668672
#endif
@@ -913,7 +917,29 @@ template simulationFile_jac_header(SimCode simCode)
913917
case simCode as SIMCODE(__) then
914918
<<
915919
/* Jacobians */
916-
static const REAL_ATTRIBUTE dummyREAL_ATTRIBUTE = omc_dummyRealAttribute;
920+
static _index_t one_dim[1] = { 1 };
921+
static modelica_real nominal_data[1] = { 1.0 };
922+
static modelica_real start_data[1] = { 0.0 };
923+
static const REAL_ATTRIBUTE dummyREAL_ATTRIBUTE = {
924+
.unit = NULL,
925+
.displayUnit = NULL,
926+
.min = -DBL_MAX,
927+
.max = DBL_MAX,
928+
.fixed = FALSE,
929+
.useNominal = FALSE,
930+
.nominal = {
931+
.ndims = 1,
932+
.dim_size = one_dim,
933+
.data = ( void* )nominal_data,
934+
.flexible = FALSE
935+
},
936+
.start = {
937+
.ndims = 1,
938+
.dim_size = one_dim,
939+
.data = ( void* )start_data,
940+
.flexible = FALSE
941+
}
942+
};
917943

918944
<%symJacDefinition(jacobianMatrices, modelNamePrefix(simCode))%><%\n%>
919945
>>
@@ -931,6 +957,8 @@ template simulationFile_opt(SimCode simCode)
931957
/* Optimization */
932958
<%simulationFileHeader(simCode.fileNamePrefix)%>
933959
#include "<%fileNamePrefix%>_12jac.h"
960+
#include "simulation/arrayIndex.h"
961+
934962
#if defined(__cplusplus)
935963
extern "C" {
936964
#endif
@@ -2868,6 +2896,8 @@ template functionNonLinearResidualsMultiFile2(list<list<SimEqSystem>> nonlinearS
28682896
/* Non Linear Systems <%fullPathPrefix + fileName%> */
28692897
<%simulationFileHeader(fileNamePrefix)%>
28702898
#include "<%fileNamePrefix%>_12jac.h"
2899+
#include "simulation/arrayIndex.h"
2900+
28712901
#if defined(__cplusplus)
28722902
extern "C" {
28732903
#endif
@@ -3287,12 +3317,22 @@ template generateStaticInitialData(list<ComponentRef> crefs, String indexName)
32873317
::=
32883318
let systemType = 'NONLINEAR_SYSTEM_DATA'
32893319
let bodyStaticData = (crefs |> cr hasindex i0 =>
3320+
let nominal = match cref2simvar(crefRemovePrePrefix(cr), getSimCode())
3321+
case SIMVAR(type_=T_REAL(__), varKind=PARAM()) then
3322+
'getNominalFromScalarIdx(data->simulationInfo, data->modelData, VAR_KIND_PARAMETER, <%crefIndexWithComment(cr)%>)'
3323+
case SIMVAR(type_=T_REAL(__)) then
3324+
'getNominalFromScalarIdx(data->simulationInfo, data->modelData, VAR_KIND_VARIABLE, <%crefIndexWithComment(cr)%>)'
3325+
else
3326+
'<%crefAttributes(cr)%>.nominal'
3327+
end match
3328+
32903329
<<
32913330
/* static nls data for <%crefStrNoUnderscore(cr)%> */
3292-
sysData->nominal[i] = <%crefAttributes(cr)%>.nominal;
3331+
sysData->nominal[i] = <%nominal%>;
32933332
sysData->min[i] = <%crefAttributes(cr)%>.min;
32943333
sysData->max[i++] = <%crefAttributes(cr)%>.max;
32953334
>>
3335+
32963336
;separator="\n")
32973337
<<
32983338
@@ -3406,17 +3446,17 @@ let &sub = buffer ""
34063446
{
34073447
/* min ******************************************************** */
34083448
infoStreamPrint(OMC_LOG_INIT, 1, "updating min-values");
3409-
<%minValueEquations |> eq as SES_SIMPLE_ASSIGN(__) => equation_call(eq, modelNamePrefix, contextOther)%>
3449+
<%(minValueEquations |> eq as SES_SIMPLE_ASSIGN(__) => equation_call(eq, modelNamePrefix, contextOther) ; separator="\n")%>
34103450
messageClose(OMC_LOG_INIT);
34113451
34123452
/* max ******************************************************** */
34133453
infoStreamPrint(OMC_LOG_INIT, 1, "updating max-values");
3414-
<%maxValueEquations |> eq as SES_SIMPLE_ASSIGN(__) => equation_call(eq, modelNamePrefix, contextOther)%>
3454+
<%(maxValueEquations |> eq as SES_SIMPLE_ASSIGN(__) => equation_call(eq, modelNamePrefix, contextOther) ; separator="\n")%>
34153455
messageClose(OMC_LOG_INIT);
34163456
34173457
/* nominal **************************************************** */
34183458
infoStreamPrint(OMC_LOG_INIT, 1, "updating nominal-values");
3419-
<%nominalValueEquations |> eq as SES_SIMPLE_ASSIGN(__) => equation_call(eq, modelNamePrefix, contextOther)%>
3459+
<%(nominalValueEquations |> eq as SES_SIMPLE_ASSIGN(__) => equation_call(eq, modelNamePrefix, contextOther) ; separator="\n")%>
34203460
messageClose(OMC_LOG_INIT);
34213461
34223462
/* start ****************************************************** */
@@ -3467,26 +3507,52 @@ template functionUpdateBoundVariableAttributesFunctionsSimpleAssign(SimEqSystem
34673507
"Generates an equation that is just a simple assignment for an arribute binding. The attribute type is given by the
34683508
function argument 'attibute' (e.g min, max ...)"
34693509
::=
3470-
match eq
3471-
case SES_SIMPLE_ASSIGN(__)
3472-
case SES_SIMPLE_ASSIGN_CONSTRAINTS(__) then
3473-
let &sub = buffer ""
3474-
let &preExp = buffer ""
3475-
let expPart = daeExp(exp, context, &preExp, &varDecls, &auxFunction)
3476-
let postExp = if isStartCref(cref) then
3477-
<<
3478-
<%cref(popCref(cref), &sub)%> = <%cref(cref, &sub)%>;
3479-
infoStreamPrint(OMC_LOG_INIT_V, 0, "updated start value: %s(start=<%crefToPrintfArg(popCref(cref))%>)", <%crefVarInfo(popCref(cref))%>.name, (<%crefType(popCref(cref))%>) <%cref(popCref(cref), &sub)%>);
3480-
>>
3481-
<<
3482-
<%modelicaLine(eqInfo(eq))%>
3483-
<%preExp%>
3484-
<%crefAttributes(cref)%>.<%attribute%> = <%expPart%>;
3485-
infoStreamPrint(OMC_LOG_INIT_V, 0, "%s(<%attribute%>=<%crefToPrintfArg(cref)%>)", <%crefVarInfo(cref)%>.name,
3486-
(<%crefType(cref)%>) <%crefAttributes(cref)%>.<%attribute%>);
3487-
<%postExp%>
3488-
<%endModelicaLine()%>
3489-
>>
3510+
match eq
3511+
case SES_SIMPLE_ASSIGN(__)
3512+
case SES_SIMPLE_ASSIGN_CONSTRAINTS(__) then
3513+
let &sub = buffer ""
3514+
let &preExp = buffer ""
3515+
let expPart = daeExp(exp, context, &preExp, &varDecls, &auxFunction)
3516+
let postExp = if isStartCref(cref) then
3517+
<<
3518+
<%cref(popCref(cref), &sub)%> = <%cref(cref, &sub)%>;
3519+
infoStreamPrint(OMC_LOG_INIT_V, 0, "updated start value: %s(start=<%crefToPrintfArg(popCref(cref))%>)",
3520+
<%crefVarInfo(popCref(cref))%>.name,
3521+
(<%crefType(popCref(cref))%>) <%cref(popCref(cref), &sub)%>);
3522+
>>
3523+
3524+
let updateEqs = match attribute
3525+
case "nominal" then
3526+
<<
3527+
if (<%crefVarDimension(cref)%>.numberOfDimensions == 0) {
3528+
put_real_element(<%expPart%>, 0, &<%crefAttributes(cref)%>.nominal);
3529+
} else {
3530+
throwStreamPrint(NULL, "Not yet implemented for array nominals.");
3531+
}
3532+
3533+
if (omc_useStream[OMC_LOG_INIT_V]) {
3534+
char nominal_buffer[2048];
3535+
real_vector_to_string(&<%crefAttributes(cref)%>.nominal, <%crefVarDimension(cref)%>.numberOfDimensions == 0, nominal_buffer, 2048);
3536+
infoStreamPrint(OMC_LOG_INIT_V, 0, "%s(nominal=%s)",
3537+
<%crefVarInfo(cref)%>.name,
3538+
nominal_buffer);
3539+
}
3540+
>>
3541+
else
3542+
<<
3543+
<%crefAttributes(cref)%>.<%attribute%> = <%expPart%>;
3544+
infoStreamPrint(OMC_LOG_INIT_V, 0, "%s(<%attribute%>=<%crefToPrintfArg(cref)%>)",
3545+
<%crefVarInfo(cref)%>.name,
3546+
(<%crefType(cref)%>) <%crefAttributes(cref)%>.<%attribute%>);
3547+
>>
3548+
3549+
<<
3550+
<%modelicaLine(eqInfo(eq))%>
3551+
<%preExp%>
3552+
<%updateEqs%>
3553+
<%postExp%>
3554+
<%endModelicaLine()%>
3555+
>>
34903556
end functionUpdateBoundVariableAttributesFunctionsSimpleAssign;
34913557
34923558
@@ -7090,7 +7156,7 @@ template optimizationComponents1(ClassAttributes classAttribute, SimCode simCode
70907156
<<
70917157
min[<%i0%>] = <%crefAttributes(name)%>.min;
70927158
max[<%i0%>] = <%crefAttributes(name)%>.max;
7093-
nominal[<%i0%>] = <%crefAttributes(name)%>.nominal;
7159+
nominal[<%i0%>] = getNominalFromScalarIdx(data->simulationInfo, data->modelData, VAR_KIND_VARIABLE, <%crefIndexWithComment(name)%>);
70947160
useNominal[<%i0%>] = <%crefAttributes(name)%>.useNominal;
70957161
name[<%i0%>] =(char *) <%crefVarInfo(name)%>.name;
70967162
<%match type_ case T_REAL() then

OMCompiler/Compiler/Template/CodegenCFunctions.tpl

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7909,6 +7909,17 @@ template crefVarInfo(ComponentRef cr)
79097909
'data->modelData-><%varArrayName(var)%>Data[<%index%>] /* <%crefCComment(var, crefStrNoUnderscore(name))%> */ .info'
79107910
end crefVarInfo;
79117911

7912+
template crefVarDimension(ComponentRef cr)
7913+
"C code to access dimension attribute of component reference"
7914+
::=
7915+
match cref2simvar(cr, getSimCode())
7916+
case var as SIMVAR(__) then
7917+
if intLt(index,0) then
7918+
error(sourceInfo(), 'crefVarDimension got negative index=<%index%> for <%crefStr(name)%>')
7919+
else
7920+
'data->modelData-><%varArrayName(var)%>Data[<%index%>] /* <%crefCComment(var, crefStrNoUnderscore(name))%> */ .dimension'
7921+
end crefVarDimension;
7922+
79127923
template initializeStaticLSVars(list<SimVar> vars, Integer index)
79137924
::=
79147925
let len = listLength(vars)
@@ -7925,7 +7936,7 @@ template initializeStaticLSVars(list<SimVar> vars, Integer index)
79257936
linearSystemData->min[i] = -DBL_MAX;
79267937
linearSystemData->max[i] = DBL_MAX;
79277938
} else {
7928-
linearSystemData->nominal[i] = data->modelData->realVarsData[indices[i]].attribute.nominal;
7939+
linearSystemData->nominal[i] = getNominalFromScalarIdx(data->simulationInfo, data->modelData, VAR_KIND_VARIABLE, indices[i]);
79297940
linearSystemData->min[i] = data->modelData->realVarsData[indices[i]].attribute.min;
79307941
linearSystemData->max[i] = data->modelData->realVarsData[indices[i]].attribute.max;
79317942
}
@@ -7956,7 +7967,7 @@ template crefAttributes(ComponentRef cr)
79567967
case var as SIMVAR(index=-1, varKind=JAC_VAR()) then "dummyREAL_ATTRIBUTE"
79577968
case var as SIMVAR(__) then
79587969
if intLt(index,0) then error(sourceInfo(), 'varAttributes got negative index=<%index%> for <%crefStr(name)%>') else
7959-
'data->modelData-><%varArrayName(var)%>Data[<%index%>].attribute /* <%crefCComment(var, crefStrNoUnderscore(name))%> */'
7970+
'data->modelData-><%varArrayName(var)%>Data[<%index%>] /* <%crefCComment(var, crefStrNoUnderscore(name))%> */ .attribute'
79607971
end crefAttributes;
79617972

79627973
template typeCastContext(Context context, Type ty)

OMCompiler/Compiler/Template/CodegenFMU.tpl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3351,7 +3351,7 @@ template ScalarVariableTypeFMU(String attrstr, String unit, String displayUnit,
33513351
<%attrstr%>.max = <%optInitValFMU(maxValue,"DBL_MAX")%>;
33523352
<%attrstr%>.fixed = <%if isFixed then 1 else 0%>;
33533353
<%attrstr%>.useNominal = <%if nominalValue then 1 else 0%>;
3354-
<%attrstr%>.nominal = <%optInitValFMU(nominalValue,"1.0")%>;
3354+
put_real_element(<%optInitValFMU(nominalValue,"1.0")%>, 0, &<%attrstr%>.nominal);
33553355
put_real_element(<%optInitValFMU(startValue,"0.0")%>, 0, &<%attrstr%>.start);
33563356
>>
33573357
case T_INTEGER(__) then

OMCompiler/SimulationRuntime/c/linearization/linearize.cpp

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
#include "util/omc_file.h"
3333
#include "simulation_data.h"
3434
#include "openmodelica_func.h"
35+
#include "simulation/arrayIndex.h"
3536
#include "simulation/solver/external_input.h"
3637
#include "simulation/options.h"
3738
#include "simulation/solver/model_help.h"
@@ -199,8 +200,9 @@ int functionJacAC_num(DATA* data, threadData_t *threadData, double *matrixA, dou
199200
x = data->localData[0]->realVars;
200201

201202
/* use actually value for xScaling */
202-
for (i=0;i<size_A;i++){
203-
xScaling[i] = fmax(data->modelData->realVarsData[i].attribute.nominal,fabs(x[i]));
203+
for (i = 0; i < size_A; i++) {
204+
modelica_real nominal = getNominalFromScalarIdx(data->simulationInfo, data->modelData, VAR_KIND_STATE, i);
205+
xScaling[i] = fmax(nominal, fabs(x[i]));
204206
}
205207

206208
/* solverData->f1 must be set outside this function based on x */

OMCompiler/SimulationRuntime/c/moo/hessian_finite_diff.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,8 @@
3333
#include <iomanip>
3434
#include <vector>
3535

36+
#include "simulation/arrayIndex.h"
37+
3638
#include "hessian_finite_diff.h"
3739

3840
/**
@@ -314,7 +316,7 @@ void eval_hessian_fwd_differences_fast(
314316
int realVarsIndex = (col < nStates ? col : u_indices[col - nStates]);
315317

316318
/* create perturbation size based on nominals and current entry */
317-
const modelica_real nom = data->modelData->realVarsData[realVarsIndex].attribute.nominal;
319+
const modelica_real nom = getNominalFromScalarIdx(data->simulationInfo, data->modelData, VAR_KIND_VARIABLE, realVarsIndex);
318320
c1_h += log(1.0 + fmax(ws_oldX[col], nom));
319321
}
320322

OMCompiler/SimulationRuntime/c/moo/strategies.cpp

Lines changed: 16 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,8 @@
2828
*
2929
*/
3030

31+
#include "simulation/arrayIndex.h"
32+
3133
#include "evaluations.h"
3234

3335
#include "strategies.h"
@@ -348,31 +350,31 @@ std::shared_ptr<NLP::Scaling> NominalScalingFactory::operator()(const GDOP::GDOP
348350
auto r_size = info.r_size;
349351
auto fg_size = f_size + g_size;
350352

351-
auto real_vars_data = info.data->modelData->realVarsData;
352-
353353
auto has_mayer = gdop.get_problem().pc->has_mayer;
354354
auto has_lagrange = gdop.get_problem().pc->has_lagrange;
355355

356356
if (has_mayer && has_lagrange) {
357-
f_nominal = (real_vars_data[info.index_mayer_real_vars].attribute.nominal +
358-
real_vars_data[info.index_lagrange_real_vars].attribute.nominal) / 2;
357+
const modelica_real nominal_mayer = getNominalFromScalarIdx(info.data->simulationInfo, info.data->modelData, VAR_KIND_VARIABLE, info.index_mayer_real_vars);
358+
const modelica_real nominal_lagrange = getNominalFromScalarIdx(info.data->simulationInfo, info.data->modelData, VAR_KIND_VARIABLE, info.index_lagrange_real_vars);
359+
360+
f_nominal = (nominal_mayer + nominal_lagrange) / 2;
359361
}
360362
else if (has_lagrange) {
361-
f_nominal = real_vars_data[info.index_lagrange_real_vars].attribute.nominal;
363+
f_nominal = getNominalFromScalarIdx(info.data->simulationInfo, info.data->modelData, VAR_KIND_VARIABLE, info.index_lagrange_real_vars);
362364
}
363365
else if (has_mayer) {
364-
f_nominal = real_vars_data[info.index_mayer_real_vars].attribute.nominal;
366+
f_nominal = getNominalFromScalarIdx(info.data->simulationInfo, info.data->modelData, VAR_KIND_VARIABLE, info.index_mayer_real_vars);
365367
}
366368

367369
// (x, u)_(t_node)
368370
for (int node = 0; node < 1 + gdop.get_mesh().node_count; node++) {
369371
for (int x = 0; x < x_size; x++) {
370-
x_nominal[node * xu_size + x] = real_vars_data[x].attribute.nominal;
372+
x_nominal[node * xu_size + x] = getNominalFromScalarIdx(info.data->simulationInfo, info.data->modelData, VAR_KIND_VARIABLE, x);
371373
}
372374

373375
for (int u = 0; u < u_size; u++) {
374376
int u_real_vars = info.u_indices_real_vars[u];
375-
x_nominal[node * xu_size + x_size + u] = real_vars_data[u_real_vars].attribute.nominal;
377+
x_nominal[node * xu_size + x_size + u] = getNominalFromScalarIdx(info.data->simulationInfo, info.data->modelData, VAR_KIND_VARIABLE, u_real_vars);
376378
}
377379
}
378380

@@ -382,18 +384,18 @@ std::shared_ptr<NLP::Scaling> NominalScalingFactory::operator()(const GDOP::GDOP
382384
}
383385

384386
for (int g = 0; g < g_size; g++) {
385-
g_nominal[f_size + node * fg_size + g] = real_vars_data[info.index_g_real_vars + g].attribute.nominal;
387+
g_nominal[f_size + node * fg_size + g] = getNominalFromScalarIdx(info.data->simulationInfo, info.data->modelData, VAR_KIND_VARIABLE, info.index_g_real_vars + g);
386388
}
387389
}
388390

389391
for (int r = 0; r < r_size; r++) {
390-
g_nominal[gdop.get_off_fg_total() + r] = real_vars_data[info.index_r_real_vars + r].attribute.nominal;
392+
g_nominal[gdop.get_off_fg_total() + r] = getNominalFromScalarIdx(info.data->simulationInfo, info.data->modelData, VAR_KIND_VARIABLE, info.index_r_real_vars + r);
391393
}
392394

393395
// artificial constraints are O(u)
394396
for (int u = 0; u < info.u_size; u++) {
395397
int u_real_vars = info.u_indices_real_vars[u];
396-
g_nominal[gdop.get_off_fgr_total() + u] = real_vars_data[u_real_vars].attribute.nominal;
398+
g_nominal[gdop.get_off_fgr_total() + u] = getNominalFromScalarIdx(info.data->simulationInfo, info.data->modelData, VAR_KIND_VARIABLE, u_real_vars);
397399
}
398400

399401
return std::make_shared<NLP::NominalScaling>(std::move(x_nominal), std::move(g_nominal), f_nominal);
@@ -405,7 +407,9 @@ GDOP::Strategies default_strategies(InfoGDOP& info, GDOP::Problem& problem, bool
405407

406408
// TODO: do add simulation_tolerance factor here?
407409
FixedVector<f64> verifier_tolerances(info.x_size);
408-
for (int x = 0; x < info.x_size; x++) { verifier_tolerances[x] = 1e-4 * info.data->modelData->realVarsData[x].attribute.nominal; }
410+
for (int x = 0; x < info.x_size; x++) {
411+
verifier_tolerances[x] = 1e-4 * getNominalFromScalarIdx(info.data->simulationInfo, info.data->modelData, VAR_KIND_VARIABLE, x);
412+
}
409413

410414
auto scaling_factory = std::make_shared<NominalScalingFactory>(info);
411415
auto emitter = std::make_shared<MatEmitter>(MatEmitter(info));

0 commit comments

Comments
 (0)