overlappingpreconditioner.hh
Go to the documentation of this file.
1 // -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
2 // vi: set et ts=4 sw=4 sts=4:
3 /*
4  Copyright (C) 2011-2013 by Andreas Lauser
5 
6  This file is part of the Open Porous Media project (OPM).
7 
8  OPM is free software: you can redistribute it and/or modify
9  it under the terms of the GNU General Public License as published by
10  the Free Software Foundation, either version 2 of the License, or
11  (at your option) any later version.
12 
13  OPM is distributed in the hope that it will be useful,
14  but WITHOUT ANY WARRANTY; without even the implied warranty of
15  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16  GNU General Public License for more details.
17 
18  You should have received a copy of the GNU General Public License
19  along with OPM. If not, see <http://www.gnu.org/licenses/>.
20 */
25 #ifndef EWOMS_OVERLAPPING_PRECONDITIONER_HH
26 #define EWOMS_OVERLAPPING_PRECONDITIONER_HH
27 
29 
30 #include <opm/common/Exceptions.hpp>
31 #include <opm/common/ErrorMacros.hpp>
32 
33 #include <dune/istl/preconditioners.hh>
34 
35 namespace Ewoms {
36 namespace Linear {
37 
41 template <class SeqPreCond, class Overlap>
43  : public Dune::Preconditioner<typename SeqPreCond::domain_type,
44  typename SeqPreCond::range_type>
45 {
46 public:
47  typedef typename SeqPreCond::domain_type domain_type;
48  typedef typename SeqPreCond::range_type range_type;
49 
50  enum { category = Dune::SolverCategory::overlapping };
51 
52  OverlappingPreconditioner(SeqPreCond &seqPreCond, const Overlap &overlap)
53  : seqPreCond_(seqPreCond), overlap_(&overlap)
54  {}
55 
56  void pre(domain_type &x, range_type &y)
57  {
58 #if HAVE_MPI
59  short success;
60  try
61  {
62  seqPreCond_.pre(x, y);
63  short localSuccess = 1;
64  MPI_Allreduce(&localSuccess, // source buffer
65  &success, // destination buffer
66  1, // number of objects in buffers
67  MPI_SHORT, // data type
68  MPI_MIN, // operation
69  MPI_COMM_WORLD); // communicator
70  }
71  catch (...)
72  {
73  short localSuccess = 0;
74  MPI_Allreduce(&localSuccess, // source buffer
75  &success, // destination buffer
76  1, // number of objects in buffers
77  MPI_SHORT, // data type
78  MPI_MIN, // operation
79  MPI_COMM_WORLD); // communicator
80  }
81 
82  if (success) {
83  x.sync();
84  }
85  else
86  OPM_THROW(Opm::NumericalProblem,
87  "Preconditioner threw an exception in pre() method on some process.");
88 #else
89  seqPreCond_.pre(x, y);
90 #endif
91 
92  // communicate the results on the overlap
93  x.sync();
94  y.sync();
95  }
96 
97  void apply(domain_type &x, const range_type &d)
98  {
99 #if HAVE_MPI
100  if (overlap_->peerSet().size() > 0) {
101  // make sure that all processes react the same if the
102  // sequential preconditioner on one process throws an
103  // exception
104  short success;
105  try
106  {
107  // execute the sequential preconditioner
108  seqPreCond_.apply(x, d);
109  short localSuccess = 1;
110  MPI_Allreduce(&localSuccess, // source buffer
111  &success, // destination buffer
112  1, // number of objects in buffers
113  MPI_SHORT, // data type
114  MPI_MIN, // operation
115  MPI_COMM_WORLD); // communicator
116  }
117  catch (...)
118  {
119  short localSuccess = 0;
120  MPI_Allreduce(&localSuccess, // source buffer
121  &success, // destination buffer
122  1, // number of objects in buffers
123  MPI_SHORT, // data type
124  MPI_MIN, // operation
125  MPI_COMM_WORLD); // communicator
126  }
127 
128  if (success) {
129  x.sync();
130  }
131  else
132  OPM_THROW(Opm::NumericalProblem,
133  "Preconditioner threw an exception on some process.");
134  }
135  else
136 #endif // HAVE_MPI
137  seqPreCond_.apply(x, d);
138  }
139 
140  void post(domain_type &x)
141  {
142 #if HAVE_MPI
143  short success;
144  try
145  {
146  seqPreCond_.post(x);
147  short localSuccess = 1;
148  MPI_Allreduce(&localSuccess, // source buffer
149  &success, // destination buffer
150  1, // number of objects in buffers
151  MPI_SHORT, // data type
152  MPI_MIN, // operation
153  MPI_COMM_WORLD); // communicator
154  }
155  catch (...)
156  {
157  short localSuccess = 0;
158  MPI_Allreduce(&localSuccess, // source buffer
159  &success, // destination buffer
160  1, // number of objects in buffers
161  MPI_SHORT, // data type
162  MPI_MIN, // operation
163  MPI_COMM_WORLD); // communicator
164  }
165 
166  if (success) {
167  x.sync();
168  }
169  else
170  OPM_THROW(Opm::NumericalProblem, "Preconditioner threw an "
171  "exception in post() method on "
172  "some process.");
173 #else
174  seqPreCond_.post(x);
175 #endif
176  }
177 
178 private:
179  SeqPreCond &seqPreCond_;
180  const Overlap *overlap_;
181 };
182 
183 } // namespace Linear
184 } // namespace Ewoms
185 
186 #endif
SeqPreCond::range_type range_type
Definition: overlappingpreconditioner.hh:48
void pre(domain_type &x, range_type &y)
Definition: overlappingpreconditioner.hh:56
An overlap aware preconditioner for any ISTL linear solver.
Definition: overlappingpreconditioner.hh:42
void post(domain_type &x)
Definition: overlappingpreconditioner.hh:140
An overlap aware ISTL scalar product.
Definition: baseauxiliarymodule.hh:35
void apply(domain_type &x, const range_type &d)
Definition: overlappingpreconditioner.hh:97
Definition: overlappingpreconditioner.hh:50
SeqPreCond::domain_type domain_type
Definition: overlappingpreconditioner.hh:47
OverlappingPreconditioner(SeqPreCond &seqPreCond, const Overlap &overlap)
Definition: overlappingpreconditioner.hh:52