OpenPFC  0.1.4
Phase Field Crystal simulation framework
Loading...
Searching...
No Matches
simulator.hpp
Go to the documentation of this file.
1// SPDX-FileCopyrightText: 2025 VTT Technical Research Centre of Finland Ltd
2// SPDX-License-Identifier: AGPL-3.0-or-later
3
43#ifndef PFC_SIMULATOR_HPP
44#define PFC_SIMULATOR_HPP
45
46#include "core/world.hpp"
47#include "field_modifier.hpp"
48#include "model.hpp"
49#include "results_writer.hpp"
50#include "time.hpp"
51#include <iostream>
52#include <memory>
53#include <unordered_map>
54
55namespace pfc {
56
57void step(class Simulator &s, Model &m);
58
63class Simulator {
64
65private:
66 Model &m_model;
67 Time &m_time;
68
69 std::unordered_map<std::string, std::unique_ptr<ResultsWriter>> m_result_writers;
70 std::vector<std::unique_ptr<FieldModifier>> m_initial_conditions;
71 std::vector<std::unique_ptr<FieldModifier>> m_boundary_conditions;
72 int m_result_counter = 0;
73
74public:
81 Simulator(Model &model, Time &time) : m_model(model), m_time(time) {}
82
88 Model &get_model() { return m_model; }
89
95 /*
96 const Decomposition &get_decomposition() {
97 return get_model().get_decomposition();
98 }
99 */
100
106 const World &get_world() { return get_model().get_world(); }
107
113 FFT &get_fft() { return get_model().get_fft(); }
114
120 Time &get_time() { return m_time; }
121
127 Field &get_field() { return get_model().get_field(); }
128
129 void initialize() { get_model().initialize(get_time().get_dt()); }
130
131 bool is_rank0() { return get_model().is_rank0(); }
132
133 unsigned int get_increment() { return get_time().get_increment(); }
134
176 bool add_results_writer(const std::string &field_name,
177 std::unique_ptr<ResultsWriter> writer) {
178 auto inbox = get_inbox(get_fft());
179 auto world = get_world();
180 writer->set_domain(get_size(world), inbox.size, inbox.low);
181
182 Model &model = get_model();
183 if (model.has_field(field_name)) {
184 m_result_writers.insert({field_name, std::move(writer)});
185 return true;
186 } else {
187 std::cout << "Warning: tried to add writer for inexistent field " << field_name
188 << ", RESULTS ARE NOT WRITTEN!" << std::endl;
189 return false;
190 }
191 }
192
193 bool add_results_writer(std::unique_ptr<ResultsWriter> writer) {
194 std::cout << "Warning: adding result writer to write field 'default'"
195 << std::endl;
196 return add_results_writer("default", std::move(writer));
197 }
198
245 bool add_initial_conditions(std::unique_ptr<FieldModifier> modifier) {
246 Model &model = get_model();
247 std::string field_name = modifier->get_field_name();
248 if (field_name == "default") {
249 std::cout << "Warning: adding initial condition to modify field 'default'"
250 << std::endl;
251 }
252 if (model.has_field(field_name)) {
253 m_initial_conditions.push_back(std::move(modifier));
254 return true;
255 } else {
256 std::cout << "Warning: tried to add initial condition for inexistent field "
257 << field_name << ", INITIAL CONDITIONS ARE NOT APPLIED!"
258 << std::endl;
259 return false;
260 }
261 }
262
273 const std::vector<std::unique_ptr<FieldModifier>> &get_initial_conditions() const {
274 return m_initial_conditions;
275 }
276
324 bool add_boundary_conditions(std::unique_ptr<FieldModifier> modifier) {
325 Model &model = get_model();
326 std::string field_name = modifier->get_field_name();
327 if (field_name == "default") {
328 std::cout << "Warning: adding boundary condition to modify field 'default'"
329 << std::endl;
330 }
331 if (model.has_field(field_name)) {
332 m_boundary_conditions.push_back(std::move(modifier));
333 return true;
334 } else {
335 std::cout << "Warning: tried to add boundary condition for inexistent field "
336 << field_name << ", BOUNDARY CONDITIONS ARE NOT APPLIED!"
337 << std::endl;
338 return false;
339 }
340 }
341
352 const std::vector<std::unique_ptr<FieldModifier>> &
354 return m_boundary_conditions;
355 }
356
357 void set_result_counter(int result_counter) { m_result_counter = result_counter; }
358
359 double get_result_counter() const { return m_result_counter; }
360
361 void write_results() {
362 int file_num = get_result_counter();
363 Model &model = get_model();
364 for (const auto &[field_name, writer] : m_result_writers) {
365 if (model.has_real_field(field_name)) {
366 writer->write(file_num, get_model().get_real_field(field_name));
367 }
368 if (model.has_complex_field(field_name)) {
369 writer->write(file_num, get_model().get_complex_field(field_name));
370 }
371 }
372 set_result_counter(file_num + 1);
373 }
374
375 void apply_initial_conditions() {
376 Model &model = get_model();
377 Time &time = get_time();
378 for (const auto &ic : m_initial_conditions) {
379 ic->apply(model, time.get_current());
380 }
381 }
382
383 void apply_boundary_conditions() {
384 Model &model = get_model();
385 Time &time = get_time();
386 for (const auto &bc : m_boundary_conditions) {
387 bc->apply(model, time.get_current());
388 }
389 }
390
442 void step() {
443 Time &time = get_time();
444 Model &model = get_model();
445 if (time.get_increment() == 0) {
446 apply_initial_conditions();
447 apply_boundary_conditions();
448 if (time.do_save()) {
449 write_results();
450 }
451 }
452 time.next();
453 apply_boundary_conditions();
454 model.step(time.get_current());
455 if (time.do_save()) {
456 write_results();
457 }
458 return;
459 }
460
490 bool done() {
491 Time &time = get_time();
492 return time.done();
493 }
494};
495
496inline void step(Simulator &s, Model &m) { m.step(s.get_time().get_current()); }
497
498} // namespace pfc
499
500#endif // PFC_SIMULATOR_HPP
The Model class represents the physics model for simulations in OpenPFC.
Definition model.hpp:95
bool is_rank0() const noexcept
Check if current MPI rank is 0.
Definition model.hpp:175
const World & get_world() const noexcept
Get the decomposition object associated with the model.
Definition model.hpp:191
virtual Field & get_field()
Get a reference to the default primary unknown field.
Definition model.hpp:662
The Simulator class is responsible for running the simulation of the model.
Definition simulator.hpp:63
const std::vector< std::unique_ptr< FieldModifier > > & get_boundary_conditions() const
Gets the boundary conditions of the simulation.
Definition simulator.hpp:353
Field & get_field()
Get the default field object.
Definition simulator.hpp:127
const std::vector< std::unique_ptr< FieldModifier > > & get_initial_conditions() const
Gets the initial conditions of the simulation.
Definition simulator.hpp:273
Simulator(Model &model, Time &time)
Construct a new Simulator object.
Definition simulator.hpp:81
FFT & get_fft()
Get the FFT object.
Definition simulator.hpp:113
Model & get_model()
Get the model object.
Definition simulator.hpp:88
Time & get_time()
Get the time object.
Definition simulator.hpp:120
const World & get_world()
Get the decomposition object.
Definition simulator.hpp:106
Definition time.hpp:233
int get_increment() const
Get the current time increment.
Definition time.hpp:397
Base class for initial conditions and boundary conditions.
Physics model abstraction for phase-field simulations.
Base interface for simulation output and I/O operations.
FFT class for distributed-memory parallel Fourier transforms.
Definition fft.hpp:248
Represents the global simulation domain (the "world").
Definition world.hpp:91
Time state management for simulation time integration.
World class definition and unified interface.