39 #include <boost/geometry.hpp>
53 template <
int dim,
int spacedim>
56 , space_dh(space_grid)
57 , embedded_dh(embedded_grid)
58 , embedded_configuration_dh(embedded_grid)
62 , grid_generator(
"/Grid/Ambient")
63 , grid_refinement(
"/Grid/Refinement")
64 , embedded_grid_generator(
"/Grid/Embedded")
65 , embedded_mapping(embedded_configuration_dh,
"/Grid/Embedded/Mapping")
66 , constants(
"/Functions")
67 , embedded_value_function(
"/Functions",
"0",
"Embedded value")
68 , forcing_term(
"/Functions",
"0",
"Forcing term")
69 , exact_solution(
"/Functions",
"0",
"Exact solution")
70 , boundary_conditions(
"/Boundary conditions")
71 , stiffness_inverse_operator(
"/Solver/Stiffness")
72 , stiffness_preconditioner(
"/Solver/Stiffness AMG")
73 , mass_preconditioner(
"/Solver/Mass AMG")
74 , schur_inverse_operator(
"/Solver/Schur")
75 , data_out(
"/Data out/Space",
"output/space")
76 , embedded_data_out(
"/Data out/Embedded",
"output/embedded")
77 , error_table_space(
"/Error table/Space")
78 , error_table_embedded(
"/Error table/Embedded")
104 template <
int dim,
int spacedim>
109 grid_generator.generate(space_grid);
110 embedded_grid_generator.generate(embedded_grid);
113 space_grid, finite_element_degree);
116 embedded_grid, embedded_space_finite_element_degree);
118 const auto embedded_base_fe =
120 embedded_grid, embedded_space_finite_element_degree);
122 embedded_configuration_fe.reset(
125 space_mapping = std::make_unique<MappingFE<spacedim>>(*space_fe);
127 space_grid_tools_cache =
128 std::make_unique<GridTools::Cache<spacedim, spacedim>>(space_grid,
131 embedded_configuration_dh.distribute_dofs(*embedded_configuration_fe);
132 embedded_configuration.reinit(embedded_configuration_dh.n_dofs());
133 embedded_mapping.initialize(embedded_configuration);
135 embedded_grid_tools_cache =
136 std::make_unique<GridTools::Cache<dim, spacedim>>(embedded_grid,
138 adjust_grid_refinements();
143 template <
int dim,
int spacedim>
146 const bool apply_delta_refinement)
154 auto refine_embedded = [&]() {
156 while (done ==
false)
160 space_grid_tools_cache
161 ->get_locally_owned_cell_bounding_boxes_rtree();
164 const auto &embedded_tree =
165 embedded_grid_tools_cache
166 ->get_locally_owned_cell_bounding_boxes_rtree();
171 for (
const auto &[embedded_box, embedded_cell] : embedded_tree)
173 const auto &[p1, p2] = embedded_box.get_boundary_points();
174 const auto diameter = p1.distance(p2);
176 for (
const auto &[space_box, space_cell] :
178 bgi::adaptors::queried(bgi::intersects(embedded_box)))
179 if (space_cell->diameter() <
diameter)
181 embedded_cell->set_refine_flag();
188 embedded_grid.execute_coarsening_and_refinement();
189 embedded_configuration_dh.distribute_dofs(
190 *embedded_configuration_fe);
191 embedded_configuration.reinit(
192 embedded_configuration_dh.n_dofs());
193 embedded_mapping.initialize(embedded_configuration);
194 embedded_grid_tools_cache =
195 std::make_unique<GridTools::Cache<dim, spacedim>>(
196 embedded_grid, embedded_mapping());
205 if (apply_delta_refinement && delta_refinement != 0)
206 for (
unsigned int i = 0; i < delta_refinement; ++i)
209 space_grid_tools_cache
210 ->get_locally_owned_cell_bounding_boxes_rtree();
212 const auto &embedded_tree =
213 embedded_grid_tools_cache
214 ->get_locally_owned_cell_bounding_boxes_rtree();
216 for (
const auto &[embedded_box, embedded_cell] : embedded_tree)
217 for (
const auto &[space_box, space_cell] :
218 tree | bgi::adaptors::queried(bgi::intersects(embedded_box)))
219 space_cell->set_refine_flag();
220 space_grid.execute_coarsening_and_refinement();
227 const double embedded_space_maximal_diameter =
229 const double embedded_space_minimal_diameter =
232 double space_minimal_diameter =
234 double space_maximal_diameter =
237 deallog <<
"Space min/max diameters: " << space_minimal_diameter <<
"/"
238 << space_maximal_diameter << std::endl
239 <<
"Embedded space min/max diameters: "
240 << embedded_space_minimal_diameter <<
"/"
241 << embedded_space_maximal_diameter << std::endl;
246 template <
int dim,
int spacedim>
250 basis_functions.resize(n_basis,
Vector<double>(embedded_dh.n_dofs()));
253 basis_functions[0] = 1.0;
255 for (
unsigned int c = 1; c < n_basis; ++c)
257 unsigned int k = (c + 1) / 2;
260 "sqrt(pi^k*(2*k + 2))*(x^2 + y^2)^(k/2)*cos(k*atan2(y, x))",
261 "k=" + std::to_string(k) +
", pi=" + std::to_string(M_PI));
263 "sqrt(pi^k*(2*k + 2))*(x^2 + y^2)^(k/2)*sin(k*atan2(y, x))",
264 "k=" + std::to_string(k) +
", pi=" + std::to_string(M_PI));
266 if ((c + 1) % 2 == 0)
280 deallog <<
"Basis function " << c
281 <<
" norm: " << basis_functions[c].l2_norm() << std::endl;
286 template <
int dim,
int spacedim>
292 space_dh.distribute_dofs(*space_fe);
295 boundary_conditions.apply_essential_boundary_conditions(*space_mapping,
302 stiffness_sparsity.copy_from(dsp);
303 stiffness_matrix.reinit(stiffness_sparsity);
306 solution.reinit(space_dh.n_dofs());
307 reduced_solution.reinit(space_dh.n_dofs());
308 rhs.reinit(space_dh.n_dofs());
310 deallog <<
"Space dofs: " << space_dh.n_dofs() << std::endl;
312 embedded_dh.distribute_dofs(*embedded_fe);
313 embedded_constraints.clear();
315 embedded_constraints);
316 embedded_constraints.close();
320 embedded_sparsity.copy_from(dsp);
321 embedded_mass_matrix.reinit(embedded_sparsity);
322 embedded_stiffness_matrix.reinit(embedded_sparsity);
325 lambda.reinit(embedded_dh.n_dofs());
326 reduced_lambda.reinit(embedded_dh.n_dofs());
328 embedded_rhs.reinit(embedded_dh.n_dofs());
329 embedded_value.reinit(embedded_dh.n_dofs());
330 reduced_embedded_value.reinit(embedded_dh.n_dofs());
332 small_rhs.reinit(n_basis);
333 small_lambda.reinit(n_basis);
334 small_value.reinit(n_basis);
336 deallog <<
"Embedded dofs: " << embedded_dh.n_dofs() << std::endl;
337 deallog <<
"Reduced dofs: " << n_basis << std::endl;
339 boundary_conditions.apply_natural_boundary_conditions(
340 *space_mapping, space_dh, constraints, stiffness_matrix, rhs);
345 template <
int dim,
int spacedim>
351 embedded_grid, embedded_fe->tensor_degree() + 1);
363 embedded_constraints);
364 coupling_sparsity.copy_from(dsp);
365 coupling_matrix.reinit(coupling_sparsity);
370 template <
int dim,
int spacedim>
375 space_grid, space_fe->tensor_degree() + 1);
377 embedded_grid, embedded_fe->tensor_degree() + 1);
381 MatrixTools::create_laplace_matrix(
395 embedded_mass_matrix,
397 embedded_constraints);
401 tmp.
merge(embedded_constraints);
405 MatrixTools::create_laplace_matrix(
409 embedded_stiffness_matrix,
424 embedded_constraints);
429 embedded_value_function,
436 embedded_value_function,
439 update_basis_functions();
441 template <
int dim,
int spacedim>
453 if (use_direct_solver)
460 stiffness_preconditioner.initialize(stiffness_matrix);
461 A_inv = stiffness_inverse_operator(A, stiffness_preconditioner);
467 mass_preconditioner.initialize(embedded_mass_matrix);
470 auto S = B * A_inv * Bt;
472 switch (schur_preconditioner)
474 case SchurPreconditioner::identity:
476 case SchurPreconditioner::M:
479 case SchurPreconditioner::Minv:
482 case SchurPreconditioner::K:
485 case SchurPreconditioner::Minv_K_Minv:
486 S_prec = Minv * K * Minv;
491 auto S_inv = schur_inverse_operator(S, S_prec);
493 deallog <<
"Solving full order system" << std::endl;
495 lambda = S_inv * (B * A_inv * rhs - embedded_rhs);
496 embedded_constraints.distribute(lambda);
498 solution = A_inv * (rhs - Bt * lambda);
499 constraints.distribute(solution);
503 deallog <<
"Solving Reduced order system" << std::endl;
505 std::vector<std::reference_wrapper<const Vector<double>>> basis(
506 basis_functions.begin(), basis_functions.end());
509 for (
unsigned int i = 0; i < n_basis; ++i)
511 embedded_value = M * basis_functions[i];
512 for (
unsigned int j = 0; j < n_basis; ++j)
513 G(i, j) = basis_functions[j] * embedded_value;
523 auto RS =
C * A_inv * Ct;
525 auto RS_inv = schur_inverse_operator(RS, RS_prec);
526 small_rhs = R * embedded_rhs;
527 Ginv.
vmult(small_value, small_rhs);
528 small_lambda = RS_inv * (
C * A_inv * rhs - small_rhs);
529 reduced_solution = A_inv * (rhs - Ct * small_lambda);
530 constraints.distribute(reduced_solution);
532 reduced_lambda = Rt * small_lambda;
533 embedded_constraints.distribute(reduced_lambda);
535 reduced_embedded_value = Rt * small_value;
536 embedded_constraints.distribute(reduced_embedded_value);
538 deallog <<
"Small lambda: " << small_lambda << std::endl;
539 deallog <<
"Small value: " << small_value << std::endl;
540 deallog <<
"Small rhs: " << small_rhs << std::endl;
546 template <
int dim,
int spacedim>
554 grid_refinement.get_n_refinement_cycles()));
556 data_out.attach_dof_handler(space_dh, suffix);
557 data_out.add_data_vector(solution, component_names);
558 data_out.add_data_vector(reduced_solution, component_names +
"_reduced");
559 data_out.write_data_and_clear(*space_mapping);
561 embedded_data_out.attach_dof_handler(embedded_dh, suffix);
562 embedded_data_out.add_data_vector(
563 lambda,
"lambda", dealii::DataOut<dim, spacedim>::type_dof_data);
564 embedded_data_out.add_data_vector(
565 embedded_value,
"g", dealii::DataOut<dim, spacedim>::type_dof_data);
566 embedded_data_out.add_data_vector(
569 dealii::DataOut<dim, spacedim>::type_dof_data);
570 embedded_data_out.add_data_vector(
571 reduced_embedded_value,
573 dealii::DataOut<dim, spacedim>::type_dof_data);
576 for (
const auto &basis : basis_functions)
578 embedded_data_out.add_data_vector(
580 "phi_" + std::to_string(c++),
581 dealii::DataOut<dim, spacedim>::type_dof_data);
583 embedded_data_out.write_data_and_clear(embedded_mapping);
588 template <
int dim,
int spacedim>
593 generate_grids_and_fes();
594 for (
const auto &cycle : grid_refinement.get_refinement_cycles())
603 error_table_space.error_from_exact(*space_mapping,
610 error_table_space.difference(*space_mapping,
614 error_table_embedded.difference(embedded_mapping(),
620 output_results(cycle);
621 if (cycle < grid_refinement.get_n_refinement_cycles() - 1)
623 grid_refinement.estimate_mark_refine(space_dh,
626 adjust_grid_refinements(
false);
630 error_table_space.output_table(std::cout);
632 error_table_embedded.output_table(std::cout);
void add_line(const size_type line_n)
void merge(const AffineConstraints< other_number > &other_constraints, const MergeConflictBehavior merge_conflict_behavior=no_conflicts_allowed, const bool allow_different_local_lines=false)
void set_inhomogeneity(const size_type constrained_dof_index, const number value)
void vmult(Vector< number2 > &w, const Vector< number2 > &v, const bool adding=false) const
void invert(const FullMatrix< number2 > &M)
void push(const std::string &text)
unsigned int depth_console(const unsigned int n)
void enter_subsection(const std::string &subsection)
void add_parameter(const std::string &entry, ParameterType ¶meter, const std::string &documentation="", ParameterHandler &prm_=prm, const Patterns::PatternBase &pattern=*Patterns::Tools::Convert< ParameterType >::to_pattern())
void initialize(const SparsityPattern &sparsity_pattern)
void update_basis_functions()
void output_results(const unsigned int cycle)
unsigned int coupling_quadrature_order
void generate_grids_and_fes()
unsigned int embedded_space_finite_element_degree
unsigned int finite_element_degree
unsigned int delta_refinement
unsigned int embedded_configuration_finite_element_degree
SchurPreconditioner schur_preconditioner
unsigned int console_level
void adjust_grid_refinements(const bool apply_delta_refinement=true)
#define Assert(cond, exc)
static ::ExceptionBase & ExcInternalError()
LinearOperator< Range, Range, Payload > identity_operator(const std::function< void(Range &, bool)> &reinit_vector)
LinearOperator< Domain, Range, Payload > transpose_operator(const LinearOperator< Range, Domain, Payload > &op)
LinearOperator< Range, Domain, TrilinosWrappers::internal::LinearOperatorImplementation::TrilinosPayload > linear_operator(const TrilinosWrappers::SparseMatrix &operator_exemplar, const Matrix &matrix)
void make_hanging_node_constraints(const DoFHandler< dim, spacedim > &dof_handler, AffineConstraints< number > &constraints)
void make_sparsity_pattern(const DoFHandler< dim, spacedim > &dof_handler, SparsityPatternBase &sparsity_pattern, const AffineConstraints< number > &constraints={}, const bool keep_constrained_dofs=true, const types::subdomain_id subdomain_id=numbers::invalid_subdomain_id)
void create_mass_matrix(const Mapping< dim, spacedim > &mapping, const DoFHandler< dim, spacedim > &dof, const Quadrature< dim > &q, MatrixType &matrix, const Function< spacedim, typename MatrixType::value_type > *const a=nullptr, const AffineConstraints< typename MatrixType::value_type > &constraints=AffineConstraints< typename MatrixType::value_type >())
void create_coupling_sparsity_pattern(const DoFHandler< dim0, spacedim > &space_dh, const DoFHandler< dim1, spacedim > &immersed_dh, const Quadrature< dim1 > &quad, SparsityPatternBase &sparsity, const AffineConstraints< number > &constraints={}, const ComponentMask &space_comps={}, const ComponentMask &immersed_comps={}, const Mapping< dim0, spacedim > &space_mapping=StaticMappingQ1< dim0, spacedim >::mapping, const Mapping< dim1, spacedim > &immersed_mapping=StaticMappingQ1< dim1, spacedim >::mapping, const AffineConstraints< number > &immersed_constraints=AffineConstraints< number >())
void create_coupling_mass_matrix(const DoFHandler< dim0, spacedim > &space_dh, const DoFHandler< dim1, spacedim > &immersed_dh, const Quadrature< dim1 > &quad, Matrix &matrix, const AffineConstraints< typename Matrix::value_type > &constraints=AffineConstraints< typename Matrix::value_type >(), const ComponentMask &space_comps={}, const ComponentMask &immersed_comps={}, const Mapping< dim0, spacedim > &space_mapping=StaticMappingQ1< dim0, spacedim >::mapping, const Mapping< dim1, spacedim > &immersed_mapping=StaticMappingQ1< dim1, spacedim >::mapping, const AffineConstraints< typename Matrix::value_type > &immersed_constraints=AffineConstraints< typename Matrix::value_type >())
SymmetricTensor< 2, dim, Number > C(const Tensor< 2, dim, Number > &F)
std::string int_to_string(const unsigned int value, const unsigned int digits=numbers::invalid_unsigned_int)
unsigned int needed_digits(const unsigned int max_number)
We collect in this namespace all PDEs that are relevant to Fluid Structure Interaction Problems.
LinearOperator< Range, Domain, Payload > projection_operator(const Range &range_exemplar, const std::vector< std::reference_wrapper< const Domain >> &local_basis, const Domain *domain_exemplar=nullptr, const Payload &payload=Payload())
Construct a LinearOperator object that projects a vector onto a basis.