Register a results writer for a specific field.
Register a results writer for a specific fieldAssociates a ResultsWriter with a named field for periodic output during simulation. The writer will be called automatically when save points are reached in the time integration loop.
#ifndef PFC_SIMULATOR_HPP
#define PFC_SIMULATOR_HPP
#include <iostream>
#include <memory>
#include <unordered_map>
namespace pfc {
void step(class Simulator &s, Model &m);
class Simulator {
private:
Model &m_model;
Time &m_time;
std::unordered_map<std::string, std::unique_ptr<ResultsWriter>> m_result_writers;
std::vector<std::unique_ptr<FieldModifier>> m_initial_conditions;
std::vector<std::unique_ptr<FieldModifier>> m_boundary_conditions;
int m_result_counter = 0;
public:
Simulator(Model &model, Time &time) : m_model(model), m_time(time) {}
bool add_results_writer(const std::string &field_name,
std::unique_ptr<ResultsWriter> writer) {
writer->set_domain(get_size(world), inbox.size, inbox.low);
if (model.has_field(field_name)) {
m_result_writers.insert({field_name, std::move(writer)});
return true;
} else {
std::cout << "Warning: tried to add writer for inexistent field " << field_name
<< ", RESULTS ARE NOT WRITTEN!" << std::endl;
return false;
}
}
bool add_results_writer(std::unique_ptr<ResultsWriter> writer) {
std::cout << "Warning: adding result writer to write field 'default'"
<< std::endl;
return add_results_writer("default", std::move(writer));
}
bool add_initial_conditions(std::unique_ptr<FieldModifier> modifier) {
std::string field_name = modifier->get_field_name();
if (field_name == "default") {
std::cout << "Warning: adding initial condition to modify field 'default'"
<< std::endl;
}
if (model.has_field(field_name)) {
m_initial_conditions.push_back(std::move(modifier));
return true;
} else {
std::cout << "Warning: tried to add initial condition for inexistent field "
<< field_name << ", INITIAL CONDITIONS ARE NOT APPLIED!"
<< std::endl;
return false;
}
}
return m_initial_conditions;
}
bool add_boundary_conditions(std::unique_ptr<FieldModifier> modifier) {
std::string field_name = modifier->get_field_name();
if (field_name == "default") {
std::cout << "Warning: adding boundary condition to modify field 'default'"
<< std::endl;
}
if (model.has_field(field_name)) {
m_boundary_conditions.push_back(std::move(modifier));
return true;
} else {
std::cout << "Warning: tried to add boundary condition for inexistent field "
<< field_name << ", BOUNDARY CONDITIONS ARE NOT APPLIED!"
<< std::endl;
return false;
}
}
const std::vector<std::unique_ptr<FieldModifier>> &
return m_boundary_conditions;
}
void set_result_counter(int result_counter) { m_result_counter = result_counter; }
double get_result_counter() const { return m_result_counter; }
void write_results() {
int file_num = get_result_counter();
for (const auto &[field_name, writer] : m_result_writers) {
if (model.has_real_field(field_name)) {
writer->write(file_num,
get_model().
get_real_field(field_name));
}
if (model.has_complex_field(field_name)) {
writer->write(file_num,
get_model().
get_complex_field(field_name));
}
}
set_result_counter(file_num + 1);
}
void apply_initial_conditions() {
for (const auto &ic : m_initial_conditions) {
ic->apply(model, time.get_current());
}
}
void apply_boundary_conditions() {
for (const auto &bc : m_boundary_conditions) {
bc->apply(model, time.get_current());
}
}
void step() {
if (time.get_increment() == 0) {
apply_initial_conditions();
apply_boundary_conditions();
if (time.do_save()) {
write_results();
}
}
time.next();
apply_boundary_conditions();
model.step(time.get_current());
if (time.do_save()) {
write_results();
}
return;
}
bool done() {
return time.done();
}
};
inline void step(Simulator &s, Model &m) { m.step(s.get_time().get_current()); }
}
#endif
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
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
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
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.
Time state management for simulation time integration.
World class definition and unified interface.