Skip to content

Commit 3a4a104

Browse files
committed
fmi3 impl
1 parent db022fb commit 3a4a104

35 files changed

Lines changed: 17479 additions & 149 deletions

CMakeLists.txt

Lines changed: 4 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,10 @@ endif ()
1212
option(FMU4CPP_BUILD_TESTS "Build internal tests" OFF)
1313

1414
set(CMAKE_CXX_STANDARD 17)
15+
if (MSVC)
16+
# fmt lib
17+
add_compile_options(/utf-8)
18+
endif ()
1519

1620

1721
############modelIdentifier###################
@@ -22,19 +26,5 @@ set(modelIdentifier identity) # <-- CHANGE ME
2226

2327
include("cmake/generate_fmu.cmake")
2428

25-
if ("${CMAKE_SIZEOF_VOID_P}" STREQUAL "8")
26-
set(BITNESS 64)
27-
else ()
28-
set(BITNESS 32)
29-
endif ()
30-
31-
if (WIN32)
32-
set(TARGET_PLATFORM win${BITNESS})
33-
elseif (APPLE)
34-
set(TARGET_PLATFORM darwin${BITNESS})
35-
else ()
36-
set(TARGET_PLATFORM linux${BITNESS})
37-
endif ()
38-
3929
add_subdirectory(export)
4030
add_subdirectory(src)

cmake/generate_fmu.cmake

Lines changed: 42 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,47 @@
11

2-
function(generateFMU modelIdentifier resourceFolder)
2+
function(generateFMU modelIdentifier fmiVersion resourceFolder)
3+
4+
target_sources(${modelIdentifier} PRIVATE "$<TARGET_OBJECTS:fmu4cpp_base>")
5+
6+
set(TARGET_PLATFORM)
7+
if (fmiVersion STREQUAL "fmi2")
8+
9+
if ("${CMAKE_SIZEOF_VOID_P}" STREQUAL "8")
10+
set(BITNESS 64)
11+
else ()
12+
set(BITNESS 32)
13+
endif ()
14+
15+
if (WIN32)
16+
set(TARGET_PLATFORM win${BITNESS})
17+
elseif (APPLE)
18+
set(TARGET_PLATFORM darwin${BITNESS})
19+
else ()
20+
set(TARGET_PLATFORM linux${BITNESS})
21+
endif ()
22+
23+
target_sources(${modelIdentifier} PRIVATE "$<TARGET_OBJECTS:fmu4cpp_fmi2>")
24+
elseif (fmiVersion STREQUAL "fmi3")
25+
26+
set(TARGET_PLATFORM "x86")
27+
if ("${CMAKE_SIZEOF_VOID_P}" STREQUAL "8")
28+
set(TARGET_PLATFORM "${TARGET_PLATFORM}_64")
29+
endif ()
30+
31+
if (WIN32)
32+
set(TARGET_PLATFORM ${TARGET_PLATFORM}-windows)
33+
elseif (APPLE)
34+
set(TARGET_PLATFORM ${TARGET_PLATFORM}-darwin)
35+
else ()
36+
set(TARGET_PLATFORM ${TARGET_PLATFORM}-linux)
37+
endif ()
38+
39+
target_sources(${modelIdentifier} PRIVATE "$<TARGET_OBJECTS:fmu4cpp_fmi3>")
40+
41+
else ()
42+
message(FATAL_ERROR "Unknown FMI version: ${fmiVersion}. Supported versions are 'fmi2' and 'fmi3'.")
43+
endif ()
344

4-
target_sources(${modelIdentifier} PRIVATE "$<TARGET_OBJECTS:fmu4cpp>")
545
target_include_directories("${modelIdentifier}" PRIVATE "${PROJECT_SOURCE_DIR}/export/include")
646
target_compile_definitions("${modelIdentifier}" PRIVATE FMU4CPP_MODEL_IDENTIFIER="${modelIdentifier}")
747

export/examples/BouncingBall/CMakeLists.txt

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,5 +2,8 @@
22
add_library(bouncing_ball SHARED
33
"bouncing_ball.cpp"
44
)
5+
target_include_directories(bouncing_ball PRIVATE
6+
"${CMAKE_CURRENT_SOURCE_DIR}/../external"
7+
)
58

6-
generateFMU("bouncing_ball" "")
9+
generateFMU("bouncing_ball" "fmi3" "")

export/examples/BouncingBall/bouncing_ball.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11

22
#include <fmu4cpp/fmu_base.hpp>
33

4+
#define FMT_HEADER_ONLY
5+
#include <fmt/core.h>
6+
47
using namespace fmu4cpp;
58

69

@@ -51,6 +54,8 @@ class BouncingBall : public fmu_base {
5154
velocity_ = -velocity_ * bounceFactor_;// Reverse velocity and apply bounce factor
5255
}
5356

57+
log(fmiOK, fmt::format("Current height: {:.2f}, Current velocity: {:.2f}", height_, velocity_));
58+
5459
return true;
5560
}
5661

export/examples/Resource/CMakeLists.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,4 +3,4 @@ add_library(resource SHARED
33
"resource.cpp"
44
)
55

6-
generateFMU("resource" "${CMAKE_CURRENT_SOURCE_DIR}/resources")
6+
generateFMU("resource" "fmi2" "${CMAKE_CURRENT_SOURCE_DIR}/resources")

export/examples/Resource/resource.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ class Resource : public fmu_base {
2828

2929
bool do_step(double currentTime, double dt) override {
3030

31-
log(fmi2OK, get_string_variable("content")->get());
31+
log(fmiOK, get_string_variable("content")->get());
3232
return true;
3333
}
3434

export/examples/SimplePendulum/CMakeLists.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,4 +3,4 @@ add_library(simple_pendulum SHARED
33
"simple_pendulum.cpp"
44
)
55

6-
generateFMU(simple_pendulum "")
6+
generateFMU(simple_pendulum "fmi2" "")
Lines changed: 220 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,220 @@
1+
// Formatting library for C++ - dynamic argument lists
2+
//
3+
// Copyright (c) 2012 - present, Victor Zverovich
4+
// All rights reserved.
5+
//
6+
// For the license information refer to format.h.
7+
8+
#ifndef FMT_ARGS_H_
9+
#define FMT_ARGS_H_
10+
11+
#ifndef FMT_MODULE
12+
# include <functional> // std::reference_wrapper
13+
# include <memory> // std::unique_ptr
14+
# include <vector>
15+
#endif
16+
17+
#include "format.h" // std_string_view
18+
19+
FMT_BEGIN_NAMESPACE
20+
namespace detail {
21+
22+
template <typename T> struct is_reference_wrapper : std::false_type {};
23+
template <typename T>
24+
struct is_reference_wrapper<std::reference_wrapper<T>> : std::true_type {};
25+
26+
template <typename T> auto unwrap(const T& v) -> const T& { return v; }
27+
template <typename T>
28+
auto unwrap(const std::reference_wrapper<T>& v) -> const T& {
29+
return static_cast<const T&>(v);
30+
}
31+
32+
// node is defined outside dynamic_arg_list to workaround a C2504 bug in MSVC
33+
// 2022 (v17.10.0).
34+
//
35+
// Workaround for clang's -Wweak-vtables. Unlike for regular classes, for
36+
// templates it doesn't complain about inability to deduce single translation
37+
// unit for placing vtable. So node is made a fake template.
38+
template <typename = void> struct node {
39+
virtual ~node() = default;
40+
std::unique_ptr<node<>> next;
41+
};
42+
43+
class dynamic_arg_list {
44+
template <typename T> struct typed_node : node<> {
45+
T value;
46+
47+
template <typename Arg>
48+
FMT_CONSTEXPR typed_node(const Arg& arg) : value(arg) {}
49+
50+
template <typename Char>
51+
FMT_CONSTEXPR typed_node(const basic_string_view<Char>& arg)
52+
: value(arg.data(), arg.size()) {}
53+
};
54+
55+
std::unique_ptr<node<>> head_;
56+
57+
public:
58+
template <typename T, typename Arg> auto push(const Arg& arg) -> const T& {
59+
auto new_node = std::unique_ptr<typed_node<T>>(new typed_node<T>(arg));
60+
auto& value = new_node->value;
61+
new_node->next = std::move(head_);
62+
head_ = std::move(new_node);
63+
return value;
64+
}
65+
};
66+
} // namespace detail
67+
68+
/**
69+
* A dynamic list of formatting arguments with storage.
70+
*
71+
* It can be implicitly converted into `fmt::basic_format_args` for passing
72+
* into type-erased formatting functions such as `fmt::vformat`.
73+
*/
74+
template <typename Context> class dynamic_format_arg_store {
75+
private:
76+
using char_type = typename Context::char_type;
77+
78+
template <typename T> struct need_copy {
79+
static constexpr detail::type mapped_type =
80+
detail::mapped_type_constant<T, char_type>::value;
81+
82+
enum {
83+
value = !(detail::is_reference_wrapper<T>::value ||
84+
std::is_same<T, basic_string_view<char_type>>::value ||
85+
std::is_same<T, detail::std_string_view<char_type>>::value ||
86+
(mapped_type != detail::type::cstring_type &&
87+
mapped_type != detail::type::string_type &&
88+
mapped_type != detail::type::custom_type))
89+
};
90+
};
91+
92+
template <typename T>
93+
using stored_t = conditional_t<
94+
std::is_convertible<T, std::basic_string<char_type>>::value &&
95+
!detail::is_reference_wrapper<T>::value,
96+
std::basic_string<char_type>, T>;
97+
98+
// Storage of basic_format_arg must be contiguous.
99+
std::vector<basic_format_arg<Context>> data_;
100+
std::vector<detail::named_arg_info<char_type>> named_info_;
101+
102+
// Storage of arguments not fitting into basic_format_arg must grow
103+
// without relocation because items in data_ refer to it.
104+
detail::dynamic_arg_list dynamic_args_;
105+
106+
friend class basic_format_args<Context>;
107+
108+
auto data() const -> const basic_format_arg<Context>* {
109+
return named_info_.empty() ? data_.data() : data_.data() + 1;
110+
}
111+
112+
template <typename T> void emplace_arg(const T& arg) {
113+
data_.emplace_back(arg);
114+
}
115+
116+
template <typename T>
117+
void emplace_arg(const detail::named_arg<char_type, T>& arg) {
118+
if (named_info_.empty())
119+
data_.insert(data_.begin(), basic_format_arg<Context>(nullptr, 0));
120+
data_.emplace_back(detail::unwrap(arg.value));
121+
auto pop_one = [](std::vector<basic_format_arg<Context>>* data) {
122+
data->pop_back();
123+
};
124+
std::unique_ptr<std::vector<basic_format_arg<Context>>, decltype(pop_one)>
125+
guard{&data_, pop_one};
126+
named_info_.push_back({arg.name, static_cast<int>(data_.size() - 2u)});
127+
data_[0] = {named_info_.data(), named_info_.size()};
128+
guard.release();
129+
}
130+
131+
public:
132+
constexpr dynamic_format_arg_store() = default;
133+
134+
operator basic_format_args<Context>() const {
135+
return basic_format_args<Context>(data(), static_cast<int>(data_.size()),
136+
!named_info_.empty());
137+
}
138+
139+
/**
140+
* Adds an argument into the dynamic store for later passing to a formatting
141+
* function.
142+
*
143+
* Note that custom types and string types (but not string views) are copied
144+
* into the store dynamically allocating memory if necessary.
145+
*
146+
* **Example**:
147+
*
148+
* fmt::dynamic_format_arg_store<fmt::format_context> store;
149+
* store.push_back(42);
150+
* store.push_back("abc");
151+
* store.push_back(1.5f);
152+
* std::string result = fmt::vformat("{} and {} and {}", store);
153+
*/
154+
template <typename T> void push_back(const T& arg) {
155+
if (detail::const_check(need_copy<T>::value))
156+
emplace_arg(dynamic_args_.push<stored_t<T>>(arg));
157+
else
158+
emplace_arg(detail::unwrap(arg));
159+
}
160+
161+
/**
162+
* Adds a reference to the argument into the dynamic store for later passing
163+
* to a formatting function.
164+
*
165+
* **Example**:
166+
*
167+
* fmt::dynamic_format_arg_store<fmt::format_context> store;
168+
* char band[] = "Rolling Stones";
169+
* store.push_back(std::cref(band));
170+
* band[9] = 'c'; // Changing str affects the output.
171+
* std::string result = fmt::vformat("{}", store);
172+
* // result == "Rolling Scones"
173+
*/
174+
template <typename T> void push_back(std::reference_wrapper<T> arg) {
175+
static_assert(
176+
need_copy<T>::value,
177+
"objects of built-in types and string views are always copied");
178+
emplace_arg(arg.get());
179+
}
180+
181+
/**
182+
* Adds named argument into the dynamic store for later passing to a
183+
* formatting function. `std::reference_wrapper` is supported to avoid
184+
* copying of the argument. The name is always copied into the store.
185+
*/
186+
template <typename T>
187+
void push_back(const detail::named_arg<char_type, T>& arg) {
188+
const char_type* arg_name =
189+
dynamic_args_.push<std::basic_string<char_type>>(arg.name).c_str();
190+
if (detail::const_check(need_copy<T>::value)) {
191+
emplace_arg(
192+
fmt::arg(arg_name, dynamic_args_.push<stored_t<T>>(arg.value)));
193+
} else {
194+
emplace_arg(fmt::arg(arg_name, arg.value));
195+
}
196+
}
197+
198+
/// Erase all elements from the store.
199+
void clear() {
200+
data_.clear();
201+
named_info_.clear();
202+
dynamic_args_ = {};
203+
}
204+
205+
/// Reserves space to store at least `new_cap` arguments including
206+
/// `new_cap_named` named arguments.
207+
void reserve(size_t new_cap, size_t new_cap_named) {
208+
FMT_ASSERT(new_cap >= new_cap_named,
209+
"set of arguments includes set of named arguments");
210+
data_.reserve(new_cap);
211+
named_info_.reserve(new_cap_named);
212+
}
213+
214+
/// Returns the number of elements in the store.
215+
size_t size() const noexcept { return data_.size(); }
216+
};
217+
218+
FMT_END_NAMESPACE
219+
220+
#endif // FMT_ARGS_H_

0 commit comments

Comments
 (0)