27 #ifndef DUBFEMHandler_HPP_
28 #define DUBFEMHandler_HPP_
30 #include <deal.II/base/exceptions.h>
31 #include <deal.II/base/quadrature.h>
33 #include <deal.II/dofs/dof_handler.h>
35 #include <deal.II/fe/fe.h>
36 #include <deal.II/fe/mapping_q1_eulerian.h>
38 #include <deal.II/lac/trilinos_vector.h>
46 #include "source/geometry/mesh_handler.hpp"
47 #include "source/init.hpp"
59 template <
class basis>
76 ,
n_quad_points(static_cast<int>(std::pow(degree + 2, lifex::dim)))
92 lifex::LinAlg::MPI::Vector
93 dubiner_to_fem(
const lifex::LinAlg::MPI::Vector &dub_solution)
const;
99 lifex::LinAlg::MPI::Vector
101 const std::string &FEM_mesh_path,
102 const std::string &subsection,
103 const MPI_Comm &mpi_comm_,
104 const unsigned int degree_fem = 1,
105 const double scaling_factor = 1)
const;
109 lifex::LinAlg::MPI::Vector
110 fem_to_dubiner(
const lifex::LinAlg::MPI::Vector &fem_solution)
const;
113 lifex::LinAlg::MPI::Vector
115 const std::string &FEM_mesh_path,
116 const std::string &subsection,
117 const MPI_Comm &mpi_comm_,
118 const unsigned int degree_fem = 1,
119 const double scaling_factor = 1)
const;
122 lifex::LinAlg::MPI::Vector
124 lifex::LinAlg::MPI::Vector dub_solution,
125 const std::shared_ptr<dealii::Function<lifex::dim>> &u_analytical)
const;
130 const double tol = 0)
const;
133 template <
class basis>
134 lifex::LinAlg::MPI::Vector
136 const lifex::LinAlg::MPI::Vector &dub_solution)
const
138 lifex::LinAlg::MPI::Vector fem_solution;
139 fem_solution.reinit(dub_solution);
148 const unsigned int degree_fem =
149 (this->poly_degree < 3) ? this->poly_degree : 2;
151 const dealii::FE_SimplexDGP<lifex::dim> fe_dg(degree_fem);
152 const std::vector<dealii::Point<lifex::dim>> support_points =
153 fe_dg.get_unit_support_points();
154 const unsigned int dofs_per_cell_fem = this->get_dofs_per_cell(degree_fem);
157 dealii::DoFHandler<lifex::dim> dof_handler_fem(
158 dof_handler.get_triangulation());
159 dof_handler_fem.distribute_dofs(fe_dg);
161 std::vector<unsigned int> dof_indices(this->dofs_per_cell);
162 std::vector<unsigned int> dof_indices_fem(dofs_per_cell_fem);
167 for (
const auto &cell : dof_handler_fem.active_cell_iterators())
169 dof_indices = dof_handler.get_dof_indices(cell);
170 cell->get_dof_indices(dof_indices_fem);
172 for (
unsigned int i = 0; i < dofs_per_cell_fem; ++i)
174 for (
unsigned int j = 0; j < this->dofs_per_cell; ++j)
176 fem_solution[dof_indices_fem[i]] +=
177 dub_solution[dof_indices[j]] *
178 this->shape_value(j, support_points[i]);
187 template <
class basis>
188 lifex::LinAlg::MPI::Vector
190 const lifex::LinAlg::MPI::Vector &dub_solution,
191 const std::string &FEM_mesh_path,
192 const std::string &subsection,
193 const MPI_Comm &mpi_comm_,
194 const unsigned int degree_fem,
195 const double scaling_factor)
const
198 lifex::utils::MeshHandler triangulation_fem(subsection, mpi_comm_);
199 AssertThrow(std::filesystem::exists(FEM_mesh_path),
200 dealii::StandardExceptions::ExcMessage(
201 "This mesh file/directory does not exist."));
202 triangulation_fem.initialize_from_file(FEM_mesh_path, scaling_factor);
203 triangulation_fem.set_element_type(
204 lifex::utils::MeshHandler::ElementType::Tet);
205 triangulation_fem.create_mesh();
207 const dealii::FE_SimplexDGP<lifex::dim> fe_dg(degree_fem);
208 const std::vector<dealii::Point<lifex::dim>> support_points =
209 fe_dg.get_unit_support_points();
210 const unsigned int dofs_per_cell_fem = this->get_dofs_per_cell(degree_fem);
213 const std::unique_ptr<dealii::MappingFE<lifex::dim>> mapping(
214 std::make_unique<dealii::MappingFE<lifex::dim>>(fe_dg));
217 dealii::DoFHandler<lifex::dim> dof_handler_fem;
218 dof_handler_fem.reinit(triangulation_fem.get());
219 dof_handler_fem.distribute_dofs(fe_dg);
222 lifex::LinAlg::MPI::Vector fem_solution;
223 dealii::IndexSet owned_dofs = dof_handler_fem.locally_owned_dofs();
224 fem_solution.reinit(owned_dofs, mpi_comm_);
227 std::vector<unsigned int> dof_indices(this->dofs_per_cell);
228 std::vector<unsigned int> dof_indices_fem(dofs_per_cell_fem);
231 const double tol = 1e-10;
235 for (
const auto &cell_fem : dof_handler_fem.active_cell_iterators())
237 cell_fem->get_dof_indices(dof_indices_fem);
238 for (
unsigned int i = 0; i < dofs_per_cell_fem; ++i)
240 dealii::Point<lifex::dim> real_support_point =
241 mapping->transform_unit_to_real_cell(cell_fem, support_points[i]);
243 for (
const auto &cell : dof_handler.active_cell_iterators())
247 if (std::abs(fem_solution[dof_indices_fem[i]]) < tol)
249 dealii::Point<lifex::dim> unit_support_point_dub =
250 mapping->transform_real_to_unit_cell(cell,
252 if (is_in_unit_cell(unit_support_point_dub, tol))
254 dof_indices = dof_handler.get_dof_indices(cell);
255 for (
unsigned int j = 0; j < this->dofs_per_cell; ++j)
257 fem_solution[dof_indices_fem[i]] +=
258 (dub_solution[dof_indices[j]] *
259 this->shape_value(j, unit_support_point_dub));
270 template <
class basis>
271 lifex::LinAlg::MPI::Vector
273 const lifex::LinAlg::MPI::Vector &fem_solution)
const
275 const dealii::FE_SimplexDGP<lifex::dim> fe_dg(this->poly_degree);
278 lifex::LinAlg::MPI::Vector dub_solution;
279 dub_solution.reinit(fem_solution);
281 std::vector<unsigned int> dof_indices(this->dofs_per_cell);
290 for (
const auto &cell : dof_handler.active_cell_iterators())
292 dof_indices = dof_handler.get_dof_indices(cell);
295 for (
unsigned int i = 0; i < this->dofs_per_cell; ++i)
297 for (
unsigned int q = 0; q < n_quad_points; ++q)
301 for (
unsigned int j = 0; j < this->dofs_per_cell; ++j)
304 fem_solution[dof_indices[j]] *
308 dub_solution[dof_indices[i]] +=
320 template <
class basis>
321 lifex::LinAlg::MPI::Vector
323 const lifex::LinAlg::MPI::Vector &fem_solution,
324 const std::string &FEM_mesh_path,
325 const std::string &subsection,
326 const MPI_Comm &mpi_comm_,
327 const unsigned int degree_fem,
328 const double scaling_factor)
const
331 lifex::utils::MeshHandler triangulation_fem(subsection, mpi_comm_);
332 AssertThrow(std::filesystem::exists(FEM_mesh_path),
333 dealii::StandardExceptions::ExcMessage(
334 "This mesh file/directory does not exist."));
335 triangulation_fem.initialize_from_file(FEM_mesh_path, scaling_factor);
336 triangulation_fem.set_element_type(
337 lifex::utils::MeshHandler::ElementType::Tet);
338 triangulation_fem.create_mesh();
340 const dealii::FE_SimplexDGP<lifex::dim> fe_dg(degree_fem);
341 const std::vector<dealii::Point<lifex::dim>> support_points =
342 fe_dg.get_unit_support_points();
343 const unsigned int dofs_per_cell_fem = this->get_dofs_per_cell(degree_fem);
346 const std::unique_ptr<dealii::MappingFE<lifex::dim>> mapping(
347 std::make_unique<dealii::MappingFE<lifex::dim>>(fe_dg));
350 dealii::DoFHandler<lifex::dim> dof_handler_fem;
351 dof_handler_fem.reinit(triangulation_fem.get());
352 dof_handler_fem.distribute_dofs(fe_dg);
355 std::vector<unsigned int> dof_indices(this->dofs_per_cell);
356 std::vector<unsigned int> dof_indices_fem(dofs_per_cell_fem);
359 const double tol = 1e-10;
363 lifex::LinAlg::MPI::Vector dub_solution;
364 dealii::IndexSet owned_dofs = dof_handler.locally_owned_dofs();
365 dub_solution.reinit(owned_dofs, mpi_comm_);
375 for (
const auto &cell : dof_handler.active_cell_iterators())
377 dof_indices = dof_handler.get_dof_indices(cell);
380 for (
unsigned int i = 0; i < this->dofs_per_cell; ++i)
382 for (
unsigned int q = 0; q < n_quad_points; ++q)
384 dealii::Point<lifex::dim> real_q =
385 mapping->transform_unit_to_real_cell(
388 for (
const auto &cell_fem :
389 dof_handler_fem.active_cell_iterators())
394 if (std::abs(eval_on_quad) < tol)
396 cell_fem->get_dof_indices(dof_indices_fem);
397 dealii::Point<lifex::dim> unit_q =
398 mapping->transform_real_to_unit_cell(cell_fem, real_q);
399 if (is_in_unit_cell(unit_q, tol))
401 for (
unsigned int j = 0; j < dofs_per_cell_fem; ++j)
403 eval_on_quad += fem_solution[dof_indices_fem[j]] *
404 fe_dg.shape_value(j, unit_q);
407 dub_solution[dof_indices[i]] +=
424 template <
class basis>
425 lifex::LinAlg::MPI::Vector
427 lifex::LinAlg::MPI::Vector dub_solution,
428 const std::shared_ptr<dealii::Function<lifex::dim>> &u_analytical)
const
432 dealii::IndexSet owned_dofs = dof_handler.locally_owned_dofs();
434 std::vector<unsigned int> dof_indices(this->dofs_per_cell);
441 for (
const auto &cell : dof_handler.active_cell_iterators())
443 dof_indices = dof_handler.get_dof_indices(cell);
446 for (
unsigned int i = 0; i < this->dofs_per_cell; ++i)
448 dub_solution[dof_indices[i]] = 0;
449 for (
unsigned int q = 0; q < n_quad_points; ++q)
454 dub_solution[dof_indices[i]] +=
466 template <
class basis>
469 const double tol)
const
473 return (unit_q[0] + unit_q[1] < 1.0 + tol && unit_q[0] > -tol &&
476 else if (lifex::dim == 3)
478 return (unit_q[0] + unit_q[1] + unit_q[2] < 1.0 + tol &&
479 unit_q[0] > -tol && unit_q[1] > -tol && unit_q[2] > -tol);
Class used to discretize analytical solutions as linear combinations of Lagrangian or Dubiner basis.
const unsigned int n_quad_points
Number of quadrature points in the volume element.
lifex::LinAlg::MPI::Vector dubiner_to_fem(const lifex::LinAlg::MPI::Vector &dub_solution) const
Conversion of a discretized solution vector from Dubiner coefficients to FEM coefficients.
lifex::LinAlg::MPI::Vector fem_to_dubiner(const lifex::LinAlg::MPI::Vector &fem_solution) const
Conversion of a discretized solution vector from FEM coefficients to Dubiner coefficients.
const DoFHandlerDG< basis > & dof_handler
Dof handler object of the problem.
lifex::LinAlg::MPI::Vector analytical_to_dubiner(lifex::LinAlg::MPI::Vector dub_solution, const std::shared_ptr< dealii::Function< lifex::dim >> &u_analytical) const
Conversion of an analytical solution to a vector of Dubiner coefficients.
bool is_in_unit_cell(const dealii::Point< lifex::dim > &unit_q, const double tol=0) const
To check if a point is inside the reference cell, needed in other methods.
Class representing the Dubiner basis functions definitions.
const double tol
Default tolerance.
Class to work with global and local degrees of freedom and their mapping.
virtual double quadrature_weight(const unsigned int q) const
Return the quadrature weight associated to the -th quadrature point.
void reinit(const typename dealii::DoFHandler< dim >::active_cell_iterator &new_cell)
Reinit objects on the current new_cell.
virtual dealii::Point< dim > quadrature_ref(const unsigned int q) const
Return the -th spatial quadrature point position on the reference element.
virtual dealii::Point< dim > quadrature_real(const unsigned int q) const
Return the -th spatial quadrature point position on the actual element.