-
Sam Yates authored6866ad5d
model.hpp 4.02 KiB
#pragma once
#include <cstdlib>
#include <vector>
#include <common_types.hpp>
#include <cell.hpp>
#include <cell_group.hpp>
#include <communication/communicator.hpp>
#include <communication/global_policy.hpp>
#include <fvm_cell.hpp>
#include <recipe.hpp>
#include <profiling/profiler.hpp>
#include "trace_sampler.hpp"
namespace nest {
namespace mc {
template <typename Cell>
class model {
public:
using cell_group_type = cell_group<Cell>;
using time_type = typename cell_group_type::time_type;
using value_type = typename cell_group_type::value_type;
using communicator_type = communication::communicator<time_type, communication::global_policy>;
using sampler_function = typename cell_group_type::sampler_function;
struct probe_record {
cell_member_type id;
probe_spec probe;
};
model(const recipe& rec, cell_gid_type cell_from, cell_gid_type cell_to):
cell_from_(cell_from),
cell_to_(cell_to),
communicator_(cell_from, cell_to)
{
cell_groups_ = std::vector<cell_group_type>{cell_to_-cell_from_};
threading::parallel_vector<probe_record> probes;
threading::parallel_for::apply(cell_from_, cell_to_,
[&](cell_gid_type i) {
PE("setup", "cells");
auto cell = rec.get_cell(i);
auto idx = i-cell_from_;
cell_groups_[idx] = cell_group_type(i, cell);
cell_lid_type j = 0;
for (const auto& probe: cell.probes()) {
cell_member_type probe_id{i,j++};
probes.push_back({probe_id, probe});
}
PL(2);
});
probes_.assign(probes.begin(), probes.end());
for (cell_gid_type i=cell_from_; i<cell_to_; ++i) {
for (const auto& cc: rec.connections_on(i)) {
connection<time_type> conn{cc.source, cc.dest, cc.weight, cc.delay};
communicator_.add_connection(conn);
}
}
communicator_.construct();
}
void reset() {
t_ = 0.;
for (auto& group: cell_groups_) {
group.reset();
}
communicator_.reset();
}
time_type run(time_type tfinal, time_type dt) {
time_type min_delay = communicator_.min_delay();
while (t_<tfinal) {
auto tuntil = std::min(t_+min_delay, tfinal);
threading::parallel_for::apply(
0u, cell_groups_.size(),
[&](unsigned i) {
auto& group = cell_groups_[i];
PE("stepping","events");
group.enqueue_events(communicator_.queue(i));
PL();
group.advance(tuntil, dt);
PE("events");
communicator_.add_spikes(group.spikes());
group.clear_spikes();
PL(2);
});
PE("stepping", "exchange");
communicator_.exchange();
PL(2);
t_ = tuntil;
}
return t_;
}
void add_artificial_spike(cell_member_type source) {
add_artificial_spike(source, t_);
}
void add_artificial_spike(cell_member_type source, time_type tspike) {
communicator_.add_spike({source, tspike});
}
void attach_sampler(cell_member_type probe_id, sampler_function f, time_type tfrom = 0) {
// TODO: translate probe_id.gid to appropriate group, but for now 1-1.
if (probe_id.gid<cell_from_ || probe_id.gid>=cell_to_) {
return;
}
cell_groups_[probe_id.gid-cell_from_].add_sampler(probe_id, f, tfrom);
}
const std::vector<probe_record>& probes() const { return probes_; }
std::size_t num_spikes() const { return communicator_.num_spikes(); }
private:
cell_gid_type cell_from_;
cell_gid_type cell_to_;
time_type t_ = 0.;
std::vector<cell_group_type> cell_groups_;
communicator_type communicator_;
std::vector<probe_record> probes_;
};
} // namespace mc
} // namespace nest