Skip to content

Commit 92b2840

Browse files
committed
Merge branch 'master' into vanderpol
2 parents bba5070 + 737335e commit 92b2840

11 files changed

Lines changed: 481 additions & 403 deletions

File tree

export/include/fmu4cpp/fmu_base.hpp

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
#include "fmu_variable.hpp"
1414
#include "logger.hpp"
1515
#include "model_info.hpp"
16+
#include "status.hpp"
1617

1718
#include <filesystem>
1819

@@ -197,9 +198,7 @@ namespace fmu4cpp {
197198

198199
[[nodiscard]] std::string guid() const;
199200

200-
[[nodiscard]] std::string make_description_v2() const;
201-
202-
[[nodiscard]] std::string make_description_v3() const;
201+
[[nodiscard]] std::string make_description() const;
203202

204203
void log(const fmiStatus s, const std::string &message) const {
205204
if (data_.fmiLogger) {

export/src/CMakeLists.txt

Lines changed: 17 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -26,44 +26,45 @@ set(publicHeaders
2626
"fmu4cpp/fmu_base.hpp"
2727
"fmu4cpp/fmu_except.hpp"
2828
"fmu4cpp/fmu_variable.hpp"
29-
)
29+
)
3030

3131
set(privateHeaders
3232
"fmu4cpp/hash.hpp"
3333
"fmu4cpp/time.hpp"
34-
)
34+
"fmu4cpp/util.hpp"
35+
)
3536

3637
set(sources
3738
"fmu4cpp/fmu_base.cpp"
3839
"fmu4cpp/fmu_variable.cpp"
39-
)
40+
)
4041

4142
set(fmi2HeadersFull)
42-
foreach(h IN LISTS fmi2Headers)
43+
foreach (h IN LISTS fmi2Headers)
4344
list(APPEND fmi2HeadersFull "${CMAKE_CURRENT_SOURCE_DIR}/../include/${h}")
44-
endforeach()
45+
endforeach ()
4546

4647
set(fmi3HeadersFull)
47-
foreach(h IN LISTS fmi3Headers)
48+
foreach (h IN LISTS fmi3Headers)
4849
list(APPEND fmi3HeadersFull "${CMAKE_CURRENT_SOURCE_DIR}/../include/${h}")
49-
endforeach()
50+
endforeach ()
5051

5152
set(publicHeadersFull)
52-
foreach(h IN LISTS publicHeaders)
53+
foreach (h IN LISTS publicHeaders)
5354
list(APPEND publicHeadersFull "${CMAKE_CURRENT_SOURCE_DIR}/../include/${h}")
54-
endforeach()
55+
endforeach ()
5556

5657
set(privateHeadersFull)
57-
foreach(h IN LISTS privateHeaders)
58+
foreach (h IN LISTS privateHeaders)
5859
list(APPEND privateHeadersFull "${CMAKE_CURRENT_SOURCE_DIR}/${h}")
59-
endforeach()
60+
endforeach ()
6061

6162
add_library(fmu4cpp_base OBJECT
6263
"${lib_info}"
6364
"${publicHeadersFull}"
6465
"${privateHeadersFull}"
6566
"${sources}"
66-
)
67+
)
6768
target_compile_features(fmu4cpp_base PRIVATE "cxx_std_17")
6869
set_target_properties(fmu4cpp_base PROPERTIES POSITION_INDEPENDENT_CODE ON)
6970
target_include_directories(fmu4cpp_base
@@ -75,7 +76,8 @@ target_include_directories(fmu4cpp_base
7576

7677
add_library(fmu4cpp_fmi2 OBJECT
7778
"${fmi2HeadersFull}"
78-
"fmu4cpp/fmi2.cpp"
79+
"fmu4cpp/fmi2/fmi2.cpp"
80+
"fmu4cpp/fmi2/fmi2_description.cpp"
7981
)
8082
target_compile_features(fmu4cpp_fmi2 PRIVATE "cxx_std_17")
8183
set_target_properties(fmu4cpp_fmi2 PROPERTIES POSITION_INDEPENDENT_CODE ON)
@@ -88,7 +90,8 @@ target_include_directories(fmu4cpp_fmi2
8890

8991
add_library(fmu4cpp_fmi3 OBJECT
9092
"${fmi3HeadersFull}"
91-
"fmu4cpp/fmi3.cpp"
93+
"fmu4cpp/fmi3/fmi3.cpp"
94+
"fmu4cpp/fmi3/fmi3_description.cpp"
9295
)
9396
target_compile_features(fmu4cpp_fmi3 PRIVATE "cxx_std_17")
9497
set_target_properties(fmu4cpp_fmi3 PROPERTIES POSITION_INDEPENDENT_CODE ON)
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ const char *fmi2GetVersion(void) {
7878

7979
FMI2_Export void write_description(const char *location) {
8080
const auto instance = fmu4cpp::createInstance({});
81-
const auto xml = instance->make_description_v2();
81+
const auto xml = instance->make_description();
8282
std::ofstream of(location);
8383
of << xml;
8484
of.close();
Lines changed: 165 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,165 @@
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+
}
Lines changed: 21 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
#include "fmu4cpp/fmu_base.hpp"
1010
#include "fmu4cpp/fmu_except.hpp"
1111
#include "fmu4cpp/logger.hpp"
12+
#include "fmu4cpp/status.hpp"
1213

1314
namespace {
1415

@@ -60,7 +61,7 @@ namespace {
6061
Fmi3Component(std::unique_ptr<fmu4cpp::fmu_base> slave, std::unique_ptr<fmi3Logger> logger)
6162
: state(State::Instantiated),
6263
slave(std::move(slave)),
63-
logger(std::move(logger)) { }
64+
logger(std::move(logger)) {}
6465

6566
State state;
6667
std::unique_ptr<fmu4cpp::fmu_base> slave;
@@ -69,28 +70,28 @@ namespace {
6970

7071
#define FMU_TYPE(type) fmi3##type
7172

72-
#define NOT_IMPLEMENTED_GETTER(type) \
73-
fmi3Status fmi3Get##type( \
74-
fmi3Instance c, \
75-
const fmi3ValueReference vr[], \
76-
size_t nValueReferences, \
77-
FMU_TYPE(type) values[], \
78-
size_t nValues) { \
79-
const auto component = static_cast<Fmi3Component *>(c); \
73+
#define NOT_IMPLEMENTED_GETTER(type) \
74+
fmi3Status fmi3Get##type( \
75+
fmi3Instance c, \
76+
const fmi3ValueReference vr[], \
77+
size_t nValueReferences, \
78+
FMU_TYPE(type) values[], \
79+
size_t nValues) { \
80+
const auto component = static_cast<Fmi3Component *>(c); \
8081
component->logger->log(fmiError, std::string("Unsupported function fmi3Get") + #type); \
81-
return fmi3Error; \
82+
return fmi3Error; \
8283
}
8384

84-
#define NOT_IMPLEMENTED_SETTER(type) \
85-
fmi3Status fmi3Set##type( \
86-
fmi3Instance c, \
87-
const fmi3ValueReference vr[], \
88-
size_t nValueReferences, \
89-
const FMU_TYPE(type) values[], \
90-
size_t nValues) { \
91-
const auto component = static_cast<Fmi3Component *>(c); \
85+
#define NOT_IMPLEMENTED_SETTER(type) \
86+
fmi3Status fmi3Set##type( \
87+
fmi3Instance c, \
88+
const fmi3ValueReference vr[], \
89+
size_t nValueReferences, \
90+
const FMU_TYPE(type) values[], \
91+
size_t nValues) { \
92+
const auto component = static_cast<Fmi3Component *>(c); \
9293
component->logger->log(fmiError, std::string("Unsupported function fmi3Set") + #type); \
93-
return fmi3Error; \
94+
return fmi3Error; \
9495
}
9596

9697
}// namespace
@@ -103,7 +104,7 @@ const char *fmi3GetVersion(void) {
103104

104105
FMI3_Export void write_description(const char *location) {
105106
const auto instance = fmu4cpp::createInstance({});
106-
const auto xml = instance->make_description_v3();
107+
const auto xml = instance->make_description();
107108
std::ofstream of(location);
108109
of << xml;
109110
of.close();

0 commit comments

Comments
 (0)