Chombo + EB  3.0
MultiGrid.H
Go to the documentation of this file.
1 #ifdef CH_LANG_CC
2 /*
3  * _______ __
4  * / ___/ / ___ __ _ / / ___
5  * / /__/ _ \/ _ \/ V \/ _ \/ _ \
6  * \___/_//_/\___/_/_/_/_.__/\___/
7  * Please refer to Copyright.txt, in Chombo's root directory.
8  */
9 #endif
10 
11 // BVS, June 18, 2003
12 
13 // We can assume that template class T has null construction.
14 
15 #ifndef _MULTIGRID_H_
16 #define _MULTIGRID_H_
17 
18 #include "CH_Timer.H"
19 #include "LinearSolver.H"
20 #include "ProblemDomain.H"
21 #include "REAL.H"
22 #include "Box.H"
23 #include "parstream.H"
24 #include "RefCountedPtr.H"
25 #include <vector>
26 #include "NamespaceHeader.H"
27 
28 // Forward declaration of MGLevelOp.
29 template <typename T>
30 class MGLevelOp;
31 
32 //! \class MGLevelOpObserver
33 //! This observer class allows objects to be notified when coefficient
34 //! data for an operator changes.
35 template <typename T>
37 {
38  public:
39 
40  //! Base level Constructor. Called by all subclasses.
42  :m_op(NULL)
43  {
44  }
45 
46  //! Destructor.
47  virtual ~MGLevelOpObserver();
48 
49  //! Use this to implement the response of the observer to changes
50  //! in the observee.
51  //! \param a_operator The operator whose state has changed. Passed to
52  //! the observer by the operator itself.
53  virtual void operatorChanged(const MGLevelOp<T>& a_operator)
54  {
55  }
56 
57  //! This gets called by the observee when this observer is added to it.
58  //! DO NOT CALL THIS METHOD DIRECTLY.
59  //! \param a_observee The object being observed by this observer.
60  void setObservee(MGLevelOp<T>* a_observee)
61  {
62  CH_assert(m_op == NULL);
63  m_op = a_observee;
64  }
65 
66  //! This gets called by the observee when it is destroyed.
67  //! DO NOT CALL THIS METHOD DIRECTLY.
69  {
70  m_op = NULL;
71  }
72 
73  private:
74 
75  // A pointer to the observed operator.
77 
78  // Forbidden ops.
81 };
82 
83 //! \class MGLevelOp
84 //! This class handles the additional tasks of coordinating operations
85 //! between this level and the level one coarser than this 'level'.
86 //! This class is also an MGLevelOpObserver, so objects of this type can
87 //! observe other MGLevelOp objects.
88 template <typename T>
89 class MGLevelOp : public LinearOp<T>, public MGLevelOpObserver<T>
90 {
91  public:
92 
93  //! Constructor.
95  :LinearOp<T>(),
96  MGLevelOpObserver<T>(),
97  m_observers(),
98  m_coarseningFactors()
99  {
100  }
101 
102  //! Destructor.
103  virtual ~MGLevelOp()
104  {
105  // Go through the list of observers and clear their observees.
106  for (size_t i = 0; i < m_observers.size(); ++i)
107  m_observers[i]->clearObservee();
108  }
109 
110  ///
111  /**
112  Create a coarsened (by two) version of the input data. This does not include averaging
113  the data. So if a_fine is over a Box of (0, 0, 0) (63, 63, 63), a_fine should
114  be over a Box (0, 0, 0) (31, 31, 31).
115  */
116  virtual void createCoarser(T& a_coarse, const T& a_fine, bool ghosted) = 0;
117 
118  ///
119  /**
120  Use your relaxtion operator to remove the high frequency wave numbers from
121  the correction so that it may be averaged to a coarser refinement.
122  A point relaxtion scheme, for example takes the form
123  a_correction -= lambda*(L(a_correction) - a_residual).
124  */
125  virtual void relax(T& a_correction, const T& a_residual, int a_iterations) = 0 ;
126 
127 
128  ///
129  /**
130  calculate restricted residual
131  a_resCoarse[2h] = I[h->2h] (rhsFine[h] - L[h](phiFine[h])
132  */
133  virtual void restrictResidual(T& a_resCoarse, T& a_phiFine, const T& a_rhsFine) = 0;
134 
135  ///
136  /**
137  correct the fine solution based on coarse correction
138  a_phiThisLevel += I[2h->h](a_correctCoarse)
139  */
140  virtual void prolongIncrement(T& a_phiThisLevel, const T& a_correctCoarse) = 0;
141 
142  //! This adds a new observer to this operator. Note that this operator does not
143  //! own the resources for the observer, so you must be careful to ensure that
144  //! the observer does not go out of scope while the operator lives. If the observer
145  //! is already observing the operator, this operation has no effect.
146  //! \param a_observer An observer to be notified when the operator changes.
148  {
149  if (std::find(m_observers.begin(), m_observers.end(), a_observer) == m_observers.end())
150  {
151  m_observers.push_back(a_observer);
152  m_coarseningFactors.push_back(-1);
153  a_observer->setObservee(this);
154  }
155  }
156 
157  //! Removes the given observer from the operator's list of observers. This
158  //! method has no effect if the observer is not found in the list.
159  //! \param a_observer An observer to be removed from the operator's observer list.
161  {
162  typename std::vector<MGLevelOpObserver<T>*>::iterator iter =
163  std::find(m_observers.begin(), m_observers.end(), a_observer);
164  if (iter != m_observers.end())
165  {
166  (*iter)->clearObservee();
167  m_observers.erase(iter);
168  // Remove the coarsening factor entry, too.
169  size_t index = std::distance(m_observers.begin(), iter);
170  m_coarseningFactors.erase(m_coarseningFactors.begin() + index);
171  }
172  }
173 
174  //! Adds a MGLevelOp observer to this operator that is notified when the
175  //! operator changes so that it can coarsen its corresponding data. This
176  //! is used to implement dependencies between multigrid operators at different
177  //! grid levels.
178  //! \param a_operator The multigrid operator that will observe this operator.
179  //! No operator may observe itself. If \a a_operator is
180  //! already observing this operator, this method has no
181  //! effect.
182  //! \param a_coarseningFactor The refinement factor between the grid
183  //! level for \a a_operator and that for this one.
185  int a_coarseningFactor)
186  {
187  CH_assert(a_operator != NULL);
188  CH_assert(a_operator != this);
189  // Add the operator to the list of observers.
190  if (std::find(m_observers.begin(), m_observers.end(), a_operator) == m_observers.end())
191  {
192  // Add the operator to our list of observers.
193  addObserver(a_operator);
194 
195  // Jot down this operator's multigrid coarsening factor.
196  m_coarseningFactors.back() = a_coarseningFactor;
197  }
198  }
199 
200  //! This should be called whenever the operator's data is updated.
202  {
203  //! Notify our observers that the operator's data has changed,
204  //! taking special care to pass multigrid operators their
205  //! level.
206  for (int i = 0; i < m_observers.size(); ++i)
207  {
208  if (m_coarseningFactors[i] != -1)
209  {
210  MGLevelOp<T>* op = dynamic_cast<MGLevelOp<T>*>(m_observers[i]);
211  CH_assert(op != NULL);
212  // This observer is a multigrid operator. Pass it its grid level.
213  op->finerOperatorChanged(*this, m_coarseningFactors[i]);
214  }
215  else
216  {
217  // Simply tell it that its operator has changed.
218  m_observers[i]->operatorChanged(*this);
219  }
220  }
221  }
222 
223  //! Overload this method to implement the response of a multigrid
224  //! operator to a change in a finer operator that it is observing. This
225  //! allows the coarser observer to coarsen any data that has been changed
226  //! in the finer operator.
227  //! \param a_operator The operator whose state has changed.
228  //! \param a_coarseningFactor The factor by which this operator's data is
229  //! coarsened with respect to that of \a a_operator.
230  virtual void finerOperatorChanged(const MGLevelOp<T>& a_operator,
231  int a_coarseningFactor)
232  {
233  }
234 
235  //! Returns the number of objects observing this operator.
236  int numObservers() const
237  {
238  return m_observers.size();
239  }
240 
241  private:
242 
243  //! List of observers for the operator.
244  std::vector<MGLevelOpObserver<T>*> m_observers;
245 
246  //! Multigrid coarsening factors.
247  std::vector<int> m_coarseningFactors;
248 
249  // Forbidden operations.
250  MGLevelOp(const MGLevelOp&);
251  MGLevelOp& operator=(const MGLevelOp&);
252 };
253 
254 ///
255 /**
256  Factory class for generating MGLevelOps
257  */
258 template <class T>
260 {
261  public:
262 
263  //! Base class constructor.
265  {
266  }
267 
268  //! Destructor.
270  {
271  }
272 
273  /**
274  Create an operator at an index space = coarsen(a_fineIndexSpace, 2^a_depth)
275  Return NULL if no such Multigrid level can be created at this a_depth.
276  If a_homoOnly = true, then only homogeneous boundary conditions will be needed.
277  */
278  virtual MGLevelOp<T>* MGnewOp(const ProblemDomain& a_FineindexSpace,
279  int a_depth,
280  bool a_homoOnly = true) = 0;
281 
282  private:
283 
284  // Forbidden operations.
287 };
288 
289 ///
290 /**
291  Class to execute geometric multigrid. This class is not meant to be particularly
292  user-friendly and a good option for people who want something a tad less raw is to
293  use AMRMultiGrid instead.
294  */
295 template <class T>
297 {
298 public:
299  MultiGrid();
300  virtual ~MultiGrid();
301 
302  /// Function to define a MultiGrid object.
303  /**
304  a_factory is the factory for generating operators.
305  a_bottomSolver is called at the bottom of v-cycle.
306  a_domain is the problem domain at the top of the vcycle.
307  maxDepth defines the location of the bottom of the v-cycle.
308  The vycle will terminate (hit bottom) when the factory returns NULL for a paticular
309  depth if maxdepth = -1. Otherwise the vycle terminates at maxdepth.
310  */
311  virtual void define(MGLevelOpFactory<T>& a_factory,
312  LinearSolver<T>* a_bottomSolver,
313  const ProblemDomain& a_domain,
314  int a_maxDepth = -1,
315  MGLevelOp<T>* a_finestLevelOp = NULL);
316 
317  ///
318  /**
319  solve L(a_phi) = a_rhs. Tolerance is how much you want the norm of the error reduced.
320  verbosity is how chatty you want the function to be. maxIterations is the maximum number
321  of v-cycles. This does the whole residual correction switcharoo and calls oneCycle up to
322  maxIterations times, evaluating the residual as it goes.
323  */
324  virtual void solve(T& a_phi, const T& a_rhs, Real a_tolerance, int a_maxIterations, int verbosity= 0);
325 
326  /// Execute ONE v-cycle of multigrid.
327  /**
328  If you want the solution to converge, you need to iterate this.
329  See solve() or AMRMultiGrid::solve for a more automatic solve() function.
330  This operates residual-correction form of solution
331  so all boundary conditions are assumed to be homogeneous.
332  L(a_e) = a_res
333  */
334  virtual void oneCycle(T& a_e, const T& a_res);
335 
336 
337  // used by AMRMultiGrid--not a part of the public API
338  void init(const T& a_correction, const T& a_residual);
339 
340  //internal function
341  void cycle(int a_depth, T& a_correction, const T& a_residual);
342 
343  //internal function
344  void clear();
345 
346  // used by AMRMultiGrid--not a part of the public API
347  void setBottomSolver(LinearSolver<T>* a_bottomSolver);
348 
349  ///
350  /**
351  Public solver parameters. m_pre and m_post are the ones
352  that usually get set and are the number of relaxations performed
353  before and after multigrid recursion. See AMRMultiGrid for a
354  more user-friendly interface.
355  */
356  int m_depth, m_defaultDepth, m_pre, m_post, m_bottom, m_cycle, m_numMG;
359 
360  ///
361  /**
362  for changing coefficients --- not for the faint of heart.
363  */
364  Vector< MGLevelOp<T>* > getAllOperators();
365 
366 protected:
367  bool m_defined;
368 
370 
375  std::vector<bool> m_ownOp;
376 
377 private:
378  MultiGrid(const MultiGrid<T>& a_opin)
379  {
380  MayDay::Error("invalid operator");
381  }
382 
383  void operator=(const MultiGrid<T>& a_opin)
384  {
385  MayDay::Error("invalid operator");
386  }
387 };
388 
389 // *******************************************************
390 // MultiGrid Implementation
391 // *******************************************************
392 
393 //-----------------------------------------------------------------------
394 template <class T>
397 {
398  Vector<MGLevelOp<T>*> retval = m_op;
399  return retval;
400 }
401 //-----------------------------------------------------------------------
402 
403 //-----------------------------------------------------------------------
404 template <class T>
406  :m_pre(3),
407  m_post(3),
408  m_bottom(0),
409  m_cycle(1),
410  m_numMG(1),
411  m_homogeneous(true),
412  m_defined(false)
413 {
414 }
415 //-----------------------------------------------------------------------
416 
417 //-----------------------------------------------------------------------
418 template <class T>
420 {
421  clear();
422 }
423 //-----------------------------------------------------------------------
424 
425 //-----------------------------------------------------------------------
426 template <class T>
428  LinearSolver<T>* a_bottomSolver,
429  const ProblemDomain& a_domain,
430  int a_maxDepth,
431  MGLevelOp<T>* a_finestOp)
432 {
433 
434  CH_TIME("MultiGrid::define");
435  clear();
436  m_depth = 0;
437  m_bottomSolver = a_bottomSolver;
438  m_residual.resize(m_depth); // the zero'th entry is left null constructed
439  m_correction.resize(m_depth); // the zero'th entry is left null constructed
441  m_ownOp.resize(0);
442  m_topLevelDomain = a_domain;
443 
444  m_bottomCells = a_domain.domainBox().numPts();
445 
446  MGLevelOp<T>* nextOp;
447  bool ownOp;
448  if (a_finestOp == NULL)
449  {
450  nextOp = a_factory.MGnewOp(a_domain, 0, true);
451  ownOp = true;
452  }
453  else
454  {
455  nextOp = a_finestOp;
456  ownOp = false;
457  }
458  while (nextOp != NULL)
459  {
460  m_residual.push_back(new T());
461  m_correction.push_back(new T());
462  m_op.push_back(nextOp);
463  m_ownOp.push_back(ownOp);
464  m_depth++;
465  if ((m_depth < a_maxDepth) || (a_maxDepth < 0))
466  {
467  // Create a coarser multigrid operator.
468  nextOp = a_factory.MGnewOp(a_domain , m_depth, true);
469  ownOp = true;
470  if (nextOp != NULL)
471  {
472  // This multigrid operator should observe the next finer operator. -JNJ
473  // NOTE: the coarsening ratio is hardwired to 2 here.
474  m_op.back()->addCoarserObserver(nextOp, 2);
475  for (int i=0; i<CH_SPACEDIM; ++i) m_bottomCells /= 2;
476  }
477  }
478  else
479  {
480  nextOp = NULL;
481  }
482  }
484  m_bottomSolver->define(m_op[m_depth-1], true);
485  m_defined = true;
486 }
487 //-----------------------------------------------------------------------
488 
489 //-----------------------------------------------------------------------
490 template <class T>
492 {
493  m_bottomSolver = a_bottomSolver;
494  m_bottomSolver->define(m_op[m_depth-1], true);
495 }
496 //-----------------------------------------------------------------------
497 
498 //-----------------------------------------------------------------------
499 template <class T>
500 void MultiGrid<T>::init(const T& a_e, const T& a_residual)
501 {
502  CH_TIME("MutliGrid::init");
503  if (m_depth > 1)
504  {
505  m_op[0]->createCoarser(*(m_residual[1]), a_residual, false);
506  m_op[0]->createCoarser(*(m_correction[1]), a_e, true);
507  }
508 
509  for (int i = 2; i < m_depth; i++)
510  {
511  m_op[i-1]->createCoarser(*(m_residual[i]), *(m_residual[i-1]), false);
512  m_op[i-1]->createCoarser(*(m_correction[i]), *(m_correction[i-1]), true);
513  }
514 }
515 //-----------------------------------------------------------------------
516 
517 //-----------------------------------------------------------------------
518 template <class T>
519 void MultiGrid<T>::solve(T& a_phi, const T& a_rhs, Real a_tolerance, int a_maxIterations, int verbosity)
520 {
521  CH_TIME("MultiGrid::solve");
522  this->init(a_phi, a_rhs);
523 
524  T correction, residual;
525  m_op[0]->create(correction, a_phi);
526  m_op[0]->create(residual, a_rhs);
527  m_op[0]->setToZero(a_phi);
528  m_op[0]->residual(residual, a_phi, a_rhs, false);
529 
530  Real errorno = m_op[0]->norm(residual, 0);
531  if (verbosity > 2)
532  {
533  pout() << "multigrid::solve initial residual = " << errorno << std::endl;
534  }
535  Real compval = a_tolerance*errorno;
536  Real epsilon = 1.0e-16;
537  compval = Max(compval, epsilon);
538  Real error = errorno;
539  int iter = 0;
540  while ((error > compval) && (error > a_tolerance*errorno) && (iter < a_maxIterations))
541  {
542  m_op[0]->setToZero(correction);
543  m_op[0]->residual(residual, a_phi, a_rhs, false);
544  error = m_op[0]->norm(residual, 0);
545  if (verbosity > 3)
546  {
547  pout() << "multigrid::solve iter = " << iter << ", residual = " << error << std::endl;
548  }
549 
550  this->cycle(0, correction, residual);
551  m_op[0]->incr(a_phi, correction, 1.0);
552 
553  iter++;
554  }
555  if (verbosity > 2)
556  {
557  pout() << "multigrid::solve final residual = " << error << std::endl;
558  }
559 
560  m_op[0]->clear(correction);
561  m_op[0]->clear(residual);
562 }
563 //-----------------------------------------------------------------------
564 
565 //-----------------------------------------------------------------------
566 template <class T>
567 void MultiGrid<T>::oneCycle(T& a_e, const T& a_residual)
568 {
569  CH_TIME("Multigrid::oneCycle");
570 
571  //this->init(a_e, a_residual); oneCycle is only used by AMRMultigrid
572  if (m_homogeneous)
573  {
574  cycle(0, a_e, a_residual);
575  }
576  else
577  {
578  T correction, residual;
579  m_op[0]->create(correction, a_e);
580  m_op[0]->create(residual, a_residual);
581 
582  m_op[0]->residual(residual, a_e, a_residual);
583 
584  m_op[0]->setToZero(correction);
585  this->cycle(0, correction, residual);
586 
587  m_op[0]->incr(a_e, correction, 1.0);
588  m_op[0]->clear(correction);
589  m_op[0]->clear(residual);
590  }
591 }
592 //-----------------------------------------------------------------------
593 
594 //-----------------------------------------------------------------------
595 template <class T>
596 void MultiGrid<T>::cycle(int depth, T& correction, const T& residual)
597 {
598  CH_TIME("Multigrid::cycle");
599 
600  // currently I can't drop a timer in this function because it is recursive. doh
601  if (depth == m_depth-1)
602  {
603  if (m_bottomCells == 1)
604  {
605  m_op[depth ]->relax(correction, residual, 1);
606  }
607  else
608  {
609  m_op[depth ]->relax(correction, residual, m_bottom);
610  m_bottomSolver->solve(correction, residual);
611  }
612  //m_op[depth ]->relax(correction, residual, 1);
613  }
614  else
615  {
616  int cycles = m_cycle;
617  if ( cycles < 0 )
618  {
619  cycles = -cycles;
620  // F cycle multigrid
621  m_op[depth ]->restrictResidual(*(m_residual[depth+1]), correction, residual);
622  m_op[depth ]->setToZero(*(m_correction[depth+1]));
623 
624  // recursive call
625  cycle(depth+1, *(m_correction[depth+1]), *(m_residual[depth+1]));
626 
627  m_op[depth ]->prolongIncrement(correction, *(m_correction[depth+1]));
628 
629  m_op[depth ]->relax(correction, residual, m_pre);
630 
631  for (int img = 0; img < cycles; img++)
632  {
633  m_op[depth ]->restrictResidual(*(m_residual[depth+1]), correction, residual);
634  m_op[depth ]->setToZero(*(m_correction[depth+1]));
635 
636  m_cycle = 1; // hack to get a V-cycle
637  cycle(depth+1, *(m_correction[depth+1]), *(m_residual[depth+1]));
638  m_cycle = -cycles;
639  //
640  m_op[depth ]->prolongIncrement(correction, *(m_correction[depth+1]));
641  }
642 
643  m_op[depth ]->relax(correction, residual, m_post);
644  }
645  else
646  {
647  m_op[depth ]->relax( correction, residual, m_pre );
648 
649  m_op[depth ]->restrictResidual(*(m_residual[depth+1]), correction, residual);
650  m_op[depth ]->setToZero(*(m_correction[depth+1]));
651 
652  for (int img = 0; img < cycles; img++)
653  {
654  cycle(depth+1, *(m_correction[depth+1]), *(m_residual[depth+1]));
655  }
656  m_op[depth ]->prolongIncrement(correction, *(m_correction[depth+1]));
657 
658  m_op[depth ]->relax(correction, residual, m_post);
659  }
660  }
661 }
662 //-----------------------------------------------------------------------
663 
664 //-----------------------------------------------------------------------
665 template <class T>
667 {
668  std::vector<bool>::reverse_iterator it = m_ownOp.rbegin();
669  for (int i=m_op.size()-1; i>=0; --i, ++it)
670  {
671  if (*it) delete m_op[i];
672  delete m_correction[i];
673  delete m_residual[i];
674  }
675  m_op.resize(0);
676  m_residual.resize(0);
677  m_correction.resize(0);
678  m_defined = false;
679 }
680 //-----------------------------------------------------------------------
681 
682 //-----------------------------------------------------------------------
683 // This destructor implementation had to appear below the MGLevelOp class
684 // definition.
685 template <typename T>
687 {
688  if (m_op != NULL)
689  {
690  // Remove this observer from its observee.
691  // For now, we skip this, since we haven't established rules
692  // for scoping between multigrid objects and AMRMultigrid objects
693  // (which own the AMR operators).
694  m_op->removeObserver(this);
695  }
696 }
697 //-----------------------------------------------------------------------
698 
699 #include "NamespaceFooter.H"
700 #endif /*_MULTIGRID_H_*/
std::ostream & pout()
Use this in place of std::cout for program output.
void addObserver(MGLevelOpObserver< T > *a_observer)
Definition: MultiGrid.H:147
MGLevelOp()
Constructor.
Definition: MultiGrid.H:94
Definition: LinearSolver.H:28
void clear()
Definition: MultiGrid.H:666
int m_cycle
Definition: MultiGrid.H:356
#define CH_SPACEDIM
Definition: SPACE.H:52
#define CH_assert(cond)
Definition: CHArray.H:37
A class to facilitate interaction with physical boundary conditions.
Definition: ProblemDomain.H:130
Vector< T *> m_residual
Definition: MultiGrid.H:373
int m_defaultDepth
Definition: MultiGrid.H:356
MGLevelOpObserver & operator=(const MGLevelOpObserver &)
MGLevelOpObserver()
Base level Constructor. Called by all subclasses.
Definition: MultiGrid.H:41
Vector< MGLevelOp< T > *> getAllOperators()
Definition: MultiGrid.H:396
one dimensional dynamic array
Definition: Vector.H:52
void removeObserver(MGLevelOpObserver< T > *a_observer)
Definition: MultiGrid.H:160
void setObservee(MGLevelOp< T > *a_observee)
Definition: MultiGrid.H:60
virtual ~MGLevelOpFactory()
Destructor.
Definition: MultiGrid.H:269
void init(const T &a_correction, const T &a_residual)
Definition: MultiGrid.H:500
virtual void define(MGLevelOpFactory< T > &a_factory, LinearSolver< T > *a_bottomSolver, const ProblemDomain &a_domain, int a_maxDepth=-1, MGLevelOp< T > *a_finestLevelOp=NULL)
Function to define a MultiGrid object.
Definition: MultiGrid.H:427
Vector< MGLevelOp< T > * > m_op
Definition: MultiGrid.H:372
virtual void oneCycle(T &a_e, const T &a_res)
Execute ONE v-cycle of multigrid.
Definition: MultiGrid.H:567
bool m_homogeneous
Definition: MultiGrid.H:357
int m_bottomCells
Definition: MultiGrid.H:369
Definition: MultiGrid.H:36
std::vector< MGLevelOpObserver< T > * > m_observers
List of observers for the operator.
Definition: MultiGrid.H:244
MultiGrid()
Definition: MultiGrid.H:405
void cycle(int a_depth, T &a_correction, const T &a_residual)
Definition: MultiGrid.H:596
int m_post
Definition: MultiGrid.H:356
std::vector< bool > m_ownOp
Definition: MultiGrid.H:375
void setBottomSolver(LinearSolver< T > *a_bottomSolver)
Definition: MultiGrid.H:491
long numPts() const
void resize(unsigned int isize)
Definition: Vector.H:323
ProblemDomain m_topLevelDomain
Definition: MultiGrid.H:371
void push_back(const T &in)
Definition: Vector.H:283
int m_depth
Definition: MultiGrid.H:356
void clear()
Definition: Vector.H:165
T & back()
Definition: Vector.H:256
#define CH_TIME(name)
Definition: CH_Timer.H:59
Definition: MultiGrid.H:259
bool m_defined
Definition: MultiGrid.H:367
double Real
Definition: REAL.H:33
Definition: MultiGrid.H:30
int numObservers() const
Returns the number of objects observing this operator.
Definition: MultiGrid.H:236
size_t size() const
Definition: Vector.H:177
int m_bottom
Definition: MultiGrid.H:356
MultiGrid(const MultiGrid< T > &a_opin)
Definition: MultiGrid.H:378
virtual void finerOperatorChanged(const MGLevelOp< T > &a_operator, int a_coarseningFactor)
Definition: MultiGrid.H:230
void clearObservee()
Definition: MultiGrid.H:68
static void Error(const char *const a_msg=m_nullString, int m_exitCode=CH_DEFAULT_ERROR_CODE)
Print out message to cerr and exit with the specified exit code.
void operator=(const MultiGrid< T > &a_opin)
Definition: MultiGrid.H:383
Definition: MultiGrid.H:296
Vector< T *> m_correction
Definition: MultiGrid.H:374
Definition: LinearSolver.H:158
virtual MGLevelOp< T > * MGnewOp(const ProblemDomain &a_FineindexSpace, int a_depth, bool a_homoOnly=true)=0
void addCoarserObserver(MGLevelOp< T > *a_operator, int a_coarseningFactor)
Definition: MultiGrid.H:184
virtual ~MultiGrid()
Definition: MultiGrid.H:419
MGLevelOpFactory()
Base class constructor.
Definition: MultiGrid.H:264
void notifyObserversOfChange()
This should be called whenever the operator&#39;s data is updated.
Definition: MultiGrid.H:201
T Max(const T &a_a, const T &a_b)
Definition: Misc.H:39
std::vector< int > m_coarseningFactors
Multigrid coarsening factors.
Definition: MultiGrid.H:247
virtual ~MGLevelOp()
Destructor.
Definition: MultiGrid.H:103
MGLevelOp< T > * m_op
Definition: MultiGrid.H:76
const Box & domainBox() const
Returns the logical computational domain.
Definition: ProblemDomain.H:868
virtual ~MGLevelOpObserver()
Destructor.
Definition: MultiGrid.H:686
virtual void operatorChanged(const MGLevelOp< T > &a_operator)
Definition: MultiGrid.H:53
int m_pre
Definition: MultiGrid.H:356
virtual void solve(T &a_phi, const T &a_rhs, Real a_tolerance, int a_maxIterations, int verbosity=0)
Definition: MultiGrid.H:519
LinearSolver< T > * m_bottomSolver
Definition: MultiGrid.H:358