applications/mp-advec-diff/cases/advection_diffusion_DG.hpp Source File

Developer Documentation: applications/mp-advec-diff/cases/advection_diffusion_DG.hpp Source File
Developer Documentation
advection_diffusion_DG.hpp
Go to the documentation of this file.
1#pragma once
2
3#include <deal.II/base/exceptions.h>
4#include <deal.II/base/function.h>
5#include <deal.II/base/function_signed_distance.h>
6#include <deal.II/base/mpi.h>
7#include <deal.II/base/point.h>
8#include <deal.II/base/tensor.h>
9#include <deal.II/base/types.h>
10
11#include <deal.II/distributed/tria.h>
12
13#include <deal.II/fe/fe_q.h>
14
15#include <deal.II/grid/grid_generator.h>
16#include <deal.II/grid/tria.h>
17
18#include <deal.II/lac/vector.h>
19
20#include <deal.II/numerics/vector_tools.h>
21
23
24#include <cmath>
25#include <iostream>
26#include <memory>
27#include <string>
28
29#include "../advection_diffusion_case.hpp"
30
32{
33 static bool inflow_outflow_bc = false;
34
35 template <int dim, typename number>
36 class ExactSolution : public dealii::Function<dim, number>
37 {
38 public:
40 : dealii::Function<dim, number>()
41
42 {}
43
44 number
45 value(const dealii::Point<dim, number> &p, const unsigned int /*component*/) const override
46 {
47 const number t = this->get_time();
48 return std::sin(4.0 * dealii::numbers::PI * (p[0] - 1.1 * t));
49 }
50
51 private:
52 };
53
54 /*
55 * this function specifies the initial field of the level set equation
56 */
57 template <int dim, typename number>
58 class InitializePhi : public dealii::Function<dim, number>
59 {
60 public:
62 : dealii::Function<dim, number>()
63 , distance_sphere(dim == 1 ? dealii::Point<dim, number>(0.0) :
64 (dim == 2) ? dealii::Point<dim, number>(0.0, 0.5) :
65 dealii::Point<dim, number>(0, 0, 0.5),
66 0.25)
67 {}
68
69 number
70 value(const dealii::Point<dim, number> &p, const unsigned int /*component*/) const override
71 {
72 return std::sin(4.0 * dealii::numbers::PI * p[0]);
73 }
74
75 private:
76 const dealii::Functions::SignedDistance::Sphere<dim> distance_sphere;
77 };
78
79 template <int dim, typename number>
80 class AdvectionField : public dealii::Function<dim, number>
81 {
82 public:
84 : dealii::Function<dim, number>(dim)
85 {}
86
87 number
88 value([[maybe_unused]] const dealii::Point<dim, number> &p,
89 const unsigned int component) const override
90 {
91 if (component == 0)
92 return 1.1;
93 else
94 return 0.0;
95 }
96 };
97
98 template <int dim, typename number>
99 class DirichletConditions : public dealii::Function<dim, number>
100 {
101 public:
103 : dealii::Function<dim, number>(dim)
104 {}
105
106 number
107 value([[maybe_unused]] const dealii::Point<dim, number> &p,
108 [[maybe_unused]] const unsigned int component) const override
109 {
110 const number t = this->get_time();
111 return std::sin(4.0 * dealii::numbers::PI * (p[0] - 1.1 * t));
112 }
113 };
114
115 /*
116 * This class collects all relevant input data for the level set simulation
117 */
118 template <int dim, typename number>
120 {
121 public:
124 {}
125
126 void
128 {
129 if (dim == 1 || this->parameters.base.fe.type == FiniteElementType::FE_SimplexP)
130 {
131 AssertDimension(dealii::Utilities::MPI::n_mpi_processes(this->mpi_communicator), 1);
132 this->triangulation = std::make_shared<dealii::Triangulation<dim>>();
133 }
134 else
135 {
136 this->triangulation = std::make_shared<dealii::parallel::distributed::Triangulation<dim>>(
137 this->mpi_communicator);
138 }
139
140 if (this->parameters.base.fe.type == FiniteElementType::FE_SimplexP)
141 {
142 dealii::GridGenerator::subdivided_hyper_cube_with_simplices(
143 *this->triangulation,
144 dealii::Utilities::pow(2, this->parameters.base.global_refinements),
147 }
148 else
149 {
150 dealii::GridGenerator::hyper_cube(*this->triangulation, left_domain, right_domain);
151 this->triangulation->refine_global(this->parameters.base.global_refinements);
152 }
153 }
154
155 void
157 {
158 /*
159 * create a pair of (boundary_id, dirichlet_function)
160 */
161 constexpr dealii::types::boundary_id inflow_bc = 42;
162 constexpr dealii::types::boundary_id do_nothing = 0;
163
164 auto dirichlet = std::make_shared<DirichletConditions<dim, number>>();
165
167 {
168 this->attach_boundary_condition({inflow_bc, dirichlet},
169 "inflow_outflow",
170 "advection_diffusion");
171 this->attach_boundary_condition({do_nothing, dirichlet},
172 "inflow_outflow",
173 "advection_diffusion");
174 }
175 else
176 this->attach_boundary_condition({inflow_bc, dirichlet}, "dirichlet", "advection_diffusion");
177
178
179 if constexpr (dim >= 2)
180 {
181 for (const auto &cell : this->triangulation->cell_iterators())
182 for (const auto &face : cell->face_iterators())
183 if ((face->at_boundary()))
184 {
185 if (face->center()[0] < -0.49)
186 {
187 face->set_boundary_id(inflow_bc);
188 }
189 else
190 {
191 face->set_boundary_id(do_nothing);
192 }
193 }
194 }
195 else
196 {
197 (void)do_nothing; // suppress unused variable for 1D
198 }
199 }
200
201 void
203 {
205 "advection_diffusion");
206 this->attach_field_function(std::make_shared<AdvectionField<dim, number>>(),
207 "prescribed_velocity",
208 "advection_diffusion");
209 }
210
211 bool
212 add_case_specific_parameters(dealii::ParameterHandler &prm) override
213 {
214 prm.add_parameter("inflow outflow bc",
216 "Set if the inflow/outflow boundary condition should be enabled.");
217
218 return this->parameters.base.do_print_parameters;
219 }
220
221 void
222 do_postprocessing(const GenericDataOut<dim, number> &generic_data_out) const final
223 {
224 dealii::ConditionalOStream pcout(
225 std::cout, dealii::Utilities::MPI::this_mpi_process(this->mpi_communicator) == 0);
226
227 /*Error Calculation*/
228 ExactSolution<dim, number> exact_solution;
229 exact_solution.set_time(generic_data_out.get_time());
230
231 const auto n_q_points = 50; // Number is high to get accurate error even on a coarse mesh
232 dealii::FE_Q<dim> fe(this->parameters.advec_diff.fe.degree);
233
234 dealii::QGauss<dim> quadrature(n_q_points);
235 dealii::FEValues<dim> fe_values(fe,
236 quadrature,
237 dealii::update_values | dealii::update_JxW_values |
238 dealii::update_quadrature_points);
239
240 std::vector<number> phi_at_q(dealii::QGauss<dim>(n_q_points).size());
241
242
243
244 generic_data_out.get_vector("advected_field").update_ghost_values();
245
246 number error = 0.0;
247 number norm_exact = 0.0;
248
249 for (const auto &cell :
250 generic_data_out.get_dof_handler("advected_field").active_cell_iterators())
251 if (cell->is_locally_owned())
252 {
253 fe_values.reinit(cell);
254 fe_values.get_function_values(generic_data_out.get_vector("advected_field"),
255 phi_at_q); // compute values of old solution
256
257 for (const unsigned int q_index : fe_values.quadrature_point_indices())
258 {
259 auto sol_difference = std::abs(
260 exact_solution.value(fe_values.quadrature_point(q_index), 0) - phi_at_q[q_index]);
261 error += sol_difference * sol_difference * fe_values.JxW(q_index);
262 norm_exact += exact_solution.value(fe_values.quadrature_point(q_index), 0) *
263 exact_solution.value(fe_values.quadrature_point(q_index), 0) *
264 fe_values.JxW(q_index);
265 }
266 }
267 error = dealii::Utilities::MPI::sum(error, this->mpi_communicator);
268 norm_exact = dealii::Utilities::MPI::sum(norm_exact, this->mpi_communicator);
269
270 pcout << "Relative error to exact solution " << std::sqrt(error) / std::sqrt(norm_exact)
271 << std::endl;
272 pcout << "---------------------------------------------" << std::endl;
273 pcout << " End of user defined postprocessing" << std::endl;
274 pcout << "---------------------------------------------" << std::endl;
275 }
276
277 private:
278 const number left_domain = -0.5;
279 const number right_domain = 0.5;
280 };
281
282} // namespace MeltPoolDG::Simulation::AdvectionDiffusionDG
A generic utility for managing simulation output data in the MeltPoolDG context.
Definition generic_data_out.hpp:32
Definition advection_diffusion_case.hpp:53
AdvectionDiffusionCase(const std::string &parameter_file_in, MPI_Comm mpi_communicator_in)
Definition advection_diffusion_case.hpp:57
AdvectionDiffusionCaseParameters< number > parameters
Definition advection_diffusion_case.hpp:55
void attach_boundary_condition(std::pair< const dealii::types::boundary_id, const std::shared_ptr< dealii::Function< dim > > > id_and_function, const std::string &type, const std::string &operation_name)
Attach a boundary condition for a specific operation.
Definition simulation_case_base.hpp:345
std::shared_ptr< dealii::Triangulation< dim, spacedim > > triangulation
Definition simulation_case_base.hpp:49
const std::string parameter_file
Definition simulation_case_base.hpp:52
void attach_initial_condition(std::shared_ptr< dealii::Function< dim > > initial_function, const std::string &operation_name)
Definition simulation_case_base.hpp:327
void attach_field_function(std::shared_ptr< dealii::Function< dim > > function, const std::string &type, const std::string &operation_name)
Definition simulation_case_base.hpp:315
const MPI_Comm mpi_communicator
Definition simulation_case_base.hpp:56
Definition advection_diffusion_DG.hpp:81
AdvectionField()
Definition advection_diffusion_DG.hpp:83
number value(const dealii::Point< dim, number > &p, const unsigned int component) const override
Definition advection_diffusion_DG.hpp:88
number value(const dealii::Point< dim, number > &p, const unsigned int component) const override
Definition advection_diffusion_DG.hpp:107
DirichletConditions()
Definition advection_diffusion_DG.hpp:102
Definition advection_diffusion_DG.hpp:37
ExactSolution()
Definition advection_diffusion_DG.hpp:39
number value(const dealii::Point< dim, number > &p, const unsigned int) const override
Definition advection_diffusion_DG.hpp:45
Definition advection_diffusion_DG.hpp:59
const dealii::Functions::SignedDistance::Sphere< dim > distance_sphere
Definition advection_diffusion_DG.hpp:76
number value(const dealii::Point< dim, number > &p, const unsigned int) const override
Definition advection_diffusion_DG.hpp:70
InitializePhi()
Definition advection_diffusion_DG.hpp:61
void set_field_conditions() final
Pure virtual function to set the field conditions.
Definition advection_diffusion_DG.hpp:202
void create_spatial_discretization() override
Pure virtual function to create the spatial discretization.
Definition advection_diffusion_DG.hpp:127
void do_postprocessing(const GenericDataOut< dim, number > &generic_data_out) const final
Perform specific postprocessing (can be overridden by derived classes).
Definition advection_diffusion_DG.hpp:222
bool add_case_specific_parameters(dealii::ParameterHandler &prm) override
Add simulation-specific parameters (can be overridden).
Definition advection_diffusion_DG.hpp:212
const number right_domain
Definition advection_diffusion_DG.hpp:279
SimulationAdvecDG(std::string parameter_file, const MPI_Comm mpi_communicator)
Definition advection_diffusion_DG.hpp:122
void set_boundary_conditions() final
Pure virtual function to set the boundary conditions.
Definition advection_diffusion_DG.hpp:156
const number left_domain
Definition advection_diffusion_DG.hpp:278
Definition advection_diffusion_DG.cpp:6
static bool inflow_outflow_bc
Definition advection_diffusion_DG.hpp:33
Definition dealii_tensor.hpp:10