Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[SSP] Move and rename osp algorithm annotation into DefaultExperiment & make algorithms pluggable #426

Closed
wants to merge 14 commits into from
Closed
15 changes: 15 additions & 0 deletions include/cse/algorithm.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -283,6 +283,21 @@ class fixed_step_algorithm : public algorithm
void initialize() override;
std::pair<duration, std::unordered_set<simulator_index>> do_step(time_point currentT) override;

/**
* Sets step size decimation factor for a simulator.
*
* This will effectively set the simulator step size to a multiple
* of the algorithm's base step size. The default decimation factor is 1.
* Can be called *before* the simulator has been added to the algorithm with `add_simulator()`.
*
* \param simulatorName
* The name of the simulator.
*
* \param factor
* The stepsize decimation factor.
*/
void set_stepsize_decimation_factor(const std::string& simulatorName, int factor);

/**
* Sets step size decimation factor for a simulator.
*
Expand Down
134 changes: 102 additions & 32 deletions include/cse/ssp_parser.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
#include <cse/orchestration.hpp>

#include <boost/filesystem/path.hpp>
#include <boost/property_tree/ptree.hpp>

#include <map>
#include <optional>
Expand All @@ -19,38 +20,107 @@ namespace cse

using simulator_map = std::map<std::string, simulator_map_entry>;

/**
* Creates an execution based on a SystemStructure.ssd file.
*
* \param [in] configPath
* Path to an .ssd file, or a directory holding SystemStructure.ssd
* \param [in] overrideStartTime
* If defined, the (logical) time point at which the simulation should start.
* If not defined, this variable will be read from .ssd file.
*/
std::pair<execution, simulator_map> load_ssp(
cse::model_uri_resolver&,
const boost::filesystem::path& configPath,
std::optional<cse::time_point> overrideStartTime);

/**
* Creates an execution based on a SystemStructure.ssd file.
*
* \param [in] configPath
* Path to an .ssd file, or a directory holding SystemStructure.ssd
* \param [in] overrideAlgorithm
* If defined, the co-simulation algorithm used in the execution.
* If not defined, the algorithm will be a `fixed_step_algorithm` with
* `stepSize` defined in the .ssd file.
* \param [in] overrideStartTime
* If defined, the (logical) time point at which the simulation should start.
* If not defined, this variable will be read from the .ssd file.
*/
std::pair<execution, simulator_map> load_ssp(
cse::model_uri_resolver&,
const boost::filesystem::path& configPath,
std::shared_ptr<cse::algorithm> overrideAlgorithm = nullptr,
std::optional<cse::time_point> overrideStartTime = std::nullopt);

class algorithm_sub_resolver
{

public:
virtual std::shared_ptr<cse::algorithm> parse(
const std::string& algorithmName,
const boost::property_tree::ptree& tree) = 0;
};

class algorithm_resolver
{
public:
/// Constructs an empty URI resolver.
algorithm_resolver() noexcept = default;

algorithm_resolver(algorithm_resolver&&) noexcept = default;
algorithm_resolver& operator=(algorithm_resolver&&) noexcept = default;

algorithm_resolver(const algorithm_resolver&) = delete;
algorithm_resolver& operator=(const algorithm_resolver&) = delete;

~algorithm_resolver() noexcept = default;

/// Adds a sub-resolver.
void add_resolver(std::shared_ptr<algorithm_sub_resolver> resolver);

std::shared_ptr<cse::algorithm> resolve(
const std::string& algorithmName,
const boost::property_tree::ptree& tree);

private:
std::vector<std::shared_ptr<algorithm_sub_resolver>> subResolvers_;
};


class fixed_step_algorithm_resolver : public algorithm_sub_resolver
{

public:
std::shared_ptr<cse::algorithm> parse(
const std::string& algorithmName,
const boost::property_tree::ptree& tree) override;
};

std::shared_ptr<algorithm_resolver> default_algorithm_resolver();


class ssp_loader
{

public:
/**
* Explicitly specify the simulation start time
* Will override any value found in the ssp.
*
* \param [in] timePoint
* The (logical) time point at which the simulation should start
*/
void set_start_time(cse::time_point timePoint);

/**
* Explicitly specify the co-simulation algorithm to use.
* Will override any value found in the ssp.
*
* \param [in] algorithm
* The co-simulation algorithm to be used in the execution.
*/
void set_algorithm(std::shared_ptr<cse::algorithm> algorithm);

/**
* Assign a non-default model_uri_resolver resolver.
*
* \param [in] resolver
* The new resolver to use.
*/
void set_model_resolver(std::shared_ptr<cse::model_uri_resolver> resolver);

/**
* Assign a non-default algorithm_resolver resolver.
*
* \param [in] resolver
* The new resolver to use.
*/
void set_algorithm_resolver(std::shared_ptr<cse::algorithm_resolver> resolver);

/**
* Creates an execution based on a SystemStructure.ssd file.
*
* \param [in] configPath
* Path to an .ssd file, or a directory holding SystemStructure.ssd
*/
std::pair<execution, simulator_map> load(const boost::filesystem::path& configPath);

private:
std::optional<cse::time_point> overrideStartTime_;
std::shared_ptr<cse::algorithm> overrideAlgorithm_;

std::shared_ptr<cse::model_uri_resolver> modelResolver_;
std::shared_ptr<cse::algorithm_resolver> algorithmResolver_;
};

} // namespace cse

Expand Down
18 changes: 7 additions & 11 deletions src/c/cse.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -204,11 +204,9 @@ cse_execution* cse_ssp_execution_create(
try {
auto execution = std::make_unique<cse_execution>();

auto resolver = cse::default_model_uri_resolver();
auto sim = cse::load_ssp(
*resolver,
sspDir,
startTimeDefined ? std::optional<cse::time_point>(to_time_point(startTime)) : std::nullopt);
cse::ssp_loader loader;
if (startTimeDefined) loader.set_start_time(to_time_point(startTime));
auto sim = loader.load(sspDir);

execution->cpp_execution = std::make_unique<cse::execution>(std::move(sim.first));
execution->simulators = std::move(sim.second);
Expand All @@ -229,12 +227,10 @@ cse_execution* cse_ssp_fixed_step_execution_create(
try {
auto execution = std::make_unique<cse_execution>();

auto resolver = cse::default_model_uri_resolver();
auto sim = cse::load_ssp(
*resolver,
sspDir,
std::make_unique<cse::fixed_step_algorithm>(to_duration(stepSize)),
startTimeDefined ? std::optional<cse::time_point>(to_time_point(startTime)) : std::nullopt);
cse::ssp_loader loader;
if (startTimeDefined) loader.set_start_time(cse::time_point(to_time_point(startTime)));
loader.set_algorithm(std::make_unique<cse::fixed_step_algorithm>(to_duration(stepSize)));
auto sim = loader.load(sspDir);

execution->cpp_execution = std::make_unique<cse::execution>(std::move(sim.first));
execution->simulators = std::move(sim.second);
Expand Down
42 changes: 42 additions & 0 deletions src/cpp/algorithm.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
#include <sstream>
#include <unordered_map>
#include <vector>
#include <queue>

namespace
{
Expand Down Expand Up @@ -90,6 +91,20 @@ class fixed_step_algorithm::impl

void initialize()
{
if (!initialized) {
initialized = true;
auto count = 0;
auto size = simulators_.size();
while (!decimationFactorsQueue_.empty()) {
std::pair<std::string, int> value = decimationFactorsQueue_.front();
set_stepsize_decimation_factor(value.first, value.second);
decimationFactorsQueue_.pop();
if (count++ > size) {
CSE_PANIC();
}
}
}

setup_simulators();
for (std::size_t i = 0; i < simulators_.size(); ++i) {
iterate_simulators();
Expand Down Expand Up @@ -142,6 +157,17 @@ class fixed_step_algorithm::impl
return std::pair(baseStepSize_, std::move(finished));
}

void set_stepsize_decimation_factor(const std::string& name, int factor)
{
CSE_INPUT_CHECK(factor > 0);
if (!initialized) {
decimationFactorsQueue_.push(std::make_pair(name, factor));
} else {
auto idx = get_simulator_index(name);
set_stepsize_decimation_factor(idx, factor);
}
}

void set_stepsize_decimation_factor(cse::simulator_index i, int factor)
{
CSE_INPUT_CHECK(factor > 0);
Expand All @@ -159,6 +185,15 @@ class fixed_step_algorithm::impl
std::unordered_map<variable_id, std::shared_ptr<connection>> incomingConnections;
};

cse::simulator_index get_simulator_index(const std::string& name) {
for (const auto& [index, info] : simulators_) {
if (info.sim->name() == name) {
return index;
}
}
return -1;
}

template<typename F>
void for_all_simulators(F f)
{
Expand Down Expand Up @@ -305,6 +340,8 @@ class fixed_step_algorithm::impl
std::optional<time_point> stopTime_;
std::unordered_map<simulator_index, simulator_info> simulators_;
int64_t stepCounter_ = 0;
bool initialized = false;
std::queue<std::pair<std::string, int>> decimationFactorsQueue_;
};


Expand Down Expand Up @@ -375,6 +412,11 @@ std::pair<duration, std::unordered_set<simulator_index>> fixed_step_algorithm::d
return pimpl_->do_step(currentT);
}

void fixed_step_algorithm::set_stepsize_decimation_factor(const std::string& simulatorName, int factor)
{
pimpl_->set_stepsize_decimation_factor(simulatorName, factor);
}

void fixed_step_algorithm::set_stepsize_decimation_factor(cse::simulator_index simulator, int factor)
{
pimpl_->set_stepsize_decimation_factor(simulator, factor);
Expand Down
Loading