Stokhos Package Browser (Single Doxygen Collection)  Version of the Day
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
NOX_Epetra_LinearSystem_SGGS.cpp
Go to the documentation of this file.
1 // @HEADER
2 // *****************************************************************************
3 // Stokhos Package
4 //
5 // Copyright 2009 NTESS and the Stokhos contributors.
6 // SPDX-License-Identifier: BSD-3-Clause
7 // *****************************************************************************
8 // @HEADER
9 
11 
12 #include "Epetra_Map.h"
13 #include "Epetra_Vector.h"
14 #include "NOX_Epetra_Interface_Jacobian.H"
15 #include "EpetraExt_BlockVector.h"
16 #include "EpetraExt_BlockUtility.h"
18 #include "Teuchos_TimeMonitor.hpp"
19 
20 NOX::Epetra::LinearSystemSGGS::
21 LinearSystemSGGS(
22  Teuchos::ParameterList& printingParams,
23  Teuchos::ParameterList& linearSolverParams,
24  const Teuchos::RCP<NOX::Epetra::LinearSystem>& det_solver_,
27  const Teuchos::RCP<const Stokhos::OrthogPolyBasis<int,double> >& sg_basis_,
28  const Teuchos::RCP<const Stokhos::ParallelData>& sg_parallel_data,
30  const Teuchos::RCP<const Epetra_Map>& base_map_,
31  const Teuchos::RCP<const Epetra_Map>& sg_map_,
33  det_solver(det_solver_),
34  sg_basis(sg_basis_),
35  epetraCijk(sg_parallel_data->getEpetraCijk()),
36  is_stoch_parallel(epetraCijk->isStochasticParallel()),
37  stoch_row_map(epetraCijk->getStochasticRowMap()),
38  Cijk(epetraCijk->getParallelCijk()),
39  jacInterfacePtr(iJac),
40  base_map(base_map_),
41  sg_map(sg_map_),
42  scaling(s),
43  utils(printingParams),
44  is_parallel(epetraCijk->isStochasticParallel())
45 {
46  sg_op = Teuchos::rcp_dynamic_cast<Stokhos::SGOperator>(J, true);
47  sg_poly = sg_op->getSGPolynomial();
48 
49  sg_df_block = Teuchos::rcp(new EpetraExt::BlockVector(*base_map, *sg_map));
50  sg_y_block = Teuchos::rcp(new EpetraExt::BlockVector(*base_map, *sg_map));
51  kx = Teuchos::rcp(new Epetra_Vector(*base_map));
52 
53  only_use_linear = linearSolverParams.get("Only Use Linear Terms", false);
54  k_limit = sg_poly->size();
55  int dim = sg_basis->dimension();
56  if (only_use_linear && sg_poly->size() > dim+1)
57  k_limit = dim + 1;
58 
59  if (is_parallel) {
61  epetraCijk->getStochasticColMap();
62  sg_col_map =
63  Teuchos::rcp(EpetraExt::BlockUtility::GenerateBlockMap(*base_map,
64  *stoch_col_map,
65  sg_map->Comm()));
66  col_exporter = Teuchos::rcp(new Epetra_Export(*sg_col_map, *sg_map));
67  sg_df_col = Teuchos::rcp(new EpetraExt::BlockVector(*base_map,
68  *sg_col_map));
69  sg_df_tmp = Teuchos::rcp(new EpetraExt::BlockVector(*base_map, *sg_map));
70  }
71 }
72 
73 NOX::Epetra::LinearSystemSGGS::
74 ~LinearSystemSGGS()
75 {
76 }
77 
78 bool NOX::Epetra::LinearSystemSGGS::
79 applyJacobian(const NOX::Epetra::Vector& input,
80  NOX::Epetra::Vector& result) const
81 {
82  sg_op->SetUseTranspose(false);
83  int status = sg_op->Apply(input.getEpetraVector(), result.getEpetraVector());
84 
85  return (status == 0);
86 }
87 
88 bool NOX::Epetra::LinearSystemSGGS::
89 applyJacobianTranspose(const NOX::Epetra::Vector& input,
90  NOX::Epetra::Vector& result) const
91 {
92  sg_op->SetUseTranspose(true);
93  int status = sg_op->Apply(input.getEpetraVector(), result.getEpetraVector());
94  sg_op->SetUseTranspose(false);
95 
96  return (status == 0);
97 }
98 
99 bool NOX::Epetra::LinearSystemSGGS::
100 applyJacobianInverse(Teuchos::ParameterList &params,
101  const NOX::Epetra::Vector &input,
102  NOX::Epetra::Vector &result)
103 {
104  int max_iter = params.get("Max Iterations",100 );
105  double sg_tol = params.get("Tolerance", 1e-12);
106  bool scale_op = params.get("Scale Operator by Inverse Basis Norms", true);
107 
108  // Extract blocks
109  EpetraExt::BlockVector sg_dx_block(View, *base_map, result.getEpetraVector());
110  EpetraExt::BlockVector sg_f_block(View, *base_map, input.getEpetraVector());
111  sg_dx_block.PutScalar(0.0);
112 
113  // Compute initial residual norm
114  double norm_f,norm_df;
115  sg_f_block.Norm2(&norm_f);
116  sg_op->Apply(sg_dx_block, *sg_df_block);
117  sg_df_block->Update(-1.0, sg_f_block, 1.0);
118  sg_df_block->Norm2(&norm_df);
119 
121  const Teuchos::Array<double>& norms = sg_basis->norm_squared();
122 
123  // sg_df_block stores the right-hand-sides for the Gauss-Seidel iteration
124  // sg_y_block stores the residual, i.e., A*x-b
125  // sg_df_col stores off-processor contributions to the RHS and residual
126  // In parallel, this is essentially domain decomposition using Gauss-Seidel
127  // in each domain and Jacobi across domains.
128 
129  int iter = 0;
130  while (((norm_df/norm_f)>sg_tol) && (iter<max_iter)) {
131  TEUCHOS_FUNC_TIME_MONITOR("Total global solve Time");
132  iter++;
133 
134  sg_y_block->Update(1.0, sg_f_block, 0.0);
135  if (is_parallel)
136  sg_df_col->PutScalar(0.0);
137 
138  for (Cijk_type::i_iterator i_it=Cijk->i_begin();
139  i_it!=Cijk->i_end(); ++i_it) {
140  int i = Stokhos::index(i_it);
141  f = sg_f_block.GetBlock(i);
142  df = sg_df_block->GetBlock(i);
143  dx = sg_dx_block.GetBlock(i);
144 
145  dx->PutScalar(0.0);
146  Teuchos::ParameterList& det_solver_params =
147  params.sublist("Deterministic Solver Parameters");
148  NOX::Epetra::Vector nox_df(df, NOX::Epetra::Vector::CreateView);
149  NOX::Epetra::Vector nox_dx(dx, NOX::Epetra::Vector::CreateView);
150  // Solve linear system
151  {
152  TEUCHOS_FUNC_TIME_MONITOR("Total deterministic solve Time");
153  det_solver->applyJacobianInverse(det_solver_params, nox_df, nox_dx);
154  }
155 
156  df->Update(1.0, *f, 0.0);
157 
158  for (Cijk_type::ik_iterator k_it = Cijk->k_begin(i_it);
159  k_it != Cijk->k_end(i_it); ++k_it) {
160  int k = Stokhos::index(k_it);
161  if (k!=0 && k<k_limit) {
162  (*sg_poly)[k].Apply(*dx, *kx);
163  for (Cijk_type::ikj_iterator j_it = Cijk->j_begin(k_it);
164  j_it != Cijk->j_end(k_it); ++j_it) {
165  int j = Stokhos::index(j_it);
166  int j_gid = epetraCijk->GCID(j);
167  double c = Stokhos::value(j_it);
168  if (scale_op)
169  c /= norms[j_gid];
170  bool owned = epetraCijk->myGRID(j_gid);
171  if (!is_parallel || owned) {
172  sg_df_block->GetBlock(j)->Update(-c, *kx, 1.0);
173  sg_y_block->GetBlock(j)->Update(-c, *kx, 1.0);
174  }
175  else
176  sg_df_col->GetBlock(j)->Update(-c, *kx, 1.0);
177  }
178  }
179  }
180 
181  (*sg_poly)[0].Apply(*dx, *kx);
182  sg_y_block->GetBlock(i)->Update(-1.0, *kx, 1.0);
183 
184  } //End of k loop
185 
186  // Add in contributions from off-process
187  if (is_parallel) {
188  sg_df_tmp->Export(*sg_df_col, *col_exporter, InsertAdd);
189  sg_df_block->Update(1.0, *sg_df_tmp, 1.0);
190  sg_y_block->Update(1.0, *sg_df_tmp, 1.0);
191  }
192 
193  sg_y_block->Norm2(&norm_df);
194  utils.out() << "\t Gauss-Seidel relative residual norm at iteration "
195  << iter <<" is " << norm_df/norm_f << std::endl;
196  } //End of iter loop
197 
198  //return status;
199  return true;
200 }
201 
202 bool NOX::Epetra::LinearSystemSGGS::
203 applyRightPreconditioning(bool useTranspose,
204  Teuchos::ParameterList& params,
205  const NOX::Epetra::Vector& input,
206  NOX::Epetra::Vector& result) const
207 {
208  return false;
209 }
210 
211 Teuchos::RCP<NOX::Epetra::Scaling> NOX::Epetra::LinearSystemSGGS::
212 getScaling()
213 {
214  return scaling;
215 }
216 
217 void NOX::Epetra::LinearSystemSGGS::
218 resetScaling(const Teuchos::RCP<NOX::Epetra::Scaling>& s)
219 {
220  scaling = s;
221  return;
222 }
223 
224 bool NOX::Epetra::LinearSystemSGGS::
225 computeJacobian(const NOX::Epetra::Vector& x)
226 {
227  bool success = jacInterfacePtr->computeJacobian(x.getEpetraVector(),
228  *sg_op);
229  sg_poly = sg_op->getSGPolynomial();
230  det_solver->setJacobianOperatorForSolve(sg_poly->getCoeffPtr(0));
231  return success;
232 }
233 
234 bool NOX::Epetra::LinearSystemSGGS::
235 createPreconditioner(const NOX::Epetra::Vector& x,
237  bool recomputeGraph) const
238 {
239  EpetraExt::BlockVector sg_x_block(View, *base_map, x.getEpetraVector());
240  bool success =
241  det_solver->createPreconditioner(*(sg_x_block.GetBlock(0)),
242  p.sublist("Deterministic Solver Parameters"),
243  recomputeGraph);
244 
245  return success;
246 }
247 
248 bool NOX::Epetra::LinearSystemSGGS::
249 destroyPreconditioner() const
250 {
251  return det_solver->destroyPreconditioner();
252 }
253 
254 bool NOX::Epetra::LinearSystemSGGS::
255 recomputePreconditioner(const NOX::Epetra::Vector& x,
256  Teuchos::ParameterList& linearSolverParams) const
257 {
258  EpetraExt::BlockVector sg_x_block(View, *base_map, x.getEpetraVector());
259  bool success =
260  det_solver->recomputePreconditioner(
261  *(sg_x_block.GetBlock(0)),
262  linearSolverParams.sublist("Deterministic Solver Parameters"));
263 
264  return success;
265 
266 }
267 
268 NOX::Epetra::LinearSystem::PreconditionerReusePolicyType
269 NOX::Epetra::LinearSystemSGGS::
270 getPreconditionerPolicy(bool advanceReuseCounter)
271 {
272  return det_solver->getPreconditionerPolicy(advanceReuseCounter);
273 }
274 
275 bool NOX::Epetra::LinearSystemSGGS::
276 isPreconditionerConstructed() const
277 {
278  return det_solver->isPreconditionerConstructed();
279 }
280 
281 bool NOX::Epetra::LinearSystemSGGS::
282 hasPreconditioner() const
283 {
284  return det_solver->hasPreconditioner();
285 }
286 
287 Teuchos::RCP<const Epetra_Operator> NOX::Epetra::LinearSystemSGGS::
288 getJacobianOperator() const
289 {
290  return sg_op;
291 }
292 
293 Teuchos::RCP<Epetra_Operator> NOX::Epetra::LinearSystemSGGS::
294 getJacobianOperator()
295 {
296  return sg_op;
297 }
298 
299 Teuchos::RCP<const Epetra_Operator> NOX::Epetra::LinearSystemSGGS::
300 getGeneratedPrecOperator() const
301 {
302  return Teuchos::null;
303 }
304 
305 Teuchos::RCP<Epetra_Operator> NOX::Epetra::LinearSystemSGGS::
306 getGeneratedPrecOperator()
307 {
308  return Teuchos::null;
309 }
310 
311 void NOX::Epetra::LinearSystemSGGS::
312 setJacobianOperatorForSolve(const
314 {
316  Teuchos::rcp_dynamic_cast<const Stokhos::SGOperator>(solveJacOp, true);
317  sg_op = Teuchos::rcp_const_cast<Stokhos::SGOperator>(const_sg_op);
318  sg_poly = sg_op->getSGPolynomial();
319 }
320 
321 void NOX::Epetra::LinearSystemSGGS::
322 setPrecOperatorForSolve(const Teuchos::RCP<const Epetra_Operator>& solvePrecOp)
323 {
324 }
#define TEUCHOS_FUNC_TIME_MONITOR(FUNCNAME)
T & get(ParameterList &l, const std::string &name)
RCP< ParameterList > sublist(const RCP< ParameterList > &paramList, const std::string &name, bool mustAlreadyExist=false, const std::string &docString="")
TEUCHOS_DEPRECATED RCP< T > rcp(T *p, Dealloc_T dealloc, bool owns_mem)
An abstract class to represent a generic stochastic Galerkin operator as an Epetra_Operator.
virtual Teuchos::RCP< Stokhos::EpetraOperatorOrthogPoly > getSGPolynomial()=0
Get SG polynomial.
expr expr expr dx(i, j)
const Epetra_Comm & Comm() const
ScalarType f(const Teuchos::Array< ScalarType > &x, double a, double b)