v0.16.0
Loading...
Searching...
No Matches
CGGTonsorialBubbleBase.cpp
Go to the documentation of this file.
1/** \file CGGTonsorialBubbleBase.hpp
2
3 \brief Implementation of tonsorial bubble base div(v) = 0.
4
5 Implementation is based and motiveted by \cite cockburn2010new. This base
6 is used to approximate stresses using Hdiv base with weakly enforced
7 symmetry.
8
9*/
10
11#include <MoFEM.hpp>
12#include <h1_hdiv_hcurl_l2.h>
13using namespace MoFEM;
15
16using namespace FTensor;
17
18namespace EshelbianPlasticity {
19
20template <typename T>
22 const T *diffN,
23 Tensor2<PackPtr<T *, 9>, 3, 3> &t_phi,
24 const int gdim) {
26
27 // FIXME: In this implementation symmetry of mix derivatives is not exploited
28
29 if (p < 1)
31
32 Index<'i', 3> i;
33 Index<'j', 3> j;
34 Index<'k', 3> k;
35 Index<'m', 3> m;
36 Index<'f', 3> f;
37
38 Tensor1<T, 3> t_diff_n[4];
39 {
40 Tensor1<PackPtr<const T *, 3>, 3> t_diff_n_tmp(&diffN[0], &diffN[1],
41 &diffN[2]);
42 for (int ii = 0; ii != 4; ++ii) {
43 t_diff_n[ii](i) = t_diff_n_tmp(i);
44 ++t_diff_n_tmp;
45 }
46 }
47
48 constexpr AinsworthHdivOptions::EdgeCoordinate ccg_ksi_type =
50
51 auto get_ksi = [](const T n0, const T n1) {
52 if constexpr (ccg_ksi_type == AinsworthHdivOptions::EdgeCoordinate::PAPER) {
53 return n1 - n0;
54 } else if constexpr (ccg_ksi_type ==
55 AinsworthHdivOptions::EdgeCoordinate::ENDPOINT_O) {
56 return T(1) - T(2) * n0;
57
58 } else if constexpr (ccg_ksi_type ==
59 AinsworthHdivOptions::EdgeCoordinate::ENDPOINT_I) {
60 return T(2) * n1 - T(1);
61 }
62 return T(0);
63 };
64
65 auto get_diff_ksi = [&](const int n0, const int n1) {
66 Tensor1<T, 3> t_diff_ksi;
67 for (int dd = 0; dd != 3; ++dd) {
68 if constexpr (ccg_ksi_type ==
69 AinsworthHdivOptions::EdgeCoordinate::PAPER) {
70 t_diff_ksi(dd) = t_diff_n[n1](dd) - t_diff_n[n0](dd);
71 } else if constexpr (ccg_ksi_type ==
72 AinsworthHdivOptions::EdgeCoordinate::ENDPOINT_O) {
73 t_diff_ksi(dd) = -T(2) * t_diff_n[n0](dd);
74 } else if constexpr (ccg_ksi_type ==
75 AinsworthHdivOptions::EdgeCoordinate::ENDPOINT_I) {
76 t_diff_ksi(dd) = T(2) * t_diff_n[n1](dd);
77 }
78 }
79 return t_diff_ksi;
80 };
81
82 Tensor1<T, 3> t_diff_ksi[3];
83 for (int ii = 0; ii != 3; ++ii)
84 t_diff_ksi[ii] = get_diff_ksi(0, ii + 1);
85
86 int lp = p >= 2 ? p - 2 + 1 : 0;
87 UBlasVector<T> l[3] = {VectorDouble(lp + 1), VectorDouble(lp + 1),
88 VectorDouble(lp + 1)};
89 UBlasMatrix<T> diff_l[3] = {MatrixDouble(3, lp + 1), MatrixDouble(3, lp + 1),
90 MatrixDouble(3, lp + 1)};
91 UBlasMatrix<T> diff2_l[3] = {MatrixDouble(9, lp + 1), MatrixDouble(9, lp + 1),
92 MatrixDouble(9, lp + 1)};
93
94 for (int ii = 0; ii != 3; ++ii)
95 diff2_l[ii].clear();
96
97 for (int gg = 0; gg != gdim; ++gg) {
98
99 const int node_shift = gg * 4;
100
101 for (int ii = 0; ii != 3; ++ii) {
102
103 auto &t_diff_ksi_ii = t_diff_ksi[ii];
104 auto &l_ii = l[ii];
105 auto &diff_l_ii = diff_l[ii];
106 auto &diff2_l_ii = diff2_l[ii];
107 const T ksi_ii = get_ksi(N[node_shift], N[node_shift + ii + 1]);
108 CHKERR Legendre_polynomials(lp, ksi_ii, &t_diff_ksi_ii(0),
109 &*l_ii.data().begin(),
110 &*diff_l_ii.data().begin(), 3);
111
112 for (int l = 1; l < lp; ++l) {
113 const T a = ((2 * (T)l + 1) / ((T)l + 1));
114 const T b = ((T)l / ((T)l + 1));
115 for (int d0 = 0; d0 != 3; ++d0)
116 for (int d1 = 0; d1 != 3; ++d1) {
117 const int r = 3 * d0 + d1;
118 diff2_l_ii(r, l + 1) = a * (t_diff_ksi_ii(d0) * diff_l_ii(d1, l) +
119 t_diff_ksi_ii(d1) * diff_l_ii(d0, l) +
120 ksi_ii * diff2_l_ii(r, l)) -
121 b * diff2_l_ii(r, l - 1);
122 }
123 }
124 }
125
126 const T n[] = {N[node_shift + 0], N[node_shift + 1], N[node_shift + 2],
127 N[node_shift + 3]};
128
129 Tensor2<T, 3, 3> t_bk;
130 Tensor3<T, 3, 3, 3> t_bk_diff;
131 const int tab[4][4] = {
132 {1, 2, 3, 0}, {2, 3, 0, 1}, {3, 0, 1, 2}, {0, 1, 2, 3}};
133 t_bk(i, j) = 0;
134 t_bk_diff(i, j, k) = 0;
135 for (int ii = 0; ii != 4; ++ii) {
136 const int i0 = tab[ii][0];
137 const int i1 = tab[ii][1];
138 const int i2 = tab[ii][2];
139 const int i3 = tab[ii][3];
140 auto &t_diff_n_i0 = t_diff_n[i0];
141 auto &t_diff_n_i1 = t_diff_n[i1];
142 auto &t_diff_n_i2 = t_diff_n[i2];
143 auto &t_diff_n_i3 = t_diff_n[i3];
145 t_k(i, j) = t_diff_n_i3(i) * t_diff_n_i3(j);
146 const T b = n[i0] * n[i1] * n[i2];
147 t_bk(i, j) += b * t_k(i, j);
148 Tensor1<T, 3> t_diff_b;
149 t_diff_b(i) = t_diff_n_i0(i) * n[i1] * n[i2] +
150 t_diff_n_i1(i) * n[i0] * n[i2] +
151 t_diff_n_i2(i) * n[i0] * n[i1];
152 t_bk_diff(i, j, k) += t_k(i, j) * t_diff_b(k);
153 }
154
155 int zz = 0;
156 for (int o = p - 2 + 1; o <= p - 2 + 1; ++o) {
157
158 for (int ii = 0; ii <= o; ++ii)
159 for (int jj = 0; (ii + jj) <= o; ++jj) {
160
161 const int kk = o - ii - jj;
162
163 auto get_diff_l = [&](const int y, const int i) {
164 return Tensor1<T, 3>(diff_l[y](0, i), diff_l[y](1, i),
165 diff_l[y](2, i));
166 };
167 auto get_diff2_l = [&](const int y, const int i) {
168 return Tensor2<T, 3, 3>(
169 diff2_l[y](0, i), diff2_l[y](1, i), diff2_l[y](2, i),
170 diff2_l[y](3, i), diff2_l[y](4, i), diff2_l[y](5, i),
171 diff2_l[y](6, i), diff2_l[y](7, i), diff2_l[y](8, i));
172 };
173
174 auto l_i = l[0][ii];
175 auto t_diff_i = get_diff_l(0, ii);
176 auto t_diff2_i = get_diff2_l(0, ii);
177 auto l_j = l[1][jj];
178 auto t_diff_j = get_diff_l(1, jj);
179 auto t_diff2_j = get_diff2_l(1, jj);
180 auto l_k = l[2][kk];
181 auto t_diff_k = get_diff_l(2, kk);
182 auto t_diff2_k = get_diff2_l(2, kk);
183
184 Tensor1<T, 3> t_diff_l2;
185 t_diff_l2(i) = t_diff_i(i) * l_j * l_k + t_diff_j(i) * l_i * l_k +
186 t_diff_k(i) * l_i * l_j;
187 Tensor2<T, 3, 3> t_diff2_l2;
188 t_diff2_l2(i, j) =
189 t_diff2_i(i, j) * l_j * l_k + t_diff_i(i) * t_diff_j(j) * l_k +
190 t_diff_i(i) * l_j * t_diff_k(j) +
191
192 t_diff2_j(i, j) * l_i * l_k + t_diff_j(i) * t_diff_i(j) * l_k +
193 t_diff_j(i) * l_i * t_diff_k(j) +
194
195 t_diff2_k(i, j) * l_i * l_j + t_diff_k(i) * t_diff_i(j) * l_j +
196 t_diff_k(i) * l_i * t_diff_j(j);
197
198 for (int dd = 0; dd != 3; ++dd) {
199
200 Tensor2<T, 3, 3> t_axial_diff;
201 t_axial_diff(i, j) = 0;
202 for (int mm = 0; mm != 3; ++mm)
203 t_axial_diff(dd, mm) = t_diff_l2(mm);
204
205 FTensor::Tensor3<T, 3, 3, 3> t_levi_civita;
206 t_levi_civita(i, j, k) = FTensor::levi_civita(i, j, k);
207
208 Tensor3<T, 3, 3, 3> t_A_diff;
209 t_A_diff(i, j, k) =
210 levi_civita<double>(i, j, m) * t_axial_diff(m, k);
211 Tensor2<T, 3, 3> t_curl_A;
212 t_curl_A(i, j) = levi_civita<double>(j, m, f) * t_A_diff(i, f, m);
213 Tensor3<T, 3, 3, 3> t_curl_A_bK_diff;
214 t_curl_A_bK_diff(i, j, k) = t_curl_A(i, m) * t_bk_diff(m, j, k);
215
216 Tensor3<T, 3, 3, 3> t_axial_diff2;
217 t_axial_diff2(i, j, k) = 0;
218 for (int mm = 0; mm != 3; ++mm)
219 for (int nn = 0; nn != 3; ++nn)
220 t_axial_diff2(dd, mm, nn) = t_diff2_l2(mm, nn);
221 Tensor4<T, 3, 3, 3, 3> t_A_diff2;
222 t_A_diff2(i, j, k, f) =
223 levi_civita<double>(i, j, m) * t_axial_diff2(m, k, f);
224 Tensor3<T, 3, 3, 3> t_curl_A_diff2;
225 t_curl_A_diff2(i, j, k) =
226 levi_civita<double>(j, m, f) * t_A_diff2(i, f, m, k);
227 Tensor3<T, 3, 3, 3> t_curl_A_diff2_bK;
228 t_curl_A_diff2_bK(i, j, k) = t_curl_A_diff2(i, m, k) * t_bk(m, j);
229
230 t_phi(i, j) =
231 levi_civita<double>(j, m, f) *
232 (t_curl_A_bK_diff(i, f, m) + t_curl_A_diff2_bK(i, f, m));
233
234 ++t_phi;
235 ++zz;
236 }
237 }
238 }
239#ifndef NDEBUG
240 if (zz != NBVOLUMETET_CCG_BUBBLE(p))
241 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
242 "Wrong number of base functions %d != %d", zz,
244#endif
245 }
246
248}
249
250MoFEMErrorCode CGG_BubbleBase_MBTET(const int p, const double *N,
251 const double *diffN,
252 Tensor2<PackPtr<double *, 9>, 3, 3> &t_phi,
253 const int gdim) {
254 return CGG_BubbleBase_MBTET_Impl<double>(p, N, diffN, t_phi, gdim);
255}
256
258 const int p, const std::complex<double> *N,
259 const std::complex<double> *diffN,
260 FTensor::Tensor2<FTensor::PackPtr<std::complex<double> *, 9>, 3, 3> &t_phi,
261 const int gdim) {
262 return CGG_BubbleBase_MBTET_Impl<std::complex<double>>(p, N, diffN, t_phi,
263 gdim);
264}
265
266} // namespace EshelbianPlasticity
Implementation of tonsorial bubble base div(v) = 0.
#define NBVOLUMETET_CCG_BUBBLE(P)
Bubble function for CGG H div space.
static double get_ksi(const double n0, const double n1)
Definition Hdiv.cpp:47
static FTensor::Tensor1< double, 3 > get_diff_ksi(const double *diffN, const int n0, const int n1)
Definition Hdiv.cpp:70
constexpr double a
#define MoFEMFunctionReturnHot(a)
Last executable line of each PETSc function used for error handling. Replaces return()
@ MOFEM_DATA_INCONSISTENCY
Definition definitions.h:31
#define CHKERR
Inline error check.
#define MoFEMFunctionBeginHot
First executable line of each MoFEM function, used for error handling. Final line of MoFEM functions ...
PetscErrorCode Legendre_polynomials(int p, double s, double *diff_s, double *L, double *diffL, int dim)
Calculate Legendre approximation basis.
Functions to approximate hierarchical spaces.
FTensor::Index< 'i', SPACE_DIM > i
const double n
refractive index of diffusive medium
FTensor::Index< 'l', 3 > l
FTensor::Index< 'j', 3 > j
FTensor::Index< 'k', 3 > k
MoFEMErrorCode CGG_BubbleBase_MBTET(const int p, const double *N, const double *diffN, FTensor::Tensor2< FTensor::PackPtr< double *, 9 >, 3, 3 > &phi, const int gdim)
Calculate CGGT tonsorial bubble base.
MoFEMErrorCode CGG_BubbleBase_MBTET_Impl(const int p, const T *N, const T *diffN, Tensor2< PackPtr< T *, 9 >, 3, 3 > &t_phi, const int gdim)
Tensors class implemented by Walter Landry.
Definition FTensor.hpp:51
constexpr std::enable_if<(Dim0<=2 &&Dim1<=2), Tensor2_Expr< Levi_Civita< T >, T, Dim0, Dim1, i, j > >::type levi_civita(const Index< i, Dim0 > &, const Index< j, Dim1 > &)
levi_civita functions to make for easy adhoc use
const Tensor2_symmetric_Expr< const ddTensor0< T, Dim, i, j >, typename promote< T, double >::V, Dim, i, j > dd(const Tensor0< T * > &a, const Index< i, Dim > index1, const Index< j, Dim > index2, const Tensor1< int, Dim > &d_ijk, const Tensor1< double, Dim > &d_xyz)
Definition ddTensor0.hpp:33
PetscErrorCode MoFEMErrorCode
MoFEM/PETSc error code.
ublas::vector< T, VecAllocator< T > > UBlasVector
Definition Types.hpp:66
UBlasMatrix< double > MatrixDouble
Definition Types.hpp:77
UBlasVector< double > VectorDouble
Definition Types.hpp:68
ublas::matrix< T, ublas::row_major, VecAllocator< T > > UBlasMatrix
Definition Types.hpp:75
implementation of Data Operators for Forces and Sources
Definition Common.hpp:10
FTensor::Index< 'm', 3 > m
const int N
Definition speed_test.cpp:3
EdgeCoordinate
Auxiliary edge coordinate used in Ainsworth H(div) functions.
Definition Hdiv.hpp:37
static constexpr EdgeCoordinate edge_coordinate
Selected edge coordinate variant.
Definition Hdiv.hpp:50