Finite Element Domain Decomposition Library
FEDDLib
Loading...
Searching...
No Matches
TimeProblem_def.hpp
1#ifndef TIMEPROBLEM_DEF_hpp
2#define TIMEPROBLEM_DEF_hpp
3#include "TimeProblem_decl.hpp"
12
13namespace FEDD {
14
15template<class SC,class LO,class GO,class NO>
16TimeProblem<SC,LO,GO,NO>::TimeProblem(Problem_Type& problem, CommConstPtr_Type comm):
17comm_(comm),
18systemCombined_(),
19systemMass_(),
20timeParameters_(),
21timeStepDef_(),
22massParameters_(),
23feFactory_(),
24dimension_(problem.getDomain(0)->getDimension()),
25verbose_(comm->getRank()==0),
26parameterList_(problem.getParameterList()),
27bcFactory_(problem.getBCFactory()),
28massBCSet_(false),
29solutionPreviousTimesteps_(0),
30velocityPreviousTimesteps_(0),
31accelerationPreviousTimesteps_(0),
32systemMassPreviousTimeSteps_(0),
33time_(0.)
34#ifdef TIMEPROBLEM_TIMER
35,TimeSolveTimer_ (Teuchos::TimeMonitor::getNewCounter("TT Problem: Solve"))
36#endif
37,precInitOnly_(false)
38{
39 problem_ = Teuchos::rcpFromRef(problem);
40 BCConstPtr_Type bcFaCSI;
41 if( problem_->preconditioner_->hasFaCSIBCFactory() )
42 bcFaCSI = problem_->preconditioner_->getFaCSIBCFactory();
43
44 problem_->preconditioner_ = Teuchos::rcp( new Preconditioner_Type( this ) ); //we reset the preconditioner of underlying problem!
45
46 if( !bcFaCSI.is_null() )
47 problem_->preconditioner_->setFaCSIBCFactory( bcFaCSI );
48 FEFacConstPtr_Type facConst = problem.getFEFactory();
49 feFactory_ = Teuchos::rcp_const_cast<FEFac_Type>(facConst);
50
51 systemMass_.reset(new BlockMatrix_Type(1));
52 systemCombined_.reset( new BlockMatrix_Type( 1 ) );
53
54}
55
56template<class SC,class LO,class GO,class NO>
57void TimeProblem<SC,LO,GO,NO>::setTimeDef( SmallMatrix<int>& def ){
58 timeStepDef_ = def;
59}
60
61template<class SC,class LO,class GO,class NO>
62void TimeProblem<SC,LO,GO,NO>::assemble( std::string type ) const{
63 // If timestepping class is external, it is assumed that the full timedependent problem matrix and rhs are assembled during the assemble call(s)
64 std::string timestepping = parameterList_->sublist("Timestepping Parameter").get("Class","Singlestep");
65
66 if (type == "MassSystem"){
67 // is not used in FSI
68 // systemMass_ wird gebaut (Massematrix), welche schon mit der Dichte \rho skaliert wurde
69 assembleMassSystem();
70 initializeCombinedSystems();
71 NonLinProbPtr_Type nonLinProb = Teuchos::rcp_dynamic_cast<NonLinProb_Type>(problem_);
72 if (!nonLinProb.is_null()){// we combine the nonlinear system with the mass matrix in the NonLinearSolver after the reassembly of each linear system
73 }
74 else{
75 if (timestepping=="External" )
76 this->systemCombined_ = problem_->getSystem();
77 else
78 this->combineSystems();
79 }
80 }
81 else{
82 //we need to tell the problem about the last solution if we use extrapolation!
83 problem_->assemble(type);
84
85 if (timestepping=="External")
86 this->systemCombined_ = problem_->getSystem();
87 else
88 this->combineSystems();
89 }
90}
91
92
93template<class SC,class LO,class GO,class NO>
94void TimeProblem<SC,LO,GO,NO>::reAssembleAndFill( BlockMatrixPtr_Type bMat, std::string type ){
95
96 NonLinProbPtr_Type nonLinProb = Teuchos::rcp_dynamic_cast<NonLinProb_Type>(problem_);
97 nonLinProb->reAssembleAndFill( bMat, type );
98}
99
100template<class SC,class LO,class GO,class NO>
101void TimeProblem<SC,LO,GO,NO>::combineSystems() const{
102 //std::cout << "combineSystems is called" << std::endl;
103 BlockMatrixPtr_Type tmpSystem = problem_->getSystem();
104 int size = tmpSystem->size();
105 systemCombined_.reset( new BlockMatrix_Type ( size ) );
106
107 for (int i=0; i<size; i++) {
108 DomainConstPtr_Type dom = this->getDomain(i);
109 for (int j=0; j<size; j++) {
110 if ( tmpSystem->blockExists(i,j) ) {
111 LO maxNumEntriesPerRow = tmpSystem->getBlock(i,j)->getGlobalMaxNumRowEntries();
112 MatrixPtr_Type matrix = Teuchos::rcp( new Matrix_Type( tmpSystem->getBlock(i,j)->getMap(), maxNumEntriesPerRow ) );
113
114 systemCombined_->addBlock( matrix, i, j );
115
116 }
117 else if (systemMass_->blockExists(i,j)) {
118 LO maxNumEntriesPerRow = systemMass_->getBlock(i,j)->getGlobalMaxNumRowEntries();
119 MatrixPtr_Type matrix = Teuchos::rcp( new Matrix_Type( systemMass_->getBlock(i,j)->getMap(), maxNumEntriesPerRow) );
120 systemCombined_->addBlock( matrix, i, j );
121 }
122 }
123 }
124 SmallMatrix<SC> ones( size , Teuchos::ScalarTraits<SC>::one());
125 SmallMatrix<SC> zeros( size , Teuchos::ScalarTraits<SC>::zero());
126 systemMass_->addMatrix( massParameters_, systemCombined_, zeros );
127 tmpSystem->addMatrix( timeParameters_, systemCombined_, ones );
128
129 for (int i=0; i<size; i++) {
130 for (int j=0; j<size; j++) {
131 if ( systemCombined_->blockExists(i,j) ) {
132 if ( tmpSystem->blockExists(i,j) ) {
133 MatrixPtr_Type matrix = tmpSystem->getBlock(i,j);
134 MatrixConstPtr_Type matrixConstComb = systemCombined_->getBlock(i,j);
135 MatrixPtr_Type matrixComb = Teuchos::rcp_const_cast<Matrix_Type>(matrixConstComb);
136 matrixComb->fillComplete( matrix->getMap("domain"), matrix->getMap("range") );
137 }
138 else if ( systemMass_->blockExists(i,j) ) {
139 MatrixPtr_Type matrix = systemMass_->getBlock(i,j);
140 MatrixConstPtr_Type matrixConstComb = systemCombined_->getBlock(i,j);
141 MatrixPtr_Type matrixComb = Teuchos::rcp_const_cast<Matrix_Type>(matrixConstComb);
142 matrixComb->fillComplete( matrix->getMap("domain"), matrix->getMap("range") );
143 }
144 else
145 TEUCHOS_TEST_FOR_EXCEPTION( true, std::runtime_error,"TimeProblem: Combined systems possess a block which does not exist in partial systems.");
146 }
147 }
148 }
149}
150
151template<class SC,class LO,class GO,class NO>
152void TimeProblem<SC,LO,GO,NO>::updateRhs(){
153
154 systemMass_->apply( *solutionPreviousTimesteps_[0], *problem_->getRhs(), massParameters_ );
155}
156
157template<class SC,class LO,class GO,class NO>
158void TimeProblem<SC,LO,GO,NO>::updateMultistepRhs(vec_dbl_Type& coeff, int nmbToUse){
159
160 problem_->getRhs()->putScalar(0.);
161
162 int size = massParameters_.size();
163
164 for (int i=0; i<nmbToUse; i++) {
165 SmallMatrix<SC> tmpMassParameter(size);
166 for (int r=0; r<size; r++) {
167 for (int s=0; s<size; s++) {
168 if (massParameters_[r][s]!=0.)
169 tmpMassParameter[r][s] = coeff[i];
170 }
171 }
172 BlockMultiVectorPtr_Type tmpVector
173 = Teuchos::rcp( new BlockMultiVector_Type( problem_->getRhs() ) );
174 BlockMultiVectorPtr_Type tmpBlockVector = solutionPreviousTimesteps_[i];
175 systemMass_->apply( *tmpBlockVector, *tmpVector, tmpMassParameter );
176 problem_->getRhs()->update( 1., tmpVector, 1. );
177 }
178
179}
180
181
182template<class SC,class LO,class GO,class NO>
183void TimeProblem<SC,LO,GO,NO>::updateMultistepRhsFSI(vec_dbl_Type& coeff, int nmbToUse){
184
185 problem_->getRhs()->putScalar(0.);
186
187 int size = massParameters_.size();
188
189 for (int i=0; i<nmbToUse; i++) {
190 SmallMatrix<SC> tmpMassParameter(size);
191 for (int r=0; r<size; r++) {
192 for (int s=0; s<size; s++) {
193 if (massParameters_[r][s]!=0.) {
194 tmpMassParameter[r][s] = coeff[i];
195 }
196
197 }
198 }
199 BlockMultiVectorPtr_Type tmpVector
200 = Teuchos::rcp( new BlockMultiVector_Type( problem_->getRhs() ) );
201 BlockMultiVectorPtr_Type tmpBlockVector = solutionPreviousTimesteps_[i];
202 systemMassPreviousTimeSteps_[i]->apply( *tmpBlockVector, *tmpVector, tmpMassParameter );
203 problem_->getRhs()->update( 1., tmpVector, 1. );
204 }
205
206}
207
208
209// Stelle die rechte Seite des zeitdiskretisierten Systems auf (ohne f_{n+1}).
210// Bei Newmark lautet dies:
211// M*[\frac{1}{dt^2*beta}*u_n + \frac{1}{dt*beta}*u'_n + \frac{0.5 - beta}{beta}*u''_n],
212// wobei u' = v (velocity) und u'' = w (acceleration).
213template<class SC,class LO,class GO,class NO>
214void TimeProblem<SC,LO,GO,NO>::updateNewmarkRhs(double dt, double beta, double gamma, vec_dbl_Type coeff)
215{
216 // ######################
217 // Wir reseten die rechte Seite (beim ersten Schritt ist dies die rechte Seite der DGL [= SourceTerm] und
218 // spaeter ist es dann die rechte Seite des zeitintegrierten System aus dem vorherigen Zeitschritt)
219 // und fuegen alle noetigen Terme bis auf den SourceTerm hinzu.
220 // Der SourceTerm wir in AdvanceInTime() hinzuaddiert.
221 // BEACHTE: Bei Struktur gibt es nur einen Block, z.B. tempVector1[0].
222 // ######################
223
224 // Temperaerer Vektor fuer die Vektoradditionen in der rechte Seite.
225 // ACHTUNG: BlockMultiVector_Type tempVector1(*(solutionPreviousTimesteps_.at(0)))
226 // veraendert solutionPreviousTimesteps_.at(0)!!! NICHT NUTZEN!!!
227 BlockMultiVectorPtrArray_Type tempVector1(1);
228 // tempVector1 = u_n (in der neuen Zeiteration)
229 tempVector1.at(0) = Teuchos::rcp(new BlockMultiVector_Type(solutionPreviousTimesteps_.at(0)));
230
231 // tempVector1 = \frac{1}{dt^2*beta}*u_n
232 tempVector1.at(0)->scale(1.0/(dt*dt*beta));
233
234 // tempVector1 = tempVector1 + \frac{1}{dt*beta}*u'_n + \frac{0.5 - beta}{beta}*u''_n
235 tempVector1.at(0)->update(1.0/(dt*beta), *(velocityPreviousTimesteps_[0]), (0.5 - beta)/beta, *(accelerationPreviousTimesteps_[0]), 1.0);
236
237
238 // In tempVector2 steht dann das Endergebniss am Ende.
239 // Siehe ACHTUNG von oben.
240 BlockMultiVectorPtrArray_Type tempVector2(1);
241 tempVector2.at(0) = Teuchos::rcp(new BlockMultiVector_Type(solutionPreviousTimesteps_.at(0)));
242
243 // Koeffizient, um die mit \frac{rho}{dt^2*beta} skalierte Massematrix wieder zur Normalen zur machen
244 // Skalierung mit \rho ist allerdings notwendig!
245 int size = massParameters_.size();
246 SmallMatrix<double> tmpMassParameter(size);
247 for(int r = 0; r < size; r++)
248 {
249 for(int s = 0; s < size; s++)
250 {
251 if(massParameters_[r][s] != 0.0)
252 {
253 tmpMassParameter[r][s] = coeff.at(0);
254 }
255
256 }
257 }
258
259 // tempVector2 = tmpMassParameter.*M*tempVector1
260 systemMass_->apply(*(tempVector1.at(0)), *(tempVector2.at(0)), tmpMassParameter);
261
262 // RHS = 0*RHS + 1.0*tempVector2
263 problem_->getRhs()->update(1.0, *(tempVector2.at(0)), .0);
264
265}
266
267
268template<class SC,class LO,class GO,class NO>
269typename TimeProblem<SC,LO,GO,NO>::BlockMultiVectorPtr_Type TimeProblem<SC,LO,GO,NO>::getSolution(){
270
271 return problem_->getSolution();
272}
273
274template<class SC,class LO,class GO,class NO>
275typename TimeProblem<SC,LO,GO,NO>::BlockMultiVectorConstPtr_Type TimeProblem<SC,LO,GO,NO>::getSolutionConst() const {
276 return problem_->getSolution();
277}
278
279template<class SC,class LO,class GO,class NO>
280typename TimeProblem<SC,LO,GO,NO>::BlockMultiVectorPtr_Type TimeProblem<SC,LO,GO,NO>::getResidual(){
281
282 NonLinProbPtr_Type nonLinProb = Teuchos::rcp_dynamic_cast<NonLinProb_Type>(problem_);
283 TEUCHOS_TEST_FOR_EXCEPTION(nonLinProb.is_null(), std::runtime_error, "Nonlinear problem is null.");
284 return nonLinProb->getResidualVector ();
285}
286
287template<class SC,class LO,class GO,class NO>
288typename TimeProblem<SC,LO,GO,NO>::BlockMultiVectorConstPtr_Type TimeProblem<SC,LO,GO,NO>::getResidualConst() const{
289
290 NonLinProbPtr_Type nonLinProb = Teuchos::rcp_dynamic_cast<NonLinProb_Type>(problem_);
291 TEUCHOS_TEST_FOR_EXCEPTION(nonLinProb.is_null(), std::runtime_error, "Nonlinear problem is null.");
292 return nonLinProb->getResidualVector ();
293}
294
295template<class SC,class LO,class GO,class NO>
296typename TimeProblem<SC,LO,GO,NO>::BlockMultiVectorPtr_Type TimeProblem<SC,LO,GO,NO>::getSolutionPreviousTimestep(){
297
298 return solutionPreviousTimesteps_[0];
299}
300
301template<class SC,class LO,class GO,class NO>
302typename TimeProblem<SC,LO,GO,NO>::BlockMultiVectorPtrArray_Type TimeProblem<SC,LO,GO,NO>::getSolutionAllPreviousTimestep(){
303
304 return solutionPreviousTimesteps_;
305}
306
307template<class SC,class LO,class GO,class NO>
308void TimeProblem<SC,LO,GO,NO>::initializeCombinedSystems() const{
309
310 BlockMatrixConstPtr_Type blockMatrixProblem = problem_->getSystem();
311
312 int size = blockMatrixProblem->size();
313
314 for (int i=0; i<size; i++) {
315 for (int j=0; j<size; j++) {
316 MatrixPtr_Type matrix;
317 bool foundMatrix = false;
318 if ( blockMatrixProblem->blockExists(i,j) ) {
319 MatrixConstPtr_Type matrixProblem = blockMatrixProblem->getBlockConst(i,j);
320 MapConstPtr_Type map = matrixProblem->getMap();
321 MapPtr_Type mapNonConst = Teuchos::rcp_const_cast<Map_Type> (map);
322 matrix = Teuchos::rcp( new Matrix_Type( mapNonConst, matrixProblem->getGlobalMaxNumRowEntries() ) ); //We should build matrices with graphs!
323 foundMatrix = true;
324 }
325 else if( systemMass_->blockExists(i,j) && !foundMatrix ){
326 MatrixConstPtr_Type matrixMass = systemMass_->getBlockConst(i,j);
327 MapConstPtr_Type map = matrixMass->getMap();
328 MapPtr_Type mapNonConst = Teuchos::rcp_const_cast<Map_Type> (map);
329 matrix = Teuchos::rcp( new Matrix_Type( mapNonConst, matrixMass->getGlobalMaxNumRowEntries() ) ); //We should build matrices with graphs!
330 foundMatrix = true;
331 }
332 if (foundMatrix)
333 systemCombined_->addBlock( matrix, i, j );
334
335 }
336 }
337}
338
339template<class SC,class LO,class GO,class NO>
340void TimeProblem<SC,LO,GO,NO>::assembleMassSystem( ) const {
341
342
343 ProblemPtr_Type tmpProblem;
344 SC eps100 = 100.*Teuchos::ScalarTraits<SC>::eps();
345
346 // Die Massematrix wird noch mit der Dichte \rho skaliert
347 double density = parameterList_->sublist("Parameter").get("Density",1.);
348
349 int size = problem_->getSystem()->size();
350 systemMass_->resize( size );
351 int dofsPerNode;
352 for (int i=0; i<size; i++ ) {
353 dofsPerNode = problem_->getDofsPerNode(i);
354 MatrixPtr_Type M;
355 if ( timeStepDef_[i][i]>0 ) {
356 if (dofsPerNode>1) {
357 M = Teuchos::rcp(new Matrix_Type( this->getDomain(i)->getMapVecFieldUnique(), dimension_*this->getDomain(i)->getApproxEntriesPerRow() ) );
358 feFactory_->assemblyMass(dimension_, problem_->getFEType(i), "Vector", M, true);
359
360 M->resumeFill();
361 M->scale(density);
362 M->fillComplete( this->getDomain(i)->getMapVecFieldUnique(), this->getDomain(i)->getMapVecFieldUnique());
363
364 systemMass_->addBlock(M, i, i);
365 }
366 else{
367 M = Teuchos::rcp(new Matrix_Type( this->getDomain(i)->getMapUnique(), this->getDomain(i)->getApproxEntriesPerRow() ) );
368 feFactory_->assemblyMass(dimension_, problem_->getFEType(i), "Scalar", M, true);
369
370 M->resumeFill();
371 M->scale(density);
372 M->fillComplete( this->getDomain(i)->getMapUnique(), this->getDomain(i)->getMapUnique());
373
374 systemMass_->addBlock(M, i, i);
375 }
376 }
377 else{
378 for (int j=0; j<size; j++) {
379 if (timeStepDef_[i][j]==2) {
380 if (dofsPerNode>1) {
381 M = Teuchos::rcp(new Matrix_Type( this->getDomain(i)->getMapVecFieldUnique(), this->getDomain(i)->getApproxEntriesPerRow() ) );
382 feFactory_->assemblyMass(dimension_, problem_->getFEType(i), "Vector", M, true);
383
384 M->resumeFill();
385 M->scale(density);
386 M->fillComplete( this->getDomain(i)->getMapVecFieldUnique(), this->getDomain(i)->getMapVecFieldUnique());
387
388 systemMass_->addBlock(M, i, j);
389 }
390 else{
391 M = Teuchos::rcp(new Matrix_Type( this->getDomain(i)->getMapUnique(), this->getDomain(i)->getApproxEntriesPerRow() ) );
392 feFactory_->assemblyMass(dimension_, problem_->getFEType(i), "Scalar", M, true);
393
394 M->resumeFill();
395 M->scale(density);
396 M->fillComplete( this->getDomain(i)->getMapUnique(), this->getDomain(i)->getMapUnique());
397
398 systemMass_->addBlock(M, i, j);
399 }
400 }
401 }
402 }
403 }
404}
405
406template<class SC,class LO,class GO,class NO>
407void TimeProblem<SC,LO,GO,NO>::setTimeParameters(SmallMatrix<double> &massParameters, SmallMatrix<double> &timeParameters){
408
409 timeParameters_ = timeParameters;
410
411 massParameters_ = massParameters;
412
413}
414
415template<class SC,class LO,class GO,class NO>
416bool TimeProblem<SC,LO,GO,NO>::getVerbose(){
417
418 return verbose_;
419}
420
421template<class SC,class LO,class GO,class NO>
422double TimeProblem<SC,LO,GO,NO>::calculateResidualNorm(){
423
424 NonLinProbPtr_Type nonLinProb = Teuchos::rcp_dynamic_cast<NonLinProb_Type>(problem_);
425 TEUCHOS_TEST_FOR_EXCEPTION(nonLinProb.is_null(), std::runtime_error, "Nonlinear problem is null.");
426 Teuchos::Array<SC> res(1);
427 nonLinProb->getResidualVector()->norm2(res);
428 return res[0];
429}
430
431template<class SC,class LO,class GO,class NO>
432void TimeProblem<SC,LO,GO,NO>::calculateNonLinResidualVec( std::string type, double time ) const{
433
434 NonLinProbPtr_Type nonLinProb = Teuchos::rcp_dynamic_cast<NonLinProb_Type>(problem_);
435 TEUCHOS_TEST_FOR_EXCEPTION(nonLinProb.is_null(), std::runtime_error, "Nonlinear problem is null.");
436
437 if (type == "external") { // we get the complete residual from AceGEN
438 nonLinProb->calculateNonLinResidualVec( "external" );
439 }
440 else{
441 // rhs and sourceterm is accounted for in calculateNonLinResidualVec.
442 // rhs must bet assembled (computed) correctly in DAESolver (e.g. M/dt*u_t). sourceterm aswell
443 nonLinProb->calculateNonLinResidualVec( timeParameters_ ,type, time );
444
445 // for FSI we need to reassemble the massmatrix system if the mesh was moved for geometry implicit computations
446 if (this->parameterList_->sublist("Parameter").get("FSI",false) ){
447 bool geometryExplicit = this->parameterList_->sublist("Parameter").get("Geometry Explicit",true);
448 if( !geometryExplicit ) {
449 typedef FSI<SC,LO,GO,NO> FSI_Type;
450 typedef Teuchos::RCP<FSI_Type> FSIPtr_Type;
451
452 MatrixPtr_Type massmatrix;
453 FSIPtr_Type fsi = Teuchos::rcp_dynamic_cast<FSI_Type>( this->problem_ );
454 fsi->setFluidMassmatrix( massmatrix );
455 this->systemMass_->addBlock( massmatrix, 0, 0 );
456 }
457 }
458 // we need to add M/dt*u_(t+1)^k (the last results of the nonlinear method) to the residualVec_
459 //Copy
460 BlockMultiVectorPtr_Type tmpMV = Teuchos::rcp(new BlockMultiVector_Type( nonLinProb->getSolution() ) );
461 tmpMV->putScalar(0.);
462
463 systemMass_->apply( *nonLinProb->getSolution(), *tmpMV, massParameters_ );
464
465 if (type=="reverse")// reverse: b-Ax
466 nonLinProb->getResidualVector()->update(-1,*tmpMV,1.);//this=1.*this + -1.*tmpMV
467 else if(type=="standard")// standard: Ax-b
468 nonLinProb->getResidualVector()->update(1,*tmpMV,1.);
469 else
470 TEUCHOS_TEST_FOR_EXCEPTION( true, std::runtime_error, "Unkown type to compute the residual for a time problem.");
471
472 if (type=="reverse")// we set the Dirichlet BC to the residual
473 this->bcFactory_->setBCMinusVector( nonLinProb->getResidualVector(), nonLinProb->getSolution(), time );
474 else if(type=="standard")// we set the negative Dirichlet BC to the residual
475 this->bcFactory_->setVectorMinusBC( nonLinProb->getResidualVector(), nonLinProb->getSolution(), time );
476
477 }
478
479
480}
481
482template<class SC,class LO,class GO,class NO>
483void TimeProblem<SC,LO,GO,NO>::setBoundaries(double time){
484
485 BlockMultiVectorPtr_Type tmpRhs = problem_->getRhs();
486
487 bcFactory_->set( systemCombined_, tmpRhs, time );
488}
489
490template<class SC,class LO,class GO,class NO>
491void TimeProblem<SC,LO,GO,NO>::setBoundariesRHS(double time){
492
493 BlockMultiVectorPtr_Type tmpRhs = problem_->getRhs();
494
495 bcFactory_->setRHS( tmpRhs, time );
496}
497
498template<class SC,class LO,class GO,class NO>
499void TimeProblem<SC,LO,GO,NO>::setBoundariesSystem() const{
500
501 bcFactory_->setSystem(systemCombined_);
502
503}
504
505template<class SC,class LO,class GO,class NO>
506int TimeProblem<SC,LO,GO,NO>::solveUpdate( ){
507
508 NonLinProbPtr_Type nonLinProb = Teuchos::rcp_dynamic_cast<NonLinProb_Type>(problem_);
509 TEUCHOS_TEST_FOR_EXCEPTION(nonLinProb.is_null(), std::runtime_error, "Nonlinear problem is null.");
510
511 *nonLinProb->previousSolution_ = *nonLinProb->getSolution();
512 int its = this->solve( nonLinProb->residualVec_ );
513
514 return its;
515}
516
517template<class SC,class LO,class GO,class NO>
518int TimeProblem<SC,LO,GO,NO>::solveAndUpdate( const std::string& criterion, double& criterionValue ){
519
520 NonLinProbPtr_Type nonLinProb = Teuchos::rcp_dynamic_cast<NonLinProb_Type>(problem_);
521 TEUCHOS_TEST_FOR_EXCEPTION(nonLinProb.is_null(), std::runtime_error, "Nonlinear problem is null.");
522
523
524 int its = solveUpdate( );
525
526 if (criterion=="Update") {
527 Teuchos::Array<SC> updateNorm(1);
528 nonLinProb->getSolution()->norm2(updateNorm());
529 criterionValue = updateNorm[0];
530 }
531
532
533 if (criterion=="ResidualAceGen") {
534 nonLinProb->getSolution()->update( 1., *nonLinProb->previousSolution_, -1. );
535 nonLinProb->assemble( "SetSolutionNewton" );
536 //nonLinProb->assembleExternal( "OnlyUpdate" ); // CH 04.06.2020: Ist das richtig?
537 }
538 else
539 nonLinProb->getSolution()->update( 1., *nonLinProb->previousSolution_, 1. );
540
541 return its;
542}
543
544template<class SC,class LO,class GO,class NO>
545int TimeProblem<SC,LO,GO,NO>::solve( BlockMultiVectorPtr_Type rhs ){
546
547 int its;
548 if (verbose_)
549 std::cout << "-- Solve System ..." << std::endl;
550 {
551 std::string type = parameterList_->sublist("General").get("Preconditioner Method","Monolithic");
552 LinearSolver<SC,LO,GO,NO> linSolver;
553 its = linSolver.solve( this, rhs, type ); // if rhs is null. Then the rhs_ of this is used in the linear solver
554 }
555 if (verbose_)
556 std::cout << " done. -- " << std::endl;
557
558 return its;
559}
560
561template<class SC,class LO,class GO,class NO>
562void TimeProblem<SC,LO,GO,NO>::updateSolutionPreviousStep(){
563
564 if (solutionPreviousTimesteps_.size()==0)
565 solutionPreviousTimesteps_.resize(1);
566
567 solutionPreviousTimesteps_[0] = Teuchos::rcp( new BlockMultiVector_Type( problem_->getSolution() ) );
568
569}
570
571template<class SC,class LO,class GO,class NO>
572void TimeProblem<SC,LO,GO,NO>::updateSolutionMultiPreviousStep(int nmbSteps){
573
574 int size = solutionPreviousTimesteps_.size();
575 if (size<nmbSteps && size > 0) {
576 BlockMultiVectorPtr_Type toAddMVreset = Teuchos::rcp( new BlockMultiVector_Type( solutionPreviousTimesteps_[size-1] ) );
577 solutionPreviousTimesteps_.push_back( toAddMVreset );
578 }
579 else if(size == 0)
580 solutionPreviousTimesteps_.resize(1);
581 else{
582 for (int i=size-1; i>0; i--)
583 solutionPreviousTimesteps_[i] = Teuchos::rcp( new BlockMultiVector_Type( solutionPreviousTimesteps_[i-1] ) );
584 }
585
586 solutionPreviousTimesteps_[0] = Teuchos::rcp( new BlockMultiVector_Type( problem_->getSolution() ) );
587
588}
589
590
591template<class SC,class LO,class GO,class NO>
592void TimeProblem<SC,LO,GO,NO>::updateSystemMassMultiPreviousStep(int nmbSteps){
593
594 int size = systemMassPreviousTimeSteps_.size();
595 if (size<nmbSteps && size > 0) {// only works for BDF2, for BDF3 we would have to adjust below else case
596 BlockMatrixPtr_Type toAddMatrixreset = Teuchos::rcp( new BlockMatrix_Type( systemMassPreviousTimeSteps_[size-1] ) );
597
598 systemMassPreviousTimeSteps_.push_back( toAddMatrixreset );
599 }
600 else if(size == 0)
601 systemMassPreviousTimeSteps_.resize(1);
602 else{
603 for (int i=size-1; i>0; i--)
604 systemMassPreviousTimeSteps_[i] = Teuchos::rcp( new BlockMatrix_Type( systemMassPreviousTimeSteps_[i-1] ) );
605 }
606
607 systemMassPreviousTimeSteps_[0] = Teuchos::rcp( new BlockMatrix_Type( systemMass_ ) );
608
609}
610
611
612// Beachte: Diese Funktion wird zu Beginn jeder time-loop aufgerufen!!!
613template<class SC,class LO,class GO,class NO>
614void TimeProblem<SC,LO,GO,NO>::updateSolutionNewmarkPreviousStep(double dt, double beta, double gamma)
615{
616 // ########################
617 // Fuer die Newmark-Variable u (displacement)
618 // ########################
619 // Zur Berechnung von u'_{n+1} und u''_{n+1} wird die letzte Loesung u_{n+1} und die Vorherige u_n gebraucht.
620 // Da wir aber bereits im neuen Zeitschritt sind (vgl. Zeitpunkt des Aufrufs der Funktion), ist u_n = u_{n+1} und u_{n-1} = u_n.
621 // Wir benoetigen solutionPreviousTimesteps_ mit zwei Eintraegen.
622 int size = solutionPreviousTimesteps_.size();
623
624 if(size < 2 && size > 0) // Sofern der Vektor solutionPreviousTimesteps_ noch nicht komplett belegt ist (bei Newmark benoetigen wir als vergangene Loesung noch u_n)
625 {
626 BlockMultiVectorPtr_Type toAddMVreset = Teuchos::rcp(new BlockMultiVector_Type(solutionPreviousTimesteps_.at(size-1)));
627 // Fuege die z.B. zweite Loesung u_2 hinten drauf, sofern eine vergangene Loesung bei der Zeitintegration gebraucht wird
628 solutionPreviousTimesteps_.push_back(toAddMVreset);
629 }
630 else if(size == 0) // Falls noch keine alte Loesung vorhanden ist
631 {
632 solutionPreviousTimesteps_.resize(1);
633 }
634 else // Verschiebe alle vergangenen Loesungen
635 {
636 for(int i = size-1; i > 0; i--)
637 {
638 solutionPreviousTimesteps_.at(i) = Teuchos::rcp(new BlockMultiVector_Type(solutionPreviousTimesteps_.at(i-1)));
639 }
640
641 }
642
643 solutionPreviousTimesteps_.at(0) = Teuchos::rcp(new BlockMultiVector_Type(problem_->getSolution()));
644
645 // Bzgl. der neuen Zeititeration steht am Ende nun an der Stelle 0 die vergangene Loesung u_n und
646 // an der Stelle die 1 davor, also u_{n-1}. Dies entspricht u_{n+1} und u_n, wenn man u'_{n+1} und
647 // u''_{n+1} bereits am Ende der letzten Zeititeration berechnet.
648
649 // ########################
650 // Fuer die Newmark-Variablen u' = v (velocity) und u'' = w (acceleration)
651 // ########################
652 if(velocityPreviousTimesteps_.size() == 0)
653 {
654 // Hier steht noch kein MultiVector drin
655 velocityPreviousTimesteps_.resize(1);
656 accelerationPreviousTimesteps_.resize(1);
657
658 // Am Anfang haben wir als Startloesung die Nulloesung.
659 // Wir wollen als Startwerte ebenso u' = u'' = 0 setzen.
660 // Schreibe die Startloesung als MultiVector hinein (damit dort irgendetwas steht) und setze diese dann auf Null
661 velocityPreviousTimesteps_.at(0) = Teuchos::rcp(new BlockMultiVector_Type(problem_->getSolution()));
662 accelerationPreviousTimesteps_.at(0) = Teuchos::rcp(new BlockMultiVector_Type(problem_->getSolution()));
663 velocityPreviousTimesteps_.at(0)->putScalar(0.0);
664 accelerationPreviousTimesteps_.at(0)->putScalar(0.0);
665 }
666 else
667 {
668 // ########################
669 // u'_{n+1} = \frac{gamma}{dt*beta}*(u_{n+1} - u_n) + (1 - \frac{gamma}{beta})*u'_n + dt*\frac{beta - 0.5*gamma}{beta}*u''_n, vgl. MA
670 // ########################
671
672 // Speichere die alte (nicht geupdatete) velocity u'_n fuer die Berechnung von u''_{n+1} ab.
673 // Siehe hier drunter fuer ACHTUNG.
674 BlockMultiVectorPtrArray_Type velocityOld;
675 velocityOld.resize(1);
676 velocityOld.at(0) = Teuchos::rcp(new BlockMultiVector_Type(velocityPreviousTimesteps_.at(0)));
677
678
679 // Berechne \frac{gamma}{dt*beta}*(u_{n+1} - u_n):
680 // ACHTUNG: BlockMultiVector_Type tmpVector1(*(solutionPreviousTimesteps_.at(0)))
681 // veraendert solutionPreviousTimesteps_.at(0)!!! NICHT NUTZEN!!!
682 // BlockMultiVector_Type tmpVector1(*(solutionPreviousTimesteps_.at(0)));
683 BlockMultiVectorPtrArray_Type tmpVector1;
684 tmpVector1.resize(1);
685 // tmpVector1 = u_{n+1}
686 tmpVector1.at(0) = Teuchos::rcp(new BlockMultiVector_Type(solutionPreviousTimesteps_.at(0)));
687
688 // Funktionsaufruf: Update(ScalarA, A, ScalarThis) => this = ScalarThis*this + ScalarA*A
689 tmpVector1.at(0)->update(-gamma/(dt*beta), *(solutionPreviousTimesteps_.at(1)), gamma/(dt*beta));
690
691 // Berechne (1 - \frac{gamma}{beta})*u'_n
692 velocityPreviousTimesteps_.at(0)->scale(1.0 - (gamma/beta));
693
694 // Addiere noch \tmpVector1 + dt*\frac{beta - 0.5*gamma}{beta}*u''_n HINZU
695 // Funktionsaufruf: Update(ScalarA, A, ScalarB, B, ScalarThis) => this = ScalarThis*this + ScalarA*A + ScalarB*B
696 velocityPreviousTimesteps_.at(0)->update(1.0, *(tmpVector1.at(0)), dt*((beta - 0.5*gamma)/(beta)), *(accelerationPreviousTimesteps_.at(0)), 1.0);
697
698
699 // ########################
700 // u''_{n+1} = \frac{1}{dt*dt*beta}*(u_{n+1} - u_n) - \frac{1}{dt*beta})*u'_n - \frac{0.5 - beta}{beta}*u''_n, vgl. MA
701 // ########################
702
703 // Berechne \frac{1}{dt*dt*beta}*(u_{n+1} - u_n):
704 // Beachte ACHTUNG von oben.
705 BlockMultiVectorPtrArray_Type tmpVector2;
706 tmpVector2.resize(1);
707 // tmpVector2 = u_{n+1}
708 tmpVector2.at(0) = Teuchos::rcp(new BlockMultiVector_Type(solutionPreviousTimesteps_.at(0)));
709
710 // Funktionsaufruf: Update(ScalarA, A, ScalarThis) => this = ScalarThis*this + ScalarA*A
711 tmpVector2.at(0)->update(-1.0/(dt*dt*beta), *(solutionPreviousTimesteps_.at(1)), 1.0/(dt*dt*beta));
712
713 // Berechne -\frac{0.5 - beta}{beta}*u''_n. ACHTUNG VORZEICHEN!!!
714 accelerationPreviousTimesteps_.at(0)->scale(-(0.5 - beta)/beta);
715
716 // Addiere noch \tmpVector2 - \frac{1}{dt*beta})*u'_n HINZU
717 // Funktionsaufruf: Update(ScalarA, A, ScalarB, B, ScalarThis) => this = ScalarThis*this + ScalarA*A + ScalarB*B
718 accelerationPreviousTimesteps_.at(0)->update(1.0, *(tmpVector2.at(0)), -1.0/(dt*beta), *(velocityOld.at(0)), 1.0);
719 }
720}
721template<class SC,class LO,class GO,class NO>
722void TimeProblem<SC,LO,GO,NO>::assembleSourceTerm( double time ){
723
724 problem_->assembleSourceTerm(time);
725
726}
727
728template<class SC,class LO,class GO,class NO>
729typename TimeProblem<SC,LO,GO,NO>::BlockMultiVectorPtr_Type TimeProblem<SC,LO,GO,NO>::getSourceTerm( ) {
730
731 return problem_->getSourceTerm();
732
733}
734
735template<class SC,class LO,class GO,class NO>
736bool TimeProblem<SC,LO,GO,NO>::hasSourceTerm( ) const{
737
738 return problem_->hasSourceTerm();
739
740}
741
742template<class SC,class LO,class GO,class NO>
743typename TimeProblem<SC,LO,GO,NO>::BlockMultiVectorPtr_Type TimeProblem<SC,LO,GO,NO>::getRhs(){
744
745 return problem_->getRhs();
746}
747
748template<class SC,class LO,class GO,class NO>
749typename TimeProblem<SC,LO,GO,NO>::BlockMultiVectorPtr_Type TimeProblem<SC,LO,GO,NO>::getRhs() const{
750
751 return problem_->getRhs();
752}
753
754template<class SC,class LO,class GO,class NO>
755typename TimeProblem<SC,LO,GO,NO>::DomainConstPtr_Type TimeProblem<SC,LO,GO,NO>::getDomain(int i) const {
756
757 return problem_->getDomain(i);
758}
759
760template<class SC,class LO,class GO,class NO>
761std::string TimeProblem<SC,LO,GO,NO>::getFEType(int i){
762
763 return problem_->getFEType(i);
764}
765
766template<class SC,class LO,class GO,class NO>
767int TimeProblem<SC,LO,GO,NO>::getDofsPerNode(int i){
768
769 return problem_->getDofsPerNode(i);
770}
771
772template<class SC,class LO,class GO,class NO>
773std::string TimeProblem<SC,LO,GO,NO>::getVariableName(int i){
774
775 return problem_->getVariableName(i);
776}
777
778template<class SC,class LO,class GO,class NO>
779typename TimeProblem<SC,LO,GO,NO>::BlockMatrixPtr_Type TimeProblem<SC,LO,GO,NO>::getSystem(){
780
781 return problem_->getSystem();
782}
783
784template<class SC,class LO,class GO,class NO>
785typename TimeProblem<SC,LO,GO,NO>::BlockMatrixPtr_Type TimeProblem<SC,LO,GO,NO>::getSystemCombined(){
786
787 TEUCHOS_TEST_FOR_EXCEPTION(systemCombined_.is_null(), std::logic_error,"system combined of TimeProblem is null.");
788
789 return systemCombined_;
790}
791
792template<class SC,class LO,class GO,class NO>
793typename TimeProblem<SC,LO,GO,NO>::BlockMatrixPtr_Type TimeProblem<SC,LO,GO,NO>::getSystemCombined() const{
794
795 TEUCHOS_TEST_FOR_EXCEPTION(systemCombined_.is_null(), std::logic_error,"system combined of TimeProblem is null.");
796
797 return systemCombined_;
798}
799
800template<class SC,class LO,class GO,class NO>
801typename TimeProblem<SC,LO,GO,NO>::ProblemPtr_Type TimeProblem<SC,LO,GO,NO>::getUnderlyingProblem(){
802
803 return problem_;
804}
805
806template<class SC,class LO,class GO,class NO>
807void TimeProblem<SC,LO,GO,NO>::addToRhs(BlockMultiVectorPtr_Type x){
808
809 problem_->addToRhs(x);
810}
811
812template<class SC,class LO,class GO,class NO>
813typename TimeProblem<SC,LO,GO,NO>::BlockMatrixPtr_Type TimeProblem<SC,LO,GO,NO>::getMassSystem(){
814
815 return systemMass_;
816}
817
818template<class SC,class LO,class GO,class NO>
819ParameterListPtr_Type TimeProblem<SC,LO,GO,NO>::getParameterList(){
820
821 return parameterList_;
822}
823
824template<class SC,class LO,class GO,class NO>
825typename TimeProblem<SC,LO,GO,NO>::LinSolverBuilderPtr_Type TimeProblem<SC,LO,GO,NO>::getLinearSolverBuilder() const{
826
827 return problem_->getLinearSolverBuilder();
828}
829
830template<class SC,class LO,class GO,class NO>
831void TimeProblem<SC,LO,GO,NO>::getValuesOfInterest( vec_dbl_Type& values ){
832
833 problem_->getValuesOfInterest( values );
834}
835
836template<class SC,class LO,class GO,class NO>
837void TimeProblem<SC,LO,GO,NO>::computeValuesOfInterestAndExport( ){
838
839 problem_->computeValuesOfInterestAndExport( );
840}
841
842
843template<class SC, class LO, class GO, class NO>
844Thyra::ModelEvaluatorBase::InArgs<SC> TimeProblem<SC,LO,GO,NO>::getNominalValues() const
845{
846 NonLinProbPtr_Type nonLinProb = Teuchos::rcp_dynamic_cast<NonLinProb_Type>(problem_);
847 TEUCHOS_TEST_FOR_EXCEPTION(nonLinProb.is_null(), std::runtime_error, "Nonlinear problem is null.");
848
849 return nonLinProb->getNominalValues();
850}
851
852template<class SC,class LO,class GO,class NO>
853Teuchos::RCP<const ::Thyra::VectorSpaceBase<SC> > TimeProblem<SC,LO,GO,NO>::get_x_space() const{
854 NonLinProbPtr_Type nonLinProb = Teuchos::rcp_dynamic_cast<NonLinProb_Type>(problem_);
855 TEUCHOS_TEST_FOR_EXCEPTION(nonLinProb.is_null(), std::runtime_error, "Nonlinear problem is null.");
856
857 return nonLinProb->get_x_space();
858}
859
860template<class SC,class LO,class GO,class NO>
861Teuchos::RCP<const ::Thyra::VectorSpaceBase<SC> > TimeProblem<SC,LO,GO,NO>::get_f_space() const{
862 NonLinProbPtr_Type nonLinProb = Teuchos::rcp_dynamic_cast<NonLinProb_Type>(problem_);
863 TEUCHOS_TEST_FOR_EXCEPTION(nonLinProb.is_null(), std::runtime_error, "Nonlinear problem is null.");
864 return nonLinProb->get_f_space();
865}
866
867template<class SC,class LO,class GO,class NO>
868Thyra::ModelEvaluatorBase::InArgs<SC> TimeProblem<SC,LO,GO,NO>::createInArgs() const
869{
870 NonLinProbPtr_Type nonLinProb = Teuchos::rcp_dynamic_cast<NonLinProb_Type>(problem_);
871 TEUCHOS_TEST_FOR_EXCEPTION(nonLinProb.is_null(), std::runtime_error, "Nonlinear problem is null.");
872 return nonLinProb->createInArgs();
873}
874
875// NOX
876template<class SC,class LO,class GO,class NO>
877Thyra::ModelEvaluatorBase::OutArgs<SC> TimeProblem<SC,LO,GO,NO>::createOutArgsImpl() const
878{
879 NonLinProbPtr_Type nonLinProb = Teuchos::rcp_dynamic_cast<NonLinProb_Type>(problem_);
880 TEUCHOS_TEST_FOR_EXCEPTION(nonLinProb.is_null(), std::runtime_error, "Nonlinear problem is null.");
881 return nonLinProb->createOutArgsImpl();
882}
883
884template<class SC,class LO,class GO,class NO>
885Teuchos::RCP<Thyra::LinearOpBase<SC> > TimeProblem<SC,LO,GO,NO>::create_W_op()
886{
887
888 this->calculateNonLinResidualVec( "standard", time_ );
889 this->assemble("Newton");
890
891// TEUCHOS_TEST_FOR_EXCEPTION( true, std::logic_error, "we need to fix the operators and preconditioners for TimeProblem NOX setup.");
892
893 std::string type = this->parameterList_->sublist("General").get("Preconditioner Method","Monolithic");
894 if ( type == "Monolithic" )
895 return create_W_op_Monolithic( );
896 else
897 return create_W_op_Block( );
898}
899
900template<class SC,class LO,class GO,class NO>
901Teuchos::RCP<Thyra::LinearOpBase<SC> > TimeProblem<SC,LO,GO,NO>::create_W_op_Monolithic()
902{
903 Teuchos::RCP<const Thyra::LinearOpBase<SC> > W_opConst = this->getSystemCombined()->getThyraLinOp();
904 Teuchos::RCP<Thyra::LinearOpBase<SC> > W_op = Teuchos::rcp_const_cast<Thyra::LinearOpBase<SC> >(W_opConst);
905 return W_op;
906}
907
908template<class SC,class LO,class GO,class NO>
909Teuchos::RCP<Thyra::LinearOpBase<SC> > TimeProblem<SC,LO,GO,NO>::create_W_op_Block()
910{
911
912 BlockMatrixPtr_Type system = this->getSystemCombined();
913
914 Teuchos::RCP<const ThyraBlockOp_Type> W_opBlocksConst = system->getThyraLinBlockOp();
915 Teuchos::RCP<ThyraBlockOp_Type> W_opBlocks = Teuchos::rcp_const_cast<ThyraBlockOp_Type >(W_opBlocksConst);
916 Teuchos::RCP<ThyraOp_Type> W_op = Teuchos::rcp_dynamic_cast<ThyraOp_Type >(W_opBlocks);
917
918 return W_op;
919}
920
921template<class SC,class LO,class GO,class NO>
922Teuchos::RCP<Thyra::PreconditionerBase<SC> > TimeProblem<SC,LO,GO,NO>::create_W_prec()
923{
924
925 NonLinProbPtr_Type nonLinProb = Teuchos::rcp_dynamic_cast<NonLinProb_Type>(problem_);
926 TEUCHOS_TEST_FOR_EXCEPTION(nonLinProb.is_null(), std::runtime_error, "Nonlinear problem is null.");
927
928 if (!nonLinProb->getPreconditionerConst()->isPreconditionerComputed()) {
929 nonLinProb->initializeSolverBuilder();
930
931 std::string type = this->parameterList_->sublist("General").get("Preconditioner Method","Monolithic");
932 this->setBoundariesSystem();
933
934 if ( type == "Teko" || type == "FaCSI-Teko" || type =="Diagonal" ) { //we need to construct the whole preconditioner if Teko is used
935 nonLinProb->setupPreconditioner( type );
936 precInitOnly_ = false;
937 }
938 else{
939 nonLinProb->setupPreconditioner( type ); //nonLinProb->initializePreconditioner( type );
940 }
941 }
942
943 Teuchos::RCP<const Thyra::PreconditionerBase<SC> > thyraPrec = nonLinProb->getPreconditionerConst()->getThyraPrecConst();
944 Teuchos::RCP<Thyra::PreconditionerBase<SC> > thyraPrecNonConst = Teuchos::rcp_const_cast<Thyra::PreconditionerBase<SC> >(thyraPrec);
945
946 return thyraPrecNonConst;
947
948}
949
950template<class SC,class LO,class GO,class NO>
951void TimeProblem<SC,LO,GO,NO>::evalModelImpl( const Thyra::ModelEvaluatorBase::InArgs<SC> &inArgs,
952 const Thyra::ModelEvaluatorBase::OutArgs<SC> &outArgs
953 ) const
954{
955 std::string type = this->parameterList_->sublist("General").get("Preconditioner Method","Monolithic");
956 if ( !type.compare("Monolithic"))
957 evalModelImplMonolithic( inArgs, outArgs );
958 else
959 evalModelImplBlock( inArgs, outArgs );
960}
961
962template<class SC,class LO,class GO,class NO>
963void TimeProblem<SC,LO,GO,NO>::evalModelImplMonolithic( const Thyra::ModelEvaluatorBase::InArgs<SC> &inArgs,
964 const Thyra::ModelEvaluatorBase::OutArgs<SC> &outArgs ) const
965{
966
967
968 using Teuchos::RCP;
969 using Teuchos::rcp;
970 using Teuchos::rcp_dynamic_cast;
971 using Teuchos::rcp_const_cast;
972 using Teuchos::ArrayView;
973 using Teuchos::Array;
974
975 TEUCHOS_TEST_FOR_EXCEPTION( inArgs.get_x().is_null(), std::logic_error, "inArgs.get_x() is null.");
976
977 RCP< const Thyra::VectorBase< SC > > vecThyra = inArgs.get_x();
978
979 RCP< Thyra::VectorBase< SC > > vecThyraNonConst = rcp_const_cast<Thyra::VectorBase< SC > >(vecThyra);
980
981 BlockMultiVectorConstPtr_Type solConst = this->getSolutionConst();
982 BlockMultiVectorPtr_Type sol = rcp_const_cast<BlockMultiVector_Type >(solConst);
983 sol->fromThyraMultiVector(vecThyraNonConst);
984
985 const RCP<Thyra::MultiVectorBase<SC> > f_out = outArgs.get_f();
986 const RCP<Thyra::LinearOpBase<SC> > W_out = outArgs.get_W_op();
987 const RCP<Thyra::PreconditionerBase<SC> > W_prec_out = outArgs.get_W_prec();
988
989 typedef Thyra::TpetraOperatorVectorExtraction<SC,LO,GO,NO> tpetra_extract;
990 typedef Tpetra::CrsMatrix<SC,LO,GO,NO> TpetraMatrix_Type;
991 typedef RCP<TpetraMatrix_Type> TpetraMatrixPtr_Type;
992 typedef RCP<const TpetraMatrix_Type> TpetraMatrixConstPtr_Type;
993
994 const bool fill_f = nonnull(f_out);
995 const bool fill_W = nonnull(W_out);
996 const bool fill_W_prec = nonnull(W_prec_out);
997
998 if ( fill_f || fill_W || fill_W_prec ) {
999
1000 // ****************
1001 // Get the underlying xpetra objects
1002 // ****************
1003 if (fill_f) {
1004
1005 this->calculateNonLinResidualVec( "standard", time_ );
1006
1007 BlockMultiVectorConstPtr_Type resConst = this->getResidualConst();
1008 BlockMultiVectorPtr_Type res = rcp_const_cast<BlockMultiVector_Type >(resConst);
1009
1010 Teuchos::RCP<Thyra::MultiVectorBase<SC> > f_thyra = res->getThyraMultiVector();
1011 f_out->assign(*f_thyra);
1012 }
1013
1014 TpetraMatrixPtr_Type W;
1015 if (fill_W) {
1016
1017 this->assemble("Newton");
1018
1019 this->setBoundariesSystem();
1020
1021 Teuchos::RCP<TpetraOp_Type> W_tpetra = tpetra_extract::getTpetraOperator(W_out);
1022 Teuchos::RCP<TpetraMatrix_Type> W_tpetraMat = Teuchos::rcp_dynamic_cast<TpetraMatrix_Type>(W_tpetra);
1023
1024 TpetraMatrixConstPtr_Type W_systemTpetra = this->getSystemCombined()->getMergedMatrix()->getTpetraMatrix();
1025 TpetraMatrixPtr_Type W_systemTpetraNonConst = rcp_const_cast<TpetraMatrix_Type>(W_systemTpetra);
1026
1027 //Tpetra::CrsMatrixWrap<SC,LO,GO,NO>& crsOp = dynamic_cast<Xpetra::CrsMatrixWrap<SC,LO,GO,NO>&>(*W_systemXpetraNonConst);
1028 //Xpetra::TpetraCrsMatrix<SC,LO,GO,NO>& xTpetraMat = dynamic_cast<Xpetra::TpetraCrsMatrix<SC,LO,GO,NO>&>(*crsOp.getCrsMatrix());
1029
1030 Teuchos::RCP<TpetraMatrix_Type> tpetraMatTpetra = W_systemTpetraNonConst; //xTpetraMat.getTpetra_CrsMatrixNonConst();
1031
1032 W_tpetraMat->resumeFill();
1033
1034 for (auto i=0; i<tpetraMatTpetra->getMap()->getLocalNumElements(); i++) {
1035 typename Tpetra::CrsMatrix<SC,LO,GO,NO>::local_inds_host_view_type indices; //ArrayView< const LO > indices
1036 typename Tpetra::CrsMatrix<SC,LO,GO,NO>::values_host_view_type values; //ArrayView< const LO > indices
1037 tpetraMatTpetra->getLocalRowView( i, indices, values);
1038 W_tpetraMat->replaceLocalValues( i, indices, values);
1039 }
1040 W_tpetraMat->fillComplete();
1041
1042 }
1043
1044 if (fill_W_prec) {
1045 this->problem_->setupPreconditioner( "Monolithic" );
1046
1047 // 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.
1048 // If this is the case, we need to pre apply the coarse level to the residual(f_out).
1049
1050 std::string levelCombination = this->parameterList_->sublist("ThyraPreconditioner").sublist("Preconditioner Types").sublist("FROSch").get("Level Combination","Additive");
1051 if (!levelCombination.compare("Multiplicative")) {
1052 TEUCHOS_TEST_FOR_EXCEPTION(true, std::logic_error, "Multiplicative Level Combination is not supported for NOX.");
1053 }
1054
1055 }
1056 }
1057}
1058
1059
1060template<class SC,class LO,class GO,class NO>
1061void TimeProblem<SC,LO,GO,NO>::evalModelImplBlock( const Thyra::ModelEvaluatorBase::InArgs<SC> &inArgs,
1062 const Thyra::ModelEvaluatorBase::OutArgs<SC> &outArgs ) const
1063{
1064
1065
1066 using Teuchos::RCP;
1067 using Teuchos::rcp;
1068 using Teuchos::rcp_dynamic_cast;
1069 using Teuchos::rcp_const_cast;
1070 using Teuchos::ArrayView;
1071 using Teuchos::Array;
1072
1073 TEUCHOS_TEST_FOR_EXCEPTION( inArgs.get_x().is_null(), std::logic_error, "inArgs.get_x() is null.");
1074
1075 RCP< const Thyra::VectorBase< SC > > vecThyra = inArgs.get_x();
1076
1077 RCP< Thyra::VectorBase< SC > > vecThyraNonConst = rcp_const_cast<Thyra::VectorBase< SC > >(vecThyra);
1078
1079 RCP< Thyra::ProductVectorBase< SC > > vecThyraBlock = rcp_dynamic_cast<Thyra::ProductVectorBase< SC > > (vecThyraNonConst);
1080 BlockMultiVectorConstPtr_Type solConst = this->getSolutionConst();
1081 BlockMultiVectorPtr_Type sol = rcp_const_cast<BlockMultiVector_Type >(solConst);
1082 for (int i=0; i<sol->size(); i++)
1083 sol->getBlockNonConst(i)->fromThyraMultiVector( vecThyraBlock->getNonconstVectorBlock(i) );
1084
1085 const RCP<Thyra::MultiVectorBase<SC> > f_out = outArgs.get_f();
1086 const RCP<Thyra::LinearOpBase<SC> > W_out = outArgs.get_W_op();
1087 const RCP<Thyra::PreconditionerBase<SC> > W_prec_out = outArgs.get_W_prec();
1088
1089 typedef Thyra::TpetraOperatorVectorExtraction<SC,LO,GO,NO> tpetra_extract;
1090 typedef Tpetra::CrsMatrix<SC,LO,GO,NO> TpetraMatrix_Type;
1091 typedef RCP<TpetraMatrix_Type> TpetraMatrixPtr_Type;
1092 typedef RCP<const TpetraMatrix_Type> TpetraMatrixConstPtr_Type;
1093
1094 const bool fill_f = nonnull(f_out);
1095 const bool fill_W = nonnull(W_out);
1096 const bool fill_W_prec = nonnull(W_prec_out);
1097
1098 if ( fill_f || fill_W || fill_W_prec ) {
1099
1100 // ****************
1101 // Get the underlying xpetra objects
1102 // ****************
1103 if (fill_f) {
1104
1105 this->calculateNonLinResidualVec("standard" , time_);
1106
1107 RCP< Thyra::ProductMultiVectorBase<SC> > f_outBlocks
1108 = rcp_dynamic_cast< Thyra::ProductMultiVectorBase<SC> > ( f_out );
1109
1110 BlockMultiVectorConstPtr_Type resConst = this->getResidualConst();
1111 BlockMultiVectorPtr_Type res = rcp_const_cast<BlockMultiVector_Type >(resConst);
1112
1113 for (int i=0; i<res->size(); i++) {
1114 RCP< Thyra::MultiVectorBase< SC > > res_i =
1115 res->getBlockNonConst(i)->getThyraMultiVector();
1116
1117 RCP< Thyra::MultiVectorBase< SC > > f_i = f_outBlocks->getNonconstMultiVectorBlock(i);
1118 f_i->assign(*res_i);
1119 }
1120 }
1121
1122 TpetraMatrixPtr_Type W;
1123 if (fill_W) {
1124
1125 typedef Tpetra::CrsMatrix<SC,LO,GO,NO> TpetraCrsMatrix;
1126
1127 this->assemble("Newton");
1128
1129 this->setBoundariesSystem();
1130
1131 RCP<ThyraBlockOp_Type> W_blocks = rcp_dynamic_cast<ThyraBlockOp_Type>(W_out);
1132
1133 BlockMatrixPtr_Type system = this->getSystemCombined();
1134
1135 for (int i=0; i<system->size(); i++) {
1136 for (int j=0; j<system->size(); j++) {
1137 if ( system->blockExists(i,j) ) {
1138 RCP<const ThyraOp_Type> W = W_blocks->getBlock(i,j);
1139 RCP<ThyraOp_Type> W_NonConst = rcp_const_cast<ThyraOp_Type>( W );
1140 RCP<TpetraOp_Type> W_tpetra = tpetra_extract::getTpetraOperator( W_NonConst );
1141 RCP<TpetraMatrix_Type> W_tpetraMat = Teuchos::rcp_dynamic_cast<TpetraMatrix_Type>(W_tpetra);
1142
1143 TpetraMatrixConstPtr_Type W_matrixTpetra = system->getBlock(i,j)->getTpetraMatrix();
1144 TpetraMatrixPtr_Type W_matrixTpetraNonConst = rcp_const_cast<TpetraMatrix_Type>(W_matrixTpetra);
1145
1146 //Xpetra::CrsMatrixWrap<SC,LO,GO,NO>& crsOp = dynamic_cast<Xpetra::CrsMatrixWrap<SC,LO,GO,NO>&>(*W_matrixXpetraNonConst);
1147 //Xpetra::TpetraCrsMatrix<SC,LO,GO,NO>& xTpetraMat = dynamic_cast<Xpetra::TpetraCrsMatrix<SC,LO,GO,NO>&>(*crsOp.getCrsMatrix());
1148
1149 RCP<TpetraMatrix_Type> tpetraMatTpetra = W_matrixTpetraNonConst;
1150
1151 W_tpetraMat->resumeFill();
1152
1153 for (auto i=0; i<tpetraMatTpetra->getMap()->getLocalNumElements(); i++) {
1154 typename Tpetra::CrsMatrix<SC,LO,GO,NO>::local_inds_host_view_type indices; //ArrayView< const LO > indices
1155 typename Tpetra::CrsMatrix<SC,LO,GO,NO>::values_host_view_type values; //ArrayView< const LO > indices
1156 tpetraMatTpetra->getLocalRowView( i, indices, values);
1157 W_tpetraMat->replaceLocalValues( i, indices, values);
1158 }
1159 W_tpetraMat->fillComplete( W_tpetraMat->getDomainMap(), W_tpetraMat->getRangeMap() );
1160 }
1161 }
1162 }
1163 }
1164
1165 if (fill_W_prec) {
1166 std::string type = this->parameterList_->sublist("General").get("Preconditioner Method","Monolithic");
1167 if (precInitOnly_)
1168 this->problem_->setupPreconditioner( type );
1169 else
1170 precInitOnly_ = true; // If a Teko preconditioner was constructed for the first time this variable is false. Because the preconditioner was not only initialized but already constructed. We can now set this variable to true to always setup all following preconditioners in the above if case
1171
1172 }
1173 }
1174}
1175template<class SC,class LO,class GO,class NO>
1176std::string TimeProblem<SC,LO,GO,NO>::description() const{ //reimplement description function and use description of underlying nonLinearProblem
1177 NonLinProbPtr_Type nonLinProb = Teuchos::rcp_dynamic_cast<NonLinProb_Type>(problem_);
1178 TEUCHOS_TEST_FOR_EXCEPTION(nonLinProb.is_null(), std::runtime_error, "Nonlinear problem is null.");
1179 return nonLinProb->description();
1180}
1181}
1182#endif
Adaptive Mesh Refinement.
Definition AdaptiveMeshRefinement.cpp:5