applications/mp-melt-pool/cases/laser_melting_simonds/laser_melting_simonds.templates.hpp Source File

Developer Documentation: applications/mp-melt-pool/cases/laser_melting_simonds/laser_melting_simonds.templates.hpp Source File
Developer Documentation
laser_melting_simonds.templates.hpp
Go to the documentation of this file.
1#pragma once
2
3#include <deal.II/base/exception_macros.h>
4#include <deal.II/base/exceptions.h>
5#include <deal.II/base/function.h>
6
7#include <cassert>
8
10//
11
12#include "../../../mp-heat-transfer/heat_transfer_case.hpp"
13#include "../../melt_pool_case.hpp"
14
16{
17 template <int dim>
19 : Function<dim>(dim)
20 {
21 AssertThrow(dim > 1, ExcMessage("Not implemented for dim=1"));
22 }
23
24 template <int dim>
25 double
26 InflowVelocity<dim>::value(const Point<dim> &p, const unsigned int component) const
27 {
28 // only the 0 component is relevant
29 if (component > 0)
30 return 0;
31
32 // not at the inflow wall
33 if (std::abs(p[0] + width * 0.5) > 1e-12)
34 return 0;
35
36 const double y = p[dim - 1];
37 const double y0 = 0.5 * delta_h;
38 const double y1 = 1.5 * delta_h;
39
40 if (y >= y1)
41 return inflow_velocity;
42 else if (y >= y0)
43 {
44 const double s = (y - y0) / (y1 - y0);
45 const double ramp = 2.0 * s * s - s * s * s * s;
46
47 return inflow_velocity * ramp;
48 }
49 else
50 return 0.0;
51 }
52
53 template <int dim>
55 const LevelSet::LevelSetType level_set_type)
56 : dealii::Function<dim>()
57 , distance_plane(dealii::Point<dim>(), -dealii::Point<dim>::unit_vector(dim - 1))
58 , eps(eps)
59 , level_set_type(level_set_type)
60 {}
61
62 template <int dim>
63 double
64 InitialLevelSet<dim>::value(const dealii::Point<dim> &p, const unsigned int /*component*/) const
65 {
66 const auto signed_distance = distance_plane.value(p);
67
68 switch (level_set_type)
69 {
70 case LevelSet::LevelSetType::tanh:
72 case LevelSet::LevelSetType::smoothed_heaviside:
73 return CharacteristicFunctions::smoothed_heaviside(signed_distance, eps);
74 case LevelSet::LevelSetType::signed_distance:
75 return signed_distance;
76 default:
77 AssertThrow(false, dealii::ExcNotImplemented());
78 }
79 // unreachable dummy return
80 return 0.0;
81 }
82
83 template <int dim>
85 const double T_initial_top,
86 const double y_min,
87 const double y_max)
88 : Function<dim>()
91 , y_min(y_min)
92 , grad_T((T_initial_top - T_initial_bottom) / (y_max - y_min))
93 {}
94
95 template <int dim>
96 double
98 const unsigned int /*component*/) const
99 {
101 return T_initial_top;
102 else
103 return T_initial_bottom + grad_T * (p[dim - 1] - y_min);
104 }
105
106 template <int dim, typename Number, typename CaseClass>
108 std::string parameter_file,
109 const MPI_Comm mpi_communicator)
110 : CaseClass(parameter_file, mpi_communicator)
111 , cell_repetitions(dim, 1)
112 {}
113
114 template <int dim, typename Number, typename CaseClass>
115 bool
117 dealii::ParameterHandler &prm)
118 {
119 prm.enter_subsection("domain");
120 {
121 prm.add_parameter("width", width, "Width of the box. Only relevant for dim > 1.");
122 prm.add_parameter("height substrate", height_substrate, "Height of the metal substrate.");
123 prm.add_parameter("height gas", height_gas, "Height of the ambient gas.");
124 prm.add_parameter("delta h", delta_h, "Distance between interface and gas inflow domain.");
125 }
126 prm.leave_subsection();
127
128 prm.enter_subsection("mesh");
129 {
130 prm.add_parameter("cell repetitions",
131 cell_repetitions,
132 "cell repetitions per dim applied before global refinement or amr");
133 prm.add_parameter("n local refinement",
134 n_local_refinement,
135 "number of (additional to the global) refinements for local region.");
136 prm.add_parameter("local refinement 1 bottom left",
137 local_refinement_1_bottom_left,
138 "Bottom left point of locally refined region.");
139 prm.add_parameter("local refinement 1 top right",
140 local_refinement_1_top_right,
141 "Top right point of locally refined region.");
142 prm.add_parameter("local refinement 2 bottom left",
143 local_refinement_2_bottom_left,
144 "Bottom left point of locally refined region.");
145 prm.add_parameter("local refinement 2 top right",
146 local_refinement_2_top_right,
147 "Top right point of locally refined region.");
148 }
149 prm.leave_subsection();
150
151 prm.enter_subsection("initial temperature");
152 {
153 prm.add_parameter("top", T_initial_top, "Set the initial temperature on the top boundary.");
154 prm.add_parameter("bottom",
156 "Set the initial temperature on the bottom boundary.");
157 }
158 prm.leave_subsection();
159
160 prm.enter_subsection("prescribed level set");
161 {
162 prm.add_parameter(
163 "eps prefactor",
165 "Factor multiplied by the minimum mesh size "
166 "to compute the interface thickness parameter. Used for the prescribed level-set function "
167 "for the HeatTransferCase with a diffuse-interface operator");
168 }
169 prm.leave_subsection();
170
171 prm.enter_subsection("bc");
172 {
173 prm.add_parameter("inflow velocity",
175 "Set the inflow velocity at the vertical domain boundary.");
176 prm.add_parameter("inflow temperature",
178 "Set the inflow temperature at the vertical domain boundary.");
179 prm.add_parameter("outlet pressure",
181 "Set the pressure at the vertical outlet boundary.");
182 }
183 prm.leave_subsection();
184
185 return this->parameters.base.do_print_parameters;
186 }
187
188 template <int dim, typename Number, typename CaseClass>
189 void
191 {
192 // NOTE: Simulation specific parameters that are read via the input file are only
193 // available here and not in the constructor
194 const Number half_width = width * 0.5;
195 bottom_left = (dim == 1) ? Point<dim>(-height_substrate) :
196 (dim == 2) ? Point<dim>(-half_width, -height_substrate) :
197 Point<dim>(-half_width, -half_width, -height_substrate);
198 top_right = (dim == 1) ? Point<dim>(height_gas) :
199 (dim == 2) ? Point<dim>(half_width, height_gas) :
200 Point<dim>(half_width, half_width, height_gas);
201
202 if (this->parameters.base.fe.type == FiniteElementType::FE_SimplexP or dim == 1)
203 {
204#ifdef DEAL_II_WITH_METIS
205 this->triangulation = std::make_shared<parallel::shared::Triangulation<dim>>(
206 this->mpi_communicator,
207 (Triangulation<dim>::MeshSmoothing::none),
208 true,
209 parallel::shared::Triangulation<dim>::Settings::partition_metis);
210#else
211 AssertThrow(
212 false,
213 ExcMessage("Missing Metis support of the deal.II installation. "
214 "Configure deal.II with -D DEAL_II_WITH_METIS='ON' to execute this example."));
215#endif
216 }
217 else
218 {
219 this->triangulation =
220 std::make_shared<parallel::distributed::Triangulation<dim>>(this->mpi_communicator);
221 }
222
223 // create mesh
224 if (this->parameters.base.fe.type == FiniteElementType::FE_SimplexP)
225 {
226 std::vector<unsigned int> subdivisions(
227 dim, 5 * Utilities::pow(2, this->parameters.base.global_refinements));
228 subdivisions[dim - 1] *= 2;
229 for (int d = 0; d < dim; d++)
230 subdivisions[d] *= cell_repetitions[d];
231
232 GridGenerator::subdivided_hyper_rectangle_with_simplices(*this->triangulation,
233 subdivisions,
234 bottom_left,
235 top_right);
236 }
237 else
238 {
239 GridGenerator::subdivided_hyper_rectangle(*this->triangulation,
240 cell_repetitions,
241 bottom_left,
242 top_right);
243 }
244 }
245
246 template <int dim, typename Number, typename CaseClass>
247 void
249 {
250 // refine global before setting IDs as we consider dimension-dependent
251 // splitting of the boundaries
252 this->triangulation->refine_global(this->parameters.base.global_refinements);
253
254 // Note: For 1D we consider the constraints along the z-axis, i.e. bottom_bc and top_bc.
255 const types::boundary_id substrate_bottom_bc = 1;
256 const types::boundary_id substrate_outflow_wall_bc = 2;
257 const types::boundary_id substrate_inflow_wall_bc = 3;
258 const types::boundary_id gas_top_bc = 4;
259 const types::boundary_id gas_inflow_bc = 5;
260 const types::boundary_id gas_outlet_bc = 6;
261
262 const auto double_eq = [](const Number a, const Number b) { return std::abs(a - b) <= 1e-10; };
263
264 // set boundary ids
265 for (const auto &cell : this->triangulation->cell_iterators())
266 for (const auto &face : cell->face_iterators())
267 if ((face->at_boundary()))
268 {
269 // set boundaries at faces where z=const
270 if (double_eq(face->center()[dim - 1], bottom_left[dim - 1]))
271 face->set_boundary_id(substrate_bottom_bc);
272 else if (double_eq(face->center()[dim - 1], top_right[dim - 1]))
273 face->set_boundary_id(gas_top_bc);
274 // set wall boundaries
275 else if (dim > 1)
276 {
277 // substrate: walls (all points with z<delta_h)
278 if (double_eq(face->center()[0], bottom_left[0]) &&
279 (face->center()[dim - 1] <= delta_h))
280 face->set_boundary_id(substrate_inflow_wall_bc);
281 else if (face->center()[dim - 1] <= delta_h)
282 face->set_boundary_id(substrate_outflow_wall_bc);
283 // gas inflow: all points with x=0 and z>=delta_h
284 else if (double_eq(face->center()[0], bottom_left[0]) &&
285 (face->center()[dim - 1] > delta_h))
286 face->set_boundary_id(gas_inflow_bc);
287 else if (face->center()[dim - 1] > delta_h)
288 face->set_boundary_id(gas_outlet_bc);
289 else
290 AssertThrow(false, ExcNotImplemented());
291 }
292 }
293
294 this->attach_boundary_condition(
295 {substrate_bottom_bc, std::make_shared<Functions::ConstantFunction<dim>>(T_initial_bottom)},
296 "dirichlet",
297 "heat_transfer");
298
299 if constexpr (std::is_same_v<CaseClass, MeltPoolCase<dim, Number>>)
300 {
301 if (inflow_velocity == 0 or dim == 1)
302 {
303 // NS
304 this->attach_boundary_condition(substrate_bottom_bc, "no_slip", "navier_stokes_u");
305
306 this->attach_boundary_condition(gas_top_bc, "no_slip", "navier_stokes_u");
307
308 this->attach_boundary_condition(gas_top_bc, "fix_pressure_constant", "navier_stokes_p");
309
310 this->attach_boundary_condition(gas_inflow_bc, "no_slip", "navier_stokes_u");
311 this->attach_boundary_condition(gas_outlet_bc, "no_slip", "navier_stokes_u");
312 this->attach_boundary_condition(substrate_outflow_wall_bc,
313 "no_slip",
314 "navier_stokes_u");
315 this->attach_boundary_condition(substrate_inflow_wall_bc, "no_slip", "navier_stokes_u");
316 }
317 else
318 {
319 // TODO: fix or add assert that this is only valid for eps = absolute value
320 const double eps =
321 this->parameters.ls.reinit.compute_interface_thickness_parameter_epsilon(
322 dealii::GridTools::minimal_cell_diameter(*this->triangulation) /
323 this->parameters.ls.get_n_subdivisions() / std::sqrt(dim));
324
325 AssertThrow(eps > 0, dealii::ExcNotImplemented());
326
327 // bottom
328 this->attach_boundary_condition(substrate_bottom_bc, "no_slip", "navier_stokes_u");
329
330 // top
331 this->attach_boundary_condition(gas_top_bc, "symmetry", "navier_stokes_u");
332
333 // outflow (gas + substrate)
334 //
335 // !!! Note: there is a switch in the BC between no-slip and pressure along the boundary
336 this->attach_boundary_condition(
337 {gas_outlet_bc, std::make_shared<Functions::ConstantFunction<dim>>(outlet_pressure)},
338 "open",
339 "navier_stokes_u");
340
341 // inflow (gas + substrate)
342 this->attach_boundary_condition({gas_inflow_bc,
343 std::make_shared<InflowVelocity<dim>>()},
344 "dirichlet",
345 "navier_stokes_u");
346 this->attach_boundary_condition({substrate_inflow_wall_bc,
347 std::make_shared<InflowVelocity<dim>>()},
348 "dirichlet",
349 "navier_stokes_u");
350 this->attach_boundary_condition(
351 {gas_inflow_bc, std::make_shared<Functions::ConstantFunction<dim>>(T_initial_bottom)},
352 "dirichlet",
353 "heat_transfer");
354 this->attach_boundary_condition({substrate_inflow_wall_bc,
355 std::make_shared<Functions::ConstantFunction<dim>>(
357 "dirichlet",
358 "heat_transfer");
359 // !!! Note: there is a switch in the BC between dirichlet and hom. Neumann for the
360 // level set
361 this->attach_boundary_condition({gas_inflow_bc,
362 std::make_shared<InitialLevelSet<dim>>(eps)},
363 "dirichlet",
364 "level_set");
365 this->attach_boundary_condition(
366 {gas_inflow_bc, std::make_shared<dealii::Functions::ZeroFunction<dim>>()},
367 "dirichlet",
368 "reinitialization");
369 }
370 }
371
372 /*
373 * locally refined region described by max. 2 bounding boxes
374 */
375 if (n_local_refinement > 0)
376 {
377 if constexpr (dim == 2)
378 {
379 const auto refinement_region =
380 BoundingBox<dim>({local_refinement_1_bottom_left, local_refinement_1_top_right});
381
382 const auto refinement_region_2 =
383 BoundingBox<dim>({local_refinement_2_bottom_left, local_refinement_2_top_right});
384
385 for (unsigned int j = 0; j < n_local_refinement; ++j)
386 {
387 for (auto &cell : this->triangulation->active_cell_iterators() |
388 IteratorFilters::LocallyOwnedCell())
389 {
390 for (unsigned int i = 0; i < cell->n_vertices(); ++i)
391 if (refinement_region.point_inside(cell->vertex(i)) or
392 refinement_region_2.point_inside(cell->vertex(i)))
393 {
394 cell->set_refine_flag();
395 break;
396 }
397 }
398 this->triangulation->execute_coarsening_and_refinement();
399 }
400 }
401 else
402 AssertThrow(false, ExcNotImplemented());
403 }
404 }
405
406 template <int dim, typename Number, typename CaseClass>
407 void
409 {
410 if constexpr (std::is_same_v<CaseClass, Heat::HeatTransferCase<dim, Number>>)
411 {
412 if (this->parameters.laser.model == Heat::LaserModelType::interface_projection_regularized)
413 {
414 // attach prescribed heaviside
415
416 const Number height = height_gas + height_substrate;
417
418 AssertThrow((height - width) <= 1e-10 || dim == 1,
419 ExcMessage("Epsilon is only defined if a square domain is considered."));
420
421 const auto min_mesh_size =
422 this->parameters.amr.do_amr ?
423 height / std::pow(2, this->parameters.amr.max_grid_refinement_level) :
424 height / std::pow(2, this->parameters.base.global_refinements);
425 const auto eps = eps_prefactor * min_mesh_size;
426
427 this->attach_initial_condition(std::make_shared<InitialLevelSet<dim>>(
428 eps, LevelSet::LevelSetType::smoothed_heaviside),
429 "prescribed_heaviside");
430 }
431 else if (this->parameters.laser.model == Heat::LaserModelType::interface_projection_sharp)
432 {
433 this->attach_initial_condition(std::make_shared<Functions::SignedDistance::Plane<dim>>(
434 Point<dim>(), -Point<dim>::unit_vector(dim - 1)),
435 "prescribed_signed_distance");
436 }
437 else
438 {
439 AssertThrow(false, ExcMessage("Laser model not supported."));
440 }
441 }
442 if constexpr (std::is_same_v<CaseClass, MeltPoolCase<dim, Number>>)
443 {
444 this->attach_initial_condition(std::make_shared<Functions::SignedDistance::Plane<dim>>(
445 Point<dim>(), -Point<dim>::unit_vector(dim - 1)),
446 "signed_distance");
447 if (inflow_velocity > 0 or dim > 1)
448 this->attach_initial_condition(std::make_shared<InflowVelocity<dim>>(),
449 "navier_stokes_u");
450 else
451 this->attach_initial_condition(std::make_shared<Functions::ZeroFunction<dim>>(),
452 "navier_stokes_u");
453 }
454
455
456 this->attach_initial_condition(
457 std::make_shared<InitialConditionTemperature<dim>>(
458 T_initial_bottom, T_initial_top, bottom_left[dim - 1], top_right[dim - 1]),
459 "heat_transfer");
460 }
461
462 template <int dim, typename Number, typename CaseClass>
463 void
465 [[maybe_unused]] const GenericDataOut<dim, Number> &generic_data_out) const
466 {
467 if (this->parameters.output.paraview.enable == false)
468 return;
469
470 n_time_step += 1;
471
472 if ((n_time_step % this->parameters.output.write_frequency) &&
473 generic_data_out.get_time() != this->parameters.time_stepping.end_time)
474 return;
475 if constexpr (std::is_same_v<CaseClass, MeltPoolCase<dim, Number>>)
476 {
477 generic_data_out.get_vector("velocity").update_ghost_values();
478 generic_data_out.get_vector("density").update_ghost_values();
479 generic_data_out.get_vector("rho_cp").update_ghost_values();
480 generic_data_out.get_vector("temperature").update_ghost_values();
481
482 QGauss<dim> quad(generic_data_out.get_dof_handler("density").get_fe().tensor_degree() + 2);
483
484 FEValues<dim> dens_values(generic_data_out.get_mapping(),
485 generic_data_out.get_dof_handler("density").get_fe(),
486 quad,
487 update_values | update_JxW_values);
488
489 FEValues<dim> rho_cp_values(generic_data_out.get_mapping(),
490 generic_data_out.get_dof_handler("rho_cp").get_fe(),
491 quad,
492 update_values);
493
494 FEValues<dim> vel_values(generic_data_out.get_mapping(),
495 generic_data_out.get_dof_handler("velocity").get_fe(),
496 quad,
497 update_values);
498
499 FEValues<dim> temp_values(generic_data_out.get_mapping(),
500 generic_data_out.get_dof_handler("temperature").get_fe(),
501 quad,
502 update_values);
503
504 std::vector<Number> density(dens_values.get_quadrature().size());
505 std::vector<Number> rho_cp(dens_values.get_quadrature().size());
506 std::vector<Number> temperature(dens_values.get_quadrature().size());
507 std::vector<Tensor<1, dim>> velocity(density.size(), Tensor<1, dim>());
508 const FEValuesExtractors::Vector velocities(0);
509
510 Number mass = 0;
511 std::vector<Number> momentum(dim, 0);
512 Number thermal_energy = 0;
513 Number kinetic_energy = 0;
514
515 for (const auto &cell :
516 this->triangulation->active_cell_iterators() | IteratorFilters::LocallyOwnedCell())
517 {
518 {
519 TriaIterator<DoFCellAccessor<dim, dim, false>> dof_cell(
520 &generic_data_out.get_dof_handler("density").get_triangulation(),
521 cell->level(),
522 cell->index(),
523 &generic_data_out.get_dof_handler("density"));
524 dens_values.reinit(dof_cell);
525 dens_values.get_function_values(generic_data_out.get_vector("density"), density);
526 }
527
528 {
529 TriaIterator<DoFCellAccessor<dim, dim, false>> dof_cell(
530 &generic_data_out.get_dof_handler("density").get_triangulation(),
531 cell->level(),
532 cell->index(),
533 &generic_data_out.get_dof_handler("rho_cp"));
534 rho_cp_values.reinit(dof_cell);
535 rho_cp_values.get_function_values(generic_data_out.get_vector("rho_cp"), rho_cp);
536 temp_values.reinit(dof_cell);
537 temp_values.get_function_values(generic_data_out.get_vector("temperature"),
538 temperature);
539 }
540
541 {
542 TriaIterator<DoFCellAccessor<dim, dim, false>> dof_cell(
543 &generic_data_out.get_dof_handler("density").get_triangulation(),
544 cell->level(),
545 cell->index(),
546 &generic_data_out.get_dof_handler("velocity"));
547 vel_values.reinit(dof_cell);
548 vel_values[velocities].get_function_values(generic_data_out.get_vector("velocity"),
549 velocity);
550 }
551
552 for (const unsigned int q : dens_values.quadrature_point_indices())
553 {
554 mass += density[q] * dens_values.JxW(q);
555 thermal_energy += rho_cp[q] * temperature[q] * dens_values.JxW(q);
556 for (unsigned int d = 0; d < dim; ++d)
557 {
558 momentum[d] += density[q] * velocity[q][d] * dens_values.JxW(q);
559 kinetic_energy +=
560 0.5 * density[q] * velocity[q][d] * velocity[q][d] * dens_values.JxW(q);
561 }
562 }
563 }
564
565 generic_data_out.get_vector("velocity").zero_out_ghost_values();
566 generic_data_out.get_vector("density").zero_out_ghost_values();
567 generic_data_out.get_vector("rho_cp").zero_out_ghost_values();
568 generic_data_out.get_vector("temperature").zero_out_ghost_values();
569
570 mass =
571 Utilities::MPI::sum(mass, generic_data_out.get_vector("density").get_mpi_communicator());
572
573 for (unsigned int d = 0; d < dim; ++d)
574 momentum[d] =
575 Utilities::MPI::sum(momentum[d],
576 generic_data_out.get_vector("density").get_mpi_communicator());
577
578 kinetic_energy =
579 Utilities::MPI::sum(kinetic_energy,
580 generic_data_out.get_vector("density").get_mpi_communicator());
581 thermal_energy =
582 Utilities::MPI::sum(thermal_energy,
583 generic_data_out.get_vector("density").get_mpi_communicator());
584
585 output_table.add_value("time", generic_data_out.get_time());
586 output_table.add_value("mass", mass);
587 output_table.add_value("kinetic_energy", kinetic_energy);
588 output_table.add_value("thermal_energy", thermal_energy);
589
590 for (unsigned int d = 0; d < dim; ++d)
591 output_table.add_value("momentum_" + std::to_string(d), momentum[d]);
592
593 if (Utilities::MPI::this_mpi_process(this->mpi_communicator) == 0)
594 {
595 namespace fs = std::filesystem;
596 std::ofstream output(
597 fs::path(this->parameters.output.directory) /
598 fs::path(this->parameters.output.paraview.filename + "_conservation_variables.txt"));
599
600 output_table.write_text(output);
601 }
602 }
603 }
604} // namespace MeltPoolDG::Simulation::LaserMeltingSimonds
A generic utility for managing simulation output data in the MeltPoolDG context.
Definition generic_data_out.hpp:32
Prescribed inflow velocity profile.
Definition laser_melting_simonds.hpp:98
InflowVelocity()
Construct the inflow velocity function.
Definition laser_melting_simonds.templates.hpp:18
double value(const Point< dim > &p, const unsigned int component) const override
Evaluate the inflow velocity.
Definition laser_melting_simonds.templates.hpp:26
Linear initial temperature profile in the vertical direction.
Definition laser_melting_simonds.hpp:179
InitialConditionTemperature(const double T_initial_bottom, const double T_initial_top, const double y_min, const double y_max)
Construct the initial temperature function.
Definition laser_melting_simonds.templates.hpp:84
double value(const Point< dim > &p, const unsigned int component) const override
Evaluate the initial temperature.
Definition laser_melting_simonds.templates.hpp:97
Initial level-set function for the horizontal substrate-gas interface.
Definition laser_melting_simonds.hpp:133
double value(const dealii::Point< dim > &p, const unsigned int component) const override
Evaluate the initial level-set field.
Definition laser_melting_simonds.templates.hpp:64
InitialLevelSet(const double eps, const LevelSet::LevelSetType level_set_type=LevelSet::LevelSetType::tanh)
Construct the initial level-set function.
Definition laser_melting_simonds.templates.hpp:54
void set_field_conditions() override
Attach initial conditions for all active fields.
Definition laser_melting_simonds.templates.hpp:408
void create_spatial_discretization() override
Create the triangulation and initial spatial discretization.
Definition laser_melting_simonds.templates.hpp:190
bool add_case_specific_parameters(dealii::ParameterHandler &prm) override
Declare simulation-specific parameters.
Definition laser_melting_simonds.templates.hpp:116
void do_postprocessing(const GenericDataOut< dim, Number > &generic_data_out) const final
Perform simulation-specific postprocessing.
Definition laser_melting_simonds.templates.hpp:464
void set_boundary_conditions() override
Assign boundary identifiers and attach boundary conditions.
Definition laser_melting_simonds.templates.hpp:248
SimulationLaserMeltingSimonds(std::string parameter_file, const MPI_Comm mpi_communicator)
Construct the Simonds laser-melting simulation.
Definition laser_melting_simonds.templates.hpp:107
number smoothed_heaviside(const number &distance, const number &eps)
Definition characteristic_functions.hpp:19
number tanh_characteristic_function(const number &distance, const number &eps)
Definition characteristic_functions.hpp:12
Definition laser_melting_simonds.cpp:7
static double inflow_temperature
Prescribed inflow temperature.
Definition laser_melting_simonds.hpp:75
static double height_substrate
Height of the substrate region.
Definition laser_melting_simonds.hpp:48
static double height_gas
Height of the gas region.
Definition laser_melting_simonds.hpp:56
static double eps_prefactor
Prefactor used to compute the diffuse-interface thickness.
Definition laser_melting_simonds.hpp:83
static double outlet_pressure
Prescribed outlet pressure.
Definition laser_melting_simonds.hpp:72
static double inflow_velocity
Prescribed inflow velocity for the gas phase.
Definition laser_melting_simonds.hpp:69
static double width
Width of the computational domain.
Definition laser_melting_simonds.hpp:40
static double T_initial_bottom
Initial temperature at the bottom boundary.
Definition laser_melting_simonds.hpp:66
static double T_initial_top
Initial temperature at the top boundary.
Definition laser_melting_simonds.hpp:63
static double delta_h
Definition laser_melting_simonds.hpp:60
Definition dealii_tensor.hpp:10