v0.14.0
Loading...
Searching...
No Matches
UnsaturatedFlowOperators.hpp
Go to the documentation of this file.
1#ifndef __UFOPERATORS_HPP__
2#define __UFOPERATORS_HPP__
3
4#include <stdlib.h>
6
7namespace UFOperators {
8
10
12
15
16using EntData = DataForcesAndSourcesCore::EntData;
17
18 const int save_every_nth_step = 4;
19 const double natural_bc_values = -1;
20 const double essential_bc_values = 0.0;
21 const int order = 2;
22
23
24 // const int dim = 3;
26
27 struct BlockData {
29 double K_s; // K_s
30 double ll; // l
31 double theta_r; // theta_r
32 double theta_s; // theta_s
33 double theta_m; // theta_m
34 double nn; // n
35 double alpha; // alpha
36 double h_s; // h_s
37
39
41 : K_s(4.8000)
42 , ll(0.5000)
43 , theta_r(0.01000000)
44 , theta_s(0.45000000)
45 , theta_m(0.45008000)
46 , nn(1.17200000)
47 , alpha(0.00170000)
48 , h_s(-2.0000)
49 {}
50
51 double get_waterContent(double head){
52 double ret_val;
53 double m = 1 - 1.0 / nn;
54 if(head < h_s){
55 ret_val = theta_r + (theta_m-theta_r) /
56 pow(1 + pow(-alpha * head, nn), m);
57 } else {
58 ret_val = theta_s;
59 }
60 return ret_val;
61 }
62
63 double get_conductivity(double head){
64 double ret_val;
65 if(head < h_s){
66 ret_val = K_s * get_relativeConductivity(head);
67 }else {
68 ret_val = K_s;
69 }
70 return ret_val;
71 }
72 double get_relativeConductivity(double head){
73 double S_e = get_effSaturation(head);
74 double F_e = get_Fe(S_e);
75 double F_1 = get_Fe(1.0);
76
77 return pow(S_e, ll) * pow(( (1 - F_e) / (1 - F_1) ), 2);
78 }
79 double get_Fe(double eff_satu){
80 double m = 1 - 1.0 / nn;
81 double S_eStar = get_eff_satuStar(eff_satu);
82 return pow(1 - pow(S_eStar, 1.0 / m), m);
83 }
84
85 double get_eff_satuStar(double eff_satu){
86 return (theta_s - theta_r) / (theta_m - theta_r) * eff_satu;
87
88 }
89
90 double get_effSaturation(double head){
91 double theta = get_waterContent(head);
92 return (theta - theta_r) / (theta_s - theta_r);
93 }
94
95 double get_capacity(double head){
96 double m = 1 - 1.0 / nn;
97 double ret_val;
98 if(head < h_s){
99 ret_val = alpha * m * nn * (theta_m - theta_r) * pow(-alpha * head, nn-1) /
100 pow(1 + pow(-alpha * head, nn), m+1);
101 } else {
102 ret_val = 0;
103 }
104 return ret_val;
105 }
106
107 double get_diffCapacity(double head){
108 double m = 1.0 - 1.0 / nn;
109 double ret_val;
110 if(head < h_s){
111 double denom = 1 + pow(-alpha * head, nn);
112 ret_val = pow(alpha, 2) * (theta_m - theta_r) * m * nn * pow(-alpha * head, nn-2) / pow(denom, m+1) *
113 ( (m + 1) * nn * pow(-alpha * head, nn) / denom + (nn-1) );
114 }else{
115 ret_val = 0;
116 }
117
118 return ret_val;
119 }
120
121 double get_diffConductivity(double head){
122 double DK_r = get_diffRelativeConductivity(head);
123 double ret_val;
124 if(head < h_s){
125 ret_val = K_s * DK_r;
126 }else{
127 ret_val = 0;
128 }
129 return ret_val;
130 }
131
132 double get_diffRelativeConductivity(double head){
133 double S_e = get_effSaturation(head);
134 double DS_e = get_diffEffSaturation(head);
135 double F_e = get_Fe(S_e);
136 double F_1 = get_Fe(1.0);
137 double DF_e = get_diffFe(S_e);
138 return pow(S_e, ll-1) * DS_e * ( (1 - F_e) / (1 - F_1) ) *
139 (ll * ( (1 - F_e) / (1 - F_1) ) - 2.0 * S_e * DF_e / (1 - F_1));
140 }
141 double get_diffFe(double s_e){
142 double m = 1 - 1.0 / nn;
143 double S_estar = get_eff_satuStar(s_e);
144 double DS_estar = get_diffEffSatuStar(s_e);
145 return -DS_estar * pow(1-pow(S_estar, 1.0/m), m-1) * pow(S_estar, 1.0/m - 1);
146 }
147
148 double get_diffEffSatuStar(double s_e){
149 return (theta_s - theta_r) / (theta_m - theta_r);
150 }
151
152 double get_diffEffSaturation(double head){
153 double Dtheta = get_capacity(head);
154 return Dtheta / (theta_s - theta_r);
155 }
156
157 };
158
159
161 MatrixDouble grads; ///< Gradients of field "u" at integration points
162 VectorDouble values; ///< Values of field "u" at integration points
163 VectorDouble dot_values; ///< Rate of values of field "u" at integration points
165
166 MatrixDouble invJac; ///< Inverse of element jacobian
167
169 };
170
171
172 template <int DIM> struct OpAssembleStiffRhs : OpVolEle {
173
175 boost::shared_ptr<PreviousData> &data,
176 std::map<int, BlockData> &block_map)
178 , setOfBlock(block_map) {}
179
180 MoFEMErrorCode doWork(int side, EntityType type, EntData &data) {
182 const int nb_dofs = data.getIndices().size();
183 if (nb_dofs) {
184 auto find_block_data = [&]() {
186 BlockData *block_raw_ptr = nullptr;
187 for (auto &m : setOfBlock) {
188 if (m.second.block_ents.find(fe_ent) != m.second.block_ents.end()) {
189 block_raw_ptr = &m.second;
190 break;
191 }
192 }
193 return block_raw_ptr;
194 };
195
196 auto block_data_ptr = find_block_data();
197 if (!block_data_ptr)
198 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY, "Block not found");
199
200 auto &block_data = *block_data_ptr;
201
202 vecF.resize(nb_dofs, false);
203 vecF.clear();
204 const int nb_integration_pts = getGaussPts().size2();
205
206 auto t_dot_val = getFTensor0FromVec(commonData->dot_values);
207 auto t_val = getFTensor0FromVec(commonData->values);
208 auto t_grad = getFTensor1FromMat<DIM>(commonData->grads);
209
210 auto t_base = data.getFTensor0N();
211 auto t_diff_base = data.getFTensor1DiffN<DIM>();
212 auto t_w = getFTensor0IntegrationWeight();
213
215
216
217 const double vol = getMeasure();
218
219 for (int gg = 0; gg != nb_integration_pts; ++gg) {
220 const double a = vol * t_w;
221
222 const double K_h = block_data.get_conductivity(t_val);
223 const double C_h = block_data.get_capacity(t_val);
224
225
226
227
228 for (int rr = 0; rr != nb_dofs; ++rr) {
229 vecF[rr] += a * (t_base * C_h * t_dot_val + K_h *
230 (t_diff_base(i) * t_grad(i) - 0.*t_diff_base(2)));
231 ++t_diff_base;
232 ++t_base;
233 }
234 // cout << "vecF : " << vecF << endl;
235 ++t_dot_val;
236 ++t_grad;
237 ++t_val;
238 ++t_w;
239 }
240 CHKERR VecSetOption(getFEMethod()->ts_F, VEC_IGNORE_NEGATIVE_INDICES,
241 PETSC_TRUE);
242 CHKERR VecSetValues(getFEMethod()->ts_F, data, &*vecF.begin(),
243 ADD_VALUES);
244 }
246 }
247
248 private:
249 boost::shared_ptr<PreviousData> commonData;
250 std::map<int, BlockData> setOfBlock;
252 std::string field;
253 };
254
255 template <int DIM> struct OpAssembleStiffLhs : OpVolEle {
256
257 OpAssembleStiffLhs(std::string fieldu,
258 boost::shared_ptr<PreviousData> &data,
259 std::map<int, BlockData> &block_map)
260 : OpVolEle(fieldu, fieldu, OpVolEle::OPROWCOL), commonData(data), setOfBlock(block_map) {
261 sYmm = true;
262 }
263 MoFEMErrorCode doWork(int row_side, int col_side, EntityType row_type,
264 EntityType col_type, EntData &row_data,
265 EntData &col_data) {
267
268 const int nb_row_dofs = row_data.getIndices().size();
269 const int nb_col_dofs = col_data.getIndices().size();
270 // cerr << "In doWork() : (row, col) = (" << nb_row_dofs << ", " <<
271 // nb_col_dofs << ")" << endl;
272 if (nb_row_dofs && nb_col_dofs) {
273 auto find_block_data = [&]() {
275 BlockData *block_raw_ptr = nullptr;
276 for (auto &m : setOfBlock) {
277 if (m.second.block_ents.find(fe_ent) != m.second.block_ents.end()) {
278 block_raw_ptr = &m.second;
279 break;
280 }
281 }
282 return block_raw_ptr;
283 };
284
285 auto block_data_ptr = find_block_data();
286 if (!block_data_ptr)
287 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY, "Block not found");
288
289 auto &block_data = *block_data_ptr;
290
291 mat.resize(nb_row_dofs, nb_col_dofs, false);
292 mat.clear();
293 const int nb_integration_pts = getGaussPts().size2();
294 auto t_row_base = row_data.getFTensor0N();
295
296
297 auto t_val = getFTensor0FromVec(commonData->values);
298 auto t_dot_val = getFTensor0FromVec(commonData->dot_values);
299 auto t_grad = getFTensor1FromMat<DIM>(commonData->grads);
300
301 auto t_row_diff_base = row_data.getFTensor1DiffN<DIM>();
302 auto t_w = getFTensor0IntegrationWeight();
303 const double ts_a = getFEMethod()->ts_a;
304 const double vol = getMeasure();
305
307
308 // cout << "B0 : " << block_data.B0 << endl;
309
310 for (int gg = 0; gg != nb_integration_pts; ++gg) {
311 const double a = vol * t_w;
312 const double K_h = block_data.get_conductivity(t_val);
313 const double C_h = block_data.get_capacity(t_val);
314 const double DK_h = block_data.get_diffConductivity(t_val);
315 const double DC_h = block_data.get_diffCapacity(t_val);
316
317 // cout << "C_h : " << C_h << endl;
318 // t_grad(2) = t_grad(2) - 1;
319 for (int rr = 0; rr != nb_row_dofs; ++rr) {
320 auto t_col_base = col_data.getFTensor0N(gg, 0);
321 auto t_col_diff_base = col_data.getFTensor1DiffN<DIM>(gg, 0);
322 for (int cc = 0; cc != nb_col_dofs; ++cc) {
323
324 mat(rr, cc) +=
325 a * (t_row_base * (DC_h * t_dot_val + C_h * ts_a) * t_col_base +
326 DK_h * t_grad(i) * t_row_diff_base(i) * t_col_base + K_h * t_row_diff_base(i) * t_col_diff_base(i));
327
328 ++t_col_base;
329 ++t_col_diff_base;
330 }
331 // cout << "mat : " << mat << endl;
332 ++t_row_base;
333 ++t_row_diff_base;
334 }
335 ++t_w;
336 ++t_val;
337 ++t_grad;
338 ++t_dot_val;
339 }
340 CHKERR MatSetValues(getFEMethod()->ts_B, row_data, col_data, &mat(0, 0),
341 ADD_VALUES);
342 if (row_side != col_side || row_type != col_type) {
343 transMat.resize(nb_col_dofs, nb_row_dofs, false);
344 noalias(transMat) = trans(mat);
345 CHKERR MatSetValues(getFEMethod()->ts_B, col_data, row_data,
346 &transMat(0, 0), ADD_VALUES);
347 }
348 }
350 }
351
352 private:
353 boost::shared_ptr<PreviousData> commonData;
354 std::map<int, BlockData> setOfBlock;
356 };
357
359 {
361 : OpFaceEle(mass_field, OpFaceEle::OPROW),
363 }
364
365 MoFEMErrorCode doWork(int side, EntityType type, EntData &data) {
367 const int nb_dofs = data.getIndices().size();
368
369 if (nb_dofs) {
370 EntityHandle row_side_ent = getFEEntityHandle();
371 bool is_natural =
372 (natural_bd_ents.find(row_side_ent) != natural_bd_ents.end());
373 if (is_natural) {
374 // cerr << "In NaturalBCRhsTau..." << endl;
375 vecF.resize(nb_dofs, false);
376 vecF.clear();
377 const int nb_integration_pts = getGaussPts().size2();
378 auto t_row_base = data.getFTensor0N();
379
380
381 auto t_w = getFTensor0IntegrationWeight();
382 const double vol = getMeasure();
383
384 for (int gg = 0; gg != nb_integration_pts; ++gg) {
385 const double a = vol * t_w;
386
387 double h = natural_bc_values;
388 for (int rr = 0; rr != nb_dofs; ++rr) {
389 vecF[rr] += t_row_base * h * a;
390 ++t_row_base;
391 }
392 // cout << "vecF : " << vecF << endl;
393 ++t_w;
394 }
395 CHKERR VecSetOption(getFEMethod()->ts_F, VEC_IGNORE_NEGATIVE_INDICES,
396 PETSC_TRUE);
397 CHKERR VecSetValues(getFEMethod()->ts_F, data, &*vecF.begin(),
398 ADD_VALUES);
399 }
400 }
402 }
403
404 private:
407 };
408
409
410
411 struct Monitor : public FEMethod {
412 double &eRror;
413 Monitor(MPI_Comm &comm, const int &rank, SmartPetscObj<DM> &dm,
414 boost::shared_ptr<PostProcVolumeOnRefinedMesh> &post_proc, double &err)
415 : cOmm(comm)
416 , rAnk(rank)
417 , dM(dm)
418 , postProc(post_proc)
419 , eRror(err){};
424 if (ts_step % save_every_nth_step == 0) {
426 CHKERR postProc->writeFile(
427 "out_level_" + boost::lexical_cast<std::string>(ts_step) + ".h5m");
428 }
429
431 }
432
433 private:
435 boost::shared_ptr<PostProcVolumeOnRefinedMesh> postProc;
436 MPI_Comm cOmm;
437 const int rAnk;
438 };
439
440}; // end UFOperators namespace
441
442#endif
constexpr double a
#define MoFEMFunctionBegin
First executable line of each MoFEM function, used for error handling. Final line of MoFEM functions ...
Definition: definitions.h:346
@ MOFEM_DATA_INCONSISTENCY
Definition: definitions.h:31
#define MoFEMFunctionReturn(a)
Last executable line of each PETSc function used for error handling. Replaces return()
Definition: definitions.h:416
#define CHKERR
Inline error check.
Definition: definitions.h:535
FTensor::Index< 'm', SPACE_DIM > m
PetscErrorCode DMoFEMLoopFiniteElements(DM dm, const char fe_name[], MoFEM::FEMethod *method, CacheTupleWeakPtr cache_ptr=CacheTupleSharedPtr())
Executes FEMethod for finite elements in DM.
Definition: DMMoFEM.cpp:572
PetscErrorCode MoFEMErrorCode
MoFEM/PETSc error code.
Definition: Exceptions.hpp:56
MoFEMErrorCode MatSetValues(Mat M, const EntitiesFieldData::EntData &row_data, const EntitiesFieldData::EntData &col_data, const double *ptr, InsertMode iora)
Assemble PETSc matrix.
static auto getFTensor0FromVec(ublas::vector< T, A > &data)
Get tensor rank 0 (scalar) form data vector.
Definition: Templates.hpp:135
MoFEMErrorCode VecSetValues(Vec V, const EntitiesFieldData::EntData &data, const double *ptr, InsertMode iora)
Assemble PETSc vector.
DataForcesAndSourcesCore::EntData EntData
const double essential_bc_values
const double natural_bc_values
FTensor::Index< 'i', 3 > i
double h
bool sYmm
If true assume that matrix is symmetric structure.
structure for User Loop Methods on finite elements
EntityHandle getFEEntityHandle() const
Return finite element entity handle.
auto getFTensor0IntegrationWeight()
Get integration weights.
double getMeasure() const
get measure of element
@ OPROW
operator doWork function is executed on FE rows
@ OPROWCOL
operator doWork is executed on FE rows &columns
const FEMethod * getFEMethod() const
Return raw pointer to Finite Element Method object.
MatrixDouble & getGaussPts()
matrix of integration (Gauss) points for Volume Element
intrusive_ptr for managing petsc objects
PetscReal ts_a
shift for U_t (see PETSc Time Solver)
PetscInt ts_step
time step number
double get_diffCapacity(double head)
double get_conductivity(double head)
double get_diffEffSatuStar(double s_e)
double get_waterContent(double head)
double get_relativeConductivity(double head)
double get_Fe(double eff_satu)
double get_diffRelativeConductivity(double head)
double get_eff_satuStar(double eff_satu)
double get_diffEffSaturation(double head)
double get_effSaturation(double head)
double get_diffConductivity(double head)
MoFEMErrorCode operator()()
function is run for every finite element
Monitor(MPI_Comm &comm, const int &rank, SmartPetscObj< DM > &dm, boost::shared_ptr< PostProcVolumeOnRefinedMesh > &post_proc, double &err)
boost::shared_ptr< PostProcVolumeOnRefinedMesh > postProc
MoFEMErrorCode postProcess()
function is run at the end of loop
MoFEMErrorCode preProcess()
function is run at the beginning of loop
OpAssembleNaturalBCRhs(std::string mass_field, Range &natural_bd_ents)
MoFEMErrorCode doWork(int side, EntityType type, EntData &data)
OpAssembleStiffLhs(std::string fieldu, boost::shared_ptr< PreviousData > &data, std::map< int, BlockData > &block_map)
MoFEMErrorCode doWork(int row_side, int col_side, EntityType row_type, EntityType col_type, EntData &row_data, EntData &col_data)
boost::shared_ptr< PreviousData > commonData
boost::shared_ptr< PreviousData > commonData
MoFEMErrorCode doWork(int side, EntityType type, EntData &data)
OpAssembleStiffRhs(std::string field, boost::shared_ptr< PreviousData > &data, std::map< int, BlockData > &block_map)
MatrixDouble invJac
Inverse of element jacobian.
VectorDouble dot_values
Rate of values of field "u" at integration points.
VectorDouble values
Values of field "u" at integration points.
MatrixDouble grads
Gradients of field "u" at integration points.