LehrFEM++ 1.0.0
A simple Finite Element Library for teaching
dpg_tools.h
1#ifndef PROJECTS_DPG_DPG_TOOLS_H
2#define PROJECTS_DPG_DPG_TOOLS_H
3
13#include <lf/base/base.h>
14#include <lf/fe/fe.h>
15#include <lf/geometry/geometry.h>
16#include <lf/mesh/mesh.h>
17#include <lf/mesh/utils/utils.h>
18#include <lf/quad/quad.h>
19
20#include <algorithm>
21#include <cmath>
22#include <vector>
23
24#include "product_dofhandler.h"
25#include "product_element_matrix_provider.h"
26#include "product_element_vector_provider.h"
27#include "product_fe_space.h"
28
29namespace projects::dpg {
30
44std::vector<lf::quad::QuadRule> BoundaryQuadRule(lf::base::RefEl ref_el,
45 const lf::quad::QuadRule& qr);
46
54Eigen::MatrixXd OuterNormals(const lf::geometry::Geometry& geometry);
55
82 public:
90 default;
91 virtual ~PrescribedSignProvider() = default;
92
99 std::shared_ptr<const lf::mesh::Mesh> mesh_ptr)
100 : mesh_ptr_(std::move(mesh_ptr)),
101 maxElement_ptr_(std::move(
102 lf::mesh::utils::make_CodimMeshDataSet(mesh_ptr_, 1, -1))) {
103 init();
104 }
105
119 [[nodiscard]] int PrescribedSign(const lf::mesh::Entity& element,
120 const lf::mesh::Entity& edge) const;
121
122 private:
124 void init();
125
127 std::shared_ptr<const lf::mesh::Mesh> mesh_ptr_;
128
135 std::shared_ptr<lf::mesh::utils::CodimMeshDataSet<int>> maxElement_ptr_;
136};
137
154template <typename CONVECTION_COEFF>
156 const std::shared_ptr<const lf::mesh::Mesh>& mesh_p,
157 CONVECTION_COEFF beta) {
158 // flag edges on the boundary
159 auto bd_flags = lf::mesh::utils::flagEntitiesOnBoundary(mesh_p, 1);
160
161 // initialize inflow boundary flags to fals
162 lf::mesh::utils::CodimMeshDataSet<bool> inflow_boundary{mesh_p, 1, false};
163
164 // iterate over all cells:
165 for (const auto* const cell : mesh_p->Entities(0)) {
166 // query geometry
167 auto geo_ptr = cell->Geometry();
168 auto sub_entities = cell->SubEntities(1);
169
170 // calcualte normals
171 Eigen::MatrixXd normals = OuterNormals(*geo_ptr);
172
173 // iterate over all edges of the cell
174 for (int i = 0; i < cell->RefEl().NumSubEntities(1); ++i) {
175 const auto* const edge = sub_entities[i];
176
177 // check the inflow condition at the center of the edge
178 bool inflow = normals.col(i).transpose() *
179 beta(*(sub_entities[i]),
180 (Eigen::MatrixXd(1, 1) << 0.5).finished())[0] <
181 0.0;
182 inflow_boundary(*edge) = bd_flags(*edge) && inflow;
183 }
184 }
185 return inflow_boundary;
186}
187
203template <typename CONVECTION_COEFF>
205 const std::shared_ptr<const lf::mesh::Mesh>& mesh_p,
206 CONVECTION_COEFF beta) {
207 // flag all entities on the boundary:
208 auto bd_flags = lf::mesh::utils::flagEntitiesOnBoundary(mesh_p, 1);
209
210 // flag all entities on the inflow boundary:
211 auto inflow_boundary = flagEntitiesOnInflowBoundary(mesh_p, beta);
212
213 // initialize outflow flags:
214 lf::mesh::utils::CodimMeshDataSet<bool> outflow_boundary{mesh_p, 1, false};
215
216 // outflow boundary dofs are those, that lie on the boundary, but not on the
217 // inflow boundary This guarantues a partition of the boundary edges into
218 // inflow and outflow edges.
219 for (const auto* const edge : mesh_p->Entities(1)) {
220 outflow_boundary(*edge) = bd_flags(*edge) && (!inflow_boundary(*edge));
221 }
222 return outflow_boundary;
223}
224
269template <typename SCALAR, typename EDGESELECTOR_DIRICHLET,
270 typename EDGESELECTOR_NEUMANN, typename FUNCTION_G,
271 typename FUNCTION_H>
272std::vector<std::pair<bool, SCALAR>> InitEssentialConditionsFromFunctions(
273 const ProductUniformFESpace<SCALAR>& fes, size_type trace_component,
274 size_type flux_component, EDGESELECTOR_DIRICHLET&& dirichletcondflag,
275 EDGESELECTOR_NEUMANN&& neumanncondflag, FUNCTION_G&& g, FUNCTION_H&& h) {
276 // check, that the two components actually differ (necessary?)
277 LF_ASSERT_MSG(trace_component != flux_component,
278 "Boundary conditions imposed on same component");
279
280 // retrive the dofhandlers for the corresponding trace and flux components
281 const auto& trace_fes = fes.ComponentFESpace(trace_component);
282 const auto& flux_fes = fes.ComponentFESpace(flux_component);
283
284 // flag dofs on the component spaces
285 std::vector<std::pair<bool, SCALAR>> componentTraceConditions =
286 lf::fe::InitEssentialConditionFromFunction(*trace_fes, dirichletcondflag,
287 g);
288 std::vector<std::pair<bool, SCALAR>> componentFluxConditions =
289 lf::fe::InitEssentialConditionFromFunction(*flux_fes, neumanncondflag, h);
290
291 // calculate offsets to transform flags on component spaces
292 // to the full product space
293 size_type trace_offset = fes.LocGlobMap().Offset(trace_component);
294 size_type flux_offset = fes.LocGlobMap().Offset(flux_component);
295
296 std::vector<std::pair<bool, SCALAR>> EssentialConditions(
297 fes.LocGlobMap().NumDofs(), {false, SCALAR{}});
298
299 // flag dofs on product space corresponding to fixed trace dofs
300 for (size_type dof = 0; dof < trace_fes->LocGlobMap().NumDofs(); dof++) {
301 EssentialConditions[trace_offset + dof] = componentTraceConditions[dof];
302 }
303
304 // flag dofs on product space corresponding to fixed flux dofs
305 for (size_type dof = 0; dof < flux_fes->LocGlobMap().NumDofs(); dof++) {
306 EssentialConditions[flux_offset + dof] = componentFluxConditions[dof];
307 }
308
309 return EssentialConditions;
310}
311
326template <typename SCALAR>
328 const ProductUniformFEDofHandler& trial_dofh,
329 // const ProductUniformFEDofHandler& test_dofh,
330 std::shared_ptr<ProductElementMatrixProvider<SCALAR>> stiffness_provider,
331 std::shared_ptr<ProductElementMatrixProvider<SCALAR>> gramian_provider,
332 std::shared_ptr<ProductElementVectorProvider<SCALAR>> load_provider,
333 const Eigen::Matrix<SCALAR, Eigen::Dynamic, 1>& sol_vec) {
334 // retrive the underlying mesh:
335 auto mesh_p = trial_dofh.Mesh();
336
337 // retrive the number of cells, initialize the return vector
338 lf::mesh::utils::CodimMeshDataSet<SCALAR> element_errors{mesh_p, 0, 0.0};
339
340 // compute the element wise errors
341 for (const auto* const cell : mesh_p->Entities(0)) {
342 // evaluate the providers on the current cell
343 auto G = gramian_provider->Eval(*cell);
344 auto B = stiffness_provider->Eval(*cell);
345 auto l = load_provider->Eval(*cell);
346
347 // retrive local solution
348 Eigen::Matrix<SCALAR, Eigen::Dynamic, 1> local_solution(
349 trial_dofh.NumLocalDofs(*cell));
350 auto global_dofs = trial_dofh.GlobalDofIndices(*cell);
351 for (size_type i = 0; i < trial_dofh.NumLocalDofs(*cell); ++i) {
352 local_solution(i) = sol_vec(global_dofs[i]);
353 }
354
355 // evaluate posterior error on current element:
356 Eigen::Matrix<SCALAR, Eigen::Dynamic, 1> r = l - B * local_solution;
357
358 SCALAR e = std::sqrt(r.transpose() * G.ldlt().solve(r));
359 element_errors(*cell) = e;
360 }
361 return element_errors;
362}
363
373template <typename SCALAR>
375 const std::shared_ptr<const lf::mesh::Mesh>& mesh_p,
376 const lf::mesh::utils::CodimMeshDataSet<SCALAR>& local_errors) {
377 SCALAR error = 0.0;
378 for (const auto* const cell : mesh_p->Entities(0)) {
379 error += local_errors(*cell) * local_errors(*cell);
380 }
381 return std::sqrt(error);
382}
383
384} // namespace projects::dpg
385#endif // PROJECTS_DPG_DPG_TOOLS_H
Represents a reference element with all its properties.
Definition: ref_el.h:106
Interface class for shape information on a mesh cell in the spirit of parametric finite element metho...
Interface class representing a topological entity in a cellular complex
Definition: entity.h:39
A MeshDataSet that attaches data of type T to every entity of a mesh that has a specified codimension...
Represents a Quadrature Rule over one of the Reference Elements.
Definition: quad_rule.h:58
Class which allows evaluation of the function.
Definition: dpg_tools.h:81
int PrescribedSign(const lf::mesh::Entity &element, const lf::mesh::Entity &edge) const
evaluates the the function at the midpoint of the edge of cell
Definition: dpg_tools.cc:143
std::shared_ptr< const lf::mesh::Mesh > mesh_ptr_
Definition: dpg_tools.h:127
PrescribedSignProvider(PrescribedSignProvider &&) noexcept=default
std::shared_ptr< lf::mesh::utils::CodimMeshDataSet< int > > maxElement_ptr_
Definition: dpg_tools.h:135
PrescribedSignProvider(const PrescribedSignProvider &)=delete
Class providing element matrices associated with bilinear forms between cartesian/product spaces.
Class providing element vectors associated with linear forms on cartesian/product spaces.
Dofhandler for uniform finite element spaces that discretizes a cartesian/product space.
size_type NumLocalDofs(const lf::mesh::Entity &entity) const override
tells the number of degrees of freedom subordinate/_belonging_ to to an entity
size_type Offset(size_type component) const
Returns the first/smallest index of a global shape function belonging to a certain component.
std::shared_ptr< const lf::mesh::Mesh > Mesh() const override
Acess to underlying mesh object.
nonstd::span< const gdof_idx_t > GlobalDofIndices(const lf::mesh::Entity &entity) const override
access to indices of global dof's belonging to an entity
cartesian/prodcut space of finite element functions on a hybrid 2D mesh.
std::shared_ptr< const lf::uscalfe::UniformScalarFESpace< SCALAR > > ComponentFESpace(size_type component) const
Constructs a lf::uscalfe::UniformScalarFESpace that describes the finite element space associated to ...
const ProductUniformFEDofHandler & LocGlobMap() const
access to associated local-to-global map
std::vector< std::pair< bool, SCALAR > > InitEssentialConditionFromFunction(const lf::fe::ScalarFESpace< SCALAR > &fes, EDGESELECTOR &&esscondflag, FUNCTION &&g)
Initialization of flags/values for dofs of a Scalar finite element space whose values are imposed by ...
Definition: fe_tools.h:301
CodimMeshDataSet< bool > flagEntitiesOnBoundary(const std::shared_ptr< const Mesh > &mesh_p, lf::base::dim_t codim)
flag entities of a specific co-dimension located on the boundary
Definition: assemble.h:30
Contains functionality for the implementation of DPG methods.
Definition: primal_dpg.h:33
std::vector< lf::quad::QuadRule > BoundaryQuadRule(lf::base::RefEl ref_el, const lf::quad::QuadRule &qr)
Constructs a quadrature rule on the boundary of a reference element.
Definition: dpg_tools.cc:13
lf::mesh::utils::CodimMeshDataSet< bool > flagEntitiesOnOutflowBoundary(const std::shared_ptr< const lf::mesh::Mesh > &mesh_p, CONVECTION_COEFF beta)
flag all edges located on the outflow boundary
Definition: dpg_tools.h:204
lf::mesh::utils::CodimMeshDataSet< SCALAR > ElementErrorEstimators(const ProductUniformFEDofHandler &trial_dofh, std::shared_ptr< ProductElementMatrixProvider< SCALAR > > stiffness_provider, std::shared_ptr< ProductElementMatrixProvider< SCALAR > > gramian_provider, std::shared_ptr< ProductElementVectorProvider< SCALAR > > load_provider, const Eigen::Matrix< SCALAR, Eigen::Dynamic, 1 > &sol_vec)
Evaluation of the local DPG error estimators on a mesh.
Definition: dpg_tools.h:327
SCALAR EvalPosteriorError(const std::shared_ptr< const lf::mesh::Mesh > &mesh_p, const lf::mesh::utils::CodimMeshDataSet< SCALAR > &local_errors)
Evaluation of the DPG error estimator.
Definition: dpg_tools.h:374
lf::mesh::utils::CodimMeshDataSet< bool > flagEntitiesOnInflowBoundary(const std::shared_ptr< const lf::mesh::Mesh > &mesh_p, CONVECTION_COEFF beta)
flag all edges located on the inflow boundary
Definition: dpg_tools.h:155
std::vector< std::pair< bool, SCALAR > > InitEssentialConditionsFromFunctions(const ProductUniformFESpace< SCALAR > &fes, size_type trace_component, size_type flux_component, EDGESELECTOR_DIRICHLET &&dirichletcondflag, EDGESELECTOR_NEUMANN &&neumanncondflag, FUNCTION_G &&g, FUNCTION_H &&h)
Initialization of flags/values for dofs of fluxes and traces of a on a product finite element space w...
Definition: dpg_tools.h:272
lf::uscalfe::size_type size_type
Type for vector length/matrix sizes.
Definition: dpg.h:17
Eigen::MatrixXd OuterNormals(const lf::geometry::Geometry &geometry)
Compute the outer normals of a geometry object.
Definition: dpg_tools.cc:49