Skip to content

Commit af440bd

Browse files
rfrankeadrpoclaude
authored
[Cpp,FMI] extend FMI export with optional custom annotations (#15727)
* [Cpp,FMI] extend FMI export with optional custom annotations This is particularly interesting for applications that go beyond simulation, like optimization, to specify additional things like constraints via custom annotations in a Modelica model. - new flag --fmiExtraAnnotations=<regex for annotations of interest> - while building the Cpp FMU, CevalScriptBackend.callBuildModelFMU dumps the model instance JSON (<prefix>_modelInstance.json), guarded by the flag - a standalone jq filter Compiler/scripts/filter-annotations.jq (installed to share/omc/scripts) selects the annotations of interest - FMI export adds file extra/org.openmodelica/modelAnnotations.json to the FMU This keeps codegen free of an NFApi dependency and moves the jq filter out of the template for better portability (e.g. paths with spaces on Windows/OMDev). Note: adds jq as a runtime dependency of the Cpp FMU export when --fmiExtraAnnotations is used. Co-authored-by: rfranke <rfranke@users.noreply.github.com> * [OMDev] bump runtime CXX standard to c++17 for std::string_view Makefile.omdev.mingw still forced -std=c++11, breaking the OMDev/MinGW build after std::string_view was introduced in systemimplmisc.cpp (f643f51). CMake already enforces C++17, so match it here. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Adrian Pop <adrian.pop@liu.se> Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
1 parent ac418d2 commit af440bd

12 files changed

Lines changed: 329 additions & 8 deletions

File tree

OMCompiler/Compiler/Makefile.in

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ CORBAHOME = @CORBAHOME@
2929

3030
PROG = omc
3131

32-
SCRIPT_FILES = openmodelica.lefty default_profiling.xsl replace-startValue.sh replace-startValue.xsl simcodedump.xsl ngspicetoModelica.py
32+
SCRIPT_FILES = openmodelica.lefty default_profiling.xsl replace-startValue.sh replace-startValue.xsl simcodedump.xsl ngspicetoModelica.py filter-annotations.jq
3333

3434
SUBDIRS = FrontEndCpp runtime Script
3535

OMCompiler/Compiler/Makefile.omdev.mingw

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ LIBSOCKET = -lwsock32
1616

1717
SHELL = /bin/sh
1818

19-
SCRIPT_FILES = Compile.bat Prompt.bat openmodelica.lefty default_profiling.xsl replace-startValue.* simcodedump.xsl ngspicetoModelica.py
19+
SCRIPT_FILES = Compile.bat Prompt.bat openmodelica.lefty default_profiling.xsl replace-startValue.* simcodedump.xsl ngspicetoModelica.py filter-annotations.jq
2020

2121
SUBDIRS = runtime Script
2222

OMCompiler/Compiler/Script/CevalScriptBackend.mo

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4455,6 +4455,11 @@ algorithm
44554455
dir := fmutmp+"/sources/";
44564456

44574457
if Config.simCodeTarget() == "Cpp" then
4458+
// dump modelInstance.json so the FMU makefile can filter out the
4459+
// requested extra annotations (see flag --fmiExtraAnnotations)
4460+
if Flags.getConfigString(Flags.FMI_EXTRA_ANNOTATIONS) <> "" then
4461+
System.writeFile(filenameprefix + "_modelInstance.json", ValuesUtil.extractValueString(NFApi.getModelInstance(className, className, "", true)));
4462+
end if;
44584463
System.removeDirectory("binaries");
44594464
for platform in platforms loop
44604465
if platform == "dynamic" or platform == "static" then

OMCompiler/Compiler/Template/CodegenFMUCpp.tpl

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,8 @@ case SIMCODE(modelInfo=modelInfo as MODELINFO(__)) then
108108
let numBoolVars = numBoolvars(modelInfo)
109109
let numStringVars = numStringvars(modelInfo)
110110

111+
let extraAnnotations = Flags.getConfigString(FMI_EXTRA_ANNOTATIONS)
112+
111113
let _ = FlagsUtil.set(Flags.HARDCODED_START_VALUES, true)
112114
let cpp = CodegenCpp.translateModel(simCode)
113115
let()= textFile(fmuWriteOutputHeaderFile(simCode , &extraFuncs , &extraFuncsDecl, ""),'OMCpp<%fileNamePrefix%>WriteOutput.h')
@@ -116,7 +118,7 @@ case SIMCODE(modelInfo=modelInfo as MODELINFO(__)) then
116118
let()= textFile((if isFMIVersion10(FMUVersion) then CodegenCppInit.modelInitXMLFile(simCode, numRealVars, numIntVars, numBoolVars, numStringVars, FMUVersion, FMUType, guid, true, "cpp-runtime", complexStartExpressions, stateDerVectorName) else
117119
CodegenFMU.fmuModelDescriptionFile(simCode, guid, FMUVersion, FMUType, sourceFiles)), 'modelDescription.xml')
118120
let()= textFile(fmudeffile(simCode, FMUVersion), '<%fileNamePrefix%>.def')
119-
let()= textFile(fmuMakefile(target,simCode, extraFuncs, extraFuncsDecl, "", FMUVersion, "", "", "", ""), '<%fileNamePrefix%>_FMU.makefile')
121+
let()= textFile(fmuMakefile(target, simCode, extraFuncs, extraFuncsDecl, "", FMUVersion, "", "", "", "", extraAnnotations), '<%fileNamePrefix%>_FMU.makefile')
120122
let()= textFile(fmuCalcHelperMainfile(simCode), 'OMCpp<%fileNamePrefix%>CalcHelperMain.cpp')
121123
let _ = FlagsUtil.set(Flags.HARDCODED_START_VALUES, false)
122124

@@ -708,7 +710,7 @@ case SIMCODE(modelInfo=MODELINFO(), modelStructure=fmiModelStructure) then
708710
end directionalDerivativeFunction;
709711

710712
template fmuMakefile(String target, SimCode simCode, Text& extraFuncs, Text& extraFuncsDecl, Text extraFuncsNamespace, String FMUVersion, String additionalLinkerFlags_GCC,
711-
String additionalLinkerFlags_MSVC, String additionalCFlags_GCC, String additionalCFlags_MSVC)
713+
String additionalLinkerFlags_MSVC, String additionalCFlags_GCC, String additionalCFlags_MSVC, String extraAnnotations)
712714
"Generates the contents of the makefile for the simulation case. Copy libexpat & correct linux fmu"
713715
::=
714716
match getGeneralTarget(target)
@@ -907,14 +909,22 @@ case SIMCODE(modelInfo=MODELINFO(__), makefileParams=MAKEFILE_PARAMS(__), simula
907909
<%\t%>zip -r "<%fmuTargetName%>.fmu" modelDescription.xml binaries sources
908910
endif
909911
endif
912+
ifneq ("<%extraAnnotations%>","")
913+
<%\t%><%mkdir%> -p extra/org.openmodelica
914+
<%\t%>jq --arg regex "<%extraAnnotations%>" -f "$(OMHOME)/share/omc/scripts/filter-annotations.jq" <%fileNamePrefix%>_modelInstance.json > extra/org.openmodelica/modelAnnotations.json
915+
ifeq ($(ZIP_FMU),ON)
916+
<%\t%>zip -ur "<%fmuTargetName%>.fmu" extra
917+
endif
918+
endif
910919

911920
ifeq ($(ZIP_FMU),OFF)
912921
<%\t%>rm -f OMCpp<%fileNamePrefix%>* <%fileNamePrefix%>_FMU.* <%fileNamePrefix%>.def <%fileNamePrefix%>.sh <%fileNamePrefix%>.bat <%fileNamePrefix%>.makefile <%fileNamePrefix%>_init.xml
922+
<%\t%>rm -f <%fileNamePrefix%>_modelInstance.json
913923
endif
914924

915925
clean:
916926
<%\t%>rm -f OMCpp<%fileNamePrefix%>* <%fileNamePrefix%>_FMU.* <%fileNamePrefix%>.def <%fileNamePrefix%>.sh <%fileNamePrefix%>.bat <%fileNamePrefix%>.makefile <%fileNamePrefix%>_init.xml
917-
<%\t%>rm -rf modelDescription.xml binaries sources documentation
927+
<%\t%>rm -rf modelDescription.xml binaries sources documentation extra <%fileNamePrefix%>_modelInstance.json
918928

919929
>>
920930
end fmuMakefile;

OMCompiler/Compiler/Template/CodegenFMUCppHpcom.tpl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -152,7 +152,7 @@ template fmuMakefile(String target, SimCode simCode, Text& extraFuncs, Text& ext
152152

153153
<<
154154
<%CodegenCppHpcom.getAdditionalMakefileFlags(additionalCFlags_GCC, additionalCFlags_MSVC, additionalLinkerFlags_GCC, additionalLinkerFlags_MSVC)%>
155-
<%CodegenFMUCpp.fmuMakefile(target, simCode, extraFuncs, extraFuncsDecl, extraFuncsNamespace, FMUVersion, additionalLinkerFlags_GCC, additionalLinkerFlags_MSVC, additionalCFlags_GCC, additionalCFlags_MSVC)%>
155+
<%CodegenFMUCpp.fmuMakefile(target, simCode, extraFuncs, extraFuncsDecl, extraFuncsNamespace, FMUVersion, additionalLinkerFlags_GCC, additionalLinkerFlags_MSVC, additionalCFlags_GCC, additionalCFlags_MSVC, "")%>
156156
>>
157157
end fmuMakefile;
158158

OMCompiler/Compiler/Template/SimCodeTV.mo

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4172,6 +4172,7 @@ package Flags
41724172
constant ConfigFlag OBFUSCATE;
41734173
constant ConfigFlag MAX_SIZE_LINEARIZATION;
41744174
constant ConfigFlag NEW_BACKEND;
4175+
constant ConfigFlag FMI_EXTRA_ANNOTATIONS;
41754176

41764177
function isSet
41774178
input DebugFlag inFlag;

OMCompiler/Compiler/Util/Flags.mo

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1404,6 +1404,9 @@ constant ConfigFlag EXECUTE_COMMAND = CONFIG_FLAG(162, "cmd",
14041404
constant ConfigFlag MOO_DYNAMIC_OPTIMIZATION = CONFIG_FLAG(163, "moo",
14051405
NONE(), EXTERNAL(), BOOL_FLAG(false), NONE(),
14061406
Gettext.gettext("Generate code for dynamic optimization library MOO."));
1407+
constant ConfigFlag FMI_EXTRA_ANNOTATIONS = CONFIG_FLAG(164, "fmiExtraAnnotations",
1408+
NONE(), EXTERNAL(), STRING_FLAG(""), NONE(),
1409+
Gettext.gettext("Export annotations matching the given regex to extra/org.openmodelica/modelAnnotations.json."));
14071410

14081411
function getFlags
14091412
"Loads the flags with getGlobalRoot. Assumes flags have been loaded."

OMCompiler/Compiler/Util/FlagsUtil.mo

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -429,7 +429,8 @@ constant list<Flags.ConfigFlag> allConfigFlags = {
429429
Flags.CAUSALIZE_DAE_MODE,
430430
Flags.SIM_CODE_SCALARIZE,
431431
Flags.EXECUTE_COMMAND,
432-
Flags.MOO_DYNAMIC_OPTIMIZATION
432+
Flags.MOO_DYNAMIC_OPTIMIZATION,
433+
Flags.FMI_EXTRA_ANNOTATIONS
433434
};
434435

435436
public function new

OMCompiler/Compiler/runtime/Makefile.omdev.mingw

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,6 @@ SHELL = /bin/sh
4848
CC = gcc
4949
CXX = g++
5050
override CFLAGS += $(CORBA_C_CLFAGS) $(USE_METIS) -Werror=implicit-function-declaration -Wall -Wno-unused-variable -I$(OMC_CONFIG_INC) -I$(top_builddir)/SimulationRuntime/c -I$(top_builddir)/SimulationRuntime/c/simulation/results -I$(top_builddir)/SimulationRuntime/c/util -I$(top_builddir)/SimulationRuntime/c/meta -I$(top_builddir)/SimulationRuntime/c/meta/gc $(CORBAINCL) $(GCINCLUDE) -I$(FMIINCLUDE) -I$(CJSONINCLUDE) -I$(GRAPHINCLUDE) -I$(SQLITE3INCLUDE) -I$(ZMQINCLUDE) -I"$(TOP_DIR)/3rdParty/zlib" -I"$(TOP_DIR)/3rdParty/libffi/install/include/" -DWIN32_LEAN_AND_MEAN
51-
override CXXFLAGS += -std=c++11 $(CFLAGS)
51+
override CXXFLAGS += -std=c++17 $(CFLAGS)
5252

5353
include Makefile.common
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
# Filter annotations of interest out of a modelInstance.json file produced by
2+
# the OpenModelica getModelInstance API. Used by the Cpp FMU export when the
3+
# --fmiExtraAnnotations=<regex> flag is set.
4+
#
5+
# Usage:
6+
# jq --arg regex "__Optimization|__Estimation" -f filter-annotations.jq Model_modelInstance.json > modelAnnotations.json
7+
def keep_annotation:
8+
if type == "object" then
9+
if (.prefixes? | type) == "object" and (.prefixes.outer? // false) then
10+
null
11+
else
12+
(
13+
. as $obj
14+
# place dims first to know them when parsing a name or type in one pass
15+
# | reduce ($obj | keys_unsorted[]) as $k
16+
| reduce ((if has("dims") then {dims} else {} end)
17+
+ with_entries(select(.key != "dims")) | keys_unsorted[]) as $k
18+
({};
19+
if $k | test($regex) then
20+
. + {($k): $obj[$k]}
21+
elif ($k == "name" or $k == "restriction" or $k == "dims")
22+
and ($obj | any(.. | objects; .annotation? | objects | keys | any(test($regex)))) then
23+
. + if $k == "dims" then {($k): $obj[$k]["typed"]} else {($k): $obj[$k]} end
24+
else
25+
($obj[$k] | keep_annotation) as $v
26+
| if $v == null or $v == {} or $v == [] then
27+
.
28+
else
29+
. + {($k): $v}
30+
end
31+
end
32+
)
33+
)
34+
| if . == {} then null else . end
35+
end
36+
elif type == "array" then
37+
map(keep_annotation)
38+
| map(select(. != null and . != {} and . != []))
39+
| if length == 0 then null else . end
40+
else null
41+
end;
42+
43+
keep_annotation

0 commit comments

Comments
 (0)