|
| 1 | +/* |
| 2 | + Copyright (C) 2011 - 2024 by the authors of the ASPECT code. |
| 3 | +
|
| 4 | + This file is part of ASPECT. |
| 5 | +
|
| 6 | + ASPECT is free software; you can redistribute it and/or modify |
| 7 | + it under the terms of the GNU General Public License as published by |
| 8 | + the Free Software Foundation; either version 2, or (at your option) |
| 9 | + any later version. |
| 10 | +
|
| 11 | + ASPECT is distributed in the hope that it will be useful, |
| 12 | + but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 13 | + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 14 | + GNU General Public License for more details. |
| 15 | +
|
| 16 | + You should have received a copy of the GNU General Public License |
| 17 | + along with ASPECT; see the file LICENSE. If not see |
| 18 | + <http://www.gnu.org/licenses/>. |
| 19 | +*/ |
| 20 | + |
| 21 | + |
| 22 | +#ifndef _aspect_mesh_deformation_external_tool_interface_h |
| 23 | +#define _aspect_mesh_deformation_external_tool_interface_h |
| 24 | + |
| 25 | +#include <aspect/mesh_deformation/interface.h> |
| 26 | + |
| 27 | + |
| 28 | +namespace aspect |
| 29 | +{ |
| 30 | + namespace MeshDeformation |
| 31 | + { |
| 32 | + /** |
| 33 | + * This class provides some support for writing classes derived |
| 34 | + * from MeshDeformation::Interface when implementing surface |
| 35 | + * deformation models that are based on external tools such as |
| 36 | + * Fastscape, Landlab, OpenLEM, etc. The primary complication of |
| 37 | + * interacting with these external tools is that they generally |
| 38 | + * use their own discretization of surface processes, using a mesh |
| 39 | + * that, in most cases, will be different from the one used by |
| 40 | + * ASPECT. (Of course, ASPECT's use is a *volume* mesh, whereas |
| 41 | + * surface processes use *surface* meshes. ASPECT's own surface |
| 42 | + * diffusion, for example, works on the surface faces of ASPECT's |
| 43 | + * mesh, but in general, external tools use a mesh that is |
| 44 | + * *entirely unrelated* to the surface cells of ASPECT's volume |
| 45 | + * mesh.) In these cases, one needs to implement transfer |
| 46 | + * operations to take ASPECT's solution and interpolate it to the |
| 47 | + * external tool's mesh, run some surface evolution steps, and |
| 48 | + * then interpolate back to the surface nodes of ASPECT's |
| 49 | + * mesh. These interpolation operations are difficult to implement |
| 50 | + * in their own right, but are made particularly cumbersome in |
| 51 | + * parallel because then, the points at which the external tool |
| 52 | + * wants to know the solution on any given MPI process will, in |
| 53 | + * general, not be located on that part of ASPECT's mesh that is |
| 54 | + * owned by that MPI process. As a consequence, implementing the |
| 55 | + * interpolation requires finding the MPI process that owns the |
| 56 | + * cell on which that point is located, and then communication |
| 57 | + * back and forth. |
| 58 | + * |
| 59 | + * @sect3{Helper functions} |
| 60 | + * |
| 61 | + * This class implements the interpolation functionality for |
| 62 | + * derived classes to use. It works through a two-stage approach: |
| 63 | + * First, derived classes declare at which points they require |
| 64 | + * ASPECT's solution to be evaluated, via the |
| 65 | + * set_evaluation_points() function. This function then finds |
| 66 | + * which process owns the cell around this point, and sets up |
| 67 | + * communication structures that will make later evaluation |
| 68 | + * efficient. Second, this class provides the |
| 69 | + * evaluate_aspect_variables_at_points() function that uses these |
| 70 | + * communication structures to evaluate ASPECT's current solution |
| 71 | + * at the points previously set. The class also provides the |
| 72 | + * interpolate_vertical_velocities_to_surface_points() function |
| 73 | + * that takes a set of (vertical) velocity values at these points |
| 74 | + * and uses them to interpolate the information back onto ASPECT's |
| 75 | + * mesh. |
| 76 | + * |
| 77 | + * All three of these functions are `protected` member functions |
| 78 | + * of this class, ready to be called by derived classes. |
| 79 | + * |
| 80 | + * |
| 81 | + * @sect3{A high-level function} |
| 82 | + * |
| 83 | + * All classes derived from Interface need to implement the |
| 84 | + * Interface::compute_velocity_constraints_on_boundary() |
| 85 | + * function. Because the basic outline of this function looks |
| 86 | + * essentially the same for all external tools, this class also |
| 87 | + * provides a high-level implementation of this function is also |
| 88 | + * provided as part of this class. In essence, it looks as |
| 89 | + * follows (pseudo-code), relying on the |
| 90 | + * `compute_updated_velocities_at_points()` function that gets |
| 91 | + * ASPECT's solution at the evaluation points and returns velocity |
| 92 | + * vectors at all of these evaluation points: |
| 93 | + * @code |
| 94 | + * // Interpolate ASPECT's solution at evaluation points: |
| 95 | + * aspect_surface_velocities = evaluate_aspect_variables_at_points(); |
| 96 | + * |
| 97 | + * // Call derive class's method to compute updated velocities: |
| 98 | + * external_surface_velocities = compute_updated_velocities_at_points(aspect_surface_velocities); |
| 99 | + * |
| 100 | + * // Turn the result into the constraints that |
| 101 | + * // compute_velocity_constraints_on_boundary is supposed |
| 102 | + * // to return. |
| 103 | + * @endcode |
| 104 | + */ |
| 105 | + template <int dim> |
| 106 | + class ExternalToolInterface : public Interface<dim>, public SimulatorAccess<dim> |
| 107 | + { |
| 108 | + public: |
| 109 | + /** |
| 110 | + * Main routine handling the mesh deformation |
| 111 | + */ |
| 112 | + virtual |
| 113 | + void |
| 114 | + compute_velocity_constraints_on_boundary(const DoFHandler<dim> &mesh_deformation_dof_handler, |
| 115 | + AffineConstraints<double> &mesh_velocity_constraints, |
| 116 | + const std::set<types::boundary_id> &boundary_ids) const override; |
| 117 | + |
| 118 | + /** |
| 119 | + * Given all solution variables at each surface point, compute velocities at these points. |
| 120 | + * |
| 121 | + * This needs to be implemented by the derived class and implement the "surface evolution". |
| 122 | + */ |
| 123 | + virtual |
| 124 | + std::vector<Tensor<1,dim>> |
| 125 | + compute_updated_velocities_at_points (const std::vector<std::vector<double>> ¤t_solution_at_points) const = 0; |
| 126 | + |
| 127 | + |
| 128 | + protected: |
| 129 | + // Helper functions to be used in derived classes: |
| 130 | + |
| 131 | + /** |
| 132 | + * Declare at which points the external tool driven by a class |
| 133 | + * derived from the current one needs to evaluate the ASPECT |
| 134 | + * solution. Each process will call this function with the points |
| 135 | + * it needs. Different processes will, in general, provide |
| 136 | + * distinct sets of points. |
| 137 | + * |
| 138 | + * The points provided here are given in the undeformed |
| 139 | + * configuration that corresponds to the initial mesh. For |
| 140 | + * example, if the mesh describes a box geometry, then the |
| 141 | + * points should like in the $x$-$y$-plane that forms the top |
| 142 | + * surface, rather than on the currently deformed top surface |
| 143 | + * that describes the current elevation map. |
| 144 | + * |
| 145 | + * @note This function sets up communication structures that |
| 146 | + * encode, among other things, which process owns which |
| 147 | + * points. This information becomes outdated when the |
| 148 | + * ASPECT mesh changes for mesh refinement. As a |
| 149 | + * consequence, the current function sets up a process that |
| 150 | + * invalidates the communication structures upon mesh |
| 151 | + * refinement. Derived classes therefore have to set up |
| 152 | + * their own code to call set_evaluation_points() again when |
| 153 | + * the ASPECT mesh changes, or perhaps simply check whether |
| 154 | + * the information needs to be updated in an overload of the |
| 155 | + * update() function called at the beginning of each time |
| 156 | + * step. |
| 157 | + */ |
| 158 | + void |
| 159 | + set_evaluation_points (const std::vector<Point<dim>> &evaluation_points); |
| 160 | + |
| 161 | + /** |
| 162 | + * Return the value of the ASPECT solution at the set of points |
| 163 | + * previously set via set_evaluation_points(). |
| 164 | + * |
| 165 | + * For each point, the return object contains a vector with as |
| 166 | + * many components as there are ASPECT solution components. |
| 167 | + */ |
| 168 | + std::vector<std::vector<double>> |
| 169 | + evaluate_aspect_variables_at_points () const; |
| 170 | + |
| 171 | + /** |
| 172 | + * Interpolate from velocities given in the evaluation points |
| 173 | + * to ASPECT velocities on the surface in form of a finite |
| 174 | + * element field. |
| 175 | + * |
| 176 | + * The @p velocities, which are typically vertical, were previously |
| 177 | + * computed by the external tool and belong to the current process. |
| 178 | + * The Output is a (global) finite element field vector that in |
| 179 | + * the velocity components of surface nodes corresponds to an |
| 180 | + * interpolation of the velocities provided. |
| 181 | + * |
| 182 | + * The output of this function can then be used as input for a |
| 183 | + * function that implements the |
| 184 | + * compute_velocity_constraints_on_boundary() function of the |
| 185 | + * base class. |
| 186 | + */ |
| 187 | + LinearAlgebra::Vector |
| 188 | + interpolate_external_velocities_to_surface_support_points (const std::vector<Tensor<1,dim>> &velocities) const; |
| 189 | + |
| 190 | + /** |
| 191 | + * The list of evaluation points owned by the current process. These are the points where the |
| 192 | + * external tool will receive the ASPECT solution values and return the updated velocities. |
| 193 | + */ |
| 194 | + std::vector<Point<dim>> evaluation_points; |
| 195 | + |
| 196 | + /** |
| 197 | + * deal.II RemotePointEvaluation object used to do point evaluation in the evaluation points. |
| 198 | + */ |
| 199 | + std::unique_ptr<Utilities::MPI::RemotePointEvaluation<dim, dim>> remote_point_evaluator; |
| 200 | + |
| 201 | + /** |
| 202 | + * A struct to map between DoF indices and evaluation points |
| 203 | + */ |
| 204 | + struct DofToEvalPointData |
| 205 | + { |
| 206 | + types::global_dof_index dof_index; |
| 207 | + unsigned int evaluation_point_index; |
| 208 | + unsigned int component; |
| 209 | + }; |
| 210 | + |
| 211 | + /** |
| 212 | + * A vector to store a map between Dof indices and evaluation points. |
| 213 | + * |
| 214 | + * The map will contain an entry for each DoF on the surface of the ASPECT mesh and contains |
| 215 | + * the index of the evaluation point that is closest to the DoF. As each support point has |
| 216 | + * several components (x,y,z velocity), the map contains one entry for each component. |
| 217 | + * |
| 218 | + * In a parallel computation, this map only contains entries for evaluation points owned by the |
| 219 | + * current process. Note that the DoF indices are not necessarily locally owned. |
| 220 | + * |
| 221 | + * This map is used in interpolate_external_velocities_to_surface_support_points() to copy |
| 222 | + * external velocities to each surface DoF from the closest evaluation point. |
| 223 | + */ |
| 224 | + std::vector<DofToEvalPointData> map_dof_to_eval_point; |
| 225 | + }; |
| 226 | + } |
| 227 | +} |
| 228 | + |
| 229 | +#endif |
0 commit comments