Finite Element Domain Decomposition Library
FEDDLib
Loading...
Searching...
No Matches
NavierStokesAssFE_def.hpp
1#ifndef NAVIERSTOKESASSFE_def_hpp
2#define NAVIERSTOKESASSFE_def_hpp
3
12
13#include "feddlib/core/FE/Domain.hpp"
14#include "feddlib//core/FE/FE.hpp"
15#include "feddlib/problems/Solver/Preconditioner.hpp"
16#include "feddlib/core/General/BCBuilder.hpp"
17
18
19/*void sxOne2D(double* x, double* res, double t, double* parameter){
20
21 res[0] = 1.;
22 res[1] = 0.;
23 return;
24}
25
26void syOne2D(double* x, double* res, double t, double* parameter){
27
28 res[0] = 0.;
29 res[1] = 1.;
30
31 return;
32}
33void sDummyFunc(double* x, double* res, double t, double* parameter){
34
35 return;
36}
37
38double OneFunction(double* x, int* parameter)
39{
40 return 1.0;
41}*/
42
43namespace FEDD {
44
45
46
47template<class SC,class LO,class GO,class NO>
48NavierStokesAssFE<SC,LO,GO,NO>::NavierStokesAssFE( const DomainConstPtr_Type &domainVelocity, std::string FETypeVelocity, const DomainConstPtr_Type &domainPressure, std::string FETypePressure, ParameterListPtr_Type parameterList ):
49NonLinearProblem<SC,LO,GO,NO>( parameterList, domainVelocity->getComm() ),
50A_(),
51pressureIDsLoc(new vec_int_Type(2)),
52u_rep_(),
53p_rep_(),
54viscosity_element_() // Added here also viscosity field
55{
56
57 this->nonLinearTolerance_ = this->parameterList_->sublist("Parameter").get("relNonLinTol",1.0e-6);
58 this->initNOXParameters();
59
60 this->addVariable( domainVelocity , FETypeVelocity , "u" , domainVelocity->getDimension());
61 this->addVariable( domainPressure , FETypePressure , "p" , 1);
62 this->dim_ = this->getDomain(0)->getDimension();
63
64 u_rep_ = Teuchos::rcp( new MultiVector_Type( this->getDomain(0)->getMapVecFieldRepeated() ) );
65
66 p_rep_ = Teuchos::rcp( new MultiVector_Type( this->getDomain(1)->getMapRepeated() ) );
67
68 if (parameterList->sublist("Parameter").get("Calculate Coefficients",false)) {
69 vec2D_dbl_ptr_Type vectmpPointsPressure = domainPressure->getPointsUnique();
70 vec2D_dbl_Type::iterator it;
71 int front = -1;
72 int back = -1;
73 if (domainPressure->getDimension() == 2) {
74 it = find_if(vectmpPointsPressure->begin(), vectmpPointsPressure->end(),
75 [&] (const std::vector<double>& a){
76 if (a.at(0) >= 0.15-1.e-12 && a.at(0) <= 0.15+1.e-12
77 && a.at(1) >= 0.2-1.e-12 && a.at(1) <= 0.2+1.e-12) {
78 return true;
79 }
80 else {
81 return false;
82 }
83 });
84
85 if (it != vectmpPointsPressure->end()) {
86 front = distance(vectmpPointsPressure->begin(),it);
87 }
88 it = find_if(vectmpPointsPressure->begin(), vectmpPointsPressure->end(),
89 [&] (const std::vector<double>& a){
90 if (a.at(0) >= 0.25-1.e-12 && a.at(0) <= 0.25+1.e-12
91 && a.at(1) >= 0.2-1.e-12 && a.at(1) <= 0.2+1.e-12) {
92 return true;
93 }
94 else {
95 return false;
96 }
97 });
98
99 if (it != vectmpPointsPressure->end()) {
100 back = distance(vectmpPointsPressure->begin(),it);
101 }
102 pressureIDsLoc->at(0) = front;
103 pressureIDsLoc->at(1) = back;
104 }
105 else if(domainPressure->getDimension() == 3){
106#ifdef ASSERTS_WARNINGS
107 MYASSERT(false,"Not implemented to calc coefficients in 3D!");
108#endif
109 }
110 }
111
112}
113
114template<class SC,class LO,class GO,class NO>
115void NavierStokesAssFE<SC,LO,GO,NO>::info(){
116 this->infoProblem();
117 this->infoNonlinProblem();
118}
119
120template<class SC,class LO,class GO,class NO>
121void NavierStokesAssFE<SC,LO,GO,NO>::assemble( std::string type ) const{
122
123 if (type=="") {
124 if (this->verbose_)
125 std::cout << "-- Assembly Navier-Stokes ... " << std::endl;
126
127 assembleConstantMatrices();
128
129 if (this->verbose_)
130 std::cout << "done -- " << std::endl;
131 }
132 else
133 reAssemble( type );
134
135};
136
137template<class SC,class LO,class GO,class NO>
138void NavierStokesAssFE<SC,LO,GO,NO>::assembleConstantMatrices() const{
139
140 if (this->verbose_)
141 std::cout << "-- Assembly constant matrices Navier-Stokes ... " << std::flush;
142
143 double viscosity = this->parameterList_->sublist("Parameter").get("Viscosity",1.);
144 double density = this->parameterList_->sublist("Parameter").get("Density",1.);
145
146 // Egal welcher Wert, da OneFunction nicht von parameter abhaengt
147 int* dummy;
148
149 A_.reset(new Matrix_Type( this->getDomain(0)->getMapVecFieldUnique(), this->getDomain(0)->getDimension() * this->getDomain(0)->getApproxEntriesPerRow() ) );
150
151 MapConstPtr_Type pressureMap;
152 if ( this->getDomain(1)->getFEType() == "P0" )
153 pressureMap = this->getDomain(1)->getElementMap();
154 else
155 pressureMap = this->getDomain(1)->getMapUnique();
156
157 if (this->system_.is_null())
158 this->system_.reset(new BlockMatrix_Type(2));
159
160 if (this->residualVec_.is_null())
161 this->residualVec_.reset(new BlockMultiVector_Type(2));
162
163 MatrixPtr_Type B(new Matrix_Type( pressureMap, this->getDomain(0)->getDimension() * this->getDomain(0)->getApproxEntriesPerRow() ) );
164 MatrixPtr_Type BT(new Matrix_Type( this->getDomain(0)->getMapVecFieldUnique(), this->getDomain(1)->getDimension() * this->getDomain(1)->getApproxEntriesPerRow() ) );
165
166
167 this->system_->addBlock(A_,0,0);
168 this->system_->addBlock(BT,0,1);
169 this->system_->addBlock(B,1,0);
170
171 this->feFactory_->assemblyNavierStokes(this->dim_, this->getDomain(0)->getFEType(), this->getDomain(1)->getFEType(), 2, this->dim_,1,u_rep_,p_rep_,this->system_,this->residualVec_,this->coeff_, this->parameterList_,false, "Jacobian", true/*call fillComplete*/);
172
173 if ( !this->getFEType(0).compare("P1") ) {
174 MatrixPtr_Type C(new Matrix_Type( this->getDomain(1)->getMapUnique(), this->getDomain(1)->getApproxEntriesPerRow() ) );
175 this->feFactory_->assemblyBDStabilization( this->dim_, "P1", C, true);
176 C->resumeFill();
177 C->scale( -1. / ( viscosity * density ) );
178 C->fillComplete( pressureMap, pressureMap );
179
180 this->system_->addBlock( C, 1, 1 );
181 }
182
183 /*
184 If pressure projection is used, we need to assemble the projection vector here
185 Only for P2-P1 or Q2-Q1 elements in monolithic case
186 In case of a monolithic preconditioner and a P2-P1 discretization we have the option to correct the pressure to have mean value = 0. This way, generally, we can improve scalabilty and results.
187 The real correction is then done via projection in the Overlapping Operator of FROSch,here we only assemble a as \int p dx . a is assembled as a column vector but in the Dissertation of C. Hochmuth defined as row.
188 */
189 if(this->parameterList_->sublist("Parameter").get("Use Pressure Projection",false) && (!this->getFEType(0).compare("P2") || (!this->getFEType(0).compare("Q2") && !this->getFEType(1).compare("Q1"))) && !this->parameterList_->sublist("General").get("Preconditioner Method","Monolithic").compare("Monolithic")){
190 // Projection vector a: \int p dx, for pressure component and 0 for velocity.
191 BlockMultiVectorPtr_Type projection(new BlockMultiVector_Type (2));
192
193 MultiVectorPtr_Type P(new MultiVector_Type( this->getDomain(1)->getMapUnique(), 1 ) );
194
195 this->feFactory_->assemblyPressureMeanValue( this->dim_,"P1",P) ;
196
197 MultiVectorPtr_Type vel0(new MultiVector_Type( this->getDomain(0)->getMapVecFieldUnique(), 1 ) );
198 vel0->putScalar(0.);
199
200 // Adding components to projection vector
201 projection->addBlock(vel0,0);
202 projection->addBlock(P,1);
203
204 // Setting projection vector in preconditioner to later pass to paramterlist in FROSch
205 this->getPreconditionerConst()->setPressureProjection( projection );
206
207 if (this->verbose_)
208 std::cout << "\n 'Use pressure correction' was set to 'true'. This requieres a version of Trilinos of that includes pressure correction in the FROSch_OverlappingOperator!!" << std::endl;
209
210 }
211
212
213#ifdef FEDD_HAVE_TEKO
214 if ( !this->parameterList_->sublist("General").get("Preconditioner Method","Monolithic").compare("Teko") ) {
215 if (!this->parameterList_->sublist("General").get("Assemble Velocity Mass",false)) {
216 MatrixPtr_Type Mvelocity(new Matrix_Type( this->getDomain(0)->getMapVecFieldUnique(), this->getDomain(0)->getApproxEntriesPerRow() ) );
217 //
218 this->feFactory_->assemblyMass( this->dim_, this->domain_FEType_vec_.at(0), "Vector", Mvelocity, true );
219 //
220 this->getPreconditionerConst()->setVelocityMassMatrix( Mvelocity );
221 if (this->verbose_)
222 std::cout << "\nVelocity mass matrix for LSC block preconditioner is assembled." << std::endl;
223 } else {
224 if (this->verbose_)
225 std::cout << "\nVelocity mass matrix for LSC block preconditioner not assembled." << std::endl;
226 }
227 }
228#endif
229 std::string precType = this->parameterList_->sublist("General").get("Preconditioner Method","Monolithic");
230 if ( precType == "Diagonal" || precType == "Triangular" ) {
231 MatrixPtr_Type Mpressure(new Matrix_Type( this->getDomain(1)->getMapUnique(), this->getDomain(1)->getApproxEntriesPerRow() ) );
232
233 this->feFactory_->assemblyMass( this->dim_, this->domain_FEType_vec_.at(1), "Scalar", Mpressure, true );
234 SC kinVisco = this->parameterList_->sublist("Parameter").get("Viscosity",1.);
235 Mpressure->scale(-1./kinVisco);
236 this->getPreconditionerConst()->setPressureMassMatrix( Mpressure );
237 }
238 if (this->verbose_)
239 std::cout << "done -- " << std::endl;
240};
241
242
243template<class SC,class LO,class GO,class NO>
244void NavierStokesAssFE<SC,LO,GO,NO>::reAssemble( MatrixPtr_Type& massmatrix, std::string type ) const
245{
246
247}
248
249
250
251template<class SC,class LO,class GO,class NO>
252void NavierStokesAssFE<SC,LO,GO,NO>::reAssemble(std::string type) const {
253
254
255 if (this->verbose_)
256 std::cout << "-- Reassembly Navier-Stokes ("<< type <<") ... " << std::flush;
257
258 double density = this->parameterList_->sublist("Parameter").get("Density",1.);
259
260 MatrixPtr_Type ANW = Teuchos::rcp(new Matrix_Type( this->getDomain(0)->getMapVecFieldUnique(), this->getDomain(0)->getDimension() * this->getDomain(0)->getApproxEntriesPerRow() ) );
261
262 MultiVectorConstPtr_Type u = this->solution_->getBlock(0);
263 u_rep_->importFromVector(u, true);
264
265 MultiVectorConstPtr_Type p = this->solution_->getBlock(1);
266 p_rep_->importFromVector(p, true);
267
268
269 if (type=="Rhs") {
270
271 this->system_->addBlock(ANW,0,0);
272 /* The next code line was unnecessary work load in solveNewton as it was also called but rewritten by assemble("Newton"), so instead we comment this out and call
273 in solveFixedPoint the assemble("FixedPoint") function, and here in "RHS" only F*current_solution is computed necessary for computing the residual vector */
274 //this->feFactory_->assemblyNavierStokes(this->dim_, this->getDomain(0)->getFEType(), this->getDomain(1)->getFEType(), 2, this->dim_,1,u_rep_,p_rep_,this->system_, this->residualVec_,this->coeff_,this->parameterList_, true, "FixedPoint", true);
275 this->feFactory_->assemblyNavierStokes(this->dim_, this->getDomain(0)->getFEType(), this->getDomain(1)->getFEType(), 2, this->dim_,1,u_rep_,p_rep_,this->system_, this->residualVec_,this->coeff_,this->parameterList_, true, "Rhs", true);
276
277 }
278 else if (type=="FixedPoint" ) {
279
280 this->system_->addBlock(ANW,0,0);
281 this->feFactory_->assemblyNavierStokes(this->dim_, this->getDomain(0)->getFEType(), this->getDomain(1)->getFEType(), 2, this->dim_,1,u_rep_,p_rep_,this->system_, this->residualVec_,this->coeff_,this->parameterList_, true, "FixedPoint", true);
282 }
283 else if(type=="Newton"){
284
285 this->system_->addBlock(ANW,0,0);
286 this->feFactory_->assemblyNavierStokes(this->dim_, this->getDomain(0)->getFEType(), this->getDomain(1)->getFEType(), 2, this->dim_,1,u_rep_,p_rep_,this->system_,this->residualVec_, this->coeff_,this->parameterList_, true,"Jacobian", true);
287
288 }
289
290 this->system_->addBlock(ANW,0,0);
291
292 if (this->verbose_)
293 std::cout << "done -- " << std::endl;
294
295
296}
297
298
299template<class SC,class LO,class GO,class NO>
300void NavierStokesAssFE<SC,LO,GO,NO>::calculateNonLinResidualVec(std::string type, double time) const{
301
302 //this->reAssemble("FixedPoint");
303 this->reAssemble("Rhs");
304
305 // We need to additionally add the residual component for the stabilization block, as it is not part of the AssembleFE routines and calculated externally here.
306 if(this->getDomain(0)->getFEType() == "P1"){
307
308 MultiVectorPtr_Type residualPressureTmp = Teuchos::rcp(new MultiVector_Type( this->getDomain(1)->getMapUnique() ));
309
310 this->system_->getBlock(1,1)->apply( *(this->solution_->getBlock(1)), *residualPressureTmp);
311
312 this->residualVec_->getBlockNonConst(1)->update(1.,*residualPressureTmp,1.);
313
314
315 }
316 // We need to account for different parameters of time discretizations here
317 // This is ok for bdf with 1.0 scaling of the system. Would be wrong for Crank-Nicolson - might be ok now for CN
318
319 /*if (this->coeff_.size() == 0)
320 this->system_->apply( *this->solution_, *this->residualVec_ );
321 else
322 this->system_->apply( *this->solution_, *this->residualVec_, this->coeff_ );*/
323
324 if (!type.compare("standard")){
325 this->residualVec_->update(-1.,*this->rhs_,1.);
326// if ( !this->sourceTerm_.is_null() )
327// this->residualVec_->update(-1.,*this->sourceTerm_,1.);
328 // this might be set again by the TimeProblem after addition of M*u
329 this->bcFactory_->setVectorMinusBC( this->residualVec_, this->solution_, time );
330
331 }
332 else if(!type.compare("reverse")){
333 this->residualVec_->update(1.,*this->rhs_,-1.); // this = -1*this + 1*rhs
334// if ( !this->sourceTerm_.is_null() )
335// this->residualVec_->update(1.,*this->sourceTerm_,1.);
336 // this might be set again by the TimeProblem after addition of M*u
337 this->bcFactory_->setBCMinusVector( this->residualVec_, this->solution_, time );
338
339 }
340
341}
342
343template<class SC,class LO,class GO,class NO>
344void NavierStokesAssFE<SC,LO,GO,NO>::calculateNonLinResidualVecWithMeshVelo(std::string type, double time, MultiVectorPtr_Type u_minus_w, MatrixPtr_Type P) const{
345
346
347 // this->reAssembleFSI( "FixedPoint", u_minus_w, P );
348
349 // We need to account for different parameters of time discretizations here
350 // This is ok for bdf with 1.0 scaling of the system. Would be wrong for Crank-Nicolson
351
352 this->system_->apply( *this->solution_, *this->residualVec_ );
353// this->residualVec_->getBlock(0)->writeMM("Ax.mm");
354// this->rhs_->getBlock(0)->writeMM("nsRHS.mm");
355 if (!type.compare("standard")){
356 this->residualVec_->update(-1.,*this->rhs_,1.);
357 if ( !this->sourceTerm_.is_null() )
358 this->residualVec_->update(-1.,*this->sourceTerm_,1.);
359 }
360 else if(!type.compare("reverse")){
361 this->residualVec_->update(1.,*this->rhs_,-1.); // this = -1*this + 1*rhs
362 if ( !this->sourceTerm_.is_null() )
363 this->residualVec_->update(1.,*this->sourceTerm_,1.);
364 }
365
366 // this might be set again by the TimeProblem after addition of M*u
367 this->bcFactory_->setBCMinusVector( this->residualVec_, this->solution_, time );
368
369// this->residualVec_->getBlock(0)->writeMM("b_Ax.mm");
370
371}
372
373/*template<class SC,class LO,class GO,class NO>
374void NavierStokesAssFE<SC,LO,GO,NO>::reAssembleFSI(std::string type, MultiVectorPtr_Type u_minus_w, MatrixPtr_Type P) const {
375
376 if (this->verbose_)
377 std::cout << "-- Reassembly Navier-Stokes ("<< type <<") for FSI ... " << std::flush;
378
379 double density = this->parameterList_->sublist("Parameter").get("Density",1.);
380
381 MatrixPtr_Type ANW = Teuchos::rcp(new Matrix_Type( this->getDomain(0)->getMapVecFieldUnique(), this->getDomain(0)->getDimension() * this->getDomain(0)->getApproxEntriesPerRow() ) );
382 if (type=="FixedPoint") {
383
384 MatrixPtr_Type N = Teuchos::rcp(new Matrix_Type( this->getDomain(0)->getMapVecFieldUnique(), this->getDomain(0)->getDimension() * this->getDomain(0)->getApproxEntriesPerRow() ) );
385 this->feFactory_->assemblyAdvectionVecField( this->dim_, this->domain_FEType_vec_.at(0), N, u_minus_w, true );
386
387 N->resumeFill();
388 N->scale(density);
389 N->fillComplete( this->getDomain(0)->getMapVecFieldUnique(), this->getDomain(0)->getMapVecFieldUnique());
390 A_->addMatrix(1.,ANW,0.);
391
392 N->addMatrix(1.,ANW,1.);
393 // P must be scaled correctly in FSI
394 P->addMatrix(1.,ANW,1.);
395
396
397 }
398 else if(type=="Newton"){
399 TEUCHOS_TEST_FOR_EXCEPTION( true, std::logic_error, "reAssembleFSI should only be called for FPI-System.");
400 }
401 ANW->fillComplete( this->getDomain(0)->getMapVecFieldUnique(), this->getDomain(0)->getMapVecFieldUnique() );
402
403 this->system_->addBlock( ANW, 0, 0 );
404
405 if (this->verbose_)
406 std::cout << "done -- " << std::endl;
407}*/
408
409
410template<class SC,class LO,class GO,class NO>
411void NavierStokesAssFE<SC,LO,GO,NO>::reAssembleExtrapolation(BlockMultiVectorPtrArray_Type previousSolutions){
412
413 if (this->verbose_)
414 std::cout << "-- Reassembly Navier-Stokes (Extrapolation) ... " << std::flush;
415
416
417 double density = this->parameterList_->sublist("Parameter").get("Density",1.);
418
419 if (previousSolutions.size()>=2) {
420
421 MultiVectorPtr_Type extrapolatedVector = Teuchos::rcp( new MultiVector_Type( previousSolutions[0]->getBlock(0) ) );
422
423 extrapolatedVector->update( -1., *previousSolutions[1]->getBlock(0), 2. );
424
425 u_rep_->importFromVector(extrapolatedVector, true);
426 }
427 else if(previousSolutions.size()==1){
428 MultiVectorConstPtr_Type u = previousSolutions[0]->getBlock(0);
429 u_rep_->importFromVector(u, true);
430 }
431 else if (previousSolutions.size()==0){
432 MultiVectorConstPtr_Type u = this->solution_->getBlock(0);
433 u_rep_->importFromVector(u, true);
434 }
435
436 MatrixPtr_Type ANW = Teuchos::rcp(new Matrix_Type( this->getDomain(0)->getMapVecFieldUnique(), this->getDomain(0)->getDimension() * this->getDomain(0)->getApproxEntriesPerRow() ) );
437
438 MatrixPtr_Type N = Teuchos::rcp(new Matrix_Type( this->getDomain(0)->getMapVecFieldUnique(), this->getDomain(0)->getDimension() * this->getDomain(0)->getApproxEntriesPerRow() ) );
439 this->feFactory_->assemblyAdvectionVecField( this->dim_, this->domain_FEType_vec_.at(0), N, u_rep_, true );
440
441 N->resumeFill();
442 N->scale(density);
443 N->fillComplete( this->getDomain(0)->getMapVecFieldUnique(), this->getDomain(0)->getMapVecFieldUnique());
444
445 A_->addMatrix(1.,ANW,0.);
446 N->addMatrix(1.,ANW,1.);
447
448 ANW->fillComplete( this->getDomain(0)->getMapVecFieldUnique(), this->getDomain(0)->getMapVecFieldUnique() );
449
450 this->system_->addBlock( ANW, 0, 0 );
451
452 if (this->verbose_)
453 std::cout << "done -- " << std::endl;
454}
455
456
457
458
459
460
461// Use converged solution to compute viscosity field
462template<class SC,class LO,class GO,class NO>
463void NavierStokesAssFE<SC,LO,GO,NO>::computeSteadyPostprocessingViscosity_Solution() {
464
465
466 MultiVectorConstPtr_Type u = this->solution_->getBlock(0); // solution_ is initialized in problem_def.hpp so the most general class
467 u_rep_->importFromVector(u, true); // this is the current velocity solution at the nodes - distributed at the processors with repeated values
468
469 MultiVectorConstPtr_Type p = this->solution_->getBlock(1);
470 p_rep_->importFromVector(p, true); // this is the current pressure solution at the nodes - distributed at the processors with repeated values
471
472 // Reset here the viscosity so at this moment this makes only sense to call at the end of a simulation
473 // to visualize viscosity field
474 // TODO: Add possibility for transient problem to save viscosity solution in each time step
475 viscosity_element_ = Teuchos::rcp( new MultiVector_Type( this->getDomain(0)->getElementMap() ) );
476 this->feFactory_->computeSteadyViscosityFE_CM(this->dim_, this->getDomain(0)->getFEType(), this->getDomain(1)->getFEType(), this->dim_,1,u_rep_,p_rep_,this->parameterList_);
477
478 Teuchos::RCP<const MultiVector<SC,LO,GO,NO>> exportSolutionViscosityAssFE = this->feFactory_->const_output_fields->getBlock(0); // For now we assume that viscosity is always saved in first block
479 viscosity_element_->importFromVector(exportSolutionViscosityAssFE, true);
480
481
482
483}
484
485
486
487
488
489
490
491}
492
493#endif
virtual void assemble(std::string type="") const
assemble of type exectuted by the derived specific non-linear problem classes
Definition NavierStokesAssFE_def.hpp:121
virtual void calculateNonLinResidualVec(std::string type="standard", double time=0.) const
Virtual function which is implemented in the specific non-linear problem classes to calculate the non...
Definition NavierStokesAssFE_def.hpp:300
Definition NonLinearProblem_decl.hpp:28
Adaptive Mesh Refinement.
Definition AdaptiveMeshRefinement_decl.hpp:36