ExaDG
Loading...
Searching...
No Matches
driver_solid.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_SOLID_H_
23#define INCLUDE_EXADG_FLUID_STRUCTURE_INTERACTION_PRECICE_DRIVER_SOLID_H_
24
25// ExaDG
26#include <exadg/fluid_structure_interaction/single_field_solvers/structure.h>
27
28namespace ExaDG
29{
30namespace FSI
31{
32namespace preCICE
33{
34template<int dim, typename Number>
35class DriverSolid : public Driver<dim, Number>
36{
37private:
38 using VectorType = typename dealii::LinearAlgebra::distributed::Vector<Number>;
39
40public:
41 DriverSolid(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 structure = std::make_shared<SolverStructure<dim, Number>>();
48 }
49
50
51 void
52 setup_structure()
53 {
54 dealii::Timer timer_local;
55 timer_local.restart();
56
57 structure->setup(this->application->structure, this->mpi_comm, this->is_test);
58
59 this->timer_tree.insert({"FSI", "Setup", "Structure"}, timer_local.wall_time());
60 }
61
62
63
64 void
65 setup_interface_coupling()
66 {
67 this->precice =
68 std::make_shared<ExaDG::preCICE::Adapter<dim, dim, VectorType>>(this->precice_parameters,
69 this->mpi_comm);
70
71 // structure to fluid
72 {
73 // TODO generalize interface handling for multiple interface IDs
74 this->precice->add_write_surface(
75 *this->application->structure->get_boundary_descriptor()->neumann_cached_bc.begin(),
76 this->precice_parameters.write_mesh_name,
77 {this->precice_parameters.displacement_data_name,
78 this->precice_parameters.velocity_data_name},
79 this->precice_parameters.write_data_type,
80 *structure->pde_operator->get_matrix_free(),
81 structure->pde_operator->get_dof_index(),
82 dealii::numbers::invalid_unsigned_int);
83 }
84
85 // fluid to structure
86 {
87 this->precice->add_read_surface(
88 *structure->pde_operator->get_matrix_free(),
89 structure->pde_operator->get_container_interface_data_neumann(),
90 this->precice_parameters.read_mesh_name,
91 {this->precice_parameters.stress_data_name});
92 }
93
94 // initialize preCICE with initial displacement data
95 VectorType displacement_structure;
96 structure->pde_operator->initialize_dof_vector(displacement_structure);
97 this->precice->initialize_precice(displacement_structure);
98 }
99
100
101
102 void
103 setup() override
104 {
105 dealii::Timer timer;
106 timer.restart();
107
108 this->pcout << std::endl << "Setting up fluid-structure interaction solver:" << std::endl;
109
110 setup_structure();
111
112 setup_interface_coupling();
113
114 this->timer_tree.insert({"FSI", "Setup"}, timer.wall_time());
115 }
116
117
118
119 void
120 solve() const final
121 {
122 bool is_new_time_window = true;
123 // preCICE dictates when the time loop is finished
124 while(this->precice->is_coupling_ongoing())
125 {
126 structure->time_integrator->advance_one_timestep_pre_solve(is_new_time_window);
127
128 this->precice->save_current_state_if_required([&]() {});
129
130 // update stress boundary condition for solid
131 coupling_fluid_to_structure();
132
133 // solve structural problem
134 // store_solution needs to be true for compatibility
135 structure->time_integrator->advance_one_timestep_partitioned_solve(is_new_time_window);
136 // send displacement data to ale
137 coupling_structure_to_ale(structure->time_integrator->get_displacement_np(),
138 structure->time_integrator->get_time_step_size());
139
140 // send velocity boundary condition to fluid
141 coupling_structure_to_fluid(structure->time_integrator->get_velocity_np(),
142 structure->time_integrator->get_time_step_size());
143
144 // TODO: Add synchronization for the time-step size here. For now, we only allow a constant
145 // time-step size
146 dealii::Timer precice_timer;
147 this->precice->advance(structure->time_integrator->get_time_step_size());
148 is_new_time_window = this->precice->is_time_window_complete();
149 this->timer_tree.insert({"FSI", "preCICE"}, precice_timer.wall_time());
150
151 // Needs to be called before the swaps in post_solve
152 this->precice->reload_old_state_if_required([&]() {});
153
154 if(is_new_time_window)
155 structure->time_integrator->advance_one_timestep_post_solve();
156 }
157 }
158
159 void
160 print_performance_results(double const total_time) const override
161 {
162 this->pcout
163 << std::endl
164 << "_________________________________________________________________________________"
165 << std::endl
166 << std::endl;
167
168 this->pcout << "Performance results for fluid-structure interaction solver:" << std::endl;
169
170 this->pcout << std::endl << "Structure:" << std::endl;
171 structure->time_integrator->print_iterations();
172
173 // wall times
174 this->pcout << std::endl << "Wall times:" << std::endl;
175
176 this->timer_tree.insert({"FSI"}, total_time);
177
178 this->timer_tree.insert({"FSI"}, structure->time_integrator->get_timings(), "Structure");
179
180 this->pcout << std::endl << "Timings for level 1:" << std::endl;
181 this->timer_tree.print_level(this->pcout, 1);
182
183 this->pcout << std::endl << "Timings for level 2:" << std::endl;
184 this->timer_tree.print_level(this->pcout, 2);
185
186 // Throughput in DoFs/s per time step per core
187 dealii::types::global_dof_index DoFs = structure->pde_operator->get_number_of_dofs();
188
189 unsigned int const N_mpi_processes = dealii::Utilities::MPI::n_mpi_processes(this->mpi_comm);
190
191 dealii::Utilities::MPI::MinMaxAvg total_time_data =
192 dealii::Utilities::MPI::min_max_avg(total_time, this->mpi_comm);
193 double const total_time_avg = total_time_data.avg;
194
195 unsigned int N_time_steps = structure->time_integrator->get_number_of_time_steps();
196
197 print_throughput_unsteady(this->pcout, DoFs, total_time_avg, N_time_steps, N_mpi_processes);
198
199 // computational costs in CPUh
200 print_costs(this->pcout, total_time_avg, N_mpi_processes);
201
202 this->pcout
203 << "_________________________________________________________________________________"
204 << std::endl
205 << std::endl;
206 }
207
208private:
209 void
210 coupling_structure_to_ale(VectorType const & displacement_structure,
211 double const time_step_size) const
212 {
213 this->precice->write_data(this->precice_parameters.write_mesh_name,
214 this->precice_parameters.displacement_data_name,
215 displacement_structure,
216 time_step_size);
217 }
218
219 void
220 coupling_structure_to_fluid(VectorType const & velocity_structure,
221 double const time_step_size) const
222 {
223 this->precice->write_data(this->precice_parameters.write_mesh_name,
224 this->precice_parameters.velocity_data_name,
225 velocity_structure,
226 time_step_size);
227 }
228
229 void
230 coupling_fluid_to_structure() const
231 {
232 this->precice->read_block_data(this->precice_parameters.read_mesh_name,
233 this->precice_parameters.stress_data_name);
234 }
235
236 // the solver
237 std::shared_ptr<SolverStructure<dim, Number>> structure;
238};
239
240} // namespace preCICE
241} // namespace FSI
242} // namespace ExaDG
243
244
245#endif /* INCLUDE_EXADG_FLUID_STRUCTURE_INTERACTION_PRECICE_DRIVER_H_ */
Definition application_base.h:472
Definition driver_solid.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