OGS
TwoPhaseFlowWithPPLocalAssembler-impl.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
24#pragma once
25
31
32namespace ProcessLib
33{
34namespace TwoPhaseFlowWithPP
35{
36namespace MPL = MaterialPropertyLib;
37
38template <typename ShapeFunction, int GlobalDim>
40 setInitialConditionsConcrete(Eigen::VectorXd const local_x,
41 double const t,
42 int const /*process_id*/)
43{
44 auto const& medium = *_process_data.media_map.getMedium(_element.getID());
45 unsigned const n_integration_points =
46 _integration_method.getNumberOfPoints();
47
48 auto const pc =
50 constexpr double dt = std::numeric_limits<double>::quiet_NaN();
52 pos.setElementID(_element.getID());
53 for (unsigned ip = 0; ip < n_integration_points; ip++)
54 {
55 auto const& N = _ip_data[ip].N;
56 MPL::VariableArray variables;
57 variables.capillary_pressure = N.dot(pc);
58 _saturation[ip] = medium.property(MPL::PropertyType::saturation)
59 .template value<double>(variables, pos, t, dt);
60 }
61}
62
63template <typename ShapeFunction, int GlobalDim>
65 double const t, double const dt, std::vector<double> const& local_x,
66 std::vector<double> const& /*local_x_prev*/,
67 std::vector<double>& local_M_data, std::vector<double>& local_K_data,
68 std::vector<double>& local_b_data)
69{
70 auto const local_matrix_size = local_x.size();
71
72 assert(local_matrix_size == ShapeFunction::NPOINTS * NUM_NODAL_DOF);
73
75 local_M_data, local_matrix_size, local_matrix_size);
77 local_K_data, local_matrix_size, local_matrix_size);
79 local_b_data, local_matrix_size);
80
81 auto Mgp =
82 local_M.template block<nonwet_pressure_size, nonwet_pressure_size>(
84 auto Mgpc = local_M.template block<nonwet_pressure_size, cap_pressure_size>(
86
87 auto Mlpc = local_M.template block<cap_pressure_size, cap_pressure_size>(
89
90 NodalMatrixType laplace_operator =
91 NodalMatrixType::Zero(ShapeFunction::NPOINTS, ShapeFunction::NPOINTS);
92
93 auto Kgp =
94 local_K.template block<nonwet_pressure_size, nonwet_pressure_size>(
96
97 auto Klp = local_K.template block<cap_pressure_size, nonwet_pressure_size>(
99
100 auto Klpc = local_K.template block<cap_pressure_size, cap_pressure_size>(
102
103 auto Bg = local_b.template segment<nonwet_pressure_size>(
105
106 auto Bl =
107 local_b.template segment<cap_pressure_size>(cap_pressure_matrix_index);
108
109 auto const& medium = *_process_data.media_map.getMedium(_element.getID());
110 auto const& liquid_phase = medium.phase("AqueousLiquid");
111 auto const& gas_phase = medium.phase("Gas");
112
113 unsigned const n_integration_points =
114 _integration_method.getNumberOfPoints();
115
117 pos.setElementID(_element.getID());
118
119 for (unsigned ip = 0; ip < n_integration_points; ip++)
120 {
121 auto const& w = _ip_data[ip].integration_weight;
122 auto const& N = _ip_data[ip].N;
123 auto const& dNdx = _ip_data[ip].dNdx;
124
125 NodalMatrixType M = N.transpose() * N * w;
126
127 double pc_int_pt = 0.;
128 double pn_int_pt = 0.;
129 NumLib::shapeFunctionInterpolate(local_x, _ip_data[ip].N, pn_int_pt,
130 pc_int_pt);
131
132 _pressure_wet[ip] = pn_int_pt - pc_int_pt;
133 MPL::VariableArray variables;
134
135 variables.gas_phase_pressure = pn_int_pt;
136 variables.capillary_pressure = pc_int_pt;
137 variables.temperature = _process_data.temperature(t, pos)[0];
138 variables.molar_mass =
139 gas_phase.property(MPL::PropertyType::molar_mass)
140 .template value<double>(variables, pos, t, dt);
141
142 auto const rho_nonwet =
143 gas_phase.property(MPL::PropertyType::density)
144 .template value<double>(variables, pos, t, dt);
145
146 auto const rho_wet = liquid_phase.property(MPL::PropertyType::density)
147 .template value<double>(variables, pos, t, dt);
148 auto& Sw = _saturation[ip];
149 Sw = medium.property(MPL::PropertyType::saturation)
150 .template value<double>(variables, pos, t, dt);
151
152 variables.liquid_saturation = Sw;
153 auto const dSw_dpc =
154 medium.property(MPL::PropertyType::saturation)
155 .template dValue<double>(
156 variables, MPL::Variable::capillary_pressure, pos, t, dt);
157
158 auto const porosity =
159 medium.property(MPL::PropertyType::porosity)
160 .template value<double>(variables, pos, t, dt);
161
162 auto const drhononwet_dpn =
163 gas_phase.property(MPL::PropertyType::density)
164 .template dValue<double>(
165 variables, MPL::Variable::gas_phase_pressure, pos, t, dt);
166
167 auto const k_rel_wet =
169 .template value<double>(variables, pos, t, dt);
170 auto const k_rel_nonwet =
171 medium
172 .property(
174 .template value<double>(variables, pos, t, dt);
175
176 auto const mu_nonwet =
177 gas_phase.property(MPL::PropertyType::viscosity)
178 .template value<double>(variables, pos, t, dt);
179
180 auto const lambda_nonwet = k_rel_nonwet / mu_nonwet;
181
182 auto const mu_wet = liquid_phase.property(MPL::PropertyType::viscosity)
183 .template value<double>(variables, pos, t, dt);
184
185 auto const lambda_wet = k_rel_wet / mu_wet;
186
187 auto const K = MPL::formEigenTensor<GlobalDim>(
188 medium.property(MPL::PropertyType::permeability)
189 .template value<double>(variables, pos, t, dt));
190
191 Mgp.noalias() += porosity * (1 - Sw) * drhononwet_dpn * M;
192 Mgpc.noalias() += -porosity * rho_nonwet * dSw_dpc * M;
193 Mlpc.noalias() += porosity * dSw_dpc * rho_wet * M;
194
195 laplace_operator.noalias() = dNdx.transpose() * K * dNdx * w;
196
197 Kgp.noalias() += rho_nonwet * lambda_nonwet * laplace_operator;
198 Klp.noalias() += rho_wet * lambda_wet * laplace_operator;
199 Klpc.noalias() += -rho_wet * lambda_wet * laplace_operator;
200
201 if (_process_data.has_gravity)
202 {
203 auto const& b = _process_data.specific_body_force;
204
205 NodalVectorType gravity_operator = dNdx.transpose() * K * b * w;
206 Bg.noalias() +=
207 rho_nonwet * rho_nonwet * lambda_nonwet * gravity_operator;
208 Bl.noalias() += rho_wet * rho_wet * lambda_wet * gravity_operator;
209 } // end of has gravity
210 }
211 if (_process_data.has_mass_lumping)
212 {
213 for (unsigned row = 0; row < Mgpc.cols(); row++)
214 {
215 for (unsigned column = 0; column < Mgpc.cols(); column++)
216 {
217 if (row != column)
218 {
219 Mgpc(row, row) += Mgpc(row, column);
220 Mgpc(row, column) = 0.0;
221 Mgp(row, row) += Mgp(row, column);
222 Mgp(row, column) = 0.0;
223 Mlpc(row, row) += Mlpc(row, column);
224 Mlpc(row, column) = 0.0;
225 }
226 }
227 }
228 } // end of mass-lumping
229}
230
231} // namespace TwoPhaseFlowWithPP
232} // namespace ProcessLib
void setElementID(std::size_t element_id)
std::vector< IntegrationPointData< NodalRowVectorType, GlobalDimNodalMatrixType, NodalMatrixType >, Eigen::aligned_allocator< IntegrationPointData< NodalRowVectorType, GlobalDimNodalMatrixType, NodalMatrixType > > > _ip_data
void setInitialConditionsConcrete(Eigen::VectorXd const local_x, double const t, int const process_id) override
void assemble(double const t, double const dt, std::vector< double > const &local_x, std::vector< double > const &local_x_prev, std::vector< double > &local_M_data, std::vector< double > &local_K_data, std::vector< double > &local_b_data) override
constexpr Eigen::Matrix< double, GlobalDim, GlobalDim > formEigenTensor(MaterialPropertyLib::PropertyDataType const &values)
@ relative_permeability_nonwetting_phase
Eigen::Map< Vector > createZeroedVector(std::vector< double > &data, Eigen::VectorXd::Index size)
Eigen::Map< Matrix > createZeroedMatrix(std::vector< double > &data, Eigen::MatrixXd::Index rows, Eigen::MatrixXd::Index cols)
void shapeFunctionInterpolate(const NodalValues &, const ShapeMatrix &)