ExaDG
Loading...
Searching...
No Matches
check_multigrid.h
1/* ______________________________________________________________________
2 *
3 * ExaDG - High-Order Discontinuous Galerkin for the Exa-Scale
4 *
5 * Copyright (C) 2021 by the ExaDG authors
6 *
7 * This program is free software: you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation, either version 3 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program. If not, see <https://www.gnu.org/licenses/>.
19 * ______________________________________________________________________
20 */
21
22#ifndef INCLUDE_SOLVERS_AND_PRECONDITIONERS_CHECKMULTIGRID_H_
23#define INCLUDE_SOLVERS_AND_PRECONDITIONERS_CHECKMULTIGRID_H_
24
25// C/C++
26#include <fstream>
27
28// deal.II
29#include <deal.II/lac/la_parallel_block_vector.h>
30#include <deal.II/numerics/data_out.h>
31
32namespace ExaDG
33{
34template<int dim, typename Number, typename Operator, typename Preconditioner>
36{
37public:
38 typedef dealii::LinearAlgebra::distributed::Vector<Number> VectorType;
39
40 typedef dealii::LinearAlgebra::distributed::Vector<typename Preconditioner::MultigridNumber>
41 VectorTypeMG;
42
43 CheckMultigrid(Operator const & underlying_operator_in,
44 std::shared_ptr<Preconditioner> preconditioner_in,
45 MPI_Comm const & mpi_comm_in)
46 : underlying_operator(underlying_operator_in),
47 preconditioner(preconditioner_in),
48 mpi_comm(mpi_comm_in)
49 {
50 }
51
52 /*
53 * Function that verifies the multgrid algorithm,
54 * especially the smoothing (on the finest level) an
55 * the whole multigrid cycle applied to a random solution vector
56 *
57 *
58 * Richardson iteration: x^{k+1} = x^{k} + M^{-1} * ( b - A*x^{k} )
59 *
60 * A: system matrix
61 * M^{-1}: preconditioner (should approximate A^{-1})
62 *
63 * rhs vector b: b = 0 (-> x_ex = 0)
64 * initial guess x^{0} = rand()
65 *
66 * --> calculate x^{1} = x^{0} - M^{-1}*A*x^{0}
67 * --> If multigrid cycle works well, x^{1} should be small (entries < 0.1)
68 */
69 void
70 check()
71 {
72 /*
73 * Whole MG Cycle
74 */
75 VectorType initial_solution;
76 underlying_operator.initialize_dof_vector(initial_solution);
77 VectorType solution_after_mg_cylce(initial_solution), tmp(initial_solution);
78
79 for(unsigned int i = 0; i < initial_solution.locally_owned_size(); ++i)
80 initial_solution.local_element(i) = (double)rand() / RAND_MAX;
81
82 underlying_operator.vmult(tmp, initial_solution);
83 tmp *= -1.0;
84 preconditioner->vmult(solution_after_mg_cylce, tmp);
85 solution_after_mg_cylce += initial_solution;
86
87 /*
88 * Smoothing
89 */
90
91 VectorTypeMG initial_solution_float;
92 initial_solution_float = initial_solution;
93 VectorTypeMG solution_after_smoothing, tmp_float;
94 solution_after_smoothing = initial_solution;
95 tmp_float = tmp;
96
97 preconditioner->apply_smoother_on_fine_level(solution_after_smoothing, tmp_float);
98 solution_after_smoothing += initial_solution_float;
99
100 /*
101 * Output
102 */
103 write_output(initial_solution, solution_after_mg_cylce, solution_after_smoothing);
104
105 /*
106 * Terminate simulation
107 */
108 // std::abort();
109 }
110
111 void
112 write_output(VectorType const & initial_solution,
113 VectorType const & solution_after_mg_cylce,
114 VectorTypeMG const & solution_after_smoothing) const
115 {
116 dealii::DataOut<dim> data_out;
117 dealii::DataOutBase::VtkFlags flags;
118 flags.write_higher_order_cells = true;
119 data_out.set_flags(flags);
120
121 unsigned int dof_index = underlying_operator.get_dof_index();
122
123 // TODO: use scalar = false for velocity field
124 bool scalar = true;
125
126 if(scalar)
127 {
128 // pressure
129 data_out.add_data_vector(underlying_operator.get_matrix_free().get_dof_handler(dof_index),
130 initial_solution,
131 "initial");
132 data_out.add_data_vector(underlying_operator.get_matrix_free().get_dof_handler(dof_index),
133 solution_after_mg_cylce,
134 "mg_cycle");
135 data_out.add_data_vector(underlying_operator.get_matrix_free().get_dof_handler(dof_index),
136 solution_after_smoothing,
137 "smoother");
138 }
139 else
140 {
141 // velocity
142 std::vector<std::string> initial(dim, "initial");
143 std::vector<dealii::DataComponentInterpretation::DataComponentInterpretation>
144 initial_component_interpretation(
145 dim, dealii::DataComponentInterpretation::component_is_part_of_vector);
146
147 data_out.add_data_vector(underlying_operator.get_matrix_free().get_dof_handler(dof_index),
148 initial_solution,
149 initial,
150 initial_component_interpretation);
151
152 std::vector<std::string> mg_cycle(dim, "mg_cycle");
153 std::vector<dealii::DataComponentInterpretation::DataComponentInterpretation>
154 mg_cylce_component_interpretation(
155 dim, dealii::DataComponentInterpretation::component_is_part_of_vector);
156
157 data_out.add_data_vector(underlying_operator.get_matrix_free().get_dof_handler(dof_index),
158 solution_after_mg_cylce,
159 mg_cycle,
160 mg_cylce_component_interpretation);
161
162 std::vector<std::string> smoother(dim, "smoother");
163 std::vector<dealii::DataComponentInterpretation::DataComponentInterpretation>
164 smoother_component_interpretation(
165 dim, dealii::DataComponentInterpretation::component_is_part_of_vector);
166
167 data_out.add_data_vector(underlying_operator.get_matrix_free().get_dof_handler(dof_index),
168 solution_after_smoothing,
169 smoother,
170 smoother_component_interpretation);
171 }
172
173 data_out.build_patches(
174 underlying_operator.get_matrix_free().get_dof_handler(dof_index).get_fe().degree);
175
176 std::ostringstream filename;
177 std::string name = "smoothing";
178 filename << name << "_Proc" << dealii::Utilities::MPI::this_mpi_process(mpi_comm) << ".vtu";
179
180 std::ofstream output(filename.str().c_str());
181 data_out.write_vtu(output);
182
183 if(dealii::Utilities::MPI::this_mpi_process(mpi_comm) == 0)
184 {
185 std::vector<std::string> filenames;
186 for(unsigned int i = 0; i < dealii::Utilities::MPI::n_mpi_processes(mpi_comm); ++i)
187 {
188 std::ostringstream filename;
189 filename << name << "_Proc" << i << ".vtu";
190
191 filenames.push_back(filename.str().c_str());
192 }
193 std::string master_name = name + ".pvtu";
194 std::ofstream master_output(master_name.c_str());
195 data_out.write_pvtu_record(master_output, filenames);
196 }
197 }
198
199private:
200 Operator const & underlying_operator;
201
202 std::shared_ptr<Preconditioner> preconditioner;
203
204 MPI_Comm mpi_comm;
205};
206
207} // namespace ExaDG
208
209#endif /* INCLUDE_SOLVERS_AND_PRECONDITIONERS_CHECKMULTIGRID_H_ */
Definition check_multigrid.h:36
Definition driver.cpp:33