ExaDG
Loading...
Searching...
No Matches
driver_fluid.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 INCLUDE_EXADG_FLUID_STRUCTURE_INTERACTION_PRECICE_DRIVER_FLUID_H_
23#define INCLUDE_EXADG_FLUID_STRUCTURE_INTERACTION_PRECICE_DRIVER_FLUID_H_
24
25// ExaDG
26#include <exadg/fluid_structure_interaction/single_field_solvers/fluid.h>
27
28namespace ExaDG
29{
30namespace FSI
31{
32namespace preCICE
33{
34template<int dim, typename Number>
35class DriverFluid : public Driver<dim, Number>
36{
37private:
38 using VectorType = typename dealii::LinearAlgebra::distributed::Vector<Number>;
39
40public:
41 DriverFluid(std::string const & input_file,
42 MPI_Comm const & comm,
43 std::shared_ptr<ApplicationBase<dim, Number>> app,
44 bool const is_test)
45 : Driver<dim, Number>(input_file, comm, app, is_test)
46 {
47 fluid = std::make_shared<SolverFluid<dim, Number>>();
48 }
49
50
51 void
52 setup_fluid_and_ale()
53 {
54 dealii::Timer timer_local;
55
56 fluid->setup(this->application->fluid, this->mpi_comm, this->is_test);
57
58 this->timer_tree.insert({"FSI", "Setup", "Fluid"}, timer_local.wall_time());
59 }
60
61
62 void
63 setup_interface_coupling()
64 {
65 this->precice =
66 std::make_shared<ExaDG::preCICE::Adapter<dim, dim, VectorType>>(this->precice_parameters,
67 this->mpi_comm);
68
69 // fluid to structure
70 {
71 // TODO generalize interface handling for multiple interface IDs
72 this->precice->add_write_surface(
73 *this->application->fluid->get_boundary_descriptor()->velocity->dirichlet_cached_bc.begin(),
74 this->precice_parameters.write_mesh_name,
75 {this->precice_parameters.stress_data_name},
76 this->precice_parameters.write_data_type,
77 fluid->pde_operator->get_matrix_free(),
78 fluid->pde_operator->get_dof_index_velocity(),
79 fluid->pde_operator->get_quad_index_velocity_linear());
80 }
81
82 // structure to ALE
83 {
84 // Poisson mesh movement
85 if(this->application->fluid->get_parameters().mesh_movement_type ==
86 IncNS::MeshMovementType::Poisson)
87 {
88 std::shared_ptr<Poisson::DeformedMapping<dim, Number>> poisson_ale_mapping =
89 std::dynamic_pointer_cast<Poisson::DeformedMapping<dim, Number>>(fluid->ale_mapping);
90
91 this->precice->add_read_surface(
92 poisson_ale_mapping->get_matrix_free(),
93 poisson_ale_mapping->get_pde_operator()->get_container_interface_data(),
94 this->precice_parameters.ale_mesh_name,
95 {this->precice_parameters.displacement_data_name});
96 }
97 // Elasticity mesh movement
98 else if(this->application->fluid->get_parameters().mesh_movement_type ==
99 IncNS::MeshMovementType::Elasticity)
100 {
101 std::shared_ptr<Structure::DeformedMapping<dim, Number>> structure_ale_mapping =
102 std::dynamic_pointer_cast<Structure::DeformedMapping<dim, Number>>(fluid->ale_mapping);
103
104 this->precice->add_read_surface(
105 structure_ale_mapping->get_matrix_free(),
106 structure_ale_mapping->get_pde_operator()->get_container_interface_data_dirichlet(),
107 this->precice_parameters.ale_mesh_name,
108 {this->precice_parameters.displacement_data_name});
109 }
110 else
111 {
112 AssertThrow(false, dealii::ExcNotImplemented());
113 }
114 }
115
116 // structure to fluid
117 {
118 this->precice->add_read_surface(fluid->pde_operator->get_matrix_free(),
119 fluid->pde_operator->get_container_interface_data(),
120 this->precice_parameters.read_mesh_name,
121 {this->precice_parameters.velocity_data_name});
122 }
123
124 // initialize preCICE with initial stress data
125 VectorType initial_stress;
126 fluid->pde_operator->initialize_vector_velocity(initial_stress);
127 this->precice->initialize_precice(initial_stress);
128 }
129
130
131
132 void
133 setup() override
134 {
135 dealii::Timer timer;
136 timer.restart();
137
138 this->pcout << std::endl << "Setting up fluid-structure interaction solver:" << std::endl;
139
140 setup_fluid_and_ale();
141
142 setup_interface_coupling();
143
144 this->timer_tree.insert({"FSI", "Setup"}, timer.wall_time());
145 }
146
147
148
149 void
150 solve() const final
151 {
152 Assert(this->application->fluid->get_parameters().adaptive_time_stepping == false,
153 dealii::ExcNotImplemented());
154
155 bool is_new_time_window = true;
156 // preCICE dictates when the time loop is finished
157 while(this->precice->is_coupling_ongoing())
158 {
159 // pre-solve
160 fluid->time_integrator->advance_one_timestep_pre_solve(is_new_time_window);
161
162 this->precice->save_current_state_if_required([&]() {});
163
164 {
165 coupling_structure_to_ale();
166
167 // move the fluid mesh and update dependent data structures
168 fluid->solve_ale();
169
170 // update velocity boundary condition for fluid
171 coupling_structure_to_fluid();
172
173 // solve fluid problem
174 fluid->time_integrator->advance_one_timestep_partitioned_solve(is_new_time_window);
175
176 // compute and send stress to solid
177 coupling_fluid_to_structure();
178
179 // TODO: Add synchronization for the time-step size here. For now, we only allow a constant
180 // time-step size
181 dealii::Timer precice_timer;
182 this->precice->advance(fluid->time_integrator->get_time_step_size());
183 is_new_time_window = this->precice->is_time_window_complete();
184 this->timer_tree.insert({"FSI", "preCICE"}, precice_timer.wall_time());
185 }
186
187 // Needs to be called before the swaps in post_solve
188 this->precice->reload_old_state_if_required([&]() {});
189
190 // post-solve
191 if(is_new_time_window)
192 fluid->time_integrator->advance_one_timestep_post_solve();
193 }
194 }
195
196 void
197 print_performance_results(double const total_time) const override
198 {
199 this->pcout
200 << std::endl
201 << "_________________________________________________________________________________"
202 << std::endl
203 << std::endl;
204
205 this->pcout << "Performance results for fluid-structure interaction solver:" << std::endl;
206
207 this->pcout << std::endl << "Fluid:" << std::endl;
208 fluid->time_integrator->print_iterations();
209
210 this->pcout << std::endl << "ALE:" << std::endl;
211 fluid->ale_mapping->print_iterations();
212
213 // wall times
214 this->pcout << std::endl << "Wall times:" << std::endl;
215
216 this->timer_tree.insert({"FSI"}, total_time);
217
218 this->timer_tree.insert({"FSI"}, fluid->time_integrator->get_timings(), "Fluid");
219
220 this->pcout << std::endl << "Timings for level 1:" << std::endl;
221 this->timer_tree.print_level(this->pcout, 1);
222
223 this->pcout << std::endl << "Timings for level 2:" << std::endl;
224 this->timer_tree.print_level(this->pcout, 2);
225
226 // Throughput in DoFs/s per time step per core
227 dealii::types::global_dof_index DoFs = fluid->pde_operator->get_number_of_dofs();
228
229 if(this->application->fluid->get_parameters().mesh_movement_type ==
230 IncNS::MeshMovementType::Poisson)
231 {
232 std::shared_ptr<Poisson::DeformedMapping<dim, Number>> poisson_ale_mapping =
233 std::dynamic_pointer_cast<Poisson::DeformedMapping<dim, Number>>(fluid->ale_mapping);
234
235 DoFs += poisson_ale_mapping->get_pde_operator()->get_number_of_dofs();
236 }
237 else if(this->application->fluid->get_parameters().mesh_movement_type ==
238 IncNS::MeshMovementType::Elasticity)
239 {
240 std::shared_ptr<Structure::DeformedMapping<dim, Number>> elasticity_ale_mapping =
241 std::dynamic_pointer_cast<Structure::DeformedMapping<dim, Number>>(fluid->ale_mapping);
242
243 DoFs += elasticity_ale_mapping->get_pde_operator()->get_number_of_dofs();
244 }
245 else
246 {
247 AssertThrow(false, dealii::ExcMessage("not implemented."));
248 }
249
250 unsigned int const N_mpi_processes = dealii::Utilities::MPI::n_mpi_processes(this->mpi_comm);
251
252 dealii::Utilities::MPI::MinMaxAvg total_time_data =
253 dealii::Utilities::MPI::min_max_avg(total_time, this->mpi_comm);
254 double const total_time_avg = total_time_data.avg;
255
256 unsigned int N_time_steps = fluid->time_integrator->get_number_of_time_steps();
257
258 print_throughput_unsteady(this->pcout, DoFs, total_time_avg, N_time_steps, N_mpi_processes);
259
260 // computational costs in CPUh
261 print_costs(this->pcout, total_time_avg, N_mpi_processes);
262
263 this->pcout
264 << "_________________________________________________________________________________"
265 << std::endl
266 << std::endl;
267 }
268
269private:
270 void
271 coupling_structure_to_ale() const
272 {
273 // TODO: parametrize names
274 this->precice->read_block_data(this->precice_parameters.ale_mesh_name,
275 this->precice_parameters.displacement_data_name);
276 }
277
278 void
279 coupling_structure_to_fluid() const
280 {
281 // TODO: parametrize names
282 this->precice->read_block_data(this->precice_parameters.read_mesh_name,
283 this->precice_parameters.velocity_data_name);
284 }
285
286 void
287 coupling_fluid_to_structure() const
288 {
289 VectorType stress_fluid;
290 fluid->pde_operator->initialize_vector_velocity(stress_fluid);
291 // calculate fluid stress at fluid-structure interface
292 fluid->pde_operator->interpolate_stress_bc(stress_fluid,
293 fluid->time_integrator->get_velocity_np(),
294 fluid->time_integrator->get_pressure_np());
295 stress_fluid *= -1.0;
296 this->precice->write_data(this->precice_parameters.write_mesh_name,
297 this->precice_parameters.stress_data_name,
298 stress_fluid,
299 fluid->time_integrator->get_time_step_size());
300 }
301
302 // solver
303 std::shared_ptr<SolverFluid<dim, Number>> fluid;
304};
305
306} // namespace preCICE
307} // namespace FSI
308} // namespace ExaDG
309
310
311#endif /* INCLUDE_EXADG_FLUID_STRUCTURE_INTERACTION_PRECICE_DRIVER_SOLID_H_ */
Definition application_base.h:472
Definition driver_fluid.h:36
Definition driver.h:42
void insert(std::vector< std::string > const ids, double const wall_time)
Definition timer_tree.cpp:47
void print_level(dealii::ConditionalOStream const &pcout, unsigned int const level) const
Definition timer_tree.cpp:175
Definition driver.cpp:33