@@ -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;
0 commit comments