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