From f93e68bc8fc002f482961b8d28320cedf6822679 Mon Sep 17 00:00:00 2001 From: Gauthier Quesnel Date: Tue, 7 Jan 2025 15:55:26 +0100 Subject: [PATCH] wip core: move parameters from dynamics into simulation vector --- app/gui/editor.cpp | 425 +------------ app/gui/generic/simulation.cpp | 25 +- lib/include/irritator/core.hpp | 389 ++++++------ lib/include/irritator/examples.hpp | 122 ++-- lib/include/irritator/modeling.hpp | 31 - lib/src/archiver.cpp | 494 +--------------- lib/src/json.cpp | 916 +++++++++++++++++------------ lib/src/parameter.cpp | 363 ++++++++---- lib/src/parameter.hpp | 293 +-------- lib/src/project.cpp | 8 +- lib/test/mod-to-sim.cpp | 4 +- lib/test/public-api.cpp | 414 ++++++------- lib/test/simulations.cpp | 70 ++- 13 files changed, 1264 insertions(+), 2290 deletions(-) diff --git a/app/gui/editor.cpp b/app/gui/editor.cpp index 825a9774..08191514 100644 --- a/app/gui/editor.cpp +++ b/app/gui/editor.cpp @@ -10,201 +10,6 @@ namespace irt { -void show_dynamics_inputs(project_window& /*sim*/, qss1_integrator& dyn) -{ - ImGui::InputReal("value", &dyn.default_X); - ImGui::InputReal("dQ", &dyn.default_dQ); -} - -void show_dynamics_inputs(project_window& /*sim*/, qss2_integrator& dyn) -{ - ImGui::InputReal("value", &dyn.default_X); - ImGui::InputReal("dQ", &dyn.default_dQ); -} - -void show_dynamics_inputs(project_window& /*sim*/, qss3_integrator& dyn) -{ - ImGui::InputReal("value", &dyn.default_X); - ImGui::InputReal("dQ", &dyn.default_dQ); -} - -void show_dynamics_inputs(project_window& /*sim*/, qss1_multiplier& /*dyn*/) {} - -void show_dynamics_inputs(project_window& /*sim*/, qss1_sum_2& dyn) -{ - ImGui::InputReal("value-0", &dyn.default_values[0]); - ImGui::InputReal("value-1", &dyn.default_values[1]); -} - -void show_dynamics_inputs(project_window& /*sim*/, qss1_sum_3& dyn) -{ - ImGui::InputReal("value-0", &dyn.default_values[0]); - ImGui::InputReal("value-1", &dyn.default_values[1]); - ImGui::InputReal("value-2", &dyn.default_values[2]); -} - -void show_dynamics_inputs(project_window& /*sim*/, qss1_sum_4& dyn) -{ - ImGui::InputReal("value-0", &dyn.default_values[0]); - ImGui::InputReal("value-1", &dyn.default_values[1]); - ImGui::InputReal("value-2", &dyn.default_values[2]); - ImGui::InputReal("value-3", &dyn.default_values[3]); -} - -void show_dynamics_inputs(project_window& /*sim*/, qss1_wsum_2& dyn) -{ - ImGui::InputReal("value-0", &dyn.default_values[0]); - ImGui::InputReal("value-1", &dyn.default_values[1]); - - ImGui::InputReal("coeff-0", &dyn.default_input_coeffs[0]); - ImGui::InputReal("coeff-1", &dyn.default_input_coeffs[1]); -} - -void show_dynamics_inputs(project_window& /*sim*/, qss1_wsum_3& dyn) -{ - ImGui::InputReal("value-0", &dyn.default_values[0]); - ImGui::InputReal("value-1", &dyn.default_values[1]); - ImGui::InputReal("value-2", &dyn.default_values[2]); - - ImGui::InputReal("coeff-0", &dyn.default_input_coeffs[0]); - ImGui::InputReal("coeff-1", &dyn.default_input_coeffs[1]); - ImGui::InputReal("coeff-2", &dyn.default_input_coeffs[2]); -} - -void show_dynamics_inputs(project_window& /*sim*/, qss1_wsum_4& dyn) -{ - ImGui::InputReal("value-0", &dyn.default_values[0]); - ImGui::InputReal("value-1", &dyn.default_values[1]); - ImGui::InputReal("value-2", &dyn.default_values[2]); - ImGui::InputReal("value-3", &dyn.default_values[3]); - - ImGui::InputReal("coeff-0", &dyn.default_input_coeffs[0]); - ImGui::InputReal("coeff-1", &dyn.default_input_coeffs[1]); - ImGui::InputReal("coeff-2", &dyn.default_input_coeffs[2]); - ImGui::InputReal("coeff-3", &dyn.default_input_coeffs[3]); -} - -void show_dynamics_inputs(project_window& /*sim*/, qss2_multiplier& /*dyn*/) {} - -void show_dynamics_inputs(project_window& /*sim*/, qss2_sum_2& dyn) -{ - ImGui::InputReal("value-0", &dyn.default_values[0]); - ImGui::InputReal("value-1", &dyn.default_values[1]); -} - -void show_dynamics_inputs(project_window& /*sim*/, qss2_sum_3& dyn) -{ - ImGui::InputReal("value-0", &dyn.default_values[0]); - ImGui::InputReal("value-1", &dyn.default_values[1]); - ImGui::InputReal("value-2", &dyn.default_values[2]); -} - -void show_dynamics_inputs(project_window& /*sim*/, qss2_sum_4& dyn) -{ - ImGui::InputReal("value-0", &dyn.default_values[0]); - ImGui::InputReal("value-1", &dyn.default_values[1]); - ImGui::InputReal("value-2", &dyn.default_values[2]); - ImGui::InputReal("value-3", &dyn.default_values[3]); -} - -void show_dynamics_inputs(project_window& /*sim*/, qss2_wsum_2& dyn) -{ - ImGui::InputReal("value-0", &dyn.default_values[0]); - ImGui::InputReal("value-1", &dyn.default_values[1]); - - ImGui::InputReal("coeff-0", &dyn.default_input_coeffs[0]); - ImGui::InputReal("coeff-1", &dyn.default_input_coeffs[1]); -} - -void show_dynamics_inputs(project_window& /*sim*/, qss2_wsum_3& dyn) -{ - ImGui::InputReal("value-0", &dyn.default_values[0]); - ImGui::InputReal("value-1", &dyn.default_values[1]); - ImGui::InputReal("value-2", &dyn.default_values[2]); - - ImGui::InputReal("coeff-0", &dyn.default_input_coeffs[0]); - ImGui::InputReal("coeff-1", &dyn.default_input_coeffs[1]); - ImGui::InputReal("coeff-2", &dyn.default_input_coeffs[2]); -} - -void show_dynamics_inputs(project_window& /*sim*/, qss2_wsum_4& dyn) -{ - ImGui::InputReal("value-0", &dyn.default_values[0]); - ImGui::InputReal("value-1", &dyn.default_values[1]); - ImGui::InputReal("value-2", &dyn.default_values[2]); - ImGui::InputReal("value-3", &dyn.default_values[3]); - - ImGui::InputReal("coeff-0", &dyn.default_input_coeffs[0]); - ImGui::InputReal("coeff-1", &dyn.default_input_coeffs[1]); - ImGui::InputReal("coeff-2", &dyn.default_input_coeffs[2]); - ImGui::InputReal("coeff-3", &dyn.default_input_coeffs[3]); -} - -void show_dynamics_inputs(project_window& /*sim*/, qss3_multiplier& /*dyn*/) {} - -void show_dynamics_inputs(project_window& /*sim*/, qss3_sum_2& dyn) -{ - ImGui::InputReal("value-0", &dyn.default_values[0]); - ImGui::InputReal("value-1", &dyn.default_values[1]); -} - -void show_dynamics_inputs(project_window& /*sim*/, qss3_sum_3& dyn) -{ - ImGui::InputReal("value-0", &dyn.default_values[0]); - ImGui::InputReal("value-1", &dyn.default_values[1]); - ImGui::InputReal("value-2", &dyn.default_values[2]); -} - -void show_dynamics_inputs(project_window& /*sim*/, qss3_sum_4& dyn) -{ - ImGui::InputReal("value-0", &dyn.default_values[0]); - ImGui::InputReal("value-1", &dyn.default_values[1]); - ImGui::InputReal("value-2", &dyn.default_values[2]); - ImGui::InputReal("value-3", &dyn.default_values[3]); -} - -void show_dynamics_inputs(project_window& /*sim*/, qss3_wsum_2& dyn) -{ - ImGui::InputReal("value-0", &dyn.default_values[0]); - ImGui::InputReal("value-1", &dyn.default_values[1]); - - ImGui::InputReal("coeff-0", &dyn.default_input_coeffs[0]); - ImGui::InputReal("coeff-1", &dyn.default_input_coeffs[1]); -} - -void show_dynamics_inputs(project_window& /*sim*/, qss3_wsum_3& dyn) -{ - ImGui::InputReal("value-0", &dyn.default_values[0]); - ImGui::InputReal("value-1", &dyn.default_values[1]); - ImGui::InputReal("value-2", &dyn.default_values[2]); - - ImGui::InputReal("coeff-0", &dyn.default_input_coeffs[0]); - ImGui::InputReal("coeff-1", &dyn.default_input_coeffs[1]); - ImGui::InputReal("coeff-2", &dyn.default_input_coeffs[2]); -} - -void show_dynamics_inputs(project_window& /*sim*/, qss3_wsum_4& dyn) -{ - ImGui::InputReal("value-0", &dyn.default_values[0]); - ImGui::InputReal("value-1", &dyn.default_values[1]); - ImGui::InputReal("value-2", &dyn.default_values[2]); - ImGui::InputReal("value-3", &dyn.default_values[3]); - - ImGui::InputReal("coeff-0", &dyn.default_input_coeffs[0]); - ImGui::InputReal("coeff-1", &dyn.default_input_coeffs[1]); - ImGui::InputReal("coeff-2", &dyn.default_input_coeffs[2]); - ImGui::InputReal("coeff-3", &dyn.default_input_coeffs[3]); -} - -void show_dynamics_inputs(project_window& /*sim*/, counter& /*dyn*/) {} - -void show_dynamics_inputs(project_window& /*sim*/, queue& dyn) -{ - ImGui::InputReal("delay", &dyn.default_ta); - ImGui::SameLine(); - HelpMarker("Delay to resent the first input receives (FIFO queue)"); -} - bool show_external_sources_combo(external_source& srcs, const char* title, u64& id, @@ -417,229 +222,6 @@ bool show_external_sources_combo(external_source& srcs, return is_changed; } -void show_dynamics_inputs(project_window& sim, dynamic_queue& dyn) -{ - ImGui::Checkbox("Stop on error", &dyn.stop_on_error); - ImGui::SameLine(); - HelpMarker( - "Unchecked, the dynamic queue stops to send data if the source are " - "empty or undefined. Checked, the simulation will stop."); - - show_external_sources_combo(sim.pj.sim.srcs, "time", dyn.default_source_ta); -} - -void show_dynamics_inputs(project_window& sim, priority_queue& dyn) -{ - ImGui::Checkbox("Stop on error", &dyn.stop_on_error); - ImGui::SameLine(); - HelpMarker( - "Unchecked, the priority queue stops to send data if the source are " - "empty or undefined. Checked, the simulation will stop."); - - show_external_sources_combo(sim.pj.sim.srcs, "time", dyn.default_source_ta); -} - -void show_dynamics_inputs(project_window& sim, generator& dyn) -{ - const char* menu[] = { "source", "external events" }; - - auto combo_ta = dyn.flags[generator::option::ta_use_source] ? 0 : 1; - auto combo_value = dyn.flags[generator::option::value_use_source] ? 0 : 1; - - { - auto ret = ImGui::Combo("ta", &combo_ta, menu, length(menu)); - ImGui::SameLine(); - HelpMarker( - "`Source` means you need to setup external source like random " - "number, input file etc. In `external events`, the value comes " - "from the input ports."); - - if (ret) - dyn.flags.set(generator::option::ta_use_source, combo_ta == 0); - } - - { - auto ret = ImGui::Combo("value", &combo_value, menu, length(menu)); - ImGui::SameLine(); - HelpMarker( - "`Source` means you need to setup external source like random " - "number, input file etc. In `external events`, the value comes " - "from the input port."); - - if (ret) - dyn.flags.set(generator::option::value_use_source, - combo_value == 0); - } - - if (dyn.flags[generator::option::ta_use_source]) { - auto stop_on_error = dyn.flags[generator::option::stop_on_error]; - - show_external_sources_combo( - sim.pj.sim.srcs, "time", dyn.default_source_ta); - ImGui::InputReal("offset", &dyn.default_offset); - if (ImGui::Checkbox("Stop on error", &stop_on_error)) - dyn.flags.set(generator::option::stop_on_error); - ImGui::SameLine(); - HelpMarker( - "Unchecked, the generator stops to send data if the source are " - "empty or undefined. Checked, the simulation will stop."); - } - - if (dyn.flags[generator::option::value_use_source]) - show_external_sources_combo( - sim.pj.sim.srcs, "source", dyn.default_source_value); -} - -void show_dynamics_inputs(project_window& /*sim*/, constant& dyn) -{ - static const char* type_names[] = { "constant", - "incoming_component_all", - "outcoming_component_all", - "incoming_component_n", - "outcoming_component_n" }; - - ImGui::InputReal("value", &dyn.default_value); - ImGui::InputReal("offset", &dyn.default_offset); - - int i = ordinal(dyn.type); - if (ImGui::Combo("type", &i, type_names, length(type_names))) - dyn.type = enum_cast(i); - - if (any_equal(dyn.type, - constant::init_type::incoming_component_n, - constant::init_type::outcoming_component_n)) { - ImGui::InputScalar("port", ImGuiDataType_U64, &dyn.port); - } -} - -void show_dynamics_inputs(project_window& /*sim*/, qss1_cross& dyn) -{ - ImGui::InputReal("threshold", &dyn.default_threshold); - ImGui::Checkbox("up detection", &dyn.default_detect_up); -} - -void show_dynamics_inputs(project_window& /*sim*/, qss2_cross& dyn) -{ - ImGui::InputReal("threshold", &dyn.default_threshold); - ImGui::Checkbox("up detection", &dyn.default_detect_up); -} - -void show_dynamics_inputs(project_window& /*sim*/, qss3_cross& dyn) -{ - ImGui::InputReal("threshold", &dyn.default_threshold); - ImGui::Checkbox("up detection", &dyn.default_detect_up); -} - -void show_dynamics_inputs(project_window& /*sim*/, qss1_filter& dyn) -{ - ImGui::InputReal("lowe threshold", &dyn.default_lower_threshold); - ImGui::InputReal("upper threshold", &dyn.default_upper_threshold); -} - -void show_dynamics_inputs(project_window& /*sim*/, qss2_filter& dyn) -{ - ImGui::InputReal("lower threshold", &dyn.default_lower_threshold); - ImGui::InputReal("upper threshold", &dyn.default_upper_threshold); -} - -void show_dynamics_inputs(project_window& /*sim*/, qss3_filter& dyn) -{ - ImGui::InputReal("lower threshold", &dyn.default_lower_threshold); - ImGui::InputReal("upper threshold", &dyn.default_upper_threshold); -} - -void show_dynamics_inputs(project_window& /*sim*/, qss1_power& dyn) -{ - ImGui::InputReal("n", &dyn.default_n); -} - -void show_dynamics_inputs(project_window& /*sim*/, qss2_power& dyn) -{ - ImGui::InputReal("n", &dyn.default_n); -} - -void show_dynamics_inputs(project_window& /*sim*/, qss3_power& dyn) -{ - ImGui::InputReal("n", &dyn.default_n); -} - -void show_dynamics_inputs(project_window& /*sim*/, qss1_square& /*dyn*/) {} - -void show_dynamics_inputs(project_window& /*sim*/, qss2_square& /*dyn*/) {} - -void show_dynamics_inputs(project_window& /*sim*/, qss3_square& /*dyn*/) {} - -void show_dynamics_inputs(project_window& /*sim*/, accumulator_2& /*dyn*/) {} - -void show_dynamics_inputs(project_window& /*sim*/, logical_and_2& dyn) -{ - ImGui::Checkbox("value 1", &dyn.default_values[0]); - ImGui::Checkbox("value 2", &dyn.default_values[1]); -} - -void show_dynamics_inputs(project_window& /*sim*/, logical_or_2& dyn) -{ - ImGui::Checkbox("value 1", &dyn.default_values[0]); - ImGui::Checkbox("value 2", &dyn.default_values[1]); -} - -void show_dynamics_inputs(project_window& /*sim*/, logical_and_3& dyn) -{ - ImGui::Checkbox("value 1", &dyn.default_values[0]); - ImGui::Checkbox("value 2", &dyn.default_values[1]); - ImGui::Checkbox("value 3", &dyn.default_values[2]); -} - -void show_dynamics_inputs(project_window& /*sim*/, logical_or_3& dyn) -{ - ImGui::Checkbox("value 1", &dyn.default_values[0]); - ImGui::Checkbox("value 2", &dyn.default_values[1]); - ImGui::Checkbox("value 3", &dyn.default_values[2]); -} - -void show_dynamics_inputs(project_window& /*sim*/, logical_invert& /*dyn*/) {} - -void show_dynamics_inputs(project_window& /*sim*/, hsm_wrapper& dyn) -{ - ImGui::InputInt("integer 1", &dyn.exec.i1); - ImGui::InputInt("integer 2", &dyn.exec.i2); - ImGui::InputDouble("real 1", &dyn.exec.r1); - ImGui::InputDouble("real 2", &dyn.exec.r2); - ImGui::InputDouble("timer", &dyn.exec.timer); -} - -void show_dynamics_inputs(project_window& /*sim*/, time_func& dyn) -{ - static const char* items[] = { "time", "square", "sin" }; - - ImGui::PushItemWidth(120.0f); - int item_current = dyn.default_f == &time_function ? 0 - : dyn.default_f == &square_time_function ? 1 - : 2; - - if (ImGui::Combo("function", &item_current, items, IM_ARRAYSIZE(items))) { - dyn.default_f = item_current == 0 ? &time_function - : item_current == 1 ? &square_time_function - : sin_time_function; - } - ImGui::PopItemWidth(); -} - -// -// -// - -// bool show_parameter_editor(application& app, -// project_window& ed, -// model& mdl, -// parameter& p) noexcept -//{ -// return dispatch( -// mdl, [&app, &p](Dynamics& dyn) noexcept -> bool { -// return show_parameter(app, ed, dyn, p); -// }); -// } - ///////////////////////////////////////////////////////////////////// bool show_parameter(dynamics_counter_tag, @@ -1393,8 +975,8 @@ bool show_parameter(dynamics_logical_invert_tag, return false; } -static auto build_default_hsm_name(const modeling& mod, - parameter& p) noexcept -> const char* +static auto build_default_hsm_name(const modeling& mod, parameter& p) noexcept + -> const char* { static constexpr auto undefined_name = "-"; @@ -1413,8 +995,7 @@ bool show_hsm_parameter(const modeling& mod, parameter& p) noexcept { int changed = false; - if (ImGui::BeginCombo("hsm component", - build_default_hsm_name(mod, p))) { + if (ImGui::BeginCombo("hsm component", build_default_hsm_name(mod, p))) { auto imgui_id = 0; ImGui::PushID(imgui_id++); diff --git a/app/gui/generic/simulation.cpp b/app/gui/generic/simulation.cpp index a0d8b475..a237647e 100644 --- a/app/gui/generic/simulation.cpp +++ b/app/gui/generic/simulation.cpp @@ -165,21 +165,21 @@ static void show_dynamics_values(project_window& /*sim*/, const qss1_integrator& dyn) { ImGui::TextFormat("X {}", dyn.X); - ImGui::TextFormat("dQ {}", dyn.default_dQ); + ImGui::TextFormat("dQ {}", dyn.dQ); } static void show_dynamics_values(project_window& /*sim*/, const qss2_integrator& dyn) { ImGui::TextFormat("X {}", dyn.X); - ImGui::TextFormat("dQ {}", dyn.default_dQ); + ImGui::TextFormat("dQ {}", dyn.dQ); } static void show_dynamics_values(project_window& /*sim*/, const qss3_integrator& dyn) { ImGui::TextFormat("X {}", dyn.X); - ImGui::TextFormat("dQ {}", dyn.default_dQ); + ImGui::TextFormat("dQ {}", dyn.dQ); } static void show_dynamics_values(project_window& /*sim*/, const qss1_sum_2& dyn) @@ -519,7 +519,9 @@ static void show_dynamics_values(project_window& /*sim*/, ImGui::TextFormat("sigma={}", dyn.exec.timer); } -static void show_model_dynamics(project_window& ed, model& mdl) noexcept +static void show_model_dynamics(application& app, + project_window& ed, + model& mdl) noexcept { dispatch(mdl, [&](Dynamics& dyn) { add_input_attribute(ed, dyn); @@ -534,7 +536,11 @@ static void show_model_dynamics(project_window& ed, model& mdl) noexcept if (ed.allow_user_changes) { ImGui::PushID(1); ImGui::PushItemWidth(120.0f); - show_dynamics_inputs(ed, dyn); + show_parameter_editor( + app, + ed, + mdl.type, + ed.pj.sim.parameters[get_index(ed.pj.sim.models.get_id(mdl))]); ImGui::PopItemWidth(); ImGui::PopID(); } @@ -543,7 +549,7 @@ static void show_model_dynamics(project_window& ed, model& mdl) noexcept }); } -void show_top_with_identifier(application& /*app*/, project_window& ed) noexcept +void show_top_with_identifier(application& app, project_window& ed) noexcept { for_each_data(ed.pj.sim.models, [&](model& mdl) noexcept -> void { const auto mdl_id = ed.pj.sim.models.get_id(mdl); @@ -556,13 +562,12 @@ void show_top_with_identifier(application& /*app*/, project_window& ed) noexcept "{}\n{}", mdl_index, dynamics_type_names[ordinal(mdl.type)]); ImNodes::EndNodeTitleBar(); - show_model_dynamics(ed, mdl); + show_model_dynamics(app, ed, mdl); ImNodes::EndNode(); }); } -void show_top_without_identifier(application& /*app*/, - project_window& ed) noexcept +void show_top_without_identifier(application& app, project_window& ed) noexcept { for_each_data(ed.pj.sim.models, [&](model& mdl) noexcept -> void { const auto mdl_id = ed.pj.sim.models.get_id(mdl); @@ -572,7 +577,7 @@ void show_top_without_identifier(application& /*app*/, ImNodes::BeginNodeTitleBar(); ImGui::TextUnformatted(dynamics_type_names[ordinal(mdl.type)]); ImNodes::EndNodeTitleBar(); - show_model_dynamics(ed, mdl); + show_model_dynamics(app, ed, mdl); ImNodes::EndNode(); }); } diff --git a/lib/include/irritator/core.hpp b/lib/include/irritator/core.hpp index 08a93e8a..efc9c760 100644 --- a/lib/include/irritator/core.hpp +++ b/lib/include/irritator/core.hpp @@ -20,15 +20,6 @@ #include #include -#ifdef __has_include -#if __has_include() -#include -#define irt_have_numbers 1 -#else -#define irt_have_numbers 0 -#endif -#endif - #include #include @@ -341,6 +332,7 @@ using message = std::array; using dated_message = std::array; using observation_message = std::array; +struct parameter; struct model; class simulation; class hierarchical_state_machine; @@ -849,6 +841,53 @@ constexpr sz dynamics_type_size() noexcept * ****************************************************************************/ +//! Stores default values for all @c irt::dynamics. +struct parameter { + parameter() noexcept = default; + + //! Import values from the model @c mdl according to the underlying @c + //! irt::dynamics_type. + parameter(const model& mdl) noexcept; + + //! Initialize values from the default dynamics type. + parameter(const dynamics_type type) noexcept; + + //! Copy data from the vectors to the simulation model. + void copy_to(model& mdl) const noexcept; + + //! Copy data from model to the vectors of this parameter. + void copy_from(const model& mdl) noexcept; + + //! Initialize data from dynamics type default values. + void init_from(const dynamics_type type) noexcept; + + //! Assign @c 0 to reals and integers arrays. + void clear() noexcept; + + parameter& set_constant(real value, real offset) noexcept; + parameter& set_cross(real threshold, bool detect_up) noexcept; + parameter& set_integrator(real X, real dQ) noexcept; + parameter& set_time_func(real offset, real timestep, int type) noexcept; + parameter& set_wsum2(real v1, real coeff1, real v2, real coeff2) noexcept; + parameter& set_wsum3(real v1, + real coeff1, + real v2, + real coeff2, + real v3, + real coeff3) noexcept; + parameter& set_wsum4(real v1, + real coeff1, + real v2, + real coeff2, + real v3, + real coeff3, + real v4, + real coeff4) noexcept; + + std::array reals; + std::array integers; +}; + struct observation { observation() noexcept = default; observation(const real x_, const real y_) noexcept @@ -1150,6 +1189,9 @@ class simulation vector immediate_models; vector immediate_observers; + /** A vector of the size of @c models data_array. */ + vector parameters; + data_array models; data_array hsms; data_array observers; @@ -1223,7 +1265,7 @@ class simulation //! @brief This function allocates dynamics and models. model& alloc(dynamics_type type) noexcept; - void observe(model& mdl, observer& obs) noexcept; + void observe(model& mdl, observer& obs) const noexcept; void unobserve(model& mdl) noexcept; @@ -1372,8 +1414,7 @@ template<> struct abstract_integrator<1> { message_id x[2]; node_id y[1]; - real default_X = zero; - real default_dQ = irt::real(0.01); + real dQ; real X; real q; real u; @@ -1387,8 +1428,7 @@ struct abstract_integrator<1> { abstract_integrator() = default; abstract_integrator(const abstract_integrator& other) noexcept - : default_X(other.default_X) - , default_dQ(other.default_dQ) + : dQ(other.dQ) , X(other.X) , q(other.q) , u(other.u) @@ -1397,14 +1437,13 @@ struct abstract_integrator<1> { status initialize(simulation& /*sim*/) noexcept { - if (!std::isfinite(default_X)) + if (!std::isfinite(X)) return new_error(X_error{}); - if (!(std::isfinite(default_dQ) && default_dQ > zero)) + if (!(std::isfinite(dQ) && dQ > zero)) return new_error(dQ_error{}); - X = default_X; - q = std::floor(X / default_dQ) * default_dQ; + q = std::floor(X / dQ) * dQ; u = zero; sigma = time_domain