15 #ifndef __GRIFFITH_FORCE_ELEMENT_HPP__
16 #define __GRIFFITH_FORCE_ELEMENT_HPP__
19 #error "MoFEM need to be compiled with ADOL-C"
24 static double calMax(
double a,
double b,
double r) {
25 return (
a + b + (1 /
r) * pow(fabs(
a - b),
r)) / 2;
29 double sgn = ((
a - b) == 0) ? 0 : (((
a - b) < 0) ? -1 : 1);
30 return (1 + pow(fabs(
a - b),
r - 1) * sgn * (+1)) / 2;
90 ierr = PetscOptionsBegin(PETSC_COMM_WORLD,
"",
91 "Get Griffith element options",
"none");
93 CHKERR PetscOptionsScalar(
"-griffith_gc",
"release energy",
"",
94 block_data.
gc, &block_data.
gc, PETSC_NULL);
95 CHKERR PetscOptionsScalar(
"-griffith_r",
"release energy",
"", block_data.
r,
96 &block_data.
r, PETSC_NULL);
97 CHKERR PetscOptionsScalar(
"-griffith_E",
"stiffness",
"", block_data.
E,
98 &block_data.
E, PETSC_NULL);
99 ierr = PetscOptionsEnd();
102 MOFEM_LOG_C(
"WORLD", Sev::inform,
"### Input parameter: -griffith_E %6.4e",
104 MOFEM_LOG_C(
"WORLD", Sev::inform,
"### Input parameter: -griffith_r %6.4e",
140 boost::function<FTensor::Tensor1<TYPE *, 3>(ublas::vector<TYPE> &
v)>
143 boost::function<FTensor::Tensor1<FTensor::PackPtr<const double *, 2>, 2>(
166 for (
int nn = 0; nn != 3; ++nn) {
188 for (
int dd = 0;
dd != 3;
dd++) {
208 for (
int dd = 0;
dd != 9;
dd++)
234 const auto nb_dofs = data.getIndices().size();
239 auto dit = data.getFieldDofs().begin();
240 auto hi_dit = data.getFieldDofs().end();
241 for (
int ii = 0; dit != hi_dit; ++dit, ++ii) {
242 if (
auto dof = (*dit)) {
246 const auto side = dof->getSideNumber();
247 const auto idx = dof->getEntDofIdx();
248 const auto rank = dof->getNbDofsOnEnt();
249 if (ii != side * rank + idx)
264 int nb_dofs = data.getIndices().size();
266 for (
int dd = 0;
dd != nb_dofs;
dd++) {
269 for (
int dd = 0;
dd != nb_dofs;
dd++) {
277 const std::string &lambda_field_name) {
281 const auto bit_field_number =
282 fe_ptr->getFEMethod()->getFieldBitNumber(lambda_field_name);
284 auto data_dofs = fe_ptr->getFEMethod()->getDataDofsPtr();
285 for (
auto dit = data_dofs->get<Unique_mi_tag>().lower_bound(
286 FieldEntity::getLoBitNumberUId(bit_field_number));
287 dit != data_dofs->get<Unique_mi_tag>().upper_bound(
288 FieldEntity::getHiBitNumberUId(bit_field_number));
290 if (dit->get()->getEntType() != MBVERTEX) {
292 "DOFs only on vertices");
294 int side = dit->get()->getSideNumber();
302 const std::string &lambda_field_name) {
308 const auto bit_field_number =
309 fe_ptr->getFEMethod()->getFieldBitNumber(lambda_field_name);
311 auto data_dofs = fe_ptr->getFEMethod()->getRowDofsPtr();
312 for (
auto dit = data_dofs->get<Unique_mi_tag>().lower_bound(
313 FieldEntity::getLoBitNumberUId(bit_field_number));
314 dit != data_dofs->get<Unique_mi_tag>().upper_bound(
315 FieldEntity::getHiBitNumberUId(bit_field_number));
318 if (dit->get()->getEntType() != MBVERTEX)
320 "DOFs only on vertices");
322 int side = dit->get()->getSideNumber();
335 AuxOp(tag, block_data, common_data) {}
340 if (
type != MBVERTEX)
344 int nb_dofs = data.getIndices().size();
347 getFEMethod()->snes_f, nb_dofs, &*
rowIndices.data().begin(),
385 AuxOp(tag, block_data, common_data) {}
391 if (
type != MBVERTEX)
395 int nb_dofs = data.getIndices().size();
396 int nb_gauss_pts = data.getN().size1();
401 for (
int dd = 0;
dd != nb_dofs;
dd++) {
406 for (
int gg = 0; gg != nb_gauss_pts; gg++) {
407 double val = getGaussPts()(2, gg) * 0.5;
441 string rho_tag_name,
const double beta_gc,
447 mField(m_field),
AuxOp(tag, block_data, common_data) {}
455 if (
type != MBVERTEX)
457 const int row_nb_dofs = row_data.getIndices().size();
464 auto &inv_AB_map =
mwlsApprox->invABMap.at(getFEEntityHandle());
465 auto &influence_nodes_map =
466 mwlsApprox->influenceNodesMap.at(getFEEntityHandle());
467 auto &dm_nodes_map =
mwlsApprox->dmNodesMap[this->getFEEntityHandle()];
469 auto get_ftensor_from_vec = [](
auto &
v) {
476 int nb_dofs = row_data.getFieldData().size();
482 auto t_coords = get_ftensor_from_vec(row_data.getFieldData());
488 auto t_coeff = get_ftensor_from_vec(gc_coeff);
489 auto t_approx_base_point =
490 getFTensor1FromMat<3>(
mwlsApprox->approxBasePoint);
491 const int nb_gauss_pts = row_data.getN().size1();
493 for (
int gg = 0; gg != nb_gauss_pts; ++gg) {
494 for (
int dd = 0;
dd != nb_dofs / 3; ++
dd) {
499 t_pos(
i) = t_coords(
i);
501 for (
int dd : {0, 1, 2})
504 mwlsApprox->getInfluenceNodes() = influence_nodes_map[gg];
506 mwlsApprox->getShortenDm() = dm_nodes_map[gg];
513 const auto &diff_vals =
mwlsApprox->getDiffDataApprox();
514 for (
int ii = 0; ii != 3; ++ii) {
541 Tag *th_coords =
nullptr)
552 std::vector<double> data(verts.size() * 3, 0);
558 for (Range::iterator tit =
tRis.begin(); tit !=
tRis.end(); ++tit) {
564 int nb_dofs = num_nodes * 3;
575 for (
int dd = 0;
dd != nb_dofs;
dd++) {
581 for (
int dd = 0;
dd != nb_dofs;
dd++) {
589 (
const void **)tag_vals);
590 for (
int nn = 0; nn != 3; ++nn) {
591 for (
int dd = 0;
dd != 3; ++
dd) {
605 const double beta_gc = 0)
607 "MESH_NODE_POSITIONS",
"MESH_NODE_POSITIONS",
609 betaGC(beta_gc),
AuxOp(tag, block_data, common_data) {}
620 if (row_type != MBVERTEX) {
635 int nb_dofs = row_data.getFieldData().size();
636 for (
int dd = 0;
dd != nb_dofs;
dd++)
641 int nb_gauss_pts = row_data.getN().size1();
642 int nb_base_row = row_data.getFieldData().size() / 3;
643 int nb_base_col = col_data.getFieldData().size() / 3;
644 int row_nb_dofs = row_data.getIndices().size();
646 mat.resize(9, 9,
false);
660 const double coefficient_1 = 0.5 * pow((t_normal(
i) * t_normal(
i)), -0.5);
661 const double coefficient_2 = 0.5 * pow((t_normal(
i) * t_normal(
i)), -1.5);
665 if (rho_v.empty() || rho_v.size() != nb_base_row) {
666 rho_v.resize(nb_base_row,
false);
669 for (
int gg = 0; gg != nb_gauss_pts; gg++) {
671 double val = getGaussPts()(2, gg) * 0.5;
672 auto t_row_diff = row_data.getFTensor1DiffN<2>(gg, 0);
673 for (
int rrr = 0; rrr != nb_base_row; rrr++) {
676 &
mat(3 * rrr + 0, 0), &
mat(3 * rrr + 0, 1), &
mat(3 * rrr + 0, 2),
677 &
mat(3 * rrr + 1, 0), &
mat(3 * rrr + 1, 1), &
mat(3 * rrr + 1, 2),
678 &
mat(3 * rrr + 2, 0), &
mat(3 * rrr + 2, 1), &
mat(3 * rrr + 2, 2),
681 auto t_tan_row = calculate_derivative(t_row_diff);
682 auto t_col_diff = col_data.getFTensor1DiffN<2>(gg, 0);
684 for (
int ccc = 0; ccc != nb_base_col; ccc++) {
686 auto t_tan_col = calculate_derivative(t_col_diff);
688 t_mat(
i,
j) -= coefficient_1 *
689 (t_tan_row(
i,
l) * t_tan_col(
l,
j) +
691 t_row_diff(N1) * t_normal(
k) -
693 t_row_diff(N0) * t_normal(
k));
695 t_mat(
i,
j) += coefficient_2 * (t_tan_row(
i,
k) * t_normal(
k)) *
696 (t_tan_col(
l,
j) * t_normal(
l));
707 int col_nb_dofs = col_data.getIndices().size();
711 &*col_data.getIndices().data().begin(),
712 &*
mat.data().begin(), ADD_VALUES);
723 CommonData &common_data,
const double beta_gc)
725 "MESH_NODE_POSITIONS",
"MESH_NODE_POSITIONS",
727 betaGC(beta_gc),
AuxOp(tag, block_data, common_data) {}
738 if (row_type != MBVERTEX) {
748 int nb_dofs = row_data.getFieldData().size();
749 for (
int dd = 0;
dd != nb_dofs;
dd++)
754 int nb_gauss_pts = row_data.getN().size1();
755 int nb_base_row = row_data.getFieldData().size() / 3;
756 int nb_base_col = col_data.getFieldData().size() / 3;
758 int row_nb_dofs = row_data.getIndices().size();
759 mat.resize(9, 9,
false);
764 auto get_ftensor_from_vec = [](
auto &
v) {
770 &
m(3 *
r + 0, 3 *
c + 0), &
m(3 *
r + 0, 3 *
c + 1),
771 &
m(3 *
r + 0, 3 *
c + 2), &
m(3 *
r + 1, 3 *
c + 0),
772 &
m(3 *
r + 1, 3 *
c + 1), &
m(3 *
r + 1, 3 *
c + 2),
773 &
m(3 *
r + 2, 3 *
c + 0), &
m(3 *
r + 2, 3 *
c + 1),
774 &
m(3 *
r + 2, 3 *
c + 2));
777 for (
int gg = 0; gg != nb_gauss_pts; gg++) {
779 double val = getGaussPts()(2, gg) * 0.5;
783 auto t_griffith = get_ftensor_from_vec(auxFun.
griffithForce);
785 for (
int rrr = 0; rrr != nb_base_row; rrr++) {
789 k(
i,
j) = t_diff_rho(
j) * t_griffith(
i) *
a;
791 auto tt_mat = get_tensor2(
mat, rrr, rrr);
792 tt_mat(
i,
j) +=
k(
i,
j);
800 int col_nb_dofs = col_data.getIndices().size();
804 &*col_data.getIndices().data().begin(),
805 &*
mat.data().begin(), ADD_VALUES);
818 const std::string &lambda_field_name)
829 std::fill(&
a[0], &
a[
n], 0);
843 CHKERR VecGhostUpdateBegin(
deltaVec, ADD_VALUES, SCATTER_REVERSE);
845 CHKERR VecGhostUpdateBegin(
deltaVec, INSERT_VALUES, SCATTER_FORWARD);
846 CHKERR VecGhostUpdateEnd(
deltaVec, INSERT_VALUES, SCATTER_FORWARD);
849 MOFEM_LOG_C(
"WORLD", Sev::noisy,
"\tdelta vec nrm = %9.8e", nrm);
864 const std::string &lambda_field_name,
865 SmartPetscObj<Vec> &delta_vec)
868 AuxOp(tag, block_data, common_data),
mField(m_field),
876 if (
type != MBVERTEX) {
885 for (
int dd = 0;
dd != 9; ++
dd)
892 double delta[] = {0, 0, 0};
893 for (
int nn = 0; nn != 3; ++nn) {
898 "Element has no nodes at crack front");
902 for (
int dd = 0;
dd != 3; ++
dd) {
903 int idx = 3 * nn +
dd;
905 (data.getFieldData()[idx] - getCoords()[idx]);
922 const std::string &lambda_field_name,
923 BlockData &block_data, SmartPetscObj<Vec> &delta_vec)
936 double sum_of_delta = 0;
937 double sum_of_lambda = 0;
938 const auto bit_field_number =
941 case CTX_SNESSETFUNCTION: {
943 bit_field_number, dit)) {
944 if (
static_cast<int>(dit->get()->getPart()) ==
946 int local_idx = dit->get()->getPetscLocalDofIdx();
947 double lambda = dit->get()->getFieldData();
950 int global_idx = dit->get()->getPetscGlobalDofIdx();
951 CHKERR VecSetValue(snes_f, global_idx, val, ADD_VALUES);
955 case CTX_SNESSETJACOBIAN: {
957 bit_field_number, dit)) {
958 if (
static_cast<int>(dit->get()->getPart()) ==
960 int local_idx = dit->get()->getPetscLocalDofIdx();
961 double lambda = dit->get()->getFieldData();
965 int global_idx = dit->get()->getPetscGlobalDofIdx();
967 "Constrains on node %lu diag = %+3.5e "
968 "delta = %+3.5e lambda = %+3.5e",
969 dit->get()->getEnt(), val,
delta[local_idx],
lambda);
970 CHKERR MatSetValue(snes_B, global_idx, global_idx, val, ADD_VALUES);
971 sum_of_delta +=
delta[local_idx];
976 "Sum of delta = %+6.4e Sum of lambda = %+6.4e",
977 sum_of_delta, sum_of_lambda);
1002 const std::string &lambda_field_name)
1005 AuxOp(tag, block_data, common_data),
mField(m_field),
1015 if (
type != MBVERTEX)
1030 nF.resize(9,
false);
1032 for (
int nn = 0; nn != 3; nn++) {
1035 for (
int dd = 0;
dd != 3;
dd++) {
1036 int idx = 3 * nn +
dd;
1044 &
nF[0], ADD_VALUES);
1059 const std::string &lambda_field_name,
1060 SmartPetscObj<Vec> &delta_vec)
1062 "MESH_NODE_POSITIONS", lambda_field_name,
1066 AuxOp(tag, block_data, common_data),
mField(m_field),
1084 EntityType col_type,
1089 if (row_type != MBVERTEX || col_type != MBVERTEX)
1103 for (
int dd = 0;
dd != 9;
dd++) {
1104 double val = getCoords()[
dd];
1108 for (
int dd = 0;
dd != 9;
dd++) {
1109 double val = row_data.getFieldData()[
dd];
1115 row_data.getDiffN(0));
1119 for (
int nn = 0; nn != 3; nn++) {
1120 if (col_data.getIndices()[nn] == -1)
1124 "data inconsistency");
1126 for (
int dd = 0;
dd != 3;
dd++) {
1127 int idx = 3 * nn +
dd;
1128 if (row_data.getFieldDofs()[idx]->getEnt() !=
1129 col_data.getFieldDofs()[nn]->getEnt()) {
1131 "data inconsistency");
1138 for (
int nn = 0; nn != 3; nn++) {
1145 for (
int nn = 0; nn != 3; nn++) {
1155 "ADOL-C function evaluation with error r = %d",
r);
1159 const double *
delta;
1160 Vec delta_vec_local;
1163 CHKERR VecGetSize(delta_vec_local, &vec_size);
1165 nG_dX.resize(3, 9,
false);
1167 for (
int nn = 0; nn != 3; ++nn) {
1168 int local_idx = col_data.getLocalIndices()[nn];
1171 "data inconsistency");
1173 if (local_idx == -1)
1175 if (vec_size < local_idx) {
1179 "data inconsistency %d < %d (%d)", vec_size, local_idx,
1184 for (
int dd = 0;
dd != 9;
dd++) {
1186 nG_dX(nn,
dd) = diff_constrain * diffW;
1189 CHKERR VecRestoreArrayRead(delta_vec_local, &
delta);
1192 &*col_data.getIndices().data().begin(), 9,
1193 &*row_data.getIndices().data().begin(),
1194 &*
nG_dX.data().begin(), ADD_VALUES);
1200 d_dA.resize(9,
false);
1201 a_dA.resize(9,
false);
1206 for (
int dd = 0;
dd != 9;
dd++) {
1207 double val = getCoords()[
dd];
1211 for (
int dd = 0;
dd != 9;
dd++) {
1212 double val = row_data.getFieldData()[
dd];
1216 for (
int nn = 0; nn != 3; nn++) {
1217 double val = col_data.getFieldData()[nn];
1223 row_data.getDiffN(0));
1225 std::fill(
a_dA.begin(),
a_dA.end(), 0);
1226 for (
int nn = 0; nn != 3; nn++) {
1227 if (col_data.getIndices()[nn] == -1)
1229 for (
int dd = 0;
dd != 3;
dd++) {
1230 int idx = 3 * nn +
dd;
1234 for (
int dd = 0;
dd != 9;
dd++) {
1241 for (
int dd = 0;
dd != 9; ++
dd) {
1253 "ADOL-C function evaluation with error r = %d",
r);
1258 for (
int rr = 0; rr != 9; rr++) {
1259 for (
int cc = 0; cc != 3; cc++) {
1264 3, &*col_data.getIndices().data().begin(),
1267 nF_dX.resize(9, 9,
false);
1268 for (
int rr = 0; rr != 9; rr++) {
1269 for (
int cc = 0; cc != 9; cc++) {
1274 9, &*row_data.getIndices().data().begin(),
1275 &*
nF_dX.data().begin(), ADD_VALUES);
1322 const std::string &lambda_field_name,
1325 "MESH_NODE_POSITIONS", lambda_field_name,
1329 AuxOp(0, block_data, common_data),
mField(m_field),
1337 if (
type != MBVERTEX) {
1350 for (
int dd = 0;
dd != 9;
dd++) {
1351 int loc_idx = data.getLocalIndices()[
dd];
1352 if (loc_idx != -1) {
1368 for (
int nn = 0; nn != 3; nn++) {
1371 auto griffith_force =
1374 for (
int dd = 0;
dd != 3;
dd++) {
1375 const int idx = 3 * nn +
dd;
1401 const std::string &lambda_field_name,
1403 :
OpIntLambda(m_field, block_data, common_data, lambda_field_name,
1414 if (
type != MBVERTEX) {
1433 for (
int dd = 0;
dd != 9;
dd++) {
1434 int loc_idx = data.getLocalIndices()[
dd];
1435 if (loc_idx != -1) {
1442 for (
int dd = 0;
dd != 9;
dd++) {
1443 int loc_idx = data.getLocalIndices()[
dd];
1444 if (loc_idx != -1) {
1457 for (
int nn = 0; nn != 3; nn++) {
1460 auto griffith_force =
1465 for (
int dd = 0;
dd != 3;
dd++) {
1466 const int idx = 3 * nn +
dd;
1471 a_delta >>= d_delta;
1483 "ADOL-C function evaluation with error r = %d",
r);
1487 for (
int dd = 0;
dd != 9;
dd++) {
1499 const std::string &lambda_field_name,
1500 boost::shared_ptr<ArcLengthCtx> &arc_ptr)
1506 int nb_local =
arcPtr->mField.get_comm_rank() == 0 ? 2 : 0;
1507 int nb_ghost = nb_local ? 0 : 2;
1508 ierr = VecCreateGhostWithArray(PETSC_COMM_WORLD, nb_local, 2, nb_ghost,
1510 CHKERRABORT(PETSC_COMM_WORLD,
ierr);
1516 CHKERRABORT(PETSC_COMM_WORLD,
ierr);
1522 case CTX_SNESSETFUNCTION: {
1523 CHKERR VecAssemblyBegin(snes_f);
1524 CHKERR VecAssemblyEnd(snes_f);
1549 case CTX_SNESSETFUNCTION: {
1551 CHKERR VecSetValue(snes_f,
arcPtr->getPetscGlobalDofIdx(),
1552 arcPtr->res_lambda, ADD_VALUES);
1554 case CTX_SNESSETJACOBIAN: {
1558 CHKERR MatSetValue(snes_B,
arcPtr->getPetscGlobalDofIdx(),
1559 arcPtr->getPetscGlobalDofIdx(), 1, ADD_VALUES);
1570 case CTX_SNESSETFUNCTION: {
1571 CHKERR VecAssemblyBegin(snes_f);
1572 CHKERR VecAssemblyEnd(snes_f);
1574 case CTX_SNESSETJACOBIAN: {
1575 CHKERR VecGhostUpdateBegin(
arcPtr->ghostDiag, INSERT_VALUES,
1577 CHKERR VecGhostUpdateEnd(
arcPtr->ghostDiag, INSERT_VALUES,
1595 double alpha =
arcPtr->alpha;
1596 double beta =
arcPtr->beta;
1597 double d_lambda =
arcPtr->dLambda;
1604 CHKERR VecGhostUpdateBegin(
arcPtr->db, INSERT_VALUES, SCATTER_FORWARD);
1605 CHKERR VecGhostUpdateEnd(
arcPtr->db, INSERT_VALUES, SCATTER_FORWARD);
1614 problemPtr->getName(),
"CRACKFRONT_AREA_ELEM", (*
feIntLambda));
1619 bit_field_number, dit)) {
1620 if (
static_cast<int>(dit->get()->getPart()) !=
1621 arcPtr->mField.get_comm_rank())
1623 int idx = dit->get()->getPetscLocalDofIdx();
1624 double val = dx[idx];
1639 CHKERR VecGhostUpdateBegin(
arcPtr->db, ADD_VALUES, SCATTER_REVERSE);
1640 CHKERR VecGhostUpdateEnd(
arcPtr->db, ADD_VALUES, SCATTER_REVERSE);
1641 CHKERR VecGhostUpdateBegin(
arcPtr->db, INSERT_VALUES, SCATTER_FORWARD);
1642 CHKERR VecGhostUpdateEnd(
arcPtr->db, INSERT_VALUES, SCATTER_FORWARD);
1645 alpha * beta * beta * d_lambda * d_lambda *
arcPtr->F_lambda2;
1648 "WORLD", Sev::noisy,
1649 "\tintLambdaLambda = %9.8e intLambdaDelta = %9.8e intLambda = %9.8e",
1654 MOFEM_LOG_C(
"WORLD", Sev::noisy,
"\tdb nrm = %9.8e", nrm);
1666 CHKERR VecGhostUpdateBegin(
arcPtr->x0, INSERT_VALUES, SCATTER_FORWARD);
1667 CHKERR VecGhostUpdateEnd(
arcPtr->x0, INSERT_VALUES, SCATTER_FORWARD);
1669 Vec l_x, l_x0, l_dx;
1670 CHKERR VecGhostGetLocalForm(x, &l_x);
1674 double *x_array, *x0_array, *dx_array;
1675 CHKERR VecGetArray(l_x, &x_array);
1676 CHKERR VecGetArray(l_x0, &x0_array);
1677 CHKERR VecGetArray(l_dx, &dx_array);
1679 problemPtr->getNbLocalDofsRow() + problemPtr->getNbGhostDofsRow();
1680 for (
int i = 0;
i != size; ++
i) {
1681 dx_array[
i] = x_array[
i] - x0_array[
i];
1683 CHKERR VecRestoreArray(l_x, &x_array);
1684 CHKERR VecRestoreArray(l_x0, &x0_array);
1685 CHKERR VecRestoreArray(l_dx, &dx_array);
1687 CHKERR VecGhostRestoreLocalForm(x, &l_x);
1692 if (
arcPtr->getPetscLocalDofIdx() != -1) {
1695 arcPtr->dLambda = array[
arcPtr->getPetscLocalDofIdx()];
1696 array[
arcPtr->getPetscLocalDofIdx()] = 0;
1699 CHKERR VecGhostUpdateBegin(
arcPtr->ghosTdLambda, INSERT_VALUES,
1701 CHKERR VecGhostUpdateEnd(
arcPtr->ghosTdLambda, INSERT_VALUES,
1705 double x_nrm, x0_nrm;
1706 CHKERR VecNorm(x, NORM_2, &x_nrm);
1710 "\tx norm = %6.4e x0 norm = %6.4e dx2 = %6.4e", x_nrm, x0_nrm,
1719 #endif //__GRIFFITH_FORCE_ELEMENT_HPP__