Finite Element Domain Decomposition Library
FEDDLib
Loading...
Searching...
No Matches
NavierStokes_def.hpp
1#ifndef NAVIERSTOKES_def_hpp
2#define NAVIERSTOKES_def_hpp
3
4#ifndef NAVIER_STOKES_START
5#define NAVIER_STOKES_START(A,S) Teuchos::RCP<Teuchos::TimeMonitor> A = Teuchos::rcp(new Teuchos::TimeMonitor(*Teuchos::TimeMonitor::getNewTimer(std::string("Assemble Navier-Stokes:") + std::string(S))));
6#endif
7
8#ifndef NAVIER_STOKES_STOP
9#define NAVIER_STOKES_STOP(A) A.reset();
10#endif
11
12#include "feddlib/core/LinearAlgebra/Matrix.hpp"
13#include "feddlib/core/General/BCBuilder.hpp"
14#include "feddlib/problems/Solver/Preconditioner.hpp"
15
24
25void sxOne2D(double* x, double* res, double t, double* parameter){
26
27 res[0] = 1.;
28 res[1] = 0.;
29 return;
30}
31
32void syOne2D(double* x, double* res, double t, double* parameter){
33
34 res[0] = 0.;
35 res[1] = 1.;
36
37 return;
38}
39void sDummyFunc(double* x, double* res, double t, double* parameter){
40
41 return;
42}
43
44void zeroDirichletBC(double* x, double* res, double t, const double* parameters){
45
46 res[0] = 0.;
47
48 return;
49}
50
51double OneFunction(double* x, int* parameter)
52{
53 return 1.0;
54}
55
56void dummyFuncRhs(double* x, double* res, double* parameters){
57
58 // parameters[1] contains the surface flag, parameter[0] contains the inlet flag
59 if(parameters[1]==parameters[0])
60 res[0]=1;
61 else
62 res[0] = 0.;
63
64 return;
65}
66
67namespace FEDD {
68
69
70
71template<class SC,class LO,class GO,class NO>
72NavierStokes<SC,LO,GO,NO>::NavierStokes( const DomainConstPtr_Type &domainVelocity, std::string FETypeVelocity, const DomainConstPtr_Type &domainPressure, std::string FETypePressure, ParameterListPtr_Type parameterList ):
73NonLinearProblem<SC,LO,GO,NO>( parameterList, domainVelocity->getComm() ),
74A_(),
75pressureIDsLoc(new vec_int_Type(2)),
76u_rep_()
78
79 this->nonLinearTolerance_ = this->parameterList_->sublist("Parameter").get("relNonLinTol",1.0e-6);
80 this->initNOXParameters();
81
82 this->addVariable( domainVelocity , FETypeVelocity , "u" , domainVelocity->getDimension());
83 this->addVariable( domainPressure , FETypePressure , "p" , 1);
84 this->dim_ = this->getDomain(0)->getDimension();
85
86 u_rep_ = Teuchos::rcp( new MultiVector_Type( this->getDomain(0)->getMapVecFieldRepeated() ) );
87
88 if (parameterList->sublist("Parameter").get("Calculate Coefficients",false)) {
89 vec2D_dbl_ptr_Type vectmpPointsPressure = domainPressure->getPointsUnique();
90 vec2D_dbl_Type::iterator it;
91 int front = -1;
92 int back = -1;
93 if (domainPressure->getDimension() == 2) {
94 it = find_if(vectmpPointsPressure->begin(), vectmpPointsPressure->end(),
95 [&] (const std::vector<double>& a){
96 if (a.at(0) >= 0.15-1.e-12 && a.at(0) <= 0.15+1.e-12
97 && a.at(1) >= 0.2-1.e-12 && a.at(1) <= 0.2+1.e-12) {
98 return true;
99 }
100 else {
101 return false;
102 }
103 });
104
105 if (it != vectmpPointsPressure->end()) {
106 front = distance(vectmpPointsPressure->begin(),it);
107 }
108 it = find_if(vectmpPointsPressure->begin(), vectmpPointsPressure->end(),
109 [&] (const std::vector<double>& a){
110 if (a.at(0) >= 0.25-1.e-12 && a.at(0) <= 0.25+1.e-12
111 && a.at(1) >= 0.2-1.e-12 && a.at(1) <= 0.2+1.e-12) {
112 return true;
113 }
114 else {
115 return false;
116 }
117 });
118
119 if (it != vectmpPointsPressure->end()) {
120 back = distance(vectmpPointsPressure->begin(),it);
121 }
122 pressureIDsLoc->at(0) = front;
123 pressureIDsLoc->at(1) = back;
124 }
125 else if(domainPressure->getDimension() == 3){
126#ifdef ASSERTS_WARNINGS
127 MYASSERT(false,"Not implemented to calc coefficients in 3D!");
128#endif
129 }
130 }
131
132 if(!this->parameterList_->sublist("General").get("Preconditioner Method","Diagonal").compare("PCD")
133 || !this->parameterList_->sublist("General").get("Preconditioner Method","Diagonal").compare("LSC")
134 || !this->parameterList_->sublist("Teko Parameters").sublist("Preconditioner Types").sublist("Teko").get("Inverse Type","SIMPLE").compare("PCD")
135 || !this->parameterList_->sublist("Teko Parameters").sublist("Preconditioner Types").sublist("Teko").get("Inverse Type","SIMPLE").compare("LSC-Pressure-Laplace") )
136 {
137
138 int flagOutlet = this->parameterList_->sublist("General").get("Flag Outlet Fluid", 3);
139 int flagInterface = this->parameterList_->sublist("General").get("Flag Interface", 6);
140
141 this->bcFactoryPCD_.reset(new BCBuilder<SC,LO,GO,NO>( ));
142 this->bcFactoryPCD_->addBC(zeroDirichletBC, flagOutlet, 0, Teuchos::rcp_const_cast<Domain_Type>( domainPressure ), "Dirichlet", 1);
143 // this->bcFactoryPCD_->addBC(zeroDirichletBC, flagInterface, 0, Teuchos::rcp_const_cast<Domain_Type>( domainPressure ), "Dirichlet", 1);
144 // this->bcFactoryPCD_->addBC(zeroDirichletBC, 9, 0, Teuchos::rcp_const_cast<Domain_Type>( domainPressure ), "Dirichlet", 1);
145 // this->bcFactoryPCD_->addBC(zeroDirichletBC, 10, 0, Teuchos::rcp_const_cast<Domain_Type>( domainPressure ), "Dirichlet", 1);
146
147 }
148
149 if(this->parameterList_->sublist("General").get("Augmented Lagrange",false))
150 augmentedLagrange_ = true;
151
152 // Establish the non zero pattern of the system matrix in (0,0) block
153 NNZ_A_.reset(new Matrix_Type( this->getDomain(0)->getMapVecFieldUnique(), this->getDomain(0)->getDimension() * this->getDomain(0)->getApproxEntriesPerRow() ) );
154 establishNNZPattern();
155
156}
157
158template<class SC,class LO,class GO,class NO>
159void NavierStokes<SC,LO,GO,NO>::info(){
160 this->infoProblem();
161 this->infoNonlinProblem();
162}
163
164template<class SC,class LO,class GO,class NO>
165void NavierStokes<SC,LO,GO,NO>::assemble( std::string type ) const{
166
167 if (type=="") {
168 if (this->verbose_)
169 std::cout << "-- Assembly Navier-Stokes ... " << std::endl;
170
171 assembleConstantMatrices();
172
173 if (this->verbose_)
174 std::cout << "done -- " << std::endl;
175 }
176 else if(type=="UpdateTime"){
177 this->newtonStep_ = 0;
178 // timeSteppingTool_->t_ = timeSteppingTool_->t_ + timeSteppingTool_->dt_prev_;
179 }
180 else if(type =="UpdateConvectionDiffusionOperator")
182 else
183 reAssemble( type );
184
185};
186
187template<class SC,class LO,class GO,class NO>
188void NavierStokes<SC,LO,GO,NO>::assembleConstantMatrices() const{
189
190 if (this->verbose_)
191 std::cout << "-- Assembly constant matrices Navier-Stokes ... " << std::flush;
192
193 double viscosity = this->parameterList_->sublist("Parameter").get("Viscosity",1.);
194 double density = this->parameterList_->sublist("Parameter").get("Density",1.);
195
196 // Egal welcher Wert, da OneFunction nicht von parameter abhaengt
197 int* dummy;
198
199 A_.reset(new Matrix_Type( this->getDomain(0)->getMapVecFieldUnique(), this->getDomain(0)->getDimension() * this->getDomain(0)->getApproxEntriesPerRow() ) );
200
201 if ( this->parameterList_->sublist("Parameter").get("Symmetric gradient",false) )
202 this->feFactory_->assemblyStress(this->dim_, this->domain_FEType_vec_.at(0), A_, OneFunction, dummy, true);
203 else
204 this->feFactory_->assemblyLaplaceVecField(this->dim_, this->domain_FEType_vec_.at(0), 2, A_, true);
205
206 A_->resumeFill();
207
208 A_->scale(viscosity);
209 A_->scale(density);
210
211 A_->fillComplete( this->getDomain(0)->getMapVecFieldUnique(), this->getDomain(0)->getMapVecFieldUnique());
212
213 if (this->system_.is_null())
214 this->system_.reset(new BlockMatrix_Type(2));
215
216 this->system_->addBlock( A_, 0, 0 );
217 assembleDivAndStab();
218
219 // If pressure projection is used, we need to assemble the projection vector here
220 // Only for P2-P1 or Q2-Q1 elements in monolithic case
221 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")){
222 // Projection vector a: \int p dx, for pressure component and 0 for velocity.
223 BlockMultiVectorPtr_Type projection(new BlockMultiVector_Type (2));
224
225 MultiVectorPtr_Type P(new MultiVector_Type( this->getDomain(1)->getMapUnique(), 1 ) );
226
227 this->feFactory_->assemblyPressureMeanValue( this->dim_,this->getFEType(1),P) ;
228
229 // Velocity component is set to zero, such that the projection vector only influences the pressure part
230 MultiVectorPtr_Type vel0(new MultiVector_Type( this->getDomain(0)->getMapVecFieldUnique(), 1 ) );
231 vel0->putScalar(0.);
232
233 // Adding components to projection vector
234 projection->addBlock(vel0,0);
235 projection->addBlock(P,1);
236
237 // Setting projection vector in preconditioner to later pass to parameterlist in FROSch
238 this->getPreconditionerConst()->setPressureProjection( projection );
239
240 if (this->verbose_)
241 std::cout << "\n 'Use pressure correction' was set to 'true'. This requires a version of Trilinos that includes pressure correction in the FROSch_OverlappingOperator!!" << std::endl;
242
243 }
244
245#ifdef FEDD_HAVE_TEKO
246 if ( !this->parameterList_->sublist("General").get("Preconditioner Method","Monolithic").compare("Teko")
247 || !this->parameterList_->sublist("General").get("Preconditioner Method","Diagonal").compare("PCD")
248 || !this->parameterList_->sublist("General").get("Preconditioner Method","Diagonal").compare("LSC")) {
249
250 // ###############################################
251 // LSC Preconditioner
252 // Constructing velocity mass matrix
253 // If the Velocity Mass Matrix is the identity matrix,
254 // it results in the BFBt preconditioner
255 if (!this->parameterList_->sublist("Teko Parameters").sublist("Preconditioner Types").sublist("Teko").get("Inverse Type","None").compare("LSC")
256 || !this->parameterList_->sublist("Teko Parameters").sublist("Preconditioner Types").sublist("Teko").get("Inverse Type","None").compare("LSC-Pressure-Laplace")
257 || !this->parameterList_->sublist("Teko Parameters").sublist("Preconditioner Types").sublist("Teko").get("Inverse Type","None").compare("SIMPLE")
258 || !this->parameterList_->sublist("General").get("Preconditioner Method","Diagonal").compare("LSC")) {
259
260 MatrixPtr_Type Mvelocity(new Matrix_Type( this->getDomain(0)->getMapVecFieldUnique(), this->getDomain(0)->getApproxEntriesPerRow() ) );
261 // Constructing velocity mass matrix
262 if(this->parameterList_->sublist("Parameter").get("BFBT",false)){
263 if(this->verbose_)
264 std::cout << "\n Setting M_u to be the identity Matrix to use BFBT preconditioner " << std::endl;
265
266 this->feFactory_->assemblyIdentity( Mvelocity );
267 }
268 else{
269 this->feFactory_->assemblyMass( this->dim_, this->domain_FEType_vec_.at(0), "Vector", Mvelocity, true );
270 }
271 // Adding the velocity mass matrix Mu to the preconditioner
272 this->getPreconditionerConst()->setVelocityMassMatrix( Mvelocity );
273
274 if (this->verbose_)
275 std::cout << "\n Velocity mass matrix for LSC block preconditioner is assembled and used for the preconditioner." << std::endl;
276
277 // For LSC-Pressure-Laplace approach we add also the Laplaian on the pressure space to the preconditioner
278 if(!this->parameterList_->sublist("Teko Parameters").sublist("Preconditioner Types").sublist("Teko").get("Inverse Type","SIMPLE").compare("LSC-Pressure-Laplace")
279 || !this->parameterList_->sublist("General").get("Preconditioner Method","Diagonal").compare("LSC"))
280 {
281 MatrixPtr_Type Lp(new Matrix_Type( this->getDomain(1)->getMapUnique(), this->getDomain(1)->getApproxEntriesPerRow() ) );
282 this->feFactory_->assemblyLaplace( this->dim_, this->domain_FEType_vec_.at(1), 2, Lp, true );
283
284 BlockMatrixPtr_Type bcBlockMatrix(new BlockMatrix_Type (1));
285 bcBlockMatrix->addBlock(Lp,0,0);
286 bcFactoryPCD_->setSystemScaled(bcBlockMatrix); // Setting boundary information where the Diagonal entry is kept
287
288 this->getPreconditionerConst()->setPressureLaplaceMatrix( Lp);
289 }
290 }
291 // ###############################################
292 // PCD Preconditioner
293 // For the PCD preconditioner we additionally need
294 // assemble the pressure mass matrix, the pressure
295 // Laplacian and the pressure convection diffusion
296 // opertor.
297 else if(!this->parameterList_->sublist("Teko Parameters").sublist("Preconditioner Types").sublist("Teko").get("Inverse Type","SIMPLE").compare("PCD")
298 || !this->parameterList_->sublist("General").get("Preconditioner Method","Diagonal").compare("PCD") ){
299
300 // ###############################################
301 // Velocity mass matrix: Currently this is set to not have an error in preconditioner. PLEASE FIX
302 MatrixPtr_Type Mvelocity(new Matrix_Type( this->getDomain(0)->getMapVecFieldUnique(), this->getDomain(0)->getApproxEntriesPerRow() ) );
303 this->feFactory_->assemblyMass( this->dim_, this->domain_FEType_vec_.at(0), "Vector", Mvelocity, true );
304 this->getPreconditionerConst()->setVelocityMassMatrix( Mvelocity );
305 // ###############################################
306
307
308 // Pressure mass matrix
309 MatrixPtr_Type Mpressure(new Matrix_Type( this->getDomain(1)->getMapUnique(), this->getDomain(1)->getApproxEntriesPerRow() ) );
310 this->feFactory_->assemblyMass( this->dim_, this->domain_FEType_vec_.at(1), "Scalar", Mpressure, true );
311 Mp_= Mpressure;
312 this->getPreconditionerConst()->setPressureMassMatrix( Mpressure );
313 // --------------------------------------------------------------------------------------------
314
315 // --------------------------------------------------------------------------------------------
316 // Pressure Laplace matrix
317 SC density = this->parameterList_->sublist("Parameter").get("Density",1.); // Ap need to be scaled with viscosity
318
319 MatrixPtr_Type Lp(new Matrix_Type( this->getDomain(1)->getMapUnique(), this->getDomain(1)->getApproxEntriesPerRow() ) );
320 this->feFactory_->assemblyLaplace( this->dim_, this->domain_FEType_vec_.at(1), 2, Lp, true );
321 // Lp->resumeFill();
322 // Lp->scale(density);
323 // Lp->fillComplete();
324 Ap_.reset(new Matrix_Type(Lp)); // Setting Ap_ as Lp without any BC
325
326 // Adding boundary information to pressure Laplace operator
327 BlockMatrixPtr_Type bcBlockMatrix(new BlockMatrix_Type (1));
328 bcBlockMatrix->addBlock(Lp,0,0);
329
330 bcFactoryPCD_->setSystemScaled(bcBlockMatrix); // Setting boundary information where the Diagonal entry is kept
331 this->getPreconditionerConst()->setPressureLaplaceMatrix( Lp); // Adding pressure laplacian to preconditioner
332 // --------------------------------------------------------------------------------------------
333
334 // --------------------------------------------------------------------------------------------
335 // Pressure convection diffusion operator
336 MatrixPtr_Type Kp(new Matrix_Type( this->getDomain(1)->getMapUnique(), this->getDomain(1)->getApproxEntriesPerRow() ) );
337 // --------------------------------------------------------------------------------------------
338 // Advection component
339 MatrixPtr_Type AdvPressure(new Matrix_Type( this->getDomain(1)->getMapUnique(), this->getDomain(1)->getApproxEntriesPerRow() ) );
340 this->feFactory_->assemblyAdvectionVecFieldScalar( this->dim_, this->domain_FEType_vec_.at(1), this->domain_FEType_vec_.at(0),AdvPressure, u_rep_, true );
341
342 // Diffusion component: \nu * \Delta
343 MatrixPtr_Type Ap2(new Matrix_Type( Ap_) );
344
345 SC kinVisco = this->parameterList_->sublist("Parameter").get("Viscosity",1.); // Ap need to be scaled with viscosity
346
347 Ap2->resumeFill();
348 Ap2->scale(kinVisco);
349 // Ap2->scale(density);
350 Ap2->fillComplete();
351
352
353 MatrixPtr_Type K_robin(new Matrix_Type( this->getDomain(1)->getMapUnique(), this->getDomain(1)->getDimension() * this->getDomain(1)->getApproxEntriesPerRow()*2 ) );
354 int flagInlet =this->parameterList_->sublist("General").get("Flag Inlet Fluid", 2);
355
356 vec_dbl_Type funcParameter(1,flagInlet);
357 funcParameter.push_back(0.0); // Dummy for flag
358 this->feFactory_->assemblySurfaceRobinBC(this->dim_, this->getDomain(1)->getFEType(),this->getDomain(0)->getFEType(),u_rep_,K_robin, funcParameter, dummyFuncRhs,this->parameterList_);
359 K_robin->addMatrix(-1.,Kp,1.); // adding robin boundary condition to to Kp
360
361 // Adding laplace and convetion-diffusion operator to Kp
362 Ap2->addMatrix(1.,Kp,1.); // adding advection to diffusion
363 AdvPressure->addMatrix(1.,Kp,1.); // adding advection to diffusion
364
365 // Kp->scale(density);
366 Kp->fillComplete();
367
368 bcBlockMatrix->addBlock(Kp,0,0);
369 bcFactoryPCD_->setSystemScaled(bcBlockMatrix);
370
371 // Adding Kp to the preconditioner
372 this->getPreconditionerConst()->setPCDOperator( Kp );
373 // --------------------------------------------------------------------------------------------
374
375 }
376 }
377#endif
378 std::string precType = this->parameterList_->sublist("General").get("Preconditioner Method","Monolithic");
379 if ( precType == "Diagonal" || precType == "Triangular" ) {
380 MatrixPtr_Type Mpressure(new Matrix_Type( this->getDomain(1)->getMapUnique(), this->getDomain(1)->getApproxEntriesPerRow() ) );
381
382 this->feFactory_->assemblyMass( this->dim_, this->domain_FEType_vec_.at(1), "Scalar", Mpressure, true );
383 SC kinVisco = this->parameterList_->sublist("Parameter").get("Viscosity",1.);
384
385 if(augmentedLagrange_){
386 double gamma = this->parameterList_->sublist("General").get("Gamma",1.0);
387 Mpressure->scale(-1./(kinVisco+gamma));
388 }
389 else{
390 Mpressure->scale(-1./kinVisco);
391 }
392 this->getPreconditionerConst()->setPressureMassMatrix( Mpressure );
393 }
394
395 if (this->verbose_)
396 std::cout << " Allocate the Matrix pattern " << std::endl;
397
398 // After the constant matrices are assembled, we establish the matrix pattern for the (0,0) block for the advection term
399 MatrixPtr_Type A_withNNZ = Teuchos::rcp( new Matrix_Type( this->getDomain(0)->getMapVecFieldUnique(), this->getDomain(0)->getDimension() * this->getDomain(0)->getApproxEntriesPerRow() ) );
400 A_->addMatrix(1.,A_withNNZ,0.); // We add the previously computed laplacian
401 NNZ_A_->addMatrix(1.,A_withNNZ,1.); // We add the zero matrix containing the nnz pattern
402
403 A_withNNZ->fillComplete( this->getDomain(0)->getMapVecFieldUnique(), this->getDomain(0)->getMapVecFieldUnique());
404 this->system_->addBlock( A_withNNZ, 0, 0 ); // We replace the (0,0) block with the new matrix containing the laplacian and the nnz pattern for the advection term
405
406 if (this->verbose_)
407 std::cout << "done -- " << std::endl;
408
409};
410
411
412template<class SC,class LO,class GO,class NO>
414
415 if ( !this->parameterList_->sublist("Teko Parameters").sublist("Preconditioner Types").sublist("Teko").get("Inverse Type","SIMPLE").compare("PCD")
416 || !this->parameterList_->sublist("General").get("Preconditioner Method","Monolithic").compare("PCD"))
417 {
418 std::cout << "NavierStokes<SC,LO,GO,NO>::updateConvectionDiffusionOperator() set to TRUE" << std::endl;
419 NAVIER_STOKES_START(ReassemblePCD," Reassembling Matrix for PCD ");
420
421 MultiVectorConstPtr_Type u = this->solution_->getBlock(0);
422 u_rep_->importFromVector(u, true);
423
424 // PCD Operator
425 MatrixPtr_Type Fp(new Matrix_Type( this->getDomain(1)->getMapUnique(), this->getDomain(1)->getApproxEntriesPerRow() ) );
426 // --------------------------------------------------------------------------------------------
427 // Advection component
428 MatrixPtr_Type AdvPressure(new Matrix_Type( this->getDomain(1)->getMapUnique(), this->getDomain(1)->getApproxEntriesPerRow() ) );
429 this->feFactory_->assemblyAdvectionVecFieldScalar( this->dim_, this->domain_FEType_vec_.at(1), this->domain_FEType_vec_.at(0),AdvPressure, u_rep_, true );
430
431 // Diffusion component: \nu * \Delta
432 MatrixPtr_Type Ap2(new Matrix_Type( Ap_ ) ); // We use A_p which we already stored
433 SC kinVisco = this->parameterList_->sublist("Parameter").get("Viscosity",1.);
434 SC density = this->parameterList_->sublist("Parameter").get("Density",1.);
435
436 Ap2->resumeFill();
437 Ap2->scale(kinVisco);
438 Ap2->fillComplete();
439
440 // ---------------------
441 // Robin boundary
442 MatrixPtr_Type Kext(new Matrix_Type( this->getDomain(1)->getMapUnique(), this->getDomain(1)->getDimension() * this->getDomain(1)->getApproxEntriesPerRow()*2 ) );
443 int flagInlet =this->parameterList_->sublist("General").get("Flag Inlet Fluid", 2);
444 vec_dbl_Type funcParameter(1,flagInlet);
445 funcParameter.push_back(0.0); // Dummy for flag
446
447 this->feFactory_->assemblySurfaceRobinBC(this->dim_, this->getDomain(1)->getFEType(),this->getDomain(0)->getFEType(),u_rep_,Kext, funcParameter, dummyFuncRhs,this->parameterList_);
448 Kext->addMatrix(-1.,Fp,1.); // adding advection to diffusion
449
450 // Adding laplace an convection together
451 Ap2->addMatrix(1.,Fp,1.); // adding advection to diffusion
452 AdvPressure->addMatrix(1.,Fp,1.); // adding advection to diffusion
453
454 // Finally if we deal with a transient problem we additionally add the Mass term 1/delta t M_p
456 if(this->parameterList_->sublist("Timestepping Parameter").get("dt",-1.)> -1 ){ // In case we have a timeproblem
457 MatrixPtr_Type Mp2(new Matrix_Type( Mp_ ) );
458 double dt = this->parameterList_->sublist("Timestepping Parameter").get("dt",-1.);
459 Mp2->resumeFill();
460 if(this->parameterList_->sublist("Timestepping Parameter").get("BDF",1) == 1) // BDF 1
461 Mp2->scale(1./dt);
462 else if(this->parameterList_->sublist("Timestepping Parameter").get("BDF",1) == 2) // BDF 1
463 Mp2->scale(3./(2.*dt));
464 else
465 TEUCHOS_TEST_FOR_EXCEPTION( true, std::logic_error, "PCD operator for transient problems only defined for BDF-1 and BDF-2.");
466
467 // Mp2->scale(density);
468 Mp2->fillComplete();
469 Mp2->addMatrix(1.,Fp,1.);
470 }
471 // Fp->scale(1./density);
472 Fp->fillComplete();
473
474 BlockMatrixPtr_Type bcBlockMatrix(new BlockMatrix_Type (1));
475
476 bcBlockMatrix->addBlock(Fp,0,0);
477 bcFactoryPCD_->setSystemScaled(bcBlockMatrix); // We set the boundary conditions into Fp. Both Ap and Fp have Dirichlet zero bc on the outlet
478 // Addionally, a robin bc is applied to the inlet bc for Fp.
479 // Note, if no surfaces are available, the matrix Kext, containg the robin bc is zero,
480 // so no robin bc is applied.
481
482 this->getPreconditionerConst()->setPCDOperator( Fp );
483
484 NAVIER_STOKES_STOP(ReassemblePCD);
485 }
486}
487template<class SC,class LO,class GO,class NO>
488void NavierStokes<SC,LO,GO,NO>::assembleDivAndStab() const{
489
490 double viscosity = this->parameterList_->sublist("Parameter").get("Viscosity",1.);
491 double density = this->parameterList_->sublist("Parameter").get("Density",1.);
492
493 MatrixPtr_Type BT(new Matrix_Type( this->getDomain(0)->getMapVecFieldUnique(), this->getDomain(1)->getDimension() * this->getDomain(1)->getApproxEntriesPerRow() ) );
494
495 MapConstPtr_Type pressureMap;
496 if ( this->getDomain(1)->getFEType() == "P0" )
497 pressureMap = this->getDomain(1)->getElementMap();
498 else
499 pressureMap = this->getDomain(1)->getMapUnique();
500
501 MatrixPtr_Type B(new Matrix_Type( pressureMap, this->getDomain(0)->getDimension() * this->getDomain(0)->getApproxEntriesPerRow() ) );
502
503 MatrixPtr_Type C;
504
505 this->feFactory_->assemblyDivAndDivTFast(this->dim_, this->getFEType(0), this->getFEType(1), 2, B, BT, this->getDomain(0)->getMapVecFieldUnique(), pressureMap, true );
506
507 B->resumeFill();
508 BT->resumeFill();
509
510 B->scale(-1.);
511 BT->scale(-1.);
512
513 B->fillComplete( this->getDomain(0)->getMapVecFieldUnique(), pressureMap );
514 BT->fillComplete( pressureMap, this->getDomain(0)->getMapVecFieldUnique() );
515
516 this->system_->addBlock( BT, 0, 1 );
517 this->system_->addBlock( B, 1, 0 );
518
519 if ( !this->getFEType(0).compare("P1") || !this->getFEType(0).compare("Q1") ) {
520 C.reset(new Matrix_Type( this->getDomain(1)->getMapUnique(), this->getDomain(1)->getApproxEntriesPerRow() ) );
521 this->feFactory_->assemblyBDStabilization( this->dim_, this->getFEType(0), C, true);
522 C->resumeFill();
523 C->scale( -1. / ( viscosity * density ) ); // scaled with dynamic viscosity with mu = nu*rho
524 C->fillComplete( pressureMap, pressureMap );
525
526 this->system_->addBlock( C, 1, 1 );
527 }
528
529 // Implementation of augmented lagrange. This works in theory, but the resulting matrix changes the nnz pattern and has a wider FE Stenciln than before. This can present an issue for the algebraic overlap.
530 // Compare for example to 'ANALYSIS OF AUGMENTED LAGRANGIAN-BASED PRECONDITIONERS FOR THE STEADY INCOMPRESSIBLE NAVIER–STOKES EQUATIONS, MICHELE BENZI AND ZHEN WANG' for the theory behind this.
531 // In augmented lagrange, the term \gamma B^T M_p^{-1} B is added to the velocity-velocity block, where M_p is the pressure mass matrix.
532 if(augmentedLagrange_){
533 NAVIER_STOKES_START(AssembleAugmentedLagrangianComponent,"AssembleDivAndStab: AL - Assemble BT Mp B");
534
535 double gamma = this->parameterList_->sublist("General").get("Gamma",1.0);
536
537 MatrixPtr_Type Mp(new Matrix_Type( this->getDomain(1)->getMapUnique(), this->getDomain(1)->getApproxEntriesPerRow() ) );
538 this->feFactory_->assemblyMass( this->dim_, this->domain_FEType_vec_.at(1), "Scalar", Mp, true );
539
540 MatrixPtr_Type MpInv = Mp->buildDiagonalInverse("Diagonal");
541
542 MpInv->resumeFill();
543 MpInv->scale(gamma);
544 MpInv->fillComplete();
545
546
547 MatrixPtr_Type BT_M(new Matrix_Type( this->getDomain(0)->getMapVecFieldUnique(), this->getDomain(0)->getDimension()*this->getDomain(0)->getApproxEntriesPerRow() ) );
548 BT_M->Multiply(BT,false,MpInv,false);
549
550 BT_Mp_ = BT_M;
551
552 MatrixPtr_Type BT_M_B(new Matrix_Type( this->getDomain(0)->getMapVecFieldUnique(), this->getDomain(0)->getDimension()*this->getDomain(0)->getApproxEntriesPerRow() ) );
553 BT_M_B->Multiply(BT_M,false,B,false);
554
555 BT_Mp_B_ = BT_M_B;
556
557 NAVIER_STOKES_STOP(AssembleAugmentedLagrangianComponent);
558 }
559
560};
561
562template<class SC,class LO,class GO,class NO>
563void NavierStokes<SC,LO,GO,NO>::reAssemble( MatrixPtr_Type& massmatrix, std::string type ) const
564{
565
566}
567
568template<class SC,class LO,class GO,class NO>
569void NavierStokes<SC,LO,GO,NO>::reAssembleFSI(std::string type, MultiVectorPtr_Type u_minus_w, MatrixPtr_Type P) const {
570
571 if (this->verbose_)
572 std::cout << "-- Reassembly Navier-Stokes ("<< type <<") for FSI ... " << std::flush;
573
574 double density = this->parameterList_->sublist("Parameter").get("Density",1.);
575
576 MatrixPtr_Type ANW = Teuchos::rcp(new Matrix_Type( this->getDomain(0)->getMapVecFieldUnique(), this->getDomain(0)->getDimension() * this->getDomain(0)->getApproxEntriesPerRow() ) );
577 if (type=="FixedPoint") {
578
579 MatrixPtr_Type N = Teuchos::rcp(new Matrix_Type( this->getDomain(0)->getMapVecFieldUnique(), this->getDomain(0)->getDimension() * this->getDomain(0)->getApproxEntriesPerRow() ) );
580 this->feFactory_->assemblyAdvectionVecField( this->dim_, this->domain_FEType_vec_.at(0), N, u_minus_w, true );
581
582 N->resumeFill();
583 N->scale(density);
584 N->fillComplete( this->getDomain(0)->getMapVecFieldUnique(), this->getDomain(0)->getMapVecFieldUnique());
585 A_->addMatrix(1.,ANW,0.);
586
587 N->addMatrix(1.,ANW,1.);
588 // P must be scaled correctly in FSI
589 P->addMatrix(1.,ANW,1.);
590
591
592 }
593 else if(type=="Newton"){
594 TEUCHOS_TEST_FOR_EXCEPTION( true, std::logic_error, "reAssembleFSI should only be called for FPI-System.");
595 }
596 ANW->fillComplete( this->getDomain(0)->getMapVecFieldUnique(), this->getDomain(0)->getMapVecFieldUnique() );
597
598 this->system_->addBlock( ANW, 0, 0 );
599
600 if (this->verbose_)
601 std::cout << "done -- " << std::endl;
602}
603
604
605template<class SC,class LO,class GO,class NO>
606void NavierStokes<SC,LO,GO,NO>::reAssemble(std::string type) const {
607
608
609 if (this->verbose_)
610 std::cout << "-- Reassembly Navier-Stokes ("<< type <<") ... " << std::flush;
611
612 double density = this->parameterList_->sublist("Parameter").get("Density",1.);
613
614 // If we use augmented lagrange, the matrix fe-stencil increases and we need to allocate more nnz entries
615 int allocationFactor = 1;
616 if(augmentedLagrange_)
617 allocationFactor = 3;
618 MatrixPtr_Type ANW = Teuchos::rcp(new Matrix_Type( this->getDomain(0)->getMapVecFieldUnique(), allocationFactor*this->getDomain(0)->getDimension() * this->getDomain(0)->getApproxEntriesPerRow() ) );
619 if (type=="FixedPoint") {
620
621 MultiVectorConstPtr_Type u = this->solution_->getBlock(0);
622 u_rep_->importFromVector(u, true);
623
624 MatrixPtr_Type N = Teuchos::rcp(new Matrix_Type( this->getDomain(0)->getMapVecFieldUnique(), this->getDomain(0)->getDimension() * this->getDomain(0)->getApproxEntriesPerRow() ) );
625 this->feFactory_->assemblyAdvectionVecField( this->dim_, this->domain_FEType_vec_.at(0), N, u_rep_, true );
626
627 N->resumeFill();
628 N->scale(density);
629 N->fillComplete( this->getDomain(0)->getMapVecFieldUnique(), this->getDomain(0)->getMapVecFieldUnique());
630
631 A_->addMatrix(1.,ANW,0.);
632 N->addMatrix(1.,ANW,1.);
633
634 }
635 else if(type=="Newton"){ // We assume that reAssmble("FixedPoint") was already called for the current iterate
636
637 MatrixPtr_Type W = Teuchos::rcp(new Matrix_Type( this->getDomain(0)->getMapVecFieldUnique(), this->getDomain(0)->getDimension() * this->getDomain(0)->getApproxEntriesPerRow() ) );
638 this->feFactory_->assemblyAdvectionInUVecField( this->dim_, this->domain_FEType_vec_.at(0), W, u_rep_, true );
639 W->resumeFill();
640 W->scale(density);
641 W->fillComplete( this->getDomain(0)->getMapVecFieldUnique(), this->getDomain(0)->getMapVecFieldUnique());
642 this->system_->getBlock( 0, 0 )->addMatrix(1.,ANW,0.);
643 W->addMatrix(1.,ANW,1.);
644
645 }
646
647 if(augmentedLagrange_)
648 BT_Mp_B_->addMatrix(1.,ANW,1.);
649
650 ANW->fillComplete( this->getDomain(0)->getMapVecFieldUnique(), this->getDomain(0)->getMapVecFieldUnique() );
651
652 this->system_->addBlock( ANW, 0, 0 );
653
654 if (this->verbose_)
655 std::cout << "done -- " << std::endl;
656}
657
658// This function assembles only the non zero pattern of the block (0,0) of the system matrix
659// This is done by using a zero solution vector zeroVec
660// Then, the advection matrices are assembled and added to an empty matrix ANW
661// The resulting matrix ANW contains then the non zero pattern
662// This is then stored as NNZ_A_
663template<class SC,class LO,class GO,class NO>
664void NavierStokes<SC,LO,GO,NO>::establishNNZPattern() const {
665
666
667 if (this->verbose_)
668 std::cout << "-- Establish NNZ Pattern Navier-Stokes ... " << std::flush;
669
670 MatrixPtr_Type ANW = Teuchos::rcp(new Matrix_Type( this->getDomain(0)->getMapVecFieldUnique(), this->getDomain(0)->getDimension() * this->getDomain(0)->getApproxEntriesPerRow() ) );
671
672 MultiVectorPtr_Type zeroVec = Teuchos::rcp( new MultiVector_Type( this->getDomain(0)->getMapVecFieldRepeated(), 1 ) );
673 zeroVec->putScalar(0.0);
674
675 MatrixPtr_Type N = Teuchos::rcp(new Matrix_Type( this->getDomain(0)->getMapVecFieldUnique(), this->getDomain(0)->getDimension() * this->getDomain(0)->getApproxEntriesPerRow() ) );
676 this->feFactory_->assemblyAdvectionVecField( this->dim_, this->domain_FEType_vec_.at(0), N, zeroVec, true );
677
678 N->addMatrix(1.,ANW,0.);
679
680 MatrixPtr_Type W = Teuchos::rcp(new Matrix_Type( this->getDomain(0)->getMapVecFieldUnique(), this->getDomain(0)->getDimension() * this->getDomain(0)->getApproxEntriesPerRow() ) );
681 this->feFactory_->assemblyAdvectionInUVecField( this->dim_, this->domain_FEType_vec_.at(0), W, zeroVec, true );
682
683 W->addMatrix(1.,ANW,1.);
684
685 ANW->fillComplete( this->getDomain(0)->getMapVecFieldUnique(), this->getDomain(0)->getMapVecFieldUnique() );
686
687 NNZ_A_= ANW;
688
689 if (this->verbose_)
690 std::cout << "done -- " << std::endl;
691}
692
693template<class SC,class LO,class GO,class NO>
694void NavierStokes<SC,LO,GO,NO>::reAssembleExtrapolation(BlockMultiVectorPtrArray_Type previousSolutions){
695
696 if (this->verbose_)
697 std::cout << "-- Reassembly Navier-Stokes (Extrapolation) ... " << std::flush;
698
699
700 double density = this->parameterList_->sublist("Parameter").get("Density",1.);
701
702 if (previousSolutions.size()>=2) {
703
704 MultiVectorPtr_Type extrapolatedVector = Teuchos::rcp( new MultiVector_Type( previousSolutions[0]->getBlock(0) ) );
705
706 extrapolatedVector->update( -1., *previousSolutions[1]->getBlock(0), 2. );
707
708 u_rep_->importFromVector(extrapolatedVector, true);
709 }
710 else if(previousSolutions.size()==1){
711 MultiVectorConstPtr_Type u = previousSolutions[0]->getBlock(0);
712 u_rep_->importFromVector(u, true);
713 }
714 else if (previousSolutions.size()==0){
715 MultiVectorConstPtr_Type u = this->solution_->getBlock(0);
716 u_rep_->importFromVector(u, true);
717 }
718
719 MatrixPtr_Type ANW = Teuchos::rcp(new Matrix_Type( this->getDomain(0)->getMapVecFieldUnique(), this->getDomain(0)->getDimension() * this->getDomain(0)->getApproxEntriesPerRow() ) );
720
721 MatrixPtr_Type N = Teuchos::rcp(new Matrix_Type( this->getDomain(0)->getMapVecFieldUnique(), this->getDomain(0)->getDimension() * this->getDomain(0)->getApproxEntriesPerRow() ) );
722 this->feFactory_->assemblyAdvectionVecField( this->dim_, this->domain_FEType_vec_.at(0), N, u_rep_, true );
723
724 N->resumeFill();
725 N->scale(density);
726 N->fillComplete( this->getDomain(0)->getMapVecFieldUnique(), this->getDomain(0)->getMapVecFieldUnique());
727
728 A_->addMatrix(1.,ANW,0.);
729 N->addMatrix(1.,ANW,1.);
730
731 ANW->fillComplete( this->getDomain(0)->getMapVecFieldUnique(), this->getDomain(0)->getMapVecFieldUnique() );
732
733 this->system_->addBlock( ANW, 0, 0 );
734
735 if (this->verbose_)
736 std::cout << "done -- " << std::endl;
737}
738
739template<class SC,class LO,class GO,class NO>
740void NavierStokes<SC,LO,GO,NO>::calculateNonLinResidualVec(std::string type, double time) const{
741
742 if (this->verbose_)
743 std::cout << "-- NavierStokes::calculateNonLinResidualVec ("<< type <<") ... " << std::flush;
744
745 this->reAssemble("FixedPoint");
746 // We need to account for different parameters of time discretizations here
747 // This is ok for bdf with 1.0 scaling of the system. Would be wrong for Crank-Nicolson - might be ok now for CN
748 if (this->coeff_.size() == 0)
749 this->system_->apply( *this->solution_, *this->residualVec_ );
750 else
751 this->system_->apply( *this->solution_, *this->residualVec_, this->coeff_ );
752
753 // The additional component needs to be acconted for in residual as well due to augmented lagrange
754 if(augmentedLagrange_){
755 MultiVectorPtr_Type rhsAL = Teuchos::rcp( new MultiVector_Type( this->residualVec_->getBlock(0) ) );
756 BT_Mp_->apply( *this->residualVec_->getBlock(1), *rhsAL );
757 this->residualVec_->getBlockNonConst(0)->update(1.,*rhsAL,1.);
758
759 }
760 if (!type.compare("standard")){
761 this->residualVec_->update(-1.,*this->rhs_,1.);
762 // this might be set again by the TimeProblem after addition of M*u
763 this->bcFactory_->setVectorMinusBC( this->residualVec_, this->solution_, time );
764
765 }
766 else if(!type.compare("reverse")){
767 this->residualVec_->update(1.,*this->rhs_,-1.); // this = -1*this + 1*rhs
768 // this might be set again by the TimeProblem after addition of M*u
769 this->bcFactory_->setBCMinusVector( this->residualVec_, this->solution_, time );
770 }
771
772}
773
774template<class SC,class LO,class GO,class NO>
775void NavierStokes<SC,LO,GO,NO>::calculateNonLinResidualVecWithMeshVelo(std::string type, double time, MultiVectorPtr_Type u_minus_w, MatrixPtr_Type P) const{
776
777
778 this->reAssembleFSI( "FixedPoint", u_minus_w, P );
779
780 // We need to account for different parameters of time discretizations here
781 // This is ok for bdf with 1.0 scaling of the system. Would be wrong for Crank-Nicolson
782
783 this->system_->apply( *this->solution_, *this->residualVec_ );
784
785 if (!type.compare("standard")){
786 this->residualVec_->update(-1.,*this->rhs_,1.);
787 if ( !this->sourceTerm_.is_null() )
788 this->residualVec_->update(-1.,*this->sourceTerm_,1.);
789 }
790 else if(!type.compare("reverse")){
791 this->residualVec_->update(1.,*this->rhs_,-1.); // this = -1*this + 1*rhs
792 if ( !this->sourceTerm_.is_null() )
793 this->residualVec_->update(1.,*this->sourceTerm_,1.);
794 }
795
796 // this might be set again by the TimeProblem after addition of M*u
797 this->bcFactory_->setBCMinusVector( this->residualVec_, this->solution_, time );
798
799}
800
801}
802
803#endif
virtual void assemble(std::string type="") const
assemble of type exectuted by the derived specific non-linear problem classes
Definition NavierStokes_def.hpp:165
void updateConvectionDiffusionOperator() const
Definition NavierStokes_def.hpp:413
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 NavierStokes_def.hpp:740
Definition NonLinearProblem_decl.hpp:28
Adaptive Mesh Refinement.
Definition AdaptiveMeshRefinement_decl.hpp:36