ExaDG
Loading...
Searching...
No Matches
precice_adapter.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_PRECICE_ADAPTER_H_
23#define EXADG_FLUID_STRUCTURE_INTERACTION_PRECICE_PRECICE_ADAPTER_H_
24
25// deal.II
26#include <deal.II/base/exceptions.h>
27#include <deal.II/base/mpi.h>
28#include <deal.II/base/utilities.h>
29#include <deal.II/fe/fe.h>
30#include <deal.II/fe/mapping_q_generic.h>
31#include <deal.II/matrix_free/matrix_free.h>
32
33// ExaDG
34#include <exadg/fluid_structure_interaction/precice/dof_coupling.h>
35#include <exadg/fluid_structure_interaction/precice/exadg_coupling.h>
36#include <exadg/fluid_structure_interaction/precice/quad_coupling.h>
37#include <exadg/utilities/tensor_utilities.h>
38
39// preCICE
40#ifdef EXADG_WITH_PRECICE
41# include <precice/SolverInterface.hpp>
42#endif
43
44// C/C++
45#include <ostream>
46
47namespace ExaDG
48{
49namespace preCICE
50{
56template<int dim,
57 int data_dim,
58 typename VectorType,
59 typename VectorizedArrayType = dealii::VectorizedArray<double>>
61{
62public:
63 static unsigned int const rank = n_components_to_rank<data_dim, dim>();
64
65 using value_type = typename CouplingBase<dim, data_dim, VectorizedArrayType>::value_type;
87 template<typename ParameterClass>
88 Adapter(ParameterClass const & parameters, MPI_Comm mpi_comm);
89
90
101 void
102 initialize_precice(VectorType const & dealii_to_precice);
103
104 void
105 add_write_surface(dealii::types::boundary_id const surface_id,
106 std::string const & mesh_name,
107 std::vector<std::string> const & write_data_names,
108 WriteDataType const write_data_type,
109 dealii::MatrixFree<dim, double, VectorizedArrayType> const & data,
110 unsigned int const dof_index,
111 unsigned int const write_quad_index);
112
113
114 void
115 add_read_surface(dealii::MatrixFree<dim, double, VectorizedArrayType> const & data,
116 std::shared_ptr<ContainerInterfaceData<rank, dim, double>> interface_data,
117 std::string const & mesh_name,
118 std::vector<std::string> const & read_data_name);
119
123 void
124 advance(double const computed_timestep_length);
125
138 void
139 save_current_state_if_required(std::function<void()> const & save_state);
140
155 void
156 reload_old_state_if_required(std::function<void()> const & reload_old_state);
157
158
159 void
160 write_data(std::string const & write_mesh_name,
161 std::string const & write_data_name,
162 VectorType const & write_data,
163 double const computed_timestep_length);
164
165 void
166 read_block_data(std::string const & mesh_name, const std::string & data_name) const;
167
173 bool
174 is_coupling_ongoing() const;
175
182 bool
184
185
186private:
187 // public precice solverinterface, needed in order to steer the time loop
188 // inside the solver.
189#ifdef EXADG_WITH_PRECICE
190 std::shared_ptr<precice::SolverInterface> precice;
191#endif
192
194 std::map<std::string, std::shared_ptr<CouplingBase<dim, data_dim, VectorizedArrayType>>> writer;
195
196 // We restrict the reader to be of type ExaDGCoupling for the moment, as all other choices don't
197 // make sense
198 std::map<std::string, std::shared_ptr<ExaDGCoupling<dim, data_dim, VectorizedArrayType>>> reader;
199
200 // Container to store time dependent data in case of an implicit coupling
201 std::vector<VectorType> old_state_data;
202};
203
204
205
206template<int dim, int data_dim, typename VectorType, typename VectorizedArrayType>
207template<typename ParameterClass>
209 MPI_Comm mpi_comm)
210
211{
212#ifdef EXADG_WITH_PRECICE
213 precice =
214 std::make_shared<precice::SolverInterface>(parameters.participant_name,
215 parameters.config_file,
216 dealii::Utilities::MPI::this_mpi_process(mpi_comm),
217 dealii::Utilities::MPI::n_mpi_processes(mpi_comm));
218
219 AssertThrow(dim == precice->getDimensions(), dealii::ExcInternalError());
220#else
221 (void)parameters;
222 (void)mpi_comm;
223 AssertThrow(false,
224 dealii::ExcMessage("EXADG_WITH_PRECICE has to be activated to use this code."));
225#endif
226
227 AssertThrow(dim > 1, dealii::ExcNotImplemented());
228}
229
230
231
232template<int dim, int data_dim, typename VectorType, typename VectorizedArrayType>
233void
234Adapter<dim, data_dim, VectorType, VectorizedArrayType>::add_write_surface(
235 dealii::types::boundary_id const dealii_boundary_surface_id,
236 std::string const & mesh_name,
237 std::vector<std::string> const & write_data_names,
238 WriteDataType const write_data_type,
239 dealii::MatrixFree<dim, double, VectorizedArrayType> const & data,
240 unsigned int const dof_index,
241 unsigned int const quad_index)
242{
243 // Check, if we already have such an interface
244 auto const found_reader = reader.find(mesh_name);
245
246 if(found_reader != reader.end())
247 {
248 // Duplicate the shared pointer
249 writer.insert({mesh_name, found_reader->second});
250 }
251 else if(write_data_type == WriteDataType::values_on_dofs)
252 {
253 writer.insert(
254 {mesh_name,
255 std::make_shared<DoFCoupling<dim, data_dim, VectorizedArrayType>>(data,
256#ifdef EXADG_WITH_PRECICE
257 precice,
258#endif
259 mesh_name,
260 dealii_boundary_surface_id,
261 dof_index)});
262 }
263 else
264 {
265 Assert(write_data_type == WriteDataType::values_on_q_points or
266 write_data_type == WriteDataType::normal_gradients_on_q_points,
267 dealii::ExcNotImplemented());
268 writer.insert({mesh_name,
269 std::make_shared<QuadCoupling<dim, data_dim, VectorizedArrayType>>(
270 data,
271#ifdef EXADG_WITH_PRECICE
272 precice,
273#endif
274 mesh_name,
275 dealii_boundary_surface_id,
276 dof_index,
277 quad_index)});
278 }
279
280 // Register the write data
281 std::vector<dealii::Point<dim>> const points;
282 for(auto const & data_name : write_data_names)
283 writer.at(mesh_name)->add_write_data(data_name);
284
285 writer.at(mesh_name)->set_write_data_type(write_data_type);
286 // Finally initialize the surface
287 writer.at(mesh_name)->define_coupling_mesh();
288}
289
290
291
292template<int dim, int data_dim, typename VectorType, typename VectorizedArrayType>
293void
294Adapter<dim, data_dim, VectorType, VectorizedArrayType>::add_read_surface(
295 dealii::MatrixFree<dim, double, VectorizedArrayType> const & data,
296 std::shared_ptr<ContainerInterfaceData<rank, dim, double>> interface_data,
297 std::string const & mesh_name,
298 std::vector<std::string> const & read_data_names)
299{
300 reader.insert(
301 {mesh_name,
302 std::make_shared<ExaDGCoupling<dim, data_dim, VectorizedArrayType>>(data,
303#ifdef EXADG_WITH_PRECICE
304 precice,
305#endif
306 mesh_name,
307 interface_data)});
308
309 for(auto const & data_name : read_data_names)
310 reader.at(mesh_name)->add_read_data(data_name);
311 reader.at(mesh_name)->define_coupling_mesh();
312}
313
314
315
316template<int dim, int data_dim, typename VectorType, typename VectorizedArrayType>
317void
319 VectorType const & dealii_to_precice)
320{
321#ifdef EXADG_WITH_PRECICE
322 // if(not dealii_to_precice.has_ghost_elements())
323 // dealii_to_precice.update_ghost_values();
324
325 // Initialize preCICE internally
326 precice->initialize();
327
328 // Only the writer needs potentially to process the coupling mesh, if the
329 // mapping is carried out in the solver
330 // writer->process_coupling_mesh();
331
332 // write initial writeData to preCICE if required
333 if(precice->isActionRequired(precice::constants::actionWriteInitialData()))
334 {
335 writer[0]->write_data(dealii_to_precice, "");
336
337 precice->markActionFulfilled(precice::constants::actionWriteInitialData());
338 }
339 precice->initializeData();
340
341 // Maybe, read block-wise and work with an AlignedVector since the read data
342 // (forces) is multiple times required during the Newton iteration
343 // if (shared_memory_parallel and precice->isReadDataAvailable())
344 // precice->readBlockVectorData(read_data_id,
345 // read_nodes_ids.size(),
346 // read_nodes_ids.data(),
347 // read_data.data());
348#else
349 (void)dealii_to_precice;
350#endif
351}
352
353template<int dim, int data_dim, typename VectorType, typename VectorizedArrayType>
354void
355Adapter<dim, data_dim, VectorType, VectorizedArrayType>::write_data(
356 std::string const & write_mesh_name,
357 std::string const & write_data_name,
358 VectorType const & dealii_to_precice,
359 double const computed_timestep_length)
360{
361#ifdef EXADG_WITH_PRECICE
362 if(precice->isWriteDataRequired(computed_timestep_length))
363 writer.at(write_mesh_name)->write_data(dealii_to_precice, write_data_name);
364#else
365 (void)write_mesh_name;
366 (void)write_data_name;
367 (void)dealii_to_precice;
368 (void)computed_timestep_length;
369#endif
370}
371
372template<int dim, int data_dim, typename VectorType, typename VectorizedArrayType>
373void
375 double const computed_timestep_length)
376{
377#ifdef EXADG_WITH_PRECICE
378 // Here, we need to specify the computed time step length and pass it to
379 // preCICE
380 // TODO: The function returns the available time-step size which is required for time-step sync
381 precice->advance(computed_timestep_length);
382#else
383 (void)computed_timestep_length;
384#endif
385}
386
387
388
389template<int dim, int data_dim, typename VectorType, typename VectorizedArrayType>
390void
391Adapter<dim, data_dim, VectorType, VectorizedArrayType>::read_block_data(
392 std::string const & mesh_name,
393 std::string const & data_name) const
394{
395 reader.at(mesh_name)->read_block_data(data_name);
396}
397
398
399
400template<int dim, int data_dim, typename VectorType, typename VectorizedArrayType>
401inline void
403 std::function<void()> const & save_state)
404{
405#ifdef EXADG_WITH_PRECICE
406 // First, we let preCICE check, whether we need to store the variables.
407 // Then, the data is stored in the class
408 if(precice->isActionRequired(precice::constants::actionWriteIterationCheckpoint()))
409 {
410 save_state();
411 precice->markActionFulfilled(precice::constants::actionWriteIterationCheckpoint());
412 }
413#else
414 (void)save_state;
415#endif
416}
417
418
419
420template<int dim, int data_dim, typename VectorType, typename VectorizedArrayType>
421inline void
423 std::function<void()> const & reload_old_state)
424{
425#ifdef EXADG_WITH_PRECICE
426 // In case we need to reload a state, we just take the internally stored
427 // data vectors and write then in to the input data
428 if(precice->isActionRequired(precice::constants::actionReadIterationCheckpoint()))
429 {
430 reload_old_state();
431 precice->markActionFulfilled(precice::constants::actionReadIterationCheckpoint());
432 }
433#else
434 (void)reload_old_state;
435#endif
436}
437
438
439
440template<int dim, int data_dim, typename VectorType, typename VectorizedArrayType>
441inline bool
443{
444#ifdef EXADG_WITH_PRECICE
445 return precice->isCouplingOngoing();
446#else
447 return true;
448#endif
449}
450
451
452
453template<int dim, int data_dim, typename VectorType, typename VectorizedArrayType>
454inline bool
456{
457#ifdef EXADG_WITH_PRECICE
458 return precice->isTimeWindowComplete();
459#else
460 return true;
461#endif
462}
463
464} // namespace preCICE
465} // namespace ExaDG
466
467#endif /* EXADG_FLUID_STRUCTURE_INTERACTION_PRECICE_PRECICE_ADAPTER_H_ */
Definition container_interface_data.h:46
void reload_old_state_if_required(std::function< void()> const &reload_old_state)
Reloads the previously stored variables in case of an implicit coupling. The current implementation s...
Definition precice_adapter.h:422
void initialize_precice(VectorType const &dealii_to_precice)
Initializes preCICE and passes all relevant data to preCICE.
Definition precice_adapter.h:318
Adapter(ParameterClass const &parameters, MPI_Comm mpi_comm)
Constructor, which sets up the precice Solverinterface.
Definition precice_adapter.h:208
void save_current_state_if_required(std::function< void()> const &save_state)
Saves current state of time dependent variables in case of an implicit coupling.
Definition precice_adapter.h:402
bool is_coupling_ongoing() const
is_coupling_ongoing Calls the preCICE API function isCouplingOnGoing
Definition precice_adapter.h:442
void advance(double const computed_timestep_length)
Advances preCICE after every timestep.
Definition precice_adapter.h:374
bool is_time_window_complete() const
is_time_window_complete Calls the preCICE API function isTimeWindowComplete
Definition precice_adapter.h:455
Definition driver.cpp:33