applications/mp-melt-pool/cases/film_boiling/film_boiling.hpp Source File

Developer Documentation: applications/mp-melt-pool/cases/film_boiling/film_boiling.hpp Source File
Developer Documentation
film_boiling.hpp
Go to the documentation of this file.
1#pragma once
2#include <deal.II/base/function.h>
3#include <deal.II/base/function_signed_distance.h>
4#include <deal.II/base/mpi.h>
5#include <deal.II/base/numbers.h>
6#include <deal.II/base/parameter_handler.h>
7#include <deal.II/base/point.h>
8#include <deal.II/base/tensor_function.h>
9#include <deal.II/base/utilities.h>
10
11#include <deal.II/distributed/tria.h>
12
13#include <deal.II/grid/grid_generator.h>
14#include <deal.II/grid/grid_tools.h>
15#include <deal.II/grid/tria.h>
16
17#include <deal.II/lac/vector.h>
18
19#include <deal.II/numerics/data_out.h>
20#include <deal.II/numerics/vector_tools.h>
21
27
28#include <cmath>
29#include <iostream>
30#include <memory>
31#include <string>
32#include <vector>
33
34#include "../../melt_pool_case.hpp"
35
46{
47 using namespace MeltPoolDG::Simulation;
48
49 // simulation specific parameters
50 static double factor_height = 1.0;
51 static double delta_T = 5;
52 static bool do_symmetry = false;
53 static std::string bc_vertical_faces = "periodic";
54 static std::string bc_temperature_top = "adiabatic";
55 static std::pair<double, double> disturbance_factors = {9. / 128, 1. / 160};
56
62 template <int dim>
63 double
64 compute_disturbed_interface(const double lambda0,
65 const dealii::Point<dim> &p,
66 const double factor_z0,
67 const double factor_dz)
68 {
69 const double projected_radius = dim == 1 ? 0 :
70 dim == 2 ? p[0] :
71 std::sqrt(p[0] * p[0] + p[1] * p[1]);
72
73 return lambda0 *
74 (factor_z0 + factor_dz * std::cos(2 * dealii::numbers::PI * projected_radius /
75 lambda0)); // according to Hardt & Wondra (2007)
76 }
77
82 template <int dim>
83 class InitialSignedDistance : public dealii::Function<dim>
84 {
85 public:
86 InitialSignedDistance(const double lambda0, const std::pair<double, double> factors)
87 : dealii::Function<dim>()
90 {}
91
92 double
93 value(const dealii::Point<dim> &p, const unsigned int /*component*/) const override
94 {
95 dealii::Point<dim> at_interface;
96 at_interface[dim - 1] =
98
99 const auto plane =
100 dealii::Functions::SignedDistance::Plane<dim>(at_interface,
101 dealii::Point<dim>::unit_vector(dim - 1));
102
103 return plane.value(p);
104 }
105 const double lambda0;
106 const std::pair<double, double> factors;
107 };
111 template <int dim>
112 class InitialValuesTemperature : public dealii::Function<dim>
113 {
114 public:
116 const double T_min,
117 const double lambda0,
118 const std::pair<double, double> factors)
119
120 : dealii::Function<dim>()
121 , T_max(T_max)
122 , T_min(T_min)
125 {}
126
127 double
128 value(const dealii::Point<dim> &p, const unsigned int /*component*/) const override
129 {
130 const double y_interface_disturbed =
132 if (p[dim - 1] > y_interface_disturbed)
133 return T_min;
134 else
135 return T_max - (T_max - T_min) / y_interface_disturbed * p[dim - 1];
136 }
137 const double T_max, T_min, lambda0;
138 const std::pair<double, double> factors;
139 };
140
144 template <int dim, typename number>
145 class SimulationFilmBoiling : public MeltPoolCase<dim, number>
146 {
147 public:
150 , lambda0(
151 2. * dealii::numbers::PI *
152 std::sqrt(3. * this->parameters.flow.surface_tension.surface_tension_coefficient /
153 (this->parameters.flow.gravity * (this->parameters.material.liquid.density -
154 this->parameters.material.gas.density))))
155 , x_max((do_symmetry) ? 0 : lambda0 / 2.)
156 , y_max(lambda0)
157 , x_min(-lambda0 / 2.)
159 {}
160
161 bool
162 add_case_specific_parameters(dealii::ParameterHandler &prm) override
163 {
164 prm.add_parameter("factor height", factor_height, "Set a factor multiplied with the height.");
165 prm.add_parameter("delta T",
166 delta_T,
167 "Set the delta of the wall temperature to the boiling temperature.");
168 prm.add_parameter("do symmetry",
170 "Exploit symmetry conditions along the center plane.");
171 prm.add_parameter("bc vertical faces",
173 "Set the boundary condition along vertical faces.",
174 dealii::Patterns::Selection("symmetry|periodic"));
175 prm.add_parameter("bc temperature top",
177 "Set the boundary condition at the top.",
178 dealii::Patterns::Selection("adiabatic|dirichlet"));
179 prm.add_parameter("disturbance factors",
181 "Set the factors controlling the initial interface function"
182 " z_Γ = z_0 + Δz * cos(2*π r/λ_0) with z_0 = factor_z0 * lambda_0 "
183 "and Δz = factor_delta_z * lambda_0");
184
185 return this->parameters.base.do_print_parameters;
186 }
187
188 void
190 {
192
193 if (this->parameters.base.fe.type == FiniteElementType::FE_SimplexP || dim == 1)
194 {
195#ifdef DEAL_II_WITH_METIS
196 this->triangulation = std::make_shared<dealii::parallel::shared::Triangulation<dim>>(
197 this->mpi_communicator,
198 dealii::Triangulation<dim>::none,
199 false,
200 dealii::parallel::shared::Triangulation<dim>::Settings::partition_metis);
201#else
202 AssertThrow(
203 false,
204 dealii::ExcMessage(
205 "Missing Metis support of the deal.II installation. "
206 "Configure deal.II with -D DEAL_II_WITH_METIS='ON' to execute this example."));
207#endif
208 }
209 else
210 {
211 this->triangulation = std::make_shared<dealii::parallel::distributed::Triangulation<dim>>(
212 this->mpi_communicator);
213 }
214
215 // create mesh
216 const dealii::Point<dim> bottom_left = dim == 1 ? dealii::Point<dim>(y_min) :
217 dim == 2 ? dealii::Point<dim>(x_min, y_min) :
218 dealii::Point<dim>(x_min, x_min, y_min);
219 const dealii::Point<dim> top_right = dim == 1 ? dealii::Point<dim>(y_max) :
220 dim == 2 ? dealii::Point<dim>(x_max, y_max) :
221 dealii::Point<dim>(x_max, x_max, y_max);
222
223 // create mesh
224 std::vector<unsigned int> subdivisions(
225 dim,
226 5 * (this->parameters.base.fe.type == FiniteElementType::FE_SimplexP ?
227 dealii::Utilities::pow(2, this->parameters.base.global_refinements) :
228 1));
229
230 // Create elements with a width to height ratio of 3. This leads to a higher resolution
231 // in the dim-1 direction, which is the predominant direction of this example.
232 subdivisions[dim - 1] *= factor_height;
233
234 if (do_symmetry)
235 subdivisions[dim - 1] *= 2;
236
237 if (this->parameters.base.fe.type == FiniteElementType::FE_SimplexP)
238 dealii::GridGenerator::subdivided_hyper_rectangle_with_simplices(
239 *this->triangulation, subdivisions, bottom_left, top_right, true /*colorize*/);
240 else
241 dealii::GridGenerator::subdivided_hyper_rectangle(
242 *this->triangulation, subdivisions, bottom_left, top_right, true /*colorize*/);
243
244 // create slice for postprocessing
245 if constexpr (dim == 3)
246 {
247 dealii::GridGenerator::subdivided_hyper_rectangle(tria_slice,
248 {1, 3} /*subdivisions*/,
249 dealii::Point<2>(x_min, y_min),
250 dealii::Point<2>(x_max, y_max));
251
252 dealii::GridTools::rotate(dealii::Point<3>::unit_vector(0),
253 0.5 * dealii::numbers::PI,
254 tria_slice);
255
256 tria_slice.refine_global(4);
257 }
258 }
259
260 void
262 {
263 // face numbering according to the deal.II colorize flag
264 const auto [lower_bc, upper_bc, left_bc, right_bc, front_bc, back_bc] =
265 get_colorized_rectangle_boundary_ids<dim>();
266
267 this->attach_boundary_condition(lower_bc, "no_slip", "navier_stokes_u");
268 this->attach_boundary_condition({upper_bc,
269 std::make_shared<dealii::Functions::ZeroFunction<dim>>()},
270 "open",
271 "navier_stokes_u");
272
273 this->attach_boundary_condition({lower_bc,
274 std::make_shared<dealii::Functions::ConstantFunction<dim>>(
275 this->parameters.material.boiling_temperature + delta_T)},
276 "dirichlet",
277 "heat_transfer");
278 if (bc_temperature_top == "dirichlet")
279 this->attach_boundary_condition({upper_bc,
280 std::make_shared<dealii::Functions::ConstantFunction<dim>>(
281 this->parameters.material.boiling_temperature)},
282 "dirichlet",
283 "heat_transfer");
284
285 // @note: this BC is necessary
287 {lower_bc, std::make_shared<dealii::Functions::ConstantFunction<dim>>(-1)},
288 "dirichlet",
289 "level_set");
291 {upper_bc, std::make_shared<dealii::Functions::ConstantFunction<dim>>(1)},
292 "inflow_outflow",
293 "level_set");
294
295 if (dim > 1)
296 {
297 if (bc_vertical_faces == "periodic")
298 this->attach_periodic_boundary_condition(left_bc, right_bc, 0);
299 else // if (bc_vertical_faces == "symmetry")
300 {
301 this->attach_boundary_condition(left_bc, "symmetry", "navier_stokes_u");
302 this->attach_boundary_condition(right_bc, "symmetry", "navier_stokes_u");
303 }
304 }
305
306 if (dim > 2)
307 {
308 if (bc_vertical_faces == "periodic")
309 this->attach_periodic_boundary_condition(front_bc, back_bc, 1);
310 else // if (bc_vertical_faces == "symmetry")
311 {
312 this->attach_boundary_condition(front_bc, "symmetry", "navier_stokes_u");
313 this->attach_boundary_condition(back_bc, "symmetry", "navier_stokes_u");
314 }
315 }
316
317 if (this->parameters.base.fe.type != FiniteElementType::FE_SimplexP)
318 this->triangulation->refine_global(this->parameters.base.global_refinements);
319 }
320
321 void
323 {
326 "signed_distance");
327
328 this->attach_initial_condition(std::make_shared<dealii::Functions::ZeroFunction<dim>>(dim),
329 "navier_stokes_u");
330
331 // assign initial temperature such that at the interface the boiling temperature is met
333 this->parameters.material.boiling_temperature + delta_T,
334 this->parameters.material.boiling_temperature,
335 lambda0,
337 "heat_transfer");
338 }
339
340 void
342 [[maybe_unused]] const GenericDataOut<dim, double> &generic_data_out) const final
343 {
344 if (this->parameters.output.do_user_defined_postprocessing == false)
345 return;
346
347 // create slice
348 if constexpr (dim == 3)
349 {
350 if (!slice)
351 {
352 const std::vector<std::string> req_vars = {"level_set", "temperature", "velocity"};
353
354 slice = std::make_shared<PostProcessingTools::SliceCreator<3, double>>(
355 generic_data_out, tria_slice, req_vars, this->parameters.output);
356 }
357 // @todo: We need to reinit, since generic_data_out is currently created
358 // for every time step.
359 slice->reinit(generic_data_out);
360
361 slice->process(n_written_time_step);
363 }
364
365 // create iso-surface
366 if constexpr (dim >= 2)
367 {
368 dealii::Triangulation<dim - 1, dim> tria;
369
370 GridGenerator::create_triangulation_with_marching_cube_algorithm<dim, double>(
371 tria,
372 generic_data_out.get_mapping(),
373 generic_data_out.get_dof_handler("level_set"),
374 generic_data_out.get_vector("level_set"),
375 0 /*iso_level*/,
376 1 /*n_subdivisions*/);
377
378
379 dealii::DataOut<dim - 1, dim> data_out;
380 data_out.attach_triangulation(tria);
381 if (tria.n_cells() > 0)
382 data_out.build_patches();
383 data_out.write_vtu_with_pvtu_record(
384 "./", "data_out_02" /*TODO*/, 0, this->mpi_communicator, 1 /*TODO*/, 1);
385 }
386 }
387
388 private:
389 const double lambda0 = 0.0;
390 const double x_max;
391 double y_max;
392 const double x_min;
393 const double y_min = 0.0;
394 mutable unsigned int n_written_time_step = 0;
395 dealii::parallel::distributed::Triangulation<2, 3> tria_slice;
396
397 mutable std::shared_ptr<PostProcessingTools::SliceCreator<3, double>> slice;
398 };
399} // namespace MeltPoolDG::Simulation::FilmBoiling
A generic utility for managing simulation output data in the MeltPoolDG context.
Definition generic_data_out.hpp:32
Definition melt_pool_case.hpp:290
MeltPoolCaseParameters< number > parameters
Definition melt_pool_case.hpp:292
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_periodic_boundary_condition(const dealii::types::boundary_id id_in, const dealii::types::boundary_id id_out, const int direction)
Definition simulation_case_base.hpp:384
void attach_initial_condition(std::shared_ptr< dealii::Function< dim > > initial_function, const std::string &operation_name)
Definition simulation_case_base.hpp:327
const MPI_Comm mpi_communicator
Definition simulation_case_base.hpp:56
const std::pair< double, double > factors
Definition film_boiling.hpp:106
double value(const dealii::Point< dim > &p, const unsigned int) const override
Definition film_boiling.hpp:93
InitialSignedDistance(const double lambda0, const std::pair< double, double > factors)
Definition film_boiling.hpp:86
const double lambda0
Definition film_boiling.hpp:105
const double T_min
Definition film_boiling.hpp:137
const double lambda0
Definition film_boiling.hpp:137
const std::pair< double, double > factors
Definition film_boiling.hpp:138
double value(const dealii::Point< dim > &p, const unsigned int) const override
Definition film_boiling.hpp:128
const double T_max
Definition film_boiling.hpp:137
InitialValuesTemperature(const double T_max, const double T_min, const double lambda0, const std::pair< double, double > factors)
Definition film_boiling.hpp:115
SimulationFilmBoiling(std::string parameter_file, const MPI_Comm mpi_communicator)
Definition film_boiling.hpp:148
void set_boundary_conditions() final
Pure virtual function to set the boundary conditions.
Definition film_boiling.hpp:261
std::shared_ptr< PostProcessingTools::SliceCreator< 3, double > > slice
Definition film_boiling.hpp:397
const double x_min
Definition film_boiling.hpp:392
void create_spatial_discretization() override
Pure virtual function to create the spatial discretization.
Definition film_boiling.hpp:189
bool add_case_specific_parameters(dealii::ParameterHandler &prm) override
Add simulation-specific parameters (can be overridden).
Definition film_boiling.hpp:162
const double x_max
Definition film_boiling.hpp:390
const double lambda0
Definition film_boiling.hpp:389
dealii::parallel::distributed::Triangulation< 2, 3 > tria_slice
Definition film_boiling.hpp:395
unsigned int n_written_time_step
Definition film_boiling.hpp:394
void do_postprocessing(const GenericDataOut< dim, double > &generic_data_out) const final
Definition film_boiling.hpp:341
const double y_min
Definition film_boiling.hpp:393
void set_field_conditions() final
Pure virtual function to set the field conditions.
Definition film_boiling.hpp:322
Definition film_boiling.cpp:6
static std::string bc_temperature_top
Definition film_boiling.hpp:54
static std::pair< double, double > disturbance_factors
Definition film_boiling.hpp:55
double compute_disturbed_interface(const double lambda0, const dealii::Point< dim > &p, const double factor_z0, const double factor_dz)
Definition film_boiling.hpp:64
static std::string bc_vertical_faces
Definition film_boiling.hpp:53
static double delta_T
Definition film_boiling.hpp:51
static bool do_symmetry
Definition film_boiling.hpp:52
static double factor_height
Definition film_boiling.hpp:50
Definition advection_diffusion.cpp:6
Definition dealii_tensor.hpp:10