Commit f5d22912 authored by K-H-Ismail's avatar K-H-Ismail Committed by Gauthier Quesnel
Browse files

core: add cross model and integrator reset

parent c4a413e7
...@@ -13,7 +13,7 @@ ...@@ -13,7 +13,7 @@
#include <cmath> #include <cmath>
#include <cstdint> #include <cstdint>
#include <cstring> #include <cstring>
//#include <iostream>
namespace irt { namespace irt {
using i8 = int8_t; using i8 = int8_t;
...@@ -93,6 +93,10 @@ enum class status ...@@ -93,6 +93,10 @@ enum class status
model_constant_empty_init_message, model_constant_empty_init_message,
model_constant_bad_init_message, model_constant_bad_init_message,
model_cross_empty_init_message,
model_cross_bad_init_message,
model_cross_bad_external_message,
}; };
constexpr bool constexpr bool
...@@ -2467,7 +2471,8 @@ enum class dynamics_type : i8 ...@@ -2467,7 +2471,8 @@ enum class dynamics_type : i8
mult_4, mult_4,
counter, counter,
generator, generator,
constant constant,
cross
}; };
struct model struct model
...@@ -2797,6 +2802,98 @@ struct constant ...@@ -2797,6 +2802,98 @@ struct constant
return status::success; return status::success;
} }
}; };
struct cross
{
model_id id;
input_port_id x[3];
output_port_id y[1];
time sigma;
double threshold;
double value = threshold - 1.0;
double if_value = 0.0;
double else_value = 0.0;
enum port_name
{
port_value,
port_if_value,
port_else_value
};
status initialize(data_array<message, message_id>& init_messages) noexcept
{
sigma = time_domain<time>::zero;
return status::success;
}
status transition(data_array<input_port, input_port_id>& input_ports,
time /*t*/,
time /*e*/,
time /*r*/) noexcept
{
bool have_message = false;
if (auto* port = input_ports.try_to_get(x[port_value]); port) {
for (const auto& msg : port->messages) {
irt_return_if_fail(
msg.type == value_type::real_64,
status::model_cross_bad_external_message);
irt_return_if_fail(
msg.size() == 1,
status::model_cross_bad_external_message);
value = msg.to_real_64(0) ;
have_message = true;
}
}
if (auto* port = input_ports.try_to_get(x[port_if_value]); port) {
for (const auto& msg : port->messages) {
irt_return_if_fail(
msg.type == value_type::real_64,
status::model_cross_bad_external_message);
irt_return_if_fail(
msg.size() == 1,
status::model_cross_bad_external_message);
if_value = msg.to_real_64(0);
}
}
if (auto* port = input_ports.try_to_get(x[port_else_value]); port) {
for (const auto& msg : port->messages) {
irt_return_if_fail(
msg.type == value_type::real_64,
status::model_cross_bad_external_message);
irt_return_if_fail(
msg.size() == 1,
status::model_cross_bad_external_message);
else_value = msg.to_real_64(0);
}
}
sigma =
have_message ? time_domain<time>::zero : time_domain<time>::infinity;
return status::success;
}
status lambda(
data_array<output_port, output_port_id>& output_ports) noexcept
{
double output_value = 0.0;
if (auto* port = output_ports.try_to_get(y[0]); port) {
output_value = value >= threshold ? if_value : else_value;
port->messages.emplace_front(output_value);
}
return status::success;
}
};
struct none struct none
{ {
...@@ -2808,13 +2905,14 @@ struct integrator ...@@ -2808,13 +2905,14 @@ struct integrator
{ {
model_id id; model_id id;
time sigma = time_domain<time>::zero; time sigma = time_domain<time>::zero;
input_port_id x[2]; input_port_id x[3];
output_port_id y[1]; output_port_id y[1];
enum port_name enum port_name
{ {
port_quanta, port_quanta,
port_x_dot port_x_dot,
port_reset
}; };
enum class state enum class state
...@@ -2830,7 +2928,9 @@ struct integrator ...@@ -2830,7 +2928,9 @@ struct integrator
double down_threshold = 0.0; double down_threshold = 0.0;
double last_output_value = 0.0; double last_output_value = 0.0;
double current_value = 0.0; double current_value = 0.0;
double expected_value = 0.0; double expected_value = 0.0;
bool reset = false;
double reset_value;
flat_double_list<record> archive; flat_double_list<record> archive;
state st = state::init; state st = state::init;
...@@ -2844,6 +2944,7 @@ struct integrator ...@@ -2844,6 +2944,7 @@ struct integrator
status external(input_port& port_quanta, status external(input_port& port_quanta,
input_port& port_x_dot, input_port& port_x_dot,
input_port& port_reset,
time t) noexcept time t) noexcept
{ {
for (const auto& msg : port_quanta.messages) { for (const auto& msg : port_quanta.messages) {
...@@ -2875,6 +2976,15 @@ struct integrator ...@@ -2875,6 +2976,15 @@ struct integrator
st = state::wait_for_quanta; st = state::wait_for_quanta;
} }
for (const auto& msg : port_reset.messages) {
irt_return_if_fail(msg.type == value_type::real_64 &&
msg.size() == 1,
status::model_integrator_bad_external_message);
reset_value = msg.to_real_64(0);
reset = true;
}
if (st == state::running) { if (st == state::running) {
current_value = compute_current_value(t); current_value = compute_current_value(t);
expected_value = compute_expected_value(); expected_value = compute_expected_value();
...@@ -2912,14 +3022,15 @@ struct integrator ...@@ -2912,14 +3022,15 @@ struct integrator
{ {
auto* port_1 = input_ports.try_to_get(x[port_quanta]); auto* port_1 = input_ports.try_to_get(x[port_quanta]);
auto* port_2 = input_ports.try_to_get(x[port_x_dot]); auto* port_2 = input_ports.try_to_get(x[port_x_dot]);
auto* port_3 = input_ports.try_to_get(x[port_reset]);
if (port_1->messages.empty() && port_2->messages.empty()) { if (port_1->messages.empty() && port_2->messages.empty() && port_3->messages.empty()) {
irt_return_if_bad(internal(t)); irt_return_if_bad(internal(t));
} else { } else {
if (time_domain<time>::is_zero(r)) if (time_domain<time>::is_zero(r))
irt_return_if_bad(internal(t)); irt_return_if_bad(internal(t));
irt_return_if_bad(external(*port_1, *port_2, t)); irt_return_if_bad(external(*port_1, *port_2, *port_3, t));
} }
return ta(); return ta();
...@@ -2982,7 +3093,7 @@ private: ...@@ -2982,7 +3093,7 @@ private:
if (archive.empty()) if (archive.empty())
return last_output_value; return last_output_value;
auto val = last_output_value; auto val = reset ? reset_value : last_output_value;
auto end = archive.end(); auto end = archive.end();
auto it = archive.begin(); auto it = archive.begin();
auto next = archive.begin(); auto next = archive.begin();
...@@ -3445,6 +3556,7 @@ struct simulation ...@@ -3445,6 +3556,7 @@ struct simulation
data_array<counter, dynamics_id> counter_models; data_array<counter, dynamics_id> counter_models;
data_array<generator, dynamics_id> generator_models; data_array<generator, dynamics_id> generator_models;
data_array<constant, dynamics_id> constant_models; data_array<constant, dynamics_id> constant_models;
data_array<cross, dynamics_id> cross_models;
scheduller sched; scheduller sched;
...@@ -3483,6 +3595,7 @@ struct simulation ...@@ -3483,6 +3595,7 @@ struct simulation
irt_return_if_bad(counter_models.init(model_capacity)); irt_return_if_bad(counter_models.init(model_capacity));
irt_return_if_bad(generator_models.init(model_capacity)); irt_return_if_bad(generator_models.init(model_capacity));
irt_return_if_bad(constant_models.init(model_capacity)); irt_return_if_bad(constant_models.init(model_capacity));
irt_return_if_bad(cross_models.init(model_capacity));
return status::success; return status::success;
} }
...@@ -3530,8 +3643,10 @@ struct simulation ...@@ -3530,8 +3643,10 @@ struct simulation
mdl.type = dynamics_type::counter; mdl.type = dynamics_type::counter;
else if constexpr (std::is_same_v<Dynamics, generator>) else if constexpr (std::is_same_v<Dynamics, generator>)
mdl.type = dynamics_type::generator; mdl.type = dynamics_type::generator;
else else if constexpr (std::is_same_v<Dynamics, constant>)
mdl.type = dynamics_type::constant; mdl.type = dynamics_type::constant;
else
mdl.type = dynamics_type::cross;
if constexpr (is_detected_v<initialize_function_t, Dynamics>) { if constexpr (is_detected_v<initialize_function_t, Dynamics>) {
//if constexpr (is_detected_v<has_init_port_t, Dynamics>) { //if constexpr (is_detected_v<has_init_port_t, Dynamics>) {
...@@ -3716,6 +3831,8 @@ struct simulation ...@@ -3716,6 +3831,8 @@ struct simulation
return make_transition(mdl, generator_models.get(mdl.id), t, o); return make_transition(mdl, generator_models.get(mdl.id), t, o);
case dynamics_type::constant: case dynamics_type::constant:
return make_transition(mdl, constant_models.get(mdl.id), t, o); return make_transition(mdl, constant_models.get(mdl.id), t, o);
case dynamics_type::cross:
return make_transition(mdl, cross_models.get(mdl.id), t, o);
} }
return make_transition(mdl, none_models.get(mdl.id), t, o); return make_transition(mdl, none_models.get(mdl.id), t, o);
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment