Directory: | ./ |
---|---|
File: | Solver/linearProblemPoroElasticity.cpp |
Date: | 2024-04-14 07:32:34 |
Exec | Total | Coverage | |
---|---|---|---|
Lines: | 127 | 300 | 42.3% |
Branches: | 135 | 614 | 22.0% |
Line | Branch | Exec | Source |
---|---|---|---|
1 | // ______ ______ _ _ _____ ______ | ||
2 | // | ____| ____| | (_)/ ____| | ____| | ||
3 | // | |__ | |__ | | _| (___ ___| |__ | ||
4 | // | __| | __| | | | |\___ \ / __| __| | ||
5 | // | | | |____| |____| |____) | (__| |____ | ||
6 | // |_| |______|______|_|_____/ \___|______| | ||
7 | // Finite Elements for Life Sciences and Engineering | ||
8 | // | ||
9 | // License: LGL2.1 License | ||
10 | // FELiScE default license: LICENSE in root folder | ||
11 | // | ||
12 | // Main authors: | ||
13 | // | ||
14 | |||
15 | // System includes | ||
16 | |||
17 | // External includes | ||
18 | |||
19 | // Project includes | ||
20 | #include "Solver/linearProblemPoroElasticity.hpp" | ||
21 | #include "FiniteElement/elementVector.hpp" | ||
22 | #include "FiniteElement/elementMatrix.hpp" | ||
23 | #include "InputOutput/io.hpp" | ||
24 | |||
25 | namespace felisce { | ||
26 | 2 | LinearProblemPoroElasticity::LinearProblemPoroElasticity(): | |
27 |
7/14✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 2 times.
✗ Branch 6 not taken.
✓ Branch 10 taken 2 times.
✗ Branch 11 not taken.
✓ Branch 13 taken 2 times.
✗ Branch 14 not taken.
✓ Branch 17 taken 2 times.
✗ Branch 18 not taken.
✓ Branch 20 taken 2 times.
✗ Branch 21 not taken.
✓ Branch 23 taken 2 times.
✗ Branch 24 not taken.
|
2 | LinearProblem("Linear Poro Elasticity",/*number of matrices*/2) { |
28 | |||
29 | // Default value for the initial (constant) pressure | ||
30 | 2 | m_pInit=0; | |
31 | |||
32 | //========Initialization of the PetscVectors=============// | ||
33 | 2 | std::vector<std::string> listPar,listSeq; | |
34 | |||
35 |
1/2✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
|
2 | listPar.emplace_back("solutionPreviousTimeStep"); |
36 |
1/2✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
|
2 | listSeq.emplace_back("solutionPreviousTimeStep"); |
37 | |||
38 |
1/2✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
|
2 | listPar.emplace_back("filtrationVelocity"); |
39 |
1/2✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
|
2 | listSeq.emplace_back("filtrationVelocity"); |
40 | |||
41 | // We do not need the sequential counterpart. | ||
42 |
1/2✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
|
2 | listPar.emplace_back("massTimesPressureGradient"); |
43 | |||
44 |
1/2✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
|
2 | listPar.emplace_back("pressureGradient"); |
45 |
1/2✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
|
2 | listSeq.emplace_back("pressureGradient"); |
46 | |||
47 | // We do not need the sequential counterpart; | ||
48 |
1/2✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
|
2 | listPar.emplace_back("anisotropicDirection"); |
49 | |||
50 |
2/2✓ Branch 1 taken 10 times.
✓ Branch 2 taken 2 times.
|
12 | for( std::size_t k(0); k<listPar.size();++k) { |
51 |
2/4✓ Branch 2 taken 10 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 10 times.
✗ Branch 6 not taken.
|
10 | m_vecs.Init(listPar[k]); |
52 | } | ||
53 |
2/2✓ Branch 1 taken 6 times.
✓ Branch 2 taken 2 times.
|
8 | for( std::size_t k(0); k<listSeq.size();++k) { |
54 |
2/4✓ Branch 2 taken 6 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 6 times.
✗ Branch 6 not taken.
|
6 | m_seqVecs.Init(listSeq[k]); |
55 | } | ||
56 | |||
57 | |||
58 | // Default value | ||
59 | 2 | m_matricesForFiltrationVelocityBuilt=false; | |
60 | |||
61 | //==============Scaling the value of the boundary conditions========// | ||
62 | // Not tested too much. | ||
63 |
2/4✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 2 times.
|
2 | if ( FelisceParam::instance().scalePressureEq ) { |
64 | ✗ | int c(0); | |
65 | ✗ | for ( std::size_t k(0); k<FelisceParam::instance().variable.size(); ++k) { | |
66 | ✗ | std::cout<<"Considering BC number: "<<k | |
67 | ✗ | <<" var: "<<FelisceParam::instance().variable[k] | |
68 | ✗ | <<" comp: "<<FelisceParam::instance().component[k] | |
69 | ✗ | <<" type: "<<FelisceParam::instance().type[k] | |
70 | ✗ | <<" value: "<<FelisceParam::instance().value[k] | |
71 | ✗ | <<std::endl; | |
72 | ✗ | int n(2); | |
73 | ✗ | if ( FelisceParam::instance().component[k] == "Comp123" ) | |
74 | ✗ | n=3; | |
75 | ✗ | if ( FelisceParam::instance().component[k] == "Comp1" || | |
76 | ✗ | FelisceParam::instance().component[k] == "CompNA" ) | |
77 | ✗ | n=1; | |
78 | |||
79 | ✗ | if ( FelisceParam::instance().variable[k] == "pressure" ) { | |
80 | ✗ | if ( FelisceParam::instance().type[k] == "Neumann" ) { | |
81 | ✗ | std::cout<<"Rescaling "<<k<<"th bc. Values from "<<c<<" to "<<c+n-1<<std::endl; | |
82 | ✗ | for ( int j(0); j<n; ++j ) { | |
83 | ✗ | std::cout<<FelisceParam::instance().value[c+j]<<" --> "; | |
84 | ✗ | FelisceParam::instance().value[c+j] *= FelisceParam::instance().timeStep*FelisceParam::instance().biotModulus; | |
85 | ✗ | std::cout<<FelisceParam::instance().value[c+j]<<std::endl; | |
86 | } | ||
87 | } else { | ||
88 | ✗ | std::cout<<"Bc n."<<k<<" was not rescaled because it was not of type neumann"<<std::endl; | |
89 | } | ||
90 | } | ||
91 | ✗ | c=c+n; | |
92 | } | ||
93 | } | ||
94 | 2 | } | |
95 | 2 | void LinearProblemPoroElasticity::initialize(std::vector<GeometricMeshRegion::Pointer>& mesh, FelisceTransient::Pointer fstransient, MPI_Comm& comm, bool doUseSNES) { | |
96 |
1/2✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
|
2 | LinearProblem::initialize(mesh,comm,doUseSNES); |
97 | |||
98 | //=================Setting the physical parameters=================// | ||
99 | 2 | m_fstransient=fstransient; | |
100 | |||
101 |
5/10✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 2 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 2 times.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✓ Branch 9 taken 2 times.
✗ Branch 10 not taken.
✓ Branch 11 taken 2 times.
|
2 | if ( FelisceParam::instance().young < 0 || FelisceParam::instance().poisson < 0 ) { |
102 | ✗ | m_mu = FelisceParam::instance().mu_lame; | |
103 | ✗ | m_lambda = FelisceParam::instance().lambda_lame; | |
104 | } else { | ||
105 |
2/4✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
|
2 | m_mu = FelisceParam::instance().young/2/(1+FelisceParam::instance().poisson); |
106 |
4/8✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 2 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 2 times.
✗ Branch 11 not taken.
|
2 | m_lambda = FelisceParam::instance().young*FelisceParam::instance().poisson/(1.+FelisceParam::instance().poisson)/(1.-2.*FelisceParam::instance().poisson); |
107 | } | ||
108 |
1/2✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
|
2 | m_deltaT = FelisceParam::instance().timeStep; |
109 |
1/2✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
|
2 | m_b = FelisceParam::instance().biotCoefficient; |
110 |
1/2✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
|
2 | m_M = FelisceParam::instance().biotModulus; |
111 |
1/2✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
|
2 | m_k0 = FelisceParam::instance().isoPermeab; |
112 |
1/2✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
|
2 | m_k1 = FelisceParam::instance().anisoPermeab; |
113 | |||
114 |
1/2✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
|
2 | this->displayPoroElasticProperties(); |
115 | |||
116 | |||
117 | //================Initializing variables and unknowns=============// | ||
118 | 2 | std::vector<PhysicalVariable> listVariable; | |
119 | 2 | std::vector<std::size_t> listNumComp; | |
120 | |||
121 | // Displacement | ||
122 |
1/2✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
|
2 | listVariable.push_back(displacement); |
123 |
1/2✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
|
2 | listNumComp.push_back(this->dimension()); |
124 | // Pore-pressure | ||
125 |
1/2✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
|
2 | listVariable.push_back(pressure); |
126 |
1/2✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
|
2 | listNumComp.push_back(1); |
127 | |||
128 |
1/2✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
|
2 | userAddOtherVariables(listVariable,listNumComp); |
129 | |||
130 | // Declare them as unknown of the linear system | ||
131 |
1/2✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
|
2 | m_listUnknown.push_back(displacement); |
132 |
1/2✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
|
2 | m_listUnknown.push_back(pressure); |
133 | |||
134 | // Declare them as physical variable | ||
135 |
1/2✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
|
2 | this->definePhysicalVariable(listVariable,listNumComp); |
136 | |||
137 | // Save the variable id of the displacement and of the pressure | ||
138 |
1/2✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
|
2 | m_iDisplacement = this->listVariable().getVariableIdList(displacement); |
139 |
1/2✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
|
2 | m_iPressure = this->listVariable().getVariableIdList(pressure); |
140 | 2 | } | |
141 | |||
142 | 2 | void LinearProblemPoroElasticity::displayPoroElasticProperties() const { | |
143 | // drained parameters | ||
144 | 2 | double shearD = m_mu; | |
145 | 2 | double lambdaD = m_lambda; | |
146 | 2 | double bulkD = lambdaD+2./3.*shearD; | |
147 | 2 | double poissonD = (3*bulkD-2*shearD)/2/(3*bulkD+shearD); | |
148 | 2 | double youngD = 9*bulkD*shearD/(3*bulkD+shearD); | |
149 | |||
150 | // undrained parameters | ||
151 | 2 | double shearU = shearD; | |
152 | 2 | double lambdaU = lambdaD + m_b*m_b*m_M; | |
153 | 2 | double bulkU = bulkD + m_b*m_b*m_M; | |
154 | 2 | double poissonU = lambdaU / (2*(lambdaU+shearD)); | |
155 | 2 | double youngU = (1+poissonU)/(1+poissonD)*youngD; | |
156 | |||
157 |
1/2✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
|
2 | std::stringstream msg; |
158 |
2/4✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
|
2 | msg<<"========================================" << std::endl; |
159 |
2/4✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
|
2 | msg<<"--- DRAINED PROPERTIES (p=0):" << std::endl; |
160 |
3/6✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 2 times.
✗ Branch 8 not taken.
|
2 | msg<<" Shear Modulus (G or mu): "<< shearD << std::endl; |
161 |
3/6✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 2 times.
✗ Branch 8 not taken.
|
2 | msg<<" Lame's coefficient (lambda): "<< lambdaD << std::endl; |
162 |
3/6✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 2 times.
✗ Branch 8 not taken.
|
2 | msg<<" Bulk modulus (K): "<< bulkD << std::endl; |
163 |
3/6✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 2 times.
✗ Branch 8 not taken.
|
2 | msg<<" Young Modulus: " << youngD << std::endl; |
164 |
3/6✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 2 times.
✗ Branch 8 not taken.
|
2 | msg<<" Poisson ratio: "<< poissonD << std::endl; |
165 | |||
166 |
2/4✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
|
2 | msg<<"--- UNDRAINED PROPERTIES (no extra mass):" << std::endl; |
167 |
3/6✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 2 times.
✗ Branch 8 not taken.
|
2 | msg<<" Shear Modulus (G or mu): "<< shearU << std::endl; |
168 |
3/6✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 2 times.
✗ Branch 8 not taken.
|
2 | msg<<" Lame's coefficient (lambda): "<< lambdaU << std::endl; |
169 |
3/6✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 2 times.
✗ Branch 8 not taken.
|
2 | msg<<" Bulk modulus (K): "<< bulkU << std::endl; |
170 |
3/6✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 2 times.
✗ Branch 8 not taken.
|
2 | msg<<" Young Modulus: " << youngU << std::endl; |
171 |
3/6✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 2 times.
✗ Branch 8 not taken.
|
2 | msg<<" Poisson ratio: "<< poissonU << std::endl; |
172 | |||
173 |
2/4✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
|
2 | msg<<"--- OTHER PARAMETERS-----"<<std::endl; |
174 |
3/6✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 2 times.
✗ Branch 8 not taken.
|
2 | msg<<" Time step: "<< m_deltaT << std::endl; |
175 |
3/6✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 2 times.
✗ Branch 8 not taken.
|
2 | msg<<" Biot coefficient(b): "<< m_b << std::endl; |
176 |
3/6✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 2 times.
✗ Branch 8 not taken.
|
2 | msg<<" Biot modulus (M): "<< m_M << std::endl; |
177 |
3/6✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 2 times.
✗ Branch 8 not taken.
|
2 | msg<<" Isotropic permeability (k0)"<< m_k0<<std::endl; |
178 |
3/6✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 2 times.
✗ Branch 8 not taken.
|
2 | msg<<" Ansotropic permeability (k1)"<< m_k1<<std::endl; |
179 | |||
180 |
3/6✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 2 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 2 times.
✗ Branch 9 not taken.
|
2 | PetscPrintf(MpiInfo::petscComm(),"%s",msg.str().c_str()); |
181 | 2 | } | |
182 | 22 | void LinearProblemPoroElasticity::initPerElementType(ElementType /*eltType*/, FlagMatrixRHS /*flagMatrixRHS*/) { | |
183 | // Pointers to the current finite element. | ||
184 | 22 | m_feDisp = m_listCurrentFiniteElement[m_iDisplacement]; | |
185 | 22 | m_fePre = m_listCurrentFiniteElement[m_iPressure]; | |
186 | |||
187 | // Element fields to store the old values of displacement and pore-pressure | ||
188 | 22 | m_elemFieldDisplacement.initialize(DOF_FIELD,*m_feDisp,this->dimension()); | |
189 | 22 | m_elemFieldPressure.initialize(DOF_FIELD,*m_fePre,1); | |
190 | 22 | } | |
191 | |||
192 | 18 | void LinearProblemPoroElasticity::advanceInTime() { | |
193 | |||
194 | // User dependent computations. | ||
195 | 18 | userPostProcessing(); | |
196 | |||
197 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 18 times.
|
18 | if ( FelisceParam::instance().exportFiltrationVelocity) { |
198 | // Computation of filtration velocity. | ||
199 | ✗ | if ( ! m_matricesForFiltrationVelocityBuilt ) { | |
200 | ✗ | this->assembleMatricesForFiltrationVelocity(); | |
201 | ✗ | m_matricesForFiltrationVelocityBuilt = true; | |
202 | } | ||
203 | ✗ | this->computeFiltrationVelocity(); | |
204 | } | ||
205 | // Move forward | ||
206 |
3/6✓ Branch 2 taken 18 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 18 times.
✗ Branch 6 not taken.
✓ Branch 9 taken 18 times.
✗ Branch 10 not taken.
|
18 | m_vecs.Get("solutionPreviousTimeStep").copyFrom(this->solution()); |
207 |
2/4✓ Branch 2 taken 18 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 18 times.
✗ Branch 6 not taken.
|
18 | this->gather("solutionPreviousTimeStep"); |
208 | 18 | } | |
209 | |||
210 | 2662 | void LinearProblemPoroElasticity::computeElementArray(const std::vector<Point*>& elemPoint, const std::vector<felInt>& /*elemIdPoint*/, felInt& iel, FlagMatrixRHS flagMatrixRHS) { | |
211 | |||
212 | // UPDATE PHASE: | ||
213 | // -- of the finite element | ||
214 | 2662 | m_feDisp->updateFirstDeriv(0, elemPoint); | |
215 | 2662 | m_fePre->updateFirstDeriv(0, elemPoint); | |
216 | // -- of the anisotropic permeability direction | ||
217 | 2662 | updateAnisotropicDirection(elemPoint); | |
218 | // -- of the elementfields | ||
219 |
2/2✓ Branch 1 taken 242 times.
✓ Branch 2 taken 2420 times.
|
2662 | if (m_fstransient->iteration == 1) { // Setting intial condition on the pressure |
220 | 242 | m_elemFieldPressure.setValue(m_pInit,0); | |
221 | } else { | ||
222 |
3/6✓ Branch 3 taken 2420 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 2420 times.
✗ Branch 7 not taken.
✓ Branch 9 taken 2420 times.
✗ Branch 10 not taken.
|
2420 | m_elemFieldPressure.setValue(m_seqVecs.Get("solutionPreviousTimeStep") ,*m_fePre,iel,m_iPressure,m_ao,dof()); |
223 | } | ||
224 |
3/6✓ Branch 3 taken 2662 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 2662 times.
✗ Branch 7 not taken.
✓ Branch 9 taken 2662 times.
✗ Branch 10 not taken.
|
2662 | m_elemFieldDisplacement.setValue(m_seqVecs.Get("solutionPreviousTimeStep"),*m_feDisp,iel,m_iDisplacement,m_ao,dof()); |
225 | |||
226 | |||
227 | // Wether the pressure equation should be multiplied by (dt*M) or by one. | ||
228 | 2662 | double scalingCoeff(1.); | |
229 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 2662 times.
|
2662 | if ( FelisceParam::instance().scalePressureEq ) |
230 | ✗ | scalingCoeff = m_deltaT*m_M; | |
231 | |||
232 | 2662 | felInt pressureBlock( this->dimension() ); | |
233 | 2662 | felInt displacementBlock(0); | |
234 |
1/4✗ Branch 0 not taken.
✓ Branch 1 taken 2662 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
|
2662 | if ( (flagMatrixRHS == FlagMatrixRHS::matrix_and_rhs) || (flagMatrixRHS == FlagMatrixRHS::only_matrix)) { |
235 |
2/2✓ Branch 1 taken 242 times.
✓ Branch 2 taken 2420 times.
|
2662 | if ( m_fstransient->iteration == 0 ) { |
236 | 242 | std::size_t idMat = 1;// Everything should be placed in the static matrix (idMat=1) | |
237 | //! ==================================DISPLACEMENT EQUATION======================================================= | ||
238 | //! Displacement equation: quasi-static, no mass here! | ||
239 | //! Divergence of the elastic component of the stress tensor just as in linear elasticity | ||
240 | 242 | m_elementMat[idMat]->eps_phi_i_eps_phi_j( 2*m_mu, *m_feDisp, /*iblock*/displacementBlock, /*jblock*/displacementBlock, /*numOfBlockRepetitions*/this->dimension()); | |
241 | 242 | m_elementMat[idMat]->div_phi_j_div_phi_i( m_lambda, *m_feDisp, /*iblock*/displacementBlock, /*jblock*/displacementBlock, /*numOfBlockRepetitions*/this->dimension()); | |
242 | //! now the pressure part | ||
243 | 242 | m_elementMat[idMat]->psi_j_div_phi_i(-m_b,*m_feDisp,*m_fePre , /*iblock*/displacementBlock, /*jblock*/pressureBlock); | |
244 | |||
245 | //! ==================================PRESSURE EQUATION=========================================================== | ||
246 | //! ------- First term coming from the time derivative of the divergence of the displacement | ||
247 | 242 | m_elementMat[idMat]->psi_i_div_phi_j(scalingCoeff*m_b/m_deltaT,*m_feDisp,*m_fePre, /*iblock*/pressureBlock,/*jblock*/displacementBlock); | |
248 | //! ------- First term coming from the time derivative of the pressure | ||
249 | 242 | m_elementMat[idMat]->phi_i_phi_j(scalingCoeff/(m_M*m_deltaT),*m_fePre,/*iblock*/pressureBlock,/*jblock*/pressureBlock,/*numOfBlockRepetitions*/1); | |
250 | |||
251 | // Pressure equation: laplacian terms. | ||
252 | // Anisotropic part of the diffusive term | ||
253 | 242 | m_elementMat[idMat]->tau_grad_phi_i_tau_grad_phi_j(scalingCoeff*m_k1,m_anisotropicDir,*m_fePre,/*iblock*/pressureBlock,/*jblock*/pressureBlock,/*nbOfBlockRep*/1,/*domain dim*/this->dimension()); | |
254 | // Isotropic part | ||
255 | 242 | m_elementMat[idMat]->grad_phi_i_grad_phi_j(scalingCoeff*m_k0,*m_fePre,/*iblock*/pressureBlock, /*jblock*/pressureBlock,/*numOfBlockRepetitions*/1); | |
256 | } | ||
257 | } | ||
258 | |||
259 | // Right hand side: | ||
260 |
1/4✗ Branch 0 not taken.
✓ Branch 1 taken 2662 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
|
2662 | if ( (flagMatrixRHS == FlagMatrixRHS::matrix_and_rhs) || (flagMatrixRHS == FlagMatrixRHS::only_rhs)) { |
261 | // Pressure equation: | ||
262 | // ------- Second term coming from the time derivative of the divergence of the displacement | ||
263 | 2662 | m_elementVector[0]->div_f_phi_i(scalingCoeff*m_b/m_deltaT, *m_feDisp,*m_fePre,m_elemFieldDisplacement,/*iblock*/pressureBlock); | |
264 | // ------- Second term coming from the time derivative of the pressure | ||
265 | 2662 | m_elementVector[0]->source(scalingCoeff/(m_M*m_deltaT), *m_fePre,m_elemFieldPressure,/*iblock*/pressureBlock,/*numOfBlockRepetitions*/1); | |
266 | } | ||
267 | // OTHER TERMS: | ||
268 | // Mass source and external load should be coded in userComputeElementArray | ||
269 | // Boundary terms such as Neumann force terms should be standard and therefore implemented in linearProblem.cpp | ||
270 | // Pay attention: | ||
271 | // if the pressure equation is multiplied by m_M you have to be consistent when coding the user files. | ||
272 | 2662 | } | |
273 | 2662 | void LinearProblemPoroElasticity::updateAnisotropicDirection(const std::vector<Point*>& /*elemPoint*/) { | |
274 | // By default there is no anisotropic permeability direction. | ||
275 | // --> Customize this function in the user | ||
276 |
2/2✓ Branch 1 taken 2 times.
✓ Branch 2 taken 2660 times.
|
2662 | if ( m_anisotropicDir.size() == 0) { |
277 | 2 | m_anisotropicDir.resize(this->dimension()*m_fePre->numDof()); | |
278 | } else { | ||
279 |
2/2✓ Branch 1 taken 15960 times.
✓ Branch 2 taken 2660 times.
|
18620 | for (std::size_t i(0); i < m_anisotropicDir.size(); ++i) { |
280 | 15960 | m_anisotropicDir[i]=0.0; | |
281 | } | ||
282 | } | ||
283 | 2662 | } | |
284 | // Exporting a zero-initial filtration velocity. | ||
285 | 2 | void LinearProblemPoroElasticity::exportInitialFiltrationVelocity(std::vector<IO::Pointer>& io) { | |
286 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
|
2 | if(FelisceParam::instance().exportFiltrationVelocity) { |
287 | ✗ | PetscVector zero; | |
288 | ✗ | zero.duplicateFrom(this->solution()); | |
289 | ✗ | zero.zeroEntries(); | |
290 | ✗ | std::stringstream msg; | |
291 | ✗ | msg<<"Writing filtration velocity"<<std::endl; | |
292 | ✗ | PetscPrintf(MpiInfo::petscComm(),"%s",msg.str().c_str()); | |
293 | ✗ | this->writeSolutionFromVec(zero, MpiInfo::rankProc(), io, m_fstransient->time, m_fstransient->iteration, std::string("filtrationVelocity")); | |
294 | // this->writeSolutionFromVec( zero, MpiInfo::rankProc(), io, m_fstransient->time, m_fstransient->iteration, std::string("anisotropicDirection")); | ||
295 | } | ||
296 | 2 | } | |
297 | |||
298 | 18 | void LinearProblemPoroElasticity::exportFiltrationVelocity(std::vector<IO::Pointer>& io) { | |
299 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 18 times.
|
18 | if( FelisceParam::instance().exportFiltrationVelocity ) { |
300 | ✗ | std::stringstream msg; | |
301 | ✗ | msg<<"Writing filtration velocity"<<std::endl; | |
302 | ✗ | PetscPrintf(MpiInfo::petscComm(),"%s",msg.str().c_str()); | |
303 | ✗ | this->writeSolutionFromVec(m_seqVecs.Get("filtrationVelocity"), | |
304 | ✗ | MpiInfo::rankProc(), | |
305 | io, | ||
306 | ✗ | m_fstransient->time, | |
307 | ✗ | m_fstransient->iteration, | |
308 | ✗ | std::string("filtrationVelocity")); | |
309 | // this->writeSolutionFromVec(m_vecs.Get("anisotropicDirection"), | ||
310 | // MpiInfo::rankProc(), | ||
311 | // io, | ||
312 | // m_fstransient->time, | ||
313 | // m_fstransient->iteration, | ||
314 | // std::string("anisotropicDirection")); | ||
315 | } | ||
316 | 18 | } | |
317 | |||
318 | ✗ | void LinearProblemPoroElasticity::assembleMatricesForFiltrationVelocity() { | |
319 | // Vector/Matrices intialization | ||
320 | ✗ | m_mass.duplicateFrom(matrix(0),MAT_DO_NOT_COPY_VALUES); | |
321 | ✗ | m_mass.zeroEntries(); | |
322 | ✗ | m_derivative.duplicateFrom(matrix(0),MAT_DO_NOT_COPY_VALUES); | |
323 | ✗ | m_derivative.zeroEntries(); | |
324 | |||
325 | ✗ | const auto& r_instance = FelisceParam::instance(this->instanceIndex()); | |
326 | ✗ | const std::string solver = r_instance.solver[m_identifier_solver]; | |
327 | ✗ | const std::string preconditioner = r_instance.preconditioner[m_identifier_solver]; | |
328 | ✗ | const double relativeTolerance = r_instance.relativeTolerance[m_identifier_solver]; | |
329 | ✗ | const double absoluteTolerance = r_instance.absoluteTolerance[m_identifier_solver]; | |
330 | ✗ | const int maxIteration = r_instance.maxIteration[m_identifier_solver]; | |
331 | ✗ | const int gmresRestart = r_instance.gmresRestart[m_identifier_solver]; | |
332 | ✗ | const bool initPrevSolution = r_instance.initSolverWithPreviousSolution[m_identifier_solver]; | |
333 | ✗ | m_kspForFiltrationVelocity->init(); | |
334 | ✗ | m_kspForFiltrationVelocity->setKSPandPCType(solver, preconditioner); | |
335 | ✗ | m_kspForFiltrationVelocity->setTolerances(relativeTolerance, absoluteTolerance, maxIteration, gmresRestart); | |
336 | ✗ | m_kspForFiltrationVelocity->setKSPOptions(solver, initPrevSolution); | |
337 | |||
338 | // Loop over the domain | ||
339 | // use to define a "global" numbering of element in the mesh. | ||
340 | felInt numElement[ GeometricMeshRegion::m_numTypesOfElement ]; | ||
341 | ✗ | for (int ityp=0; ityp<GeometricMeshRegion::m_numTypesOfElement; ityp++ ) { | |
342 | ✗ | ElementType eltType = (ElementType)ityp; | |
343 | ✗ | numElement[eltType] = 0; | |
344 | } | ||
345 | |||
346 | ✗ | std::vector<Point*> elemPoint; | |
347 | ✗ | std::vector<felInt> elemIdPoint; | |
348 | felInt ielSupportDof; | ||
349 | |||
350 | ✗ | const std::vector<ElementType>& bagElementTypeDomain = m_meshLocal[m_currentMesh]->bagElementTypeDomain(); | |
351 | ✗ | for (std::size_t i = 0; i < bagElementTypeDomain.size(); ++i) { | |
352 | ✗ | ElementType eltType = bagElementTypeDomain[i]; | |
353 | |||
354 | // resize array. | ||
355 | ✗ | int numPointPerElt = GeometricMeshRegion::m_numPointsPerElt[eltType]; | |
356 | ✗ | elemPoint.resize(numPointPerElt, nullptr); | |
357 | ✗ | elemIdPoint.resize(numPointPerElt, 0); | |
358 | |||
359 | ✗ | defineFiniteElement(eltType); | |
360 | ✗ | initElementArray(); | |
361 | ✗ | allocateArrayForAssembleMatrixRHS(FlagMatrixRHS::matrix_and_rhs); | |
362 | |||
363 | // virtual function use in derived problem to allocate elemenField necessary. | ||
364 | ✗ | initPerElementType(eltType, FlagMatrixRHS::only_matrix); | |
365 | // second loop on region of the mesh. | ||
366 | ✗ | for(auto itRef = m_meshLocal[m_currentMesh]->intRefToBegEndMaps[eltType].begin(); | |
367 | ✗ | itRef != m_meshLocal[m_currentMesh]->intRefToBegEndMaps[eltType].end(); itRef++) { | |
368 | // int currentLabel = itRef->first; | ||
369 | ✗ | felInt numEltPerLabel = itRef->second.second; | |
370 | // Third loop on element in the region with the type: eltType. ("real" loop on elements). | ||
371 | ✗ | for ( felInt iel = 0; iel < numEltPerLabel; iel++) { | |
372 | ✗ | setElemPoint(eltType, numElement[eltType], elemPoint, elemIdPoint, &ielSupportDof); | |
373 | |||
374 | // FE update | ||
375 | ✗ | m_listCurrentFiniteElement[1/*pressure*/]->updateFirstDeriv(0, elemPoint); | |
376 | |||
377 | // MASS | ||
378 | ✗ | m_elementMat[0]->zero(); | |
379 | ✗ | m_elementMat[0]->phi_i_phi_j(1., *m_listCurrentFiniteElement[1],0,0,this->dimension()+1); | |
380 | ✗ | setValueCustomMatrix(ielSupportDof,ielSupportDof,m_mass); | |
381 | |||
382 | // Derivative | ||
383 | ✗ | m_elementMat[0]->zero(); | |
384 | ✗ | for (int h(0); h<this->dimension();++h) { | |
385 | ✗ | m_elementMat[0]->dpsi_j_dh_psi_i(1.0,*m_listCurrentFiniteElement[1],*m_listCurrentFiniteElement[1], h, h, this->dimension()); | |
386 | } | ||
387 | ✗ | setValueCustomMatrix(ielSupportDof,ielSupportDof,m_derivative); | |
388 | |||
389 | ✗ | numElement[eltType]++; | |
390 | } | ||
391 | } | ||
392 | ✗ | desallocateArrayForAssembleMatrixRHS(FlagMatrixRHS::matrix_and_rhs); | |
393 | } | ||
394 | ✗ | m_mass.assembly(MAT_FINAL_ASSEMBLY); | |
395 | ✗ | m_derivative.assembly(MAT_FINAL_ASSEMBLY); | |
396 | |||
397 | ✗ | const std::string preconditionerOption = r_instance.setPreconditionerOption[m_identifier_solver]; | |
398 | ✗ | m_kspForFiltrationVelocity->setKSPOperator(m_mass, preconditionerOption); | |
399 | } | ||
400 | |||
401 | ✗ | void LinearProblemPoroElasticity::computeFiltrationVelocity() { | |
402 | ✗ | std::stringstream msg; | |
403 | ✗ | msg<<"Solution of the linear system to compute the filtration velocity: "<<std::endl; | |
404 | ✗ | PetscPrintf(MpiInfo::petscComm(),"%s",msg.str().c_str()); | |
405 | ✗ | mult(m_derivative,this->solution(),m_vecs.Get("massTimesPressureGradient")); // aux_i = < \nabla p, \phi_i > | |
406 | |||
407 | ✗ | const auto& r_instance = FelisceParam::instance(this->instanceIndex()); | |
408 | ✗ | m_kspForFiltrationVelocity->solve(m_vecs.Get("massTimesPressureGradient"), m_vecs.Get("pressureGradient"), r_instance.linearSolverVerbose); | |
409 | ✗ | this->gather("pressureGradient"); | |
410 | |||
411 | // correctly Perform the product v=Kv; | ||
412 | felInt numElement[ GeometricMeshRegion::m_numTypesOfElement ]; | ||
413 | ✗ | for (int ityp=0; ityp<GeometricMeshRegion::m_numTypesOfElement; ityp++ ) { | |
414 | ✗ | ElementType eltType = (ElementType)ityp; | |
415 | ✗ | numElement[eltType] = 0; | |
416 | } | ||
417 | |||
418 | ✗ | std::vector<Point*> elemPoint; | |
419 | ✗ | std::vector<felInt> elemIdPoint; | |
420 | felInt ielSupportDof; | ||
421 | |||
422 | ✗ | const std::vector<ElementType>& bagElementTypeDomain = m_meshLocal[m_currentMesh]->bagElementTypeDomain(); | |
423 | ✗ | for (std::size_t i = 0; i < bagElementTypeDomain.size(); ++i) { | |
424 | ✗ | ElementType eltType = bagElementTypeDomain[i]; | |
425 | |||
426 | // resize array. | ||
427 | ✗ | int numPointPerElt = GeometricMeshRegion::m_numPointsPerElt[eltType]; | |
428 | ✗ | elemPoint.resize(numPointPerElt, nullptr); | |
429 | ✗ | elemIdPoint.resize(numPointPerElt, 0); | |
430 | |||
431 | ✗ | defineFiniteElement(eltType); | |
432 | ✗ | initElementArray(); | |
433 | ✗ | allocateArrayForAssembleMatrixRHS(FlagMatrixRHS::matrix_and_rhs); | |
434 | |||
435 | // virtual function use in derived problem to allocate elemenField necessary. | ||
436 | ✗ | initPerElementType(eltType, FlagMatrixRHS::only_matrix); | |
437 | // second loop on region of the mesh. | ||
438 | ✗ | for(auto itRef = m_meshLocal[m_currentMesh]->intRefToBegEndMaps[eltType].begin(); | |
439 | ✗ | itRef != m_meshLocal[m_currentMesh]->intRefToBegEndMaps[eltType].end(); itRef++) { | |
440 | // int currentLabel = itRef->first; | ||
441 | ✗ | felInt numEltPerLabel = itRef->second.second; | |
442 | // Third loop on element in the region with the type: eltType. ("real" loop on elements). | ||
443 | ✗ | for ( felInt iel = 0; iel < numEltPerLabel; iel++) { | |
444 | ✗ | setElemPoint(eltType, numElement[eltType], elemPoint, elemIdPoint, &ielSupportDof); | |
445 | ✗ | this->updateAnisotropicDirection(elemPoint); | |
446 | |||
447 | ✗ | m_elementVector[0]->zero(); | |
448 | ✗ | felInt counter(0);//we assume the displacement is the first unknown | |
449 | ✗ | for (int icomp(0); icomp<this->dimension();++icomp) { | |
450 | ✗ | for ( int idof(0); idof<m_fePre->numDof(); ++idof) { | |
451 | ✗ | m_elementVector[0]->vec()(counter) = m_anisotropicDir[this->dimension()*idof+icomp]; | |
452 | ✗ | counter++; | |
453 | } | ||
454 | } | ||
455 | ✗ | setValueCustomVector(ielSupportDof,INSERT_VALUES,m_vecs.Get("anisotropicDirection")); | |
456 | |||
457 | ✗ | m_elementVector[0]->zero(); | |
458 | ✗ | counter=0;//we assume the displacement is the first unknown | |
459 | ✗ | for (int icomp(0); icomp<this->dimension();++icomp) { | |
460 | ✗ | for ( int idof(0); idof<m_fePre->numDof(); ++idof) { | |
461 | //identify physical point | ||
462 | double x,y,z; | ||
463 | ✗ | if ( (std::size_t)idof >= elemPoint.size() ) { // ONLY FOR P2, assuming prisms | |
464 | ✗ | x=0.5*(elemPoint[idof-3]->x()+elemPoint[idof-6]->x()); | |
465 | ✗ | y=0.5*(elemPoint[idof-3]->y()+elemPoint[idof-6]->y()); | |
466 | ✗ | z=0.5*(elemPoint[idof-3]->z()+elemPoint[idof-6]->z()); | |
467 | } else { | ||
468 | ✗ | x=elemPoint[idof]->x(); | |
469 | ✗ | y=elemPoint[idof]->y(); | |
470 | ✗ | z=elemPoint[idof]->z(); | |
471 | } | ||
472 | ✗ | for (int jcomp(0); jcomp<this->dimension();++jcomp) { | |
473 | //compute -phi(idof)*tensor(idof)_{icomp,jcomp} | ||
474 | ✗ | double val=m_k1*m_anisotropicDir[this->dimension()*idof+icomp]*m_anisotropicDir[this->dimension()*idof+jcomp]; | |
475 | ✗ | if (icomp==jcomp) | |
476 | ✗ | val+=m_k0; | |
477 | ✗ | val = -val*this->userEvaluatePorosity(x,y,z); | |
478 | |||
479 | //retrieving the good value from pressureGradient | ||
480 | double valOfGradP; | ||
481 | felInt gdof; | ||
482 | ✗ | dof().loc2glob(ielSupportDof,idof,0/*idVariable*/,jcomp,gdof); | |
483 | ✗ | AOApplicationToPetsc(ao(),1,&gdof); | |
484 | ✗ | m_seqVecs.Get("pressureGradient").getValues(1,&gdof,&valOfGradP); | |
485 | |||
486 | //summing | ||
487 | ✗ | m_elementVector[0]->vec()(counter) += val*valOfGradP; | |
488 | } | ||
489 | ✗ | counter++; | |
490 | } | ||
491 | } | ||
492 | ✗ | setValueCustomVector(ielSupportDof,INSERT_VALUES,m_vecs.Get("filtrationVelocity")); | |
493 | ✗ | numElement[eltType]++; | |
494 | } | ||
495 | } | ||
496 | ✗ | desallocateArrayForAssembleMatrixRHS(FlagMatrixRHS::matrix_and_rhs); | |
497 | } | ||
498 | ✗ | m_vecs.Get("filtrationVelocity").assembly(); | |
499 | ✗ | this->gather("filtrationVelocity"); | |
500 | } | ||
501 | |||
502 | #ifdef FELISCE_WITH_CVGRAPH | ||
503 | /*! \brief this function assemble the mass matrix at the boundary. | ||
504 | * And the KSP | ||
505 | */ | ||
506 | ✗ | void LinearProblemPoroElasticity::assembleMassBoundaryAndInitKSP( std::size_t iBD ) { | |
507 | ✗ | LinearProblem::assembleMassBoundaryAndInitKSP( &LinearProblemPoroElasticity::massMatrixComputer, | |
508 | ✗ | FelisceParam::instance().interfaceLabels, | |
509 | &LinearProblemPoroElasticity::initPerETMass, | ||
510 | &LinearProblemPoroElasticity::updateFE, | ||
511 | iBD); | ||
512 | } | ||
513 | |||
514 | |||
515 | |||
516 | /*! \brief Function to assemble the mass matrix | ||
517 | * Function to be called in the assemblyLoopBoundaryGeneral | ||
518 | */ | ||
519 | ✗ | void LinearProblemPoroElasticity::massMatrixComputer(felInt ielSupportDof) { | |
520 | ✗ | this->m_elementMatBD[0]->zero(); | |
521 | ✗ | this->m_elementMatBD[0]->phi_i_phi_j(/*coef*/1.,*m_curvFeDisp,/*iblock*/0,/*iblock*/0,this->dimension()); | |
522 | ✗ | this->setValueMatrixBD(ielSupportDof); | |
523 | } | ||
524 | void | ||
525 | ✗ | LinearProblemPoroElasticity::initPerETMass() { | |
526 | ✗ | felInt numDofTotal = 0; | |
527 | //pay attention this numDofTotal is bigger than expected since it counts for all the VARIABLES | ||
528 | ✗ | for (std::size_t iFe = 0; iFe < this->m_listCurvilinearFiniteElement.size(); iFe++) {//this loop is on variables while it should be on unknown | |
529 | ✗ | numDofTotal += this->m_listCurvilinearFiniteElement[iFe]->numDof()*this->m_listVariable[iFe].numComponent(); | |
530 | } | ||
531 | ✗ | m_globPosColumn.resize(numDofTotal); m_globPosRow.resize(numDofTotal); m_matrixValues.resize(numDofTotal*numDofTotal); | |
532 | |||
533 | ✗ | m_curvFeDisp = this->m_listCurvilinearFiniteElement[ m_iDisplacement ]; | |
534 | } | ||
535 | void | ||
536 | ✗ | LinearProblemPoroElasticity::updateFE(const std::vector<Point*>& elemPoint, const std::vector<int>&) { | |
537 | ✗ | m_curvFeDisp->updateMeasNormal(0, elemPoint); | |
538 | } | ||
539 | #endif | ||
540 | } | ||
541 |