Finite Element Domain Decomposition Library
FEDDLib
Loading...
Searching...
No Matches
FSI_def.hpp
1#ifndef FSI_def_hpp
2#define FSI_def_hpp
3#include "FSI_decl.hpp"
4
5double OneFunc(double* x, int* parameter)
6{
7 return 1.0;
8}
9
10void drag2D(double* x, double* res, double t, const double* parameters)
11{
12 res[0] = 1.;
13 res[1] = 0.;
14
15 return;
16}
17
18void drag3D(double* x, double* res, double t, const double* parameters)
19{
20 res[0] = 1.;
21 res[1] = 0.;
22 res[2] = 0.;
23
24 return;
25}
26
27void lift2D(double* x, double* res, double t, const double* parameters)
28{
29 res[0] = 0.;
30 res[1] = 1.;
31
32 return;
33}
34
35void lift3D(double* x, double* res, double t, const double* parameters)
36{
37 res[0] = 0.;
38 res[1] = 1.;
39 res[2] = 0.;
40
41 return;
42}
43
44namespace FEDD {
45// Funktionen fuer die rechte Seite der Struktur/ Fluid/ Geometrie sind im jeweiligen Problem
46
47template<class SC,class LO,class GO,class NO>
48FSI<SC,LO,GO,NO>::FSI(const DomainConstPtr_Type &domainVelocity, std::string FETypeVelocity,
49 const DomainConstPtr_Type &domainPressure, std::string FETypePressure,
50 const DomainConstPtr_Type &domainStructure, std::string FETypeStructure,
51 const DomainConstPtr_Type &domainInterface, std::string FETypeInterface,
52 const DomainConstPtr_Type &domainGeometry, std::string FETypeGeometry,
53 ParameterListPtr_Type parameterListFluid, ParameterListPtr_Type parameterListStructure,
54 ParameterListPtr_Type parameterListFSI, ParameterListPtr_Type parameterListGeometry,
55 Teuchos::RCP<SmallMatrix<int> > &defTS):
56NonLinearProblem<SC,LO,GO,NO>( parameterListFSI, domainVelocity->getComm() ),
57// hasSourceTerm = drittes Arguement. assembleSourceTerm() fuer NS nicht programmiert.
58// Deswegen hier erstmal false (default Parameter).
59// Fuer Struktur hingegen ist default Parameter true, da programmiert.
60P_(),
61problemFluid_(),
62problemStructure_(),
63problemStructureNonLin_(),
64problemGeometry_(),
65meshDisplacementOld_rep_(),
66meshDisplacementNew_rep_(),
67u_rep_(),
68w_rep_(),
69u_minus_w_rep_(),
70p_rep_(),
71defTS_(defTS),
72timeSteppingTool_(),
73materialModel_( parameterListStructure->sublist("Parameter").get("Material model","linear") ),
74valuesForExport_(0),
75exporterTxtDrag_(),
76exporterGeo_()
77{
78 this->nonLinearTolerance_ = this->parameterList_->sublist("Parameter").get("relNonLinTol",1.0e-6);
79 geometryExplicit_ = this->parameterList_->sublist("Parameter").get("Geometry Explicit",true);
80
81 this->initNOXParameters();
82 counterP = 0;
83
84 std::string linearization = parameterListFSI->sublist("General").get("Linearization","FixedPoint");
85
86 TEUCHOS_TEST_FOR_EXCEPTION( !(linearization == "Newton" || linearization == "NOX") && materialModel_ != "linear", std::runtime_error, "Nonlinear material models can only be used with Newton's method or FixedPoint (nonlinear material Jacobian will still be used).");
87
88 this->addVariable( domainVelocity, FETypeVelocity, "u_f", domainVelocity->getDimension() ); // Fluid-Geschw.
89 this->addVariable( domainPressure, FETypePressure, "p", 1); // Fluid-Druck
90 this->addVariable( domainStructure, FETypeStructure, "d_s", domainStructure->getDimension() ); // Struktur
91 this->addVariable( domainInterface, FETypeInterface, "lambda", domainInterface->getDimension() ); // Interface
92 this->addVariable( domainGeometry, FETypeGeometry, "d_f", domainGeometry->getDimension() ); // Geometrie
93 this->dim_ = this->getDomain(0)->getDimension();
94
95 problemFluid_ = Teuchos::rcp( new FluidProblem_Type( domainVelocity, FETypeVelocity, domainPressure, FETypePressure, parameterListFluid ) );
96 problemFluid_->initializeProblem();
97
98 if (materialModel_=="linear"){
99 problemStructure_ = Teuchos::rcp( new StructureProblem_Type( domainStructure, FETypeStructure, parameterListStructure ) );
100 problemStructure_->initializeProblem();
101 }
102 else{
103 problemStructureNonLin_ = Teuchos::rcp( new StructureNonLinProblem_Type( domainStructure, FETypeStructure, parameterListStructure) );
104 problemStructureNonLin_->initializeProblem();
105 }
106
107 problemGeometry_ = Teuchos::rcp( new GeometryProblem_Type( domainGeometry, FETypeGeometry, parameterListGeometry ) );
108 problemGeometry_->initializeProblem();
109 //We initialize the subproblems. In the main routine, we need to call initializeFSI(). There, we first initialize the vectors of the FSI problem and then we set the pointers of the subproblems to the vectors of the full monolithic FSI system. This way all values are only saved once in the subproblems and can be used by the monolithic FSI system.
110
111 meshDisplacementNew_rep_ = Teuchos::rcp( new MultiVector_Type( this->getDomain(4)->getMapVecFieldRepeated() ) );
112 meshDisplacementOld_rep_ = Teuchos::rcp( new MultiVector_Type( this->getDomain(4)->getMapVecFieldRepeated() ) );
113 u_rep_ = Teuchos::rcp( new MultiVector_Type( this->getDomain(0)->getMapVecFieldRepeated() ) );
114 w_rep_ = Teuchos::rcp( new MultiVector_Type( this->getDomain(0)->getMapVecFieldRepeated() ) );
115 u_minus_w_rep_ = Teuchos::rcp( new MultiVector_Type( this->getDomain(0)->getMapVecFieldRepeated() ) );
116
117 // Exporting benchmark values
118 if ( parameterListFSI->sublist("General").get("Export Extra Data",false) ){
119 if (this->dim_==2)
120 findDisplacementTurek2DBenchmark();
121 else if (this->dim_==3)
122 findDisplacementRichter3DBenchmark();
123 }
124 if ( parameterListFSI->sublist("General").get("Export drag and lift",false) ){
125 exporterTxtDrag_ = Teuchos::rcp(new ExporterTxt () );
126 exporterTxtDrag_->setup( "drag_force", this->comm_ );
127 exporterTxtLift_ = Teuchos::rcp(new ExporterTxt () );
128 exporterTxtLift_->setup( "lift_force", this->comm_ );
129 }
130 p_rep_ = Teuchos::rcp( new MultiVector_Type( this->getDomain(1)->getMapRepeated() ) );
131
132}
133
134template<class SC,class LO,class GO,class NO>
135void FSI<SC,LO,GO,NO>::findDisplacementTurek2DBenchmark(){
136 valuesForExport_.resize(1);
137 vec_dbl_Type x = {0.6,0.2};
138 //we save the local index as a double
139 valuesForExport_[0] = this->getDomain(2)->findInPointsUnique( x );
140}
141
142template<class SC,class LO,class GO,class NO>
143void FSI<SC,LO,GO,NO>::findDisplacementRichter3DBenchmark(){
144 valuesForExport_.resize(1);
145 vec_dbl_Type x = {0.45,0.15,0.15};
146 //we save the local index as a double
147 valuesForExport_[0] = this->getDomain(2)->findInPointsUnique( x );
148}
149
150template<class SC,class LO,class GO,class NO>
151FSI<SC,LO,GO,NO>::~FSI()
152{
153 if (!exporterGeo_.is_null()) {
154 exporterGeo_->closeExporter();
155 }
156}
157
158template<class SC,class LO,class GO,class NO>
159void FSI<SC,LO,GO,NO>::info()
160{
161 this->infoProblem();
162 this->infoNonlinProblem();
163}
164
165// Alle linearen Probleme
166template<class SC,class LO,class GO,class NO>
167void FSI<SC,LO,GO,NO>::assemble( std::string type ) const
168{
169 if (type == "") {
170 if (this->verbose_)
171 {
172 std::cout << "-- Assembly FSI ... " << std::endl;
173 }
174
175 // P_.reset(new Matrix_Type( this->getDomain(0)->getMapVecFieldUnique(), 10 ) );
176
177 this->problemFluid_->assemble();
178
179 // steady rhs wird hier assembliert.
180 // rhsFunc auf 0 (=x) und 0 (=y) abaendern bei LinElas!
181 if (materialModel_=="linear")
182 this->problemStructure_->assemble();
183 else
184 this->problemStructureNonLin_->assemble();
185
186 this->problemGeometry_->assemble();
187
188 if ( geometryExplicit_ && this->parameterList_->sublist("Exporter").get("Export GE geometry solution",false)){
189 exporterGeo_ = Teuchos::rcp(new Exporter_Type());
190
191 DomainConstPtr_Type dom = this->getDomain(4);
192
193 int exportEveryXTimesteps = this->parameterList_->sublist("Exporter").get( "Export every X timesteps", 1 );
194 std::string suffix = this->parameterList_->sublist("Exporter").get("Geometry Suffix", "" );
195 std::string varName = "d_f" + suffix;
196
197 MeshPtr_Type meshNonConst = Teuchos::rcp_const_cast<Mesh_Type>( dom->getMesh() );
198 exporterGeo_->setup(varName, meshNonConst, dom->getFEType(), exportEveryXTimesteps, this->parameterList_);
199
200 MultiVectorConstPtr_Type exportVector = this->problemGeometry_->getSolution()->getBlock(0);
201
202 exporterGeo_->addVariable( exportVector, varName, "Vector", this->dim_, dom->getMapUnique() );
203 }
204
205
206 if (!geometryExplicit_) {
207 // RW fuer die Geometrie-Matrix H setzen, weil wenn wir das spaeter im FSI-System
208 // machen, dann wird aufgrund der RW auf dem Interface auch der Kopplungsblock
209 // zur Struktur C4 ausgenullt, was wir nicht wollen.
210 this->problemGeometry_->setBoundariesSystem(); // RW im System setzen (mit den Flags von oben)
211 this->problemGeometry_->getRhs()->putScalar(0.0);
212 }
213
214 // ###########################
215 // Kopplungsbloecke
216 // ###########################
217 // ACHTUNG: Anders als im Matlab-Code!!!
218 // Matlab: C1_T hat so viele Zeilen wie das komplette Fluid-System (u + p)
219 // FEDDLib: C1_T hat so viele Zeilen wie das Geschwindigkeitssystem (nur u)
220 // Bemerkung: Verteilung der Zeilen wird angegeben (Range-Map).
221 // Interface wird von der Fluid-Seite aus gehalten, deswegen auch
222 // getDomain(0) bei C2, obwohl es in der Struktur-Spalte ist.
223 MatrixPtr_Type C1_T(new Matrix_Type( this->getDomain(0)->getMapVecFieldUnique(), 1 ) ); // Fluid-Kopplung
224 MatrixPtr_Type C1(new Matrix_Type( this->getDomain(0)->getInterfaceMapVecFieldUnique(), 1 ) ); // Fluid-Spalte
225 MatrixPtr_Type C2(new Matrix_Type( this->getDomain(0)->getInterfaceMapVecFieldUnique(), 1 ) ); // Struktur-Spalte
226 MatrixPtr_Type C3_T(new Matrix_Type( this->getDomain(2)->getMapVecFieldUnique(), 1 ) ); // Struktur-Kopplung
227
228
229 // Nur vorhanden, falls geometrisch implizit
230 MatrixPtr_Type C4(new Matrix_Type( this->getDomain(4)->getMapVecFieldUnique(), 1 ) ); // Geometrie (=Fluid)
231
232 // Fluid-Bloecke
233 this->feFactory_->assemblyFSICoupling(this->dim_, this->domain_FEType_vec_.at(0), C1, C1_T, 0, 0,
234 this->getDomain(0)->getInterfaceMapVecFieldUnique(), this->getDomain(0)->getMapVecFieldUnique(), true);
235
236 // Struktur-Bloecke
237 // ACHTUNG: Die Interface-Variable \lambda wird eindeutig von der Fluid-Seite gehalten.
238 // Deswegen auch getDomain(0) fuer die Spalten der Kopplungsbloecke.
239 this->feFactory_->assemblyFSICoupling(this->dim_, this->domain_FEType_vec_.at(2), C2, C3_T, 0, 2,
240 this->getDomain(0)->getInterfaceMapVecFieldUnique(), this->getDomain(2)->getMapVecFieldUnique(), true);
241
242
243 // Falls geometrisch implizit
244 if(!geometryExplicit_)
245 {
246 // TODO: Wegen IndicesGlobalMatched_ vlt .sicherheitshalber FEloc = 0 nehmen.
247 // TODO: Check C4
248 this->feFactory_->assemblyGeometryCoupling(this->dim_, this->domain_FEType_vec_.at(4), C4, 4,
249 this->getDomain(0)->getGlobalInterfaceMapUnique(),
250 this->getDomain(2)->getMapVecFieldUnique(),
251 this->getDomain(4)->getMapVecFieldUnique(), true);
252 }
253
254 MatrixPtr_Type dummyC;
255 // we need to set the dummy coupling conditions for monolithic preconditioning with FROSch
256 if ( !this->getDomain(0)->getGlobalInterfaceMapVecFieldPartial().is_null() ) {
257 dummyC.reset(new Matrix_Type( this->getDomain(0)->getInterfaceMapVecFieldUnique(), 1 ) );
258 this->feFactory_->assemblyDummyCoupling(this->dim_, this->domain_FEType_vec_.at(0), dummyC, 0,true);
259 }
260
261 // ###########################
262 // Korrekte Skalierung der entsprechenden Bloecke
263 // ###########################
264 double dt = this->parameterList_->sublist("Timestepping Parameter").get("dt",0.02);
265
266 C2->resumeFill();
267 C3_T->resumeFill();
268
269 C2->scale( -(1.0/dt) ); // this will be used in a first order approximation of the solid velocity
270 C3_T->scale( -1.0 );
271
272 // ACHTUNG: Die Interface-Variable \lambda wird eindeutig von der Fluid-Seite gehalten.
273 // Deswegen auch getDomain(0) fuer die Spalten von C3_T.
274 C2->fillComplete(this->getDomain(2)->getMapVecFieldUnique(), this->getDomain(0)->getInterfaceMapVecFieldUnique());
275 C3_T->fillComplete(this->getDomain(0)->getInterfaceMapVecFieldUnique(), this->getDomain(2)->getMapVecFieldUnique());
276
277 // C2 in Membervariable C2_ speichern, fuer rechte Seite im Interface-Block:
278 // C2*d_s^n
279 C2_ = C2;
280
281 if(!geometryExplicit_)
282 {
283 C4->resumeFill();
284 C4->scale(-1.0);
285 // Domain = Spalten = Struktur; Range = Zeilen = Geometrie
286 C4->fillComplete(this->getDomain(2)->getMapVecFieldUnique(), this->getDomain(4)->getMapVecFieldUnique());
287 }
288
289
290
291 // ###########################
292 // Bloecke hinzufuegen
293 // ###########################
294 if(geometryExplicit_)
295 this->system_.reset(new BlockMatrix_Type(4));
296 else
297 this->system_.reset(new BlockMatrix_Type(5));
298
299 // Fluid
300 this->system_->addBlock( this->problemFluid_->system_->getBlock(0,0), 0, 0 );
301 this->system_->addBlock( this->problemFluid_->system_->getBlock(0,1), 0, 1 );
302 this->system_->addBlock( this->problemFluid_->system_->getBlock(1,0), 1, 0 );
303 if (this->getDomain(0)->getFEType()=="P1")
304 this->system_->addBlock( this->problemFluid_->system_->getBlock(1,1), 1, 1 );
305
306 // Struktur
307 if (materialModel_=="linear")
308 this->system_->addBlock( this->problemStructure_->system_->getBlock(0,0), 2, 2 );
309 else
310 this->system_->addBlock( this->problemStructureNonLin_->system_->getBlock(0,0), 2, 2 );
311 // Kopplung
312 this->system_->addBlock( C1_T, 0, 3 );
313 this->system_->addBlock( C3_T, 2, 3 );
314 this->system_->addBlock( C1, 3, 0 );
315 this->system_->addBlock( C2, 3, 2 );
316
317 if (!dummyC.is_null())
318 this->system_->addBlock( dummyC, 3, 3 );
319
320 if(!geometryExplicit_)
321 {
322 // Geometrie
323 this->system_->addBlock( this->problemGeometry_->system_->getBlock(0,0), 4, 4 );
324 // Kopplung
325 this->system_->addBlock( C4, 4, 2 );
326 }
327
328 // Sollte (bzw. muss) erst aufgerufen werden, wenn alle Bloecke aus assemble()
329 // in das ganze System hineingeschrieben worden ist. Ansonsten findet
330 // blockExists() keinen Block
331 // this->initializeVectors();
332 // this->initializeVectorsNonLinear();
333 //NOX
334
335 // We set the vector from the partial problems
336 this->setFromPartialVectorsInit();
337
338 // Fuer die Zeitprobleme
339 timeSteppingTool_ = Teuchos::rcp(new TimeSteppingTools(sublist(this->parameterList_,"Timestepping Parameter") , this->comm_));
340 ParameterListPtr_Type plStructure;
341 if (materialModel_=="linear")
342 plStructure = this->problemStructure_->getParameterList();
343 else
344 plStructure = this->problemStructureNonLin_->getParameterList();
345
346 setupSubTimeProblems(this->problemFluid_->getParameterList(), plStructure);
347
348 if (this->verbose_)
349 {
350 std::cout << "done -- " << std::endl;
351 }
352 }
353 else
354 reAssemble(type);
355}
356
357
358template<class SC,class LO,class GO,class NO>
359void FSI<SC,LO,GO,NO>::reAssemble(std::string type) const
360{
361
362 double dt = this->parameterList_->sublist("Timestepping Parameter").get("dt",0.02);
363
364 // Fluid-Dichte
365 double density = this->problemFluid_->getParameterList()->sublist("Parameter").get("Density",1.);
366 double viscosity = this->problemFluid_->getParameterList()->sublist("Parameter").get("Viscosity",1.);
367
368 if(type == "UpdateMeshDisplacement")
369 {
370 if(this->verbose_)
371 std::cout << "-- Reassembly (UpdateMeshDisplacement)" << '\n';
372
373 // Da dieser Abschnitt zu Beginn der neuen Zeititeration aufgerufen wird, muss
374 // auch die alte Gitterverschiebung durch die neue Loesung aktualisiert werden.
375 updateMeshDisplacement();
376 return;
377 }
378
379 if(type == "SolveGeometryProblem")
380 {
381 if(this->verbose_)
382 std::cout << "-- Reassembly (SolveGeometryProblem)" << '\n';
383
384 solveGeometryProblem();
385 return;
386 }
387
388 if(type == "UpdateTime")
389 {
390 if(this->verbose_)
391 std::cout << "-- Reassembly (UpdateTime)" << '\n';
392
393 updateTime();
394 return;
395 }
396
397 if(type == "UpdateFluidInTime")
398 {
399 if(this->verbose_)
400 std::cout << "-- Reassembly (UpdateFluidInTime)" << '\n';
401
402 updateFluidInTime();
403 return;
404 }
405
406 if(type == "MoveMesh")
407 {
408 if(this->verbose_)
409 std::cout << "-- Reassembly (MoveMesh)" << '\n';
410
411 moveMesh();
412 return;
413 }
414
415 if(type == "AddInterfaceBlockRHS")
416 {
417 if(this->verbose_)
418 std::cout << "-- Reassembly (AddInterfaceBlockRHS)" << '\n';
419
420 addInterfaceBlockRHS();
421 return;
422 }
423
424 if(type == "ComputeFluidRHSInTime")
425 {
426 if(this->verbose_)
427 std::cout << "-- Reassembly (ComputeFluidRHSInTime)" << '\n';
428
429 computeFluidRHSInTime( );
430 return;
431 }
432 if(type == "ComputeSolidRHSInTime")
433 {
434 if(this->verbose_)
435 std::cout << "-- Reassembly (ComputeSolidRHSInTime)" << '\n';
436
437 computeSolidRHSInTime( );
438 return;
439 }
440
441
442 // ###############
443 // Berechne die Gittergeschwindigkeit w und FSI-Konvektion-Anteil (u-w)
444 // ###############
445 MultiVectorConstPtr_Type fluidSolution = this->solution_->getBlock(0);
446 u_rep_->importFromVector(fluidSolution, true);
447 u_minus_w_rep_->importFromVector(fluidSolution, true); // u_minus_w_rep_ = *u_rep_;
448
449 MultiVectorConstPtr_Type geometrySolution;
450 if(geometryExplicit_)
451 {
452 geometrySolution = this->problemGeometry_->getSolution()->getBlock(0);
453 }
454 else
455 {
456 geometrySolution = this->solution_->getBlock(4);
457 }
458 meshDisplacementNew_rep_->importFromVector(geometrySolution, true);
459
460 *w_rep_ = *meshDisplacementNew_rep_;
461 w_rep_->update(-1.0, *meshDisplacementOld_rep_, 1.0);
462 w_rep_->scale( 1.0/dt );
463
464 u_minus_w_rep_->update( -1.0, *w_rep_, 1.0 );
465
466 // Selbiges fuer den Druck
467 MultiVectorConstPtr_Type pressureSolution = this->solution_->getBlock(1);
468 p_rep_->importFromVector(pressureSolution, true);
469
470
471 // ###############
472 // Neu-Assemblierung zu Beginn der neuen Zeititeration im Falle von geometrisch explizit,
473 // da das Geometrieproblem zu Beginn der neuen Zeititeration geloest wird und sich somit
474 // das Gitter danach bewegt.
475 // ###############
476 if(type == "ForTime")
477 {
478 if(this->verbose_)
479 std::cout << "-- Reassembly (ForTime)" << '\n';
480
481 // Do we need ForTime at this point? see DAESolverInTime, is it only needed for extrapolation?
482 if(geometryExplicit_)
483 {
484 // ACHTUNG: Fluid-Loesung wird hier auf Null gesetzt, wegen initializeVectors().
485 // Somit dann auch die problemTimeFluid_ wodurch eine falsche BDF2-RHS entsteht.
486 // Rufe im DAESolverInTime deswegen erneut setPartialSolutions() auf.
487
488
489 this->problemFluid_->assembleConstantMatrices(); // Die Steifikeitsmatrix wird weiter unten erst genutzt
490
491 // Es ist P = P_
492 P_.reset(new Matrix_Type( this->getDomain(0)->getMapVecFieldUnique(), this->getDomain(0)->getDimension() * this->getDomain(0)->getApproxEntriesPerRow() ) );
493// counterP++;
494// std::string outNameMeshVelo = "meshVelo" + to_string(counterP) + ".mm";
495// w_rep_->writeMM(outNameMeshVelo);
496// Teuchos::ArrayRCP<SC> values = w_rep_->getDataNonConst(0);
497// for (int i=0; i<values.size()/2; i++) {
498// values[2*i] = i;
499// }
500 this->feFactory_->assemblyAdditionalConvection( this->dim_, this->domain_FEType_vec_.at(0), P_, w_rep_, true );
501 P_->resumeFill();
502 P_->scale(density);
503 P_->scale(-1.0);
504// P_->scale(.0);
505 P_->fillComplete( this->getDomain(0)->getMapVecFieldUnique(), this->getDomain(0)->getMapVecFieldUnique());
506// std::string outNameP = "P" + to_string(counterP) + ".mm";
507// std::cout << "write P:"<<std::endl;
508// P_->writeMM( "P.mm" );
509 // Druck und Divergenz hinzufuegen
510 this->system_->addBlock( this->problemFluid_->system_->getBlock(0,1), 0, 1 );
511 this->system_->addBlock( this->problemFluid_->system_->getBlock(1,0), 1, 0 );
512 if (this->problemFluid_->system_->blockExists(1,1))
513 this->system_->addBlock( this->problemFluid_->system_->getBlock(1,1), 1, 1 );
514 }
515
516 return; // Damit wir nicht den ganzen Rest auch noch machen!
517 }
518
519
520 // ###############
521 // Neu-Assemblierung
522 // ###############
523 // Fluid: A+P+N+W
524 MatrixPtr_Type APNW = Teuchos::rcp(new Matrix_Type( this->getDomain(0)->getMapVecFieldUnique(), this->getDomain(0)->getDimension() * this->getDomain(0)->getApproxEntriesPerRow() ) );
525
526 if(geometryExplicit_)
527 {
528
529 if(type == "FixedPoint")
530 {
531 TEUCHOS_TEST_FOR_EXCEPTION(true, std::runtime_error, "should always be called by the residual and never here.");
532 }
533 else if(type == "Newton")
534 {
535 if(this->verbose_){
536 std::cout << "-- Reassembly GE (Newton)" << '\n';
537 std::cout << "-- Reassembly GE (Newton) ... full reassembly" << '\n';
538 }
539
540 problemFluid_->reAssemble( "Newton" );
541
542 if (materialModel_ != "linear")
543 this->problemStructureNonLin_->reAssemble("Newton");
544
545 }
546 }
547 else
548 {
549 if(type == "FixedPoint")
550 {
551 TEUCHOS_TEST_FOR_EXCEPTION(true, std::runtime_error, "should always be called by the residual and never here.");
552 }
553 else if(type == "Newton")
554 {
555 if(this->verbose_){
556 std::cout << "-- Reassembly GI (Newton)" << '\n';
557 std::cout << "-- Reassembly GI (Newton) ... only W" << '\n';
558 }
559
560 problemFluid_->reAssemble( "Newton" );
561
562 // TODO: Shape
563 // domain(0) = domain(4)
564 MatrixPtr_Type shapeVelocity = Teuchos::rcp(new Matrix_Type( this->getDomain(0)->getMapVecFieldUnique(), this->getDomain(0)->getDimension() * this->getDomain(0)->getApproxEntriesPerRow() ) );
565 MatrixPtr_Type shapeDiv = Teuchos::rcp(new Matrix_Type( this->getDomain(1)->getMapUnique(), this->getDomain(1)->getDimension() * this->getDomain(1)->getApproxEntriesPerRow() ) ); // shape fuer div-Nebenbedingung
566
567 this->feFactory_->assemblyShapeDerivativeVelocity(this->dim_, this->domain_FEType_vec_.at(4), this->domain_FEType_vec_.at(1),
568 shapeVelocity, 4, u_rep_, w_rep_, p_rep_, dt, density, viscosity, true);
569 this->feFactory_->assemblyShapeDerivativeDivergence(this->dim_, this->domain_FEType_vec_.at(4), this->domain_FEType_vec_.at(1),
570 shapeDiv, 1, 4, this->getDomain(1)->getMapUnique(), this->getDomain(4)->getMapVecFieldUnique(), u_rep_, true);
571 shapeDiv->resumeFill();
572 shapeDiv->scale(-1.0);
573 shapeDiv->fillComplete(this->getDomain(4)->getMapVecFieldUnique(), this->getDomain(1)->getMapUnique());
574
575 // Shape Reinschreiben
576 this->system_->addBlock(shapeVelocity, 0, 4);
577 this->system_->addBlock(shapeDiv, 1, 4);
578
579 if (materialModel_ != "linear")
580 this->problemStructureNonLin_->reAssemble("Newton");
581
582 }
583 }
584
585 this->system_->addBlock( problemFluid_->getSystem()->getBlock( 0, 0 ), 0, 0 );
586
587 if (materialModel_ != "linear")
588 this->system_->addBlock( this->problemStructureNonLin_->getSystem()->getBlock(0,0), 2, 2 );
589}
590
591template<class SC,class LO,class GO,class NO>
592void FSI<SC,LO,GO,NO>::reAssembleExtrapolation(BlockMultiVectorPtrArray_Type previousSolutions)
593{
594 double dt = this->parameterList_->sublist("Timestepping Parameter").get("dt",0.02);
595 // Fluid-Dichte
596 double density = this->problemFluid_->getParameterList()->sublist("Parameter").get("Density",1.);
597
598 // ###############
599 // w bestimmen
600 // ###############
601 MultiVectorConstPtr_Type geometrySolution;
602 if(geometryExplicit_)
603 {
604 geometrySolution = this->problemGeometry_->getSolution()->getBlock(0);
605 }
606 else
607 {
608 geometrySolution = this->solution_->getBlock(4);
609 }
610 meshDisplacementNew_rep_->importFromVector(geometrySolution, true);
611
612
613 *w_rep_ = *meshDisplacementNew_rep_;
614 // update(): this = alpha*A + beta*this
615 w_rep_->update(-1.0, *meshDisplacementOld_rep_, 1.0);
616 w_rep_->scale(1.0/dt);
617
618
619 // ###############
620 // u extrapolieren
621 // ###############
622 // Beachte: getBlock(0) ist hier der Richtige, da dies der u-Variable in FSI entspricht.
623 if (previousSolutions.size() >= 2)
624 {
625 MultiVectorPtr_Type extrapolatedVector = Teuchos::rcp( new MultiVector_Type( previousSolutions[0]->getBlock(0) ) );
626
627 // Extrapolation fuer BDF2
628 // update(): this = alpha*A + beta*this
629 extrapolatedVector->update( -1., *previousSolutions[1]->getBlock(0), 2. );
630
631 u_rep_->importFromVector(extrapolatedVector, true);
632 }
633 else if(previousSolutions.size() == 1)
634 {
635 MultiVectorConstPtr_Type u = previousSolutions[0]->getBlock(0);
636 u_rep_->importFromVector(u, true);
637 }
638 else if (previousSolutions.size() == 0)
639 {
640 MultiVectorConstPtr_Type u = this->solution_->getBlock(0);
641 u_rep_->importFromVector(u, true);
642 }
643
644 // (u-w)
645 *u_minus_w_rep_ = *u_rep_;
646 // update(): this = alpha*A + beta*this
647 u_minus_w_rep_->update(-1.0, *w_rep_, 1.0);
648
649
650 // ###############
651 // Neu assemblieren
652 // ###############
653
654 MatrixPtr_Type APN = Teuchos::rcp(new Matrix_Type( this->getDomain(0)->getMapVecFieldUnique(), this->getDomain(0)->getDimension() * this->getDomain(0)->getApproxEntriesPerRow() ) );
655
656 MatrixPtr_Type N = Teuchos::rcp(new Matrix_Type( this->getDomain(0)->getMapVecFieldUnique(), this->getDomain(0)->getDimension() * this->getDomain(0)->getApproxEntriesPerRow() ) );
657 this->feFactory_->assemblyAdvectionVecField( this->dim_, this->domain_FEType_vec_.at(0), N, u_minus_w_rep_, true );
658
659 P_.reset(new Matrix_Type( this->getDomain(0)->getMapVecFieldUnique(), this->getDomain(0)->getDimension() * this->getDomain(0)->getApproxEntriesPerRow() ) );
660
661 this->feFactory_->assemblyAdditionalConvection( this->dim_, this->domain_FEType_vec_.at(0), P_, w_rep_, true );
662 P_->resumeFill();
663 P_->scale(density);
664 P_->scale(-1.0);
665 P_->fillComplete( this->getDomain(0)->getMapVecFieldUnique(), this->getDomain(0)->getMapVecFieldUnique());
666
667
668 N->resumeFill();
669 N->scale(density);
670 N->fillComplete( this->getDomain(0)->getMapVecFieldUnique(), this->getDomain(0)->getMapVecFieldUnique());
671
672 this->problemFluid_->A_->addMatrix(1.0, APN, 0.0);
673 P_->addMatrix(1.0, APN, 1.0);
674 N->addMatrix(1.0, APN, 1.0);
675
676 APN->fillComplete( this->getDomain(0)->getMapVecFieldUnique(), this->getDomain(0)->getMapVecFieldUnique() );
677
678 this->system_->addBlock( APN, 0, 0 );
679}
680
681template<class SC,class LO,class GO,class NO>
682void FSI<SC,LO,GO,NO>::calculateNonLinResidualVec(std::string type, double time) const
683{
684
685 MultiVectorConstPtr_Type geometrySolution;
686
687 if(geometryExplicit_)
688 geometrySolution = this->problemGeometry_->getSolution()->getBlock(0);
689 else {
690 moveMesh();
691 geometrySolution = this->solution_->getBlock(4);
692 }
693
694 meshDisplacementNew_rep_->importFromVector(geometrySolution, true);
695
696 MultiVectorConstPtr_Type fluidSolution = this->solution_->getBlock(0);
697 u_rep_->importFromVector(fluidSolution, true);
698 u_minus_w_rep_->importFromVector(fluidSolution, true); // u_minus_w_rep_ = *u_rep_;
699
700 *w_rep_ = *meshDisplacementNew_rep_;
701 w_rep_->update(-1.0, *meshDisplacementOld_rep_, 1.0);
702 double dt = this->parameterList_->sublist("Timestepping Parameter").get("dt",0.02);
703 w_rep_->scale(1.0/dt);
704
705 u_minus_w_rep_->update(-1.0, *w_rep_, 1.0);
706
707 if (!geometryExplicit_) {
708
709 P_.reset(new Matrix_Type( this->getDomain(0)->getMapVecFieldUnique(), this->getDomain(0)->getDimension() * this->getDomain(0)->getApproxEntriesPerRow() ) );
710 double density = this->problemTimeFluid_->getParameterList()->sublist("Parameter").get("Density",1000.e-0);
711
712 this->feFactory_->assemblyAdditionalConvection( this->dim_, this->domain_FEType_vec_.at(0), P_, w_rep_, true );
713 P_->resumeFill();
714 P_->scale(density);
715 P_->scale(-1.0);
716 P_->fillComplete( this->getDomain(0)->getMapVecFieldUnique(), this->getDomain(0)->getMapVecFieldUnique());
717
718 problemFluid_->assembleConstantMatrices();
719
720 this->system_->addBlock( this->problemFluid_->system_->getBlock(0,1), 0, 1 );
721 this->system_->addBlock( this->problemFluid_->system_->getBlock(1,0), 1, 0 );
722 TEUCHOS_TEST_FOR_EXCEPTION(this->problemFluid_->system_->blockExists(1,1) , std::runtime_error, "Stabilization is used. Account for it.");
723 }
724 if ( this->verbose_ )
725 std::cout << "Warning: Wrong consideration of temporal discretization for multi-stage RK methods!" << std::endl;
726
727 this->problemFluid_->calculateNonLinResidualVecWithMeshVelo( "reverse", time, u_minus_w_rep_, P_ );
728 this->system_->addBlock( problemFluid_->getSystem()->getBlock( 0, 0 ), 0, 0 );
729
730 // we need to account for the coupling in the residuals
731 if (materialModel_!="linear"){
732 this->problemStructureNonLin_->calculateNonLinResidualVec( "reverse", time );
733 this->residualVec_->addBlock( this->problemStructureNonLin_->getResidualVector()->getBlockNonConst(0) , 2);
734 // we need to add a possible source term
735 }
736 else{
737 MultiVectorPtr_Type residualSolidFSI =
738 Teuchos::rcp_const_cast<MultiVector_Type>( this->residualVec_->getBlock(2) );
739 this->problemStructure_->getSystem()->getBlock(0,0)->apply( *this->problemStructure_->getSolution()->getBlock(0), *residualSolidFSI, Teuchos::NO_TRANS, -1. ); // y= -Ax + 0*y
740 MultiVectorPtr_Type resSolidNonConst = Teuchos::rcp_const_cast<MultiVector_Type> ( this->residualVec_->getBlock(2) );
741 resSolidNonConst->update(1., *this->problemStructure_->getRhs()->getBlock(0), 1.);
742 // we need to add a possible source term
743 }
744
745 MultiVectorPtr_Type residualFluidVelocityFSI =
746 Teuchos::rcp_const_cast<MultiVector_Type>( this->residualVec_->getBlock(0) );
747 MultiVectorPtr_Type residualSolidFSI =
748 Teuchos::rcp_const_cast<MultiVector_Type>( this->residualVec_->getBlock(2) );
749
750 MultiVectorPtr_Type residualCouplingFSI =
751 Teuchos::rcp_const_cast<MultiVector_Type>( this->residualVec_->getBlock(3) );
752 residualCouplingFSI->update( 1. , *this->rhs_->getBlock(3), 0. ); // change to -1 for standard
753
754 //Now we need to add the coupling blocks
755 this->system_->getBlock(0,3)->apply( *this->solution_->getBlock(3) , *residualFluidVelocityFSI, Teuchos::NO_TRANS, -1., 1. );
756
757 this->system_->getBlock(2,3)->apply( *this->solution_->getBlock(3) , *residualSolidFSI, Teuchos::NO_TRANS, -1., 1. );
758
759 this->system_->getBlock(3,0)->apply( *this->solution_->getBlock(0) , *residualCouplingFSI, Teuchos::NO_TRANS, -1., 1. );
760
761 this->system_->getBlock(3,2)->apply( *this->solution_->getBlock(2) , *residualCouplingFSI, Teuchos::NO_TRANS, -1., 1. );
762
763 if (!geometryExplicit_) {
764
765 MultiVectorPtr_Type residualGeometryFSI =
766 Teuchos::rcp_const_cast<MultiVector_Type>( this->residualVec_->getBlock(4) );
767 residualGeometryFSI->update( 1. , *this->rhs_->getBlock(4), 0. ); // change to -1 for standard
768
769 this->system_->getBlock(4,4)->apply( *this->solution_->getBlock(4) , *residualGeometryFSI, Teuchos::NO_TRANS, -1., 1. );
770
771 this->system_->getBlock(4,2)->apply( *this->solution_->getBlock(2) , *residualGeometryFSI, Teuchos::NO_TRANS, -1., 1. );
772
773 }
774 // might also be called in the sub calculateNonLinResidualVec() methods which where used above
775 if (type == "reverse")
776 this->bcFactory_->setBCMinusVector( this->residualVec_, this->solution_, time );
777 else if (type == "standard"){
778 this->residualVec_->scale(-1.);
779 this->bcFactory_->setVectorMinusBC( this->residualVec_, this->solution_, time );
780 }
781
782
783}
784
785// Muss derzeit nur am Anfang jeder Zeititeration aufgerufen werden, damit
786// problemTimeFluid_ und problemTimeStructure_ die aktuelle Loesung haben.
787// ACHTUNG: Wenn wir irgendwann einmal anfangen reAssemble() auf problemFluid_ und
788// problemStructure_ aufzurufen, dann muessen wir in jeder nichtlinearen Iteration
789// diese setPartialSolutions() aufrufen, damit problemFluid_ und problemStructure_
790// den korrekten nichtlinearen Term ausrechnen koennen.
791// CH: Ist das noch relevant?
792// We need to build FSI so this method is not needed anymore
793template<class SC,class LO,class GO,class NO>
794void FSI<SC,LO,GO,NO>::setFromPartialVectorsInit() const
795{
796
797 //Fluid velocity
798 this->solution_->addBlock( this->problemFluid_->getSolution()->getBlockNonConst(0), 0 );
799 this->residualVec_->addBlock( this->problemFluid_->getResidualVector()->getBlockNonConst(0), 0 );
800 this->residualVec_->addBlock( this->problemFluid_->getResidualVector()->getBlockNonConst(0), 0 );
801 this->rhs_->addBlock( this->problemFluid_->getRhs()->getBlockNonConst(0), 0 );
802 this->sourceTerm_->addBlock( this->problemFluid_->getSourceTerm()->getBlockNonConst(0), 0 );
803
804 //Fluid pressure
805 this->solution_->addBlock( this->problemFluid_->getSolution()->getBlockNonConst(1), 1 );
806 this->residualVec_->addBlock( this->problemFluid_->getResidualVector()->getBlockNonConst(1), 1 );
807 this->rhs_->addBlock( this->problemFluid_->getRhs()->getBlockNonConst(1), 1 );
808 this->previousSolution_->addBlock( this->problemFluid_->getPreviousSolution()->getBlockNonConst(1), 1 );
809 this->sourceTerm_->addBlock( this->problemFluid_->getSourceTerm()->getBlockNonConst(1), 1 );
810
811 if (materialModel_=="linear"){
812 this->solution_->addBlock( this->problemStructure_->getSolution()->getBlockNonConst(0), 2 );
813 // we dont have a residual vector for linear problems
814 this->rhs_->addBlock( this->problemStructure_->getRhs()->getBlockNonConst(0), 2 );
815 this->sourceTerm_->addBlock( this->problemStructure_->getSourceTerm()->getBlockNonConst(0), 2 );
816 }
817 else{
818 this->solution_->addBlock( this->problemStructureNonLin_->getSolution()->getBlockNonConst(0), 2 );
819 this->residualVec_->addBlock( this->problemStructureNonLin_->getResidualVector()->getBlockNonConst(0), 2 );
820 this->rhs_->addBlock( this->problemStructureNonLin_->getRhs()->getBlockNonConst(0), 2 );
821 this->previousSolution_->addBlock( this->problemStructureNonLin_->getPreviousSolution()->getBlockNonConst(0), 2 );
822 this->sourceTerm_->addBlock( this->problemStructureNonLin_->getSourceTerm()->getBlockNonConst(0), 2 );
823 }
824
825 if(!geometryExplicit_){
826 this->solution_->addBlock( this->problemGeometry_->getSolution()->getBlockNonConst(0), 4 );
827 // we dont have a previous solution for linear problems
828 this->rhs_->addBlock( this->problemGeometry_->getRhs()->getBlockNonConst(0), 4 );
829 this->sourceTerm_->addBlock( this->problemGeometry_->getSourceTerm()->getBlockNonConst(0), 4 );
830 }
831}
832
833template<class SC,class LO,class GO,class NO>
834void FSI<SC,LO,GO,NO>::updateMeshDisplacement() const
835{
836
837 *meshDisplacementOld_rep_ = *meshDisplacementNew_rep_;
838
839}
840
841
842template<class SC,class LO,class GO,class NO>
843void FSI<SC,LO,GO,NO>::solveGeometryProblem() const
844{
845 DomainPtr_Type domainFluid = Teuchos::rcp_const_cast<Domain_Type>(this->getDomain(0));
846 DomainPtr_Type domainStruct = Teuchos::rcp_const_cast<Domain_Type>(this->getDomain(2));
847
848 // Hole die dof-Map
849 MapConstPtr_Type interfaceMapFluidVecField = domainFluid->getInterfaceMapVecFieldUnique();
850 MapConstPtr_Type interfaceMapStructureVecField = domainStruct->getInterfaceMapVecFieldUnique();
851
852 MapConstPtr_Type interfaceMapGlobalFluidVecField = domainFluid->getGlobalInterfaceMapVecFieldUnique();
853 MapConstPtr_Type interfaceMapGlobalStructureVecField = domainStruct->getGlobalInterfaceMapVecFieldUnique();
854
855 MeshUnstrPtr_Type meshUnstructuredFluid = Teuchos::rcp_dynamic_cast<MeshUnstr_Type>( domainFluid->getMesh() );
856 vec3D_GO_ptr_Type indicesGlobalMatchedOriginFluid = meshUnstructuredFluid->getMeshInterface()->getIndicesGlobalMatchedOrigin();
857
858 // Strukturloesung holen
859 MultiVectorConstPtr_Type struc_sol_unique = this->solution_->getBlock(2);
860
861 // Extrahiere nun aus der globalen Strukturloesung die Loesung auf dem Interface (in parallel).
862 MultiVectorPtr_Type interfaceSolutionStruct = Teuchos::rcp( new MultiVector_Type( interfaceMapStructureVecField, 1 ) );
863
864 {
865 int flagCounter = 0;
866 Teuchos::ArrayRCP< SC > valuesInterface = interfaceSolutionStruct->getDataNonConst(0); //single MultiVector
867 Teuchos::ArrayRCP< SC > valuesStructure = struc_sol_unique->getDataNonConst(0); //single MultiVector
868
869 for(UN i = 0; i < valuesInterface.size(); i++)
870 {
871 GO interfaceIDGlobal = interfaceMapGlobalStructureVecField->getGlobalElement( i ); // ID (vektorwertig, also dofID) in der Interface-Nummerierung
872// GO nodeID; // nodeID der interfaceID in der Interface-Nummerierung
873// LO localDofNumber; // Ranges from 0 to dofs-1
874// toNodeID(this->dim_, interfaceID, nodeID, localDofNumber); //This function assumes NodeWise ordering.
875//
876// // Ggf. ist die ID auf einer anderen Flag.
877// // Bei nur einer Interface-Flag kommt man nicht hier hinein.
878// while( nodeID > indicesGlobalMatchedOriginFluid->at(flagCounter).at(0).size()-1 )
879// {
880// nodeID = nodeID - indicesGlobalMatchedOriginFluid->at(flagCounter).at(0).size();
881// flagCounter = flagCounter + 1; // hier steht dann die korrekte Flag
882// }
883//
884// // Beachte: at(1) ist Struktur!!!
885// // GlobaleID des Interface-Knotens in der Struktur-Nummerierung
886// GO globalInterfaceIDNode = indicesGlobalMatchedOriginFluid->at(flagCounter).at(1).at(nodeID);
887// GO globalInterfaceIDinStructure; // dofID
888// toDofID(this->dim_, globalInterfaceIDNode, localDofNumber, globalInterfaceIDinStructure);
889
890 // LokaleID auf dem Prozessor vom Interface-Knoten.
891 LO localInterfaceIDinStructure = domainStruct->getMapVecFieldUnique()->getLocalElement(interfaceIDGlobal);
892
893 valuesInterface[i] = valuesStructure[localInterfaceIDinStructure];
894 }
895 }
896
897 MultiVectorPtr_Type interfaceSolutionFluid = Teuchos::rcp( new MultiVector_Type( interfaceMapFluidVecField, 1 ) );
898 interfaceSolutionFluid->importFromVector( interfaceSolutionStruct );
899
900 {
901 // Strukturlsg als RW setzen (per Hand)
902 this->problemGeometry_->setBoundariesSystem(); // RW im System setzen (mit den Flags von oben)
903 this->problemGeometry_->getRhs()->putScalar(0.0);
904
905 Teuchos::ArrayRCP< SC > valuesInterface = interfaceSolutionFluid->getDataNonConst(0); //single MultiVector
906 Teuchos::ArrayRCP< SC > valuesFluidRhs = this->problemGeometry_->getRhs()->getBlock(0)->getDataNonConst(0); //single MultiVector
907
908 int flagCounter = 0;
909 for(UN i = 0; i < valuesInterface.size(); i++)
910 {
911 GO interfaceIDGlobal = interfaceMapGlobalFluidVecField->getGlobalElement( i );
912// GO interfaceID = interfaceMapFluidVecField->getGlobalElement( i ); // dofID in der Interface-Nummerierung
913// GO nodeID; // dofID der interfaceID in der Interface-Nummerierung
914// LO localDofNumber; // Ranges from 0 to dofs-1
915// toNodeID(this->dim_, interfaceID, nodeID, localDofNumber);//This function assumes NodeWise ordering.
916//
917// // Ggf. ist die ID auf einer anderen Flag.
918// // Bei nur einer Interface-Flag kommt man nicht hier hinein.
919// while(nodeID > indicesGlobalMatchedOriginFluid->at(flagCounter).at(0).size()-1)
920// {
921// nodeID = nodeID - indicesGlobalMatchedOriginFluid->at(flagCounter).at(0).size();
922// flagCounter = flagCounter + 1; // hier steht dann die korrekte Flag
923// }
924//
925// // Beachte: at(0) ist Fluid!!!
926// // GlobaleID des Interface-Knotens in der Fluid-Nummerierung
927// GO globalInterfaceIDNode = indicesGlobalMatchedOriginFluid->at(flagCounter).at(0).at(nodeID);
928// GO globalInterfaceIDinFluid; // dofID
929// toDofID(this->dim_, globalInterfaceIDNode, localDofNumber, globalInterfaceIDinFluid);
930
931 // LokaleID auf dem Prozessor des Interface-Knotens.
932 LO localInterfaceIDinFluid = domainFluid->getMapVecFieldUnique()->getLocalElement(interfaceIDGlobal);
933
934 valuesFluidRhs[localInterfaceIDinFluid] = valuesInterface[i];
935
936 // valuesFluidRhs[localInterfaceIDinFluid.at(i)] = valuesInterface[i];
937 }
938
939 this->problemGeometry_->solve();
940
941 if (!exporterGeo_.is_null())
942 this->exporterGeo_->save( this->timeSteppingTool_->currentTime() );
943
944
945 }
946
947
948
949}
950
951
952template<class SC,class LO,class GO,class NO>
953void FSI<SC,LO,GO,NO>::setupSubTimeProblems(ParameterListPtr_Type parameterListFluid, ParameterListPtr_Type parameterListStructure) const
954{
955 if(this->verbose_)
956 std::cout << "-- Setup FSI Sub-TimeProblems \n" << std::flush;
957
958 double dt = timeSteppingTool_->get_dt();
959 double beta = timeSteppingTool_->get_beta();
960
961 int sizeFluid = this->problemFluid_->getSystem()->size();
962 int sizeStructure;
963 if (materialModel_=="linear")
964 sizeStructure = this->problemStructure_->getSystem()->size();
965 else
966 sizeStructure = this->problemStructureNonLin_->getSystem()->size();
967
968 problemTimeFluid_.reset(new TimeProblem<SC,LO,GO,NO>(*this->problemFluid_, this->comm_));
969 if (materialModel_=="linear")
970 problemTimeStructure_.reset(new TimeProblem<SC,LO,GO,NO>(*this->problemStructure_, this->comm_));
971 else
972 problemTimeStructure_.reset(new TimeProblem<SC,LO,GO,NO>(*this->problemStructureNonLin_, this->comm_));
973
974 // ######################
975 // Fluid: Mass-, Problem, SourceTerm Koeffizienten
976 // ######################
977 SmallMatrix<double> massCoeffFluid(sizeFluid);
978 SmallMatrix<double> problemCoeffFluid(sizeFluid);
979 SmallMatrix<int> defFluid(sizeFluid);
980
981 double coeffSourceTermFluid = 0.0;
982 if ( this->getParameterList()->sublist("Timestepping Parameter").get("Class","Multistep") == "Multistep" ) {
983 for (int i=0; i<sizeFluid; i++) {
984 for (int j=0; j<sizeFluid; j++) {
985 if ((*defTS_)[i][j]==1 && i==j) {
986 defFluid[i][j] = 1;
987 massCoeffFluid[i][j] = timeSteppingTool_->getInformationBDF(0) / dt;
988 }
989 else{
990 massCoeffFluid[i][j] = 0.0;
991 }
992 }
993 }
994 for (int i=0; i<sizeFluid; i++) {
995 for (int j=0; j<sizeFluid; j++){
996 if ((*defTS_)[i][j]==1){
997 problemCoeffFluid[i][j] = timeSteppingTool_->getInformationBDF(1);
998 coeffSourceTermFluid = timeSteppingTool_->getInformationBDF(1);
999 }
1000 else{
1001 problemCoeffFluid[i][j] = 1.;
1002 }
1003 }
1004 }
1005 this->problemTimeFluid_->setTimeDef(defFluid);
1006 this->problemTimeFluid_->setTimeParameters(massCoeffFluid,problemCoeffFluid);
1007 }
1008 else{
1009 TEUCHOS_TEST_FOR_EXCEPTION(true, std::logic_error, "Implement other FSI fluid time stepping than BDF.");
1010 }
1011 // ######################
1012 // Struktur: Mass-, Problem, SourceTerm Koeffizienten
1013 // ######################
1014 // Koeffizienten vor der Massematrix und vor der Systemmatrix des steady-Problems
1015 SmallMatrix<double> massCoeffStructure(sizeStructure);
1016 SmallMatrix<double> problemCoeffStructure(sizeStructure);
1017 SmallMatrix<int> defStructure(sizeStructure);
1018 double coeffSourceTermStructure = 0.0; // Koeffizient fuer den Source-Term (= rechte Seite der DGL); mit Null initialisieren
1019
1020 // Koeffizient vor der Massematrix
1021 for(int i = 0; i < sizeStructure; i++)
1022 {
1023 for(int j = 0; j < sizeStructure; j++)
1024 {
1025 // Falls in dem Block von timeStepDef_ zeitintegriert werden soll.
1026 // i == j, da vektorwertige Massematrix blockdiagonal ist
1027 if((*defTS_)[i + sizeFluid][j + sizeFluid] == 1 && i == j) // Weil: (u_f, p, d_s,...) und timeStepDef_ von FSI
1028 {
1029 defStructure[i][j] = 1;
1030 // Vorfaktor der Massematrix in der LHS
1031 massCoeffStructure[i][j] = 1.0/(dt*dt*beta);
1032 }
1033 else
1034 {
1035 massCoeffStructure[i][j] = 0.;
1036 }
1037 }
1038 }
1039
1040 // Die anderen beiden Koeffizienten
1041 for(int i = 0; i < sizeStructure; i++)
1042 {
1043 for(int j = 0; j < sizeStructure; j++)
1044 {
1045 if((*defTS_)[i + sizeFluid][j + sizeFluid] == 1)
1046 {
1047 problemCoeffStructure[i][j] = 1.0;
1048 // Der Source Term ist schon nach der Assemblierung mit der Dichte \rho skaliert worden
1049 coeffSourceTermStructure = 1.0; // ACHTUNG FUER SOURCE TERM, DER NICHT IN DER ZEIT DISKRETISIERT WIRD!
1050 }
1051 else // Die steady-Systemmatrix ist nicht zwingend blockdiagonal
1052 {
1053 problemCoeffStructure[i][j] = 1.0;
1054 }
1055 }
1056 }
1057 this->problemTimeStructure_->setTimeDef(defStructure);
1058 this->problemTimeStructure_->setTimeParameters(massCoeffStructure,problemCoeffStructure);
1059
1060 this->problemTimeFluid_->assemble( "MassSystem" );
1061 this->problemTimeStructure_->assemble( "MassSystem" );
1062}
1063
1064
1065template<class SC,class LO,class GO,class NO>
1066void FSI<SC,LO,GO,NO>::setFluidMassmatrix( MatrixPtr_Type& massmatrix ) const
1067{
1068 //######################
1069 // Massematrix fuer FSI combineSystems(), ggf nichtlinear.
1070 //######################
1071 double density = this->problemTimeFluid_->getParameterList()->sublist("Parameter").get("Density",1000.e-0);
1072 int size = this->problemTimeFluid_->getSystem()->size();
1073
1074 this->problemTimeFluid_->systemMass_.reset(new BlockMatrix_Type(size));
1075 {
1076 massmatrix = Teuchos::rcp(new Matrix_Type( this->problemTimeFluid_->getDomain(0)->getMapVecFieldUnique(), this->getDomain(0)->getApproxEntriesPerRow() ) );
1077 // 0 = Fluid
1078 this->feFactory_->assemblyMass( this->dim_, this->problemTimeFluid_->getFEType(0), "Vector", massmatrix, 0, true );
1079 massmatrix->resumeFill();
1080 massmatrix->scale(density);
1081 massmatrix->fillComplete( this->problemTimeFluid_->getDomain(0)->getMapVecFieldUnique(), this->problemTimeFluid_->getDomain(0)->getMapVecFieldUnique() );
1082
1083 this->problemTimeFluid_->systemMass_->addBlock(massmatrix, 0, 0);
1084 }
1085}
1086
1087
1088// TODO: updateMultistepRhsFSI() einbauen!
1089template<class SC,class LO,class GO,class NO>
1090void FSI<SC,LO,GO,NO>::computeFluidRHSInTime( ) const
1091{
1092 //######################
1093 // RHS nach BDF2
1094 //######################
1095 int sizeFluid = this->problemFluid_->getSystem()->size();
1096 double dt = timeSteppingTool_->get_dt();
1097 int nmbBDF = timeSteppingTool_->getBDFNumber();
1098
1099 vec_dbl_Type coeffPrevSteps(nmbBDF);
1100 for(int i = 0; i < coeffPrevSteps.size(); i++)
1101 {
1102 coeffPrevSteps.at(i) = timeSteppingTool_->getInformationBDF(i+2) / dt;
1103 }
1104
1105 if (timeSteppingTool_->currentTime()==0.) {
1106 SmallMatrix<double> tmpmassCoeff(sizeFluid);
1107 SmallMatrix<double> tmpproblemCoeff(sizeFluid);
1108 for (int i=0; i<sizeFluid; i++) {
1109 for (int j=0; j<sizeFluid; j++) {
1110 if ((*defTS_)[i][j]==1 && i==j) {
1111 tmpmassCoeff[i][j] = 1. / dt;
1112 }
1113 else{
1114 tmpmassCoeff[i][j] = 0.;
1115 }
1116 }
1117 }
1118 for (int i=0; i<sizeFluid; i++) {
1119 for (int j=0; j<sizeFluid; j++){
1120 if ((*defTS_)[i][j]==1){
1121 tmpproblemCoeff[i][j] = 1.; // ist das richtig? Vermutlich schon, da BDF so geschrieben ist, dass zu berechnende Lsg den Koeffizienten 1 hat
1122 }
1123 else{
1124 tmpproblemCoeff[i][j] = 1.;
1125 }
1126 }
1127 }
1128 this->problemTimeFluid_->setTimeParameters(tmpmassCoeff, tmpproblemCoeff);
1129 }
1130 if (timeSteppingTool_->currentTime()==0.) {
1131 vec_dbl_Type tmpcoeffPrevSteps(1, 1. / dt);
1132 this->problemTimeFluid_->updateMultistepRhsFSI(tmpcoeffPrevSteps,1);/*apply (mass matrix_t / dt) to u_t*/
1133 }
1134 else{
1135 this->problemTimeFluid_->updateMultistepRhsFSI(coeffPrevSteps,nmbBDF);/*apply (mass matrix_t / dt) to u_t and more*/
1136 }
1137
1138 // TODO
1139 if (this->problemTimeFluid_->hasSourceTerm()) {
1140 TEUCHOS_TEST_FOR_EXCEPTION(true, std::logic_error, "Check sourceterm.");
1141 }
1142
1143 // Wieder zu den eigentlichen Parametern zuruecksetzen, nachdem die temporaeren
1144 // genommen wurden.
1145 if (timeSteppingTool_->currentTime()==0.) {
1146 SmallMatrix<double> massCoeffFluid(sizeFluid);
1147 SmallMatrix<double> problemCoeffFluid(sizeFluid);
1148
1149 for (int i=0; i<sizeFluid; i++) {
1150 for (int j=0; j<sizeFluid; j++) {
1151 if ((*defTS_)[i][j]==1 && i==j) {
1152 massCoeffFluid[i][j] = timeSteppingTool_->getInformationBDF(0) / dt;
1153 }
1154 else{
1155 massCoeffFluid[i][j] = 0.0;
1156 }
1157 }
1158 }
1159 for (int i=0; i<sizeFluid; i++) {
1160 for (int j=0; j<sizeFluid; j++){
1161 if ((*defTS_)[i][j]==1){
1162 problemCoeffFluid[i][j] = timeSteppingTool_->getInformationBDF(1);
1163 }
1164 else{
1165 problemCoeffFluid[i][j] = 1.;
1166 }
1167 }
1168 }
1169
1170 this->problemTimeFluid_->setTimeParameters(massCoeffFluid, problemCoeffFluid);
1171 }
1172}
1173
1174
1175// Am Anfang der Zeititeration erst updateSolutionMultiPreviousStep() aufrufen und dann erst updateMultistepRhs(),
1176// damit die previousSolution_ initialisiert sind. Genauso fuer SystemMass
1177// TODO: updateSystemMassMultiPreviousStep() fertig programmieren
1178template<class SC,class LO,class GO,class NO>
1179void FSI<SC,LO,GO,NO>::updateFluidInTime() const
1180{
1181 int nmbBDF = timeSteppingTool_->getBDFNumber();
1182
1183 if(nmbBDF<2 && !this->parameterList_->sublist("General").get("Linearization","FixedPoint").compare("Extrapolation")) {
1184 if (timeSteppingTool_->currentTime()!=0.){
1185 this->problemTimeFluid_->updateSolutionMultiPreviousStep(2);
1186 this->problemTimeFluid_->updateSystemMassMultiPreviousStep(2);
1187 }
1188 else{
1189 this->problemTimeFluid_->updateSolutionMultiPreviousStep(1);
1190 this->problemTimeFluid_->updateSystemMassMultiPreviousStep(1);
1191 }
1192 }
1193 else{
1194 this->problemTimeFluid_->updateSolutionMultiPreviousStep(nmbBDF);
1195 this->problemTimeFluid_->updateSystemMassMultiPreviousStep(nmbBDF);
1196 }
1197}
1198
1199template<class SC,class LO,class GO,class NO>
1200void FSI<SC,LO,GO,NO>::computeSolidRHSInTime() const {
1201 //######################
1202 // RHS nach Newmark
1203 //######################
1204 double dt = timeSteppingTool_->get_dt();
1205 double beta = timeSteppingTool_->get_beta();
1206 double gamma = timeSteppingTool_->get_gamma();
1207
1208 // Temporaerer Koeffizienten fuer die Skalierung der Massematrix in der rechten Seite des Systems in UpdateNewmarkRhs()
1209 vec_dbl_Type coeffTemp(1);
1210 coeffTemp.at(0) = 1.0;
1211
1212 // Update u und berechne u' und u'' mit Hilfe der Newmark-Vorschrift
1213 this->problemTimeStructure_->updateSolutionNewmarkPreviousStep(dt, beta, gamma);
1214
1215 // Stelle die rechte Seite des zeitdiskretisierten Systems auf (ohne f_{n+1}).
1216 // Bei Newmark lautet dies:
1217 // M*[\frac{1}{dt^2*beta}*u_n + \frac{1}{dt*beta}*u'_n + \frac{0.5 - beta}{beta}*u''_n],
1218 // wobei u' = v (velocity) und u'' = w (acceleration).
1219 this->problemTimeStructure_->updateNewmarkRhs(dt, beta, gamma, coeffTemp);
1220
1221 //can we get rid of this?
1222 double time = timeSteppingTool_->currentTime() + dt;
1223
1224 // TODO: SourceTerm wird in jedem Zeitschritt neu berechnet; auch wenn konstant!!!
1225 // if(time == 0){nur dann konstanten SourceTerm berechnen}
1226 if (this->problemTimeStructure_->hasSourceTerm())
1227 {
1228 this->problemTimeStructure_->assembleSourceTerm( time );
1229
1230 // Fuege die rechte Seite der DGL (f bzw. f_{n+1}) der rechten Seite hinzu (skaliert mit coeffSourceTerm)
1231 // Die Skalierung mit der Dichte erfolgt schon in der Assemblierungsfunktion!
1232
1233 // addSourceTermToRHS() aus DAESolverInTime
1234 double coeffSourceTermStructure = 1.0;
1235 BlockMultiVectorPtr_Type tmpPtr = this->problemTimeStructure_->getSourceTerm();
1236 this->problemTimeStructure_->getRhs()->update(coeffSourceTermStructure, *tmpPtr, 1.);
1237 }
1238
1239}
1240
1241template<class SC,class LO,class GO,class NO>
1242void FSI<SC,LO,GO,NO>::setSolidMassmatrix( MatrixPtr_Type& massmatrix ) const
1243{
1244 //######################
1245 // Massematrix
1246 //######################
1247 double density = this->problemTimeStructure_->getParameterList()->sublist("Parameter").get("Density",1000.e-0);
1248 int size = this->problemTimeStructure_->getSystem()->size();
1249
1250 if(timeSteppingTool_->currentTime() == 0.0)
1251 {
1252 this->problemTimeStructure_->systemMass_.reset(new BlockMatrix_Type(size));
1253 {
1254
1255 massmatrix = Teuchos::rcp(new Matrix_Type( this->problemTimeStructure_->getDomain(0)->getMapVecFieldUnique(), this->getDomain(0)->getApproxEntriesPerRow() ) );
1256 // 2 = Struktur
1257 this->feFactory_->assemblyMass(this->dim_, this->problemTimeStructure_->getFEType(0), "Vector", massmatrix, 2, true);
1258 massmatrix->resumeFill();
1259 massmatrix->scale(density);
1260 massmatrix->fillComplete( this->problemTimeStructure_->getDomain(0)->getMapVecFieldUnique(), this->problemTimeStructure_->getDomain(0)->getMapVecFieldUnique());
1261
1262 this->problemTimeStructure_->systemMass_->addBlock( massmatrix, 0, 0 );
1263 }
1264 }
1265}
1266
1267
1268// Damit die richtige timeSteppingTool_->currentTime() genommen wird.
1269template<class SC,class LO,class GO,class NO>
1270void FSI<SC,LO,GO,NO>::updateTime() const
1271{
1272 timeSteppingTool_->t_ = timeSteppingTool_->t_ + timeSteppingTool_->dt_prev_;
1273}
1274
1275template<class SC,class LO,class GO,class NO>
1276void FSI<SC,LO,GO,NO>::moveMesh() const
1277{
1278
1279 MultiVectorConstPtr_Type displacementUniqueConst;
1280 if(geometryExplicit_)
1281 {
1282 displacementUniqueConst = this->problemGeometry_->getSolution()->getBlock(0);
1283 }
1284 else
1285 {
1286 displacementUniqueConst = this->solution_->getBlock(4);
1287 }
1288 MultiVectorPtr_Type displacementRepeated = Teuchos::rcp( new MultiVector_Type( this->problemGeometry_->getDomain(0)->getMapVecFieldRepeated() ) );
1289
1290 displacementRepeated->importFromVector( displacementUniqueConst );
1291 MultiVectorPtr_Type displacementUnique = Teuchos::rcp_const_cast<MultiVector_Type>(displacementUniqueConst);
1292
1293
1294 // Verschiebe die Gitter fuer Fluid-Velocity und Fluid-Druck
1295 // ACHTUNG: Klappt nur, weil die P2-Knoten hinter den P1-Knoten kommen.
1296 // Sonst muessen fuer den Druck die P1-Knoten extrahiert werden.
1297 // TODO: Wahrscheinlich reicht nur FSI-Domain, da selbes Objekt bei problemFluid_ und problemTimeFluid_.
1298 ( Teuchos::rcp_const_cast<Domain_Type>(this->getDomain(0)) )->moveMesh(displacementUnique, displacementRepeated);
1299 ( Teuchos::rcp_const_cast<Domain_Type>(this->getDomain(1)) )->moveMesh(displacementUnique, displacementRepeated);
1300 ( Teuchos::rcp_const_cast<Domain_Type>(this->problemFluid_->getDomain(0)) )->moveMesh(displacementUnique, displacementRepeated);
1301 ( Teuchos::rcp_const_cast<Domain_Type>(this->problemFluid_->getDomain(1)) )->moveMesh(displacementUnique, displacementRepeated);
1302 ( Teuchos::rcp_const_cast<Domain_Type>(this->problemTimeFluid_->getDomain(0)) )->moveMesh(displacementUnique, displacementRepeated);
1303 ( Teuchos::rcp_const_cast<Domain_Type>(this->problemTimeFluid_->getDomain(1)) )->moveMesh(displacementUnique, displacementRepeated);
1304}
1305
1306
1307template<class SC,class LO,class GO,class NO>
1308void FSI<SC,LO,GO,NO>::addInterfaceBlockRHS() const
1309{
1310 MultiVectorPtr_Type vectorToAdd = Teuchos::rcp( new MultiVector_Type( this->rhs_->getBlock(3) ) );
1311
1312 C2_->apply(*(this->solution_->getBlock(2)), *vectorToAdd);
1313 this->rhs_->addBlock(vectorToAdd, 3);
1314}
1315
1316
1317template<class SC,class LO,class GO,class NO>
1318void FSI<SC,LO,GO,NO>::evalModelImpl(const Thyra::ModelEvaluatorBase::InArgs<SC> &inArgs,
1319 const Thyra::ModelEvaluatorBase::OutArgs<SC> &outArgs
1320 ) const
1321{
1322 TEUCHOS_TEST_FOR_EXCEPTION( true, std::logic_error, "implement NOX for steady FSI.");
1323 std::string type = this->parameterList_->sublist("General").get("Preconditioner Method","Monolithic");
1324// if ( !type.compare("Monolithic"))
1325// evalModelImplMonolithic( inArgs, outArgs );
1326// else if ( !type.compare("FaCSI")){
1327// evalModelImplBlock( inArgs, outArgs );
1328// }
1329// else
1330// TEUCHOS_TEST_FOR_EXCEPTION( true, std::logic_error, "Unkown preconditioner/solver type.");
1331}
1332
1333template<class SC,class LO,class GO,class NO>
1334void FSI<SC,LO,GO,NO>::getValuesOfInterest( vec_dbl_Type& values ){
1335 if (this->dim_==2)
1336 getValuesOfInterest2DBenchmark( values );
1337 else if(this->dim_==3)
1338 getValuesOfInterest3DBenchmark( values);
1339
1340}
1341
1342template<class SC,class LO,class GO,class NO>
1343void FSI<SC,LO,GO,NO>::getValuesOfInterest2DBenchmark( vec_dbl_Type& values ){
1344
1345
1346 if ( valuesForExport_[0] >= 0. ) { // we set the displacement of the 2D Turek Benchmark in x and y direction
1347 LO loc = valuesForExport_[0] + 10*Teuchos::ScalarTraits<SC>::eps();
1348 values[0] = this->getSolution()->getBlock(2)->getData(0)[2*loc];
1349 values[1] = this->getSolution()->getBlock(2)->getData(0)[2*loc+1];
1350 }
1351}
1352
1353template<class SC,class LO,class GO,class NO>
1354void FSI<SC,LO,GO,NO>::getValuesOfInterest3DBenchmark( vec_dbl_Type& values ){
1355
1356 if ( valuesForExport_[0] >= 0. ) { // we set the displacement of the 3D Richter Benchmark in x, y, and z direction
1357 LO loc = valuesForExport_[0] + 10*Teuchos::ScalarTraits<SC>::eps();
1358 values[0] = this->getSolution()->getBlock(2)->getData(0)[3*loc];
1359 values[1] = this->getSolution()->getBlock(2)->getData(0)[3*loc+1];
1360 values[2] = this->getSolution()->getBlock(2)->getData(0)[3*loc+2];
1361 }
1362}
1363
1364template<class SC,class LO,class GO,class NO>
1365void FSI<SC,LO,GO,NO>::computeValuesOfInterestAndExport(){
1366 if ( this->getParameterList()->sublist("General").get("Export drag and lift",false) ) {
1367
1368 int dim = this->dim_;
1369 TEUCHOS_TEST_FOR_EXCEPTION( this->parameterList_->sublist("Parameter").get("Criterion","Residual") == "Update", std::runtime_error, "Wrong nonlinear criterion to calculate the drag coefficient. The last system is the Newton system but we need the fixed point system. Either use Criterion=Residual or implement for Criterion=Update." );
1370
1371 TEUCHOS_TEST_FOR_EXCEPTION( this->problemFluid_->hasSourceTerm(), std::runtime_error, "We need to substract the additional source term: drag = < F*u + B_T*p + C1_T*lamba - f, v >" );
1372
1373 Teuchos::Array<SC> drag(1);
1374 Teuchos::Array<SC> lift(1);
1375
1376 BlockMultiVectorPtr_Type uDrag = Teuchos::rcp( new BlockMultiVector_Type( this->problemFluid_->getSolution() ) );
1377 BlockMultiVectorPtr_Type uLift = Teuchos::rcp( new BlockMultiVector_Type( this->problemFluid_->getSolution() ) );
1378 // should be the last fixed point system without boundary conditions or the last extrapolation system without boundary values.
1379 // We need to reassemble B and BT, because we might have set Dirichlet boundary conditions in BT (less likely in B)
1380 this->problemFluid_->assembleDivAndStab();
1381
1382 this->problemFluid_->getSystem()->apply( *this->problemFluid_->getSolution(), *uDrag );
1383 this->problemFluid_->getSystem()->apply( *this->problemFluid_->getSolution(), *uLift );
1384
1385 MultiVectorPtr_Type C1T_lambda = Teuchos::rcp( new MultiVector_Type( this->getSolution()->getBlock(0) ) );
1386 this->system_->getBlock(0,3)->apply( *this->getSolution()->getBlock(3), *C1T_lambda );
1387
1388 uDrag->getBlockNonConst(0)->update( 1., *C1T_lambda, 1. ); // velocity + C1_T * lambda
1389 uLift->getBlockNonConst(0)->update( 1., *C1T_lambda, 1. ); // velocity + C1_T * lambda
1390
1391 BCPtr_Type bcFactoryDrag = Teuchos::rcp( new BC_Type( ) );
1392 BCPtr_Type bcFactoryLift = Teuchos::rcp( new BC_Type( ) );
1393
1394 DomainConstPtr_Type domainVelocityConst = this->problemFluid_->getDomain(0);
1395 DomainPtr_Type domainVelocity = Teuchos::rcp_const_cast<Domain_Type>(domainVelocityConst);
1396 if( dim == 2 ){
1397 bcFactoryDrag->addBC(drag2D, 4, 0, domainVelocity, "Dirichlet", dim); // obstacle
1398 bcFactoryDrag->addBC(drag2D, 5, 0, domainVelocity, "Dirichlet", dim); // interface; check main fsi for matching flags at the obstacle and interface
1399 bcFactoryLift->addBC(lift2D, 4, 0, domainVelocity, "Dirichlet", dim);
1400 bcFactoryLift->addBC(lift2D, 5, 0, domainVelocity, "Dirichlet", dim);
1401 }
1402 else if( dim == 3 ){
1403 bcFactoryDrag->addBC(drag3D, 3, 0, domainVelocity, "Dirichlet", dim); // check main fsi for matching
1404 bcFactoryDrag->addBC(drag3D, 6, 0, domainVelocity, "Dirichlet", dim); // check main fsi for matching flags at the obstacle and interface
1405 bcFactoryLift->addBC(lift3D, 3, 0, domainVelocity, "Dirichlet", dim);
1406 bcFactoryLift->addBC(lift3D, 6, 0, domainVelocity, "Dirichlet", dim);
1407 }
1408
1409 BlockMultiVectorPtr_Type vD = Teuchos::rcp( new BlockMultiVector_Type( this->problemFluid_->getSolution() ) );
1410 BlockMultiVectorPtr_Type vL = Teuchos::rcp( new BlockMultiVector_Type( this->problemFluid_->getSolution() ) );
1411
1412 vD->putScalar(0.);
1413 vL->putScalar(0.);
1414
1415 bcFactoryDrag->setRHS( vD );
1416 bcFactoryLift->setRHS( vL );
1417
1418 uDrag->dot( vD, drag() );
1419 uLift->dot( vL, lift() );
1420
1421// double density = this->problemFluid_->getParameterList()->sublist("Parameter").get("Density",1.);
1422// double uMean = this->getParameterList()->sublist("Parameter").get("MeanVelocity",2.0);
1423// double L = 0.;
1424// if ( dim == 2)
1425// L = 2.*0.05;
1426// else
1427// L = 1.;
1428//
1429// drag[0] *= -(2./(density*uMean*uMean*L));
1430// lift[0] *= -(2./(density*uMean*uMean*L));
1431
1432 drag[0] *= -1.;
1433 lift[0] *= -1.;
1434
1435 exporterTxtDrag_->exportData( drag[0] );
1436 exporterTxtLift_->exportData( lift[0] );
1437 }
1438}
1439
1440template<class SC,class LO,class GO,class NO>
1441void FSI<SC,LO,GO,NO>::initializeGE(){
1442/*All vectors (solution, rhs, previousSolution,...) should be initialized at this point (initializeProblem() was called)
1443 Therefore, all these BlockMVectors should have a length of 5 since the geometry problem is included in the general setup. We need to resize these BlockMVs here if the Geometry Explicit (GE) system is used.
1444*/
1445 if (geometryExplicit_) {
1446 this->solution_->resize( 4 );
1447 this->rhs_->resize( 4 );
1448 this->sourceTerm_->resize( 4 );
1449 this->rhsFuncVec_.resize( 4 );
1450 this->previousSolution_->resize( 4 );
1451 this->residualVec_->resize( 4 );
1452 this->initVectorSpaces(); //reinitialize NOX vector spaces
1453 }
1454}
1455
1456}
1457#endif
Definition NonLinearProblem_decl.hpp:24
This class represents a templated small Matrix of type T. Primarily created for 2x2 and 3x3 matrices....
Definition SmallMatrix.hpp:22
Adaptive Mesh Refinement.
Definition AdaptiveMeshRefinement.cpp:5