/* ------------------------------------------------------------------------ * * SPDX-License-Identifier: LGPL-2.1-or-later * Copyright (C) 2000 - 2024 by the deal.II authors * * This file is part of the deal.II library. * * Part of the source code is dual licensed under Apache-2.0 WITH * LLVM-exception OR LGPL-2.1-or-later. Detailed license information * governing the source code and code contributions can be found in * LICENSE.md and CONTRIBUTING.md at the top level directory of deal.II. * * ------------------------------------------------------------------------ */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include namespace Step8 { using namespace dealii; template class ElasticProblem { public: ElasticProblem(); void run(); private: void setup_system(); void assemble_system(); void solve(); void refine_grid(); void output_results(const unsigned int cycle) const; Triangulation triangulation; DoFHandler dof_handler; const FESystem fe; AffineConstraints constraints; SparsityPattern sparsity_pattern; SparseMatrix system_matrix; Vector solution; Vector system_rhs; }; template void right_hand_side(const std::vector> &points, std::vector> &values) { AssertDimension(values.size(), points.size()); Assert(dim >= 2, ExcNotImplemented()); Point point_1, point_2; point_1[0] = 0.5; point_2[0] = -0.5; for (unsigned int point_n = 0; point_n < points.size(); ++point_n) { if (((points[point_n] - point_1).norm_square() < 0.2 * 0.2) || ((points[point_n] - point_2).norm_square() < 0.2 * 0.2)) values[point_n][0] = 1.0; else values[point_n][0] = 0.0; if (points[point_n].norm_square() < 0.2 * 0.2) values[point_n][1] = 1.0; else values[point_n][1] = 0.0; } } template ElasticProblem::ElasticProblem() : dof_handler(triangulation) , fe(FE_Q(1) ^ dim) {} template void ElasticProblem::setup_system() { dof_handler.distribute_dofs(fe); solution.reinit(dof_handler.n_dofs()); system_rhs.reinit(dof_handler.n_dofs()); constraints.clear(); DoFTools::make_hanging_node_constraints(dof_handler, constraints); VectorTools::interpolate_boundary_values(dof_handler, types::boundary_id(0), Functions::ZeroFunction(dim), constraints); constraints.close(); DynamicSparsityPattern dsp(dof_handler.n_dofs(), dof_handler.n_dofs()); DoFTools::make_sparsity_pattern(dof_handler, dsp, constraints, /*keep_constrained_dofs = */ false); sparsity_pattern.copy_from(dsp); system_matrix.reinit(sparsity_pattern); } template void ElasticProblem::assemble_system() { const QGauss quadrature_formula(fe.degree + 1); FEValues fe_values(fe, quadrature_formula, update_values | update_gradients | update_quadrature_points | update_JxW_values); const unsigned int dofs_per_cell = fe.n_dofs_per_cell(); const unsigned int n_q_points = quadrature_formula.size(); FullMatrix cell_matrix(dofs_per_cell, dofs_per_cell); Vector cell_rhs(dofs_per_cell); std::vector local_dof_indices(dofs_per_cell); std::vector lambda_values(n_q_points); std::vector mu_values(n_q_points); Functions::ConstantFunction lambda(1.), mu(1.); std::vector> rhs_values(n_q_points); for (const auto &cell : dof_handler.active_cell_iterators()) { fe_values.reinit(cell); cell_matrix = 0; cell_rhs = 0; lambda.value_list(fe_values.get_quadrature_points(), lambda_values); mu.value_list(fe_values.get_quadrature_points(), mu_values); right_hand_side(fe_values.get_quadrature_points(), rhs_values); for (const unsigned int i : fe_values.dof_indices()) { const unsigned int component_i = fe.system_to_component_index(i).first; for (const unsigned int j : fe_values.dof_indices()) { const unsigned int component_j = fe.system_to_component_index(j).first; for (const unsigned int q_point : fe_values.quadrature_point_indices()) { cell_matrix(i, j) += ( (fe_values.shape_grad(i, q_point)[component_i] * fe_values.shape_grad(j, q_point)[component_j] * lambda_values[q_point]) + (fe_values.shape_grad(i, q_point)[component_j] * fe_values.shape_grad(j, q_point)[component_i] * mu_values[q_point]) + ((component_i == component_j) ? (fe_values.shape_grad(i, q_point) * fe_values.shape_grad(j, q_point) * mu_values[q_point]) : 0) ) * fe_values.JxW(q_point); } } } for (const unsigned int i : fe_values.dof_indices()) { const unsigned int component_i = fe.system_to_component_index(i).first; for (const unsigned int q_point : fe_values.quadrature_point_indices()) cell_rhs(i) += fe_values.shape_value(i, q_point) * rhs_values[q_point][component_i] * fe_values.JxW(q_point); } cell->get_dof_indices(local_dof_indices); constraints.distribute_local_to_global( cell_matrix, cell_rhs, local_dof_indices, system_matrix, system_rhs); } } template void ElasticProblem::solve() { SolverControl solver_control(1000, 1e-6 * system_rhs.l2_norm()); SolverCG> cg(solver_control); PreconditionSSOR> preconditioner; preconditioner.initialize(system_matrix, 1.2); cg.solve(system_matrix, solution, system_rhs, preconditioner); constraints.distribute(solution); } template void ElasticProblem::refine_grid() { Vector estimated_error_per_cell(triangulation.n_active_cells()); KellyErrorEstimator::estimate(dof_handler, QGauss(fe.degree + 1), {}, solution, estimated_error_per_cell); GridRefinement::refine_and_coarsen_fixed_number(triangulation, estimated_error_per_cell, 0.3, 0.03); triangulation.execute_coarsening_and_refinement(); } template void ElasticProblem::output_results(const unsigned int cycle) const { DataOut data_out; data_out.attach_dof_handler(dof_handler); std::vector solution_names; switch (dim) { case 1: solution_names.emplace_back("displacement"); break; case 2: solution_names.emplace_back("x_displacement"); solution_names.emplace_back("y_displacement"); break; case 3: solution_names.emplace_back("x_displacement"); solution_names.emplace_back("y_displacement"); solution_names.emplace_back("z_displacement"); break; } data_out.add_data_vector(solution, solution_names); data_out.build_patches(); std::ofstream output("solution-" + std::to_string(cycle) + ".vtk"); data_out.write_vtk(output); } template void ElasticProblem::run() { for (unsigned int cycle = 0; cycle < 8; ++cycle) { std::cout << "Cycle " << cycle << ':' << std::endl; if (cycle == 0) { GridGenerator::hyper_cube(triangulation, -1, 1); triangulation.refine_global(4); } else refine_grid(); std::cout << " Number of active cells: " << triangulation.n_active_cells() << std::endl; setup_system(); std::cout << " Number of degrees of freedom: " << dof_handler.n_dofs() << std::endl; assemble_system(); solve(); output_results(cycle); } } } // namespace Step8 int main() { cout << "\n"; cout << "step-8():\n"; cout << " dealii example code.\n"; cout << "\n"; try { Step8::ElasticProblem<2> elastic_problem_2d; elastic_problem_2d.run(); } catch (std::exception &exc) { std::cerr << std::endl << std::endl << "----------------------------------------------------" << std::endl; std::cerr << "Exception on processing: " << std::endl << exc.what() << std::endl << "Aborting!" << std::endl << "----------------------------------------------------" << std::endl; return 1; } catch (...) { std::cerr << std::endl << std::endl << "----------------------------------------------------" << std::endl; std::cerr << "Unknown exception!" << std::endl << "Aborting!" << std::endl << "----------------------------------------------------" << std::endl; return 1; } cout << "\n"; cout << "step-8():\n"; cout << " Normal end of execution.\n"; return 0; }