LifeV
NonLinearAitken.hpp
Go to the documentation of this file.
1 //@HEADER
2 /*
3 *******************************************************************************
4 
5  Copyright (C) 2004, 2005, 2007 EPFL, Politecnico di Milano, INRIA
6  Copyright (C) 2010 EPFL, Politecnico di Milano, Emory University
7 
8  This file is part of LifeV.
9 
10  LifeV is free software; you can redistribute it and/or modify
11  it under the terms of the GNU Lesser General Public License as published by
12  the Free Software Foundation, either version 3 of the License, or
13  (at your option) any later version.
14 
15  LifeV is distributed in the hope that it will be useful,
16  but WITHOUT ANY WARRANTY; without even the implied warranty of
17  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18  Lesser General Public License for more details.
19 
20  You should have received a copy of the GNU Lesser General Public License
21  along with LifeV. If not, see <http://www.gnu.org/licenses/>.
22 
23 *******************************************************************************
24 */
25 //@HEADER
26 
27 /*!
28  * @file
29  * @brief File containing the non-linear generalized Aitken algorithm
30  *
31  * @date 23-09-2004
32  * @author Simone Deparis <simone.deparis@epfl.ch>
33  * @author Gilles Fourestey <gilles.fourestey@epfl.ch>
34  * @author Cristiano Malossi <cristiano.malossi@epfl.ch>
35  *
36  * @maintainer Cristiano Malossi <cristiano.malossi@epfl.ch>
37  */
38 
39 #ifndef NonLinearAitken_H
40 #define NonLinearAitken_H
41 
42 
43 #include <array>
44 
45 
46 #include <lifev/core/LifeV.hpp>
47 #include <lifev/core/util/LifeDebug.hpp>
48 
49 namespace LifeV
50 {
51 
52 //! NonLinearAitken - LifeV class for the non-linear generalized Aitken algorithm
53 /*
54  * @author Simone Deparis, Gilles Fourestey, Cristiano Malossi
55  * @see S. Deparis, M. Discacciati and A. Quarteroni, A domain decompostion framework for fluid/structure interaction problems.
56  *
57  * Compute the acceleration with the vector variant of Aitken.
58  *
59  * TODO Modify computeDeltaLambdaFSI - we should have only one defaultOmega parameter
60  * to be more general, and the same for M_oldResidualSolid & M_oldResidualFluid.
61  */
62 template< typename VectorType >
64 {
65 
66 public:
67 
68  //! @name Public Types
69  //@{
70 
71  typedef VectorType vector_Type;
73 
74  //@}
75 
76 
77  //! @name Constructors & Destructor
78  //@{
79 
80  //! Constructor
81  explicit NonLinearAitken();
82 
83  //! Destructor
84  virtual ~NonLinearAitken() {}
85 
86  //@}
87 
88 
89  //! @name Methods
90  //@{
91 
92  //! Use default omega
93  /*!
94  * @param useDefaultOmega true: use always default Omega (relaxed fixed-point method)
95  */
96  void useDefaultOmega ( const bool useDefaultOmega = true )
97  {
98  M_useDefaultOmega = useDefaultOmega;
99  }
100 
101  //! Reinitialize Omega to the default value
102  void restart()
103  {
104  M_restart = true;
105  }
106 
107  //! Compute OmegaS * deltaRSolid + OmegaF * deltaRFluid
108  /*!
109  * @param solution - vector of unknown
110  * @param residualFluid - vector of residuals (Fluid for FSI problems)
111  * @param residualSolid - vector of residuals (Solid for FSI problems)
112  */
114  const vector_Type& residualFluid,
115  const vector_Type& residualSolid );
116 
117  //! Compute Omega * residual - Paragraph 4.2.3 & 4.2.4 of S. Deparis PhD Thesis
118  /*!
119  * @param solution - vector of unknown
120  * @param residual - vector of residuals
121  * @param invertedOmega - false (default): minimizing on omega; true: minimizing on omega^-1
122  */
124  const vector_Type& residual );
125 
126  //! Compute Omega * residual - Paragraph 4.2.6 of S. Deparis PhD Thesis
127  /*!
128  * @param solution - vector of unknown
129  * @param residual - vector of residuals
130  */
132  const vector_Type& residual,
133  const bool& independentOmega = false );
134 
135  //! Compute Omega * residual - Paragraph 4.2.6 of S. Deparis PhD Thesis
136  /*!
137  * @param solution - vector of unknown
138  * @param residual - vector of residuals
139  * @param blocksVector - vector identifying the different blocks ( ID start from 1 )
140  * @param blocksNumber - number of different blocks == higher ID (if = 1, it equal to the scalar case)
141  */
143  const vector_Type& residual,
144  const vector_Type& blocksVector,
145  const UInt& blocksNumber = 1);
146 
147  //@}
148 
149 
150  //! @name Set Methods
151  //@{
152 
153  //! Set starting values for Omega
154  /*!
155  * @param defaultOmegaFluid default value for the omega fluid parameter
156  * @param defaultOmegaSolid default value for the omega solid parameter
157  * if defaultOmegaFluid is negative, set M_useDefaultOmega equal true
158  */
159  void setDefaultOmega ( const Real& defaultOmegaFluid = 0.1, const Real& defaultOmegaSolid = 0.1 );
160 
161  //! Set the range of Omega.
162  /*!
163  * The range of Omega is defined as: OmegaMin < Omega < OmegaMax.
164  *
165  * @param omegaRange array with the minimum and the maximum of Omega
166  */
167  void setOmegaRange ( const std::array< Real, 2 >& omegaRange )
168  {
169  M_rangeOmega = omegaRange;
170  }
171 
172  //! Set the minimum of Omega.
173  /*!
174  * @param omegaMin minimum of Omega
175  */
176  void setOmegaMin ( const Real& omegaMin )
177  {
178  M_rangeOmega[0] = std::fabs ( omegaMin );
179  }
180 
181  //! Set the maximum of Omega.
182  /*!
183  * @param omegaMax maximum of Omega
184  */
185  void setOmegaMax ( const Real& omegaMax )
186  {
187  M_rangeOmega[1] = std::fabs ( omegaMax );
188  }
189 
190  //! Set minimization type.
191  /*!
192  * @param inverseOmega false: minimizing on omega; true: minimizing on omega^-1
193  */
194  void setMinimizationType ( const bool& inverseOmega )
195  {
196  M_inverseOmega = inverseOmega;
197  }
198 
199  //@}
200 
201 
202  //! @name Get Methods
203  //@{
204 
205  //! Get the default value of omega fluid.
206  /*!
207  * @return default value of omega fluid
208  */
209  const Real& defaultOmegaFluid() const
210  {
211  return M_defaultOmegaFluid;
212  }
213 
214  //! Get the default value of omega solid.
215  /*!
216  * @return default value of omega solid
217  */
218  const Real& defaultOmegaSolid() const
219  {
220  return M_defaultOmegaSolid;
221  }
222 
223  //@}
224 
225 private:
226 
227  //! @name Private unimplemented Methods
228  //@{
229 
230  NonLinearAitken ( const NonLinearAitken& aitken );
231 
232  NonLinearAitken& operator= ( const NonLinearAitken& aitken );
233 
234  //@}
235 
236 
237  //! @name Private Methods
238  //@{
239 
240  void checkRange ( Real& omega );
241 
242  //@}
243 
244  // fluid/structure interface dof count
245  vectorPtr_Type M_oldSolution; // \lambda^{k - 1}
248 
249  // defaults \omega_s and \omega_f
252 
253  // first time call boolean
254  bool M_restart;
255 
256  // If default omega is negative, then always use the
257  // absolute value of the default omega.
258  // In this case M_usedefault=true
260 
261  // The max & min values for Omega
263 
264  // Minimize on omega or omega^-1
266 };
267 
268 
269 
270 // ===================================================
271 // Constructors
272 // ===================================================
273 template < class VectorType >
275  M_oldSolution ( ),
276  M_oldResidualFluid ( ),
277  M_oldResidualSolid ( ),
278  M_defaultOmegaFluid ( 0.1 ),
279  M_defaultOmegaSolid ( 0.1 ),
280  M_restart ( true ),
281  M_useDefaultOmega ( false ),
282  M_rangeOmega ( ),
283  M_inverseOmega ( false )
284 {
285  // Initializing the array
286  M_rangeOmega[0] = 0.;
287  M_rangeOmega[1] = 0.;
288 }
289 
290 // ===================================================
291 // Methods
292 // ===================================================
293 template < class VectorType >
294 typename NonLinearAitken< VectorType >::vector_Type
295 NonLinearAitken< VectorType >::computeDeltaLambdaFSI ( const vector_Type& solution,
296  const vector_Type& residualFluid,
297  const vector_Type& residualSolid )
298 {
299  if ( M_restart || M_useDefaultOmega )
300  {
301  M_restart = false;
302 
303  M_oldSolution.reset ( new vector_Type ( solution ) );
304  M_oldResidualSolid.reset ( new vector_Type ( residualSolid ) );
305  M_oldResidualFluid.reset ( new vector_Type ( residualFluid) );
306 
307 #ifdef HAVE_LIFEV_DEBUG
308  debugStream (7020) << "NonLinearAitken: omegaFluid = " << M_defaultOmegaFluid << " omegaSolid = " << M_defaultOmegaSolid << "\n";
309 #endif
310  return M_defaultOmegaFluid * residualFluid + M_defaultOmegaSolid * residualSolid;
311  }
312  else
313  {
314  Real deltaRSolid ( residualSolid - M_oldResidualSolid );
315  Real deltaRFluid ( residualFluid - M_oldResidualFluid );
316 
317  Real a11 = deltaRFluid * deltaRFluid;
318  Real a21 = deltaRFluid * deltaRSolid;
319  Real a22 = deltaRSolid * deltaRSolid;
320 
321  Real b1 = deltaRFluid * ( solution - *M_oldSolution);
322  Real b2 = deltaRSolid * ( solution - *M_oldSolution);
323 
324  Real det ( a22 * a11 - a21 * a21 );
325 
326  Real omegaFluid ( M_defaultOmegaFluid );
327  Real omegaSolid ( M_defaultOmegaSolid );
328 
329  if ( std::fabs ( det ) != 0. ) //! eq. (12) page 8
330  {
331  omegaFluid = - ( a22 * b1 - a21 * b2 ) / det;
332  omegaSolid = - ( a11 * b2 - a21 * b1 ) / det;
333 
334  if ( omegaFluid == 0. )
335  {
336  omegaFluid = M_defaultOmegaFluid;
337  }
338 
339  if ( omegaSolid == 0. )
340  {
341  omegaSolid = M_defaultOmegaSolid;
342  }
343  }
344  else if ( std::fabs ( a22 ) == 0. )
345  {
346 #ifdef HAVE_LIFEV_DEBUG
347  debugStream (7020) << "NonLinearAitken: a22 = " << std::fabs (a22) << "\n";
348 #endif
349  omegaFluid = -b1 / a11;
350  omegaSolid = 0.;
351  }
352  else if ( std::fabs (a11) == 0. )
353  {
354 #ifdef HAVE_LIFEV_DEBUG
355  debugStream (7020) << "NonLinearAitken: a11 = " << std::fabs (a11) << "\n";
356 #endif
357  omegaFluid = 0.;
358  omegaSolid = -b2 / a22;
359  }
360 #ifdef HAVE_LIFEV_DEBUG
361  else
362  {
363  debugStream (7020) << "NonLinearAitken: Failure: Det=0!!" << std::fabs (det) << "\n";
364  }
365 
366  debugStream (7020) << " --------------- NonLinearAitken: \n";
367  debugStream (7020) << " omegaSolid = " << omegaSolid << " omegaFluid = " << omegaFluid << "\n";
368 #endif
369 
370  *M_oldSolution = solution;
371  *M_oldResidualFluid = residualFluid;
372  *M_oldResidualSolid = residualSolid;
373 
374  return omegaFluid * residualFluid + omegaSolid * residualSolid;
375  }
376 }
377 
378 /*! one parameter version of the generalized aitken method. cf page 85 S. Deparis, PhD thesis */
379 template < class VectorType >
380 typename NonLinearAitken< VectorType >::vector_Type
381 NonLinearAitken< VectorType >::computeDeltaLambdaScalar ( const vector_Type& solution,
382  const vector_Type& residual )
383 {
384  if ( M_restart || M_useDefaultOmega )
385  {
386  M_restart = false;
387 
388  M_oldSolution.reset ( new vector_Type ( solution ) );
389  M_oldResidualFluid.reset ( new vector_Type ( residual ) );
390 
391 #ifdef HAVE_LIFEV_DEBUG
392  debugStream (7020) << "NonLinearAitken: omega = " << M_defaultOmegaFluid << "\n";
393 #endif
394 
395  return M_defaultOmegaFluid * residual;
396  }
397 
398  vector_Type deltaX ( solution );
399  vector_Type deltaR ( residual );
400 
401  deltaX -= *M_oldSolution;
402  deltaR -= *M_oldResidualFluid;
403 
404  *M_oldSolution = solution;
405  *M_oldResidualFluid = residual;
406 
407  Real omega, norm;
408  if ( M_inverseOmega )
409  {
410  // Minimization of the inverse omega
411  omega = deltaX.dot ( deltaX );
412  norm = deltaR.dot ( deltaX );
413  }
414  else
415  {
416  //Minimization of the original omega
417  omega = deltaX.dot ( deltaR );
418  norm = deltaR.dot ( deltaR );
419  }
420 
421  omega = - omega / norm ;
422 
423  //Check omega limits
424  checkRange (omega);
425 
426 #ifdef HAVE_LIFEV_DEBUG
427  debugStream (7020) << "NonLinearAitken: omega = " << omega << "\n";
428 #endif
429 
430  return omega * residual;
431 }
432 
433 template < class VectorType >
434 typename NonLinearAitken< VectorType >::vector_Type
435 NonLinearAitken< VectorType >::computeDeltaLambdaVector ( const vector_Type& solution,
436  const vector_Type& residual,
437  const bool& independentOmega )
438 {
439  if ( M_restart || M_useDefaultOmega )
440  {
441  M_restart = false;
442 
443  M_oldSolution.reset ( new vector_Type ( solution ) );
444  M_oldResidualFluid.reset ( new vector_Type ( residual ) );
445 
446 #ifdef HAVE_LIFEV_DEBUG
447  debugStream (7020) << "NonLinearAitken: omega = " << M_defaultOmegaFluid << "\n";
448 #endif
449 
450  return M_defaultOmegaFluid * residual;
451  }
452 
453  vector_Type deltaX ( solution );
454  vector_Type deltaR ( residual );
455 
456  deltaX -= *M_oldSolution;
457  deltaR -= *M_oldResidualFluid;
458 
459  *M_oldSolution = solution;
460  *M_oldResidualFluid = residual;
461 
462  vector_Type omega ( deltaX );
463  Real norm = 1;
464  if ( independentOmega )
465  {
466  deltaR += !deltaR; // add +1 where deltaR is equal to zero!
467  omega /= deltaR;
468  }
469  else if ( M_inverseOmega )
470  {
471  omega *= deltaX;
472  norm = deltaR.dot ( deltaX );
473  }
474  else
475  {
476  omega *= deltaR;
477  norm = deltaR.dot ( deltaR );
478  }
479 
480  omega /= -norm;
481 
482  //Check omega limits
483  for ( UInt i (0) ; i < static_cast<UInt> ( omega.size() ) ; ++i )
484  {
485  checkRange (omega[i]);
486  }
487 
488 #ifdef HAVE_LIFEV_DEBUG
489  debugStream (7020) << "NonLinearAitken: omega = " << "\n";
490  omega.showMe();
491 #endif
492 
493  omega *= residual;
494 
495  return omega;
496 }
497 
498 template < class VectorType >
499 typename NonLinearAitken< VectorType >::vector_Type
501  const vector_Type& residual,
502  const vector_Type& blocksVector,
503  const UInt& blocksNumber )
504 {
505  if ( M_restart || M_useDefaultOmega )
506  {
507  M_restart = false;
508 
509  M_oldSolution.reset ( new vector_Type ( solution ) );
510  M_oldResidualFluid.reset ( new vector_Type ( residual ) );
511 
512 #ifdef HAVE_LIFEV_DEBUG
513  debugStream (7020) << "NonLinearAitken: omega = " << M_defaultOmegaFluid << "\n";
514 #endif
515 
516  return M_defaultOmegaFluid * residual;
517  }
518 
519  vector_Type deltaX ( solution );
520  vector_Type deltaR ( residual );
521 
522  deltaX -= *M_oldSolution;
523  deltaR -= *M_oldResidualFluid;
524 
525  *M_oldSolution = solution;
526  *M_oldResidualFluid = residual;
527 
528  vector_Type omega ( deltaX );
529  omega = 0.0;
530  Real tempOmega = 0;
531 
532  vector_Type tempVector ( blocksVector );
533  vector_Type tempDeltaX ( deltaX );
534  vector_Type tempDeltaR ( deltaR );
535 
536  for ( UInt i = 0 ; i < blocksNumber ; ++i )
537  {
538  tempVector = blocksVector - i;
539  tempVector = !tempVector;
540 
541  tempDeltaX = deltaX;
542  tempDeltaX *= tempVector;
543 
544  tempDeltaR = deltaR;
545  tempDeltaR *= tempVector;
546 
547  if ( M_inverseOmega )
548  {
549  // Minimization of the inverse omega
550  tempOmega = - ( tempDeltaX.Dot ( tempDeltaX ) ) / ( tempDeltaR.Dot ( tempDeltaX ) );
551  }
552  else
553  {
554  //Minimization of the original omega
555  tempOmega = - ( tempDeltaX.Dot ( tempDeltaR ) ) / ( tempDeltaR.Dot ( tempDeltaR ) );
556  }
557 
558  //Check omega limits
559  checkRange (tempOmega);
560 
561  omega += tempOmega * tempVector;
562  }
563 
564 #ifdef HAVE_LIFEV_DEBUG
565  debugStream (7020) << "NonLinearAitken: omega = " << "\n";
566  omega.ShowMe();
567 #endif
568 
569  return omega * residual;
570 }
571 
572 // ===================================================
573 // Set Methods
574 // ===================================================
575 template < class VectorType >
576 inline void
577 NonLinearAitken< VectorType >::setDefaultOmega ( const Real& defaultOmegaFluid, const Real& defaultOmegaSolid )
578 {
579  M_defaultOmegaFluid = defaultOmegaFluid;
580  M_defaultOmegaSolid = defaultOmegaSolid;
581 
582  if (M_defaultOmegaFluid < 0 )
583  {
584  M_useDefaultOmega = true;
585  }
586 }
587 
588 // ===================================================
589 // Private Methods
590 // ===================================================
591 template < class VectorType >
592 inline void
593 NonLinearAitken< VectorType >::checkRange ( Real& omega )
594 {
595  //The division and multiplication is to make the range of Omega
596  //bigger. This changes was introduce in order to improve the convergence
597  //of the fsi_segregated solver using fixed point method for Dirichlet-Neumann
598  if ( std::fabs (omega) < std::fabs (M_rangeOmega[0]) / 1024. )
599  {
600  if ( omega < 0 )
601  {
602  omega = -M_rangeOmega[0];
603  }
604  else
605  {
606  omega = M_rangeOmega[0];
607  }
608  }
609  else if ( std::fabs (omega) > std::fabs (M_rangeOmega[1]) * 1024. )
610  {
611  if ( omega < 0 )
612  {
613  omega = -M_rangeOmega[1];
614  }
615  else
616  {
617  omega = M_rangeOmega[1];
618  }
619  }
620 }
621 
622 } // end namespace LifeV
623 
624 #endif // NonLinearAitken_H
void setOmegaMin(const Real &omegaMin)
Set the minimum of Omega.
vectorPtr_Type M_oldSolution
NonLinearAitken()
Constructor.
virtual ~NonLinearAitken()
Destructor.
void restart()
Reinitialize Omega to the default value.
vector_Type computeDeltaLambdaVectorBlock(const vector_Type &solution, const vector_Type &residual, const vector_Type &blocksVector, const UInt &blocksNumber=1)
Compute Omega * residual - Paragraph 4.2.6 of S. Deparis PhD Thesis.
const Real & defaultOmegaFluid() const
Get the default value of omega fluid.
void setMinimizationType(const bool &inverseOmega)
Set minimization type.
vector_Type computeDeltaLambdaFSI(const vector_Type &solution, const vector_Type &residualFluid, const vector_Type &residualSolid)
Compute OmegaS * deltaRSolid + OmegaF * deltaRFluid.
std::array< Real, 2 > M_rangeOmega
void checkRange(Real &omega)
NonLinearAitken & operator=(const NonLinearAitken &aitken)
void useDefaultOmega(const bool useDefaultOmega=true)
Use default omega.
vector_Type computeDeltaLambdaVector(const vector_Type &solution, const vector_Type &residual, const bool &independentOmega=false)
Compute Omega * residual - Paragraph 4.2.6 of S. Deparis PhD Thesis.
vectorPtr_Type M_oldResidualFluid
NonLinearAitken - LifeV class for the non-linear generalized Aitken algorithm.
std::shared_ptr< vector_Type > vectorPtr_Type
double Real
Generic real data.
Definition: LifeV.hpp:175
vector_Type computeDeltaLambdaScalar(const vector_Type &solution, const vector_Type &residual)
Compute Omega * residual - Paragraph 4.2.3 & 4.2.4 of S. Deparis PhD Thesis.
void setOmegaRange(const std::array< Real, 2 > &omegaRange)
Set the range of Omega.
NonLinearAitken(const NonLinearAitken &aitken)
const Real & defaultOmegaSolid() const
Get the default value of omega solid.
uint32_type UInt
generic unsigned integer (used mainly for addressing)
Definition: LifeV.hpp:191
void setDefaultOmega(const Real &defaultOmegaFluid=0.1, const Real &defaultOmegaSolid=0.1)
Set starting values for Omega.
vectorPtr_Type M_oldResidualSolid
void setOmegaMax(const Real &omegaMax)
Set the maximum of Omega.