v0.16.0
Loading...
Searching...
No Matches
MatVolumeLengthQuality.cpp
Go to the documentation of this file.
1/**
2 * @file MatVolumeLengthQuality.cpp
3 * @brief ADOL-C implementation of the volume-length quality material
4 * @version 0.1
5 * @date 2026-04-03
6 *
7 * @copyright Copyright (c) 2026
8 *
9 */
10
11namespace MatOps {
12
13static const char *VolumeLengthQualityTypeNames[] = {
14 "QUALITY", "BARRIER_AND_QUALITY", "BARRIER_AND_CHANGE_QUALITY",
15 "BARRIER_AND_CHANGE_QUALITY_SCALED_BY_VOLUME"};
16
17template <int DIM>
19 using MatElasticImpl<DIM>::MatElasticImpl;
20
22
23 static inline constexpr std::array<std::array<int, 2>, 6> edgeNodes = {
24 std::array<int, 2>{0, 1}, std::array<int, 2>{0, 2},
25 std::array<int, 2>{0, 3}, std::array<int, 2>{1, 2},
26 std::array<int, 2>{1, 3}, std::array<int, 2>{2, 3}};
27
28 MoFEMErrorCode getOptions(MoFEM::Interface *m_field_ptr = nullptr) override {
30
31 MOFEM_LOG_CHANNEL("WORLD");
32
33 PetscOptionsBegin(PETSC_COMM_WORLD, "",
34 "Get VolumeLengthQuality material options", "none");
35 CHKERR PetscOptionsEList(
36 "-volume_length_type", "Volume length quality type", "",
38 VolumeLengthQualityTypeNames[tYpe], &tYpe, PETSC_NULLPTR);
39 CHKERR PetscOptionsScalar("-volume_length_alpha",
40 "volume length alpha parameter", "", aLpha,
41 &aLpha, PETSC_NULLPTR);
42 CHKERR PetscOptionsScalar("-volume_length_gamma",
43 "volume length parameter (barrier)", "", gAmma,
44 &gAmma, PETSC_NULLPTR);
45 PetscOptionsEnd();
46
47 MOFEM_TAG_AND_LOG("WORLD", Sev::inform, "VolumeLengthQuality")
48 << " type = " << VolumeLengthQualityTypeNames[tYpe]
49 << " alpha = " << aLpha << " gamma = " << gAmma;
50
51 mFieldPtr = m_field_ptr;
52
54 };
55
56 MoFEMErrorCode setParams(FEMethod *fe_ptr, int gg) override {
58 (void)gg;
59 const auto ent = fe_ptr->getFEEntityHandle();
60
61 if (mFieldPtr == nullptr) {
62 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
63 "MoFEM interface pointer not set");
64 }
65
66 const EntityHandle *conn = nullptr;
67 int num_nodes = 0;
68 CHKERR mFieldPtr->get_moab().get_connectivity(ent, conn, num_nodes, true);
69 if (PetscUnlikely(num_nodes != 4)) {
70 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
71 "VolumeLengthQuality is implemented for 4-node tetrahedra only");
72 }
73
74 CHKERR mFieldPtr->get_moab().get_coords(conn, num_nodes, coordsTet.data());
75 set_param_vec(A::tAg, coordsTet.size(), coordsTet.data());
76
78 }
79
80 MoFEMErrorCode recordTape() override {
82 static_assert(DIM == 3,
83 "MatVolumeLengthQuality is implemented for 3D only");
84
85 A::matOpsDataPtr->insertCommonData("grad", MatrixDouble());
86 A::matOpsDataPtr->insertCommonData("P", MatrixDouble());
87 A::matOpsDataPtr->insertCommonData("P_dF", MatrixDouble());
88
89 A::matOpsDataPtr->insertActiveData("F", MatrixDouble());
90 A::matOpsDataPtr->insertDependentData("P", MatrixDouble());
91 A::matOpsDataPtr->insertDependentDerivativesData("P_dF", MatrixDouble());
92
93 A::matOpsDataPtr->getActiveDataPtr("F")->resize(DIM, DIM, false);
94 A::matOpsDataPtr->getDependentDataPtr("P")->resize(DIM, DIM, false);
95
96 auto t_F = getFTensor2FromPtr<DIM, DIM>(
97 A::matOpsDataPtr->getActiveDataPtr("F")->data().data());
98 auto t_P = getFTensor2FromPtr<DIM, DIM>(
99 A::matOpsDataPtr->getDependentDataPtr("P")->data().data());
100
102
103 FTENSOR_INDEX(DIM, i);
104 FTENSOR_INDEX(DIM, j);
105 FTENSOR_INDEX(DIM, I);
106 FTENSOR_INDEX(DIM, J);
107
108 // That assumes that nodal positions are approximated.
109 t_F(i, J) = t_kd(i, J);
110
118
119 adouble det_aF;
120
121 trace_on(A::tAg);
122
123 std::array<adouble, 12> refCoords;
124 for (auto dd = 0; dd != 12; ++dd) {
125 refCoords[dd] = mkparam(coordsTet[dd]);
126 }
127
128 ta_F(i, J) <<= t_F(i, J);
129 det_aF = determinantTensor(ta_F);
130 CHKERR invertTensor(ta_F, det_aF, ta_invF);
131
132 const auto x00 = refCoords[0];
133 const auto x01 = refCoords[1];
134 const auto x02 = refCoords[2];
135 const auto x10 = refCoords[3];
136 const auto x11 = refCoords[4];
137 const auto x12 = refCoords[5];
138 const auto x20 = refCoords[6];
139 const auto x21 = refCoords[7];
140 const auto x22 = refCoords[8];
141 const auto x30 = refCoords[9];
142 const auto x31 = refCoords[10];
143 const auto x32 = refCoords[11];
144
145 const auto ax = x10 - x00;
146 const auto ay = x11 - x01;
147 const auto az = x12 - x02;
148
149 const auto bx = x20 - x00;
150 const auto by = x21 - x01;
151 const auto bz = x22 - x02;
152
153 const auto cx = x30 - x00;
154 const auto cy = x31 - x01;
155 const auto cz = x32 - x02;
156
157 const adouble signed_volume =
158 (ax * (by * cz - bz * cy) - ay * (bx * cz - bz * cx) +
159 az * (bx * cy - by * cx)) /
160 6.0;
161
162 dX_dChiT(i, J) = 0.0;
163
164 adouble lrms_squared = 0.0;
165 adouble lrms_squared0 = 0.0;
166
167 for (auto ee = 0; ee != 6; ++ee) {
168 for (auto dd = 0; dd != DIM; ++dd) {
169 delta_chi(dd) =
170 refCoords[3 * edgeNodes[ee][0] + dd] -
171 refCoords[3 * edgeNodes[ee][1] + dd];
172 }
173
174 delta_X(i) = ta_F(i, J) * delta_chi(J);
175
176 lrms_squared += (1. / 6.) * delta_X(i) * delta_X(i);
177 lrms_squared0 += (1. / 6.) * delta_chi(I) * delta_chi(I);
178 dX_dChiT(i, I) += delta_X(i) * delta_chi(I);
179 }
180
181 Q(i, j) = ta_invF(j, i) - 0.5 * dX_dChiT(i, j) / lrms_squared;
182
183 const adouble lrms_cubed0 = lrms_squared0 * sqrt(lrms_squared0);
184 const adouble b =
185 det_aF / (lrms_squared * sqrt(lrms_squared) / lrms_cubed0);
186 const adouble current_volume = det_aF * signed_volume;
187 const adouble q =
188 6. * sqrt(2.) * current_volume / (lrms_squared * sqrt(lrms_squared));
189
190 switch (tYpe) {
191 case QUALITY:
192 ta_P(i, J) = q * Q(i, J);
193 break;
194 case BARRIER_AND_QUALITY: {
195 const adouble t_mp = q / (1.0 - gAmma) - 1.0 / (q - gAmma);
196 ta_P(i, J) = t_mp * Q(i, J);
197 break;
198 }
200 const adouble t_mp = b / (1.0 - gAmma) - 1.0 / (b - gAmma);
201 ta_P(i, J) = t_mp * Q(i, J);
202 break;
203 }
205 adouble t_mp = current_volume;
206 t_mp *= b / (1.0 - gAmma) - 1.0 / (b - gAmma);
207 ta_P(i, J) = t_mp * Q(i, J);
208 break;
209 }
210 default:
211 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
212 "Unknown volume-length-quality type");
213 }
214
215 ta_P(i, J) *= aLpha / signed_volume;
216 ta_P(i, J) >>= t_P(i, J);
217
218 trace_off();
219
221 }
222
223protected:
225 double aLpha = 1.0;
226 double gAmma = 0.0;
227 std::array<double, 12> coordsTet = {
228
229 0.0, 0.0, 0.0,
230
231 1.0, 0.0, 0.0,
232
233 0.0, 1.0, 0.0,
234
235 0.0, 0.0, 1.0};
237};
238
239template <>
240boost::shared_ptr<PhysicalEquations>
242 boost::shared_ptr<MatOpsData> mat_ops_data_ptr, int tag) {
243 return boost::make_shared<MatVolumeLengthQuality<3>>(mat_ops_data_ptr, tag);
244}
245
246} // namespace MatOps
#define MOFEM_TAG_AND_LOG(channel, severity, tag)
Tag and log in channel.
#define FTENSOR_INDEX(DIM, I)
Kronecker Delta class.
#define MoFEMFunctionBegin
First executable line of each MoFEM function, used for error handling. Final line of MoFEM functions ...
@ MOFEM_DATA_INCONSISTENCY
Definition definitions.h:31
#define MoFEMFunctionReturn(a)
Last executable line of each PETSc function used for error handling. Replaces return()
#define CHKERR
Inline error check.
constexpr auto t_kd
#define MOFEM_LOG_CHANNEL(channel)
Set and reset channel.
FTensor::Index< 'i', SPACE_DIM > i
FTensor::Index< 'J', DIM1 > J
Definition level_set.cpp:30
FTensor::Index< 'j', 3 > j
static const char * VolumeLengthQualityTypeNames[]
@ BARRIER_AND_CHANGE_QUALITY_SCALED_BY_VOLUME
@ BARRIER_AND_QUALITY
@ LASTOP_VOLUMELENGTHQUALITYTYPE
@ BARRIER_AND_CHANGE_QUALITY
boost::shared_ptr< PhysicalEquations > createMatOpsPhysicalEquationsPtr< ELASTICITY::VOLUMELENGTHQUALITY, MODEL_3D >(boost::shared_ptr< MatOpsData > mat_ops_data_ptr, int tag)
constexpr IntegrationType I
MoFEMErrorCode setParams(FEMethod *fe_ptr, int gg) override
MoFEMErrorCode getOptions(MoFEM::Interface *m_field_ptr=nullptr) override
static constexpr std::array< std::array< int, 2 >, 6 > edgeNodes
boost::shared_ptr< MatOpsData > matOpsDataPtr
Definition MatOps.hpp:154
virtual moab::Interface & get_moab()=0
Deprecated interface functions.