194 const Number half_width =
width * 0.5;
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);
202 if (this->parameters.base.fe.type == FiniteElementType::FE_SimplexP or dim == 1)
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),
209 parallel::shared::Triangulation<dim>::Settings::partition_metis);
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."));
219 this->triangulation =
220 std::make_shared<parallel::distributed::Triangulation<dim>>(this->mpi_communicator);
224 if (this->parameters.base.fe.type == FiniteElementType::FE_SimplexP)
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];
232 GridGenerator::subdivided_hyper_rectangle_with_simplices(*this->triangulation,
239 GridGenerator::subdivided_hyper_rectangle(*this->triangulation,
252 this->triangulation->refine_global(this->parameters.base.global_refinements);
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;
262 const auto double_eq = [](
const Number a,
const Number b) {
return std::abs(a - b) <= 1e-10; };
265 for (
const auto &cell : this->triangulation->cell_iterators())
266 for (
const auto &face : cell->face_iterators())
267 if ((face->at_boundary()))
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);
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);
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);
290 AssertThrow(
false, ExcNotImplemented());
294 this->attach_boundary_condition(
295 {substrate_bottom_bc, std::make_shared<Functions::ConstantFunction<dim>>(
T_initial_bottom)},
299 if constexpr (std::is_same_v<CaseClass, MeltPoolCase<dim, Number>>)
304 this->attach_boundary_condition(substrate_bottom_bc,
"no_slip",
"navier_stokes_u");
306 this->attach_boundary_condition(gas_top_bc,
"no_slip",
"navier_stokes_u");
308 this->attach_boundary_condition(gas_top_bc,
"fix_pressure_constant",
"navier_stokes_p");
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,
315 this->attach_boundary_condition(substrate_inflow_wall_bc,
"no_slip",
"navier_stokes_u");
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));
325 AssertThrow(eps > 0, dealii::ExcNotImplemented());
328 this->attach_boundary_condition(substrate_bottom_bc,
"no_slip",
"navier_stokes_u");
331 this->attach_boundary_condition(gas_top_bc,
"symmetry",
"navier_stokes_u");
336 this->attach_boundary_condition(
337 {gas_outlet_bc, std::make_shared<Functions::ConstantFunction<dim>>(
outlet_pressure)},
342 this->attach_boundary_condition({gas_inflow_bc,
343 std::make_shared<InflowVelocity<dim>>()},
346 this->attach_boundary_condition({substrate_inflow_wall_bc,
347 std::make_shared<InflowVelocity<dim>>()},
350 this->attach_boundary_condition(
351 {gas_inflow_bc, std::make_shared<Functions::ConstantFunction<dim>>(
T_initial_bottom)},
354 this->attach_boundary_condition({substrate_inflow_wall_bc,
355 std::make_shared<Functions::ConstantFunction<dim>>(
361 this->attach_boundary_condition({gas_inflow_bc,
362 std::make_shared<InitialLevelSet<dim>>(eps)},
365 this->attach_boundary_condition(
366 {gas_inflow_bc, std::make_shared<dealii::Functions::ZeroFunction<dim>>()},
375 if (n_local_refinement > 0)
377 if constexpr (dim == 2)
379 const auto refinement_region =
380 BoundingBox<dim>({local_refinement_1_bottom_left, local_refinement_1_top_right});
382 const auto refinement_region_2 =
383 BoundingBox<dim>({local_refinement_2_bottom_left, local_refinement_2_top_right});
385 for (
unsigned int j = 0; j < n_local_refinement; ++j)
387 for (
auto &cell : this->triangulation->active_cell_iterators() |
388 IteratorFilters::LocallyOwnedCell())
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)))
394 cell->set_refine_flag();
398 this->triangulation->execute_coarsening_and_refinement();
402 AssertThrow(
false, ExcNotImplemented());
410 if constexpr (std::is_same_v<CaseClass, Heat::HeatTransferCase<dim, Number>>)
412 if (this->parameters.laser.model == Heat::LaserModelType::interface_projection_regularized)
418 AssertThrow((height -
width) <= 1e-10 || dim == 1,
419 ExcMessage(
"Epsilon is only defined if a square domain is considered."));
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);
428 eps, LevelSet::LevelSetType::smoothed_heaviside),
429 "prescribed_heaviside");
431 else if (this->parameters.laser.model == Heat::LaserModelType::interface_projection_sharp)
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");
439 AssertThrow(
false, ExcMessage(
"Laser model not supported."));
442 if constexpr (std::is_same_v<CaseClass, MeltPoolCase<dim, Number>>)
444 this->attach_initial_condition(std::make_shared<Functions::SignedDistance::Plane<dim>>(
445 Point<dim>(), -Point<dim>::unit_vector(dim - 1)),
451 this->attach_initial_condition(std::make_shared<Functions::ZeroFunction<dim>>(),
456 this->attach_initial_condition(
467 if (this->parameters.output.paraview.enable ==
false)
472 if ((n_time_step % this->parameters.output.write_frequency) &&
473 generic_data_out.get_time() != this->parameters.time_stepping.end_time)
475 if constexpr (std::is_same_v<CaseClass, MeltPoolCase<dim, Number>>)
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();
482 QGauss<dim> quad(generic_data_out.get_dof_handler(
"density").get_fe().tensor_degree() + 2);
484 FEValues<dim> dens_values(generic_data_out.get_mapping(),
485 generic_data_out.get_dof_handler(
"density").get_fe(),
487 update_values | update_JxW_values);
489 FEValues<dim> rho_cp_values(generic_data_out.get_mapping(),
490 generic_data_out.get_dof_handler(
"rho_cp").get_fe(),
494 FEValues<dim> vel_values(generic_data_out.get_mapping(),
495 generic_data_out.get_dof_handler(
"velocity").get_fe(),
499 FEValues<dim> temp_values(generic_data_out.get_mapping(),
500 generic_data_out.get_dof_handler(
"temperature").get_fe(),
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);
511 std::vector<Number> momentum(dim, 0);
512 Number thermal_energy = 0;
513 Number kinetic_energy = 0;
515 for (
const auto &cell :
516 this->triangulation->active_cell_iterators() | IteratorFilters::LocallyOwnedCell())
519 TriaIterator<DoFCellAccessor<dim, dim, false>> dof_cell(
520 &generic_data_out.get_dof_handler(
"density").get_triangulation(),
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);
529 TriaIterator<DoFCellAccessor<dim, dim, false>> dof_cell(
530 &generic_data_out.get_dof_handler(
"density").get_triangulation(),
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"),
542 TriaIterator<DoFCellAccessor<dim, dim, false>> dof_cell(
543 &generic_data_out.get_dof_handler(
"density").get_triangulation(),
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"),
552 for (
const unsigned int q : dens_values.quadrature_point_indices())
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)
558 momentum[d] += density[q] * velocity[q][d] * dens_values.JxW(q);
560 0.5 * density[q] * velocity[q][d] * velocity[q][d] * dens_values.JxW(q);
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();
571 Utilities::MPI::sum(mass, generic_data_out.get_vector(
"density").get_mpi_communicator());
573 for (
unsigned int d = 0; d < dim; ++d)
575 Utilities::MPI::sum(momentum[d],
576 generic_data_out.get_vector(
"density").get_mpi_communicator());
579 Utilities::MPI::sum(kinetic_energy,
580 generic_data_out.get_vector(
"density").get_mpi_communicator());
582 Utilities::MPI::sum(thermal_energy,
583 generic_data_out.get_vector(
"density").get_mpi_communicator());
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);
590 for (
unsigned int d = 0; d < dim; ++d)
591 output_table.add_value(
"momentum_" + std::to_string(d), momentum[d]);
593 if (Utilities::MPI::this_mpi_process(this->mpi_communicator) == 0)
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"));
600 output_table.write_text(output);