LifeV
PreconditionerML.cpp
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 ML preconditioner
30 
31  @author Simone Deparis <simone.deparis@epfl.ch>
32  @contributor Gwenol Grandperrin <gwenol.grandperrin@epfl.ch>
33  @maintainer Gwenol Grandperrin <gwenol.grandperrin@epfl.ch>
34 
35  @date 09-11-2006
36  */
37 
38 #include <lifev/core/algorithm/PreconditionerML.hpp>
39 
40 #include <lifev/core/LifeV.hpp>
41 
42 namespace LifeV
43 {
44 
45 // ===================================================
46 // Constructors & Destructor
47 // ===================================================
48 PreconditionerML::PreconditionerML ( std::shared_ptr<Epetra_Comm> comm ) :
49  super(),
50  M_comm ( comm ),
51  M_operator(),
53  M_analyze (false),
55 {
56 
57 }
58 
60 {
61  M_preconditioner.reset();
62  M_operator.reset();
63 }
64 
65 
66 // ===================================================
67 // Methods
68 // ===================================================
69 Int
70 PreconditionerML::buildPreconditioner ( operator_type& matrix )
71 {
72 
73  //the Trilinos::MultiLevelPreconditioner unsafely access to the area of memory co-owned by M_operator.
74  //to avoid the risk of dandling pointers always deallocate M_preconditioner first and then M_operator
75  M_preconditioner.reset();
76  M_operator = matrix;
77 
78  M_precType = M_list.get ( "prec type", "undefined??" );
79  M_precType += "_ML";
80 
81  // <one-level-postsmoothing> / <two-level-additive>
82  // <two-level-hybrid> / <two-level-hybrid2>
83 
84  M_preconditioner.reset ( new prec_raw_type ( * (M_operator->matrixPtr() ), this->parametersList(), true ) );
85 
86  if ( M_analyze )
87  {
88  ML_Epetra::MultiLevelPreconditioner* prec;
89  prec = dynamic_cast<ML_Epetra::MultiLevelPreconditioner*> ( M_preconditioner.get() );
90  Int NumPreCycles = 5;
91  Int NumPostCycles = 1;
92  Int NumMLCycles = 10;
93  prec->AnalyzeHierarchy ( true, NumPreCycles, NumPostCycles, NumMLCycles );
94  }
95 
96  this->M_preconditionerCreated = true;
97 
98  return ( EXIT_SUCCESS );
99 }
100 
101 void
103 {
104  //the Trilinos::MultiLevelPreconditioner unsafely access to the area of memory co-owned by M_operator.
105  //to avoid the risk of dandling pointers always deallocate M_preconditioner first and then M_operator
106 
107  M_preconditioner.reset();
108  M_operator.reset();
109 
110  this->M_preconditionerCreated = false;
111 }
112 
113 void
115  const GetPot& dataFile,
116  const std::string& section,
117  const std::string& subSection,
118  const bool& verbose )
119 {
120  list.setName ( "ML paramters list" );
121 
122  std::string defList = dataFile ( (section + "/" + subSection + "/default_parameter_list").data(), "SA" );
123  if ( defList != "none" )
124  {
125  ML_Epetra::SetDefaults ( defList, list );
126  }
127 
128  bool found;
129 
130  bool MLPrintParameterList = dataFile ( (section + "/displayList").data(), false, found );
131 
132  Int MLOutput = dataFile ( (section + "/" + subSection + "/MLOuput").data(), 0, found);
133  if ( found )
134  {
135  list.set ( "ML output", MLOutput );
136  }
137 
138  Int printUnused = dataFile ( (section + "/" + subSection + "/print_unused").data(), -2, found);
139  if ( found )
140  {
141  list.set ( "print unused", printUnused );
142  }
143 
144  Int PDEEquations = dataFile ( (section + "/" + subSection + "/pde_equations").data(), 1, found);
145  if ( found )
146  {
147  list.set ( "PDE equations", PDEEquations );
148  }
149 
150  Int CycleApplications = dataFile ( (section + "/" + subSection + "/cycle_applications").data(), 1, found);
151  if ( found )
152  {
153  list.set ( "cycle applications", CycleApplications );
154  }
155 
156  Int MaxLevels = dataFile ( (section + "/" + subSection + "/max_levels").data(), 2, found);
157  if ( found )
158  {
159  list.set ( "max levels", MaxLevels );
160  }
161 
162  std::string IncOrDec = dataFile ( (section + "/" + subSection + "/inc_or_dec").data(), "increasing", found);
163  if ( found )
164  {
165  list.set ( "increasing or decreasing", IncOrDec );
166  }
167 
168  std::string precType = dataFile ( (section + "/" + subSection + "/prec_type").data(), "MGV", found);
169  if ( found )
170  {
171  list.set ( "prec type", precType );
172  }
173 
174  // Int NumProjectedModes = dataFile( (section + "/" + subSection + "/number_of_prejected_modes").data(), 0 );
175  // if ( found ) list.set( "ML print parameter list", MLPrintParameterList );
176 
177  std::string eigenAnalysisType = dataFile ( (section + "/" + subSection + "/eigne-analysis/type").data(), "cg", found );
178  if ( found )
179  {
180  list.set ( "eigen-analysis: type", eigenAnalysisType );
181  }
182 
183  Int eigenAnalysisIterations = dataFile ( (section + "/" + subSection + "/eigne-analysis/iterations").data(), 10, found );
184  if ( found )
185  {
186  list.set ( "eigen-analysis: iterations", eigenAnalysisIterations );
187  }
188 
189  // Aggregation options
190 
191  std::string AggregationType = dataFile ( (section + "/" + subSection + "/aggregation/type").data(), "Uncoupled", found );
192  if ( found )
193  {
194  list.set ( "aggregation: type", AggregationType );
195  }
196 
197  bool AggregationBlockScaling = dataFile ( (section + "/" + subSection + "/aggregation/block_scaling").data(), false, found );
198  if ( found )
199  {
200  list.set ( "aggregation: block scaling", AggregationBlockScaling );
201  }
202 
203  Real AggregationThreshold = dataFile ( (section + "/" + subSection + "/aggregation/threshold").data(), 0.0 , found );
204  if ( found )
205  {
206  list.set ( "aggregation: threshold", AggregationThreshold );
207  }
208 
209  Real AggregationDampingFactor = dataFile ( (section + "/" + subSection + "/aggregation/damping_factor").data(), 4. / 3. , found );
210  if ( found )
211  {
212  list.set ( "aggregation: damping factor", AggregationDampingFactor );
213  }
214 
215  Int AggregationSmoothingSweeps = dataFile ( (section + "/" + subSection + "/aggregation/smoothing_sweeps").data(), 1, found );
216  if ( found )
217  {
218  list.set ( "aggregation: smoothing sweeps", AggregationSmoothingSweeps );
219  }
220 
221  Int AggregationGlobalAggregates = dataFile ( (section + "/" + subSection + "/aggregation/global_aggregates").data(), 1, found );
222  if ( found )
223  {
224  list.set ( "aggregation: global aggregates", AggregationGlobalAggregates );
225  }
226 
227  Int AggregationLocalAggregates = dataFile ( (section + "/" + subSection + "/aggregation/local_aggregates").data(), 1, found );
228  if ( found )
229  {
230  list.set ( "aggregation: local aggregates", AggregationLocalAggregates );
231  }
232 
233  Int AggregationNodesPerAggregate = dataFile ( (section + "/" + subSection + "/aggregation/nodes_per_aggregate").data(), 1, found );
234  if ( found )
235  {
236  list.set ( "aggregation: nodes per aggregate", AggregationNodesPerAggregate );
237  }
238 
239  Int AggregationNextLevelAggregatesPerProcess = dataFile ( (section + "/" + subSection + "/aggregation/next-level_aggregates_per_process").data(), 128, found );
240  if ( found )
241  {
242  list.set ( "aggregation: next level aggregates per process", AggregationNextLevelAggregatesPerProcess );
243  }
244 
245  bool AggregationUseTentativeRestriction = dataFile ( (section + "/" + subSection + "/aggregation/tentative_restriction").data(), false, found );
246  if ( found )
247  {
248  list.set ( "aggregation: use tentative restriction", AggregationUseTentativeRestriction );
249  }
250 
251  bool AggregationSymmetrize = dataFile ( (section + "/" + subSection + "/aggregation/symmetrize").data(), false, found );
252  if ( found )
253  {
254  list.set ( "aggregation: symmetrize", AggregationSymmetrize );
255  }
256 
257  Int AggregationNumLevelTypes = dataFile ( (section + "/" + subSection + "/aggregation/level_type").data(), 0, found );
258  if ( found )
259  {
260  for (Int i (0); i < AggregationNumLevelTypes; ++i)
261  {
262  std::string levelIndex = dataFile ( (section + "/" + subSection + "/aggregation/level_type").data(), "0", 2 * i + 1 );
263  std::string levelParamValue = dataFile ( (section + "/" + subSection + "/aggregation/level_type").data(), "METIS", 2 * i + 2 );
264  list.set ( ("aggregation: type (level " + levelIndex + ")").data(), levelParamValue );
265  }
266  }
267 
268  bool EnergyMinimizationEnable = dataFile ( (section + "/" + subSection + "/energy_minimization/enable").data(), false, found );
269  if ( found )
270  {
271  list.set ( "energy minimization: enable", EnergyMinimizationEnable );
272  }
273 
274  Int EnergyMinimizationType = dataFile ( (section + "/" + subSection + "/energy_minimization/type").data(), 2, found );
275  if ( found )
276  {
277  list.set ( "energy minimization: type", EnergyMinimizationType );
278  }
279 
280  Real EnergyMinimizationDropTol = dataFile ( (section + "/" + subSection + "/energy_minimization/droptol").data(), 0., found );
281  if ( found )
282  {
283  list.set ( "energy minimization: droptol", EnergyMinimizationDropTol );
284  }
285 
286  bool EnergyMinimizationCheap = dataFile ( (section + "/" + subSection + "/energy_minimization/cheap").data(), false, found );
287  if ( found )
288  {
289  list.set ( "energy minimization: cheap", EnergyMinimizationCheap );
290  }
291 
292  // Smoothing parameters
293 
294  std::string SmootherType = dataFile ( (section + "/" + subSection + "/smoother/type").data(), "IFPACK", found );
295  if ( found )
296  {
297  list.set ( "smoother: type", SmootherType );
298  }
299 
300  Int SmootherSweeps = dataFile ( (section + "/" + subSection + "/smoother/sweeps").data(), 2, found );
301  if ( found )
302  {
303  list.set ( "smoother: sweeps", SmootherSweeps );
304  }
305 
306  Real SmootherDampingFactor = dataFile ( (section + "/" + subSection + "/smoother/damping_factor").data(), 1.0, found );
307  if ( found )
308  {
309  list.set ( "smoother: damping factor", SmootherDampingFactor );
310  }
311 
312  std::string SmootherPreOrPost = dataFile ( (section + "/" + subSection + "/smoother/pre_or_post").data(), "both", found );
313  if ( found )
314  {
315  list.set ( "smoother: pre or post", SmootherPreOrPost );
316  }
317 
318  Real SmootherChebyshevAlpha = dataFile ( (section + "/" + subSection + "/smoother/Chebyshev_alpha").data(), 20., found );
319  if ( found )
320  {
321  list.set ( "smoother: Chebyshev alpha", SmootherChebyshevAlpha );
322  }
323 
324  bool SmootherHiptmairEfficientSymmetric = dataFile ( (section + "/" + subSection + "/smoother/Hiptmair_efficient_symmetric").data(), true, found );
325  if ( found )
326  {
327  list.set ( "smoother: Hiptmair efficient symmetric", SmootherHiptmairEfficientSymmetric );
328  }
329 
330  std::string SmootherIfpackType = dataFile ( (section + "/" + subSection + "/smoother/ifpack_type").data(), "ILU", found );
331  if ( found )
332  {
333  list.set ( "smoother: ifpack type", SmootherIfpackType );
334  }
335 
336  Int SmootherIfpackOverlap = dataFile ( (section + "/" + subSection + "/smoother/ifpack_overlap").data(), 1, found );
337  if ( found )
338  {
339  list.set ( "smoother: ifpack overlap", SmootherIfpackOverlap );
340  }
341 
342  Int SmootherNumLevelTypes = dataFile ( (section + "/" + subSection + "/smoother/level_type").data(), 0, found );
343  if ( found )
344  {
345  for (Int i (0); i < SmootherNumLevelTypes; ++i)
346  {
347  std::string levelIndex = dataFile ( (section + "/" + subSection + "/smoother/level_type").data(), "0", 2 * i + 1 );
348  std::string levelParamValue = dataFile ( (section + "/" + subSection + "/smoother/level_type").data(), "IFPACK", 2 * i + 2 );
349  list.set ( ("smoother: type (level " + levelIndex + ")").data(), levelParamValue );
350  }
351  }
352 
353  Int SmootherNumLevelSweeps = dataFile ( (section + "/" + subSection + "/smoother/level_sweeps").data(), 0, found );
354  if ( found )
355  {
356  for (Int i (0); i < SmootherNumLevelSweeps; ++i)
357  {
358  std::string levelIndex = dataFile ( (section + "/" + subSection + "/smoother/level_sweeps").data(), "0", 2 * i + 1 );
359  Int levelParamValue = dataFile ( (section + "/" + subSection + "/smoother/level_sweeps").data(), 1, 2 * i + 2 );
360  list.set ( ("smoother: sweeps (level " + levelIndex + ")").data(), levelParamValue );
361  }
362  }
363 
364  // subsmoother parameter
365 
366  std::string SubSmootherType = dataFile ( (section + "/" + subSection + "/subsmoother/type").data(), "Chebyshev", found );
367  if ( found )
368  {
369  list.set ( "subsmoother: type", SubSmootherType );
370  }
371 
372  Real SubSmootherChebyshevAlpha = dataFile ( (section + "/" + subSection + "/subsmoother/Chebyshev_alpha").data(), 20., found );
373  if ( found )
374  {
375  list.set ( "subsmoother: Chebyshev alpha", SubSmootherChebyshevAlpha );
376  }
377 
378  // Real SubSmootherSGSDampingFactor = dataFile((section + "/" + subSection + "/subsmoothers/SGS_damping_factor").data(), 1., found );
379  Int SubSmootherEdgeSweeps = dataFile ( (section + "/" + subSection + "/subsmoother/edge_sweeps").data(), 2, found );
380  if ( found )
381  {
382  list.set ( "subsmoother: edge sweeps", SubSmootherEdgeSweeps );
383  }
384 
385  Int SubSmootherNodeSweeps = dataFile ( (section + "/" + subSection + "/subsmoother/node_sweeps").data(), 2, found );
386  if ( found )
387  {
388  list.set ( "subsmoother: node sweeps", SubSmootherNodeSweeps );
389  }
390 
391 
392  // Coarsest Grid Parameters
393 
394  Int CoarseMaxSize = dataFile ( (section + "/" + subSection + "/coarse/max_size").data(), 128, found );
395  if ( found )
396  {
397  list.set ( "coarse: max size", CoarseMaxSize );
398  }
399 
400  std::string CoarseType = dataFile ( (section + "/" + subSection + "/coarse/type").data(), "Chebyshev", found );
401  if ( found )
402  {
403  list.set ( "coarse: type", CoarseType );
404  }
405 
406  std::string CoarsePreOrPost = dataFile ( (section + "/" + subSection + "/coarse/pre_or_post").data(), "post", found );
407  if ( found )
408  {
409  list.set ( "coarse: pre or post", CoarsePreOrPost );
410  }
411 
412  Int CoarseSweeps = dataFile ( (section + "/" + subSection + "/coarse/sweeps").data(), 2, found );
413  if ( found )
414  {
415  list.set ( "coarse: sweeps", CoarseSweeps );
416  }
417 
418  Real CoarseDampingFactor = dataFile ( (section + "/" + subSection + "/coarse/damping_factor").data(), 1.0, found );
419  if ( found )
420  {
421  list.set ( "coarse: damping factor", CoarseDampingFactor );
422  }
423 
424  std::string CoarseSubsmootherType = dataFile ( (section + "/" + subSection + "/coarse/subsmoother_type").data(), "Chebyshev", found );
425  if ( found )
426  {
427  list.set ( "coarse: subsmoother type", CoarseSubsmootherType );
428  }
429 
430  Int CoarseNodeSweeps = dataFile ( (section + "/" + subSection + "/coarse/node_sweeps").data(), 2, found );
431  if ( found )
432  {
433  list.set ( "coarse: node sweeps", CoarseNodeSweeps );
434  }
435 
436  Int CoarseEdgeSweeps = dataFile ( (section + "/" + subSection + "/coarse/edge_sweeps").data(), 2, found );
437  if ( found )
438  {
439  list.set ( "coarse: edge sweeps", CoarseEdgeSweeps );
440  }
441 
442  Real CoarseChebyshevAlpha = dataFile ( (section + "/" + subSection + "/coarse/Chebyshev_alpha").data(), 30., found );
443  if ( found )
444  {
445  list.set ( "coarse: Chebyshev alpha", CoarseChebyshevAlpha );
446  }
447 
448  Int CoarseMaxProcesses = dataFile ( (section + "/" + subSection + "/coarse/max_processes").data(), -1, found );
449  if ( found )
450  {
451  list.set ( "coarse: max processes", CoarseMaxProcesses );
452  }
453 
454 
455  // Load-balancing Options
456  Int RepartitionEnable = dataFile ( (section + "/" + subSection + "/repartition/enable").data(), 0, found );
457  if ( found )
458  {
459  list.set ( "repartition: enable", RepartitionEnable );
460  }
461 
462  std::string RepartitionPartitioner = dataFile ( (section + "/" + subSection + "/repartition/partitioner").data(), "ParMETIS", found );
463  if ( found )
464  {
465  list.set ( "repartition: partitioner", RepartitionPartitioner );
466  }
467 
468  Real RepartitionMaxMinRatio = dataFile ( (section + "/" + subSection + "/repartition/max_min_ratio").data(), 1.3, found );
469  if ( found )
470  {
471  list.set ( "repartition: max min ratio", RepartitionMaxMinRatio );
472  }
473 
474  Int RepartitionMinPerProc = dataFile ( (section + "/" + subSection + "/repartition/min_per_proc").data(), 512, found );
475  if ( found )
476  {
477  list.set ( "repartition: min per proc", RepartitionMinPerProc );
478  }
479 
480  Real RepartitionNodeMaxMinRatio = dataFile ( (section + "/" + subSection + "/repartition/node_max_min_ratio").data(), 1.3, found );
481  if ( found )
482  {
483  list.set ( "repartition: node max min ratio", RepartitionNodeMaxMinRatio );
484  }
485 
486  Int RepartitionNodeMinPerProc = dataFile ( (section + "/" + subSection + "/repartition/node_min_per_proc").data(), 170, found );
487  if ( found )
488  {
489  list.set ( "repartition: node min per proc", RepartitionNodeMinPerProc );
490  }
491 
492  Int RepartitionZoltanDimensions = dataFile ( (section + "/" + subSection + "/repartition/Zoltan_dimensions").data(), 2, found );
493  if ( found )
494  {
495  list.set ( "repartition: Zoltan dimensions", RepartitionZoltanDimensions );
496  }
497 
498  if ( MLPrintParameterList && verbose )
499  {
500  std::cout << "ML parameters list:" << std::endl;
501  std::cout << "-----------------------------" << std::endl;
502  list.print ( std::cout );
503  std::cout << "-----------------------------" << std::endl;
504  }
505 }
506 
507 void PreconditionerML::showMe ( std::ostream& output ) const
508 {
509  output << "showMe must be implemented for the PreconditionerML class" << std::endl;
510 }
511 
512 // ===================================================
513 // Set Methods
514 // ===================================================
515 void
517  const std::string& section )
518 {
519  bool verbose = M_comm->MyPID() == 0;
520 
521  M_analyze = dataFile ( (section + "/" + "ML" + "/analyze_smoother" ).data(), false); // To be moved in createMLList
522 
523  // ML List
524  createMLList ( M_list, dataFile, section, "ML", verbose );
525 
526  // visualization
527  bool found (false);
528  bool enableViz = dataFile ( (section + "/" + "ML" + "/visualization/enable").data(), false, found );
529  if ( found )
530  {
531  /*
532  If the visualization is desired and we have set the required data,
533  we set the following variables.
534  (see Trilinos::ML manual for more details)
535  */
537  {
538  M_list.set ( "viz: enable", enableViz);
539  M_list.set ( "viz: output format", "vtk");
540  M_list.set ("x-coordinates", & ( (*M_xCoord) [0]) );
541  M_list.set ("y-coordinates", & ( (*M_yCoord) [0]) );
542  M_list.set ("z-coordinates", & ( (*M_zCoord) [0]) );
543  }
544  else
545  {
546  std::cout << "Warning: Visualization options are not available if you have not use setVerticesCoordinates first!" << std::endl;
547  }
548  }
549 
550  // IfPack list
551  bool MLPrintParameterList = dataFile ( (section + "/displayList").data(), false );
552  if ( MLPrintParameterList && verbose )
553  {
554  std::cout << "Smoother: ";
555  }
556  list_Type& SmootherIFSubList = M_list.sublist ( "smoother: ifpack list" );
557  PreconditionerIfpack::createIfpackList ( SmootherIFSubList, dataFile, section, "ML", verbose );
558 }
559 
560 void
561 PreconditionerML::setVerticesCoordinates (std::shared_ptr<std::vector<Real> > xCoord,
564 {
565  M_xCoord = xCoord;
566  M_yCoord = yCoord;
567  M_zCoord = zCoord;
569 }
570 
571 
572 // ===================================================
573 // Get Methods
574 // ===================================================
575 Real
577 {
578  return 0.;
579 }
580 
583 {
584  return M_preconditioner.get();
585 }
586 
587 } // namespace LifeV
int32_type Int
Generic integer data.
Definition: LifeV.hpp:188
void updateInverseJacobian(const UInt &iQuadPt)
void resetPreconditioner()
Reset the preconditioner.
virtual ~PreconditionerML()
destructor.
void setDataFromGetPot(const GetPot &dataFile, const std::string &section)
Set the data of the preconditioner using a GetPot object.
Preconditioner(const commPtr_Type &comm=commPtr_Type())
Constructor.
double Real
Generic real data.
Definition: LifeV.hpp:175
virtual void showMe(std::ostream &output=std::cout) const
Show informations about the preconditioner.
Teuchos::ParameterList list_Type
static void createMLList(list_Type &list, const GetPot &dataFile, const std::string &section, const std::string &subSection="ML", const bool &verbose=true)
Create the list of parameters of the preconditioner.
PreconditionerML(std::shared_ptr< Epetra_Comm > comm=std::shared_ptr< Epetra_Comm >(new Epetra_MpiComm(MPI_COMM_WORLD)))
Empty constructor.
Int buildPreconditioner(operator_type &matrix)
Build a preconditioner based on the given matrix.