Skip to content

Commit bcdab67

Browse files
committed
address comments
1 parent 2023709 commit bcdab67

File tree

2 files changed

+63
-47
lines changed

2 files changed

+63
-47
lines changed

include/aspect/mesh_deformation/external_tool_interface.h

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -166,20 +166,23 @@ namespace aspect
166166
evaluate_aspect_variables_at_points () const;
167167

168168
/**
169-
* Given velocities (typically vertical, but not always) at
170-
* all of the points this process has previously set via
171-
* set_evaluation_points(), compute a (global) finite element
172-
* field vector that in the velocity components of surface
173-
* nodes corresponds to an interpolation of the velocities
174-
* provided.
169+
* Interpolate from velocities given in the evaluation points
170+
* to ASPECT velocities on the surface in form of a finite
171+
* element field.
172+
*
173+
* The @p velocities, which are typically vertical, were previously
174+
* computed by the external tool and belong to the current process.
175+
* The Output is a (global) finite element field vector that in
176+
* the velocity components of surface nodes corresponds to an
177+
* interpolation of the velocities provided.
175178
*
176179
* The output of this function can then be used as input for a
177180
* function that implements the
178181
* compute_velocity_constraints_on_boundary() function of the
179182
* base class.
180183
*/
181184
LinearAlgebra::Vector
182-
interpolate_velocities_to_surface_points (const std::vector<Tensor<1,dim>> &vertical_velocities) const;
185+
interpolate_external_velocities_to_surface_support_points (const std::vector<Tensor<1,dim>> &velocities) const;
183186

184187
protected:
185188

source/mesh_deformation/external_tool_interface.cc

Lines changed: 53 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,9 @@ namespace aspect
3737
{
3838

3939

40-
40+
/**
41+
* Produce graphical output defined in points provided by the user.
42+
*/
4143
template <int dim, int spacedim = dim>
4244
class PointDataOut : public dealii::DataOutInterface<0, spacedim>
4345
{
@@ -72,14 +74,21 @@ namespace aspect
7274
DataComponentInterpretation::DataComponentInterpretation>
7375
&data_component_interpretations_ = {})
7476
{
75-
Assert(
76-
data_component_names.size() == data_component_interpretations_.size(),
77-
ExcMessage(
78-
"When calling Particles::DataOut::build_patches with data component "
79-
"names and interpretations you need to provide as many data component "
80-
"names as interpretations. Provide the same name for components that "
81-
"belong to a single vector or tensor."));
82-
77+
Assert(data_component_names.size() == data_component_interpretations_.size(),
78+
ExcMessage(
79+
"When calling PointDataOut::build_patches() with data component "
80+
"names and interpretations you need to provide as many data component "
81+
"names as interpretations. Provide the same name for components that "
82+
"belong to a single vector or tensor."));
83+
84+
Assert(data.size() == 0 || locations.size(),
85+
ExcMessage("You need to either provide no data or data for each point."));
86+
for (const auto &datum : data)
87+
Assert(datum.size() == data_component_names.size(),
88+
ExcMessage("The data provided in each point needs to have the same number "
89+
"of components as names were provided."));
90+
91+
// Prepend the "id" to the data fields provided by the user:
8392
dataset_names.clear();
8493
dataset_names.emplace_back("id");
8594
dataset_names.insert(dataset_names.end(),
@@ -104,26 +113,17 @@ namespace aspect
104113
patches[i].vertices[0] = locations[i];
105114
patches[i].patch_index = i;
106115

107-
// We have one more data components than dataset_names (the particle id)
116+
// Store id and properties given by the user:
108117
patches[i].data.reinit(n_data_components, 1);
109-
110-
patches[i].data(0, 0) = i; // id
111-
112-
if (n_data_components > 1)
113-
{
114-
for (unsigned int property_index = 0;
115-
property_index < n_property_components;
116-
++property_index)
117-
patches[i].data(property_index + 1, 0) =
118-
data[i][property_index];
119-
}
118+
patches[i].data(0, 0) = i; // store id
119+
for (unsigned int property_index = 0; property_index < n_property_components; ++property_index)
120+
patches[i].data(property_index + 1, 0) = data[i][property_index];
120121
}
121122
}
122123

123124
protected:
124125
/**
125-
* Returns the patches built by the data_out class which was previously
126-
* built using a particle handler
126+
* Returns the patches previously built by the build_patches() function.
127127
*/
128128
virtual const std::vector<DataOutBase::Patch<0, spacedim>> &
129129
get_patches() const override
@@ -318,7 +318,7 @@ namespace aspect
318318
= compute_updated_velocities_at_points(aspect_surface_velocities);
319319

320320
const LinearAlgebra::Vector v_interpolated
321-
= interpolate_velocities_to_surface_points(external_surface_velocities);
321+
= interpolate_external_velocities_to_surface_support_points(external_surface_velocities);
322322

323323
// TODO: need ghost values of v_interpolated?
324324

@@ -363,10 +363,12 @@ namespace aspect
363363
// for later function calls describe the same number of points.
364364
this->evaluation_points = evaluation_points;
365365

366-
// Set up RemotePointEvaluation with a Mapping of the undeformed mesh:
367-
remote_point_evaluator = std::make_unique<Utilities::MPI::RemotePointEvaluation<dim, dim>>();
368-
// TODO: does this need to be a higher order mapping for spherical problems?
366+
// Set up RemotePointEvaluation. The evaluation points are given in reference coordinates,
367+
// so we need to use a simple mapping instead of the one stored in the Simulator. The latter
368+
// would produce the deformed mesh. We currently always use a Q1 mapping when mesh deformation
369+
// is enabled, so a Q1 mapping is the right choice.
369370
static MappingQ<dim> mapping(1);
371+
remote_point_evaluator = std::make_unique<Utilities::MPI::RemotePointEvaluation<dim, dim>>();
370372
remote_point_evaluator->reinit(this->evaluation_points, this->get_triangulation(), mapping);
371373

372374
// Finally, also ensure that upon mesh refinement, all of the
@@ -401,13 +403,13 @@ namespace aspect
401403
// to put directly into deal.II...
402404
for (unsigned int c=0; c<n_components; ++c)
403405
{
404-
std::vector<double> values = VectorTools::point_values<1>(*this->remote_point_evaluator,
405-
this->get_dof_handler(),
406-
this->get_solution(),
407-
dealii::VectorTools::EvaluationFlags::avg,
408-
c);
406+
const std::vector<double> values = VectorTools::point_values<1>(*this->remote_point_evaluator,
407+
this->get_dof_handler(),
408+
this->get_solution(),
409+
dealii::VectorTools::EvaluationFlags::avg,
410+
c);
409411
for (unsigned int i=0; i<evaluation_points.size(); ++i)
410-
solution_at_points[i][c]=values[i];
412+
solution_at_points[i][c] = values[i];
411413
}
412414

413415
return solution_at_points;
@@ -418,7 +420,7 @@ namespace aspect
418420
template <int dim>
419421
LinearAlgebra::Vector
420422
ExternalToolInterface<dim>::
421-
interpolate_velocities_to_surface_points (const std::vector<Tensor<1,dim>> &velocities) const
423+
interpolate_external_velocities_to_surface_support_points (const std::vector<Tensor<1,dim>> &velocities) const
422424
{
423425
Assert (remote_point_evaluator != nullptr,
424426
ExcMessage("You can only call this function if you have previously "
@@ -458,16 +460,24 @@ namespace aspect
458460
const DoFHandler<dim> &mesh_dof_handler = this->get_mesh_deformation_handler().get_mesh_deformation_dof_handler();
459461
LinearAlgebra::Vector vector_with_surface_velocities(mesh_dof_handler.locally_owned_dofs(),
460462
this->get_mpi_communicator());
463+
464+
// The remote_point_evaluator will gives us the velocities in all evaluation points that are within one of our locally
465+
// owned cells. The lambda defined below receives a list of points and their velocities for each cell. The coordinates
466+
// are given in coordinates of the unit cell.
467+
// For each support point of the velocity DoFHandler, we will set the velocity from the closest evaluation point. We
468+
// do this by keeping track of 1/distance of the closest evaluation point checked so far. The initial value of 0.0
469+
// denotes an infinite distance.
461470
LinearAlgebra::Vector one_over_distance_vec(mesh_dof_handler.locally_owned_dofs(),
462471
this->get_mpi_communicator());
463472

464-
465473
const unsigned int dofs_per_cell = mesh_dof_handler.get_fe().dofs_per_cell;
466-
std::vector<types::global_dof_index> cell_dof_indices (dofs_per_cell);
467474

475+
// Note: We assume that process_and_evaluate() does not call our lambda concurrently, otherwise we would have write
476+
// conflicts when updating vector_with_surface_velocities and one_over_distance_vec.
468477
const auto eval_func = [&](const ArrayView< const Tensor<1,dim>> &values,
469478
const typename Utilities::MPI::RemotePointEvaluation<dim>::CellData &cell_data)
470479
{
480+
std::vector<types::global_dof_index> cell_dof_indices (dofs_per_cell);
471481
for (const auto cell_index : cell_data.cell_indices())
472482
{
473483
const auto cell_dofs =
@@ -478,6 +488,9 @@ namespace aspect
478488
const auto local_values = cell_data.get_data_view(cell_index, values);
479489

480490
cell_dofs->get_dof_indices(cell_dof_indices);
491+
492+
// Note: This search is a nested loop with the inner part executed #evaluation_point_in_this_cell * #dofs_per_cell
493+
// times. We could precompute this information as the point locations and do not change (outside of mesh refinement).
481494
const std::vector< Point< dim >> &support_points = mesh_dof_handler.get_fe().get_unit_support_points();
482495
for (unsigned int i=0; i<unit_points.size(); ++i)
483496
{
@@ -486,18 +499,18 @@ namespace aspect
486499
const double one_over_distance = 1.0/(unit_points[i].distance(support_points[j])+1e-10);
487500
if (one_over_distance > one_over_distance_vec(cell_dof_indices[j]))
488501
{
502+
// The point i is closer to support point j than anything we have seen so far. Keep track
503+
// of the distance and write the correct velocity component into the result:
489504
one_over_distance_vec(cell_dof_indices[j]) = one_over_distance;
490-
const unsigned int c = mesh_dof_handler.get_fe().system_to_component_index(j).first;
491-
vector_with_surface_velocities(cell_dof_indices[j]) = local_values[i][c];
505+
const unsigned int component = mesh_dof_handler.get_fe().system_to_component_index(j).first;
506+
vector_with_surface_velocities(cell_dof_indices[j]) = local_values[i][component];
492507
}
493508
}
494509
}
495510
}
496511
};
497512

498513
this->remote_point_evaluator->template process_and_evaluate<Tensor<1,dim>,1>(velocities, eval_func, /*sort_data*/ true);
499-
500-
one_over_distance_vec.compress(VectorOperation::insert);
501514
vector_with_surface_velocities.compress(VectorOperation::insert);
502515

503516
return vector_with_surface_velocities;

0 commit comments

Comments
 (0)