OGS
StokesFlowFEM.h
Go to the documentation of this file.
1 
11 #pragma once
12 
13 #include <Eigen/Dense>
14 #include <vector>
15 
16 #include "IntegrationPointData.h"
18 #include "StokesFlowProcessData.h"
19 
21 #include "MaterialLib/MPL/Medium.h"
28 
29 namespace ProcessLib::StokesFlow
30 {
31 template <typename ShapeFunctionLiquidVelocity, typename ShapeFunctionPressure,
32  typename IntegrationMethod, int GlobalDim>
34 {
35  static const int liquid_velocity_index = 0;
36  static const int pressure_index =
37  ShapeFunctionLiquidVelocity::NPOINTS * GlobalDim;
38 
39  static const int liquid_velocity_size =
40  ShapeFunctionLiquidVelocity::NPOINTS * GlobalDim;
41  static const int pressure_size = ShapeFunctionPressure::NPOINTS;
42 
47 
49 
50 public:
52  std::size_t const /*local_matrix_size*/,
53  bool const is_axially_symmetric,
54  unsigned const integration_order,
55  StokesFlowProcessData const& process_data)
56  : _element(element),
57  _is_axially_symmetric(is_axially_symmetric),
58  _integration_method(integration_order),
59  _process_data(process_data)
60  {
61  unsigned const n_integration_points =
62  _integration_method.getNumberOfPoints();
63  _ip_data.reserve(n_integration_points);
64 
65  auto const shape_matrices_v =
66  NumLib::initShapeMatrices<ShapeFunctionLiquidVelocity,
68  element, is_axially_symmetric, _integration_method);
69 
70  auto const shape_matrices_p =
71  NumLib::initShapeMatrices<ShapeFunctionPressure,
72  ShapeMatrixTypePressure, GlobalDim>(
73  element, is_axially_symmetric, _integration_method);
74 
75  for (unsigned ip = 0; ip < n_integration_points; ip++)
76  {
77  _ip_data.emplace_back(
78  shape_matrices_v[ip].N, shape_matrices_v[ip].dNdx,
79  shape_matrices_p[ip].N, shape_matrices_p[ip].dNdx,
80  _integration_method.getWeightedPoint(ip).getWeight() *
81  shape_matrices_v[ip].integralMeasure *
82  shape_matrices_v[ip].detJ);
83 
84  auto& ip_data = _ip_data[ip];
85 
86  ip_data.N_v_op = ShapeMatrixTypeLiquidVelocity::template MatrixType<
87  GlobalDim, liquid_velocity_size>::Zero(GlobalDim,
89 
90  ip_data.dNdx_v_op =
91  ShapeMatrixTypeLiquidVelocity::template MatrixType<
92  GlobalDim * GlobalDim,
93  liquid_velocity_size>::Zero(GlobalDim * GlobalDim,
95 
96  for (int i = 0; i < GlobalDim; ++i)
97  {
98  ip_data.N_v_op
99  .template block<1, liquid_velocity_size / GlobalDim>(
100  i, i * liquid_velocity_size / GlobalDim)
101  .noalias() = shape_matrices_v[ip].N;
102 
103  ip_data.dNdx_v_op
104  .template block<GlobalDim,
105  liquid_velocity_size / GlobalDim>(
106  i * GlobalDim, i * liquid_velocity_size / GlobalDim)
107  .noalias() = shape_matrices_v[ip].dNdx;
108  }
109  }
110  }
111 
112  void assemble(double const t, double const dt,
113  std::vector<double> const& local_x,
114  std::vector<double> const& /*local_xdot*/,
115  std::vector<double>& /*local_M_data*/,
116  std::vector<double>& local_K_data,
117  std::vector<double>& local_b_data) override
118  {
119  auto const local_matrix_size = liquid_velocity_size + pressure_size;
120  assert(local_x.size() == local_matrix_size);
121 
122  auto local_p = Eigen::Map<const NodalVectorType>(
123  &local_x[pressure_index], pressure_size);
124 
125  auto local_K = MathLib::createZeroedMatrix<
126  typename ShapeMatrixTypeLiquidVelocity::template MatrixType<
127  local_matrix_size, local_matrix_size>>(
128  local_K_data, local_matrix_size, local_matrix_size);
129  auto local_b = MathLib::createZeroedVector<
130  typename ShapeMatrixTypeLiquidVelocity::template VectorType<
131  local_matrix_size>>(local_b_data, local_matrix_size);
132 
133  // Get block matrices
134  // Kvv
135  auto Kvv =
136  local_K.template block<liquid_velocity_size, liquid_velocity_size>(
138  // Kvp
139  auto Kvp = local_K.template block<liquid_velocity_size, pressure_size>(
141  // kpv
142  auto Kpv = local_K.template block<pressure_size, liquid_velocity_size>(
144  // bv
145  auto bv = local_b.template segment<liquid_velocity_size>(
147 
148  unsigned const n_integration_points =
149  _integration_method.getNumberOfPoints();
150 
152  pos.setElementID(_element.getID());
153 
154  auto const& b = _process_data.specific_body_force;
155 
157 
158  // create unit vector
159  assert(GlobalDim == 2);
160  auto const identity_mat =
161  Eigen::Matrix<double, GlobalDim, GlobalDim>::Identity().eval();
162  auto const unit_vector = Eigen::Map<const Eigen::RowVectorXd>(
163  identity_mat.data(), identity_mat.size())
164  .eval();
165 
166  // Get material properties
167  auto const& medium =
168  *_process_data.media_map->getMedium(_element.getID());
169  auto const& phase = medium.phase("AqueousLiquid");
170 
171  for (unsigned ip(0); ip < n_integration_points; ++ip)
172  {
173  pos.setIntegrationPoint(ip);
174 
175  auto& ip_data = _ip_data[ip];
176 
177  auto const& N_p = ip_data.N_p;
178  auto const& N_v_op = ip_data.N_v_op;
179 
180  auto const& dNdx_v = ip_data.dNdx_v;
181  auto const& dNdx_v_op = ip_data.dNdx_v_op;
182  auto const& dNdx_p = ip_data.dNdx_p;
183 
184  auto const& w = ip_data.integration_weight;
185 
186  double p_int_pt = 0.0;
187 
188  NumLib::shapeFunctionInterpolate(local_p, N_p, p_int_pt);
189 
190  vars[static_cast<int>(
192 
193  // Use the viscosity model to compute the viscosity
194  auto const mu = phase[MaterialPropertyLib::PropertyType::viscosity]
195  .template value<double>(vars, pos, t, dt);
196 
197  // Kvv
199  {
200  // permeability
201  auto const K = MaterialPropertyLib::formEigenTensor<GlobalDim>(
203  .value(vars, pos, t, dt));
204 
205  Kvv.noalias() +=
206  w * N_v_op.transpose() * mu * K.inverse() * N_v_op;
207  }
208 
209  for (int i = 0; i < GlobalDim; ++i)
210  {
211  Kvv.template block<liquid_velocity_size / GlobalDim,
212  liquid_velocity_size / GlobalDim>(
213  i * liquid_velocity_size / GlobalDim,
214  i * liquid_velocity_size / GlobalDim)
215  .noalias() += w * dNdx_v.transpose() * mu * dNdx_v;
216  }
217 
218  // Kvp
219  Kvp.noalias() += w * N_v_op.transpose() * dNdx_p;
220 
221  // Kpv
222  Kpv.noalias() += w * N_p.transpose() * unit_vector * dNdx_v_op;
223 
224  // bv
225  bv.noalias() += w * N_v_op.transpose() * b;
226  }
227  }
228 
229  Eigen::Map<const Eigen::RowVectorXd> getShapeMatrix(
230  const unsigned integration_point) const override
231  {
232  auto const& N_p = _ip_data[integration_point].N_p;
233 
234  // assumes N_p is stored contiguously in memory
235  return Eigen::Map<const Eigen::RowVectorXd>(N_p.data(), N_p.size());
236  }
237 
239  double const /*t*/,
240  double const /*dt*/,
241  Eigen::VectorXd const& local_x,
242  Eigen::VectorXd const& /*local_x_dot*/) override
243  {
244  auto const local_p =
245  local_x.template segment<pressure_size>(pressure_index);
246 
248  ShapeFunctionPressure,
249  typename ShapeFunctionLiquidVelocity::MeshElement, GlobalDim>(
252  }
253 
254 private:
257  IntegrationMethod const _integration_method;
259 
261  ShapeMatrixTypePressure, GlobalDim,
262  ShapeFunctionLiquidVelocity::NPOINTS>,
263  Eigen::aligned_allocator<IntegrationPointData<
265  GlobalDim, ShapeFunctionLiquidVelocity::NPOINTS>>>
267 };
268 
269 } // namespace ProcessLib::StokesFlow
virtual std::size_t getID() const final
Returns the ID of the element.
Definition: Element.h:82
void setElementID(std::size_t element_id)
void setIntegrationPoint(unsigned integration_point)
std::vector< IntegrationPointData< ShapeMatrixTypeLiquidVelocity, ShapeMatrixTypePressure, GlobalDim, ShapeFunctionLiquidVelocity::NPOINTS >, Eigen::aligned_allocator< IntegrationPointData< ShapeMatrixTypeLiquidVelocity, ShapeMatrixTypePressure, GlobalDim, ShapeFunctionLiquidVelocity::NPOINTS > > > _ip_data
void assemble(double const t, double const dt, std::vector< double > const &local_x, std::vector< double > const &, std::vector< double > &, std::vector< double > &local_K_data, std::vector< double > &local_b_data) override
void computeSecondaryVariableConcrete(double const, double const, Eigen::VectorXd const &local_x, Eigen::VectorXd const &) override
Eigen::Map< const Eigen::RowVectorXd > getShapeMatrix(const unsigned integration_point) const override
Provides the shape matrix at the given integration point.
IntegrationMethod const _integration_method
StokesFlowProcessData const & _process_data
LocalAssemblerData(MeshLib::Element const &element, std::size_t const, bool const is_axially_symmetric, unsigned const integration_order, StokesFlowProcessData const &process_data)
Definition: StokesFlowFEM.h:51
ShapeMatrixPolicyType< ShapeFunctionLiquidVelocity, GlobalDim > ShapeMatrixTypeLiquidVelocity
Definition: StokesFlowFEM.h:44
typename ShapeMatrixTypePressure::NodalVectorType NodalVectorType
Definition: StokesFlowFEM.h:48
ShapeMatrixPolicyType< ShapeFunctionPressure, GlobalDim > ShapeMatrixTypePressure
Definition: StokesFlowFEM.h:46
std::array< VariableType, static_cast< int >(Variable::number_of_variables)> VariableArray
Definition: VariableType.h:108
Eigen::Map< Matrix > createZeroedMatrix(std::vector< double > &data, Eigen::MatrixXd::Index rows, Eigen::MatrixXd::Index cols)
Definition: EigenMapTools.h:32
Eigen::Map< Vector > createZeroedVector(std::vector< double > &data, Eigen::VectorXd::Index size)
void shapeFunctionInterpolate(const NodalValues &nodal_values, const ShapeMatrix &shape_matrix_N, double &interpolated_value, ScalarTypes &... interpolated_values)
Definition: Interpolation.h:79
void interpolateToHigherOrderNodes(MeshLib::Element const &element, bool const is_axially_symmetric, Eigen::MatrixBase< EigenMatrixType > const &node_values, MeshLib::PropertyVector< double > &interpolated_values_global_vector)
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)
VectorType< ShapeFunction::NPOINTS > NodalVectorType
Eigen::VectorXd const specific_body_force
an external force that applies in the bulk of the fluid, like gravity.
std::unique_ptr< MaterialPropertyLib::MaterialSpatialDistributionMap > media_map
MeshLib::PropertyVector< double > * pressure_interpolated