Skip to content

Commit

Permalink
Added initialize start values function
Browse files Browse the repository at this point in the history
  • Loading branch information
davidhjp01 committed Nov 16, 2024
1 parent 1e54be8 commit 00ced51
Show file tree
Hide file tree
Showing 7 changed files with 75 additions and 19 deletions.
5 changes: 5 additions & 0 deletions include/cosim/algorithm/simulator.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,11 @@ class simulator : public manipulable
*/
virtual void start_simulation() = 0;

/**
* Runs fmiXSetINI (4.2.4) functions to initialize variables' start values.
*/
virtual void initialize_start_values() = 0;

/**
* Performs a single time step.
*
Expand Down
24 changes: 17 additions & 7 deletions src/cosim/algorithm/fixed_step_algorithm.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,23 @@ class fixed_step_algorithm::impl

void initialize()
{
// FMU's start values are set in "instantiated" state (4.2.4)
// Some of the FMUs do not see start values if this is not
// done before fmiXEnterInitializationMode
for (auto& s : simulators_) {
pool_.submit([&] {
s.second.sim->initialize_start_values();
});
}
pool_.wait_for_tasks_to_finish();

for (auto& s : simulators_) {
pool_.submit([&] {
s.second.sim->setup(startTime_, stopTime_, std::nullopt);
});
}
pool_.wait_for_tasks_to_finish();

// Run N iterations of the simulators' and functions' step/calculation
// procedures, where N is the number of simulators in the system,
// to propagate initial values.
Expand All @@ -164,13 +181,6 @@ class fixed_step_algorithm::impl
calculate_and_transfer();
}

for (auto& s : simulators_) {
pool_.submit([&] {
s.second.sim->setup(startTime_, stopTime_, std::nullopt);
});
}
pool_.wait_for_tasks_to_finish();


for (auto& s : simulators_) {
pool_.submit([&] {
Expand Down
54 changes: 46 additions & 8 deletions src/cosim/slave_simulator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
#include <sstream>
#include <stdexcept>
#include <unordered_map>
#include <iostream>


namespace cosim
Expand Down Expand Up @@ -216,19 +217,23 @@ class set_variable_cache
}
}

std::pair<gsl::span<value_reference>, gsl::span<const T>> modify_and_get(duration deltaT)
std::pair<gsl::span<value_reference>, gsl::span<const T>> modify_and_get(
duration deltaT,
std::optional<std::function<bool(const value_reference&)>> filter = std::nullopt)
{
if (!hasRunModifiers_) {
for (const auto& entry : modifiers_) {
const auto ref = entry.first;
auto& arrayIndex = exposedVariables_.at(ref).arrayIndex;
if (arrayIndex < 0) {
arrayIndex = references_.size();
assert(references_.size() == values_.size());
references_.emplace_back(ref);
values_.emplace_back(exposedVariables_.at(ref).lastValue);
if (!filter || filter && (*filter)(ref)) {
auto& arrayIndex = exposedVariables_.at(ref).arrayIndex;
if (arrayIndex < 0) {
arrayIndex = references_.size();
assert(references_.size() == values_.size());
references_.emplace_back(ref);
values_.emplace_back(exposedVariables_.at(ref).lastValue);
}
values_[arrayIndex] = entry.second(values_[arrayIndex], deltaT);
}
values_[arrayIndex] = entry.second(values_[arrayIndex], deltaT);
}
assert(references_.size() == values_.size());
hasRunModifiers_ = true;
Expand Down Expand Up @@ -518,6 +523,34 @@ class slave_simulator::impl
return result;
}

void initialize_start_values()
{
auto deltaT = duration::zero();
auto filter = [&](variable_type vt) {
return [&vt, this](const value_reference &vr) {
const auto &vd = this->find_variable_description(vr, vt);
/// FMI Specification 2.0.4 - Section 4.2.4
return vd.variability != variable_variability::constant &&
vd.causality != variable_causality::input;
};
};

const auto [realRefs, realValues] = realSetCache_.modify_and_get(deltaT, filter(variable_type::real));
const auto [integerRefs, integerValues] = integerSetCache_.modify_and_get(deltaT, filter(variable_type::integer));
const auto [booleanRefs, booleanValues] = booleanSetCache_.modify_and_get(deltaT, filter(variable_type::boolean));
const auto [stringRefs, stringValues] = stringSetCache_.modify_and_get(deltaT, filter(variable_type::string));

slave_->set_variables(
gsl::make_span(realRefs),
gsl::make_span(realValues),
gsl::make_span(integerRefs),
gsl::make_span(integerValues),
gsl::make_span(booleanRefs),
gsl::make_span(booleanValues),
gsl::make_span(stringRefs),
gsl::make_span(stringValues));
}

private:
void set_variables(duration deltaT)
{
Expand Down Expand Up @@ -803,4 +836,9 @@ step_result slave_simulator::do_step(
}


void slave_simulator::initialize_start_values()
{
return pimpl_->initialize_start_values();
}

} // namespace cosim
2 changes: 2 additions & 0 deletions src/cosim/slave_simulator.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,8 @@ class slave_simulator : public simulator

void do_iteration() override;

void initialize_start_values() override;

void start_simulation() override;

step_result do_step(
Expand Down
2 changes: 1 addition & 1 deletion tests/data/msmi/OspSystemStructure_StateInitExample.xml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
<Simulator name="example" source="../fmi2/StateInitExample.fmu">
<InitialValues>
<InitialValue variable="Parameters.Integrator1_x0">
<Real value="10" />
<Real value="10.0" />
</InitialValue>
</InitialValues>
</Simulator>
Expand Down
1 change: 1 addition & 0 deletions tests/last_value_observer_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,7 @@ int main()

observer->get_real(sim, gsl::make_span(&realInRef, 1), gsl::make_span(&realInValue, 1));
observer->get_real(sim, gsl::make_span(&realOutRef, 1), gsl::make_span(&realOutValue, 1));
std::cout << realInValue << std::endl;
REQUIRE(std::fabs(realInValue - 2.0) < 1.0e-9);
REQUIRE(std::fabs(realOutValue - 3.234) < 1.0e-9);

Expand Down
6 changes: 3 additions & 3 deletions tests/state_init_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -35,15 +35,15 @@ int main()
execution.simulate_until(cosim::to_time_point(0.1));

auto sim = entityMaps.simulators.at("example");
const cosim::value_reference inRef = 2;
const cosim::value_reference outRef = 3;
const auto inRef = config.system_structure.get_variable_description({"example", "Parameters.Integrator1_x0"}).reference;
const auto outRef = config.system_structure.get_variable_description({"example", "Integrator_out1"}).reference;

double initialValue = 0.0;
double outputValue = 0.0;
lvObserver->get_real(sim, gsl::make_span(&inRef, 1), gsl::make_span(&initialValue, 1));
lvObserver->get_real(sim, gsl::make_span(&outRef, 1), gsl::make_span(&outputValue, 1));

REQUIRE(initialValue == 1.0);
REQUIRE(std::fabs(initialValue - 10.0) < 1.0e-9);
REQUIRE(std::fabs(outputValue - 10.1) < 1.0e-9);

} catch (const std::exception& e) {
Expand Down

0 comments on commit 00ced51

Please sign in to comment.