Skip to content

Commit 6e7884e

Browse files
committed
sequential version
1 parent b1f32ad commit 6e7884e

File tree

9 files changed

+721
-145
lines changed

9 files changed

+721
-145
lines changed

include/aspect/mesh_deformation/external_tool_interface.h

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -189,6 +189,22 @@ namespace aspect
189189
std::vector<Point<dim>> evaluation_points;
190190

191191
std::unique_ptr<Utilities::MPI::RemotePointEvaluation<dim, dim>> remote_point_evaluator;
192+
193+
/**
194+
* A struct to map between DoF indices and evaluation points
195+
*/
196+
struct dof_to_eval_point_data
197+
{
198+
types::global_dof_index dof_index;
199+
unsigned int evaluation_point_index;
200+
unsigned int component;
201+
};
202+
203+
/**
204+
* A vector to store a map between Dof indices and evaluation points
205+
*/
206+
std::vector<dof_to_eval_point_data> map_dof_to_eval_point;
207+
192208
};
193209
}
194210
}

source/mesh_deformation/external_tool_interface.cc

Lines changed: 88 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -371,6 +371,91 @@ namespace aspect
371371
remote_point_evaluator = std::make_unique<Utilities::MPI::RemotePointEvaluation<dim, dim>>();
372372
remote_point_evaluator->reinit(this->evaluation_points, this->get_triangulation(), mapping);
373373

374+
375+
// Create a mapping from evaluation points to support points. Note that one evaluation point can map to
376+
// multiple support points.
377+
{
378+
// For now, we only support a single MPI rank for ASPECT and the external mesh deformation class. Because deciding
379+
// which evaluation point is closest to a support point requires somewhat complex MPI communication.
380+
Assert(Utilities::MPI::n_mpi_processes(this->get_mpi_communicator()) == 1,
381+
ExcNotImplemented("This function is not implemented for parallel computations."));
382+
383+
const DoFHandler<dim> &mesh_dof_handler = this->get_mesh_deformation_handler().get_mesh_deformation_dof_handler();
384+
385+
std::vector<double> squared_distances(mesh_dof_handler.locally_owned_dofs().size(), std::numeric_limits<double>::max());
386+
std::vector<dof_to_eval_point_data> closest_evaluation_point_and_component(mesh_dof_handler.locally_owned_dofs().size(),
387+
dof_to_eval_point_data {numbers::invalid_dof_index, numbers::invalid_unsigned_int, numbers::invalid_unsigned_int});
388+
389+
// TODO: do we need to support the case of more than one different mesh deformation plugin to be active?
390+
const auto boundary_ids = this->get_mesh_deformation_boundary_indicators();
391+
392+
IndexSet boundary_dofs = DoFTools::extract_boundary_dofs(mesh_dof_handler, ComponentMask(dim, true), boundary_ids);
393+
394+
const unsigned int dofs_per_cell = mesh_dof_handler.get_fe().dofs_per_cell;
395+
std::vector<types::global_dof_index> local_dof_indices (dofs_per_cell);
396+
397+
// The remote_point_evaluator will gives us the velocities in all evaluation points that are within one of our locally
398+
// owned cells. The lambda defined below receives a list of points and their velocities for each cell. The coordinates
399+
// are given in coordinates of the unit cell.
400+
// For each support point of the velocity DoFHandler, we will try to find the closest evaluation point. We
401+
// do this by keeping track of the squared distance of the closest evaluation point checked so far.
402+
403+
404+
// Note: We assume that process_and_evaluate() does not call our lambda concurrently, otherwise we would have write
405+
// conflicts when updating vector_with_surface_velocities and one_over_distance_vec.
406+
407+
const auto eval_func = [&](const ArrayView<const unsigned int> &values,
408+
const typename Utilities::MPI::RemotePointEvaluation<dim>::CellData &cell_data)
409+
{
410+
std::vector<types::global_dof_index> cell_dof_indices (dofs_per_cell);
411+
for (const auto cell_index : cell_data.cell_indices())
412+
{
413+
const auto cell_dofs =
414+
cell_data.get_active_cell_iterator(cell_index)->as_dof_handler_iterator(
415+
mesh_dof_handler);
416+
cell_dofs->get_dof_indices(cell_dof_indices);
417+
418+
const ArrayView<const Point<dim>> unit_points = cell_data.get_unit_points(cell_index);
419+
const auto local_values = cell_data.get_data_view(cell_index, values);
420+
421+
const std::vector< Point< dim >> &support_points = mesh_dof_handler.get_fe().get_unit_support_points();
422+
for (unsigned int i=0; i<unit_points.size(); ++i)
423+
{
424+
for (unsigned int j=0; j<support_points.size(); ++j)
425+
{
426+
const double distance_sq = unit_points[i].distance_square(support_points[j]);
427+
if (distance_sq < squared_distances[cell_dof_indices[j]])
428+
{
429+
squared_distances[cell_dof_indices[j]] = distance_sq;
430+
const unsigned int component = mesh_dof_handler.get_fe().system_to_component_index(j).first;
431+
closest_evaluation_point_and_component[cell_dof_indices[j]] =
432+
dof_to_eval_point_data {cell_dof_indices[j], local_values[i], component};
433+
}
434+
}
435+
}
436+
}
437+
};
438+
439+
std::vector<unsigned int> indices (evaluation_points.size());
440+
std::iota(indices.begin(), indices.end(), 0);
441+
this->remote_point_evaluator->template process_and_evaluate<unsigned int, 1>(indices, eval_func, /*sort_data*/ true);
442+
443+
map_dof_to_eval_point.clear();
444+
for (unsigned int i=0; i<closest_evaluation_point_and_component.size(); ++i)
445+
{
446+
if (closest_evaluation_point_and_component[i].dof_index != numbers::invalid_dof_index)
447+
map_dof_to_eval_point.push_back(closest_evaluation_point_and_component[i]);
448+
}
449+
450+
// print all information:
451+
std::cout << "map_dof_to_eval_point (dof, evaluation_point_index, component): " << std::endl;
452+
for (const auto &dof_to_eval_point : map_dof_to_eval_point)
453+
{
454+
std::cout << dof_to_eval_point.dof_index << " " << dof_to_eval_point.evaluation_point_index << " " << dof_to_eval_point.component << std::endl;
455+
}
456+
}
457+
458+
374459
// Finally, also ensure that upon mesh refinement, all of the
375460
// information set herein is invalidated:
376461
this->get_signals().pre_refinement_store_user_data
@@ -434,7 +519,7 @@ namespace aspect
434519
static unsigned int output_no = 0;
435520

436521
PointDataOut<dim, dim> out;
437-
// const auto &mapping = this->get_mapping();
522+
//const auto &mapping = this->get_mapping();
438523
std::vector<Point<dim>> real_evaluation_points(evaluation_points.size());
439524
std::vector<std::vector<double>> data(evaluation_points.size(), std::vector<double>(dim, 0.0));
440525
for (unsigned int i=0; i<evaluation_points.size(); ++i)
@@ -461,56 +546,9 @@ namespace aspect
461546
LinearAlgebra::Vector vector_with_surface_velocities(mesh_dof_handler.locally_owned_dofs(),
462547
this->get_mpi_communicator());
463548

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.
470-
LinearAlgebra::Vector one_over_distance_vec(mesh_dof_handler.locally_owned_dofs(),
471-
this->get_mpi_communicator());
472-
473-
const unsigned int dofs_per_cell = mesh_dof_handler.get_fe().dofs_per_cell;
474-
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.
477-
const auto eval_func = [&](const ArrayView< const Tensor<1,dim>> &values,
478-
const typename Utilities::MPI::RemotePointEvaluation<dim>::CellData &cell_data)
479-
{
480-
std::vector<types::global_dof_index> cell_dof_indices (dofs_per_cell);
481-
for (const auto cell_index : cell_data.cell_indices())
482-
{
483-
const auto cell_dofs =
484-
cell_data.get_active_cell_iterator(cell_index)->as_dof_handler_iterator(
485-
mesh_dof_handler);
486-
487-
const ArrayView<const Point<dim>> unit_points = cell_data.get_unit_points(cell_index);
488-
const auto local_values = cell_data.get_data_view(cell_index, values);
489-
490-
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).
494-
const std::vector< Point< dim >> &support_points = mesh_dof_handler.get_fe().get_unit_support_points();
495-
for (unsigned int i=0; i<unit_points.size(); ++i)
496-
{
497-
for (unsigned int j=0; j<support_points.size(); ++j)
498-
{
499-
const double one_over_distance = 1.0/(unit_points[i].distance(support_points[j])+1e-10);
500-
if (one_over_distance > one_over_distance_vec(cell_dof_indices[j]))
501-
{
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:
504-
one_over_distance_vec(cell_dof_indices[j]) = one_over_distance;
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];
507-
}
508-
}
509-
}
510-
}
511-
};
549+
for (const auto &entry : map_dof_to_eval_point)
550+
vector_with_surface_velocities[entry.dof_index] = velocities[entry.evaluation_point_index][entry.component];
512551

513-
this->remote_point_evaluator->template process_and_evaluate<Tensor<1,dim>,1>(velocities, eval_func, /*sort_data*/ true);
514552
vector_with_surface_velocities.compress(VectorOperation::insert);
515553

516554
return vector_with_surface_velocities;

tests/mesh_deformation_external_01.cc

Lines changed: 11 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -60,28 +60,19 @@ namespace aspect
6060
{
6161
if constexpr (dim == 2)
6262
{
63-
points.emplace_back(0.3, 1.0);
64-
points.emplace_back(0.5, 1.0);
63+
for (unsigned int x=0; x<11; ++x)
64+
points.emplace_back(0.05+x*1.0/11, 1.0);
6565
}
6666
else
6767
{
68-
points.emplace_back(0.3, 0.7, 1.0);
69-
points.emplace_back(0.5, 0.5, 1.0);
70-
points.emplace_back(0.7, 0.2, 1.0);
71-
points.emplace_back(0.7, 0.91, 1.0);
68+
for (unsigned int x=0; x<5; ++x)
69+
for (unsigned int y=0; y<5; ++y)
70+
points.emplace_back(0.1+x*1.0/5, 0.1+y*1.0/5, 1.0);
7271
}
7372
}
7473
else
75-
{
76-
if constexpr (dim == 2)
77-
{
78-
points.emplace_back(0.72, 1.0);
79-
}
80-
else
81-
{
82-
points.emplace_back(0.9, 0.9, 1.0);
83-
}
84-
}
74+
Assert(false, ExcNotImplemented());
75+
8576
this->set_evaluation_points (points);
8677
}
8778
}
@@ -123,10 +114,11 @@ namespace aspect
123114

124115
Assert(current_solution_at_points.size() == this->evaluation_points.size(), ExcInternalError());
125116
std::vector<Tensor<1,dim>> velocities(current_solution_at_points.size(), Tensor<1,dim>());
126-
if (velocities.size()>1)
117+
if (velocities.size()>6)
127118
{
128-
velocities[0][dim-1]=30.0;
129-
velocities[1][dim-1]=-3.5;
119+
velocities[1][dim-1]=30.0;
120+
velocities[4][dim-1]=-5.0;
121+
velocities[6][dim-1]=10.0;
130122
}
131123
return velocities;
132124
}

tests/mesh_deformation_external_01.prm

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,10 @@
22
# derived class written as a plugin, 2d box geometry, initial
33
# topography coming from the plugin (and not initial topography)
44
#
5-
# MPI: 2
5+
# MPI: 1
66

77
set Dimension = 2
8-
set Use years in output instead of seconds = false
8+
set Use years instead of seconds = false
99
set End time = 0.004
1010
set Maximum time step = 0.0005
1111
set Nonlinear solver scheme = no Advection, no Stokes
@@ -78,7 +78,7 @@ end
7878
# We here use a globally refined mesh without
7979
# adaptive mesh refinement.
8080
subsection Mesh refinement
81-
set Initial global refinement = 4
81+
set Initial global refinement = 3
8282
set Initial adaptive refinement = 0
8383
set Time steps between mesh refinement = 0
8484
end

0 commit comments

Comments
 (0)