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

core: adding time_func model

This model permits through a lambda function to applyt t -> f(t).

- adding tests for time_func model and adpting Izhikevitch simulation
- update public-api.cpp
parent bd5c847b
......@@ -13,7 +13,8 @@
#include <cmath>
#include <cstdint>
#include <cstring>
//#include <iostream>
namespace irt {
using i8 = int8_t;
......@@ -97,6 +98,9 @@ enum class status
model_cross_empty_init_message,
model_cross_bad_init_message,
model_cross_bad_external_message,
model_time_func_empty_init_message,
model_time_func_bad_init_message,
};
constexpr bool
......@@ -2472,7 +2476,8 @@ enum class dynamics_type : i8
counter,
generator,
constant,
cross
cross,
time_func
};
struct model
......@@ -2802,6 +2807,42 @@ struct constant
return status::success;
}
};
struct time_func
{
model_id id;
output_port_id y[1];
time sigma;
double value;
double (*f)(double);
status initialize(data_array<message, message_id>& init_messages) noexcept
{
sigma = 1.0;
value = sigma;
return status::success;
}
status transition(data_array<input_port, input_port_id>& input_ports,
time t,
time /*e*/,
time /*r*/) noexcept
{
sigma = (*f)(t) ;
value = sigma;
return status::success;
}
status lambda(
data_array<output_port, output_port_id>& output_ports) noexcept
{
auto& port = output_ports.get(y[0]);
port.messages.emplace_front(value);
return status::success;
}
};
struct cross
{
model_id id;
......@@ -2847,6 +2888,7 @@ struct cross
status::model_cross_bad_external_message);
value = msg.to_real_64(0) ;
have_message = true;
}
}
......@@ -2862,6 +2904,7 @@ struct cross
status::model_cross_bad_external_message);
if_value = msg.to_real_64(0);
have_message = true;
}
}
if (auto* port = input_ports.try_to_get(x[port_else_value]); port) {
......@@ -2875,6 +2918,7 @@ struct cross
status::model_cross_bad_external_message);
else_value = msg.to_real_64(0);
have_message = true;
}
}
......@@ -3557,6 +3601,7 @@ struct simulation
data_array<generator, dynamics_id> generator_models;
data_array<constant, dynamics_id> constant_models;
data_array<cross, dynamics_id> cross_models;
data_array<time_func, dynamics_id> time_func_models;
scheduller sched;
......@@ -3596,6 +3641,7 @@ struct simulation
irt_return_if_bad(generator_models.init(model_capacity));
irt_return_if_bad(constant_models.init(model_capacity));
irt_return_if_bad(cross_models.init(model_capacity));
irt_return_if_bad(time_func_models.init(model_capacity));
return status::success;
}
......@@ -3645,8 +3691,10 @@ struct simulation
mdl.type = dynamics_type::generator;
else if constexpr (std::is_same_v<Dynamics, constant>)
mdl.type = dynamics_type::constant;
else
else if constexpr (std::is_same_v<Dynamics, cross>)
mdl.type = dynamics_type::cross;
else
mdl.type = dynamics_type::time_func;
if constexpr (is_detected_v<initialize_function_t, Dynamics>) {
//if constexpr (is_detected_v<has_init_port_t, Dynamics>) {
......@@ -3833,6 +3881,8 @@ struct simulation
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);
case dynamics_type::time_func:
return make_transition(mdl, time_func_models.get(mdl.id), t, o);
}
return make_transition(mdl, none_models.get(mdl.id), t, o);
......
......@@ -87,7 +87,7 @@ dot_graph_save(const irt::simulation& sim, std::FILE* os)
}
}
}
double f (double t) {return t*t;}
int
main()
{
......@@ -734,6 +734,42 @@ main()
expect(cnt.number == 9_ul);
};
"time_func"_test = [] {
irt::simulation sim;
expect(irt::is_success(sim.init(16lu, 256lu)));
expect(sim.time_func_models.can_alloc(1));
expect(sim.counter_models.can_alloc(1));
auto& time_fun = sim.time_func_models.alloc();
auto& cnt = sim.counter_models.alloc();
double f(double t);
time_fun.f = &f;
expect(sim.models.can_alloc(2));
expect(irt::is_success(sim.alloc(time_fun, sim.time_func_models.get_id(time_fun))));
expect(irt::is_success(sim.alloc(cnt, sim.counter_models.get_id(cnt))));
expect(sim.connect(time_fun.y[0], cnt.x[0]) == irt::status::success);
expect(sim.begin == irt::time_domain<irt::time>::zero);
expect(sim.end == irt::time_domain<irt::time>::infinity);
sim.end = 30.0;
irt::time t = sim.begin;
irt::status st;
do {
st = sim.run(t);
expect(irt::is_success(st));
expect(time_fun.value == t*t);
expect(cnt.number <= static_cast<long unsigned>(t));
} while (t < sim.end);
};
"lotka_volterra_simulation"_test = [] {
irt::simulation sim;
......@@ -865,18 +901,18 @@ main()
irt::simulation sim;
expect(irt::is_success(sim.init(64lu, 256lu)));
expect(sim.constant_models.can_alloc(4));
expect(sim.constant_models.can_alloc(2));
expect(sim.adder_2_models.can_alloc(3));
expect(sim.adder_4_models.can_alloc(1));
expect(sim.mult_2_models.can_alloc(1));
expect(sim.integrator_models.can_alloc(2));
expect(sim.quantifier_models.can_alloc(2));
expect(sim.cross_models.can_alloc(2));
expect(sim.time_func_models.can_alloc(1));
auto& c1 = sim.constant_models.alloc();
auto& c2 = sim.constant_models.alloc();
auto& c3 = sim.constant_models.alloc();
auto& c4 = sim.constant_models.alloc();
auto& time_fun = sim.time_func_models.alloc();
auto& constant = sim.constant_models.alloc();
auto& constant2 = sim.constant_models.alloc();
auto& sum_a = sim.adder_2_models.alloc();
auto& sum_b = sim.adder_2_models.alloc();
auto& sum_c = sim.adder_4_models.alloc();
......@@ -889,14 +925,13 @@ main()
auto& cross = sim.cross_models.alloc();
auto& cross2 = sim.cross_models.alloc();
double a = 0.2;
double b = 2.0;
double c = -56.0;
double d = -16.0;
double I = -99.0;
double vt = 30.0;
double f(double);
integrator_a.current_value = 0.0;
......@@ -922,24 +957,26 @@ main()
sum_b.input_coeffs[1] = a*b;
sum_c.input_coeffs[0] = 0.04;
sum_c.input_coeffs[1] = 5.0;
sum_c.input_coeffs[2] = 1.0;
sum_c.input_coeffs[2] = 140.0;
sum_c.input_coeffs[3] = 1.0;
sum_d.input_coeffs[0] = 1.0;
sum_d.input_coeffs[1] = 1.0;
c1.value = 140.0;
c2.value = I;
c3.value = c;
c4.value = d;
sum_d.input_coeffs[1] = d;
constant.value = 1.0;
constant2.value = c;
cross.threshold = vt;
cross2.threshold = vt;
time_fun.f = &f;
expect(sim.models.can_alloc(12));
!expect(irt::is_success(
sim.alloc(c1, sim.constant_models.get_id(c1),"140")));
sim.alloc(time_fun, sim.time_func_models.get_id(time_fun),"tfun")));
!expect(irt::is_success(
sim.alloc(c2, sim.constant_models.get_id(c2),"I")));
sim.alloc(constant, sim.constant_models.get_id(constant),"1.0")));
!expect(irt::is_success(
sim.alloc(c3, sim.constant_models.get_id(c3),"c")));
sim.alloc(constant2, sim.constant_models.get_id(constant2),"-56.0")));
!expect(irt::is_success(
sim.alloc(sum_a, sim.adder_2_models.get_id(sum_a), "sum_a")));
......@@ -969,7 +1006,7 @@ main()
expect(sim.connect(integrator_a.y[0], cross.x[0]) ==
irt::status::success);
expect(sim.connect(c3.y[0], cross.x[1]) ==
expect(sim.connect(constant2.y[0], cross.x[1]) ==
irt::status::success);
expect(sim.connect(integrator_a.y[0], cross.x[2]) ==
irt::status::success);
......@@ -987,9 +1024,9 @@ main()
expect(sim.connect( cross.y[0], sum_b.x[1]) ==
irt::status::success);
expect(sim.connect(c1.y[0] ,sum_c.x[2]) ==
expect(sim.connect(constant.y[0] ,sum_c.x[2]) ==
irt::status::success);
expect(sim.connect(c2.y[0] ,sum_c.x[3]) ==
expect(sim.connect(time_fun.y[0] ,sum_c.x[3]) ==
irt::status::success);
expect(sim.connect(sum_c.y[0],sum_a.x[0]) ==
......
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