Reduced Lagrange Multipliers
 
Loading...
Searching...
No Matches
elasticity.cc
Go to the documentation of this file.
1// ---------------------------------------------------------------------
2//
3// Copyright (C) 2024 by Luca Heltai
4//
5// This file is part of the reduced_lagrange_multipliers application, based on
6// the deal.II library.
7//
8// The reduced_lagrange_multipliers application is free software; you can use
9// it, redistribute it, and/or modify it under the terms of the Apache-2.0
10// License WITH LLVM-exception as published by the Free Software Foundation;
11// either version 3.0 of the License, or (at your option) any later version. The
12// full text of the license can be found in the file LICENSE.md at the top level
13// of the reduced_lagrange_multipliers distribution.
14//
15// ---------------------------------------------------------------------
16
17
18#include "elasticity.h"
19
20#include <boost/algorithm/string.hpp>
21
23
24template <int dim, int spacedim>
27 : par(par)
28 , mpi_communicator(MPI_COMM_WORLD)
29 , pcout(std::cout, (Utilities::MPI::this_mpi_process(mpi_communicator) == 0))
31 pcout,
32 TimerOutput::summary,
33 TimerOutput::wall_times)
35 typename Triangulation<spacedim>::MeshSmoothing(
36 Triangulation<spacedim>::smoothing_on_refinement |
37 Triangulation<spacedim>::smoothing_on_coarsening))
38 , inclusions(spacedim)
39 , dh(tria)
40 , displacement(0)
41{}
42
43
44template <int dim, int spacedim>
45void
46read_grid_and_cad_files(const std::string &grid_file_name,
47 const std::string &ids_and_cad_file_names,
49{
51 grid_in.attach_triangulation(tria);
52 grid_in.read(grid_file_name);
53#ifdef DEAL_II_WITH_OPENCASCADE
54 using map_type = std::map<types::manifold_id, std::string>;
55 using Converter = Patterns::Tools::Convert<map_type>;
56 for (const auto &pair : Converter::to_value(ids_and_cad_file_names))
57 {
58 const auto &manifold_id = pair.first;
59 const auto &cad_file_name = pair.second;
60 const auto extension = boost::to_lower_copy(
61 cad_file_name.substr(cad_file_name.find_last_of('.') + 1));
62 TopoDS_Shape shape;
63 if (extension == "iges" || extension == "igs")
64 shape = OpenCASCADE::read_IGES(cad_file_name);
65 else if (extension == "step" || extension == "stp")
66 shape = OpenCASCADE::read_STEP(cad_file_name);
67 else
68 AssertThrow(false,
69 ExcNotImplemented("We found an extension that we "
70 "do not recognize as a CAD file "
71 "extension. Bailing out."));
72 const auto n_elements = OpenCASCADE::count_elements(shape);
73 if ((std::get<0>(n_elements) == 0))
74 tria.set_manifold(
75 manifold_id,
77 else if (spacedim == 3)
78 {
79 const auto t = reinterpret_cast<Triangulation<dim, 3> *>(&tria);
80 t->set_manifold(manifold_id,
82 shape));
83 }
84 else
85 tria.set_manifold(manifold_id,
87 TopoDS::Face(shape)));
88 }
89#else
90 (void)ids_and_cad_file_names;
91 AssertThrow(false, ExcNotImplemented("Generation of the grid failed."));
92#endif
93}
94
95
96
97template <int dim, int spacedim>
98void
100{
101 if (par.domain_type == "generate")
102 {
103 try
104 {
106 tria, par.name_of_grid, par.arguments_for_grid);
107 }
108 catch (...)
109 {
110 pcout << "Generating from name and argument failed." << std::endl
111 << "Trying to read from file name." << std::endl;
112 read_grid_and_cad_files(par.name_of_grid,
113 par.arguments_for_grid,
114 tria);
115 }
116 }
117 else if (par.domain_type == "cylinder")
118 {
119 Assert(spacedim == 2, ExcInternalError());
121 std::cout << " ATTENTION: GRID: cirle of radius 1." << std::endl;
122 }
123 else if (par.domain_type == "cheese")
124 {
125 Assert(spacedim == 2, ExcInternalError());
126 GridGenerator::cheese(tria, std::vector<unsigned int>(2, 2));
127 }
128 else if (par.domain_type == "file")
129 {
132#ifdef DEAL_II_WITH_GMSH_API
133 std::string infile(par.name_of_grid);
134#else
135 std::ifstream infile(par.name_of_grid);
136 Assert(infile.good(), ExcIO());
137#endif
138 try
139 {
140 gi.read_msh(infile);
141 // gi.read_vtk(infile);
142 }
143 catch (...)
144 {
145 Assert(false, ExcInternalError());
146 }
147 }
148
149 tria.refine_global(par.initial_refinement);
150}
151
152
153
154template <int dim, int spacedim>
155void
157{
158 TimerOutput::Scope t(computing_timer, "Initial setup");
159 fe = std::make_unique<FESystem<spacedim>>(FE_Q<spacedim>(par.fe_degree),
160 spacedim);
161 quadrature = std::make_unique<QGauss<spacedim>>(par.fe_degree + 1);
163 std::make_unique<QGauss<spacedim - 1>>(par.fe_degree + 1);
164}
165
166
167template <int dim, int spacedim>
168void
170{
171 TimerOutput::Scope t(computing_timer, "Setup dofs");
172 dh.distribute_dofs(*fe);
173
174 owned_dofs.resize(2);
175 owned_dofs[0] = dh.locally_owned_dofs();
176 relevant_dofs.resize(2);
178
179 FEFaceValues<spacedim> fe_face_values(*fe,
184
185 {
186 constraints.reinit(relevant_dofs[0]);
188 for (const auto id : par.dirichlet_ids)
189 {
191 }
192 std::map<types::boundary_id, const Function<spacedim, double> *>
193 function_map;
194 for (const auto id : par.normal_flux_ids)
195 {
196 function_map.insert(
198 id, &par.Neumann_bc));
199 }
201 dh, 0, par.normal_flux_ids, function_map, constraints);
202 constraints.close();
203
204 /*{
205 mean_value_constraints.clear();
206 mean_value_constraints.reinit(relevant_dofs[0]);
207
208 for (const auto id : par.normal_flux_ids)
209 {
210 const std::set<types::boundary_id > &boundary_ids={id};
211 const ComponentMask &component_mask=ComponentMask();
212 const IndexSet boundary_dofs = DoFTools::extract_boundary_dofs(dh,
213 component_mask, boundary_ids);
214
215 const types::global_dof_index first_boundary_dof =
216 boundary_dofs.nth_index_in_set(0);
217
218 mean_value_constraints.add_line(first_boundary_dof);
219 for (types::global_dof_index i : boundary_dofs)
220 if (i != first_boundary_dof)
221 mean_value_constraints.add_entry(first_boundary_dof, i, -1);
222 }
223 mean_value_constraints.close();
224
225 constraints.merge(mean_value_constraints);
226 }*/
227 }
228 {
232 owned_dofs[0],
234 relevant_dofs[0]);
235 stiffness_matrix.clear();
237 owned_dofs[0],
238 dsp,
240 }
241 inclusion_constraints.close();
242
243 if (inclusions.n_dofs() > 0)
244 {
245 auto inclusions_set =
247 mpi_communicator, inclusions.n_inclusions());
248
249 owned_dofs[1] = inclusions_set.tensor_product(
250 complete_index_set(inclusions.n_dofs_per_inclusion()));
251
252 DynamicSparsityPattern dsp(dh.n_dofs(),
253 inclusions.n_dofs(),
254 relevant_dofs[0]);
255
257 relevant_dofs[1].add_indices(owned_dofs[1]);
259 owned_dofs[0],
261 relevant_dofs[0]);
262 coupling_matrix.clear();
263 coupling_matrix.reinit(owned_dofs[0],
264 owned_dofs[1],
265 dsp,
267
269 for (const auto i : relevant_dofs[1])
270 idsp.add(i, i);
271
273 owned_dofs[1],
275 relevant_dofs[1]);
276 inclusion_matrix.clear();
278 owned_dofs[1],
279 idsp,
281 }
282
286
288 {
289 pcout << " Number of degrees of freedom: " << owned_dofs[0].size()
290 << " + " << owned_dofs[1].size()
291 << " (locally owned: " << owned_dofs[0].n_elements() << " + "
292 << owned_dofs[1].n_elements() << ")" << std::endl;
293 }
294}
295
296template <int dim, int spacedim>
297void
299{
301 coupling_matrix = 0;
302 system_rhs = 0;
303 TimerOutput::Scope t(computing_timer, "Assemble Stiffness and rhs");
304 FEValues<spacedim> fe_values(*fe,
305 *quadrature,
308 FEFaceValues<spacedim> fe_face_values(*fe,
313
314 const unsigned int dofs_per_cell = fe->n_dofs_per_cell();
315 const unsigned int n_q_points = quadrature->size();
316 FullMatrix<double> cell_matrix(dofs_per_cell, dofs_per_cell);
317 Vector<double> cell_rhs(dofs_per_cell);
318 std::vector<Vector<double>> rhs_values(n_q_points, Vector<double>(spacedim));
319 std::vector<Tensor<2, spacedim>> grad_phi_u(dofs_per_cell);
320 std::vector<double> div_phi_u(dofs_per_cell);
321 std::vector<types::global_dof_index> local_dof_indices(dofs_per_cell);
322
323 for (const auto &cell : dh.active_cell_iterators())
324 if (cell->is_locally_owned())
325 {
326 cell_matrix = 0;
327 cell_rhs = 0;
328 fe_values.reinit(cell);
329 par.rhs.vector_value_list(fe_values.get_quadrature_points(),
330 rhs_values);
331 for (unsigned int q = 0; q < n_q_points; ++q)
332 {
333 for (unsigned int k = 0; k < dofs_per_cell; ++k)
334 {
335 grad_phi_u[k] =
336 fe_values[displacement].symmetric_gradient(k, q);
337 div_phi_u[k] = fe_values[displacement].divergence(k, q);
338 }
339 for (unsigned int i = 0; i < dofs_per_cell; ++i)
340 {
341 for (unsigned int j = 0; j < dofs_per_cell; ++j)
342 {
343 cell_matrix(i, j) +=
344 (2 * par.Lame_mu *
345 scalar_product(grad_phi_u[i], grad_phi_u[j]) +
346 par.Lame_lambda * div_phi_u[i] * div_phi_u[j]) *
347 fe_values.JxW(q);
348 }
349 const auto comp_i = fe->system_to_component_index(i).first;
350 cell_rhs(i) += fe_values.shape_value(i, q) *
351 rhs_values[q][comp_i] * fe_values.JxW(q);
352 }
353 }
354
355
356 // Neumann boundary conditions
357 // for (const auto &f : cell->face_iterators()) ////
358 for (unsigned int f = 0; f < GeometryInfo<spacedim>::faces_per_cell;
359 ++f)
360 if (cell->face(f)->at_boundary())
361 {
362 // auto it = par.neumann_ids.find(cell->face(f)->boundary_id());
363 // if (it != par.neumann_ids.end())
364 if (std::find(par.neumann_ids.begin(),
365 par.neumann_ids.end(),
366 cell->face(f)->boundary_id()) !=
367 par.neumann_ids.end())
368 {
369 fe_face_values.reinit(cell, f);
370 for (unsigned int q = 0;
371 q < fe_face_values.n_quadrature_points;
372 ++q)
373 {
374 double neumann_value = 0;
375 for (int d = 0; d < spacedim; ++d)
376 neumann_value +=
377 par.Neumann_bc.value(
378 fe_face_values.quadrature_point(q), d) *
379 fe_face_values.normal_vector(q)[d];
380 neumann_value /= spacedim;
381 for (unsigned int i = 0; i < dofs_per_cell; ++i)
382 {
383 cell_rhs(i) += -neumann_value *
384 fe_face_values.shape_value(i, q) *
385 fe_face_values.JxW(q);
386 }
387 }
388 }
389 }
390 cell->get_dof_indices(local_dof_indices);
391 constraints.distribute_local_to_global(cell_matrix,
392 cell_rhs,
393 local_dof_indices,
395 system_rhs.block(0));
396 }
399}
400
401
402
403template <int dim, int spacedim>
407{
409 "Setup dofs: Assemble Coupling sparsity");
410
411 IndexSet relevant(inclusions.n_dofs());
412
413 std::vector<types::global_dof_index> dof_indices(fe->n_dofs_per_cell());
414 std::vector<types::global_dof_index> inclusion_dof_indices;
415
416 auto particle = inclusions.inclusions_as_particles.begin();
417 while (particle != inclusions.inclusions_as_particles.end())
418 {
419 const auto &cell = particle->get_surrounding_cell();
420 const auto dh_cell =
421 typename DoFHandler<spacedim>::cell_iterator(*cell, &dh);
422 dh_cell->get_dof_indices(dof_indices);
423 const auto pic =
424 inclusions.inclusions_as_particles.particles_in_cell(cell);
425 Assert(pic.begin() == particle, ExcInternalError());
426 std::set<types::global_dof_index> inclusion_dof_indices_set;
427 for (const auto &p : pic)
428 {
429 const auto ids = inclusions.get_dof_indices(p.get_id());
430 inclusion_dof_indices_set.insert(ids.begin(), ids.end());
431 }
432 inclusion_dof_indices.resize(0);
433 inclusion_dof_indices.insert(inclusion_dof_indices.begin(),
434 inclusion_dof_indices_set.begin(),
435 inclusion_dof_indices_set.end());
436 constraints.add_entries_local_to_global(dof_indices,
438 inclusion_dof_indices,
439 dsp);
440 relevant.add_indices(inclusion_dof_indices.begin(),
441 inclusion_dof_indices.end());
442 particle = pic.end();
443 }
444 return relevant;
445}
446
447
448
449template <int dim, int spacedim>
450void
452{
453 TimerOutput::Scope t(computing_timer, "Assemble Coupling matrix");
454
455 // const FEValuesExtractors::Scalar scalar(0);
456 std::vector<types::global_dof_index> fe_dof_indices(fe->n_dofs_per_cell());
457 std::vector<types::global_dof_index> inclusion_dof_indices(
458 inclusions.n_dofs_per_inclusion());
459
460 FullMatrix<double> local_coupling_matrix(fe->n_dofs_per_cell(),
461 inclusions.n_dofs_per_inclusion());
462
463 FullMatrix<double> local_inclusion_matrix(inclusions.n_dofs_per_inclusion(),
464 inclusions.n_dofs_per_inclusion());
465
466 Vector<double> local_rhs(inclusions.n_dofs_per_inclusion());
467
468 auto particle = inclusions.inclusions_as_particles.begin();
469 while (particle != inclusions.inclusions_as_particles.end())
470 {
471 const auto &cell = particle->get_surrounding_cell();
472 const auto dh_cell =
473 typename DoFHandler<spacedim>::cell_iterator(*cell, &dh);
474 dh_cell->get_dof_indices(fe_dof_indices);
475 const auto pic =
476 inclusions.inclusions_as_particles.particles_in_cell(cell);
477 Assert(pic.begin() == particle, ExcInternalError());
478
479 auto p = pic.begin();
480 auto next_p = pic.begin();
481 while (p != pic.end())
482 {
483 const auto inclusion_id = inclusions.get_inclusion_id(p->get_id());
484 inclusion_dof_indices = inclusions.get_dof_indices(p->get_id());
485 local_coupling_matrix = 0;
486 local_inclusion_matrix = 0;
487 local_rhs = 0;
488 // Extract all points that refer to the same inclusion
489 std::vector<Point<spacedim>> ref_q_points;
490 for (; next_p != pic.end() &&
491 inclusions.get_inclusion_id(next_p->get_id()) == inclusion_id;
492 ++next_p)
493 ref_q_points.push_back(next_p->get_reference_location());
495 ref_q_points,
497 fev.reinit(dh_cell);
498 // double temp = 0;
499 for (unsigned int q = 0; q < ref_q_points.size(); ++q)
500 {
501 const auto id = p->get_id();
502 const auto &inclusion_fe_values = inclusions.get_fe_values(id);
503 const auto &real_q = p->get_location();
504 const auto ds = inclusions.get_JxW(id);
505
506
507 // Coupling and inclusions matrix
508 for (unsigned int j = 0; j < inclusions.n_dofs_per_inclusion();
509 ++j)
510 {
511 for (unsigned int i = 0; i < fe->n_dofs_per_cell(); ++i)
512 {
513 const auto comp_i =
514 fe->system_to_component_index(i).first;
515 if (comp_i == inclusions.get_component(j))
516 {
517 local_coupling_matrix(i, j) +=
518 (fev.shape_value(i, q)) * inclusion_fe_values[j] /
519 inclusions.get_section_measure(inclusion_id) * ds;
520 }
521 }
522 if (inclusions.inclusions_data[inclusion_id].size() > 0)
523 {
524 if (inclusions.inclusions_data[inclusion_id].size() + 1 >
525 inclusions.get_fourier_component(j))
526 {
527 auto temp =
528 inclusion_fe_values[j] * ds /
529 inclusions.get_section_measure(inclusion_id) *
530 // phi_i ds
531 // now we need to build g from the data.
532 // this is sum E^i g_i where g_i are coefficients of
533 // the modes, but only the j one survives
534 inclusion_fe_values[j] *
535 inclusions.get_inclusion_data(inclusion_id, j);
536
537 if (par.initial_time != par.final_time)
538 temp *= inclusions.inclusions_rhs.value(
539 real_q, inclusions.get_component(j));
540 local_rhs(j) += temp;
541 }
542 }
543 else
544 {
545 local_rhs(j) +=
546 inclusion_fe_values[j] /
547 inclusions.get_section_measure(inclusion_id) *
548 inclusions.inclusions_rhs.value(
549 real_q, inclusions.get_component(j)) // /
550 // inclusions.get_radius(inclusion_id)
551 * ds;
552 }
553 local_inclusion_matrix(j, j) +=
554 (inclusion_fe_values[j] * inclusion_fe_values[j] * ds);
555 }
556 ++p;
557 }
558 // I expect p and next_p to be the same now.
559 Assert(p == next_p, ExcInternalError());
560 // Add local matrices to global ones
561 constraints.distribute_local_to_global(local_coupling_matrix,
562 fe_dof_indices,
564 inclusion_dof_indices,
566 inclusion_constraints.distribute_local_to_global(
567 local_rhs, inclusion_dof_indices, system_rhs.block(1));
568
569 inclusion_constraints.distribute_local_to_global(
570 local_inclusion_matrix, inclusion_dof_indices, inclusion_matrix);
571 }
572 particle = pic.end();
573 }
577}
578
579
580
581template <int dim, int spacedim>
582void
584{
586 LA::MPI::PreconditionAMG prec_A;
587 {
588 // LA::MPI::PreconditionAMG::AdditionalData data;
590#ifdef USE_PETSC_LA
591 data.symmetric_operator = true;
592#endif
593
594
595 Teuchos::ParameterList parameter_list;
596 std::unique_ptr<Epetra_MultiVector> ptr_operator_modes;
597 parameter_list.set("smoother: type", "Chebyshev");
598 parameter_list.set("smoother: sweeps", 2);
599 parameter_list.set("smoother: pre or post", "both");
600 parameter_list.set("coarse: type", "Amesos-KLU");
601 parameter_list.set("coarse: max size", 2000);
602 parameter_list.set("aggregation: threshold", 0.02);
603
604#if DEAL_II_VERSION_GTE(9, 7, 0)
605 using VectorType = std::vector<double>;
606 MappingQ1<spacedim> mapping;
607 std::vector<std::vector<double>> rigid_body_modes =
609#else
610 // Ad-hoc null space for elasticity
612 std::vector<LinearAlgebra::distributed::Vector<double>> rigid_body_modes(
613 spacedim == 3 ? 6 : 3);
614 for (unsigned int i = 0; i < rigid_body_modes.size(); ++i)
615 {
616 rigid_body_modes[i].reinit(dh.locally_owned_dofs(), mpi_communicator);
618 VectorTools::interpolate(dh, rbm, rigid_body_modes[i]);
619 }
620#endif
621
623 parameter_list,
624 ptr_operator_modes,
625 stiffness_matrix.trilinos_matrix(),
626 rigid_body_modes);
627 prec_A.initialize(stiffness_matrix, parameter_list);
628 }
629
631 auto invA = A;
632
633 const auto amgA = linear_operator(A, prec_A);
634
635 // for small radius you might need SolverFGMRES<LA::MPI::Vector>
636 SolverCG<LA::MPI::Vector> cg_stiffness(par.inner_control);
637 // SolverFGMRES<LA::MPI::Vector> cg_stiffness(par.inner_control);
638 invA = inverse_operator(A, cg_stiffness, amgA);
639
640 // Some aliases
641 auto &u = solution.block(0);
642 auto &lambda = solution.block(1);
643
644 const auto &f = system_rhs.block(0);
645 auto &g = system_rhs.block(1);
646
647 if (inclusions.n_dofs() == 0)
648 {
649 u = invA * f;
650 }
651 else
652 {
654 const auto B = transpose_operator(Bt);
656
657 // auto interp_g = g;
658 // interp_g = 0.1;
659 // g = C * interp_g;
660
661 // Schur complement
662 const auto S = B * invA * Bt;
663
664 // Schur complement preconditioner
665 // VERSION 1
666 // auto invS = S;
667 // SolverFGMRES<LA::MPI::Vector> cg_schur(par.outer_control);
668 SolverMinRes<LA::MPI::Vector> cg_schur(par.outer_control);
669 // invS = inverse_operator(S, cg_schur);
670 // VERSION2
671 auto invS = S;
672 auto S_inv_prec = B * invA * Bt + M;
673 // auto S_inv_prec = B * invA * Bt;
674 // SolverCG<Vector<double>> cg_schur(par.outer_control);
675 // PrimitiveVectorMemory<Vector<double>> mem;
676 // SolverGMRES<Vector<double>> solver_gmres(
677 // par.outer_control, mem,
678 // SolverGMRES<Vector<double>>::AdditionalData(20));
679 invS = inverse_operator(S, cg_schur, S_inv_prec);
680
681 pcout << " f norm: " << f.l2_norm() << ", g norm: " << g.l2_norm()
682 << std::endl;
683
684 // Compute Lambda first
685 lambda = invS * (B * invA * f - g);
686 pcout << " Solved for lambda in " << par.outer_control.last_step()
687 << " iterations." << std::endl;
688
689 // Then compute u
690 u = invA * (f - Bt * lambda);
691 pcout << " u norm: " << u.l2_norm()
692 << ", lambda norm: " << lambda.l2_norm() << std::endl;
693 }
694
695 pcout << " Solved for u in " << par.inner_control.last_step()
696 << " iterations." << std::endl;
697 constraints.distribute(u);
698 inclusion_constraints.distribute(lambda);
700}
701
702
703
704template <int dim, int spacedim>
705void
707{
709 Vector<float> error_per_cell(tria.n_active_cells());
711 QGauss<spacedim - 1>(par.fe_degree +
712 1),
713 {},
715 error_per_cell);
716 if (par.refinement_strategy == "fixed_fraction")
717 {
719 tria, error_per_cell, par.refinement_fraction, par.coarsening_fraction);
720 }
721 else if (par.refinement_strategy == "fixed_number")
722 {
724 tria,
725 error_per_cell,
726 par.refinement_fraction,
727 par.coarsening_fraction,
728 par.max_cells);
729 }
730 else if (par.refinement_strategy == "global")
731 for (const auto &cell : tria.active_cell_iterators())
732 cell->set_refine_flag();
733
735 dh);
736 tria.prepare_coarsening_and_refinement();
737 inclusions.inclusions_as_particles.prepare_for_coarsening_and_refinement();
740 // transfer.prepare_for_coarsening_and_refinement(
741 // locally_relevant_solution.block(1));
742 tria.execute_coarsening_and_refinement();
743 inclusions.inclusions_as_particles.unpack_after_coarsening_and_refinement();
744 setup_dofs();
745 transfer.interpolate(solution.block(0));
746 constraints.distribute(solution.block(0));
747 locally_relevant_solution.block(0) = solution.block(0);
748 locally_relevant_solution.block(1) = solution.block(1);
749}
750
751
752
753template <int dim, int spacedim>
754std::string
756{
757 std::vector<std::string> solution_names(spacedim, "displacement");
758 std::vector<std::string> exact_solution_names(spacedim, "exact_displacement");
759
760
761 auto exact_vec(solution.block(0));
762 // VectorTools::interpolate(dh, par.bc, exact_vec);
763 VectorTools::interpolate(dh, par.exact_solution, exact_vec);
764 auto exact_vec_locally_relevant(locally_relevant_solution.block(0));
765 exact_vec_locally_relevant = exact_vec;
766
767 std::vector<DataComponentInterpretation::DataComponentInterpretation>
768 data_component_interpretation(
770
771 DataOut<spacedim> data_out;
772 data_out.attach_dof_handler(dh);
774 solution_names,
776 data_component_interpretation);
777
778 data_out.add_data_vector(exact_vec_locally_relevant,
779 exact_solution_names,
781 data_component_interpretation);
782
783 Vector<float> subdomain(tria.n_active_cells());
784 for (unsigned int i = 0; i < subdomain.size(); ++i)
785 subdomain(i) = tria.locally_owned_subdomain();
786 data_out.add_data_vector(subdomain, "subdomain");
787 data_out.build_patches();
788 const std::string filename =
789 par.output_name + "_" + std::to_string(cycle) + ".vtu";
790 data_out.write_vtu_in_parallel(par.output_directory + "/" + filename,
792 return filename;
793}
794
795// template <int dim, int spacedim>
796// std::string
797// ElasticityProblem<dim, spacedim>::output_stresses() const
798// {
799// std::vector<std::string> solution_names(spacedim*spacedim, "face_stress");
800
801// std::vector<DataComponentInterpretation::DataComponentInterpretation>
802// face_component_type(
803// spacedim, DataComponentInterpretation::component_is_part_of_vector);
804
805// DataOutFaces<spacedim> data_out_faces(true);
806// data_out_faces.add_data_vector(dh,
807// sigma_n,
808// solution_names,
809// face_component_type);
810
811// data_out_faces.build_patches(fe->degree);
812// const std::string filename =
813// par.output_name + "_stress_" + std::to_string(cycle) + ".vtu";
814// data_out_faces.write_vtu_in_parallel(par.output_directory + "/" + filename,
815// mpi_communicator);
816// return filename;
817// }
818
819
820
821// template <int dim, int spacedim>
822// std::string
823// ElasticityProblem<dim, spacedim>::output_particles() const
824// {
825// Particles::DataOut<spacedim> particles_out;
826// particles_out.build_patches(inclusions.inclusions_as_particles);
827// const std::string filename =
828// par.output_name + "_particles_" + std::to_string(cycle) + ".vtu";
829// particles_out.write_vtu_in_parallel(par.output_directory + "/" +
830// filename,
831// mpi_communicator);
832// return filename;
833// }
834
835
836template <int dim, int spacedim>
837void
839{
840 TimerOutput::Scope t(computing_timer, "Postprocessing: Output results");
841 static std::vector<std::pair<double, std::string>> cycles_and_solutions;
842 static std::vector<std::pair<double, std::string>> cycles_and_particles;
843 // static std::vector<std::pair<double, std::string>> cycles_and_stresses;
844
845 if (cycles_and_solutions.size() == cycle)
846 {
847 cycles_and_solutions.push_back({(double)cycle, output_solution()});
848 std::ofstream pvd_solutions(par.output_directory + "/" + par.output_name +
849 ".pvd");
850 DataOutBase::write_pvd_record(pvd_solutions, cycles_and_solutions);
851
852 if (cycle == 0)
853 {
854 const std::string particles_filename =
855 par.output_name + "_particles.vtu";
856
857 inclusions.output_particles(par.output_directory + "/" +
858 particles_filename);
859 cycles_and_particles.push_back({(double)cycle, particles_filename});
860
861 std::ofstream pvd_particles(par.output_directory + "/" +
862 par.output_name + "_particles.pvd");
863 DataOutBase::write_pvd_record(pvd_particles, cycles_and_particles);
864 }
865 }
866}
867
868template <int dim, int spacedim>
869void
871{
872#ifdef USE_PETSC_LA
873 pcout << "Running ElasticityProblem<" << Utilities::dim_string(dim, spacedim)
874 << "> using PETSc." << std::endl;
875#else
876 pcout << "Running ElasticityProblem<" << Utilities::dim_string(dim, spacedim)
877 << "> using Trilinos." << std::endl;
878#endif
879 par.prm.print_parameters(par.output_directory + "/" + "used_parameters_" +
880 std::to_string(dim) + std::to_string(spacedim) +
881 ".prm",
883}
884
888template <int dim, int spacedim>
889void
891{
892 for (const auto id : par.dirichlet_ids)
893 {
894 for (const auto Nid : par.neumann_ids)
895 if (id == Nid)
896 AssertThrow(false,
897 ExcNotImplemented("incoherent boundary conditions."));
898 for (const auto noid : par.normal_flux_ids)
899 if (id == noid)
900 AssertThrow(false,
901 ExcNotImplemented("incoherent boundary conditions."));
902 }
903}
904
905
913template <int dim, int spacedim>
914void
916 bool openfilefirsttime) const
917{
920 "Postprocessing: Computing internal and boundary stresses");
921
922 std::map<types::boundary_id, Tensor<1, spacedim>> boundary_stress;
923 std::map<types::boundary_id, double> u_dot_n;
924 Tensor<2, spacedim> internal_stress;
925 Tensor<1, spacedim> average_displacement;
926
927 auto all_ids = tria.get_boundary_ids();
928 std::map<types::boundary_id, double> perimeter;
929 for (auto id : all_ids)
930 // for (const auto id : par.dirichlet_ids)
931 {
932 boundary_stress[id] = 0.0;
933 perimeter[id] = 0.0;
934 u_dot_n[id] = 0.0;
935 }
936 double internal_area = 0.;
937 // // FEValues<spacedim> fe_values(*fe,
938 // // *quadrature,
939 // // update_values | update_gradients |
940 // // update_quadrature_points | update_JxW_values);
941 FEFaceValues<spacedim> fe_face_values(*fe,
948
949 // // const unsigned int dofs_per_cell =
950 // fe->n_dofs_per_cell();
951 // // const unsigned int n_q_points =
952 // quadrature->size();
953 // // std::vector<types::global_dof_index> local_dof_indices(dofs_per_cell);
954 // // Tensor<2, spacedim> grad_phi_u;
955 // // double div_phi_u;
957 for (unsigned int ix = 0; ix < spacedim; ++ix)
958 identity[ix][ix] = 1;
959
960 // // std::vector<std::vector<Tensor<1,spacedim>>>
961 // // solution_gradient(face_quadrature_formula->size(),
962 // // std::vector<Tensor<1,spacedim> >(spacedim+1));
963 std::vector<Tensor<2, spacedim>> displacement_gradient(
965 std::vector<double> displacement_divergence(face_quadrature_formula->size());
966 std::vector<Tensor<1, spacedim>> displacement_values(
968
969 for (const auto &cell : dh.active_cell_iterators())
970 {
971 if (cell->is_locally_owned())
972 {
973 // // if constexpr (spacedim == 2)
974 // // {
975 // // cell->get_dof_indices(local_dof_indices);
976 // // fe_values.reinit(cell);
977 // // for (unsigned int q = 0; q < n_q_points; ++q)
978 // // {
979 // // internal_area += fe_values.JxW(q);
980 // // for (unsigned int k = 0; k < dofs_per_cell;
981 // ++k)
982 // // {
983 // // grad_phi_u =
984 // // fe_values[displacement].symmetric_gradient(k, q);
985 // // div_phi_u =
986 // fe_values[displacement].divergence(k, q);
987 // // internal_stress +=
988 // // (2 * par.Lame_mu * grad_phi_u +
989 // // par.Lame_lambda * div_phi_u * identity)
990 // *
991 // // locally_relevant_solution.block(
992 // // 0)[local_dof_indices[k]] *
993 // // fe_values.JxW(q);
994 // // average_displacement +=
995 // // fe_values[displacement].value(k, q) *
996 // // locally_relevant_solution.block(
997 // // 0)[local_dof_indices[k]] *
998 // // fe_values.JxW(q);
999 // // }
1000 // // }
1001 // // }
1002
1003 for (unsigned int f = 0; f < GeometryInfo<spacedim>::faces_per_cell;
1004 ++f)
1005 // for (const auto &f : cell->face_iterators())
1006 // for (const auto f : GeometryInfo<spacedim>::face_indices())
1007 if (cell->face(f)->at_boundary())
1008 {
1009 auto boundary_index = cell->face(f)->boundary_id();
1010 fe_face_values.reinit(cell, f);
1011
1012 fe_face_values[displacement].get_function_gradients(
1013 locally_relevant_solution.block(0), displacement_gradient);
1014 fe_face_values[displacement].get_function_values(
1015 locally_relevant_solution.block(0), displacement_values);
1016 fe_face_values[displacement].get_function_divergences(
1017 locally_relevant_solution.block(0), displacement_divergence);
1018
1019 for (unsigned int q = 0; q < fe_face_values.n_quadrature_points;
1020 ++q)
1021 {
1022 perimeter[boundary_index] += fe_face_values.JxW(q);
1023
1024 boundary_stress[boundary_index] +=
1025 (2 * par.Lame_mu * displacement_gradient[q] +
1026 par.Lame_lambda * displacement_divergence[q] *
1027 identity) *
1028 fe_face_values.JxW(q) * fe_face_values.normal_vector(q);
1029 u_dot_n[boundary_index] +=
1030 (displacement_values[q] *
1031 fe_face_values.normal_vector(q)) *
1032 fe_face_values.JxW(q);
1033 }
1034 }
1035 }
1036 }
1037
1038 // if constexpr (spacedim == 2)
1039 // {
1040 // internal_stress = Utilities::MPI::sum(internal_stress,
1041 // mpi_communicator); average_displacement =
1042 // Utilities::MPI::sum(average_displacement, mpi_communicator);
1043 // internal_area = Utilities::MPI::sum(internal_area, mpi_communicator);
1044
1045 // internal_stress /= internal_area;
1046 // average_displacement /= internal_area;
1047 // }
1048 for (auto id : all_ids) // par.dirichlet_ids) // all_ids)
1049 {
1050 boundary_stress[id] =
1051 Utilities::MPI::sum(boundary_stress[id], mpi_communicator);
1052 perimeter[id] = Utilities::MPI::sum(perimeter[id], mpi_communicator);
1053 Assert(perimeter[id] > 0, ExcInternalError());
1054 boundary_stress[id] /= perimeter[id];
1055 }
1056
1058 {
1059 const std::string filename(par.output_directory + "/forces.txt");
1060 std::ofstream forces_file;
1061 if (openfilefirsttime)
1062 {
1063 forces_file.open(filename);
1064 if constexpr (spacedim == 2)
1065 {
1066 forces_file << "cycle area";
1067 for (auto id : all_ids) // par.dirichlet_ids) // all_ids)
1068 forces_file << " perimeter" << id;
1069 forces_file
1070 << " meanInternalStressxx meanInternalStressxy meanInternalStressyx meanInternalStressyy avg_u_x avg_u_y";
1071 for (auto id : all_ids) // par.dirichlet_ids) // all_ids)
1072 forces_file << " boundaryStressX_" << id << " boundaryStressY_"
1073 << id << " uDotN_" << id;
1074 forces_file << std::endl;
1075 }
1076 else
1077 {
1078 forces_file << "cycle";
1079 for (auto id : all_ids)
1080 forces_file << "perimeter" << id << " sigmanX_" << id
1081 << " sigmanY_" << id << " sigmanZ_" << id
1082 << " uDotN_" << id;
1083 forces_file << std::endl;
1084 }
1085 }
1086 else
1087 forces_file.open(filename, std::ios_base::app);
1088
1089 if constexpr (spacedim == 2)
1090 {
1091 forces_file << cycle << " " << internal_area << " ";
1092 for (auto id : all_ids)
1093 forces_file << perimeter[id] << " ";
1094 forces_file << internal_stress << " " << average_displacement << " ";
1095 for (auto id : all_ids)
1096 forces_file << boundary_stress[id] << " " << u_dot_n[id] << " ";
1097 forces_file << std::endl;
1098 }
1099 else // spacedim = 3
1100 {
1101 forces_file << cycle << " ";
1102 for (auto id : all_ids)
1103 forces_file << perimeter[id] << " ";
1104 for (auto id : all_ids)
1105 forces_file << boundary_stress[id] << " " << u_dot_n[id] << " ";
1106 forces_file << std::endl;
1107 }
1108 forces_file.close();
1109 }
1110
1111 return;
1112}
1113
1119
1120template <int dim, int spacedim>
1121void
1123{
1124 if (par.output_pressure == false)
1125 return;
1126 TimerOutput::Scope t(computing_timer, "Postprocessing: Output Pressure");
1127
1128 if (inclusions.n_inclusions() > 0
1129 // &&
1130 // inclusions.get_offset_coefficients() == 1 &&
1131 // inclusions.n_coefficients >= 2
1132 )
1133 {
1134 const auto locally_owned_vessels =
1136 mpi_communicator, inclusions.get_n_vessels());
1137 const auto locally_owned_inclusions =
1139 mpi_communicator, inclusions.n_inclusions());
1140
1141 TrilinosWrappers::MPI::Vector pressure(locally_owned_vessels,
1143 pressure = 0;
1144 TrilinosWrappers::MPI::Vector pressure_at_inc(locally_owned_inclusions,
1146 pressure_at_inc = 0;
1147
1148 auto &lambda_to_pressure = locally_relevant_solution.block(1);
1149
1150 const auto used_number_modes = inclusions.get_n_coefficients();
1151
1152 const auto local_lambda = lambda_to_pressure.locally_owned_elements();
1153
1154 if constexpr (spacedim == 3)
1155 {
1156 for (const auto &element_of_local_lambda : local_lambda)
1157 {
1158 const unsigned inclusion_number = (unsigned int)floor(
1159 element_of_local_lambda / (used_number_modes));
1160
1161 AssertIndexRange(inclusion_number, inclusions.n_inclusions());
1162 pressure[inclusions.get_vesselID(inclusion_number)] +=
1163 lambda_to_pressure[element_of_local_lambda];
1164
1165 pressure_at_inc[inclusion_number] +=
1166 lambda_to_pressure[element_of_local_lambda];
1167 }
1169 pressure_at_inc.compress(VectorOperation::add);
1170 }
1171 else // spacedim = 2
1172 {
1173 for (auto element_of_local_lambda : local_lambda)
1174 {
1175 const unsigned inclusion_number = (unsigned int)floor(
1176 element_of_local_lambda / (used_number_modes));
1177
1178 AssertIndexRange(inclusion_number, inclusions.n_inclusions());
1179 pressure_at_inc[inclusion_number] +=
1180 lambda_to_pressure[element_of_local_lambda];
1181 }
1182 pressure = pressure_at_inc;
1183 // pressure.compress(VectorOperation::add);
1184 // pressure_at_inc.compress(VectorOperation::add);
1185 }
1186
1187 // print .txt only sequential
1189 {
1190 const std::string filename(par.output_directory +
1191 "/externalPressure.txt");
1192 std::ofstream pressure_file;
1193 if (openfilefirsttime)
1194 {
1195 pressure_file.open(filename);
1196 pressure_file << "cycle ";
1197 for (unsigned int num = 0; num < pressure.size(); ++num)
1198 pressure_file << "vessel" << num << " ";
1199 pressure_file << std::endl;
1200 }
1201 else
1202 pressure_file.open(filename, std::ios_base::app);
1203
1204 pressure_file << cycle << " ";
1205 pressure.print(pressure_file);
1206 pressure_file.close();
1207 }
1208 else
1209 // print .h5
1210 if (par.initial_time == par.final_time)
1211 {
1212#ifdef DEAL_II_WITH_HDF5
1213 const std::string FILE_NAME(par.output_directory +
1214 "/externalPressure.h5");
1215
1216 auto accessMode = HDF5::File::FileAccessMode::create;
1217 if (!openfilefirsttime)
1218 accessMode = HDF5::File::FileAccessMode::open;
1219
1220 HDF5::File file_h5(FILE_NAME, accessMode, mpi_communicator);
1221 const std::string DATASET_NAME("externalPressure_" +
1222 std::to_string(cycle));
1223
1224 HDF5::DataSet dataset =
1225 file_h5.create_dataset<double>(DATASET_NAME,
1226 {inclusions.get_n_vessels()});
1227
1228 std::vector<double> data_to_write;
1229 // std::vector<hsize_t> coordinates;
1230 data_to_write.reserve(pressure.locally_owned_size());
1231 // coordinates.reserve(pressure.locally_owned_size());
1232 for (const auto &el : locally_owned_vessels)
1233 {
1234 // coordinates.emplace_back(el);
1235 data_to_write.emplace_back(pressure[el]);
1236 }
1237 if (pressure.locally_owned_size() > 0)
1238 {
1239 hsize_t prefix = 0;
1240 hsize_t los = pressure.locally_owned_size();
1241 int ierr = MPI_Exscan(&los,
1242 &prefix,
1243 1,
1244 MPI_UNSIGNED_LONG_LONG,
1245 MPI_SUM,
1247 AssertThrowMPI(ierr);
1248
1249 std::vector<hsize_t> offset = {prefix, 1};
1250 std::vector<hsize_t> count = {pressure.locally_owned_size(), 1};
1251 // data.write_selection(data_to_write, coordinates);
1252 dataset.write_hyperslab(data_to_write, offset, count);
1253 }
1254 else
1255 dataset.write_none<int>();
1256#else
1257 AssertThrow(false, ExcNeedsHDF5());
1258#endif
1259 }
1260 else
1261 {
1262 pcout
1263 << "output_pressure file for time dependent simulation not implemented"
1264 << std::endl;
1265 }
1266 }
1267 else
1268 {
1269 pcout << "Inclusions number = 0, pressure file not created" << std::endl;
1270 }
1271}
1272
1273template <int dim, int spacedim>
1274void
1276{
1277 auto &lambda = locally_relevant_solution.block(1);
1278 const auto used_number_modes = inclusions.get_n_coefficients();
1279
1280 if (lambda.size() > 0)
1281 {
1282 const std::string filename(par.output_directory + "/lambda.txt");
1283 std::ofstream file;
1284 file.open(filename);
1285
1286 unsigned int tot = inclusions.reference_inclusion_data.size() - 4;
1287 Assert(tot > 0, ExcNotImplemented());
1288
1289 for (unsigned int i = 0; i < inclusions.n_inclusions(); ++i)
1290 {
1291 for (unsigned int j = 0; j < tot; ++j)
1292 file << "lambda" << (i * tot + j) << " ";
1293 file << "lambda" << i << "norm ";
1294 }
1295 file << std::endl;
1296
1297 for (unsigned int i = 0; i < inclusions.n_inclusions(); ++i)
1298 {
1299 unsigned int mode_of_inclusion = 0;
1300 double lambda_norm = 0;
1301 for (mode_of_inclusion = 0; mode_of_inclusion < used_number_modes;
1302 mode_of_inclusion++)
1303 {
1304 auto elem_of_lambda = i * used_number_modes + mode_of_inclusion;
1305 file << lambda[elem_of_lambda] << " ";
1306 lambda_norm += lambda[elem_of_lambda] * lambda[elem_of_lambda];
1307 }
1308 while (mode_of_inclusion < tot)
1309 {
1310 file << "0 ";
1311 mode_of_inclusion++;
1312 }
1313 file << lambda_norm << " ";
1314 }
1315 file << std::endl;
1316 file.close();
1317 }
1318}
1319
1323template <int dim, int spacedim>
1324void
1326{
1327 if (par.initial_time == par.final_time) // time stationary
1328 {
1330 make_grid();
1331 setup_fe();
1333 {
1334 TimerOutput::Scope t(computing_timer, "Setup inclusion");
1335 inclusions.setup_inclusions_particles(tria);
1336 }
1337 // setup_dofs(); // called inside refine_and_transfer
1338 for (cycle = 0; cycle < par.n_refinement_cycles; ++cycle)
1339 {
1340 setup_dofs();
1341 if (par.output_results_before_solving)
1344
1346 solve();
1348 output_pressure(cycle == 0 ? true : false);
1349 if (spacedim == 2)
1350 {
1351 FunctionParser<spacedim> weight(par.weight_expression);
1352 par.convergence_table.error_from_exact(
1353 dh,
1355 par.exact_solution,
1356 &weight);
1357 }
1358 else
1359 par.convergence_table.error_from_exact(
1360 dh, locally_relevant_solution.block(0), par.bc);
1361 if (cycle != par.n_refinement_cycles - 1)
1363 }
1364
1365 // if (par.domain_type == "generate")
1366 {
1368 }
1369 if (pcout.is_active())
1370 {
1371 par.convergence_table.output_table(pcout.get_stream());
1372 }
1373 if (false)
1374 output_lambda();
1375 }
1376 else // Time dependent simulation
1377 {
1378 // TODO: add refinement as the first cycle,
1379 pcout << "time dependent simulation, refinement not implemented"
1380 << std::endl;
1382 make_grid();
1383 setup_fe();
1385 cycle = 0;
1386 {
1387 TimerOutput::Scope t(computing_timer, "Setup inclusion");
1388 inclusions.setup_inclusions_particles(tria);
1389 }
1390 setup_dofs();
1392 for (current_time = par.initial_time; current_time < par.final_time;
1393 current_time += par.dt, ++cycle)
1394 {
1395 pcout << "Time: " << current_time << std::endl;
1396 // assemble_elasticity_system();
1397 inclusions.inclusions_rhs.set_time(current_time);
1398 par.Neumann_bc.set_time(current_time);
1400 solve();
1402 output_pressure(cycle == 0 ? true : false);
1403
1404 if (par.domain_type == "generate")
1405 compute_internal_and_boundary_stress(cycle == 0 ? true : false);
1406 }
1407 }
1408}
1409
1410
1411
1412// Template instantiations
1413template class ElasticityProblem<2>;
1414template class ElasticityProblem<2, 3>; // dim != spacedim
1415template class ElasticityProblem<3>;
void write_vtu_in_parallel(const std::string &filename, const MPI_Comm comm) const
void attach_dof_handler(const DoFHandler< dim, spacedim > &)
void add_data_vector(const VectorType &data, const std::vector< std::string > &names, const DataVectorType type=type_automatic, const std::vector< DataComponentInterpretation::DataComponentInterpretation > &data_component_interpretation={})
virtual void build_patches(const unsigned int n_subdivisions=0)
void add(const size_type i, const size_type j)
void reinit(const TriaIterator< DoFCellAccessor< dim, spacedim, level_dof_access > > &cell, const unsigned int face_no)
void get_function_values(const ReadVector< Number > &fe_function, std::vector< Number > &values) const
const std::vector< Point< spacedim > > & get_quadrature_points() const
const Tensor< 1, spacedim > & normal_vector(const unsigned int q_point) const
const Point< spacedim > & quadrature_point(const unsigned int q_point) const
const unsigned int n_quadrature_points
void get_function_gradients(const ReadVector< Number > &fe_function, std::vector< Tensor< 1, spacedim, Number > > &gradients) const
double JxW(const unsigned int q_point) const
const double & shape_value(const unsigned int i, const unsigned int q_point) const
void reinit(const TriaIterator< DoFCellAccessor< dim, spacedim, level_dof_access > > &cell)
void attach_triangulation(Triangulation< dim, spacedim > &tria)
void read_msh(std::istream &in)
void read(std::istream &in, Format format=Default)
void write_hyperslab(const Container &data, const std::vector< hsize_t > &offset, const std::vector< hsize_t > &count)
void write_none()
DataSet create_dataset(const std::string &name, const std::vector< hsize_t > &dimensions) const
void add_indices(const ForwardIterator &begin, const ForwardIterator &end)
static void estimate(const Mapping< dim, spacedim > &mapping, const DoFHandler< dim, spacedim > &dof, const Quadrature< dim - 1 > &quadrature, const std::map< types::boundary_id, const Function< spacedim, Number > * > &neumann_bc, const ReadVector< Number > &solution, Vector< float > &error, const ComponentMask &component_mask={}, const Function< spacedim > *coefficients=nullptr, const unsigned int n_threads=numbers::invalid_unsigned_int, const types::subdomain_id subdomain_id=numbers::invalid_subdomain_id, const types::material_id material_id=numbers::invalid_material_id, const Strategy strategy=cell_diameter_over_24)
void prepare_for_coarsening_and_refinement(const std::vector< const VectorType * > &all_in)
void interpolate(std::vector< VectorType * > &all_out)
void compress(VectorOperation::values operation)
size_type size() const override
void print(std::ostream &out, const unsigned int precision=3, const bool scientific=true, const bool across=true) const
size_type locally_owned_size() const
virtual size_type size() const override
void output_pressure(bool openfilefirsttime) const
compute tissue pressure ($\Lambda$) over the vessels and output to a .txt file (sequential) or ....
ElasticityProblem(const ElasticityProblemParameters< dim, spacedim > &par)
Definition elasticity.cc:25
void compute_internal_and_boundary_stress(bool openfilefirsttime) const
compute stresses on boundaries (2D and 3D) and internal (2D) this function makes use of boundary id,...
std::vector< IndexSet > relevant_dofs
Definition elasticity.h:382
void output_lambda() const
TimerOutput computing_timer
Definition elasticity.h:374
LA::MPI::SparseMatrix coupling_matrix
Definition elasticity.h:389
void check_boundary_ids()
check on the boundary id that no boundary conditions are in disagreement
AffineConstraints< double > constraints
Definition elasticity.h:384
void refine_and_transfer()
LA::MPI::BlockVector solution
Definition elasticity.h:391
void print_parameters() const
unsigned int cycle
Definition elasticity.h:395
std::unique_ptr< Quadrature< spacedim - 1 > > face_quadrature_formula
Definition elasticity.h:379
ConditionalOStream pcout
Definition elasticity.h:373
std::unique_ptr< FiniteElement< spacedim > > fe
Definition elasticity.h:376
const ElasticityProblemParameters< dim, spacedim > & par
Definition elasticity.h:371
std::string output_solution() const
LA::MPI::BlockVector locally_relevant_solution
Definition elasticity.h:392
std::unique_ptr< Quadrature< spacedim > > quadrature
Definition elasticity.h:378
parallel::distributed::Triangulation< spacedim > tria
Definition elasticity.h:375
MPI_Comm mpi_communicator
Definition elasticity.h:372
std::vector< IndexSet > owned_dofs
Definition elasticity.h:381
Inclusions< spacedim > inclusions
Definition elasticity.h:377
void assemble_elasticity_system()
LA::MPI::SparseMatrix inclusion_matrix
Definition elasticity.h:390
AffineConstraints< double > inclusion_constraints
Definition elasticity.h:385
FEValuesExtractors::Vector displacement
Definition elasticity.h:397
DoFHandler< spacedim > dh
Definition elasticity.h:380
IndexSet assemble_coupling_sparsity(DynamicSparsityPattern &dsp)
LA::MPI::SparseMatrix stiffness_matrix
Definition elasticity.h:388
LA::MPI::BlockVector system_rhs
Definition elasticity.h:393
void output_results() const
void run()
set up, assemble and run the problem
void read_grid_and_cad_files(const std::string &grid_file_name, const std::string &ids_and_cad_file_names, Triangulation< dim, spacedim > &tria)
Definition elasticity.cc:46
#define Assert(cond, exc)
#define AssertThrowMPI(error_code)
#define AssertIndexRange(index, range)
#define AssertThrow(cond, exc)
LinearOperator< Range, Domain, Payload > linear_operator(const OperatorExemplar &, const Matrix &)
LinearOperator< Domain, Range, Payload > transpose_operator(const LinearOperator< Range, Domain, Payload > &op)
LinearOperator< Domain, Range, Payload > inverse_operator(const LinearOperator< Range, Domain, Payload > &op, Solver &solver, const Preconditioner &preconditioner)
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 compute_nonzero_normal_flux_constraints(const DoFHandler< dim, spacedim > &dof_handler, const unsigned int first_vector_component, const std::set< types::boundary_id > &boundary_ids, const std::map< types::boundary_id, const Function< spacedim, double > * > &function_map, AffineConstraints< double > &constraints, const Mapping< dim, spacedim > &mapping=(ReferenceCells::get_hypercube< dim >() .template get_default_linear_mapping< dim, spacedim >()), const bool use_manifold_for_normal=true)
update_values
update_normal_vectors
update_JxW_values
update_gradients
update_quadrature_points
void set_manifold(const types::manifold_id number, const Manifold< dim, spacedim > &manifold_object)
IndexSet complete_index_set(const IndexSet::size_type N)
std::vector< index_type > data
void write_pvd_record(std::ostream &out, const std::vector< std::pair< double, std::string > > &times_and_names)
Expression floor(const Expression &x)
IndexSet extract_locally_relevant_dofs(const DoFHandler< dim, spacedim > &dof_handler)
std::vector< std::vector< double > > extract_rigid_body_modes(const Mapping< dim, spacedim > &mapping, const DoFHandler< dim, spacedim > &dof_handler, const ComponentMask &component_mask={})
void generate_from_name_and_arguments(Triangulation< dim, spacedim > &tria, const std::string &grid_generator_function_name, const std::string &grid_generator_function_arguments)
void cheese(Triangulation< dim, spacedim > &tria, const std::vector< unsigned int > &holes)
void hyper_ball(Triangulation< dim, spacedim > &tria, const Point< spacedim > &center={}, const double radius=1., const bool attach_spherical_manifold_on_boundary_cells=false)
std::tuple< unsigned int, unsigned int, unsigned int > count_elements(const TopoDS_Shape &shape)
TopoDS_Shape read_STEP(const std::string &filename, const double scale_factor=1e-3)
TopoDS_Shape read_IGES(const std::string &filename, const double scale_factor=1e-3)
SymmetricTensor< 2, dim, Number > d(const Tensor< 2, dim, Number > &F, const Tensor< 2, dim, Number > &dF_dt)
void distribute_sparsity_pattern(DynamicSparsityPattern &dsp, const IndexSet &locally_owned_rows, const MPI_Comm mpi_comm, const IndexSet &locally_relevant_rows)
T sum(const T &t, const MPI_Comm mpi_communicator)
unsigned int n_mpi_processes(const MPI_Comm mpi_communicator)
unsigned int this_mpi_process(const MPI_Comm mpi_communicator)
IndexSet create_evenly_distributed_partitioning(const MPI_Comm comm, const types::global_dof_index total_size)
std::string dim_string(const int dim, const int spacedim)
void interpolate(const Mapping< dim, spacedim > &mapping, const DoFHandler< dim, spacedim > &dof, const Function< spacedim, typename VectorType::value_type > &function, VectorType &vec, const ComponentMask &component_mask={}, const unsigned int level=numbers::invalid_unsigned_int)
void interpolate_boundary_values(const Mapping< dim, spacedim > &mapping, const DoFHandler< dim, spacedim > &dof, const std::map< types::boundary_id, const Function< spacedim, number > * > &function_map, std::map< types::global_dof_index, number > &boundary_values, const ComponentMask &component_mask={})
void set_null_space(Teuchos::ParameterList &parameter_list, std::unique_ptr< Epetra_MultiVector > &ptr_distributed_modes, const Epetra_RowMatrix &matrix, const std::vector< VectorType > &modes)
Set the null space of the matrix using a pre-computed set of vectors. Needed for the AMG precondition...
void refine_and_coarsen_fixed_fraction(::Triangulation< dim, spacedim > &tria, const ::Vector< Number > &criteria, const double top_fraction_of_error, const double bottom_fraction_of_error, const VectorTools::NormType norm_type=VectorTools::L1_norm)
void refine_and_coarsen_fixed_number(::Triangulation< dim, spacedim > &tria, const ::Vector< Number > &criteria, const double top_fraction_of_cells, const double bottom_fraction_of_cells, const types::global_cell_index max_n_cells=std::numeric_limits< types::global_cell_index >::max())
::SolutionTransfer< dim, VectorType, spacedim > SolutionTransfer
unsigned int boundary_id
std_cxx20::type_identity< T > identity