ExaDG
Loading...
Searching...
No Matches
quad_coupling.h
1/* ______________________________________________________________________
2 *
3 * ExaDG - High-Order Discontinuous Galerkin for the Exa-Scale
4 *
5 * Copyright (C) 2022 by the ExaDG authors
6 *
7 * This program is free software: you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation, either version 3 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program. If not, see <https://www.gnu.org/licenses/>.
19 * ______________________________________________________________________
20 */
21
22#ifndef EXADG_FLUID_STRUCTURE_INTERACTION_PRECICE_QUAD_COUPLING_H_
23#define EXADG_FLUID_STRUCTURE_INTERACTION_PRECICE_QUAD_COUPLING_H_
24
25// deal.II
26#include <deal.II/matrix_free/fe_evaluation.h>
27
28// ExaDG
29#include <exadg/fluid_structure_interaction/precice/coupling_base.h>
30
31namespace ExaDG
32{
33namespace preCICE
34{
42template<int dim, int data_dim, typename VectorizedArrayType>
43class QuadCoupling : public CouplingBase<dim, data_dim, VectorizedArrayType>
44{
45public:
46 QuadCoupling(dealii::MatrixFree<dim, double, VectorizedArrayType> const & data,
47#ifdef EXADG_WITH_PRECICE
48 std::shared_ptr<precice::SolverInterface> precice,
49#endif
50 std::string const mesh_name,
51 dealii::types::boundary_id const surface_id,
52 int const mf_dof_index,
53 int const mf_quad_index);
54
58 using value_type = typename CouplingBase<dim, data_dim, VectorizedArrayType>::value_type;
59
64 virtual void
65 define_coupling_mesh() override;
66
79 virtual void
80 write_data(dealii::LinearAlgebra::distributed::Vector<double> const & data_vector,
81 std::string const & data_name) override;
82
83private:
93 void
94 write_data_factory(
95 dealii::LinearAlgebra::distributed::Vector<double> const & data_vector,
96 int const write_data_id,
97 dealii::EvaluationFlags::EvaluationFlags const flags,
98 std::function<value_type(FEFaceIntegrator &, unsigned int)> const & get_write_value);
99
101 std::vector<std::array<int, VectorizedArrayType::size()>> coupling_nodes_ids;
102
105 int const mf_dof_index;
106 int const mf_quad_index;
107
108 virtual std::string
109 get_surface_type() const override;
110};
111
112
113
114template<int dim, int data_dim, typename VectorizedArrayType>
115QuadCoupling<dim, data_dim, VectorizedArrayType>::QuadCoupling(
116 dealii::MatrixFree<dim, double, VectorizedArrayType> const & data,
117#ifdef EXADG_WITH_PRECICE
118 std::shared_ptr<precice::SolverInterface> precice,
119#endif
120 std::string const mesh_name,
121 dealii::types::boundary_id const surface_id,
122 int const mf_dof_index_,
123 int const mf_quad_index_)
124 : CouplingBase<dim, data_dim, VectorizedArrayType>(data,
125#ifdef EXADG_WITH_PRECICE
126 precice,
127#endif
128 mesh_name,
129 surface_id),
130 mf_dof_index(mf_dof_index_),
131 mf_quad_index(mf_quad_index_)
132{
133}
134
135
136
137template<int dim, int data_dim, typename VectorizedArrayType>
138void
140{
141 Assert(this->mesh_id != -1, dealii::ExcNotInitialized());
142
143 // In order to avoid that we define the surface multiple times when reader
144 // and writer refer to the same object
145 if(coupling_nodes_ids.size() > 0)
146 return;
147
148 // Initial guess: half of the boundary is part of the coupling surface
149 coupling_nodes_ids.reserve(this->matrix_free.n_boundary_face_batches() / 2);
150
151 // Set up data structures
152 FEFaceIntegrator phi(this->matrix_free, true, mf_dof_index, mf_quad_index);
153 std::array<double, dim * VectorizedArrayType::size()> unrolled_vertices;
154 std::array<int, VectorizedArrayType::size()> node_ids;
155 unsigned int size = 0;
156 // Loop over all boundary faces
157 for(unsigned int face = this->matrix_free.n_inner_face_batches();
158 face < this->matrix_free.n_boundary_face_batches() + this->matrix_free.n_inner_face_batches();
159 ++face)
160 {
161 auto const boundary_id = this->matrix_free.get_boundary_id(face);
162
163 // Only for interface nodes
164 if(boundary_id != this->dealii_boundary_surface_id)
165 continue;
166
167 phi.reinit(face);
168 int const active_faces = this->matrix_free.n_active_entries_per_face_batch(face);
169
170 // Loop over all quadrature points and pass the vertices to preCICE
171 for(unsigned int q = 0; q < phi.n_q_points; ++q)
172 {
173 auto const local_vertex = phi.quadrature_point(q);
174
175 // Transform dealii::Point<Vectorized> into preCICE conform format
176 // We store here also the potential 'dummy'/empty lanes (not only
177 // active_faces), but it allows us to use a static loop as well as a
178 // static array for the indices
179 for(int d = 0; d < dim; ++d)
180 for(unsigned int v = 0; v < VectorizedArrayType::size(); ++v)
181 unrolled_vertices[d + dim * v] = local_vertex[d][v];
182
183#ifdef EXADG_WITH_PRECICE
184 this->precice->setMeshVertices(this->mesh_id,
185 active_faces,
186 unrolled_vertices.data(),
187 node_ids.data());
188#else
189 (void)active_faces;
190#endif
191 coupling_nodes_ids.emplace_back(node_ids);
192 ++size;
193 }
194 }
195
196 // resize the IDs in case the initial guess was too large
197 coupling_nodes_ids.resize(size);
198
199#ifdef EXADG_WITH_PRECICE
200 // Consistency check: the number of IDs we stored is equal or greater than
201 // the IDs preCICE knows
202 Assert(size * VectorizedArrayType::size() >=
203 static_cast<unsigned int>(this->precice->getMeshVertexSize(this->mesh_id)),
204 dealii::ExcInternalError());
205
206 if(this->read_data_map.size() > 0)
207 this->print_info(true, this->precice->getMeshVertexSize(this->mesh_id));
208 if(this->write_data_map.size() > 0)
209 this->print_info(false, this->precice->getMeshVertexSize(this->mesh_id));
210#endif
211}
212
213
214template<int dim, int data_dim, typename VectorizedArrayType>
215void
217 dealii::LinearAlgebra::distributed::Vector<double> const & data_vector,
218 std::string const & data_name)
219{
220 int const write_data_id = this->write_data_map.at(data_name);
221
222 switch(this->write_data_type)
223 {
224 case WriteDataType::values_on_q_points:
225 write_data_factory(data_vector,
226 write_data_id,
227 dealii::EvaluationFlags::values,
228 [](auto & phi, auto q_point) { return phi.get_value(q_point); });
229 break;
230 case WriteDataType::normal_gradients_on_q_points:
231 write_data_factory(data_vector,
232 write_data_id,
233 dealii::EvaluationFlags::gradients,
234 [](auto & phi, auto q_point) {
235 return phi.get_normal_derivative(q_point);
236 });
237 break;
238 default:
239 AssertThrow(false, dealii::ExcNotImplemented());
240 }
241}
242
243
244
245template<int dim, int data_dim, typename VectorizedArrayType>
246void
247QuadCoupling<dim, data_dim, VectorizedArrayType>::write_data_factory(
248 dealii::LinearAlgebra::distributed::Vector<double> const & data_vector,
249 int const write_data_id,
250 dealii::EvaluationFlags::EvaluationFlags const flags,
251 std::function<value_type(FEFaceIntegrator &, unsigned int)> const & get_write_value)
252{
253 Assert(write_data_id != -1, dealii::ExcNotInitialized());
254 Assert(coupling_nodes_ids.size() > 0, dealii::ExcNotInitialized());
255 // Similar as in define_coupling_mesh
256 FEFaceIntegrator phi(this->matrix_free, true, mf_dof_index, mf_quad_index);
257
258 // In order to unroll the vectorization
259 std::array<double, data_dim * VectorizedArrayType::size()> unrolled_local_data;
260 (void)unrolled_local_data;
261
262 auto index = coupling_nodes_ids.begin();
263
264 // Loop over all faces
265 for(unsigned int face = this->matrix_free.n_inner_face_batches();
266 face < this->matrix_free.n_boundary_face_batches() + this->matrix_free.n_inner_face_batches();
267 ++face)
268 {
269 auto const boundary_id = this->matrix_free.get_boundary_id(face);
270
271 // Only for interface nodes
272 if(boundary_id != this->dealii_boundary_surface_id)
273 continue;
274
275 // Read and interpolate
276 phi.reinit(face);
277 phi.read_dof_values_plain(data_vector);
278 phi.evaluate(flags);
279 int const active_faces = this->matrix_free.n_active_entries_per_face_batch(face);
280
281 for(unsigned int q = 0; q < phi.n_q_points; ++q, ++index)
282 {
283 Assert(index != coupling_nodes_ids.end(), dealii::ExcInternalError());
284 auto const local_data = get_write_value(phi, q);
285
286 // Constexpr evaluation required in order to comply with the
287 // compiler here
288 if constexpr(data_dim > 1)
289 {
290 // Transform Tensor<1,dim,VectorizedArrayType> into preCICE
291 // conform format
292 for(int d = 0; d < data_dim; ++d)
293 for(unsigned int v = 0; v < VectorizedArrayType::size(); ++v)
294 unrolled_local_data[d + data_dim * v] = local_data[d][v];
295
296#ifdef EXADG_WITH_PRECICE
297 this->precice->writeBlockVectorData(write_data_id,
298 active_faces,
299 index->data(),
300 unrolled_local_data.data());
301#else
302 (void)active_faces;
303 (void)write_data_id;
304#endif
305 }
306 else
307 {
308#ifdef EXADG_WITH_PRECICE
309 this->precice->writeBlockScalarData(write_data_id,
310 active_faces,
311 index->data(),
312 &local_data[0]);
313#endif
314 }
315 }
316 }
317}
318
319
320
321template<int dim, int data_dim, typename VectorizedArrayType>
322std::string
323QuadCoupling<dim, data_dim, VectorizedArrayType>::get_surface_type() const
324{
325 return "quadrature points using matrix-free quad index " +
326 dealii::Utilities::to_string(mf_quad_index);
327}
328
329} // namespace preCICE
330} // namespace ExaDG
331
332#endif /* EXADG_FLUID_STRUCTURE_INTERACTION_PRECICE_QUAD_COUPLING_H_ */
Definition coupling_base.h:65
std::string const mesh_name
public precice solverinterface
Definition coupling_base.h:151
FaceIntegrator< dim, data_dim, double, VectorizedArrayType > FEFaceIntegrator
Alias for the face integrator.
Definition coupling_base.h:77
dealii::MatrixFree< dim, double, VectorizedArrayType > const & matrix_free
The dealii::MatrixFree object (preCICE can only handle double precision)
Definition coupling_base.h:143
void print_info(bool const reader, unsigned int const local_size) const
Print information of the current setup.
Definition coupling_base.h:255
virtual void define_coupling_mesh() override
define_mesh_vertices Define a vertex coupling mesh for preCICE coupling the classical preCICE way
Definition quad_coupling.h:139
typename CouplingBase< dim, data_dim, VectorizedArrayType >::FEFaceIntegrator FEFaceIntegrator
Alias as defined in the base class.
Definition quad_coupling.h:56
virtual void write_data(dealii::LinearAlgebra::distributed::Vector< double > const &data_vector, std::string const &data_name) override
write_data Evaluates the given
Definition quad_coupling.h:216
Definition driver.cpp:33