OGS
SurfaceFluxLocalAssembler.h
Go to the documentation of this file.
1// SPDX-FileCopyrightText: Copyright (c) OpenGeoSys Community (opengeosys.org)
2// SPDX-License-Identifier: BSD-3-Clause
3
4#pragma once
5
6#include <Eigen/Geometry>
7
15
16namespace ProcessLib
17{
19{
20public:
22
23 virtual void integrate(
24 std::size_t const element_id,
25 std::vector<GlobalVector*> const& x,
27 double const t,
28 MeshLib::Mesh const& bulk_mesh,
29 std::function<Eigen::Vector3d(std::size_t const,
30 MathLib::Point3d const&, double const,
31 std::vector<GlobalVector*> const&)>) = 0;
32};
33
34template <typename ShapeFunction, int GlobalDim>
37{
38protected:
42
43public:
55 MeshLib::Element const& surface_element,
56 std::size_t /*const local_matrix_size*/,
57 NumLib::GenericIntegrationMethod const& integration_method,
58 bool const is_axially_symmetric,
59 MeshLib::PropertyVector<std::size_t> const& bulk_element_ids,
60 MeshLib::PropertyVector<std::size_t> const& bulk_face_ids)
61 : _surface_element(surface_element),
62 _integration_method(integration_method),
63 _bulk_element_id(bulk_element_ids[surface_element.getID()]),
64 _bulk_face_id(bulk_face_ids[surface_element.getID()])
65 {
66 auto const n_integration_points =
67 _integration_method.getNumberOfPoints();
68
69 auto const shape_matrices =
72 _surface_element, is_axially_symmetric, _integration_method);
73 for (std::size_t ip = 0; ip < n_integration_points; ++ip)
74 {
76 shape_matrices[ip].detJ * shape_matrices[ip].integralMeasure);
77 }
78 }
79
93 void integrate(std::size_t const element_id,
94 std::vector<GlobalVector*> const& x,
96 double const t,
97 MeshLib::Mesh const& bulk_mesh,
98 std::function<Eigen::Vector3d(
99 std::size_t const, MathLib::Point3d const&, double const,
100 std::vector<GlobalVector*> const&)>
101 getFlux) override
102 {
103 auto const& bulk_element = *bulk_mesh.getElement(_bulk_element_id);
104 auto const surface_element_normal =
105 getSurfaceNormal(_surface_element, bulk_element);
106
107 double element_area = 0.0;
108 std::size_t const n_integration_points =
109 _integration_method.getNumberOfPoints();
110 // specific_flux[id_of_element] +=
111 // int_{\Gamma_e} \alpha \cdot flux \cdot normal \d \Gamma /
112 // element_area
113 for (std::size_t ip(0); ip < n_integration_points; ip++)
114 {
115 auto const& wp = _integration_method.getWeightedPoint(ip);
116
117 auto const bulk_element_point =
119 auto const bulk_flux =
120 getFlux(_bulk_element_id, bulk_element_point, t, x);
121 for (int component_id(0);
122 component_id < specific_flux.getNumberOfGlobalComponents();
123 ++component_id)
124 {
125 // TODO find solution for 2d case
126 double const bulk_grad_times_normal(
127 Eigen::Map<Eigen::RowVectorXd const>(bulk_flux.data(),
128 bulk_flux.size())
129 .dot(surface_element_normal));
130
131 specific_flux.getComponent(element_id, component_id) +=
132 bulk_grad_times_normal * _detJ_times_integralMeasure[ip] *
133 wp.getWeight();
134 }
135 element_area += _detJ_times_integralMeasure[ip] * wp.getWeight();
136 }
137 for (int component_id(0);
138 component_id < specific_flux.getNumberOfGlobalComponents();
139 ++component_id)
140 {
141 specific_flux.getComponent(element_id, component_id) /=
142 element_area;
143 }
144 }
145
146private:
147 static Eigen::Vector3d getSurfaceNormal(
148 MeshLib::Element const& surface_element,
149 MeshLib::Element const& bulk_element)
150 {
151 Eigen::Vector3d surface_element_normal;
152
153 if (surface_element.getGeomType() == MeshLib::MeshElemType::LINE)
154 {
155 auto const bulk_normal =
157 auto const& l0 = surface_element.getNode(0)->asEigenVector3d();
158 auto const& l1 = surface_element.getNode(1)->asEigenVector3d();
159 Eigen::Vector3d const line = l1 - l0;
160 surface_element_normal = line.cross(bulk_normal);
161 }
162 else
163 {
164 surface_element_normal =
166 }
167 surface_element_normal.normalize();
168 // At the moment (2016-09-28) the surface normal is not oriented
169 // according to the right hand rule. Thus for an intuitive flux
170 // output, i.e., inflow has positive sign, outflow has negative
171 // sign, the normal must not be multiplied by -1.
172 return surface_element_normal;
173 };
174
176
177 std::vector<double> _detJ_times_integralMeasure;
178
180 std::size_t const _bulk_element_id;
181 std::size_t const _bulk_face_id;
182};
183
184} // namespace ProcessLib
EigenFixedShapeMatrixPolicy< ShapeFunction, GlobalDim > ShapeMatrixPolicyType
Eigen::Vector3d const & asEigenVector3d() const
Definition Point3d.h:55
virtual MeshElemType getGeomType() const =0
virtual const Node * getNode(unsigned idx) const =0
static Eigen::Vector3d getSurfaceNormal(Element const &e)
Returns the surface normal of a 2D element.
Definition FaceRule.cpp:33
const Element * getElement(std::size_t idx) const
Get the element with the given index.
Definition Mesh.h:85
int getNumberOfGlobalComponents() const
PROP_VAL_TYPE & getComponent(std::size_t tuple_index, int component)
Returns the value for the given component stored in the given tuple.
virtual void integrate(std::size_t const element_id, std::vector< GlobalVector * > const &x, MeshLib::PropertyVector< double > &specific_flux, double const t, MeshLib::Mesh const &bulk_mesh, std::function< Eigen::Vector3d(std::size_t const, MathLib::Point3d const &, double const, std::vector< GlobalVector * > const &)>)=0
ShapeMatrixPolicyType< ShapeFunction, GlobalDim > ShapeMatricesType
static Eigen::Vector3d getSurfaceNormal(MeshLib::Element const &surface_element, MeshLib::Element const &bulk_element)
void integrate(std::size_t const element_id, std::vector< GlobalVector * > const &x, MeshLib::PropertyVector< double > &specific_flux, double const t, MeshLib::Mesh const &bulk_mesh, std::function< Eigen::Vector3d(std::size_t const, MathLib::Point3d const &, double const, std::vector< GlobalVector * > const &)> getFlux) override
NumLib::GenericIntegrationMethod const & _integration_method
typename ShapeMatricesType::NodalMatrixType NodalMatrixType
SurfaceFluxLocalAssembler(MeshLib::Element const &surface_element, std::size_t, NumLib::GenericIntegrationMethod const &integration_method, bool const is_axially_symmetric, MeshLib::PropertyVector< std::size_t > const &bulk_element_ids, MeshLib::PropertyVector< std::size_t > const &bulk_face_ids)
typename ShapeMatricesType::NodalVectorType NodalVectorType
MathLib::Point3d getBulkElementPoint(MeshLib::CellType const bulk_element_cell_type, std::size_t const bulk_face_id, MathLib::WeightedPoint const &point_on_face)
std::vector< typename ShapeMatricesType::ShapeMatrices, Eigen::aligned_allocator< typename ShapeMatricesType::ShapeMatrices > > initShapeMatrices(MeshLib::Element const &e, bool const is_axially_symmetric, IntegrationMethod const &integration_method)
@ N_J
calculates N, dNdr, J, and detJ
MatrixType< ShapeFunction::NPOINTS, ShapeFunction::NPOINTS > NodalMatrixType
VectorType< ShapeFunction::NPOINTS > NodalVectorType