v0.15.0
Loading...
Searching...
No Matches
FiniteThermalOps.hpp
Go to the documentation of this file.
1/**
2 * @file FiniteThermalOps.hpp
3 * @author Ross Williams (ross.williams@glasgow.ac.uk)
4 * @brief Operators for Piola transformation of the thermal conductivity
5 * @version 0.14.0
6 * @date 2025-03-31
7 */
8
9#ifndef __FINITE_THERMAL_OPS_HPP__
10#define __FINITE_THERMAL_OPS_HPP__
11
13
14struct CommonData : public boost::enable_shared_from_this<CommonData> {
15 boost::shared_ptr<double> thermalConductivityPtr;
16 boost::shared_ptr<double> heatCapacityPtr;
17 boost::shared_ptr<VectorDouble> coeffExpansionPtr;
18 boost::shared_ptr<double> refTempPtr;
19};
20
21template <int DIM, IntegrationType I, typename DomainEleOp>
23
24// Calculate 1/J * K^-1 * Q * deltaQ
25// Calculate 1/J * (F_Ji^T * k_im^-1 * FmN) * Q_N * deltaQ_J
26template <int DIM, typename DomainEleOp>
27struct OpCalculateQdotQRhs<DIM, GAUSS, DomainEleOp> : public DomainEleOp {
28
30 boost::shared_ptr<MatrixDouble> vec,
31 ScalarFun resistance_function,
32 boost::shared_ptr<MatrixDouble> mat_Grad_Ptr,
33 boost::shared_ptr<Range> ents_ptr = nullptr)
34 : DomainEleOp(field_name, field_name, DomainEleOp::OPROW), fluxVec(vec),
35 resistanceFunction(resistance_function), matGradPtr(mat_Grad_Ptr) {}
36
37protected:
38 boost::shared_ptr<MatrixDouble> fluxVec;
40 boost::shared_ptr<MatrixDouble> matGradPtr;
41 MoFEMErrorCode iNtegrate(EntitiesFieldData::EntData &data);
42};
43
44template <int DIM, typename DomainEleOp>
46 EntitiesFieldData::EntData &data) {
48
49 FTensor::Index<'i', DIM> i;
50 FTensor::Index<'J', DIM> J;
51 FTensor::Index<'m', DIM> m;
52 FTensor::Index<'N', DIM> N;
53
54 const auto nb_integration_pts = DomainEleOp::getGaussPts().size2();
55
57 FTensor::Tensor1<double, DIM> t_K_inv_Q_over_J;
58
59 constexpr auto t_kd = FTensor::Kronecker_Delta<int>();
60
61 auto t_grad = getFTensor2FromMat<DIM, DIM>(*(matGradPtr));
62
63 // get element volume
64 const double vol = DomainEleOp::getMeasure();
65 // get integration weights
66 auto t_w = DomainEleOp::getFTensor0IntegrationWeight();
67 // get base function gradient on rows
68 auto t_row_base = data.getFTensor1N<3>();
69 // get flux values
70 auto t_flux = getFTensor1FromMat<DIM>(*fluxVec);
71 // get coordinate at integration points
72 auto t_coords = AssemblyDomainEleOp::getFTensor1CoordsAtGaussPts();
73
74 // loop over integration points
75 for (size_t gg = 0; gg != nb_integration_pts; ++gg) {
76 // take into account Jacobian
77 const double alpha = t_w * vol;
78
79 t_F(i, J) = t_grad(i, J) + t_kd(i, J); // Deformation gradient
80 auto t_J = determinantTensor(t_F); // Volume jacobian
81
82 t_K_inv_Q_over_J(J) =
83 resistanceFunction(t_coords(0), t_coords(1), t_coords(2)) * t_F(m, J) *
84 t_F(m, N) * t_flux(N) / t_J; // Value which multiplies delta Q
85
86 // loop over rows base functions
87 size_t rr = 0;
88 for (; rr != DomainEleOp::nbRows; ++rr) {
89 DomainEleOp::locF[rr] += t_K_inv_Q_over_J(J) * alpha * (t_row_base(J));
90 ++t_row_base;
91 }
92 for (; rr < DomainEleOp::nbRowBaseFunctions; ++rr)
93 ++t_row_base;
94 ++t_w; // move to another integration weight
95 ++t_coords;
96 ++t_flux;
97 ++t_grad;
98 };
100}
101
102template <int DIM, IntegrationType I, typename AssemblyDomainEleOp>
104
105// Calculate LHS of OpCalculateQdotQRhs wrt Q
106template <int DIM, typename AssemblyDomainEleOp>
108 : public AssemblyDomainEleOp {
109
110 OpCalculateQdotQLhs_dQ(const std::string row_field_name,
111 const std::string col_field_name,
112 ScalarFun resistance_function,
113 boost::shared_ptr<MatrixDouble> mat_Grad_Ptr,
114 boost::shared_ptr<Range> ents_ptr = nullptr)
115 : AssemblyDomainEleOp(row_field_name, col_field_name,
116 AssemblyDomainEleOp::OPROWCOL),
117 resistanceFunction(resistance_function), matGradPtr(mat_Grad_Ptr) {}
118
119protected:
121 boost::shared_ptr<MatrixDouble> matGradPtr;
122 MoFEMErrorCode iNtegrate(EntitiesFieldData::EntData &row_data,
123 EntitiesFieldData::EntData &col_data);
124};
125
126template <int DIM, typename AssemblyDomainEleOp>
127MoFEMErrorCode
129 EntitiesFieldData::EntData &row_data,
130 EntitiesFieldData::EntData &col_data) {
132
133 FTensor::Index<'i', DIM> i;
134 FTensor::Index<'J', DIM> J;
135 FTensor::Index<'M', DIM> M;
136 FTensor::Index<'L', DIM> L;
137
138 auto t_w = this->getFTensor0IntegrationWeight();
139
140 auto t_row_base = row_data.getFTensor1N<3>();
141
143 FTensor::Tensor2<double, DIM, DIM> t_right_Cauchy_Green;
145 FTensor::Tensor1<double, DIM> t_Kinv_over_J_row_base;
146
147 constexpr auto t_kd = FTensor::Kronecker_Delta<int>();
148
149 auto t_grad = getFTensor2FromMat<DIM, DIM>(*(matGradPtr));
150
151 // get coordinate at integration points
152 auto t_coords = AssemblyDomainEleOp::getFTensor1CoordsAtGaussPts();
153
154 for (size_t gg = 0; gg != AssemblyDomainEleOp::nbIntegrationPts; ++gg) {
155
156 t_F(i, J) = t_grad(i, J) + t_kd(i, J); // Deformation gradient
157 auto t_J = determinantTensor(t_F); // Volume jacobian
158
159 t_right_Cauchy_Green(M, L) =
160 t_F(i, M) *
161 t_F(i, L); // The inverse of the material thermal conductivity tensor
162
163 const double alpha = this->getMeasure() * t_w;
164
165 t_Kinv_over_J(M, L) =
166 (alpha * resistanceFunction(t_coords(0), t_coords(1), t_coords(2)) /
167 t_J) *
168 t_right_Cauchy_Green(M, L);
169
170 size_t rr = 0;
171 for (; rr != AssemblyDomainEleOp::nbRows; ++rr) {
172 t_Kinv_over_J_row_base(L) = t_Kinv_over_J(M, L) * t_row_base(M);
173 auto t_col_base = col_data.getFTensor1N<3>(gg, 0);
174 for (size_t cc = 0; cc != AssemblyDomainEleOp::nbCols; ++cc) {
175 this->locMat(rr, cc) += t_Kinv_over_J_row_base(L) * t_col_base(L);
176 ++t_col_base;
177 }
178 ++t_row_base;
179 }
180 for (; rr < AssemblyDomainEleOp::nbRowBaseFunctions; ++rr)
181 ++t_row_base;
182
183 ++t_w; // move to another integration weight
184 ++t_coords;
185 ++t_grad;
186 }
187
189}
190
191template <int DIM, IntegrationType I, typename AssemblyDomainEleOp,
192 bool IS_LARGE_STRAINS>
194
195// Calculate LHS of OpCalculateQdotQRhs wrt U
196template <int DIM, typename AssemblyDomainEleOp>
198 : public AssemblyDomainEleOp {
199
200 OpCalculateQdotQLhs_dU(const std::string row_field_name,
201 const std::string col_field_name,
202 boost::shared_ptr<MatrixDouble> vec,
203 ScalarFun resistance_function,
204 boost::shared_ptr<MatrixDouble> mat_Grad_Ptr,
205 boost::shared_ptr<Range> ents_ptr = nullptr)
206 : AssemblyDomainEleOp(row_field_name, col_field_name,
207 AssemblyDomainEleOp::OPROWCOL),
208 fluxVec(vec), resistanceFunction(resistance_function),
209 matGradPtr(mat_Grad_Ptr) {
210 AssemblyDomainEleOp::sYmm = false;
211 }
212
213protected:
214 boost::shared_ptr<MatrixDouble> fluxVec;
216 boost::shared_ptr<MatrixDouble> matGradPtr;
217 MoFEMErrorCode iNtegrate(EntitiesFieldData::EntData &row_data,
218 EntitiesFieldData::EntData &col_data);
219};
220
221template <int DIM, typename AssemblyDomainEleOp>
222MoFEMErrorCode
224 EntitiesFieldData::EntData &row_data,
225 EntitiesFieldData::EntData &col_data) {
227
228 FTensor::Index<'i', DIM> i;
229 FTensor::Index<'J', DIM> J;
230 FTensor::Index<'m', DIM> m;
231 FTensor::Index<'M', DIM> M;
232 FTensor::Index<'l', DIM> l;
233 FTensor::Index<'L', DIM> L;
234
235 auto t_w = this->getFTensor0IntegrationWeight();
236
237 // Always need three components for vectorial basis
238 auto t_row_base = row_data.getFTensor1N<3>();
239
241 FTensor::Tensor2<double, DIM, DIM> t_right_Cauchy_Green;
246 FTensor::Tensor2<double, DIM, DIM> t_FtF_Finv_Q_row_base;
248
249 constexpr auto t_kd = FTensor::Kronecker_Delta<int>();
250
251 auto t_grad = getFTensor2FromMat<DIM, DIM>(*(matGradPtr));
252
253 // get flux values
254 auto t_flux = getFTensor1FromMat<DIM>(*fluxVec);
255
256 // for each integration point
257 for (size_t gg = 0; gg != AssemblyDomainEleOp::nbIntegrationPts; ++gg) {
258
259 t_F(i, J) = t_grad(i, J) + t_kd(i, J); // Deformation gradient
260 auto t_J = determinantTensor(t_F); // Volume jacobian
261 CHKERR invertTensor(t_F, t_J, t_F_inv);
262
263 t_right_Cauchy_Green(M, L) =
264 t_F(i, M) *
265 t_F(i, L); // The inverse of the material thermal conductivity tensor
266
267 const double alpha = this->getMeasure() * t_w;
268
269 // get the vector of the local matrix for the derivative wrt a vectorial
270 // field with a scalar basis
271 auto t_vec = getFTensor1FromPtr<DIM>(&this->locMat(0, 0));
272
273 // get coordinate at integration points
274 auto t_coords = AssemblyDomainEleOp::getFTensor1CoordsAtGaussPts();
275
276 auto alpha_resistance_Jinv =
277 alpha * resistanceFunction(t_coords(0), t_coords(1), t_coords(2)) / t_J;
278 t_F_flux(l) = t_F(l, L) * t_flux(L);
279
280 t_FtF_Q(M) = t_right_Cauchy_Green(M, L) * t_flux(L);
281
282 // for each row coefficient
283 size_t rr = 0;
284 for (; rr != AssemblyDomainEleOp::nbRows; ++rr) {
285 auto t_col_grad_base = col_data.getFTensor1DiffN<DIM>(gg, 0);
286
287 t_FtF_Finv_Q_row_base(J, l) = t_FtF_Q(M) * t_row_base(M) * t_F_inv(J, l);
288 t_F_row_base(l) = t_F(l, M) * t_row_base(M);
289 t_F_Q_row_base(l, M) = t_F_flux(l) * t_row_base(M);
290
291 // for each coupled coefficient in the columns
292 // divied by DIM since scalar basis for vectorial field
293 for (size_t cc = 0; cc != AssemblyDomainEleOp::nbCols / DIM; ++cc) {
294 t_vec(l) += alpha_resistance_Jinv *
295 (-t_FtF_Finv_Q_row_base(J, l) * t_col_grad_base(J) +
296 t_F_Q_row_base(l, M) * t_col_grad_base(M) +
297 t_F_row_base(l) * t_col_grad_base(L) * t_flux(L));
298 ++t_col_grad_base;
299 ++t_vec;
300 }
301 ++t_row_base;
302 }
303 for (; rr < AssemblyDomainEleOp::nbRowBaseFunctions; ++rr)
304 ++t_row_base;
305
306 ++t_w; // move to another integration weight
307 ++t_coords;
308 ++t_flux;
309 ++t_grad;
310 }
311
313}
314
315template <int DIM, typename AssemblyDomainEleOp>
317 : public AssemblyDomainEleOp {
318
319 OpCalculateQdotQLhs_dU(const std::string row_field_name,
320 const std::string col_field_name,
321 boost::shared_ptr<MatrixDouble> vec,
322 ScalarFun resistance_function,
323 boost::shared_ptr<MatrixDouble> mat_Grad_Ptr,
324 boost::shared_ptr<Range> ents_ptr = nullptr)
325 : AssemblyDomainEleOp(row_field_name, col_field_name,
326 AssemblyDomainEleOp::OPROWCOL),
327 fluxVec(vec), resistanceFunction(resistance_function),
328 matGradPtr(mat_Grad_Ptr) {
329 AssemblyDomainEleOp::sYmm = false;
330 }
331
332protected:
333 boost::shared_ptr<MatrixDouble> fluxVec;
335 boost::shared_ptr<MatrixDouble> matGradPtr;
336 MoFEMErrorCode iNtegrate(EntitiesFieldData::EntData &row_data,
337 EntitiesFieldData::EntData &col_data);
338};
339
340template <int DIM, typename AssemblyDomainEleOp>
341MoFEMErrorCode
343 EntitiesFieldData::EntData &row_data,
344 EntitiesFieldData::EntData &col_data) {
346
347 // Empty implementation of OpCalculateQdotQLhs_dU for small the case of small
348 // strains. This allows the operator to be called without adding any
349 // contribution to the stiffness matrix.
350
352}
353
354} // namespace FiniteThermalOps
355
356#endif // __FINITE_THERMAL_OPS_HPP__
Kronecker Delta class.
#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.
constexpr auto t_kd
FTensor::Index< 'i', SPACE_DIM > i
FTensor::Index< 'J', DIM1 > J
Definition level_set.cpp:30
FTensor::Index< 'l', 3 > l
constexpr IntegrationType I
constexpr auto field_name
FTensor::Index< 'm', 3 > m
const int N
Definition speed_test.cpp:3
boost::shared_ptr< double > heatCapacityPtr
boost::shared_ptr< VectorDouble > coeffExpansionPtr
boost::shared_ptr< double > refTempPtr
boost::shared_ptr< double > thermalConductivityPtr
OpCalculateQdotQLhs_dQ(const std::string row_field_name, const std::string col_field_name, ScalarFun resistance_function, boost::shared_ptr< MatrixDouble > mat_Grad_Ptr, boost::shared_ptr< Range > ents_ptr=nullptr)
OpCalculateQdotQLhs_dU(const std::string row_field_name, const std::string col_field_name, boost::shared_ptr< MatrixDouble > vec, ScalarFun resistance_function, boost::shared_ptr< MatrixDouble > mat_Grad_Ptr, boost::shared_ptr< Range > ents_ptr=nullptr)
OpCalculateQdotQLhs_dU(const std::string row_field_name, const std::string col_field_name, boost::shared_ptr< MatrixDouble > vec, ScalarFun resistance_function, boost::shared_ptr< MatrixDouble > mat_Grad_Ptr, boost::shared_ptr< Range > ents_ptr=nullptr)
OpCalculateQdotQRhs(const std::string field_name, boost::shared_ptr< MatrixDouble > vec, ScalarFun resistance_function, boost::shared_ptr< MatrixDouble > mat_Grad_Ptr, boost::shared_ptr< Range > ents_ptr=nullptr)
FormsIntegrators< DomainEleOp >::Assembly< A >::OpBase AssemblyDomainEleOp
constexpr bool IS_LARGE_STRAINS