40 ShapeFunctionPressure, GlobalDim>::
41 HydroMechanicsLocalAssemblerFracture(
44 std::vector<unsigned>
const& dofIndex_to_localIndex,
46 bool const is_axially_symmetric,
49 e, is_axially_symmetric, integration_method,
50 ShapeFunctionDisplacement::NPOINTS * GlobalDim +
51 ShapeFunctionPressure::NPOINTS,
52 dofIndex_to_localIndex),
53 _process_data(process_data)
57 unsigned const n_integration_points =
60 _ip_data.reserve(n_integration_points);
63 auto const shape_matrices_u =
66 e, is_axially_symmetric, integration_method);
68 auto const shape_matrices_p =
71 e, is_axially_symmetric, integration_method);
78 aperture0_node_values = frac_prop.aperture0.getNodalValuesOnElement(
83 for (
unsigned ip = 0; ip < n_integration_points; ip++)
88 auto const& sm_u = shape_matrices_u[ip];
89 auto const& sm_p = shape_matrices_p[ip];
91 ip_data.integration_weight =
92 sm_u.detJ * sm_u.integralMeasure *
95 ip_data.H_u.setZero(GlobalDim,
96 ShapeFunctionDisplacement::NPOINTS * GlobalDim);
98 GlobalDim, ShapeFunctionDisplacement::NPOINTS,
101 ip_data.N_p = sm_p.N;
102 ip_data.dNdx_p = sm_p.dNdx;
107 ip_data.w.setZero(GlobalDim);
108 ip_data.sigma_eff.setZero(GlobalDim);
111 ip_data.w_prev.resize(GlobalDim);
112 ip_data.sigma_eff_prev.resize(GlobalDim);
114 ip_data.C.resize(GlobalDim, GlobalDim);
116 ip_data.aperture0 = aperture0_node_values.dot(sm_u.N);
117 ip_data.aperture = ip_data.aperture0;
119 ip_data.permeability_state =
120 frac_prop.permeability_model->getNewState();
122 auto const initial_effective_stress =
123 _process_data.initial_fracture_effective_stress(0, x_position);
124 for (
int i = 0; i < GlobalDim; i++)
126 ip_data.sigma_eff[i] = initial_effective_stress[i];
127 ip_data.sigma_eff_prev[i] = initial_effective_stress[i];
135 ShapeFunctionPressure, GlobalDim>::
136 assembleWithJacobianConcrete(
double const t,
double const dt,
137 Eigen::VectorXd
const& local_x,
138 Eigen::VectorXd
const& local_x_prev,
139 Eigen::VectorXd& local_b,
140 Eigen::MatrixXd& local_J)
142 auto const p = local_x.segment(pressure_index, pressure_size);
143 auto const p_prev = local_x_prev.segment(pressure_index, pressure_size);
144 auto const g = local_x.segment(displacement_index, displacement_size);
146 local_x_prev.segment(displacement_index, displacement_size);
148 auto rhs_p = local_b.segment(pressure_index, pressure_size);
149 auto rhs_g = local_b.segment(displacement_index, displacement_size);
150 auto J_pp = local_J.block(pressure_index, pressure_index, pressure_size,
152 auto J_pg = local_J.block(pressure_index, displacement_index, pressure_size,
154 auto J_gp = local_J.block(displacement_index, pressure_index,
155 displacement_size, pressure_size);
156 auto J_gg = local_J.block(displacement_index, displacement_index,
157 displacement_size, displacement_size);
159 assembleBlockMatricesWithJacobian(t, dt, p, p_prev, g, g_prev, rhs_p, rhs_g,
160 J_pp, J_pg, J_gg, J_gp);
166 ShapeFunctionPressure, GlobalDim>::
167 assembleBlockMatricesWithJacobian(
168 double const t,
double const dt,
169 Eigen::Ref<const Eigen::VectorXd>
const& p,
170 Eigen::Ref<const Eigen::VectorXd>
const& p_prev,
171 Eigen::Ref<const Eigen::VectorXd>
const& g,
172 Eigen::Ref<const Eigen::VectorXd>
const& g_prev,
173 Eigen::Ref<Eigen::VectorXd> rhs_p, Eigen::Ref<Eigen::VectorXd> rhs_g,
174 Eigen::Ref<Eigen::MatrixXd> J_pp, Eigen::Ref<Eigen::MatrixXd> J_pg,
175 Eigen::Ref<Eigen::MatrixXd> J_gg, Eigen::Ref<Eigen::MatrixXd> J_gp)
177 auto const& frac_prop = *_process_data.fracture_property;
178 auto const& R = frac_prop.R;
182 auto constexpr index_normal = GlobalDim - 1;
185 ShapeMatricesTypePressure::NodalMatrixType::Zero(pressure_size,
189 ShapeMatricesTypePressure::NodalMatrixType::Zero(pressure_size,
192 typename ShapeMatricesTypeDisplacement::template MatrixType<
193 displacement_size, pressure_size>
194 Kgp = ShapeMatricesTypeDisplacement::template MatrixType<
195 displacement_size, pressure_size>::Zero(displacement_size,
199 Eigen::MatrixXd
const global2local_rotation =
200 R.template topLeftCorner<ShapeFunctionPressure::DIM, GlobalDim>();
203 global2local_rotation *
204 _process_data.specific_body_force;
209 unsigned const n_integration_points = _ip_data.size();
210 for (
unsigned ip = 0; ip < n_integration_points; ip++)
214 auto& ip_data = _ip_data[ip];
215 auto const& ip_w = ip_data.integration_weight;
216 auto const& N_p = ip_data.N_p;
217 auto const& dNdx_p = ip_data.dNdx_p;
218 auto const& H_g = ip_data.H_u;
219 auto const& identity2 =
222 auto& mat = ip_data.fracture_material;
223 auto& effective_stress = ip_data.sigma_eff;
224 auto const& effective_stress_prev = ip_data.sigma_eff_prev;
226 auto const& w_prev = ip_data.w_prev;
228 auto& state = *ip_data.material_state_variables;
229 auto& b_m = ip_data.aperture;
231 double const S = frac_prop.specific_storage(t, x_position)[0];
232 double const mu = _process_data.fluid_viscosity(t, x_position)[0];
233 auto const alpha = frac_prop.biot_coefficient(t, x_position)[0];
234 auto const rho_fr = _process_data.fluid_density(t, x_position)[0];
237 w.noalias() = R * H_g * g;
240 b_m = ip_data.aperture0 + w[index_normal];
244 "Element {:d}, gp {:d}: Fracture aperture is {:g}, but it must "
246 "non-negative. Setting it to zero.",
247 _element.getID(), ip, b_m);
251 auto const initial_effective_stress =
252 _process_data.initial_fracture_effective_stress(0, x_position);
254 Eigen::Map<typename HMatricesType::ForceVectorType const>
const stress0(
255 initial_effective_stress.data(), initial_effective_stress.size());
258 mat.computeConstitutiveRelation(
259 t, x_position, ip_data.aperture0, stress0, w_prev, w,
260 effective_stress_prev, effective_stress, C, state);
262 auto& k = ip_data.permeability;
263 k = frac_prop.permeability_model->permeability(
264 ip_data.permeability_state.get(), ip_data.aperture0, b_m);
268 frac_prop.permeability_model->dpermeability_daperture(
269 ip_data.permeability_state.get(), ip_data.aperture0, b_m);
275 H_g.transpose() * R.transpose() * effective_stress * ip_w;
276 J_gg.noalias() += H_g.transpose() * R.transpose() * C * R * H_g * ip_w;
282 H_g.transpose() * R.transpose() * alpha * identity2 * N_p * ip_w;
287 storage_p.noalias() += N_p.transpose() * b_m * S * N_p * ip_w;
288 laplace_p.noalias() +=
289 dNdx_p.transpose() * b_m * k / mu * dNdx_p * ip_w;
291 dNdx_p.transpose() * b_m * k / mu * rho_fr * gravity_vec * ip_w;
297 (dNdx_p * p + rho_fr * gravity_vec) / mu;
298 Eigen::Matrix<double, 1, displacement_size>
const mT_R_Hg =
299 identity2.transpose() * R * H_g;
301 ip_data.darcy_velocity = -k * grad_head_over_mu;
303 N_p.transpose() * S * N_p * (p - p_prev) / dt * mT_R_Hg * ip_w;
305 dNdx_p.transpose() * k * grad_head_over_mu * mT_R_Hg * ip_w;
306 J_pg.noalias() += dNdx_p.transpose() * b_m * dk_db * grad_head_over_mu *
311 J_gp.noalias() -= Kgp;
314 J_pp.noalias() += laplace_p + storage_p / dt;
317 J_pg.noalias() += Kgp.transpose() / dt;
320 rhs_p.noalias() -= laplace_p * p + storage_p * (p - p_prev) / dt +
321 Kgp.transpose() * (g - g_prev) / dt;
324 rhs_g.noalias() -= -Kgp * p;
331 GlobalDim>::postTimestepConcreteWithVector(
const double t,
333 Eigen::VectorXd
const& local_x)
335 auto const nodal_g = local_x.segment(displacement_index, displacement_size);
337 auto const& frac_prop = *_process_data.fracture_property;
338 auto const& R = frac_prop.R;
341 auto constexpr index_normal = GlobalDim - 1;
344 auto const e_id = _element.getID();
347 unsigned const n_integration_points = _ip_data.size();
348 for (
unsigned ip = 0; ip < n_integration_points; ip++)
352 auto& ip_data = _ip_data[ip];
353 auto const& H_g = ip_data.H_u;
354 auto& mat = ip_data.fracture_material;
355 auto& effective_stress = ip_data.sigma_eff;
356 auto const& effective_stress_prev = ip_data.sigma_eff_prev;
358 auto const& w_prev = ip_data.w_prev;
360 auto& state = *ip_data.material_state_variables;
361 auto& b_m = ip_data.aperture;
364 w.noalias() = R * H_g * nodal_g;
367 b_m = ip_data.aperture0 + w[index_normal];
371 "Element {:d}, gp {:d}: Fracture aperture is {:g}, but it is "
372 "expected to be non-negative. Setting it to zero now.",
373 _element.getID(), ip, b_m);
377 auto const initial_effective_stress =
378 _process_data.initial_fracture_effective_stress(0, x_position);
380 Eigen::Map<typename HMatricesType::ForceVectorType const>
const stress0(
381 initial_effective_stress.data(), initial_effective_stress.size());
384 mat.computeConstitutiveRelation(
385 t, x_position, ip_data.aperture0, stress0, w_prev, w,
386 effective_stress_prev, effective_stress, C, state);
392 HMatricesType::ForceVectorType::Zero(GlobalDim);
394 HMatricesType::ForceVectorType::Zero(GlobalDim);
397 double ele_Fs = -std::numeric_limits<double>::max();
398 for (
auto const& ip : _ip_data)
400 ele_b += ip.aperture;
401 ele_k += ip.permeability;
403 ele_sigma_eff += ip.sigma_eff;
404 ele_velocity += ip.darcy_velocity;
406 ele_Fs, ip.material_state_variables->getShearYieldFunctionValue());
408 ele_b /=
static_cast<double>(n_integration_points);
409 ele_k /=
static_cast<double>(n_integration_points);
410 ele_w /=
static_cast<double>(n_integration_points);
411 ele_sigma_eff /=
static_cast<double>(n_integration_points);
412 ele_velocity /=
static_cast<double>(n_integration_points);
413 auto const element_id = _element.getID();
414 (*_process_data.mesh_prop_b)[element_id] = ele_b;
415 (*_process_data.mesh_prop_k_f)[element_id] = ele_k;
417 Eigen::Map<GlobalDimVectorType>(
418 &(*_process_data.element_fracture_stresses)[e_id * GlobalDim]) =
421 Eigen::Map<GlobalDimVectorType>(
422 &(*_process_data.element_fracture_velocities)[e_id * GlobalDim]) =
425 Eigen::Map<GlobalDimVectorType>(
426 &(*_process_data.element_local_jumps)[e_id * GlobalDim]) = ele_w;
428 (*_process_data.mesh_prop_fracture_shear_failure)[element_id] = ele_Fs;