MueLu  Version of the Day
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
MueLu_MHDRAPFactory_def.hpp
Go to the documentation of this file.
1 // @HEADER
2 //
3 // ***********************************************************************
4 //
5 // MueLu: A package for multigrid based preconditioning
6 // Copyright 2012 Sandia Corporation
7 //
8 // Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
9 // the U.S. Government retains certain rights in this software.
10 //
11 // Redistribution and use in source and binary forms, with or without
12 // modification, are permitted provided that the following conditions are
13 // met:
14 //
15 // 1. Redistributions of source code must retain the above copyright
16 // notice, this list of conditions and the following disclaimer.
17 //
18 // 2. Redistributions in binary form must reproduce the above copyright
19 // notice, this list of conditions and the following disclaimer in the
20 // documentation and/or other materials provided with the distribution.
21 //
22 // 3. Neither the name of the Corporation nor the names of the
23 // contributors may be used to endorse or promote products derived from
24 // this software without specific prior written permission.
25 //
26 // THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY
27 // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
28 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
29 // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE
30 // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
31 // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
32 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
33 // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
34 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
35 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
36 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
37 //
38 // Questions? Contact
39 // Jonathan Hu (jhu@sandia.gov)
40 // Andrey Prokopenko (aprokop@sandia.gov)
41 // Ray Tuminaro (rstumin@sandia.gov)
42 //
43 // ***********************************************************************
44 //
45 // @HEADER
46 #ifndef MUELU_MHDRAPFACTORY_DEF_HPP
47 #define MUELU_MHDRAPFACTORY_DEF_HPP
48 
49 #include <sstream>
50 
51 #include <Xpetra_Map.hpp>
52 #include <Xpetra_MapFactory.hpp>
53 #include <Xpetra_Matrix.hpp>
54 #include <Xpetra_CrsMatrixWrap.hpp>
55 #include <Xpetra_Vector.hpp>
56 #include <Xpetra_VectorFactory.hpp>
57 
59 #include "MueLu_Monitor.hpp"
60 
61 namespace MueLu {
62 
63 template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
65  : implicitTranspose_(true) {}
66 
67 template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
69  if (implicitTranspose_ == false) {
70  Input(coarseLevel, "R");
71  Input(coarseLevel, "RV");
72  Input(coarseLevel, "RP");
73  Input(coarseLevel, "RM");
74  }
75 
76  Input(fineLevel, "A");
77  Input(fineLevel, "A00");
78  Input(fineLevel, "A01");
79  Input(fineLevel, "A02");
80  Input(fineLevel, "A10");
81  Input(fineLevel, "A11");
82  Input(fineLevel, "A12");
83  Input(fineLevel, "A20");
84  Input(fineLevel, "A21");
85  Input(fineLevel, "A22");
86 
87  Input(coarseLevel, "P");
88  Input(coarseLevel, "PV");
89  Input(coarseLevel, "PP");
90  Input(coarseLevel, "PM");
91 }
92 
93 template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
94 void MHDRAPFactory<Scalar, LocalOrdinal, GlobalOrdinal, Node>::Build(Level &fineLevel, Level &coarseLevel) const { // FIXME make fineLevel const
95  {
96  FactoryMonitor m(*this, "Computing Ac", coarseLevel);
97 
98  //
99  // Inputs: A, P
100  //
101 
102  // DEBUG
103  // Teuchos::FancyOStream fout(*GetOStream(Runtime1));
104  // coarseLevel.print(fout,Teuchos::VERB_HIGH);
105 
106  RCP<Matrix> A = Get<RCP<Matrix> >(fineLevel, "A");
107  RCP<Matrix> A00 = Get<RCP<Matrix> >(fineLevel, "A00");
108  RCP<Matrix> A01 = Get<RCP<Matrix> >(fineLevel, "A01");
109  RCP<Matrix> A02 = Get<RCP<Matrix> >(fineLevel, "A02");
110  RCP<Matrix> A10 = Get<RCP<Matrix> >(fineLevel, "A10");
111  RCP<Matrix> A11 = Get<RCP<Matrix> >(fineLevel, "A11");
112  RCP<Matrix> A12 = Get<RCP<Matrix> >(fineLevel, "A12");
113  RCP<Matrix> A20 = Get<RCP<Matrix> >(fineLevel, "A20");
114  RCP<Matrix> A21 = Get<RCP<Matrix> >(fineLevel, "A21");
115  RCP<Matrix> A22 = Get<RCP<Matrix> >(fineLevel, "A22");
116 
117  RCP<Matrix> P = Get<RCP<Matrix> >(coarseLevel, "P");
118  RCP<Matrix> PV = Get<RCP<Matrix> >(coarseLevel, "PV");
119  RCP<Matrix> PP = Get<RCP<Matrix> >(coarseLevel, "PP");
120  RCP<Matrix> PM = Get<RCP<Matrix> >(coarseLevel, "PM");
121 
122  //
123  // Build Ac = RAP
124  //
125 
126  RCP<Matrix> AP;
127  RCP<Matrix> AP00;
128  RCP<Matrix> AP01;
129  RCP<Matrix> AP02;
130  RCP<Matrix> AP10;
131  RCP<Matrix> AP11;
132  RCP<Matrix> AP12;
133  RCP<Matrix> AP20;
134  RCP<Matrix> AP21;
135  RCP<Matrix> AP22;
136 
137  {
138  SubFactoryMonitor subM(*this, "MxM: A x P", coarseLevel);
139 
140  AP = Utils::Multiply(*A, false, *P, false, AP, GetOStream(Statistics2));
141  AP00 = Utils::Multiply(*A00, false, *PV, false, AP00, GetOStream(Statistics2));
142  AP01 = Utils::Multiply(*A01, false, *PP, false, AP01, GetOStream(Statistics2));
143  AP02 = Utils::Multiply(*A02, false, *PM, false, AP02, GetOStream(Statistics2));
144  AP10 = Utils::Multiply(*A10, false, *PV, false, AP10, GetOStream(Statistics2));
145  AP11 = Utils::Multiply(*A11, false, *PP, false, AP11, GetOStream(Statistics2));
146  AP12 = Utils::Multiply(*A12, false, *PM, false, AP12, GetOStream(Statistics2));
147  AP20 = Utils::Multiply(*A20, false, *PV, false, AP20, GetOStream(Statistics2));
148  AP21 = Utils::Multiply(*A21, false, *PP, false, AP21, GetOStream(Statistics2));
149  AP22 = Utils::Multiply(*A22, false, *PM, false, AP22, GetOStream(Statistics2));
150  }
151 
152  RCP<Matrix> Ac;
153  RCP<Matrix> Ac00;
154  RCP<Matrix> Ac01;
155  RCP<Matrix> Ac02;
156  RCP<Matrix> Ac10;
157  RCP<Matrix> Ac11;
158  RCP<Matrix> Ac12;
159  RCP<Matrix> Ac20;
160  RCP<Matrix> Ac21;
161  RCP<Matrix> Ac22;
162 
163  if (implicitTranspose_) {
164  SubFactoryMonitor m2(*this, "MxM: P' x (AP) (implicit)", coarseLevel);
165 
166  Ac = Utils::Multiply(*P, true, *AP, false, Ac, GetOStream(Statistics2));
167  Ac00 = Utils::Multiply(*PV, true, *AP00, false, Ac00, GetOStream(Statistics2));
168  Ac01 = Utils::Multiply(*PV, true, *AP01, false, Ac01, GetOStream(Statistics2));
169  Ac02 = Utils::Multiply(*PV, true, *AP02, false, Ac02, GetOStream(Statistics2));
170  Ac10 = Utils::Multiply(*PP, true, *AP10, false, Ac10, GetOStream(Statistics2));
171  Ac11 = Utils::Multiply(*PP, true, *AP11, false, Ac11, GetOStream(Statistics2));
172  Ac12 = Utils::Multiply(*PP, true, *AP12, false, Ac12, GetOStream(Statistics2));
173  Ac20 = Utils::Multiply(*PM, true, *AP20, false, Ac20, GetOStream(Statistics2));
174  Ac21 = Utils::Multiply(*PM, true, *AP21, false, Ac21, GetOStream(Statistics2));
175  Ac22 = Utils::Multiply(*PM, true, *AP22, false, Ac22, GetOStream(Statistics2));
176 
177  } else {
178  SubFactoryMonitor m2(*this, "MxM: R x (AP) (explicit)", coarseLevel);
179 
180  RCP<Matrix> R = Get<RCP<Matrix> >(coarseLevel, "R");
181  RCP<Matrix> RV = Get<RCP<Matrix> >(coarseLevel, "RV");
182  RCP<Matrix> RP = Get<RCP<Matrix> >(coarseLevel, "RP");
183  RCP<Matrix> RM = Get<RCP<Matrix> >(coarseLevel, "RM");
184 
185  Ac = Utils::Multiply(*R, false, *AP, false, Ac, GetOStream(Statistics2));
186  Ac00 = Utils::Multiply(*RV, false, *AP00, false, Ac00, GetOStream(Statistics2));
187  Ac01 = Utils::Multiply(*RV, false, *AP01, false, Ac01, GetOStream(Statistics2));
188  Ac02 = Utils::Multiply(*RV, false, *AP02, false, Ac02, GetOStream(Statistics2));
189  Ac10 = Utils::Multiply(*RP, false, *AP10, false, Ac10, GetOStream(Statistics2));
190  Ac11 = Utils::Multiply(*RP, false, *AP11, false, Ac11, GetOStream(Statistics2));
191  Ac12 = Utils::Multiply(*RP, false, *AP12, false, Ac12, GetOStream(Statistics2));
192  Ac20 = Utils::Multiply(*RM, false, *AP20, false, Ac20, GetOStream(Statistics2));
193  Ac21 = Utils::Multiply(*RM, false, *AP21, false, Ac21, GetOStream(Statistics2));
194  Ac22 = Utils::Multiply(*RM, false, *AP22, false, Ac22, GetOStream(Statistics2));
195  }
196  // FINISHED MAKING COARSE BLOCKS
197 
198  Set(coarseLevel, "A", Ac);
199  Set(coarseLevel, "A00", Ac00);
200  Set(coarseLevel, "A01", Ac01);
201  Set(coarseLevel, "A02", Ac02);
202  Set(coarseLevel, "A10", Ac10);
203  Set(coarseLevel, "A11", Ac11);
204  Set(coarseLevel, "A12", Ac12);
205  Set(coarseLevel, "A20", Ac20);
206  Set(coarseLevel, "A21", Ac21);
207  Set(coarseLevel, "A22", Ac22);
208  }
209 }
210 
211 /*
212  template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
213  std::string MHDRAPFactory<Scalar, LocalOrdinal, GlobalOrdinal, Node>::PerfUtils::PrintMatrixInfo(const Matrix & Ac, const std::string & msgTag) {
214  std::stringstream ss(std::stringstream::out);
215  ss << msgTag
216  << " # global rows = " << Ac.getGlobalNumRows()
217  << ", estim. global nnz = " << Ac.getGlobalNumEntries()
218  << std::endl;
219  return ss.str();
220  }
221 */
222 
223 template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
224 std::string MHDRAPFactory<Scalar, LocalOrdinal, GlobalOrdinal, Node>::PrintLoadBalancingInfo(const Matrix &Ac, const std::string &msgTag) {
225  std::stringstream ss(std::stringstream::out);
226 
227  // TODO: provide a option to skip this (to avoid global communication)
228  // TODO: skip if nproc == 1
229 
230  // nonzero imbalance
231  size_t numMyNnz = Ac.getLocalNumEntries();
232  GO maxNnz, minNnz;
233  RCP<const Teuchos::Comm<int> > comm = Ac.getRowMap()->getComm();
234  MueLu_maxAll(comm, (GO)numMyNnz, maxNnz);
235  // min nnz over all proc (disallow any processors with 0 nnz)
236  MueLu_minAll(comm, (GO)((numMyNnz > 0) ? numMyNnz : maxNnz), minNnz);
237  double imbalance = ((double)maxNnz) / minNnz;
238 
239  size_t numMyRows = Ac.getLocalNumRows();
240  // Check whether Ac is spread over more than one process.
241  GO numActiveProcesses = 0;
242  MueLu_sumAll(comm, (GO)((numMyRows > 0) ? 1 : 0), numActiveProcesses);
243 
244  // min, max, and avg # rows per proc
245  GO minNumRows, maxNumRows;
246  double avgNumRows;
247  MueLu_maxAll(comm, (GO)numMyRows, maxNumRows);
248  MueLu_minAll(comm, (GO)((numMyRows > 0) ? numMyRows : maxNumRows), minNumRows);
249  assert(numActiveProcesses > 0);
250  avgNumRows = Ac.getGlobalNumRows() / numActiveProcesses;
251 
252  ss << msgTag << " # processes with rows = " << numActiveProcesses << std::endl;
253  ss << msgTag << " min # rows per proc = " << minNumRows << ", max # rows per proc = " << maxNumRows << ", avg # rows per proc = " << avgNumRows << std::endl;
254  ss << msgTag << " nonzero imbalance = " << imbalance << std::endl;
255 
256  return ss.str();
257 }
258 
259 } // namespace MueLu
260 
261 #define MUELU_MHDRAPFACTORY_SHORT
262 #endif // MUELU_MHDRAPFACTORY_DEF_HPP
#define MueLu_sumAll(rcpComm, in, out)
#define MueLu_maxAll(rcpComm, in, out)
GlobalOrdinal GO
Timer to be used in factories. Similar to Monitor but with additional timers.
void Build(Level &fineLevel, Level &coarseLevel) const
Build an object with this factory.
#define MueLu_minAll(rcpComm, in, out)
Print even more statistics.
Class that holds all level-specific information.
Definition: MueLu_Level.hpp:99
static std::string PrintLoadBalancingInfo(const Matrix &Ac, const std::string &msgTag)
Timer to be used in factories. Similar to SubMonitor but adds a timer level by level.
void DeclareInput(Level &fineLevel, Level &coarseLevel) const
Input.