1+
2+ #include " fmu4cpp/fmu_base.hpp"
3+ #include " fmu4cpp/lib_info.hpp"
4+ #include " fmu4cpp/time.hpp"
5+ #include " fmu4cpp/util.hpp"
6+
7+ #include < sstream>
8+
9+ using namespace fmu4cpp ;
10+
11+ std::string fmu_base::make_description () const {
12+
13+ const model_info m = get_model_info ();
14+ std::stringstream ss;
15+ ss << R"( <?xml version="1.0" encoding="UTF-8"?>)"
16+ << " \n "
17+ << R"( <fmiModelDescription fmiVersion="2.0")"
18+ << " modelName=\" " << m.modelName << " \" "
19+ << " guid=\" " << guid () << " \" "
20+ << " generationTool=\" fmu4cpp"
21+ << " v" << to_string (library_version ()) << " \" "
22+ << " generationDateAndTime=\" " << now () << " \" "
23+ << " description=\" " << m.description << " \" "
24+ << " author=\" " << m.author << " \" "
25+ << " variableNamingConvention=\" " << m.variableNamingConvention << " \" "
26+ << " >\n " ;
27+
28+ ss << " \t " << std::boolalpha
29+ << " <CoSimulation needsExecutionTool=\" " << m.needsExecutionTool << " \" "
30+ << " modelIdentifier=\" " << m.modelIdentifier << " \" "
31+ << " canHandleVariableCommunicationStepSize=\" " << m.canHandleVariableCommunicationStepSize << " \" "
32+ << " canBeInstantiatedOnlyOncePerProcess=\" " << m.canBeInstantiatedOnlyOncePerProcess << " \" "
33+ << " canGetAndSetFMUstate=\" " << m.canGetAndSetFMUstate << " \" "
34+ << " canSerializeFMUstate=\" " << m.canSerializeFMUstate << " \" "
35+ << R"( canNotUseMemoryManagementFunctions="true")"
36+ << " >\n "
37+ << " \t </CoSimulation>"
38+ << " \n " ;
39+
40+ if (!m.vendorAnnotations .empty ()) {
41+ ss << " \t <VendorAnnotations>\n " ;
42+ for (const auto &annotation: m.vendorAnnotations ) {
43+ std::string indentedAnnotation = indent_multiline_string (annotation, 3 );
44+ ss << indentedAnnotation << " \n " ;
45+ }
46+ ss << " \t </VendorAnnotations>\n " ;
47+ }
48+
49+ ss << " \t <ModelVariables>\n " ;
50+
51+ const auto allVars = [&] {
52+ auto allVars = collect (integers_, reals_, booleans_, strings_);
53+ std::sort (allVars.begin (), allVars.end (), [](const VariableBase *v1, const VariableBase *v2) {
54+ return v1->index () < v2->index ();
55+ });
56+ return allVars;
57+ }();
58+
59+ for (const auto &v: allVars) {
60+ const auto variability = v->variability ();
61+ const auto initial = v->initial ();
62+ const auto annotations = v->getAnnotations ();
63+ ss << " \t\t <!--"
64+ << " index=" << v->index () << " -->\n "
65+ << " \t\t <ScalarVariable name=\" "
66+ << v->name () << " \" valueReference=\" " << v->value_reference () << " \" "
67+ << " causality=\" " << to_string (v->causality ()) << " \" " ;
68+ if (variability) {
69+ ss << " variability=\" " << to_string (*variability) << " \" " ;
70+ }
71+ if (initial) {
72+ ss << " initial=\" " << to_string (*initial) << " \" " ;
73+ }
74+ ss << " >\n " ;
75+ if (auto i = dynamic_cast <const IntVariable *>(v)) {
76+ ss << " \t\t\t <Integer" ;
77+ if (requires_start (*v)) {
78+ ss << " start=\" " << i->get () << " \" " ;
79+ }
80+ } else if (auto r = dynamic_cast <const RealVariable *>(v)) {
81+ ss << " \t\t\t <Real" ;
82+ if (requires_start (*v)) {
83+ ss << " start=\" " << r->get () << " \" " ;
84+ }
85+ const auto min = r->getMin ();
86+ const auto max = r->getMax ();
87+ if (min && max) {
88+ ss << " min=\" " << *min << " \" max=\" " << *max << " \" " ;
89+ }
90+ } else if (auto s = dynamic_cast <const StringVariable *>(v)) {
91+ ss << " \t\t\t <String" ;
92+ if (requires_start (*v)) {
93+ ss << " start=\" " << s->get () << " \" " ;
94+ }
95+ } else if (auto b = dynamic_cast <const BoolVariable *>(v)) {
96+ ss << " \t\t\t <Boolean" ;
97+ if (requires_start (*v)) {
98+ ss << " start=\" " << b->get () << " \" " ;
99+ }
100+ }
101+ ss << " />\n " ;
102+ if (!annotations.empty ()) {
103+ ss << " \t\t\t <Annotations>\n " ;
104+ for (const auto &annotation: annotations) {
105+ std::string indentedAnnotation = indent_multiline_string (annotation, 4 );
106+ ss << indentedAnnotation << " \n " ;
107+ }
108+ ss << " \t\t\t </Annotations>\n " ;
109+ }
110+ ss << " \t\t </ScalarVariable>"
111+ << " \n " ;
112+ }
113+
114+ ss << " \t </ModelVariables>\n " ;
115+
116+ ss << " \t <ModelStructure>\n " ;
117+
118+ const auto unknowns = collect (integers_, reals_, booleans_, strings_, [](auto &v) {
119+ return v.causality () == causality_t ::OUTPUT;
120+ });
121+
122+ if (!unknowns.empty ()) {
123+ ss << " \t\t <Outputs>\n " ;
124+ for (const auto &v: unknowns) {
125+ ss << " \t\t\t <Unknown index=\" " << v->index () << " \" " ;
126+ if (const auto deps = v->getDependencies (); !deps.empty ()) {
127+ ss << " dependencies=\" " ;
128+ for (unsigned i = 0 ; i < deps.size (); i++) {
129+ const auto &depName = deps[i];
130+ const auto dep = std::find_if (allVars.begin (), allVars.end (), [depName](const auto &v) {
131+ return v->name () == depName;
132+ });
133+ if (dep == allVars.end ()) {
134+ throw std::runtime_error (" Unknown dependency: " + depName);
135+ }
136+ ss << (*dep)->index ();
137+ if (i != deps.size () - 1 ) {
138+ ss << " " ;
139+ }
140+ }
141+ ss << " \" " ;
142+ }
143+ ss << " />\n " ;
144+ }
145+ ss << " \t\t </Outputs>\n " ;
146+ }
147+
148+ const auto initialUnknowns = collect (integers_, reals_, booleans_, strings_, [](auto &v) {
149+ return (v.causality () == causality_t ::OUTPUT && v.initial () == initial_t ::APPROX || v.initial () == initial_t ::CALCULATED) || v.causality () == causality_t ::CALCULATED_PARAMETER;
150+ });
151+ if (!initialUnknowns.empty ()) {
152+ ss << " \t\t <InitialUnknowns>\n " ;
153+ for (const auto &v: initialUnknowns) {
154+ ss << " \t\t\t <Unknown index=\" " << v->index () << " \" " ;
155+ ss << " />\n " ;
156+ }
157+ ss << " \t\t </InitialUnknowns>\n " ;
158+ }
159+
160+ ss << " \t </ModelStructure>\n " ;
161+
162+ ss << " </fmiModelDescription>\n " ;
163+
164+ return ss.str ();
165+ }
0 commit comments