1 #include <deal.II/lac/constrained_linear_operator.h> 3 #include <deal.II/dofs/dof_tools.h> 6 #include <deal.II/lac/solver_gmres.h> 7 #include <deal.II/lac/solver_bicgstab.h> 11 #include <deal.II/lac/dynamic_sparsity_pattern.h> 12 #include <deal.II/lac/sparsity_tools.h> 13 #include <deal.II/lac/affine_constraints.h> 14 #include <deal.II/lac/trilinos_precondition.h> 15 #include <deal.II/lac/trilinos_solver.h> 17 #include <deal.II/lac/trilinos_sparse_matrix.h> 19 #include "meshmover_linear_elasticity.hpp" 42 template <
int dim,
typename real>
45 const dealii::LinearAlgebra::distributed::Vector<double> &boundary_displacements_vector)
47 *(high_order_grid.triangulation),
48 high_order_grid.mapping_fe_field,
49 high_order_grid.dof_handler_grid,
50 high_order_grid.surface_to_volume_indices,
51 boundary_displacements_vector)
54 template <
int dim,
typename real>
57 const std::shared_ptr<dealii::MappingFEField<dim,dim,VectorType,DoFHandlerType>>
mapping_fe_field,
59 const dealii::LinearAlgebra::distributed::Vector<int> &_boundary_ids_vector,
60 const dealii::LinearAlgebra::distributed::Vector<double> &_boundary_displacements_vector)
85 template <
int dim,
typename real>
87 tensor_to_vector(
const std::vector<dealii::Tensor<1,dim,real>> &boundary_displacements_tensors)
const 89 (void) boundary_displacements_tensors;
97 template <
int dim,
typename real>
98 dealii::LinearAlgebra::distributed::Vector<real>
101 pcout <<
"Solving linear elasticity problem for volume displacements..." << std::endl;
108 template <
int dim,
typename real>
142 const bool is_accessible = partitionner->in_local_range(isurf) || partitionner->is_ghost_entry(isurf);
146 Assert(
all_constraints.can_store_line(iglobal_row), dealii::ExcInternalError());
152 dealii::IndexSet temp_locally_active_dofs;
153 dealii::DoFTools::extract_locally_active_dofs(
dof_handler, temp_locally_active_dofs);
155 AssertThrow(
all_constraints.is_consistent_in_parallel(local_dofs_per_process,
156 temp_locally_active_dofs,
159 dealii::ExcInternalError());
163 dealii::DoFTools::make_sparsity_pattern(
dof_handler,
168 dealii::SparsityTools::distribute_sparsity_pattern(sparsity_pattern,
184 template <
int dim,
typename real>
187 pcout <<
" Assembling MeshMover::LinearElasticity system..." << std::endl;
195 const dealii::FESystem<dim> &fe_system =
dof_handler.get_fe(0);
196 dealii::FEValues<dim> fe_values(
200 dealii::update_values | dealii::update_gradients |
201 dealii::update_quadrature_points | dealii::update_JxW_values);
202 const unsigned int dofs_per_cell = fe_system.dofs_per_cell;
204 std::vector<dealii::types::global_dof_index> local_dof_indices(dofs_per_cell);
205 dealii::FullMatrix<double> cell_matrix(dofs_per_cell, dofs_per_cell);
206 dealii::Vector<double> cell_rhs(dofs_per_cell);
211 std::vector<double> youngs_modulus(n_q_points, 1.0);
212 std::vector<double> poissons_ratio(n_q_points, 0.1);
214 std::vector<double> lame_lambda_values(n_q_points);
215 std::vector<double> lame_mu_values(n_q_points);
216 for (
unsigned int iquad = 0; iquad < n_q_points; ++iquad) {
217 const double E = youngs_modulus[iquad];
218 const double nu = poissons_ratio[iquad];
219 lame_lambda_values[iquad] = E*nu/((1.0+nu)*(1-2.0*nu));
220 lame_mu_values[iquad] = 0.5*E/(1.0+nu);
223 dealii::Functions::ZeroFunction<dim> body_force(dim);
224 std::vector<dealii::Vector<double>> body_force_values(n_q_points,dealii::Vector<double>(dim));
226 for (
const auto &cell :
dof_handler.active_cell_iterators()) {
227 if (!cell->is_locally_owned())
continue;
231 fe_values.reinit(cell);
234 for (
unsigned int q_point = 0; q_point < n_q_points; ++q_point) {
235 volume += fe_values.JxW(q_point);
241 for (
unsigned int itest = 0; itest < dofs_per_cell; ++itest) {
243 const unsigned int component_test = fe_system.system_to_component_index(itest).first;
245 for (
unsigned int itrial = 0; itrial < dofs_per_cell; ++itrial) {
247 const unsigned int component_trial = fe_system.system_to_component_index(itrial).first;
249 for (
unsigned int q_point = 0; q_point < n_q_points; ++q_point) {
251 const double E = youngs_modulus[q_point] / volume;
252 const double nu = poissons_ratio[q_point];
253 lame_lambda_values[q_point] = E*nu/((1.0+nu)*(1-2.0*nu));
254 lame_mu_values[q_point] = 0.5*E/(1.0+nu);
257 double value = lame_lambda_values[q_point]
258 * fe_values.shape_grad_component(itest, q_point, component_test)
259 * fe_values.shape_grad_component(itrial, q_point, component_trial);
260 value += lame_mu_values[q_point]
261 * fe_values.shape_grad_component(itest, q_point, component_trial)
262 * fe_values.shape_grad_component(itrial, q_point, component_test);
263 if (component_test == component_trial) {
264 value += lame_mu_values[q_point]
265 * fe_values.shape_grad_component(itest, q_point, component_test)
266 * fe_values.shape_grad_component(itrial, q_point, component_trial);
268 value *= fe_values.JxW(q_point);
270 cell_matrix(itest, itrial) += value;
274 body_force.vector_value_list(fe_values.get_quadrature_points(), body_force_values);
275 for (
unsigned int itest = 0; itest < dofs_per_cell; ++itest) {
276 const unsigned int component_test = fe_system.system_to_component_index(itest).first;
277 for (
unsigned int q_point = 0; q_point < n_q_points; ++q_point) {
278 cell_rhs(itest) += body_force_values[q_point][component_test] * fe_values.shape_value(itest, q_point);
279 cell_rhs(itest) *= fe_values.JxW(q_point);
282 cell->get_dof_indices(local_dof_indices);
284 const bool use_inhomogeneities_for_rhs =
false;
311 for (
unsigned int itest = 0; itest < dofs_per_cell; ++itest) {
312 for (
unsigned int itrial = 0; itrial < dofs_per_cell; ++itrial) {
320 system_rhs.compress(dealii::VectorOperation::add);
324 MPI_Barrier(MPI_COMM_WORLD);
326 const bool is_accessible = partitionner->in_local_range(isurf) || partitionner->is_ghost_entry(isurf);
338 const bool is_accessible = partitionner->in_local_range(isurf) || partitionner->is_ghost_entry(isurf);
345 system_rhs.compress(dealii::VectorOperation::insert);
349 template <
int dim,
typename real>
358 template <
int dim,
typename real>
362 const dealii::LinearAlgebra::distributed::Vector<double> &input_vector,
363 dealii::LinearAlgebra::distributed::Vector<double> &output_vector)
365 pcout <<
"Applying [dXvdXs] onto a vector..." << std::endl;
366 assert(input_vector.size() == output_vector.size());
368 double input_vector_norm = input_vector.l2_norm();
369 if (input_vector_norm == 0.0) {
370 pcout <<
"Zero input vector. Zero output vector." << std::endl;
378 dealii::SolverControl solver_control(20000, 1e-14 * input_vector_norm, log_history);
380 solver_control.log_frequency(100);
381 const int max_n_tmp_vectors=200;
382 const bool right_preconditioning=
true;
383 const bool use_default_residual=
true;
384 const bool force_re_orthogonalization=
false;
385 dealii::SolverGMRES<dealii::LinearAlgebra::distributed::Vector<double>>::AdditionalData gmres_settings(max_n_tmp_vectors, right_preconditioning, use_default_residual, force_re_orthogonalization);
386 dealii::SolverGMRES<dealii::LinearAlgebra::distributed::Vector<double>> solver(solver_control, gmres_settings);
396 dealii::TrilinosWrappers::PreconditionILUT precondition;
397 const unsigned int ilut_fill=50;
398 const double ilut_drop=1e-15;
399 const double ilut_atol=1e-6;
400 const double ilut_rtol=1.00001;
401 const unsigned int overlap=1;
402 dealii::TrilinosWrappers::PreconditionILUT::AdditionalData precond_settings(ilut_drop, ilut_fill, ilut_atol, ilut_rtol, overlap);
414 using trilinos_vector_type = dealii::LinearAlgebra::distributed::Vector<double>;
415 using payload_type = dealii::TrilinosWrappers::internal::LinearOperatorImplementation::TrilinosPayload;
416 const auto op_a = dealii::linear_operator<trilinos_vector_type,trilinos_vector_type,payload_type>(
system_matrix);
418 const auto &rhs_vector = input_vector;
419 output_vector = input_vector;
423 dealii::deallog.depth_console(2);
424 solver.solve(op_a, output_vector, rhs_vector, precondition);
426 pcout <<
"dXvdXvs Solver took " << solver_control.last_step() <<
" steps. " 427 <<
"Residual: " << solver_control.last_value() <<
". " 430 solver.solve(op_a, output_vector, rhs_vector, precondition);
432 pcout <<
"dXvdXvs Solver took " << solver_control.last_step() <<
" steps. " 433 <<
"Residual: " << solver_control.last_value() <<
". " 436 if (solver_control.last_check() != dealii::SolverControl::State::success) {
437 pcout <<
"Failed to converge." << std::endl;
442 template <
int dim,
typename real>
446 std::vector<dealii::LinearAlgebra::distributed::Vector<double>> &list_of_vectors,
447 dealii::TrilinosWrappers::SparseMatrix &output_matrix)
452 const unsigned int n_cols = list_of_vectors.size();
455 const dealii::IndexSet &row_part =
dof_handler.locally_owned_dofs();
458 dealii::DynamicSparsityPattern full_dsp(n_rows, n_cols, row_part);
459 for (
const auto &i_row: row_part) {
460 for (
unsigned int i_col = 0; i_col < n_cols; ++i_col) {
461 full_dsp.add(i_row, i_col);
466 dealii::SparsityPattern full_sp;
467 full_sp.copy_from(full_dsp);
469 const dealii::IndexSet col_part = dealii::Utilities::MPI::create_evenly_distributed_partitioning(MPI_COMM_WORLD,n_cols);
481 dealii::TrilinosWrappers::PreconditionILUT precondition;
482 const unsigned int ilut_fill=50;
483 const double ilut_drop=0.0;
484 const double ilut_atol=0.0;
485 const double ilut_rtol=1.0;
486 const unsigned int overlap=1;
487 dealii::TrilinosWrappers::PreconditionILUT::AdditionalData precond_settings(ilut_drop, ilut_fill, ilut_atol, ilut_rtol, overlap);
499 using trilinos_vector_type = dealii::LinearAlgebra::distributed::Vector<double>;
500 using payload_type = dealii::TrilinosWrappers::internal::LinearOperatorImplementation::TrilinosPayload;
501 const auto op_a = dealii::linear_operator<trilinos_vector_type,trilinos_vector_type,payload_type>(
system_matrix);
504 pcout <<
"Applying for [dXvdXs] onto " << list_of_vectors.size() <<
" vectors..." << std::endl;
506 unsigned int col = 0;
507 dealii::LinearAlgebra::distributed::Vector<double> output_vector;
508 output_vector.reinit(list_of_vectors[0]);
509 for (
auto &input_vector: list_of_vectors) {
511 pcout <<
" Vector " << col <<
" out of " << list_of_vectors.size() << std::endl;
513 dealii::deallog.depth_console(0);
515 double input_vector_norm = input_vector.l2_norm();
516 if (input_vector_norm == 0.0) {
517 pcout <<
"Zero input vector. Zero output vector." << std::endl;
521 dealii::SolverControl solver_control(20000, 1e-14 * input_vector_norm, log_history);
523 solver_control.log_frequency(100);
524 const int max_n_tmp_vectors=200;
525 const bool right_preconditioning=
true;
526 const bool use_default_residual=
true;
527 const bool force_re_orthogonalization=
false;
528 dealii::SolverGMRES<dealii::LinearAlgebra::distributed::Vector<double>>::AdditionalData gmres_settings(max_n_tmp_vectors, right_preconditioning, use_default_residual, force_re_orthogonalization);
529 dealii::SolverGMRES<dealii::LinearAlgebra::distributed::Vector<double>> solver(solver_control, gmres_settings);
533 dealii::deallog.depth_console(2);
534 solver.solve(op_a, output_vector, input_vector, precondition);
535 pcout <<
"dXvdXvs Solver took " << solver_control.last_step() <<
" steps. " 536 <<
"Residual: " << solver_control.last_value() <<
". " 539 solver.solve(op_a, output_vector, input_vector, precondition);
540 pcout <<
"dXvdXvs Solver took " << solver_control.last_step() <<
" steps. " 541 <<
"Residual: " << solver_control.last_value() <<
". " 545 dXvdXs.push_back(output_vector);
547 for (
const auto &row:
dof_handler.locally_owned_dofs()) {
548 output_matrix.set(row, col,
dXvdXs[col][row]);
552 output_matrix.compress(dealii::VectorOperation::insert);
556 template <
int dim,
typename real>
560 const dealii::LinearAlgebra::distributed::Vector<double> &input_vector,
561 dealii::LinearAlgebra::distributed::Vector<double> &output_vector)
563 pcout <<
"Applying [transpose(dXvdXvs)] onto a vector..." << std::endl;
565 double input_vector_norm = input_vector.l2_norm();
566 if (input_vector_norm == 0.0) {
567 pcout <<
"Zero input vector. Zero output vector." << std::endl;
575 dealii::SolverControl solver_control(20000, 1e-14 * input_vector_norm, log_history);
577 solver_control.log_frequency(100);
578 const int max_n_tmp_vectors=200;
579 const bool right_preconditioning=
true;
580 const bool use_default_residual=
true;
581 const bool force_re_orthogonalization=
false;
582 dealii::SolverGMRES<dealii::LinearAlgebra::distributed::Vector<double>>::AdditionalData gmres_settings(max_n_tmp_vectors, right_preconditioning, use_default_residual, force_re_orthogonalization);
583 dealii::SolverGMRES<dealii::LinearAlgebra::distributed::Vector<double>> solver(solver_control, gmres_settings);
593 dealii::TrilinosWrappers::PreconditionILUT precondition;
594 const unsigned int ilut_fill=50;
595 const double ilut_drop=1e-15;
596 const double ilut_atol=1e-6;
597 const double ilut_rtol=1.00001;
598 const unsigned int overlap=1;
599 dealii::TrilinosWrappers::PreconditionILUT::AdditionalData precond_settings(ilut_drop, ilut_fill, ilut_atol, ilut_rtol, overlap);
611 using payload_type = dealii::TrilinosWrappers::internal::LinearOperatorImplementation::TrilinosPayload;
612 const auto op_a = dealii::linear_operator<trilinos_vector_type,trilinos_vector_type,payload_type>(
system_matrix);
613 const auto op_at = dealii::transpose_operator(op_a);
616 dealii::deallog.depth_console(2);
617 output_vector = input_vector;
618 solver.solve(op_at, output_vector, input_vector, precondition);
619 pcout <<
"dXvdXvs_Transpose Solver took " << solver_control.last_step() <<
" steps. " 620 <<
"Residual: " << solver_control.last_value() <<
". " 622 solver.solve(op_at, output_vector, input_vector, precondition);
623 pcout <<
"dXvdXvs_Transpose Solver took " << solver_control.last_step() <<
" steps. " 624 <<
"Residual: " << solver_control.last_value() <<
". " 626 if (solver_control.last_check() != dealii::SolverControl::State::success) {
627 pcout <<
"Failed to converge." << std::endl;
880 template <
int dim,
typename real>
883 std::vector<dealii::LinearAlgebra::distributed::Vector<double>> unit_rhs_vector;
886 pcout <<
"Solving for dXvdXs with " << n_dirichlet_constraints <<
" surface nodes..." << std::endl;
887 pcout <<
"*******************************************************" << std::endl;
888 pcout <<
"Are you sure that you need to for the dXvdXs matrix...?" << std::endl;
889 pcout <<
"Ideally, you would apply dXvdXs onto a vector such that" << std::endl;
890 pcout <<
"only 1 linear system needs to be solved. " << std::endl;
891 pcout <<
"*******************************************************" << std::endl;
892 for (
unsigned int iconstraint = 0; iconstraint < n_dirichlet_constraints; iconstraint++) {
894 dealii::LinearAlgebra::distributed::Vector<double> unit_rhs;
899 unit_rhs[constrained_row] = 1.0;
901 unit_rhs.update_ghost_values();
903 unit_rhs_vector.push_back(unit_rhs);
905 dealii::TrilinosWrappers::SparseMatrix dXvdXs_matrix;
dealii::LinearAlgebra::distributed::Vector< double > system_rhs_unconstrained
MPI_Comm mpi_communicator
MPI communicator.
const dealii::LinearAlgebra::distributed::Vector< int > & boundary_ids_vector
dealii::TrilinosWrappers::SparseMatrix system_matrix
System matrix corresponding to linearized elasticity problem.
dealii::ConditionalOStream pcout
ConditionalOStream for output.
dealii::IndexSet locally_owned_dofs
Locally owned DoFs.
const std::shared_ptr< dealii::MappingFEField< dim, dim, VectorType, DoFHandlerType > > mapping_fe_field
MappingFEField corresponding to curved mesh.
Files for the baseline physics.
dealii::IndexSet locally_relevant_dofs
Locally relevant DoFs.
void apply_dXvdXvs_transpose(const dealii::LinearAlgebra::distributed::Vector< double > &input_vector, dealii::LinearAlgebra::distributed::Vector< double > &output_vector)
dealii::LinearAlgebra::distributed::Vector< double > tensor_to_vector(const std::vector< dealii::Tensor< 1, dim, real >> &boundary_displacements_tensors) const
void apply_dXvdXvs(std::vector< dealii::LinearAlgebra::distributed::Vector< double >> &list_of_vectors, dealii::TrilinosWrappers::SparseMatrix &output_matrix)
dealii::parallel::distributed::Triangulation< dim > Triangulation
dealii::TrilinosWrappers::SparseMatrix system_matrix_unconstrained
const Triangulation & triangulation
std::vector< dealii::types::global_dof_index > local_dofs_per_process
List of number of DoFs per process.
dealii::LinearAlgebra::distributed::Vector< double > system_rhs
VectorType get_volume_displacements()
LinearElasticity(const Triangulation &_triangulation, const std::shared_ptr< dealii::MappingFEField< dim, dim, VectorType, DoFHandlerType >> mapping_fe_field, const DoFHandlerType &_dof_handler, const dealii::LinearAlgebra::distributed::Vector< int > &_boundary_ids_vector, const dealii::LinearAlgebra::distributed::Vector< double > &_boundary_displacements_vector)
Constructor.
dealii::DoFHandler< dim > DoFHandlerType
DoFHandler.
void setup_system()
Allocation and boundary condition setup.
VectorType displacement_solution
void assemble_system()
Assemble the system and its right-hand side.
const DoFHandlerType & dof_handler
Same DoFHandler as the HighOrderGrid.
dealii::AffineConstraints< double > hanging_node_constraints
dealii::LinearAlgebra::distributed::Vector< real > VectorType
Distributed vector of double.
dealii::AffineConstraints< double > all_constraints
const unsigned int this_mpi_process
MPI rank.
const dealii::QGauss< dim > quadrature_formula
Integration strength of the mesh order plus one.
std::vector< dealii::LinearAlgebra::distributed::Vector< double > > dXvdXs
const unsigned int n_mpi_processes
Number of MPI processes.
const dealii::LinearAlgebra::distributed::Vector< double > & boundary_displacements_vector