OGS
SurfaceFluxLocalAssembler.h
Go to the documentation of this file.
1 
11 #pragma once
12 
19 
20 namespace ProcessLib
21 {
23 {
24 public:
26 
27  virtual void integrate(
28  std::size_t const element_id,
29  std::vector<GlobalVector*> const& x,
30  MeshLib::PropertyVector<double>& specific_flux,
31  double const t,
32  MeshLib::Mesh const& bulk_mesh,
33  std::function<Eigen::Vector3d(std::size_t const,
34  MathLib::Point3d const&, double const,
35  std::vector<GlobalVector*> const&)>) = 0;
36 };
37 
38 template <typename ShapeFunction, typename IntegrationMethod, int GlobalDim>
41 {
42 protected:
46 
47 public:
59  MeshLib::Element const& surface_element,
60  std::size_t /*const local_matrix_size*/,
61  bool const is_axially_symmetric,
62  unsigned const integration_order,
63  MeshLib::PropertyVector<std::size_t> const& bulk_element_ids,
64  MeshLib::PropertyVector<std::size_t> const& bulk_face_ids)
65  : _surface_element(surface_element),
66  _integration_method(integration_order),
67  _bulk_element_id(bulk_element_ids[surface_element.getID()]),
68  _bulk_face_id(bulk_face_ids[surface_element.getID()])
69  {
70  auto const n_integration_points =
71  _integration_method.getNumberOfPoints();
72 
73  auto const shape_matrices =
75  GlobalDim, NumLib::ShapeMatrixType::N_J>(
76  _surface_element, is_axially_symmetric, _integration_method);
77  for (std::size_t ip = 0; ip < n_integration_points; ++ip)
78  {
80  shape_matrices[ip].detJ * shape_matrices[ip].integralMeasure);
81  }
82  }
83 
97  void integrate(std::size_t const element_id,
98  std::vector<GlobalVector*> const& x,
99  MeshLib::PropertyVector<double>& specific_flux,
100  double const t,
101  MeshLib::Mesh const& bulk_mesh,
102  std::function<Eigen::Vector3d(
103  std::size_t const, MathLib::Point3d const&, double const,
104  std::vector<GlobalVector*> const&)>
105  getFlux) override
106  {
107  auto get_surface_normal =
108  [this, &bulk_mesh](
109  MeshLib::Element const& surface_element) -> Eigen::Vector3d {
110  Eigen::Vector3d surface_element_normal;
111  if (surface_element.getGeomType() == MeshLib::MeshElemType::LINE)
112  {
113  auto const bulk_normal = MeshLib::FaceRule::getSurfaceNormal(
114  *bulk_mesh.getElements()[_bulk_element_id]);
115  auto const l0 = Eigen::Map<Eigen::Vector3d const>(
117  auto const l1 = Eigen::Map<Eigen::Vector3d const>(
119  Eigen::Vector3d const line = l1 - l0;
120  surface_element_normal = line.cross(bulk_normal);
121  }
122  else
123  {
124  surface_element_normal =
125  MeshLib::FaceRule::getSurfaceNormal(surface_element);
126  }
127  surface_element_normal.normalize();
128  // At the moment (2016-09-28) the surface normal is not oriented
129  // according to the right hand rule. Thus for an intuitive flux
130  // output, i.e., inflow has positive sign, outflow has negative
131  // sign, the normal must not be multiplied by -1.
132  return surface_element_normal;
133  };
134  auto const surface_element_normal =
135  get_surface_normal(_surface_element);
136 
137  double element_area = 0.0;
138  std::size_t const n_integration_points =
139  _integration_method.getNumberOfPoints();
140  // specific_flux[id_of_element] +=
141  // int_{\Gamma_e} \alpha \cdot flux \cdot normal \d \Gamma /
142  // element_area
143  for (std::size_t ip(0); ip < n_integration_points; ip++)
144  {
145  auto const& wp = _integration_method.getWeightedPoint(ip);
146 
147  auto const bulk_element_point = MeshLib::getBulkElementPoint(
148  bulk_mesh, _bulk_element_id, _bulk_face_id, wp);
149  auto const bulk_flux =
150  getFlux(_bulk_element_id, bulk_element_point, t, x);
151  for (int component_id(0);
152  component_id < specific_flux.getNumberOfGlobalComponents();
153  ++component_id)
154  {
155  // TODO find solution for 2d case
156  double const bulk_grad_times_normal(
157  Eigen::Map<Eigen::RowVectorXd const>(bulk_flux.data(),
158  bulk_flux.size())
159  .dot(surface_element_normal));
160 
161  specific_flux.getComponent(element_id, component_id) +=
162  bulk_grad_times_normal * _detJ_times_integralMeasure[ip] *
163  wp.getWeight();
164  }
165  element_area += _detJ_times_integralMeasure[ip] * wp.getWeight();
166  }
167  for (int component_id(0);
168  component_id < specific_flux.getNumberOfGlobalComponents();
169  ++component_id)
170  {
171  specific_flux.getComponent(element_id, component_id) /=
172  element_area;
173  }
174  }
175 
176 private:
178 
179  std::vector<double> _detJ_times_integralMeasure;
180 
181  IntegrationMethod const _integration_method;
182  std::size_t const _bulk_element_id;
183  std::size_t const _bulk_face_id;
184 };
185 
186 } // namespace ProcessLib
const T * getCoords() const
Definition: TemplatePoint.h:75
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:40
std::vector< Element * > const & getElements() const
Get the element-vector for the mesh.
Definition: Mesh.h:98
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
typename ShapeMatricesType::NodalMatrixType NodalMatrixType
SurfaceFluxLocalAssembler(MeshLib::Element const &surface_element, std::size_t, bool const is_axially_symmetric, unsigned const integration_order, MeshLib::PropertyVector< std::size_t > const &bulk_element_ids, MeshLib::PropertyVector< std::size_t > const &bulk_face_ids)
ShapeMatrixPolicyType< ShapeFunction, GlobalDim > ShapeMatricesType
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
typename ShapeMatricesType::NodalVectorType NodalVectorType
MathLib::Point3d getBulkElementPoint(Tri const &, std::size_t const face_id, MathLib::WeightedPoint1D const &wp)
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