/* ------------------------------------------------------------------------ * * SPDX-License-Identifier: LGPL-2.1-or-later * Copyright (C) 1999 - 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 using namespace dealii; template class Step4 { public: Step4(); void run(); private: void make_grid(); void setup_system(); void assemble_system(); void solve(); void output_results() const; Triangulation triangulation; const FE_Q fe; DoFHandler dof_handler; SparsityPattern sparsity_pattern; SparseMatrix system_matrix; Vector solution; Vector system_rhs; }; template class RightHandSide : public Function { public: virtual double value(const Point &p, const unsigned int component = 0) const override; }; template class BoundaryValues : public Function { public: virtual double value(const Point &p, const unsigned int component = 0) const override; }; template double RightHandSide::value(const Point &p, const unsigned int /*component*/) const { double return_value = 0.0; for (unsigned int i = 0; i < dim; ++i) return_value += 4.0 * std::pow(p[i], 4.0); return return_value; } template double BoundaryValues::value(const Point &p, const unsigned int /*component*/) const { return p.square(); } template Step4::Step4() : fe(/* polynomial degree = */ 1) , dof_handler(triangulation) {} template void Step4::make_grid() { GridGenerator::hyper_cube(triangulation, -1, 1); triangulation.refine_global(4); std::cout << " Number of active cells: " << triangulation.n_active_cells() << std::endl << " Total number of cells: " << triangulation.n_cells() << std::endl; } template void Step4::setup_system() { dof_handler.distribute_dofs(fe); std::cout << " Number of degrees of freedom: " << dof_handler.n_dofs() << std::endl; DynamicSparsityPattern dsp(dof_handler.n_dofs()); DoFTools::make_sparsity_pattern(dof_handler, dsp); sparsity_pattern.copy_from(dsp); system_matrix.reinit(sparsity_pattern); solution.reinit(dof_handler.n_dofs()); system_rhs.reinit(dof_handler.n_dofs()); } template void Step4::assemble_system() { const QGauss quadrature_formula(fe.degree + 1); RightHandSide right_hand_side; 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(); FullMatrix cell_matrix(dofs_per_cell, dofs_per_cell); Vector cell_rhs(dofs_per_cell); std::vector local_dof_indices(dofs_per_cell); for (const auto &cell : dof_handler.active_cell_iterators()) { fe_values.reinit(cell); cell_matrix = 0; cell_rhs = 0; for (const unsigned int q_index : fe_values.quadrature_point_indices()) for (const unsigned int i : fe_values.dof_indices()) { for (const unsigned int j : fe_values.dof_indices()) cell_matrix(i, j) += (fe_values.shape_grad(i, q_index) * // grad phi_i(x_q) fe_values.shape_grad(j, q_index) * // grad phi_j(x_q) fe_values.JxW(q_index)); // dx const auto &x_q = fe_values.quadrature_point(q_index); cell_rhs(i) += (fe_values.shape_value(i, q_index) * // phi_i(x_q) right_hand_side.value(x_q) * // f(x_q) fe_values.JxW(q_index)); // dx } cell->get_dof_indices(local_dof_indices); for (const unsigned int i : fe_values.dof_indices()) { for (const unsigned int j : fe_values.dof_indices()) system_matrix.add(local_dof_indices[i], local_dof_indices[j], cell_matrix(i, j)); system_rhs(local_dof_indices[i]) += cell_rhs(i); } } std::map boundary_values; VectorTools::interpolate_boundary_values(dof_handler, types::boundary_id(0), BoundaryValues(), boundary_values); MatrixTools::apply_boundary_values(boundary_values, system_matrix, solution, system_rhs); } template void Step4::solve() { SolverControl solver_control(1000, 1e-6 * system_rhs.l2_norm()); SolverCG> solver(solver_control); solver.solve(system_matrix, solution, system_rhs, PreconditionIdentity()); std::cout << " " << solver_control.last_step() << " CG iterations needed to obtain convergence." << std::endl; } template void Step4::output_results() const { DataOut data_out; data_out.attach_dof_handler(dof_handler); data_out.add_data_vector(solution, "solution"); data_out.build_patches(); std::ofstream output(dim == 2 ? "solution-2d.vtk" : "solution-3d.vtk"); data_out.write_vtk(output); } template void Step4::run() { std::cout << "Solving problem in " << dim << " space dimensions." << std::endl; make_grid(); setup_system(); assemble_system(); solve(); output_results(); } int main() { cout << "\n"; cout << "step-4():\n"; cout << " dealii example code.\n"; cout << "\n"; { Step4<2> laplace_problem_2d; laplace_problem_2d.run(); } { Step4<3> laplace_problem_3d; laplace_problem_3d.run(); } cout << "\n"; cout << "step-4():\n"; cout << " Normal end of execution.\n"; return 0; }