v0.15.5
Loading...
Searching...
No Matches
VolumeLengthQuality.hpp
Go to the documentation of this file.
1/** \file VolumeLengthQuality.hpp
2 * \ingroup nonlinear_elastic_elem
3 * \brief Implementation of Volume-Length-Quality measure with barrier
4 */
5
6
7
8#ifndef __VOLUME_LENGTH_QUALITY_HPP__
9#define __VOLUME_LENGTH_QUALITY_HPP__
10
11#ifndef WITH_ADOL_C
12#error "MoFEM need to be compiled with ADOL-C"
13#endif
14
15#include <Smoother.hpp>
16
24
25static const char *VolumeLengthQualityTypeNames[] = {
26 "QUALITY", "BARRIER_AND_QUALITY", "BARRIER_AND_CHANGE_QUALITY",
27 "BARRIER_AND_CHANGE_QUALITY_SCALED_BY_VOLUME"};
28
29/** \brief Volume Length Quality
30 \ingroup nonlinear_elastic_elem
31
32 */
33template <typename TYPE>
35 : public Smoother::CalculatePK1<TYPE> {
36
37 // VolumeLengthQualityType tYpe;
38 int tYpe;
39 double aLpha;
40 double gAmma;
41
45
46 VolumeLengthQuality(VolumeLengthQualityType type, double alpha, double gamma,
47 const std::string &field_name = "MESH_NODE_POSITIONS")
48 : Smoother::CalculatePK1<TYPE>(field_name), tYpe(type), aLpha(alpha),
49 gAmma(gamma) {
51 CHKERRABORT(PETSC_COMM_WORLD, ierr);
52 }
53
54 MoFEMErrorCode getMaterialOptions() {
56 PetscOptionsBegin(PETSC_COMM_WORLD, "",
57 "Get VolumeLengthQuality material options",
58 "none");
59 CHKERR PetscOptionsEList(
60 "-volume_length_type", "Volume length quality type", "",
62 VolumeLengthQualityTypeNames[tYpe], &tYpe, PETSC_NULLPTR);
63 CHKERR PetscOptionsScalar("-volume_length_alpha",
64 "volume length alpha parameter", "", aLpha,
65 &aLpha, PETSC_NULLPTR);
66 CHKERR PetscOptionsScalar("-volume_length_gamma",
67 "volume length parameter (barrier)", "", gAmma,
68 &gAmma, PETSC_NULLPTR);
69 PetscOptionsEnd();
71 }
72
73 VectorDouble coordsEdges;
75 VectorDouble deltaChi;
76
77 ublas::vector<TYPE> deltaX;
78 ublas::matrix<TYPE> Q, dXdChiT;
80
81 /** Get coordinates of edges using cannonical element numeration
82 */
83 MoFEMErrorCode getEdgesFromElemCoords() {
85 if (coordsEdges.empty()) {
86 coordsEdges.resize(6 * 2 * 3, false);
87 }
88 cblas_dcopy(3, &this->opPtr->getCoords()[0 * 3], 1,
89 &coordsEdges[0 * 3 * 2 + 0], 1);
90 cblas_dcopy(3, &this->opPtr->getCoords()[1 * 3], 1,
91 &coordsEdges[0 * 3 * 2 + 3], 1);
92 cblas_dcopy(3, &this->opPtr->getCoords()[0 * 3], 1,
93 &coordsEdges[1 * 3 * 2 + 0], 1);
94 cblas_dcopy(3, &this->opPtr->getCoords()[2 * 3], 1,
95 &coordsEdges[1 * 3 * 2 + 3], 1);
96 cblas_dcopy(3, &this->opPtr->getCoords()[0 * 3], 1,
97 &coordsEdges[2 * 3 * 2 + 0], 1);
98 cblas_dcopy(3, &this->opPtr->getCoords()[3 * 3], 1,
99 &coordsEdges[2 * 3 * 2 + 3], 1);
100 cblas_dcopy(3, &this->opPtr->getCoords()[1 * 3], 1,
101 &coordsEdges[3 * 3 * 2 + 0], 1);
102 cblas_dcopy(3, &this->opPtr->getCoords()[2 * 3], 1,
103 &coordsEdges[3 * 3 * 2 + 3], 1);
104 cblas_dcopy(3, &this->opPtr->getCoords()[1 * 3], 1,
105 &coordsEdges[4 * 3 * 2 + 0], 1);
106 cblas_dcopy(3, &this->opPtr->getCoords()[3 * 3], 1,
107 &coordsEdges[4 * 3 * 2 + 3], 1);
108 cblas_dcopy(3, &this->opPtr->getCoords()[2 * 3], 1,
109 &coordsEdges[5 * 3 * 2 + 0], 1);
110 cblas_dcopy(3, &this->opPtr->getCoords()[3 * 3], 1,
111 &coordsEdges[5 * 3 * 2 + 3], 1);
113 }
114
115 /** \brief Calculate mean element edge length
116
117 \f[
118 \Delta \boldsymbol\chi = \boldsymbol\chi^1 - \boldsymbol\chi^2
119 \f]
120
121 \f[
122 \Delta X = \mathbf{F} \Delta \boldsymbol\chi
123 \f]
124
125 \f[
126 l_\textrm{rms} = \sqrt{\frac{1}{6} \sum_{i=0}^6 l_i^2 } =
127 L_\textrm{rms}dl_\textrm{rms} \f]
128
129 */
130 MoFEMErrorCode calculateLrms() {
132 if (deltaChi.size() != 3) {
133 deltaChi.resize(3);
134 deltaX.resize(3);
135 dXdChiT.resize(3, 3);
136 }
137 lrmsSquared = 0;
138 lrmsSquared0 = 0;
139 std::fill(dXdChiT.data().begin(), dXdChiT.data().end(), 0);
140 for (int ee = 0; ee < 6; ee++) {
141 for (int dd = 0; dd < 3; dd++) {
142 deltaChi[dd] = coordsEdges[6 * ee + dd] - coordsEdges[6 * ee + 3 + dd];
143 }
144 std::fill(deltaX.begin(), deltaX.end(), 0);
145 for (int ii = 0; ii != 3; ++ii)
146 for (int jj = 0; jj != 3; ++jj)
147 deltaX(ii) += this->F(ii, jj) * deltaChi(jj);
148
149 for (int dd = 0; dd < 3; dd++) {
150 lrmsSquared += (1. / 6.) * deltaX[dd] * deltaX[dd];
151 lrmsSquared0 += (1. / 6.) * deltaChi[dd] * deltaChi[dd];
152 }
153 for (int ii = 0; ii != 3; ++ii)
154 for (int jj = 0; jj != 3; ++jj)
155 dXdChiT(ii, jj) += deltaX(ii) * deltaChi(jj);
156 }
158 }
159
160 /** \brief Calculate Q
161
162 \f[
163 \mathbf{Q} =
164 \mathbf{F}^{-\mathsf{T}}
165 -
166 \frac{1}{2}
167 \frac{1}{l^2_\textrm{rms}}
168 \sum_i^6
169 \Delta\mathbf{X}_i
170 \Delta\boldsymbol\chi_i^\mathsf{T}
171 \f]
172
173 */
174 MoFEMErrorCode calculateQ() {
176 Q.resize(3, 3, false);
177 auto t_Q = getFTensor2FromArray3by3(Q, FTensor::Number<0>(), 0);
178 auto t_invF = getFTensor2FromArray3by3(this->invF, FTensor::Number<0>(), 0);
179 auto t_dXdChiT = getFTensor2FromArray3by3(dXdChiT, FTensor::Number<0>(), 0);
180 t_Q(i, j) = t_invF(j, i) - 0.5 * t_dXdChiT(i, j) / lrmsSquared;
182 }
183
184 /** \brief Volume Length Quality
185
186 Based on:
187 Three‐dimensional brittle fracture: configurational‐force‐driven crack
188 propagation International Journal for Numerical Methods in Engineering 97
189 (7), 531-550
190
191 \f[
192 \mathcal{B}(a)=\frac{a}{2(1-\gamma)}-\ln{(a-\gamma)}
193 \f]
194
195 \f[
196 q = q_0 b,
197 \quad q_0 = 6\sqrt{2}\frac{V_0}{L^3_\textrm{rms}},
198 \quad b = \frac{\textrm{det}(\mathbf{F})}{\textrm{d}l^3_\textrm{rms}}
199 \f]
200
201 \f[
202 \mathbf{P} = \mathcal{B}(a)\mathbf{Q},
203 \f]
204 where \f$a\f$ depending on problem could be \f$q\f$ or \f$b\f$.
205
206 */
207 virtual MoFEMErrorCode calculateP_PiolaKirchhoffI() {
209
211 detF = determinantTensor3by3(this->F);
212 if (this->invF.size1() != 3)
213 this->invF.resize(3, 3);
214
215 CHKERR invertTensor3by3(this->F, detF, this->invF);
218
219 double lrms03 = lrmsSquared0 * sqrt(lrmsSquared0);
220 b = detF / (lrmsSquared * sqrt(lrmsSquared) / lrms03);
221
222 currentVolume = detF * this->opPtr->getVolume();
223 q = 6. * sqrt(2.) * currentVolume / (lrmsSquared * sqrt(lrmsSquared));
224
225 if (this->P.size1() != 3)
226 this->P.resize(3, 3);
227
228 switch (tYpe) {
229 case QUALITY:
230 // Only use for testing, simple quality gradient
231 noalias(this->P) = q * Q;
232 break;
234 // This is used form mesh smoothing
235 tMp = q / (1.0 - gAmma) - 1.0 / (q - gAmma);
236 noalias(this->P) = tMp * Q;
237 break;
239 // Works well with Arbitrary Lagrangian Formulation
240 tMp = b / (1.0 - gAmma) - 1.0 / (b - gAmma);
241 noalias(this->P) = tMp * Q;
242 break;
244 // When scaled by volume works well with ALE and face flipping.
245 // Works well with smooth crack propagation
247 tMp *= b / (1.0 - gAmma) - 1.0 / (b - gAmma);
248 noalias(this->P) = tMp * Q;
249 break;
250 }
251
252 // Divide by volume, to make units as they should be
253 this->P *= aLpha / this->opPtr->getVolume();
254
256 }
257};
258
259#endif //__VOLUME_LENGTH_QUALITY_HPP__
static PetscErrorCode ierr
#define MoFEMFunctionReturnHot(a)
Last executable line of each PETSc function used for error handling. Replaces return()
#define MoFEMFunctionBegin
First executable line of each MoFEM function, used for error handling. Final line of MoFEM functions ...
#define MoFEMFunctionReturn(a)
Last executable line of each PETSc function used for error handling. Replaces return()
#define CHKERR
Inline error check.
#define MoFEMFunctionBeginHot
First executable line of each MoFEM function, used for error handling. Final line of MoFEM functions ...
constexpr auto field_name
MoFEM::VolumeElementForcesAndSourcesCore::UserDataOperator * opPtr
pointer to finite element tetrahedral operator
Definition Smoother.hpp:252
CalculatePK1(const std::string field_name)
Definition Smoother.hpp:237
MatrixBoundedArray< TYPE, 9 > F
Definition Smoother.hpp:245
MatrixBoundedArray< TYPE, 9 > invF
Definition Smoother.hpp:245
MatrixBoundedArray< TYPE, 9 > P
Definition Smoother.hpp:245
FTensor::Tensor2< FTensor::PackPtr< TYPE *, 0 >, 3, 3 > t_invF
Definition Smoother.hpp:246
Volume Length Quality.
FTensor::Index< 'k', 3 > k
MoFEMErrorCode calculateQ()
Calculate Q.
ublas::matrix< TYPE > Q
ublas::vector< TYPE > deltaX
FTensor::Index< 'j', 3 > j
VolumeLengthQuality(VolumeLengthQualityType type, double alpha, double gamma, const std::string &field_name="MESH_NODE_POSITIONS")
FTensor::Index< 'i', 3 > i
MoFEMErrorCode getEdgesFromElemCoords()
virtual MoFEMErrorCode calculateP_PiolaKirchhoffI()
Volume Length Quality.
MoFEMErrorCode getMaterialOptions()
MoFEMErrorCode calculateLrms()
Calculate mean element edge length.
ublas::matrix< TYPE > dXdChiT
VolumeLengthQualityType
@ LASTOP_VOLUMELENGTHQUALITYTYPE
@ BARRIER_AND_CHANGE_QUALITY_SCALED_BY_VOLUME
@ BARRIER_AND_QUALITY
@ BARRIER_AND_CHANGE_QUALITY
static const char * VolumeLengthQualityTypeNames[]
VolumeLengthQualityType
@ LASTOP_VOLUMELENGTHQUALITYTYPE
@ BARRIER_AND_CHANGE_QUALITY_SCALED_BY_VOLUME
@ BARRIER_AND_QUALITY
@ BARRIER_AND_CHANGE_QUALITY
static const char * VolumeLengthQualityTypeNames[]