20 template <
typename ShapeFunction,
typename IntegrationMethod,
22 void PhaseFieldLocalAssembler<ShapeFunction, IntegrationMethod,
24 assembleWithJacobianForStaggeredScheme(
25 double const t,
double const dt, Eigen::VectorXd
const& local_x,
26 Eigen::VectorXd
const& ,
const double ,
27 const double ,
int const process_id,
28 std::vector<double>& ,
29 std::vector<double>& ,
30 std::vector<double>& local_b_data, std::vector<double>& local_Jac_data)
33 if (process_id == phase_process_id)
35 assembleWithJacobianPhaseFieldEquations(t, dt, local_x, local_b_data,
41 assembleWithJacobianForDeformationEquations(t, dt, local_x, local_b_data,
45 template <
typename ShapeFunction,
typename IntegrationMethod,
49 assembleWithJacobianForDeformationEquations(
50 double const t,
double const dt, Eigen::VectorXd
const& local_x,
51 std::vector<double>& local_b_data, std::vector<double>& local_Jac_data)
53 using DeformationMatrix =
54 typename ShapeMatricesType::template MatrixType<displacement_size,
56 auto const d = local_x.template segment<phasefield_size>(phasefield_index);
58 local_x.template segment<displacement_size>(displacement_index);
60 auto local_Jac = MathLib::createZeroedMatrix<DeformationMatrix>(
61 local_Jac_data, displacement_size, displacement_size);
63 auto local_rhs = MathLib::createZeroedVector<DeformationVector>(
64 local_b_data, displacement_size);
69 auto local_pressure = 0.0;
70 if (_process_data.crack_pressure)
72 local_pressure = _process_data.unity_pressure;
75 int const n_integration_points = _integration_method.getNumberOfPoints();
76 for (
int ip = 0; ip < n_integration_points; ip++)
79 auto const& w = _ip_data[ip].integration_weight;
80 auto const& N = _ip_data[ip].N;
81 auto const& dNdx = _ip_data[ip].dNdx;
84 NumLib::interpolateXCoordinate<ShapeFunction, ShapeMatricesType>(
89 ShapeFunction::NPOINTS,
91 dNdx, N, x_coord, _is_axially_symmetric);
93 auto& eps = _ip_data[ip].eps;
94 eps.noalias() = B * u;
95 double const k = _process_data.residual_stiffness(t, x_position)[0];
96 double const d_ip = N.dot(d);
97 double const degradation = d_ip * d_ip * (1 - k) + k;
98 _ip_data[ip].updateConstitutiveRelation(t, x_position, dt, u,
101 auto& sigma = _ip_data[ip].sigma;
102 auto const& C_tensile = _ip_data[ip].C_tensile;
103 auto const& C_compressive = _ip_data[ip].C_compressive;
105 typename ShapeMatricesType::template MatrixType<DisplacementDim,
107 N_u = ShapeMatricesType::template MatrixType<
108 DisplacementDim, displacement_size>::Zero(DisplacementDim,
111 for (
int i = 0; i < DisplacementDim; ++i)
113 N_u.template block<1, displacement_size / DisplacementDim>(
114 i, i * displacement_size / DisplacementDim)
118 auto const rho_sr = _process_data.solid_density(t, x_position)[0];
119 auto const& b = _process_data.specific_body_force;
121 local_rhs.noalias() -=
122 (B.transpose() * sigma - N_u.transpose() * rho_sr * b -
123 local_pressure * N_u.transpose() * dNdx * d) *
126 local_Jac.noalias() +=
127 B.transpose() * (degradation * C_tensile + C_compressive) * B * w;
131 template <
typename ShapeFunction,
typename IntegrationMethod,
135 assembleWithJacobianPhaseFieldEquations(
double const t,
double const dt,
136 Eigen::VectorXd
const& local_x,
137 std::vector<double>& local_b_data,
138 std::vector<double>& local_Jac_data)
140 auto const d = local_x.template segment<phasefield_size>(phasefield_index);
142 local_x.template segment<displacement_size>(displacement_index);
144 auto local_Jac = MathLib::createZeroedMatrix<PhaseFieldMatrix>(
145 local_Jac_data, phasefield_size, phasefield_size);
146 auto local_rhs = MathLib::createZeroedVector<PhaseFieldVector>(
147 local_b_data, phasefield_size);
152 auto local_pressure = 0.0;
153 if (_process_data.crack_pressure)
155 local_pressure = _process_data.unity_pressure;
157 else if (_process_data.hydro_crack)
159 local_pressure = _process_data.pressure;
162 int const n_integration_points = _integration_method.getNumberOfPoints();
163 for (
int ip = 0; ip < n_integration_points; ip++)
166 auto const& w = _ip_data[ip].integration_weight;
167 auto const& N = _ip_data[ip].N;
168 auto const& dNdx = _ip_data[ip].dNdx;
170 double const gc = _process_data.crack_resistance(t, x_position)[0];
171 double const ls = _process_data.crack_length_scale(t, x_position)[0];
173 double const k = _process_data.residual_stiffness(t, x_position)[0];
174 double const d_ip = N.dot(d);
175 double const degradation = d_ip * d_ip * (1 - k) + k;
177 NumLib::interpolateXCoordinate<ShapeFunction, ShapeMatricesType>(
181 ShapeFunction::NPOINTS,
183 dNdx, N, x_coord, _is_axially_symmetric);
185 auto& eps = _ip_data[ip].eps;
186 eps.noalias() = B * u;
187 _ip_data[ip].updateConstitutiveRelation(t, x_position, dt, u,
190 auto const& strain_energy_tensile = _ip_data[ip].strain_energy_tensile;
192 auto& ip_data = _ip_data[ip];
193 ip_data.strain_energy_tensile = strain_energy_tensile;
195 typename ShapeMatricesType::template MatrixType<DisplacementDim,
197 N_u = ShapeMatricesType::template MatrixType<
198 DisplacementDim, displacement_size>::Zero(DisplacementDim,
201 for (
int i = 0; i < DisplacementDim; ++i)
203 N_u.template block<1, displacement_size / DisplacementDim>(
204 i, i * displacement_size / DisplacementDim)
208 local_Jac.noalias() +=
209 (2 * N.transpose() * N * strain_energy_tensile) * w;
211 local_rhs.noalias() -=
212 (N.transpose() * N * d * 2 * strain_energy_tensile -
213 local_pressure * dNdx.transpose() * N_u * u) *
216 switch (_process_data.phasefield_model)
220 local_Jac.noalias() +=
221 gc * 0.75 * dNdx.transpose() * dNdx * ls * w;
223 local_rhs.noalias() -=
225 (-0.375 * N.transpose() / ls +
226 0.75 * dNdx.transpose() * dNdx * ls * d) *
232 local_Jac.noalias() +=
234 (N.transpose() * N / ls + dNdx.transpose() * dNdx * ls) * w;
236 local_rhs.noalias() -=
238 ((N.transpose() * N / ls + dNdx.transpose() * dNdx * ls) *
240 N.transpose() / ls) *
248 template <
typename ShapeFunction,
typename IntegrationMethod,
252 computeCrackIntegral(std::size_t mesh_item_id,
253 std::vector<std::reference_wrapper<
256 double& crack_volume,
259 assert(cpl_xs !=
nullptr);
261 std::vector<std::vector<GlobalIndexType>> indices_of_processes;
262 indices_of_processes.reserve(dof_tables.size());
263 std::transform(dof_tables.begin(), dof_tables.end(),
264 std::back_inserter(indices_of_processes),
266 { return NumLib::getIndices(mesh_item_id, dof_table); });
268 auto local_coupled_xs =
270 assert(local_coupled_xs.size() == displacement_size + phasefield_size);
272 auto const d = Eigen::Map<PhaseFieldVector const>(
273 &local_coupled_xs[phasefield_index], phasefield_size);
274 auto const u = Eigen::Map<DeformationVector const>(
275 &local_coupled_xs[displacement_index], displacement_size);
280 int const n_integration_points = _integration_method.getNumberOfPoints();
281 for (
int ip = 0; ip < n_integration_points; ip++)
284 auto const& w = _ip_data[ip].integration_weight;
285 auto const& N = _ip_data[ip].N;
286 auto const& dNdx = _ip_data[ip].dNdx;
288 typename ShapeMatricesType::template MatrixType<DisplacementDim,
290 N_u = ShapeMatricesType::template MatrixType<
291 DisplacementDim, displacement_size>::Zero(DisplacementDim,
294 for (
int i = 0; i < DisplacementDim; ++i)
296 N_u.template block<1, displacement_size / DisplacementDim>(
297 i, i * displacement_size / DisplacementDim)
301 crack_volume += (N_u * u).dot(dNdx * d) * w;
305 template <
typename ShapeFunction,
typename IntegrationMethod,
309 computeEnergy(std::size_t mesh_item_id,
310 std::vector<std::reference_wrapper<
313 double& elastic_energy,
double& surface_energy,
314 double& pressure_work,
317 assert(cpl_xs !=
nullptr);
319 std::vector<std::vector<GlobalIndexType>> indices_of_processes;
320 indices_of_processes.reserve(dof_tables.size());
321 std::transform(dof_tables.begin(), dof_tables.end(),
322 std::back_inserter(indices_of_processes),
324 { return NumLib::getIndices(mesh_item_id, dof_table); });
326 auto const local_coupled_xs =
328 assert(local_coupled_xs.size() == displacement_size + phasefield_size);
330 auto const d = Eigen::Map<PhaseFieldVector const>(
331 &local_coupled_xs[phasefield_index], phasefield_size);
332 auto const u = Eigen::Map<DeformationVector const>(
333 &local_coupled_xs[displacement_index], displacement_size);
338 double element_elastic_energy = 0.0;
339 double element_surface_energy = 0.0;
340 double element_pressure_work = 0.0;
342 int const n_integration_points = _integration_method.getNumberOfPoints();
343 for (
int ip = 0; ip < n_integration_points; ip++)
346 auto const& w = _ip_data[ip].integration_weight;
347 auto const& N = _ip_data[ip].N;
348 auto const& dNdx = _ip_data[ip].dNdx;
349 double const d_ip = N.dot(d);
350 auto pressure_ip = _process_data.pressure;
351 double const gc = _process_data.crack_resistance(t, x_position)[0];
352 double const ls = _process_data.crack_length_scale(t, x_position)[0];
354 typename ShapeMatricesType::template MatrixType<DisplacementDim,
356 N_u = ShapeMatricesType::template MatrixType<
357 DisplacementDim, displacement_size>::Zero(DisplacementDim,
360 for (
int i = 0; i < DisplacementDim; ++i)
362 N_u.template block<1, displacement_size / DisplacementDim>(
363 i, i * displacement_size / DisplacementDim)
367 element_elastic_energy += _ip_data[ip].elastic_energy * w;
369 switch (_process_data.phasefield_model)
373 element_surface_energy +=
375 ((1 - d_ip) / ls + (dNdx * d).dot((dNdx * d)) * ls) * w;
381 element_surface_energy += 0.5 * gc *
382 ((1 - d_ip) * (1 - d_ip) / ls +
383 (dNdx * d).dot((dNdx * d)) * ls) *
389 if (_process_data.crack_pressure)
391 element_pressure_work += pressure_ip * (N_u * u).dot(dNdx * d) * w;
396 int const n_all_nodes = indices_of_processes[1].size();
397 int const n_regular_nodes = std::count_if(
398 begin(indices_of_processes[1]), end(indices_of_processes[1]),
400 if (n_all_nodes != n_regular_nodes)
402 element_elastic_energy *=
403 static_cast<double>(n_regular_nodes) / n_all_nodes;
404 element_surface_energy *=
405 static_cast<double>(n_regular_nodes) / n_all_nodes;
406 element_pressure_work *=
407 static_cast<double>(n_regular_nodes) / n_all_nodes;
410 elastic_energy += element_elastic_energy;
411 surface_energy += element_surface_energy;
412 pressure_work += element_pressure_work;
GlobalMatrix::IndexType GlobalIndexType
Global vector based on Eigen vector.
void setElementID(std::size_t element_id)
void setIntegrationPoint(unsigned integration_point)
MatrixType< _kelvin_vector_size, _number_of_dof > BMatrixType
BMatrixType computeBMatrix(DNDX_Type const &dNdx, N_Type const &N, const double radius, const bool is_axially_symmetric)
Fills a B-matrix based on given shape function dN/dx values.
std::vector< double > getCoupledLocalSolutions(std::vector< GlobalVector * > const &global_solutions, std::vector< std::vector< GlobalIndexType >> const &indices)
std::vector< GlobalVector * > const & coupled_xs
References to the current solutions of the coupled processes.