Utopia 2
Framework for studying models of complex & adaptive systems.
Loading...
Searching...
No Matches
SimpleFlocking.hh
Go to the documentation of this file.
1#ifndef UTOPIA_MODELS_SIMPLEFLOCKING_HH
2#define UTOPIA_MODELS_SIMPLEFLOCKING_HH
3
4#include <random>
5#include <functional>
6
10#include <utopia/core/apply.hh>
11
12#include "state.hh"
13
14
16
17// ++ Type definitions ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
18
21
23
27
28
29
30
31// ++ Model definition ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
33
40 public Model<SimpleFlocking, ModelTypes>
41{
42public:
45
48
51
53 using AgentPtr = std::shared_ptr<Agent>;
54
56 using Rule = typename AgentManager::RuleFunc;
57
60
63
65 using DataSet = typename Base::DataSet;
66
67
68private:
69 // -- Members -------------------------------------------------------------
70
73
74 // .. Global parameters ...................................................
75
77 double _speed;
78
81
84
85
86 // .. Temporary and helper objects ........................................
87
89 std::uniform_real_distribution<double> _noise_distr;
90
91
92 // .. Output-related ......................................................
95
96 // Agent-specific datasets
97 std::shared_ptr<DataSet> _dset_agent_x;
98 std::shared_ptr<DataSet> _dset_agent_y;
99 std::shared_ptr<DataSet> _dset_agent_orientation;
100
101 // Global observables
102 std::shared_ptr<DataSet> _dset_orientation_circmean;
103 std::shared_ptr<DataSet> _dset_orientation_circstd;
104 std::shared_ptr<DataSet> _dset_norm_group_velocity;
105
106
107public:
108 // -- Model Setup ---------------------------------------------------------
109
111
119 template<class ParentModel>
121 const std::string& name,
123 const DataIO::Config& custom_cfg = {}
124 )
125 :
127
128 , _am(*this)
129
130 , _speed(get_as<double>("speed", this->_cfg))
131 , _interaction_radius(get_as<double>("interaction_radius", this->_cfg))
132 , _noise_level(get_as<double>("noise_level", this->_cfg))
133
135
136 // .. Output-related ......................................................
137 , _store_agent_data(get_as<bool>("store_agent_data", this->_cfg))
138
139 , _dset_agent_x(this->create_am_dset("agent/x", _am))
140 , _dset_agent_y(this->create_am_dset("agent/y", _am))
141 , _dset_agent_orientation(this->create_am_dset("agent/orientation", _am))
142
144 this->create_dset("orientation_circmean", {})
145 )
147 this->create_dset("orientation_circstd", {})
148 )
150 this->create_dset("norm_group_velocity", {})
151 )
152 {
154
155 this->_log->info("{} all set up.", this->_name);
156 this->_log->info(" Store agent data? {}", _store_agent_data);
157 }
158
159
160private:
161 // .. Setup functions .....................................................
162
163 // .. Helper functions ....................................................
164
165public:
166 // -- Public Interface ----------------------------------------------------
167 // .. Simulation Control ..................................................
168
170
176
177
179
184 void monitor () {
185 const auto orientations = get_from_agents([](const auto& agent){
186 return agent->state().get_orientation();
187 });
188
190 this->_monitor.set_entry("orientation_mean", circ_mean);
191 this->_monitor.set_entry("orientation_std", circ_std);
192 this->_monitor.set_entry("norm_group_velocity", norm_group_velocity());
193 }
194
195
197 void write_data () {
198 using WriteT = float;
199 const auto& agents = _am.agents();
200
201 // -- Global observables
202 const auto orientations = get_from_agents([](const auto& agent){
203 return agent->state().get_orientation();
204 });
205
209
211
212 // -- Agent-specific data
213 // ... only stored optionally
214 if (not _store_agent_data) return;
215
216 _dset_agent_x->write(
217 agents.begin(), agents.end(),
218 [](const auto& agent) {
219 return static_cast<WriteT>(agent->position()[0]);
220 });
221
222 _dset_agent_y->write(
223 agents.begin(), agents.end(),
224 [](const auto& agent) {
225 return static_cast<WriteT>(agent->position()[1]);
226 });
227
229 orientations.begin(), orientations.end(),
230 [](const auto& orientation) {
231 return static_cast<WriteT>(orientation);
232 });
233 }
234
235
236 // Getters and setters ....................................................
237
239 std::size_t num_agents () const {
240 return _am.agents().size();
241 }
242
244 void set_agent_speed (const double new_speed) {
245 this->_log->info("Setting all agent's speed to {} ...", new_speed);
247 [speed=new_speed](const auto& agent){
248 auto state = agent->state();
249 state.set_speed(speed);
250 return state;
251 },
252 this->_am.agents()
253 );
254 }
255
257
266 double norm_group_velocity () const {
267 const auto velocities = get_from_agents([](const auto& agent){
268 return agent->state().get_displacement();
269 });
270 return absolute_group_velocity(velocities) / std::fabs(_speed);
271 }
272
274 template<
275 class Adapter,
276 class ValueType = std::invoke_result_t<Adapter, const AgentPtr&>
277 >
278 std::vector<ValueType> get_from_agents (const Adapter& adapter) const {
279 std::vector<ValueType> cont;
280 cont.reserve(num_agents());
281
283 this->_am.agents().begin(), this->_am.agents().end(),
284 std::back_inserter(cont), adapter
285 );
286 return cont;
287 }
288
289
290 // Rules ..................................................................
291
293
298 const Rule _adjust_orientation = [this](const auto& agent){
299 auto state = agent->state();
300
301 // Find all agents within the interaction radius and compute their
302 // average orientation, including (!) the current agent.
303 // To find an average orientation, we need to separate the x- and y-
304 // components and later combine them back into an angle.
305 auto agg_sin = std::sin(agent->state().get_orientation());
306 auto agg_cos = std::cos(agent->state().get_orientation());
307
308 // NOTE The AgentManager::neighbors_of method finds neighbors with
309 // linear complexity in agent number, leading to an overall
310 // quadratic complexity in agent number for this search.
311 // This can be mitigated (on the level of the AgentManager!) by
312 // using a spatially restricted search or a lookup grid.
313 for (const auto& nb :
315 {
316 agg_sin += std::sin(nb->state().get_orientation());
317 agg_cos += std::cos(nb->state().get_orientation());
318 }
319
320 // Can now set the orientation, including noise
321 // NOTE Could divide by number of involved agents here, but that is
322 // unnecessary because it cancels out through division anyway.
323 state.set_orientation(
324 std::atan2(agg_sin, agg_cos) +
325 (this->_noise_level > 0. ? _noise_distr(*this->_rng) : 0.)
326 );
327
328 return state;
329 };
330
332 const VoidRule _move = [this](const auto& agent){
333 this->_am.move_by(agent, agent->state().get_displacement());
334 };
335
336};
337
338
339} // namespace Utopia::Models::SimpleFlocking
340
341#endif // UTOPIA_MODELS_SIMPLEFLOCKING_HH
An agent is a slightly specialized state container.
Definition agent.hh:47
const AgentContainer< Agent > & agents() const
Return const reference to the managed agents.
Definition agent_manager.hh:184
void move_by(const std::shared_ptr< Agent > &agent, const SpaceVec &move_vec) const
Move an agent relative to its current position.
Definition agent_manager.hh:214
SpaceVecType< dim > SpaceVec
The type of the vectors that represent physical quantities.
Definition agent_manager.hh:52
std::function< void(const std::shared_ptr< Agent > &)> VoidRuleFunc
The type of a void rule function acting on agents of this agent manager.
Definition agent_manager.hh:70
std::function< AgentState(const std::shared_ptr< Agent > &)> RuleFunc
The type of a rule function acting on agents of this agent manager.
Definition agent_manager.hh:64
AgentContainer< Agent > neighbors_of(const std::shared_ptr< Agent > &agent, const double radius) const
Returns a container of all agents within a certain radius.
Definition agent_manager.hh:434
Utopia::Agent< AgentTraits, Space > Agent
The type of the managed agents.
Definition agent_manager.hh:40
Base class interface for Models using the CRT Pattern.
Definition model.hh:112
Monitor _monitor
The monitor.
Definition model.hh:188
typename ModelTypes::DataSet DataSet
Data type that is used for storing data.
Definition model.hh:125
const Config _cfg
Config node belonging to this model instance.
Definition model.hh:158
const std::string _name
Name of the model instance.
Definition model.hh:149
std::shared_ptr< DataSet > create_am_dset(const std::string name, const AgentManager &am, const std::size_t compression_level=1, const std::vector< hsize_t > chunksize={})
Create a dataset storing data from a AgentManager.
Definition model.hh:939
const std::shared_ptr< spdlog::logger > _log
The (model) logger.
Definition model.hh:164
const std::shared_ptr< RNG > _rng
The RNG shared between models.
Definition model.hh:161
std::shared_ptr< DataSet > create_dset(const std::string name, const std::shared_ptr< DataGroup > &hdfgrp, std::vector< hsize_t > add_write_shape, const std::size_t compression_level=1, const std::vector< hsize_t > chunksize={})
Create a new dataset within the given group.
Definition model.hh:752
The SimpleFlocking Model.
Definition SimpleFlocking.hh:41
double _interaction_radius
The radius within which agents interact with each other.
Definition SimpleFlocking.hh:80
std::shared_ptr< DataSet > _dset_agent_orientation
Definition SimpleFlocking.hh:99
void perform_step()
Iterate a single step: adjust agent orientation, then move all agents.
Definition SimpleFlocking.hh:172
AgentManager _am
The agent manager.
Definition SimpleFlocking.hh:72
std::shared_ptr< DataSet > _dset_agent_x
Definition SimpleFlocking.hh:97
void write_data()
Write data.
Definition SimpleFlocking.hh:197
const VoidRule _move
Rule that applies the current displacement vector to the agent position.
Definition SimpleFlocking.hh:332
Model< SimpleFlocking, ModelTypes > Base
The type of the Model base class of this derived class.
Definition SimpleFlocking.hh:44
std::shared_ptr< DataSet > _dset_norm_group_velocity
Definition SimpleFlocking.hh:104
std::shared_ptr< Agent > AgentPtr
Pointer to agent.
Definition SimpleFlocking.hh:53
typename AgentManager::VoidRuleFunc VoidRule
Type of the update rules for agents where no state is to be returned.
Definition SimpleFlocking.hh:59
std::size_t num_agents() const
The number of agents in the system (typically constant)
Definition SimpleFlocking.hh:239
double _noise_level
The amplitude of the noise applied to the orientation update.
Definition SimpleFlocking.hh:83
typename Base::DataSet DataSet
Data type for a dataset.
Definition SimpleFlocking.hh:65
SimpleFlocking(const std::string &name, ParentModel &parent_model, const DataIO::Config &custom_cfg={})
Construct the SimpleFlocking model instance.
Definition SimpleFlocking.hh:120
std::uniform_real_distribution< double > _noise_distr
The distribution used for determining the orientation noise.
Definition SimpleFlocking.hh:89
double _speed
The global speed value, used as the uniform speed of all agents.
Definition SimpleFlocking.hh:77
const Rule _adjust_orientation
Rule that sets agent orientation to the mean orientation (in a radius)
Definition SimpleFlocking.hh:298
void monitor()
Monitor the model state.
Definition SimpleFlocking.hh:184
std::vector< ValueType > get_from_agents(const Adapter &adapter) const
Aggregate agent properties into a container.
Definition SimpleFlocking.hh:278
std::shared_ptr< DataSet > _dset_orientation_circmean
Definition SimpleFlocking.hh:102
double norm_group_velocity() const
The normalized absolute group velocity.
Definition SimpleFlocking.hh:266
std::shared_ptr< DataSet > _dset_agent_y
Definition SimpleFlocking.hh:98
typename AgentManager::RuleFunc Rule
Type of the update rules for agents.
Definition SimpleFlocking.hh:56
void set_agent_speed(const double new_speed)
Sets the speed value of all agents.
Definition SimpleFlocking.hh:244
bool _store_agent_data
Whether to store agent-specific data.
Definition SimpleFlocking.hh:94
typename AgentManager::SpaceVec SpaceVec
Type of spatial vectors within the domain.
Definition SimpleFlocking.hh:62
std::shared_ptr< DataSet > _dset_orientation_circstd
Definition SimpleFlocking.hh:103
OutputIt transform(const Utopia::ExecPolicy policy, InputIt first1, InputIt last1, OutputIt d_first, UnaryOperation unary_op)
Apply a unary operator to a range and store the result in a new range.
Definition parallel.hh:368
YAML::Node Config
Type of a variadic dictionary-like data structure used throughout Utopia.
Definition types.hh:71
ReturnType get_as(const std::string &key, const DataIO::Config &node)
This function is a wrapper around the yaml-cpp YAML::Node::as function.
Definition cfg_utils.hh:158
Container select_entities(const Manager &mngr, const DataIO::Config &sel_cfg)
Select entities according to parameters specified in a configuration.
Definition select.hh:213
void apply_rule(Rule &&rule, const ContTarget &cont_target, ContArgs &&... cont_args)
Sequential overload.
Definition apply.hh:133
Definition SimpleFlocking.hh:15
double absolute_group_velocity(const Container &velocities)
Computes the absolute group velocity from a container of velocity vectors.
Definition utils.hh:58
auto circular_mean_and_std(const Container &angles)
Computes the circular mean and std from a sample of (constrained) angles.
Definition utils.hh:129
The entity traits struct gathers types to be used for specializing an entity.
Definition entity.hh:49
Wrapper struct for defining model class data types.
Definition model.hh:92