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_SGJacobi.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_Vector.h"
13 #include "NOX_Epetra_Interface_Jacobian.H"
14 #include "EpetraExt_BlockVector.h"
16 #include "Teuchos_TimeMonitor.hpp"
18 
19 NOX::Epetra::LinearSystemSGJacobi::
20 LinearSystemSGJacobi(
21  Teuchos::ParameterList& printingParams,
22  Teuchos::ParameterList& linearSolverParams_,
23  const Teuchos::RCP<NOX::Epetra::LinearSystem>& det_solver_,
26  const Teuchos::RCP<const Stokhos::OrthogPolyBasis<int,double> >& sg_basis,
27  const Teuchos::RCP<const Stokhos::ParallelData>& sg_parallel_data,
29  const Teuchos::RCP<const Epetra_Map>& base_map_,
30  const Teuchos::RCP<const Epetra_Map>& sg_map_,
32  det_solver(det_solver_),
33  epetraCijk(sg_parallel_data->getEpetraCijk()),
34  jacInterfacePtr(iJac),
35  base_map(base_map_),
36  sg_map(sg_map_),
37  scaling(s),
38  utils(printingParams)
39 {
40  sg_op = Teuchos::rcp_dynamic_cast<Stokhos::SGOperator>(J, true);
41  sg_poly = sg_op->getSGPolynomial();
42 
43  sg_df_block =
44  Teuchos::rcp(new EpetraExt::BlockVector(*base_map, *sg_map));
45  kx = Teuchos::rcp(new Epetra_Vector(*base_map));
46 
48  Teuchos::rcp(&(linearSolverParams_.sublist("Jacobi SG Operator")), false);
49  sgOpParams->set("Include Mean", false);
50  if (!sgOpParams->isParameter("Only Use Linear Terms"))
51  sgOpParams->set("Only Use Linear Terms", false);
52 
53  // Build new parallel Cijk if we are only using the linear terms, Cijk
54  // is distributed over proc's, and Cijk includes more than just the linear
55  // terms (so we have the right column map; otherwise we will be importing
56  // much more than necessary)
57  if (sgOpParams->get<bool>("Only Use Linear Terms") &&
58  epetraCijk->isStochasticParallel()) {
59  int dim = sg_basis->dimension();
60  if (epetraCijk->getKEnd() > dim+1)
61  epetraCijk =
63  *epetraCijk, 1, dim+1));
64 
65  }
66 
67  Stokhos::SGOperatorFactory sg_op_factory(sgOpParams);
69  sg_parallel_data->getMultiComm();
70  mat_free_op =
71  sg_op_factory.build(sg_comm, sg_basis, epetraCijk,
72  base_map, base_map, sg_map, sg_map);
73 }
74 
75 NOX::Epetra::LinearSystemSGJacobi::
76 ~LinearSystemSGJacobi()
77 {
78 }
79 
80 bool NOX::Epetra::LinearSystemSGJacobi::
81 applyJacobian(const NOX::Epetra::Vector& input,
82  NOX::Epetra::Vector& result) const
83 {
84  sg_op->SetUseTranspose(false);
85  int status = sg_op->Apply(input.getEpetraVector(), result.getEpetraVector());
86 
87  return (status == 0);
88 }
89 
90 bool NOX::Epetra::LinearSystemSGJacobi::
91 applyJacobianTranspose(const NOX::Epetra::Vector& input,
92  NOX::Epetra::Vector& result) const
93 {
94  sg_op->SetUseTranspose(true);
95  int status = sg_op->Apply(input.getEpetraVector(), result.getEpetraVector());
96  sg_op->SetUseTranspose(false);
97 
98  return (status == 0);
99 }
100 
101 bool NOX::Epetra::LinearSystemSGJacobi::
102 applyJacobianInverse(Teuchos::ParameterList &params,
103  const NOX::Epetra::Vector &input,
104  NOX::Epetra::Vector &result)
105 {
106  int max_iter = params.get("Max Iterations",100 );
107  double sg_tol = params.get("Tolerance", 1e-12);
108 
109  // Extract blocks
110  EpetraExt::BlockVector sg_dx_block(View, *base_map, result.getEpetraVector());
111  EpetraExt::BlockVector sg_f_block(View, *base_map, input.getEpetraVector());
112  sg_dx_block.PutScalar(0.0);
113 
114  // Compute initial residual norm
115  double norm_f,norm_df;
116  sg_f_block.Norm2(&norm_f);
117  sg_op->Apply(sg_dx_block, *sg_df_block);
118  sg_df_block->Update(-1.0, sg_f_block, 1.0);
119  sg_df_block->Norm2(&norm_df);
120 
122  Teuchos::ParameterList& det_solver_params =
123  params.sublist("Deterministic Solver Parameters");
124 
125  int myBlockRows = epetraCijk->numMyRows();
126  int iter = 0;
127  while (((norm_df/norm_f)>sg_tol) && (iter<max_iter)) {
128  TEUCHOS_FUNC_TIME_MONITOR("Total global solve Time");
129  iter++;
130 
131  // Compute RHS
132  if (iter == 0)
133  sg_df_block->Update(1.0, sg_f_block, 0.0);
134  else {
135  mat_free_op->Apply(sg_dx_block, *sg_df_block);
136  sg_df_block->Update(1.0, sg_f_block, -1.0);
137  }
138 
139  for (int i=0; i<myBlockRows; i++) {
140  df = sg_df_block->GetBlock(i);
141  dx = sg_dx_block.GetBlock(i);
142  NOX::Epetra::Vector nox_df(df, NOX::Epetra::Vector::CreateView);
143  NOX::Epetra::Vector nox_dx(dx, NOX::Epetra::Vector::CreateView);
144 
145  (*sg_poly)[0].Apply(*dx, *kx);
146 
147  dx->PutScalar(0.0);
148  // Solve linear system
149  {
150  TEUCHOS_FUNC_TIME_MONITOR("Total deterministic solve Time");
151  det_solver->applyJacobianInverse(det_solver_params, nox_df, nox_dx);
152  }
153 
154  df->Update(-1.0, *kx, 1.0);
155  }
156 
157  sg_df_block->Norm2(&norm_df);
158  utils.out() << "\t Jacobi relative residual norm at iteration "
159  << iter <<" is " << norm_df/norm_f << std::endl;
160  } //End of iter loop
161 
162  //return status;
163  return true;
164 }
165 
166 bool NOX::Epetra::LinearSystemSGJacobi::
167 applyRightPreconditioning(bool useTranspose,
168  Teuchos::ParameterList& params,
169  const NOX::Epetra::Vector& input,
170  NOX::Epetra::Vector& result) const
171 {
172  return false;
173 }
174 
175 Teuchos::RCP<NOX::Epetra::Scaling> NOX::Epetra::LinearSystemSGJacobi::
176 getScaling()
177 {
178  return scaling;
179 }
180 
181 void NOX::Epetra::LinearSystemSGJacobi::
182 resetScaling(const Teuchos::RCP<NOX::Epetra::Scaling>& s)
183 {
184  scaling = s;
185  return;
186 }
187 
188 bool NOX::Epetra::LinearSystemSGJacobi::
189 computeJacobian(const NOX::Epetra::Vector& x)
190 {
191  bool success = jacInterfacePtr->computeJacobian(x.getEpetraVector(),
192  *sg_op);
193  sg_poly = sg_op->getSGPolynomial();
194  det_solver->setJacobianOperatorForSolve(sg_poly->getCoeffPtr(0));
195  mat_free_op->setupOperator(sg_poly);
196  return success;
197 }
198 
199 bool NOX::Epetra::LinearSystemSGJacobi::
200 createPreconditioner(const NOX::Epetra::Vector& x,
202  bool recomputeGraph) const
203 {
204  EpetraExt::BlockVector sg_x_block(View, *base_map, x.getEpetraVector());
205  bool success =
206  det_solver->createPreconditioner(*(sg_x_block.GetBlock(0)),
207  p.sublist("Deterministic Solver Parameters"),
208  recomputeGraph);
209 
210  return success;
211 }
212 
213 bool NOX::Epetra::LinearSystemSGJacobi::
214 destroyPreconditioner() const
215 {
216  return det_solver->destroyPreconditioner();
217 }
218 
219 bool NOX::Epetra::LinearSystemSGJacobi::
220 recomputePreconditioner(const NOX::Epetra::Vector& x,
221  Teuchos::ParameterList& linearSolverParams) const
222 {
223  EpetraExt::BlockVector sg_x_block(View, *base_map, x.getEpetraVector());
224  bool success =
225  det_solver->recomputePreconditioner(
226  *(sg_x_block.GetBlock(0)),
227  linearSolverParams.sublist("Deterministic Solver Parameters"));
228 
229  return success;
230 }
231 
232 NOX::Epetra::LinearSystem::PreconditionerReusePolicyType
233 NOX::Epetra::LinearSystemSGJacobi::
234 getPreconditionerPolicy(bool advanceReuseCounter)
235 {
236  return det_solver->getPreconditionerPolicy(advanceReuseCounter);
237 }
238 
239 bool NOX::Epetra::LinearSystemSGJacobi::
240 isPreconditionerConstructed() const
241 {
242  return det_solver->isPreconditionerConstructed();
243 }
244 
245 bool NOX::Epetra::LinearSystemSGJacobi::
246 hasPreconditioner() const
247 {
248  return det_solver->hasPreconditioner();
249 }
250 
251 Teuchos::RCP<const Epetra_Operator> NOX::Epetra::LinearSystemSGJacobi::
252 getJacobianOperator() const
253 {
254  return sg_op;
255 }
256 
257 Teuchos::RCP<Epetra_Operator> NOX::Epetra::LinearSystemSGJacobi::
258 getJacobianOperator()
259 {
260  return sg_op;
261 }
262 
263 Teuchos::RCP<const Epetra_Operator> NOX::Epetra::LinearSystemSGJacobi::
264 getGeneratedPrecOperator() const
265 {
266  return Teuchos::null;
267 }
268 
269 Teuchos::RCP<Epetra_Operator> NOX::Epetra::LinearSystemSGJacobi::
270 getGeneratedPrecOperator()
271 {
272  return Teuchos::null;
273 }
274 
275 void NOX::Epetra::LinearSystemSGJacobi::
276 setJacobianOperatorForSolve(const
278 {
280  Teuchos::rcp_dynamic_cast<const Stokhos::SGOperator>(solveJacOp, true);
281  sg_op = Teuchos::rcp_const_cast<Stokhos::SGOperator>(const_sg_op);
282  sg_poly = sg_op->getSGPolynomial();
283 }
284 
285 void NOX::Epetra::LinearSystemSGJacobi::
286 setPrecOperatorForSolve(const
288 {
289 }
#define TEUCHOS_FUNC_TIME_MONITOR(FUNCNAME)
Teuchos::RCP< const EpetraExt::MultiComm > getMultiComm() const
Get global comm.
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="")
ParameterList & set(std::string const &name, T &&value, std::string const &docString="", RCP< const ParameterEntryValidator > const &validator=null)
bool isParameter(const std::string &name) const
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)
Factory for generating stochastic Galerkin preconditioners.