Skip to content

Commit

Permalink
Merge pull request #5920 from MFraters/further_multipl_particle_world…
Browse files Browse the repository at this point in the history
…_infrastructre

Add further multiple particle world instrastructure.
  • Loading branch information
gassmoeller authored Jun 21, 2024
2 parents 6d7abad + 530c96a commit 405b780
Show file tree
Hide file tree
Showing 23 changed files with 65 additions and 57 deletions.
2 changes: 1 addition & 1 deletion include/aspect/simulator.h
Original file line number Diff line number Diff line change
Expand Up @@ -1980,7 +1980,7 @@ namespace aspect
/**
* The world holding the particles
*/
std::unique_ptr<Particle::World<dim>> particle_world;
std::vector<std::unique_ptr<Particle::World<dim>>> particle_worlds;

/**
* @}
Expand Down
8 changes: 4 additions & 4 deletions include/aspect/simulator_access.h
Original file line number Diff line number Diff line change
Expand Up @@ -937,20 +937,20 @@ namespace aspect
n_particle_worlds() const;

/**
* Returns a const reference to the particle world, in case anyone
* Returns a const reference to a single particle world, in case anyone
* wants to query something about particles.
*/
const Particle::World<dim> &
get_particle_world() const;
get_particle_world(const unsigned int particle_world_index) const;

/**
* Returns a reference to the particle world, in case anyone wants to
* Returns a reference to a single particle world, in case anyone wants to
* change something within the particle world. Use with care, usually
* you want to only let the functions within the particle subsystem
* change member variables of the particle world.
*/
Particle::World<dim> &
get_particle_world();
get_particle_world(const unsigned int particle_world_index);

/**
* Return true if using the block GMG Stokes solver.
Expand Down
2 changes: 1 addition & 1 deletion source/material_model/rheology/strain_dependent.cc
Original file line number Diff line number Diff line change
Expand Up @@ -412,7 +412,7 @@ namespace aspect
// Currently this functionality only works in field composition
if (healing_mechanism != no_healing && this->n_particle_worlds() > 0)
{
const Particle::Property::Manager<dim> &particle_property_manager = this->get_particle_world().get_property_manager();
const Particle::Property::Manager<dim> &particle_property_manager = this->get_particle_world(0).get_property_manager();
AssertThrow(particle_property_manager.plugin_name_exists("viscoplastic strain invariants") == false, ExcMessage("This healing mechanism currently does not work if the strain is tracked on particles."));
}

Expand Down
2 changes: 1 addition & 1 deletion source/mesh_refinement/particle_density.cc
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ namespace aspect
"postprocessor plugin `particles' to be selected. Please activate the "
"particles or deactivate this mesh refinement plugin."));

const Particle::ParticleHandler<dim> &particle_handler = this->get_particle_world().get_particle_handler();
const Particle::ParticleHandler<dim> &particle_handler = this->get_particle_world(0).get_particle_handler();

for (const auto &cell : this->get_dof_handler().active_cell_iterators())
if (cell->is_locally_owned())
Expand Down
2 changes: 1 addition & 1 deletion source/particle/integrator/rk_2.cc
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ namespace aspect
void
RK2<dim>::initialize ()
{
const auto &property_information = this->get_particle_world().get_property_manager().get_data_info();
const auto &property_information = this->get_particle_world(this->get_particle_world_index()).get_property_manager().get_data_info();
property_index_old_location = property_information.get_position_by_field_name("internal: integrator properties");
}

Expand Down
2 changes: 1 addition & 1 deletion source/particle/integrator/rk_4.cc
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ namespace aspect
void
RK4<dim>::initialize ()
{
const auto &property_information = this->get_particle_world().get_property_manager().get_data_info();
const auto &property_information = this->get_particle_world(this->get_particle_world_index()).get_property_manager().get_data_info();

property_indices[0] = property_information.get_position_by_field_name("internal: integrator properties");
property_indices[1] = property_indices[0] + dim;
Expand Down
2 changes: 1 addition & 1 deletion source/particle/interpolator/bilinear_least_squares.cc
Original file line number Diff line number Diff line change
Expand Up @@ -281,7 +281,7 @@ namespace aspect
{
prm.enter_subsection("Bilinear least squares");
{
const auto &particle_property_information = this->get_particle_world().get_property_manager().get_data_info();
const auto &particle_property_information = this->get_particle_world(this->get_particle_world_index()).get_property_manager().get_data_info();
const unsigned int n_property_components = particle_property_information.n_components();
const unsigned int n_internal_components = particle_property_information.get_components_by_field_name("internal: integrator properties");

Expand Down
2 changes: 1 addition & 1 deletion source/particle/interpolator/quadratic_least_squares.cc
Original file line number Diff line number Diff line change
Expand Up @@ -558,7 +558,7 @@ namespace aspect
{
prm.enter_subsection("Quadratic least squares");
{
const auto &particle_property_information = this->get_particle_world().get_property_manager().get_data_info();
const auto &particle_property_information = this->get_particle_world(this->get_particle_world_index()).get_property_manager().get_data_info();
const unsigned int n_property_components = particle_property_information.n_components();
const unsigned int n_internal_components = particle_property_information.get_components_by_field_name("internal: integrator properties");

Expand Down
4 changes: 2 additions & 2 deletions source/particle/property/cpo_bingham_average.cc
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ namespace aspect
{
const unsigned int my_rank = Utilities::MPI::this_mpi_process(MPI_COMM_WORLD);
this->random_number_generator.seed(random_number_seed+my_rank);
const auto &manager = this->get_particle_world().get_property_manager();
const auto &manager = this->get_particle_world(this->get_particle_world_index()).get_property_manager();
AssertThrow(manager.plugin_name_exists("crystal preferred orientation"),
ExcMessage("No crystal preferred orientation property plugin found."));

Expand Down Expand Up @@ -252,7 +252,7 @@ namespace aspect
{
// Get a pointer to the CPO particle property.
cpo_particle_property = std::make_unique<const Particle::Property::CrystalPreferredOrientation<dim>> (
this->get_particle_world().get_property_manager().template get_matching_property<Particle::Property::CrystalPreferredOrientation<dim>>());
this->get_particle_world(this->get_particle_world_index()).get_property_manager().template get_matching_property<Particle::Property::CrystalPreferredOrientation<dim>>());

random_number_seed = prm.get_integer ("Random number seed");
n_grains = cpo_particle_property->get_number_of_grains();
Expand Down
4 changes: 2 additions & 2 deletions source/particle/property/cpo_elastic_tensor.cc
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ namespace aspect
void
CpoElasticTensor<dim>::initialize ()
{
const auto &manager = this->get_particle_world().get_property_manager();
const auto &manager = this->get_particle_world(this->get_particle_world_index()).get_property_manager();
AssertThrow(manager.plugin_name_exists("crystal preferred orientation"),
ExcMessage("No crystal preferred orientation property plugin found."));

Expand Down Expand Up @@ -147,7 +147,7 @@ namespace aspect
{
// Get a reference to the CPO particle property.
const Particle::Property::CrystalPreferredOrientation<dim> &cpo_particle_property =
this->get_particle_world().get_property_manager().template get_matching_property<Particle::Property::CrystalPreferredOrientation<dim>>();
this->get_particle_world(this->get_particle_world_index()).get_property_manager().template get_matching_property<Particle::Property::CrystalPreferredOrientation<dim>>();


const SymmetricTensor<2,6> C_average = voigt_average_elastic_tensor(cpo_particle_property,
Expand Down
2 changes: 1 addition & 1 deletion source/particle/property/elastic_tensor_decomposition.cc
Original file line number Diff line number Diff line change
Expand Up @@ -270,7 +270,7 @@ namespace aspect
void
ElasticTensorDecomposition<dim>::initialize ()
{
const Particle::Property::Manager<dim> &manager = this->get_particle_world().get_property_manager();
const Particle::Property::Manager<dim> &manager = this->get_particle_world(this->get_particle_world_index()).get_property_manager();
AssertThrow(manager.plugin_name_exists("crystal preferred orientation"),
ExcMessage("No cpo property plugin found."));
AssertThrow(manager.plugin_name_exists("cpo elastic tensor"),
Expand Down
6 changes: 3 additions & 3 deletions source/postprocess/crystal_preferred_orientation.cc
Original file line number Diff line number Diff line change
Expand Up @@ -173,8 +173,8 @@ namespace aspect
CrystalPreferredOrientation<dim>::execute (TableHandler &statistics)
{

const Particle::Property::Manager<dim> &manager = this->get_particle_world().get_property_manager();
const Particle::Property::ParticleHandler<dim> &particle_handler = this->get_particle_world().get_particle_handler();
const Particle::Property::Manager<dim> &manager = this->get_particle_world(0).get_property_manager();
const Particle::Property::ParticleHandler<dim> &particle_handler = this->get_particle_world(0).get_particle_handler();

const bool cpo_elastic_decomposition_plugin_exists = manager.plugin_name_exists("elastic tensor decomposition");

Expand Down Expand Up @@ -220,7 +220,7 @@ namespace aspect
+ "isotropic_norm_square") : "") << std::endl;

// get particle data
const Particle::Property::ParticlePropertyInformation &property_information = this->get_particle_world().get_property_manager().get_data_info();
const Particle::Property::ParticlePropertyInformation &property_information = this->get_particle_world(0).get_property_manager().get_data_info();

AssertThrow(property_information.fieldname_exists("cpo mineral 0 type") ,
ExcMessage("No CPO particle properties found. Make sure that the CPO particle property plugin is selected."));
Expand Down
2 changes: 1 addition & 1 deletion source/postprocess/load_balance_statistics.cc
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ namespace aspect

if (this->n_particle_worlds() > 0)
{
const unsigned int locally_owned_particles = this->get_particle_world().
const unsigned int locally_owned_particles = this->get_particle_world(0).
get_particle_handler().n_locally_owned_particles();
const dealii::Utilities::MPI::MinMaxAvg particles_per_process =
dealii::Utilities::MPI::min_max_avg(locally_owned_particles,this->get_mpi_communicator());
Expand Down
4 changes: 2 additions & 2 deletions source/postprocess/particle_count_statistics.cc
Original file line number Diff line number Diff line change
Expand Up @@ -35,11 +35,11 @@ namespace aspect
ParticleCountStatistics<dim>::execute (TableHandler &statistics)
{
const Particle::ParticleHandler<dim> &particle_handler =
this->get_particle_world().get_particle_handler();
this->get_particle_world(0).get_particle_handler();

unsigned int local_min_particles = std::numeric_limits<unsigned int>::max();
unsigned int local_max_particles = 0;
const Particle::types::particle_index global_particles = this->get_particle_world().n_global_particles();
const Particle::types::particle_index global_particles = this->get_particle_world(0).n_global_particles();

// compute local min/max
for (const auto &cell : this->get_dof_handler().active_cell_iterators())
Expand Down
6 changes: 3 additions & 3 deletions source/postprocess/particles.cc
Original file line number Diff line number Diff line change
Expand Up @@ -323,7 +323,7 @@ namespace aspect
if (std::isnan(last_output_time))
last_output_time = this->get_time() - output_interval;

const Particle::World<dim> &world = this->get_particle_world();
const Particle::World<dim> &world = this->get_particle_world(0);

statistics.add_value("Number of advected particles",world.n_global_particles());

Expand Down Expand Up @@ -562,7 +562,7 @@ namespace aspect
std::ostringstream os;
aspect::oarchive oa (os);

this->get_particle_world().save(os);
this->get_particle_world(0).save(os);
oa << (*this);

status_strings["Particles"] = os.str();
Expand All @@ -580,7 +580,7 @@ namespace aspect
aspect::iarchive ia (is);

// Load the particle world
this->get_particle_world().load(is);
this->get_particle_world(0).load(is);

ia >> (*this);
}
Expand Down
2 changes: 1 addition & 1 deletion source/postprocess/visualization/particle_count.cc
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ namespace aspect
ParticleCount<dim>::execute() const
{
const Particle::ParticleHandler<dim> &particle_handler =
this->get_particle_world().get_particle_handler();
this->get_particle_world(0).get_particle_handler();

std::pair<std::string, std::unique_ptr<Vector<float>>>
return_value ("particles_per_cell",
Expand Down
27 changes: 17 additions & 10 deletions source/simulator/core.cc
Original file line number Diff line number Diff line change
Expand Up @@ -189,7 +189,7 @@ namespace aspect
nullptr),
#endif
boundary_heat_flux (BoundaryHeatFlux::create_boundary_heat_flux<dim>(prm)),
particle_world(nullptr),
particle_worlds(),
time (numbers::signaling_nan<double>()),
time_step (numbers::signaling_nan<double>()),
old_time_step (numbers::signaling_nan<double>()),
Expand Down Expand Up @@ -448,12 +448,16 @@ namespace aspect

if (postprocess_manager.template has_matching_postprocessor<Postprocess::Particles<dim>>())
{
particle_world = std::make_unique<Particle::World<dim>>();
if (SimulatorAccess<dim> *sim = dynamic_cast<SimulatorAccess<dim>*>(particle_world.get()))
sim->initialize_simulator (*this);
particle_worlds.emplace_back(std::move(std::make_unique<Particle::World<dim>>()));
for (unsigned int particle_world_index = 0 ; particle_world_index < particle_worlds.size(); ++particle_world_index)
{
if (SimulatorAccess<dim> *sim = dynamic_cast<SimulatorAccess<dim>*>(particle_worlds[particle_world_index].get()))
sim->initialize_simulator (*this);

particle_worlds.back()->parse_parameters(prm,particle_world_index);
particle_worlds.back()->initialize();

particle_world->parse_parameters(prm,0);
particle_world->initialize();
}
}

mesh_refinement_manager.initialize_simulator (*this);
Expand Down Expand Up @@ -568,7 +572,9 @@ namespace aspect
// is destroyed after the latter. But it stores a pointer to the
// triangulation and uses it during destruction. This results in
// trouble. So destroy it first.
particle_world.reset();

for (auto &particle_world : particle_worlds)
particle_world.reset();

// wait if there is a thread that's still writing the statistics
// object (set from the output_statistics() function)
Expand Down Expand Up @@ -608,9 +614,10 @@ namespace aspect

// Copy particle handler to restore particle location and properties
// before repeating a timestep
if (particle_world.get() != nullptr)
for (auto &particle_world : particle_worlds)
particle_world->backup_particles();


// then interpolate the current boundary velocities. copy constraints
// into current_constraints and then add to current_constraints
compute_current_constraints ();
Expand Down Expand Up @@ -642,7 +649,7 @@ namespace aspect
if (prescribed_stokes_solution.get())
prescribed_stokes_solution->update();

if (particle_world.get() != nullptr)
for (auto &particle_world : particle_worlds)
particle_world->update();

// do the same for the traction boundary conditions and other things
Expand Down Expand Up @@ -2133,7 +2140,7 @@ namespace aspect
// Restore particles through stored copy of particle handler,
// created in start_timestep(),
// but only if this timestep is to be repeated.
if (particle_world.get() != nullptr)
for (auto &particle_world : particle_worlds)
particle_world->restore_particles();

continue; // repeat time step loop
Expand Down
6 changes: 3 additions & 3 deletions source/simulator/initial_conditions.cc
Original file line number Diff line number Diff line change
Expand Up @@ -284,8 +284,8 @@ namespace aspect
// need to write into it and we can not
// write into vectors with ghost elements

const Particle::Interpolator::Interface<dim> &particle_interpolator = particle_world->get_interpolator();
const Particle::Property::Manager<dim> &particle_property_manager = particle_world->get_property_manager();
const Particle::Interpolator::Interface<dim> &particle_interpolator = particle_worlds[0]->get_interpolator();
const Particle::Property::Manager<dim> &particle_property_manager = particle_worlds[0]->get_property_manager();

std::vector<unsigned int> particle_property_indices;
ComponentMask property_mask (particle_property_manager.get_data_info().n_components(),false);
Expand Down Expand Up @@ -356,7 +356,7 @@ namespace aspect
try
{
particle_properties =
particle_interpolator.properties_at_points(particle_world->get_particle_handler(),
particle_interpolator.properties_at_points(particle_worlds[0]->get_particle_handler(),
quadrature_points,
property_mask,
cell);
Expand Down
17 changes: 7 additions & 10 deletions source/simulator/simulator_access.cc
Original file line number Diff line number Diff line change
Expand Up @@ -821,30 +821,27 @@ namespace aspect
unsigned int
SimulatorAccess<dim>::n_particle_worlds() const
{
// operator () returns whether an object is managed by a unique ptr
return (simulator->particle_world ? 1 : 0);
return simulator->particle_worlds.size();
}



template <int dim>
const Particle::World<dim> &
SimulatorAccess<dim>::get_particle_world() const
SimulatorAccess<dim>::get_particle_world(unsigned int particle_world_index) const
{
Assert (simulator->particle_world.get() != nullptr,
ExcMessage("You can not call this function if there is no particle world."));
return *simulator->particle_world.get();
AssertThrow (particle_world_index < simulator->particle_worlds.size(), ExcInternalError());
return *simulator->particle_worlds[particle_world_index].get();
}



template <int dim>
Particle::World<dim> &
SimulatorAccess<dim>::get_particle_world()
SimulatorAccess<dim>::get_particle_world(unsigned int particle_world_index)
{
Assert (simulator->particle_world.get() != nullptr,
ExcMessage("You can not call this function if there is no particle world."));
return *simulator->particle_world.get();
AssertThrow (particle_world_index < simulator->particle_worlds.size(), ExcInternalError());
return *simulator->particle_worlds[particle_world_index].get();
}


Expand Down
14 changes: 9 additions & 5 deletions source/simulator/solver_schemes.cc
Original file line number Diff line number Diff line change
Expand Up @@ -226,7 +226,7 @@ namespace aspect
{
// Advect the particles before they are potentially used to
// set up the compositional fields.
if (particle_world.get() != nullptr)
for (auto &particle_world : particle_worlds)
{
// Do not advect the particles in the initial refinement stage
const bool in_initial_refinement = (timestep_number == 0)
Expand Down Expand Up @@ -958,8 +958,10 @@ namespace aspect
// Restore particles through stored copy of particle handler,
// but only if they have already been displaced in a nonlinear
// iteration (in the assemble_and_solve_composition call).
if ((particle_world.get() != nullptr) && (nonlinear_iteration > 0))
particle_world->restore_particles();

if (nonlinear_iteration > 0)
for (auto &particle_world : particle_worlds)
particle_world->restore_particles();

const double relative_temperature_residual =
assemble_and_solve_temperature(initial_temperature_residual,
Expand Down Expand Up @@ -1115,8 +1117,10 @@ namespace aspect
// Restore particles through stored copy of particle handler,
// but only if they have already been displaced in a nonlinear
// iteration (in the assemble_and_solve_composition call).
if ((particle_world.get() != nullptr) && (nonlinear_iteration > 0))
particle_world->restore_particles();

if (nonlinear_iteration > 0)
for (auto &particle_world : particle_worlds)
particle_world->restore_particles();

const double relative_temperature_residual =
assemble_and_solve_temperature(initial_temperature_residual,
Expand Down
2 changes: 1 addition & 1 deletion tests/mesh_deformation_particles.cc
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ void post_mesh_deformation (const SimulatorAccess<dim> &simulator_access)
// Get the reference location of the one particle,
// and check that it has the correct value.
const Point<dim> predicted_particle_reference_location =
simulator_access.get_particle_world().get_particle_handler().begin()->get_reference_location();
simulator_access.get_particle_world(0).get_particle_handler().begin()->get_reference_location();
// At timestep 0, the mesh is not deformed
// other than through the initial topography/
// initial mesh deformation plugins, which
Expand Down
2 changes: 1 addition & 1 deletion tests/particle_handler_copy.cc
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ void duplicate_particle_handler(const SimulatorAccess<dim> &simulator_access,
const unsigned int,
const SolverControl &)
{
const auto &particle_world = simulator_access.get_particle_world();
const auto &particle_world = simulator_access.get_particle_world(0);
dealii::Particles::ParticleHandler<dim> particle_handler;
std::cout << "duplicating particle handler" << std::endl;

Expand Down
Loading

0 comments on commit 405b780

Please sign in to comment.