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