Finite Element Domain Decomposition Library
FEDDLib
Loading...
Searching...
No Matches
NavierStokes_def.hpp
1#ifndef NAVIERSTOKES_def_hpp
2#define NAVIERSTOKES_def_hpp
3#include "NavierStokes_decl.hpp"
4
13
14void sxOne2D(double* x, double* res, double t, double* parameter){
15
16 res[0] = 1.;
17 res[1] = 0.;
18 return;
19}
20
21void syOne2D(double* x, double* res, double t, double* parameter){
22
23 res[0] = 0.;
24 res[1] = 1.;
25
26 return;
27}
28void sDummyFunc(double* x, double* res, double t, double* parameter){
29
30 return;
31}
32
33double OneFunction(double* x, int* parameter)
34{
35 return 1.0;
36}
37
38namespace FEDD {
39
40
41
42template<class SC,class LO,class GO,class NO>
43NavierStokes<SC,LO,GO,NO>::NavierStokes( const DomainConstPtr_Type &domainVelocity, std::string FETypeVelocity, const DomainConstPtr_Type &domainPressure, std::string FETypePressure, ParameterListPtr_Type parameterList ):
44NonLinearProblem<SC,LO,GO,NO>( parameterList, domainVelocity->getComm() ),
45A_(),
46pressureIDsLoc(new vec_int_Type(2)),
47u_rep_()
48{
49
50 this->nonLinearTolerance_ = this->parameterList_->sublist("Parameter").get("relNonLinTol",1.0e-6);
51 this->initNOXParameters();
52
53 this->addVariable( domainVelocity , FETypeVelocity , "u" , domainVelocity->getDimension());
54 this->addVariable( domainPressure , FETypePressure , "p" , 1);
55 this->dim_ = this->getDomain(0)->getDimension();
56
57 u_rep_ = Teuchos::rcp( new MultiVector_Type( this->getDomain(0)->getMapVecFieldRepeated() ) );
58
59 if (parameterList->sublist("Parameter").get("Calculate Coefficients",false)) {
60 vec2D_dbl_ptr_Type vectmpPointsPressure = domainPressure->getPointsUnique();
61 vec2D_dbl_Type::iterator it;
62 int front = -1;
63 int back = -1;
64 if (domainPressure->getDimension() == 2) {
65 it = find_if(vectmpPointsPressure->begin(), vectmpPointsPressure->end(),
66 [&] (const std::vector<double>& a){
67 if (a.at(0) >= 0.15-1.e-12 && a.at(0) <= 0.15+1.e-12
68 && a.at(1) >= 0.2-1.e-12 && a.at(1) <= 0.2+1.e-12) {
69 return true;
70 }
71 else {
72 return false;
73 }
74 });
75
76 if (it != vectmpPointsPressure->end()) {
77 front = distance(vectmpPointsPressure->begin(),it);
78 }
79 it = find_if(vectmpPointsPressure->begin(), vectmpPointsPressure->end(),
80 [&] (const std::vector<double>& a){
81 if (a.at(0) >= 0.25-1.e-12 && a.at(0) <= 0.25+1.e-12
82 && a.at(1) >= 0.2-1.e-12 && a.at(1) <= 0.2+1.e-12) {
83 return true;
84 }
85 else {
86 return false;
87 }
88 });
89
90 if (it != vectmpPointsPressure->end()) {
91 back = distance(vectmpPointsPressure->begin(),it);
92 }
93 pressureIDsLoc->at(0) = front;
94 pressureIDsLoc->at(1) = back;
95 }
96 else if(domainPressure->getDimension() == 3){
97#ifdef ASSERTS_WARNINGS
98 MYASSERT(false,"Not implemented to calc coefficients in 3D!");
99#endif
100 }
101 }
102
103}
104
105template<class SC,class LO,class GO,class NO>
106void NavierStokes<SC,LO,GO,NO>::info(){
107 this->infoProblem();
108 this->infoNonlinProblem();
109}
110
111template<class SC,class LO,class GO,class NO>
112void NavierStokes<SC,LO,GO,NO>::assemble( std::string type ) const{
113
114 if (type=="") {
115 if (this->verbose_)
116 std::cout << "-- Assembly Navier-Stokes ... " << std::endl;
117
118 assembleConstantMatrices();
119
120 if (this->verbose_)
121 std::cout << "done -- " << std::endl;
122 }
123 else
124 reAssemble( type );
125
126};
127
128template<class SC,class LO,class GO,class NO>
129void NavierStokes<SC,LO,GO,NO>::assembleConstantMatrices() const{
130
131 if (this->verbose_)
132 std::cout << "-- Assembly constant matrices Navier-Stokes ... " << std::flush;
133
134 double viscosity = this->parameterList_->sublist("Parameter").get("Viscosity",1.);
135 double density = this->parameterList_->sublist("Parameter").get("Density",1.);
136
137 // Egal welcher Wert, da OneFunction nicht von parameter abhaengt
138 int* dummy;
139
140 A_.reset(new Matrix_Type( this->getDomain(0)->getMapVecFieldUnique(), this->getDomain(0)->getDimension() * this->getDomain(0)->getApproxEntriesPerRow() ) );
141
142 if ( this->parameterList_->sublist("Parameter").get("Symmetric gradient",false) )
143 this->feFactory_->assemblyStress(this->dim_, this->domain_FEType_vec_.at(0), A_, OneFunction, dummy, true);
144 else
145 this->feFactory_->assemblyLaplaceVecField(this->dim_, this->domain_FEType_vec_.at(0), 2, A_, true);
146
147 A_->resumeFill();
148
149 A_->scale(viscosity);
150 A_->scale(density);
151
152 A_->fillComplete( this->getDomain(0)->getMapVecFieldUnique(), this->getDomain(0)->getMapVecFieldUnique());
153
154 if (this->system_.is_null())
155 this->system_.reset(new BlockMatrix_Type(2));
156
157 this->system_->addBlock( A_, 0, 0 );
158 assembleDivAndStab();
159
160#ifdef FEDD_HAVE_TEKO
161 if ( !this->parameterList_->sublist("General").get("Preconditioner Method","Monolithic").compare("Teko") ) {
162 if (!this->parameterList_->sublist("General").get("Assemble Velocity Mass",false)) {
163 MatrixPtr_Type Mvelocity(new Matrix_Type( this->getDomain(0)->getMapVecFieldUnique(), this->getDomain(0)->getApproxEntriesPerRow() ) );
164 //
165 this->feFactory_->assemblyMass( this->dim_, this->domain_FEType_vec_.at(0), "Vector", Mvelocity, true );
166 //
167 this->getPreconditionerConst()->setVelocityMassMatrix( Mvelocity );
168 if (this->verbose_)
169 std::cout << "\nVelocity mass matrix for LSC block preconditioner is assembled." << std::endl;
170 } else {
171 if (this->verbose_)
172 std::cout << "\nVelocity mass matrix for LSC block preconditioner not assembled." << std::endl;
173 }
174 }
175#endif
176 std::string precType = this->parameterList_->sublist("General").get("Preconditioner Method","Monolithic");
177 if ( precType == "Diagonal" || precType == "Triangular" ) {
178 MatrixPtr_Type Mpressure(new Matrix_Type( this->getDomain(1)->getMapUnique(), this->getDomain(1)->getApproxEntriesPerRow() ) );
179
180 this->feFactory_->assemblyMass( this->dim_, this->domain_FEType_vec_.at(1), "Scalar", Mpressure, true );
181 SC kinVisco = this->parameterList_->sublist("Parameter").get("Viscosity",1.);
182 Mpressure->scale(-1./kinVisco);
183 this->getPreconditionerConst()->setPressureMassMatrix( Mpressure );
184 }
185
186 if (this->verbose_)
187 std::cout << " Call Reassemble FixedPoint and Newton to allocate the Matrix pattern " << std::endl;
188
189 // This was moved here from 'create_W_op'.
190 // Here it will definetly be called before create_W_op and create_W_prec is called.
191 this->reAssemble("FixedPoint");
192 this->reAssemble("Newton");
193
194 if (this->verbose_)
195 std::cout << "done -- " << std::endl;
196
197};
198
199template<class SC,class LO,class GO,class NO>
200void NavierStokes<SC,LO,GO,NO>::assembleDivAndStab() const{
201
202 double viscosity = this->parameterList_->sublist("Parameter").get("Viscosity",1.);
203 double density = this->parameterList_->sublist("Parameter").get("Density",1.);
204
205 // Egal welcher Wert, da OneFunction nicht von parameter abhaengt
206
207 MatrixPtr_Type BT(new Matrix_Type( this->getDomain(0)->getMapVecFieldUnique(), this->getDomain(1)->getDimension() * this->getDomain(1)->getApproxEntriesPerRow() ) );
208
209 MapConstPtr_Type pressureMap;
210 if ( this->getDomain(1)->getFEType() == "P0" )
211 pressureMap = this->getDomain(1)->getElementMap();
212 else
213 pressureMap = this->getDomain(1)->getMapUnique();
214
215 MatrixPtr_Type B(new Matrix_Type( pressureMap, this->getDomain(0)->getDimension() * this->getDomain(0)->getApproxEntriesPerRow() ) );
216
217 MatrixPtr_Type C;
218
219 this->feFactory_->assemblyDivAndDivTFast(this->dim_, this->getFEType(0), this->getFEType(1), 2, B, BT, this->getDomain(0)->getMapVecFieldUnique(), pressureMap, true );
220
221 B->resumeFill();
222 BT->resumeFill();
223
224 B->scale(-1.);
225 BT->scale(-1.);
226
227 B->fillComplete( this->getDomain(0)->getMapVecFieldUnique(), pressureMap );
228 BT->fillComplete( pressureMap, this->getDomain(0)->getMapVecFieldUnique() );
229
230 this->system_->addBlock( BT, 0, 1 );
231 this->system_->addBlock( B, 1, 0 );
232
233 if ( !this->getFEType(0).compare("P1") ) {
234 C.reset(new Matrix_Type( this->getDomain(1)->getMapUnique(), this->getDomain(1)->getApproxEntriesPerRow() ) );
235 this->feFactory_->assemblyBDStabilization( this->dim_, "P1", C, true);
236 C->resumeFill();
237 C->scale( -1. / ( viscosity * density ) );
238 C->fillComplete( pressureMap, pressureMap );
239
240 this->system_->addBlock( C, 1, 1 );
241 }
242 //else
243 // C.reset(new Matrix_Type( this->getDomain(1)->getMapUnique(), this->getDomain(1)->getApproxEntriesPerRow() ) );
244 // this->feFactory_->assemblyEmptyMatrix(C);
245
246 //this->system_->addBlock( C, 1, 1 );
247
248};
249
250template<class SC,class LO,class GO,class NO>
251void NavierStokes<SC,LO,GO,NO>::reAssemble( MatrixPtr_Type& massmatrix, std::string type ) const
252{
253
254}
255
256template<class SC,class LO,class GO,class NO>
257void NavierStokes<SC,LO,GO,NO>::reAssembleFSI(std::string type, MultiVectorPtr_Type u_minus_w, MatrixPtr_Type P) const {
258
259 if (this->verbose_)
260 std::cout << "-- Reassembly Navier-Stokes ("<< type <<") for FSI ... " << std::flush;
261
262 double density = this->parameterList_->sublist("Parameter").get("Density",1.);
263
264 MatrixPtr_Type ANW = Teuchos::rcp(new Matrix_Type( this->getDomain(0)->getMapVecFieldUnique(), this->getDomain(0)->getDimension() * this->getDomain(0)->getApproxEntriesPerRow() ) );
265 if (type=="FixedPoint") {
266
267 MatrixPtr_Type N = Teuchos::rcp(new Matrix_Type( this->getDomain(0)->getMapVecFieldUnique(), this->getDomain(0)->getDimension() * this->getDomain(0)->getApproxEntriesPerRow() ) );
268 this->feFactory_->assemblyAdvectionVecField( this->dim_, this->domain_FEType_vec_.at(0), N, u_minus_w, true );
269
270 N->resumeFill();
271 N->scale(density);
272 N->fillComplete( this->getDomain(0)->getMapVecFieldUnique(), this->getDomain(0)->getMapVecFieldUnique());
273 A_->addMatrix(1.,ANW,0.);
274
275 N->addMatrix(1.,ANW,1.);
276 // P must be scaled correctly in FSI
277 P->addMatrix(1.,ANW,1.);
278
279
280 }
281 else if(type=="Newton"){
282 TEUCHOS_TEST_FOR_EXCEPTION( true, std::logic_error, "reAssembleFSI should only be called for FPI-System.");
283 }
284 ANW->fillComplete( this->getDomain(0)->getMapVecFieldUnique(), this->getDomain(0)->getMapVecFieldUnique() );
285
286 this->system_->addBlock( ANW, 0, 0 );
287
288 if (this->verbose_)
289 std::cout << "done -- " << std::endl;
290}
291
292
293template<class SC,class LO,class GO,class NO>
294void NavierStokes<SC,LO,GO,NO>::reAssemble(std::string type) const {
295
296
297 if (this->verbose_)
298 std::cout << "-- Reassembly Navier-Stokes ("<< type <<") ... " << std::flush;
299
300 double density = this->parameterList_->sublist("Parameter").get("Density",1.);
301
302 MatrixPtr_Type ANW = Teuchos::rcp(new Matrix_Type( this->getDomain(0)->getMapVecFieldUnique(), this->getDomain(0)->getDimension() * this->getDomain(0)->getApproxEntriesPerRow() ) );
303 if (type=="FixedPoint") {
304
305 MultiVectorConstPtr_Type u = this->solution_->getBlock(0);
306 u_rep_->importFromVector(u, true);
307
308 MatrixPtr_Type N = Teuchos::rcp(new Matrix_Type( this->getDomain(0)->getMapVecFieldUnique(), this->getDomain(0)->getDimension() * this->getDomain(0)->getApproxEntriesPerRow() ) );
309 this->feFactory_->assemblyAdvectionVecField( this->dim_, this->domain_FEType_vec_.at(0), N, u_rep_, true );
310
311 N->resumeFill();
312 N->scale(density);
313 N->fillComplete( this->getDomain(0)->getMapVecFieldUnique(), this->getDomain(0)->getMapVecFieldUnique());
314
315 A_->addMatrix(1.,ANW,0.);
316 N->addMatrix(1.,ANW,1.);
317 }
318 else if(type=="Newton"){ // We assume that reAssmble("FixedPoint") was already called for the current iterate
319 MatrixPtr_Type W = Teuchos::rcp(new Matrix_Type( this->getDomain(0)->getMapVecFieldUnique(), this->getDomain(0)->getDimension() * this->getDomain(0)->getApproxEntriesPerRow() ) );
320 this->feFactory_->assemblyAdvectionInUVecField( this->dim_, this->domain_FEType_vec_.at(0), W, u_rep_, true );
321 W->resumeFill();
322 W->scale(density);
323 W->fillComplete( this->getDomain(0)->getMapVecFieldUnique(), this->getDomain(0)->getMapVecFieldUnique());
324 this->system_->getBlock( 0, 0 )->addMatrix(1.,ANW,0.);
325 W->addMatrix(1.,ANW,1.);
326 }
327 ANW->fillComplete( this->getDomain(0)->getMapVecFieldUnique(), this->getDomain(0)->getMapVecFieldUnique() );
328
329 this->system_->addBlock( ANW, 0, 0 );
330
331 if (this->verbose_)
332 std::cout << "done -- " << std::endl;
333}
334
335template<class SC,class LO,class GO,class NO>
336void NavierStokes<SC,LO,GO,NO>::reAssembleExtrapolation(BlockMultiVectorPtrArray_Type previousSolutions){
337
338 if (this->verbose_)
339 std::cout << "-- Reassembly Navier-Stokes (Extrapolation) ... " << std::flush;
340
341
342 double density = this->parameterList_->sublist("Parameter").get("Density",1.);
343
344 if (previousSolutions.size()>=2) {
345
346 MultiVectorPtr_Type extrapolatedVector = Teuchos::rcp( new MultiVector_Type( previousSolutions[0]->getBlock(0) ) );
347
348 extrapolatedVector->update( -1., *previousSolutions[1]->getBlock(0), 2. );
349
350 u_rep_->importFromVector(extrapolatedVector, true);
351 }
352 else if(previousSolutions.size()==1){
353 MultiVectorConstPtr_Type u = previousSolutions[0]->getBlock(0);
354 u_rep_->importFromVector(u, true);
355 }
356 else if (previousSolutions.size()==0){
357 MultiVectorConstPtr_Type u = this->solution_->getBlock(0);
358 u_rep_->importFromVector(u, true);
359 }
360
361 MatrixPtr_Type ANW = Teuchos::rcp(new Matrix_Type( this->getDomain(0)->getMapVecFieldUnique(), this->getDomain(0)->getDimension() * this->getDomain(0)->getApproxEntriesPerRow() ) );
362
363 MatrixPtr_Type N = Teuchos::rcp(new Matrix_Type( this->getDomain(0)->getMapVecFieldUnique(), this->getDomain(0)->getDimension() * this->getDomain(0)->getApproxEntriesPerRow() ) );
364 this->feFactory_->assemblyAdvectionVecField( this->dim_, this->domain_FEType_vec_.at(0), N, u_rep_, true );
365
366 N->resumeFill();
367 N->scale(density);
368 N->fillComplete( this->getDomain(0)->getMapVecFieldUnique(), this->getDomain(0)->getMapVecFieldUnique());
369
370 A_->addMatrix(1.,ANW,0.);
371 N->addMatrix(1.,ANW,1.);
372
373 ANW->fillComplete( this->getDomain(0)->getMapVecFieldUnique(), this->getDomain(0)->getMapVecFieldUnique() );
374
375 this->system_->addBlock( ANW, 0, 0 );
376
377 if (this->verbose_)
378 std::cout << "done -- " << std::endl;
379}
380
381//template<class SC,class LO,class GO,class NO>
382//int NavierStokes<SC,LO,GO,NO>::ComputeDragLift(vec_dbl_ptr_Type &values){
383//
384// int dimension = this->domainPtr_vec_.at(0)->GetDimension();
385// MultiVector_ptr_vec_ptr_Type sol_unique_vec(new std::vector<MultiVector_ptr_Type>(0));
386// this->system_->FillSplitVector64(*this->solution_, sol_unique_vec);
387// this->system_->BuildRepeatedVectorBlocks(sol_unique_vec);
388// Vector_ptr_Type u_rep(new Epetra_Vector(*(this->system_->GetRepeatedVec(0))));
389// Teuchos::RCP<Epetra_FECrsMatrix> N(new Epetra_FECrsMatrix(Epetra_DataAccess::Copy,*(this->domainPtr_vec_.at(0)->GetMapXDimUnique()),10));
390// u_rep.reset(new Epetra_Vector(*(this->system_->GetRepeatedVec(0))));
391// N.reset(new Epetra_FECrsMatrix(Epetra_DataAccess::Copy,*(this->domainPtr_vec_.at(0)->GetMapXDimUnique()),10));
392// this->feFactory_->AssemblyAdvectionXDim(dimension, this->domain_FEType_vec_.at(0), 7, N, u_rep /* u */, setZeros);
393//
394// Teuchos::RCP<Epetra_CrsMatrix> AN(new Epetra_CrsMatrix(Epetra_DataAccess::Copy,*(this->domainPtr_vec_.at(0)->GetMapXDimUnique()),10));
395//
396// EpetraExt::MatrixMatrix::Add(*A_,false,1.,*AN,1.);
397// EpetraExt::MatrixMatrix::Add(*N,false,1.,*AN,1.);
398//
399// AN.reset(new Epetra_CrsMatrix(Epetra_DataAccess::Copy,*(this->domainPtr_vec_.at(0)->GetMapXDimUnique()),10));
400// EpetraExt::MatrixMatrix::Add(*A_,false,1.,*AN,1.);
401// EpetraExt::MatrixMatrix::Add(*N,false,1.,*AN,1.);
402// AN->FillComplete();
403//
404//
405// Teuchos::RCP<Epetra_FECrsMatrix> B_T (new Epetra_FECrsMatrix(Epetra_DataAccess::Copy,*(this->domainPtr_vec_.at(0)->GetMapXDimUnique()),5));
406// Teuchos::RCP<Epetra_FECrsMatrix> B (new Epetra_FECrsMatrix(Epetra_DataAccess::Copy,*(this->domainPtr_vec_.at(1)->GetMapUnique()),5));
407// this->feFactory_->AssemblyDivergence(dimension, this->domain_FEType_vec_.at(0), this->domain_FEType_vec_.at(1), 2, B, B_T, setZeros, this->domainPtr_vec_.at(0)->GetMapXDimUnique(), this->domainPtr_vec_.at(1)->GetMapUnique());
408// B_T->Scale(-1.);
409// Teuchos::RCP<BlockElement> BE_AN(new BlockElement(AN));
410// Teuchos::RCP<BlockElement> BE_B_T(new BlockElement(B_T));
411//
412// BE_AN.reset(new BlockElement(AN));
413// BE_B_T.reset(new BlockElement(B_T));
414//
415// this->system_->ReplaceBlock(BE_AN,0,0);
416// this->system_->ReplaceBlock(BE_B_T,0,1);
417//
418// Teuchos::RCP<BCBuilder> bCFactoryDrag(new BCBuilder(sublist(this->parameterList_,"Parameter")));
419// Teuchos::RCP<BCBuilder> bCFactoryLift(new BCBuilder(sublist(this->parameterList_,"Parameter")));
420//
421// bCFactoryDrag->AddBC(sxOne2D, 4, 0, this->domainPtr_vec_.at(0), "Dirichlet", dimension);
422// bCFactoryDrag->AddBC(sDummyFunc, 666, 1, this->domainPtr_vec_.at(1), "Neumann", 1);
423//
424// bCFactoryLift->AddBC(syOne2D, 4, 0, this->domainPtr_vec_.at(0), "Dirichlet", dimension);
425// bCFactoryLift->AddBC(sDummyFunc, 666, 1, this->domainPtr_vec_.at(1), "Neumann", 1);
426//
427// Teuchos::RCP<Epetra_Vector> dragVec(new Epetra_Vector(*(*this->solution_)(0)));
428// Teuchos::RCP<Epetra_Vector> liftVec(new Epetra_Vector(*(*this->solution_)(0)));
429// dragVec->PutScalar(0.);
430// liftVec->PutScalar(0.);
431// bCFactoryDrag->SetRHS(this->system_, dragVec);
432// bCFactoryLift->SetRHS(this->system_, liftVec);
433//
434// Teuchos::RCP<Epetra_Vector> mat_sol(new Epetra_Vector(*(*this->solution_)(0)));
435// this->system_->Apply(*this->solution_,*mat_sol);
436// mat_sol->Scale(-1.);
437// double dragCoeff;
438// double liftCoeff;
439// mat_sol->Dot(*dragVec,&dragCoeff);
440// mat_sol->Dot(*liftVec,&liftCoeff);
441// values->at(0) = dragCoeff;
442// values->at(1) = liftCoeff;
443// if (this->verbose_) {
444// cout<< "Not scaled drag coefficient: " << dragCoeff<< endl;
445// cout<< "Not scaled lift coefficient: " << liftCoeff<< endl;
446// }
447// Teuchos::RCP<Epetra_Vector> pressureSolutuion( new Epetra_Vector(*((*(sol_unique_vec->at(1)))(0))));
448// double p1 = numeric_limits<double>::min();
449// double p2 = numeric_limits<double>::min();
450// if (pressureIDsLoc->at(0)>-1) {
451// p1 = (*pressureSolutuion)[pressureIDsLoc->at(0)];
452//
453// }
454// if (pressureIDsLoc->at(1)>-1) {
455// p2 = (*pressureSolutuion)[pressureIDsLoc->at(1)];
456// }
457// this->comm_->Barrier();
458// double res;
459// this->comm_->MaxAll(&p1,&res,1);
460// values->at(2) = res;
461// this->comm_->MaxAll(&p2,&res,1);
462// values->at(3) = res;
463// return 0;
464//}
465
466//template<class SC,class LO,class GO,class NO>
467//typename NavierStokes<SC,LO,GO,NO>::MultiVector_Type NavierStokes<SC,LO,GO,NO>::GetExactSolution(double time){
468//#ifdef ASSERTS_WARNINGS
469// MYASSERT(false,"no analytic solution.");
470//#endif
471// return *this->solution_;
472//}
473
474
475//template<class SC,class LO,class GO,class NO>
476//void NavierStokes<SC,LO,GO,NO>::set_x0(const Teuchos::ArrayView<const SC> &x0_in){
477//#ifdef TEUCHOS_DEBUG
478// TEUCHOS_ASSERT_EQUALITY(xSpace_->dim(), x0_in.size());
479//#endif
480// Thyra::DetachedVectorView<SC> x0(x0_);
481// x0.sv().values()().assign(x0_in);
482//}
483
484template<class SC,class LO,class GO,class NO>
485void NavierStokes<SC,LO,GO,NO>::evalModelImpl(const Thyra::ModelEvaluatorBase::InArgs<SC> &inArgs,
486 const Thyra::ModelEvaluatorBase::OutArgs<SC> &outArgs
487 ) const
488{
489 std::string type = this->parameterList_->sublist("General").get("Preconditioner Method","Monolithic");
490 if ( !type.compare("Monolithic"))
491 evalModelImplMonolithic( inArgs, outArgs );
492 else if ( !type.compare("Teko")){
493#ifdef FEDD_HAVE_TEKO
494 evalModelImplBlock( inArgs, outArgs );
495#else
496 TEUCHOS_TEST_FOR_EXCEPTION( true, std::logic_error, "Teko not found! Build Trilinos with Teko.");
497#endif
498 }
499 else
500 TEUCHOS_TEST_FOR_EXCEPTION( true, std::logic_error, "Unkown preconditioner/solver type.");
501}
502
507template<class SC,class LO,class GO,class NO>
508void NavierStokes<SC,LO,GO,NO>::evalModelImplMonolithic(const Thyra::ModelEvaluatorBase::InArgs<SC> &inArgs,
509 const Thyra::ModelEvaluatorBase::OutArgs<SC> &outArgs ) const
510{
511
512
513 using Teuchos::RCP;
514 using Teuchos::rcp;
515 using Teuchos::rcp_dynamic_cast;
516 using Teuchos::rcp_const_cast;
517 using Teuchos::ArrayView;
518 using Teuchos::Array;
519 RCP<Teuchos::FancyOStream> fancy = Teuchos::fancyOStream(Teuchos::rcpFromRef(std::cout));
520 TEUCHOS_TEST_FOR_EXCEPTION( inArgs.get_x().is_null(), std::logic_error, "inArgs.get_x() is null.");
521
522 RCP< const Thyra::VectorBase< SC > > vecThyra = inArgs.get_x();
523 RCP<Teuchos::FancyOStream> out = Teuchos::VerboseObjectBase::getDefaultOStream();
524
525 RCP< Thyra::VectorBase< SC > > vecThyraNonConst = rcp_const_cast<Thyra::VectorBase< SC > >(vecThyra);
526
527 this->solution_->fromThyraMultiVector(vecThyraNonConst);
528
529 const RCP<Thyra::MultiVectorBase<SC> > f_out = outArgs.get_f();
530 const RCP<Thyra::LinearOpBase<SC> > W_out = outArgs.get_W_op();
531 const RCP<Thyra::PreconditionerBase<SC> > W_prec_out = outArgs.get_W_prec();
532
533 typedef Thyra::TpetraOperatorVectorExtraction<SC,LO,GO,NO> tpetra_extract;
534 typedef Tpetra::CrsMatrix<SC,LO,GO,NO> TpetraMatrix_Type;
535 typedef RCP<TpetraMatrix_Type> TpetraMatrixPtr_Type;
536 typedef RCP<const TpetraMatrix_Type> TpetraMatrixConstPtr_Type;
537
538 const bool fill_f = nonnull(f_out);
539 const bool fill_W = nonnull(W_out);
540 const bool fill_W_prec = nonnull(W_prec_out);
541
542
543 if ( fill_f || fill_W || fill_W_prec ) {
544
545 // ****************
546 // Get the underlying xpetra objects
547 // ****************
548 if (fill_f) {
549
550 this->calculateNonLinResidualVec("standard"); // Calculating residual Vector
551
552 // Changing the residualVector into a ThyraMultivector
553
554 Teuchos::RCP<Thyra::MultiVectorBase<SC> > f_thyra = this->getResidualVector()->getThyraMultiVector();
555 f_out->assign(*f_thyra);
556 }
557
558 TpetraMatrixPtr_Type W;
559 if (fill_W) {
560 this->reAssemble("Newton"); // ReAssembling matrices with updated u in this class
561
562 this->setBoundariesSystem(); // setting boundaries to the system
563
564 Teuchos::RCP<TpetraOp_Type> W_tpetra = tpetra_extract::getTpetraOperator(W_out);
565 Teuchos::RCP<TpetraMatrix_Type> W_tpetraMat = Teuchos::rcp_dynamic_cast<TpetraMatrix_Type>(W_tpetra);
566
567 TpetraMatrixConstPtr_Type W_systemTpetra = this->getSystem()->getMergedMatrix()->getTpetraMatrix();
568 TpetraMatrixPtr_Type W_systemTpetraNonConst = rcp_const_cast<TpetraMatrix_Type>(W_systemTpetra);
569
570 //Tpetra::CrsMatrixWrap<SC,LO,GO,NO>& crsOp = dynamic_cast<Xpetra::CrsMatrixWrap<SC,LO,GO,NO>&>(*W_systemXpetraNonConst);
571 //Xpetra::TpetraCrsMatrix<SC,LO,GO,NO>& xTpetraMat = dynamic_cast<Xpetra::TpetraCrsMatrix<SC,LO,GO,NO>&>(*crsOp.getCrsMatrix());
572
573 Teuchos::RCP<TpetraMatrix_Type> tpetraMatTpetra = W_systemTpetraNonConst; //xTpetraMat.getTpetra_CrsMatrixNonConst();
574
575 W_tpetraMat->resumeFill();
576
577 for (auto i=0; i<tpetraMatTpetra->getMap()->getLocalNumElements(); i++) {
578 typename Tpetra::CrsMatrix<SC,LO,GO,NO>::local_inds_host_view_type indices; //ArrayView< const LO > indices
579 typename Tpetra::CrsMatrix<SC,LO,GO,NO>::values_host_view_type values;
580 tpetraMatTpetra->getLocalRowView( i, indices, values);
581 W_tpetraMat->replaceLocalValues( i, indices, values);
582 }
583 W_tpetraMat->fillComplete();
584
585 }
586
587 if (fill_W_prec) {
588 this->setupPreconditioner( "Monolithic" );
589
590 // ch 26.04.19: After each setup of the preconditioner we check if we use a two-level precondtioner with multiplicative combination between the levels.
591 // If this is the case, we need to pre apply the coarse level to the residual(f_out).
592
593 std::string levelCombination = this->parameterList_->sublist("ThyraPreconditioner").sublist("Preconditioner Types").sublist("FROSch").get("Level Combination","Additive");
594 if (!levelCombination.compare("Multiplicative")) {
595 TEUCHOS_TEST_FOR_EXCEPTION(true, std::logic_error, "Multiplicative Level Combination is not supported for NOX.");
596// ParameterListPtr_Type solverPList = this->getLinearSolverBuilder()->getNonconstParameterList();
597//
598// solverPList->sublist("Preconditioner Types").sublist("FROSch").set("Only apply coarse",true);
599//
600// Teuchos::RCP<const Thyra::LinearOpBase<SC> > thyra_linOp = this->getPreconditionerConst()->getThyraPrecConst()->getUnspecifiedPrecOp();
601//
602// f_out->describe(*out,Teuchos::VERB_EXTREME);
603// vecThyraNonConst->describe(*out,Teuchos::VERB_EXTREME);
604// Thyra::apply( *thyra_linOp, Thyra::NOTRANS, *f_out, vecThyraNonConst.ptr() );
605// solverPList->sublist("Preconditioner Types").sublist("FROSch").set("Only apply coarse",false);
606 }
607
608 }
609 }
610}
618#ifdef FEDD_HAVE_TEKO
619template<class SC,class LO,class GO,class NO>
620void NavierStokes<SC,LO,GO,NO>::evalModelImplBlock(const Thyra::ModelEvaluatorBase::InArgs<SC> &inArgs,
621 const Thyra::ModelEvaluatorBase::OutArgs<SC> &outArgs ) const
622{
623
624
625 using Teuchos::RCP;
626 using Teuchos::rcp;
627 using Teuchos::rcp_dynamic_cast;
628 using Teuchos::rcp_const_cast;
629 using Teuchos::ArrayView;
630 using Teuchos::Array;
631
632 RCP<Teuchos::FancyOStream> fancy = Teuchos::fancyOStream(Teuchos::rcpFromRef(std::cout));
633 TEUCHOS_TEST_FOR_EXCEPTION( inArgs.get_x().is_null(), std::logic_error, "inArgs.get_x() is null.");
634
635 RCP< const Thyra::VectorBase< SC > > vecThyra = inArgs.get_x();
636 RCP<Teuchos::FancyOStream> out = Teuchos::VerboseObjectBase::getDefaultOStream();
637
638 RCP< Thyra::VectorBase< SC > > vecThyraNonConst = rcp_const_cast<Thyra::VectorBase< SC > >(vecThyra);
639
640 RCP< Thyra::ProductVectorBase< SC > > vecThyraBlock = rcp_dynamic_cast<Thyra::ProductVectorBase< SC > > (vecThyraNonConst);
641
642 this->solution_->getBlockNonConst(0)->fromThyraMultiVector( vecThyraBlock->getNonconstVectorBlock(0) );
643 this->solution_->getBlockNonConst(1)->fromThyraMultiVector( vecThyraBlock->getNonconstVectorBlock(1) );
644
645 const RCP<Thyra::MultiVectorBase<SC> > f_out = outArgs.get_f();
646 const RCP<Thyra::LinearOpBase<SC> > W_out = outArgs.get_W_op();
647 const RCP<Thyra::PreconditionerBase<SC> > W_prec_out = outArgs.get_W_prec();
648
649 typedef Thyra::TpetraOperatorVectorExtraction<SC,LO,GO,NO> tpetra_extract;
650 typedef Tpetra::CrsMatrix<SC,LO,GO,NO> TpetraMatrix_Type;
651 typedef RCP<TpetraMatrix_Type> TpetraMatrixPtr_Type;
652 typedef RCP<const TpetraMatrix_Type> TpetraMatrixConstPtr_Type;
653
654 const bool fill_f = nonnull(f_out);
655 const bool fill_W = nonnull(W_out);
656 const bool fill_W_prec = nonnull(W_prec_out);
657
658 if ( fill_f || fill_W || fill_W_prec ) {
659
660 // ****************
661 // Get the underlying xpetra objects
662 // ****************
663 if (fill_f) {
664
665 this->calculateNonLinResidualVec("standard");
666
667 Teko::MultiVector f0;
668 Teko::MultiVector f1;
669 f0 = this->getResidualVector()->getBlockNonConst(0)->getThyraMultiVector();
670 f1 = this->getResidualVector()->getBlockNonConst(1)->getThyraMultiVector();
671
672 std::vector<Teko::MultiVector> f_vec; f_vec.push_back(f0); f_vec.push_back(f1);
673
674 Teko::MultiVector f = Teko::buildBlockedMultiVector(f_vec);
675
676 f_out->assign(*f);
677 }
678
679 TpetraMatrixPtr_Type W;
680 if (fill_W) {
681
682 typedef Tpetra::CrsMatrix<SC,LO,GO,NO> TpetraCrsMatrix;
683
684 this->reAssemble("Newton");
685
686 this->setBoundariesSystem();
687
688 RCP<ThyraBlockOp_Type> W_blocks = rcp_dynamic_cast<ThyraBlockOp_Type>(W_out);
689 RCP<const ThyraOp_Type> W_block00 = W_blocks->getBlock(0,0);
690 RCP<ThyraOp_Type> W_block00NonConst = rcp_const_cast<ThyraOp_Type>( W_block00 );
691 RCP<TpetraOp_Type> W_tpetra = tpetra_extract::getTpetraOperator( W_block00NonConst );
692
693 RCP<TpetraMatrix_Type> W_tpetraMat = Teuchos::rcp_dynamic_cast<TpetraMatrix_Type>(W_tpetra);
694
695 TpetraMatrixConstPtr_Type W_matrixTpetra = this->getSystem()->getBlock(0,0)->getTpetraMatrix();
696 TpetraMatrixPtr_Type W_matrixTpetraNonConst = rcp_const_cast<TpetraMatrix_Type>(W_matrixTpetra);
697 RCP<TpetraMatrix_Type> tpetraMatTpetra = W_matrixTpetraNonConst;
698
699 W_tpetraMat->resumeFill();
700
701 for (auto i=0; i<tpetraMatTpetra->getMap()->getLocalNumElements(); i++) {
702 typename Tpetra::CrsMatrix<SC,LO,GO,NO>::local_inds_host_view_type indices; //ArrayView< const LO > indices
703 typename Tpetra::CrsMatrix<SC,LO,GO,NO>::values_host_view_type values;
704 tpetraMatTpetra->getLocalRowView( i, indices, values);
705 W_tpetraMat->replaceLocalValues( i, indices, values);
706 }
707 W_tpetraMat->fillComplete();
708
709 }
710
711 if (fill_W_prec) {
712 if (stokesTekoPrecUsed_){
713 this->setupPreconditioner( "Teko" );
714 }
715 else
716 stokesTekoPrecUsed_ = true;
717
718 // ch 26.04.19: After each setup of the preconditioner we check if we use a two-level precondtioner with multiplicative combination between the levels.
719 // If this is the case, we need to pre apply the coarse level to the residual(f_out).
720
721 ParameterListPtr_Type tmpSubList = sublist( sublist( sublist( sublist( this->parameterList_, "Teko Parameters" ) , "Preconditioner Types" ) , "Teko" ) , "Inverse Factory Library" );
722
723 std::string levelCombination1 = tmpSubList->sublist( "FROSch-Velocity" ).get("Level Combination","Additive");
724 std::string levelCombination2 = tmpSubList->sublist( "FROSch-Pressure" ).get("Level Combination","Additive");
725
726 if ( !levelCombination1.compare("Multiplicative") || !levelCombination2.compare("Multiplicative") ) {
727
728 TEUCHOS_TEST_FOR_EXCEPTION(true, std::logic_error, "Multiplicative Level Combination is not supported for NOX.");
729 ParameterListPtr_Type solverPList = this->getLinearSolverBuilder()->getNonconstParameterList();
730
731// pListThyraSolver->sublist("Preconditioner Types").sublist("FROSch").set("Only apply coarse",true);
732//
733// Teuchos::RCP<const Thyra::LinearOpBase<SC> > thyra_linOp = this->getPreconditioner()->getThyraPrec()->getUnspecifiedPrecOp();
734// Thyra::apply( *thyra_linOp, Thyra::NOTRANS, *thyraB, thyraX.ptr() );
735// pListThyraSolver->sublist("Preconditioner Types").sublist("FROSch").set("Only apply coarse",false);
736
737
738 }
739 }
740 }
741}
742#endif
743
744template<class SC,class LO,class GO,class NO>
745void NavierStokes<SC,LO,GO,NO>::calculateNonLinResidualVec(std::string type, double time) const{
746 this->reAssemble("FixedPoint");
747
748 // We need to account for different parameters of time discretizations here
749 // This is ok for bdf with 1.0 scaling of the system. Would be wrong for Crank-Nicolson - might be ok now for CN
750 if (this->coeff_.size() == 0)
751 this->system_->apply( *this->solution_, *this->residualVec_ );
752 else
753 this->system_->apply( *this->solution_, *this->residualVec_, this->coeff_ );
754
755 if (!type.compare("standard")){
756 this->residualVec_->update(-1.,*this->rhs_,1.);
757// if ( !this->sourceTerm_.is_null() )
758// this->residualVec_->update(-1.,*this->sourceTerm_,1.);
759 // this might be set again by the TimeProblem after addition of M*u
760 this->bcFactory_->setVectorMinusBC( this->residualVec_, this->solution_, time );
761
762 }
763 else if(!type.compare("reverse")){
764 this->residualVec_->update(1.,*this->rhs_,-1.); // this = -1*this + 1*rhs
765// if ( !this->sourceTerm_.is_null() )
766// this->residualVec_->update(1.,*this->sourceTerm_,1.);
767 // this might be set again by the TimeProblem after addition of M*u
768 this->bcFactory_->setBCMinusVector( this->residualVec_, this->solution_, time );
769 }
770
771}
772
773template<class SC,class LO,class GO,class NO>
774void NavierStokes<SC,LO,GO,NO>::calculateNonLinResidualVecWithMeshVelo(std::string type, double time, MultiVectorPtr_Type u_minus_w, MatrixPtr_Type P) const{
775
776
777 this->reAssembleFSI( "FixedPoint", u_minus_w, P );
778
779 // We need to account for different parameters of time discretizations here
780 // This is ok for bdf with 1.0 scaling of the system. Would be wrong for Crank-Nicolson
781
782 this->system_->apply( *this->solution_, *this->residualVec_ );
783// this->residualVec_->getBlock(0)->writeMM("Ax.mm");
784// this->rhs_->getBlock(0)->writeMM("nsRHS.mm");
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// this->residualVec_->getBlock(0)->writeMM("b_Ax.mm");
800
801}
802
803
804template<class SC,class LO,class GO,class NO>
805Teuchos::RCP<Thyra::LinearOpBase<SC> > NavierStokes<SC,LO,GO,NO>::create_W_op() const
806{
807 std::string type = this->parameterList_->sublist("General").get("Preconditioner Method","Monolithic");
808 if ( !type.compare("Monolithic"))
809 return create_W_op_Monolithic( );
810 else if ( !type.compare("Teko")){
811#ifdef FEDD_HAVE_TEKO
812 return create_W_op_Block( );
813#else
814 TEUCHOS_TEST_FOR_EXCEPTION( true, std::logic_error, "Teko not found! Build Trilinos with Teko.");
815#endif
816 }
817 else
818 TEUCHOS_TEST_FOR_EXCEPTION( true, std::logic_error, "Unkown preconditioner/solver type.");
819}
820
821template<class SC,class LO,class GO,class NO>
822Teuchos::RCP<Thyra::LinearOpBase<SC> > NavierStokes<SC,LO,GO,NO>::create_W_op_Monolithic() const
823{
824 Teuchos::RCP<const Thyra::LinearOpBase<SC> > W_opConst = this->system_->getThyraLinOp();
825 Teuchos::RCP<Thyra::LinearOpBase<SC> > W_op = Teuchos::rcp_const_cast<Thyra::LinearOpBase<SC> >(W_opConst);
826 return W_op;
827}
828
829#ifdef FEDD_HAVE_TEKO
830template<class SC,class LO,class GO,class NO>
831Teuchos::RCP<Thyra::LinearOpBase<SC> > NavierStokes<SC,LO,GO,NO>::create_W_op_Block() const
832{
833
834 Teko::LinearOp thyraF = this->system_->getBlock(0,0)->getThyraLinOp();
835 Teko::LinearOp thyraBT = this->system_->getBlock(0,1)->getThyraLinOp();
836 Teko::LinearOp thyraB = this->system_->getBlock(1,0)->getThyraLinOp();
837
838 if (!this->system_->blockExists(1,1)){
839 MatrixPtr_Type dummy = Teuchos::rcp( new Matrix_Type( this->system_->getBlock(1,0)->getMap(), 1 ) );
840 dummy->fillComplete();
841 this->system_->addBlock( dummy, 1, 1 );
842 }
843
844 Teko::LinearOp thyraC = this->system_->getBlock(1,1)->getThyraLinOp();
845
846 Teuchos::RCP<const Thyra::LinearOpBase<SC> > W_opConst = Thyra::block2x2(thyraF,thyraBT,thyraB,thyraC);
847 Teuchos::RCP<Thyra::LinearOpBase<SC> > W_op = Teuchos::rcp_const_cast<Thyra::LinearOpBase<SC> >(W_opConst);
848 return W_op;
849}
850#endif
851
852template<class SC,class LO,class GO,class NO>
853Teuchos::RCP<Thyra::PreconditionerBase<SC> > NavierStokes<SC,LO,GO,NO>::create_W_prec() const
854{
855 this->initializeSolverBuilder();
856
857 std::string type = this->parameterList_->sublist("General").get("Preconditioner Method","Monolithic");
858 this->setBoundariesSystem();
859
860 if (!type.compare("Teko")) { //
861 this->setupPreconditioner( type );
862 stokesTekoPrecUsed_ = false;
863 }
864 else{
865 this->setupPreconditioner( type ); // initializePreconditioner( type );
866 }
867
868
869 Teuchos::RCP<const Thyra::PreconditionerBase<SC> > thyraPrec = this->getPreconditionerConst()->getThyraPrecConst();
870 Teuchos::RCP<Thyra::PreconditionerBase<SC> > thyraPrecNonConst = Teuchos::rcp_const_cast<Thyra::PreconditionerBase<SC> >(thyraPrec);
871
872 return thyraPrecNonConst;
873
874}
875}
876
877#endif
virtual void calculateNonLinResidualVec(std::string type="standard", double time=0.) const
Block Approach for Nonlinear Solver NOX. Input. Includes calculation of the residual vector and updat...
Definition NavierStokes_def.hpp:745
Definition NonLinearProblem_decl.hpp:24
Adaptive Mesh Refinement.
Definition AdaptiveMeshRefinement.cpp:5