-
Notifications
You must be signed in to change notification settings - Fork 241
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add distance weighted average interpolator
- Loading branch information
1 parent
0d485a6
commit 792e91f
Showing
6 changed files
with
398 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
Added: A new particle interpolator plugin 'distance weighted average' that | ||
computes the interpolated properties as an average of particle properties | ||
weighted by a distance function. This plugin is similarly accurate | ||
as the 'cell average' interpolator, but provides smoother results and is | ||
less susceptible to jumps in interpolated properties if particles move | ||
small distances. | ||
<br> | ||
(Rene Gassmoeller, 2024/06/09) |
72 changes: 72 additions & 0 deletions
72
include/aspect/particle/interpolator/distance_weighted_average.h
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,72 @@ | ||
/* | ||
Copyright (C) 2024 by the authors of the ASPECT code. | ||
This file is part of ASPECT. | ||
ASPECT is free software; you can redistribute it and/or modify | ||
it under the terms of the GNU General Public License as published by | ||
the Free Software Foundation; either version 2, or (at your option) | ||
any later version. | ||
ASPECT is distributed in the hope that it will be useful, | ||
but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
GNU General Public License for more details. | ||
You should have received a copy of the GNU General Public License | ||
along with ASPECT; see the file LICENSE. If not see | ||
<http://www.gnu.org/licenses/>. | ||
*/ | ||
|
||
#ifndef _aspect_particle_interpolator_distance_weighted_average_h | ||
#define _aspect_particle_interpolator_distance_weighted_average_h | ||
|
||
#include <aspect/particle/interpolator/interface.h> | ||
#include <aspect/simulator_access.h> | ||
|
||
#include <deal.II/grid/grid_tools_cache.h> | ||
|
||
namespace aspect | ||
{ | ||
namespace Particle | ||
{ | ||
namespace Interpolator | ||
{ | ||
/** | ||
* Return the interpolated properties of all particles of the given cell using bilinear least squares method. | ||
* Currently, only the two dimensional model is supported. | ||
* | ||
* @ingroup ParticleInterpolators | ||
*/ | ||
template <int dim> | ||
class DistanceWeightedAverage : public Interface<dim>, public aspect::SimulatorAccess<dim> | ||
{ | ||
public: | ||
/** | ||
* Update function. Called once at the beginning of each time step. | ||
*/ | ||
void update() override; | ||
|
||
/** | ||
* Return the cell-wise evaluated particle properties at the given @p positions. | ||
*/ | ||
std::vector<std::vector<double>> | ||
properties_at_points(const ParticleHandler<dim> &particle_handler, | ||
const std::vector<Point<dim>> &positions, | ||
const ComponentMask &selected_properties, | ||
const typename parallel::distributed::Triangulation<dim>::active_cell_iterator &cell) const override; | ||
|
||
// avoid -Woverloaded-virtual: | ||
using Interface<dim>::properties_at_points; | ||
|
||
private: | ||
/** | ||
* Cached information. | ||
*/ | ||
std::vector<std::set<typename Triangulation<dim>::active_cell_iterator>> vertex_to_cell_map; | ||
}; | ||
} | ||
} | ||
} | ||
|
||
#endif |
139 changes: 139 additions & 0 deletions
139
source/particle/interpolator/distance_weighted_average.cc
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,139 @@ | ||
/* | ||
Copyright (C) 2024 by the authors of the ASPECT code. | ||
This file is part of ASPECT. | ||
ASPECT is free software; you can redistribute it and/or modify | ||
it under the terms of the GNU General Public License as published by | ||
the Free Software Foundation; either version 2, or (at your option) | ||
any later version. | ||
ASPECT is distributed in the hope that it will be useful, | ||
but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
GNU General Public License for more details. | ||
You should have received a copy of the GNU General Public License | ||
along with ASPECT; see the file LICENSE. If not see | ||
<http://www.gnu.org/licenses/>. | ||
*/ | ||
|
||
#include <aspect/particle/interpolator/distance_weighted_average.h> | ||
|
||
#include <deal.II/base/signaling_nan.h> | ||
#include <deal.II/grid/grid_tools.h> | ||
|
||
namespace aspect | ||
{ | ||
namespace Particle | ||
{ | ||
namespace Interpolator | ||
{ | ||
namespace internal | ||
{ | ||
double weight (const double distance, const double cell_width) | ||
{ | ||
// linear weight function (hat function) | ||
return std::max(1.0 - (distance/cell_width),0.0); | ||
} | ||
} | ||
|
||
|
||
|
||
template <int dim> | ||
void | ||
DistanceWeightedAverage<dim>::update() | ||
{ | ||
vertex_to_cell_map = GridTools::vertex_to_cell_map(this->get_triangulation()); | ||
} | ||
|
||
|
||
|
||
template <int dim> | ||
std::vector<std::vector<double>> | ||
DistanceWeightedAverage<dim>::properties_at_points(const ParticleHandler<dim> &particle_handler, | ||
const std::vector<Point<dim>> &positions, | ||
const ComponentMask &selected_properties, | ||
const typename parallel::distributed::Triangulation<dim>::active_cell_iterator &cell) const | ||
{ | ||
const unsigned int n_interpolate_positions = positions.size(); | ||
const unsigned int n_particle_properties = particle_handler.n_properties_per_particle(); | ||
|
||
// Create with signaling NaNs | ||
std::vector<std::vector<double>> cell_properties(n_interpolate_positions, | ||
std::vector<double>(n_particle_properties, | ||
numbers::signaling_nan<double>())); | ||
|
||
// Set requested properties to 0.0 | ||
for (unsigned int index_positions = 0; index_positions < n_interpolate_positions; ++index_positions) | ||
for (unsigned int index_properties = 0; index_properties < n_particle_properties; ++index_properties) | ||
if (selected_properties[index_properties]) | ||
cell_properties[index_positions][index_properties] = 0.0; | ||
|
||
std::set<typename Triangulation<dim>::active_cell_iterator> cell_and_neighbors; | ||
|
||
for (const auto v : cell->vertex_indices()) | ||
{ | ||
const unsigned int vertex_index = cell->vertex_index(v); | ||
cell_and_neighbors.insert(vertex_to_cell_map[vertex_index].begin(), | ||
vertex_to_cell_map[vertex_index].end()); | ||
} | ||
|
||
const double interpolation_support = 0.5 * cell->diameter(); | ||
std::vector<double> integrated_weight(n_interpolate_positions,0.0); | ||
|
||
for (const auto ¤t_cell: cell_and_neighbors) | ||
{ | ||
const typename ParticleHandler<dim>::particle_iterator_range particle_range = | ||
particle_handler.particles_in_cell(current_cell); | ||
|
||
for (const auto &particle: particle_range) | ||
{ | ||
const ArrayView<const double> particle_properties = particle.get_properties(); | ||
unsigned int index_positions = 0; | ||
|
||
for (const auto &interpolation_point: positions) | ||
{ | ||
const double distance = particle.get_location().distance(interpolation_point); | ||
const double weight = internal::weight(distance,interpolation_support); | ||
|
||
for (unsigned int index_properties = 0; index_properties < particle_properties.size(); ++index_properties) | ||
if (selected_properties[index_properties]) | ||
cell_properties[index_positions][index_properties] += weight * particle_properties[index_properties]; | ||
|
||
integrated_weight[index_positions] += weight; | ||
++index_positions; | ||
} | ||
} | ||
} | ||
|
||
for (unsigned int index_positions = 0; index_positions < n_interpolate_positions; ++index_positions) | ||
{ | ||
AssertThrow(integrated_weight[index_positions] > 0.0, ExcInternalError()); | ||
|
||
for (unsigned int index_properties = 0; index_properties < n_particle_properties; ++index_properties) | ||
if (selected_properties[index_properties]) | ||
cell_properties[index_positions][index_properties] /= integrated_weight[index_positions]; | ||
} | ||
|
||
return cell_properties; | ||
} | ||
} | ||
} | ||
} | ||
|
||
|
||
// explicit instantiations | ||
namespace aspect | ||
{ | ||
namespace Particle | ||
{ | ||
namespace Interpolator | ||
{ | ||
ASPECT_REGISTER_PARTICLE_INTERPOLATOR(DistanceWeightedAverage, | ||
"distance weighted average", | ||
"Interpolates particle properties onto a vector of points using a " | ||
"distance weighed averaging method.") | ||
} | ||
} | ||
} |
122 changes: 122 additions & 0 deletions
122
tests/particle_interpolator_distance_weighted_average.prm
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,122 @@ | ||
# A test that performs interpolation from particle properties to | ||
# compositional fields that are flagged as 'particle' advected | ||
# fields. | ||
|
||
# MPI: 2 | ||
|
||
set Dimension = 2 | ||
set End time = 70 | ||
set Use years in output instead of seconds = false | ||
|
||
subsection Geometry model | ||
set Model name = box | ||
|
||
subsection Box | ||
set X extent = 0.9142 | ||
set Y extent = 1.0000 | ||
end | ||
end | ||
|
||
subsection Boundary velocity model | ||
set Tangential velocity boundary indicators = left, right | ||
set Zero velocity boundary indicators = bottom, top | ||
end | ||
|
||
subsection Material model | ||
set Model name = simple | ||
|
||
subsection Simple model | ||
set Reference density = 1010 | ||
set Viscosity = 1e2 | ||
set Thermal expansion coefficient = 0 | ||
set Density differential for compositional field 1 = -10 | ||
end | ||
end | ||
|
||
subsection Gravity model | ||
set Model name = vertical | ||
|
||
subsection Vertical | ||
set Magnitude = 10 | ||
end | ||
end | ||
|
||
############### Parameters describing the temperature field | ||
# Note: The temperature plays no role in this model | ||
|
||
subsection Initial temperature model | ||
set Model name = function | ||
|
||
subsection Function | ||
set Function expression = 0 | ||
end | ||
end | ||
|
||
############### Parameters describing the compositional field | ||
# Note: The compositional field is what drives the flow | ||
# in this example | ||
|
||
subsection Compositional fields | ||
set Number of fields = 3 | ||
set Names of fields = advection_field, advection_particle, advection_particle2 | ||
set Compositional field methods = field, particles, particles | ||
set Mapped particle properties = advection_particle2:velocity [1], advection_particle:function | ||
end | ||
|
||
subsection Initial composition model | ||
set Model name = function | ||
|
||
subsection Function | ||
set Variable names = x,z | ||
set Function constants = pi=3.1415926 | ||
set Function expression = 0.5*(1+tanh((0.2+0.02*cos(pi*x/0.9142)-z)/0.02));0.0;0.0 | ||
end | ||
end | ||
|
||
subsection Discretization | ||
set Use discontinuous composition discretization = true | ||
end | ||
|
||
############### Parameters describing the discretization | ||
|
||
subsection Mesh refinement | ||
set Initial adaptive refinement = 0 | ||
set Strategy = composition | ||
set Initial global refinement = 4 | ||
set Time steps between mesh refinement = 0 | ||
set Coarsening fraction = 0.05 | ||
set Refinement fraction = 0.3 | ||
end | ||
|
||
############### Parameters describing what to do with the solution | ||
|
||
subsection Postprocess | ||
set List of postprocessors = velocity statistics, composition statistics,particles | ||
|
||
subsection Visualization | ||
set Interpolate output = false | ||
set Time between graphical output = 70 | ||
end | ||
|
||
subsection Particles | ||
set Number of particles = 100000 | ||
set Time between data output = 70 | ||
set Data output format = none | ||
set List of particle properties = velocity, function, initial composition | ||
set Interpolation scheme = distance weighted average | ||
set Update ghost particles = true | ||
set Particle generator name = random uniform | ||
|
||
subsection Function | ||
set Variable names = x,z | ||
set Function expression = 0.5*(1+tanh((0.2+0.02*cos(pi*x/0.9142)-z)/0.02)) | ||
end | ||
|
||
subsection Generator | ||
subsection Probability density function | ||
set Variable names = x,z | ||
set Function expression = x*x*z | ||
end | ||
end | ||
end | ||
end |
31 changes: 31 additions & 0 deletions
31
tests/particle_interpolator_distance_weighted_average/screen-output
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
|
||
Number of active cells: 256 (on 5 levels) | ||
Number of degrees of freedom: 10,468 (2,178+289+1,089+2,304+2,304+2,304) | ||
|
||
*** Timestep 0: t=0 seconds, dt=0 seconds | ||
Skipping temperature solve because RHS is zero. | ||
Advecting particles... done. | ||
Solving advection_field system ... 0 iterations. | ||
Rebuilding Stokes preconditioner... | ||
Solving Stokes system... 34+0 iterations. | ||
|
||
Postprocessing: | ||
RMS, max velocity: 0.000181 m/s, 0.000404 m/s | ||
Compositions min/max/mass: 0/1/0.1825 // 0/1/0.1828 // 0/0/0 | ||
Number of advected particles: 100000 | ||
|
||
*** Timestep 1: t=70 seconds, dt=70 seconds | ||
Skipping temperature solve because RHS is zero. | ||
Advecting particles... done. | ||
Solving advection_field system ... 5 iterations. | ||
Solving Stokes system... 34+0 iterations. | ||
|
||
Postprocessing: | ||
RMS, max velocity: 0.000328 m/s, 0.000732 m/s | ||
Compositions min/max/mass: -0.007595/1.023/0.1825 // 0/1/0.1829 // -0.0002466/0.0003166/-1.013e-08 | ||
Number of advected particles: 100000 | ||
|
||
Termination requested by criterion: end time | ||
|
||
|
||
|
Oops, something went wrong.