Trilinos based (stochastic) FEM solvers
newtonRaphson.cpp
Go to the documentation of this file.
1 /*
2 Brian Staber (brian.staber@gmail.com)
3 */
4 
5 #include "newtonRaphson.hpp"
6 
7 newtonRaphson::newtonRaphson(nonLinearFiniteElementProblem & Interface, Teuchos::ParameterList & Parameters){
8 
9  interface = &Interface;
10  Comm = interface->Comm;
11  Krylov = &Parameters.sublist("Krylov");
12  MyPID = Comm->MyPID();
13 
14  setParameters(Parameters);
15 
16  x = new Epetra_Vector(*interface->StandardMap);
17 }
18 
19 void newtonRaphson::setParameters(Teuchos::ParameterList & Parameters){
20 
21  delta = Teuchos::getParameter<double>(Parameters.sublist("Newton"), "delta");
22  iter_min = Teuchos::getParameter<int>(Parameters.sublist("Newton"), "iterMin");
23  iter_max = Teuchos::getParameter<int>(Parameters.sublist("Newton"), "iterMax");
24  nb_bis_max = Teuchos::getParameter<int>(Parameters.sublist("Newton"), "nbBisMax");
25  norm_inf_tol = Teuchos::getParameter<double>(Parameters.sublist("Newton"), "NormFTol");
26  norm_inf_max = Teuchos::getParameter<double>(Parameters.sublist("Newton"), "NormFMax");
27  eps = Teuchos::getParameter<double>(Parameters.sublist("Newton"), "eps");
28  success = Teuchos::getParameter<double>(Parameters.sublist("Newton"), "success_parameter");
29  failure = Teuchos::getParameter<double>(Parameters.sublist("Newton"), "failure_parameter");
30  bc_disp = Teuchos::getParameter<double>(Parameters.sublist("Newton"), "bc_disp");
31  pressure_load = Teuchos::getParameter<double>(Parameters.sublist("Newton"), "pressure_load");
32  tol = Teuchos::getParameter<double>(Parameters.sublist("Newton"), "tol");
33 }
34 
35 int newtonRaphson::Solve_with_Stratimikos(Teuchos::RCP<Teuchos::ParameterList> solverBuilderSL){
36 
37  double assemble_time,displacement, norm_inf_rhs, time_init, time_max, krylov_res;
38  int FLAG1, FLAG2, FLAG3, nb_bis, iter, krylov_its;
39  time_init = delta;
40  time_max = 1.0;
41  time = 0.0;
42 
43  std::string solver_its = "krylov_its";
44  std::string solver_res = "krylov_res";
45 
46  Epetra_Time Time(*Comm);
47 
48  Teuchos::RCP<Epetra_FECrsMatrix> epetra_A = Teuchos::rcp(new Epetra_FECrsMatrix(Copy,*interface->FEGraph));
49  Teuchos::RCP<Epetra_FEVector> epetra_rhs = Teuchos::rcp(new Epetra_FEVector(*interface->StandardMap));
50  Teuchos::RCP<Epetra_Vector> epetra_lhs = Teuchos::rcp(new Epetra_Vector(*interface->StandardMap));
51  Teuchos::RCP<Epetra_Vector> epetra_y = Teuchos::rcp(new Epetra_Vector(*interface->StandardMap));
52  Teuchos::RCP<Epetra_MultiVector> epetra_rhsv = epetra_rhs;
53 
54  Stratimikos::DefaultLinearSolverBuilder linearSolverBuilder;
55  linearSolverBuilder.setParameterList(solverBuilderSL);
56 
57  Teuchos::RCP<Thyra::LinearOpWithSolveFactoryBase<double> > lowsFactory =
58  linearSolverBuilder.createLinearSolveStrategy("");
59  Teuchos::RCP<Thyra::LinearOpWithSolveBase<double> > lows = lowsFactory->createOp();
60 
61  Teuchos::RCP<Teuchos::FancyOStream> out = Teuchos::VerboseObjectBase::getDefaultOStream();
62  //lowsFactory->setOStream(out);
63  //lowsFactory->setVerbLevel(Teuchos::VERB_HIGH);
64 
65  Teuchos::RCP<const Thyra::LinearOpBase<double>> thyra_A = Thyra::epetraLinearOp(epetra_A);
66  Teuchos::RCP<Thyra::VectorBase<double>> thyra_lhs = Thyra::create_Vector(epetra_lhs,thyra_A->domain());
67  Teuchos::RCP<const Thyra::MultiVectorBase<double>> thyra_rhs = Thyra::create_MultiVector(epetra_rhsv,thyra_A->range());
68 
69  Thyra::SolveStatus<double> status;
70 
71  FLAG1=1;
72  while (FLAG1==1){
73 
74  FLAG1=0;
75  FLAG2=1;
76  FLAG3=1;
77  nb_bis = 0;
78  time += delta;
79  *epetra_y = *x;
80 
81  while (FLAG2==1){
82  FLAG2=0;
83  if(time-time_max>eps){
84  if(time_max+delta-time>eps){
85  delta=time_max+delta-time;
86  time=time_max;
87  }
88  else{
89  FLAG1=0;
90  break;
91  }
92  }
93 
95  iter = 0;
96  while (FLAG3==1){
97  FLAG3=0;
98  iter++;
99  if(iter>iter_max){
100  if (MyPID==0){std::cout << "Iteration limit exceeds.\n";}
101  return 1;
102  }
103  Time.ResetStartTime();
104  interface->get_matrix_and_rhs(*x, *epetra_A, *epetra_rhs);
105  assemble_time = Time.ElapsedTime();
106 
107  if (iter==1){
108  displacement = delta*bc_disp;
109  }
110  else{
111  displacement = 0.0;
112  }
113  interface->apply_dirichlet_conditions(*epetra_A, *epetra_rhs, displacement);
114 
115  if(iter>1){
116  epetra_rhs->NormInf(&norm_inf_rhs);
117 
118  if (MyPID==0){
119  if(iter>2){
120  std::cout << "\t\t\t" << iter << "\t" << norm_inf_rhs << "\t" << krylov_res << "\t\t" << assemble_time << "\t\t\t" << time*pressure_load/1000.0 << "\n";
121  }
122  else{
123  std::cout << "\n Time" << "\t" << "Timestep" << "\t" << "Iter" << "\t" << "NormInf" << "\t" << solver_res << "\t\t" << "assemble_time" << "\t\t" << "pressure_load [kPa]" << "\n";
124  std::cout << " " << time << "\t" << delta << "\t\t" << iter << "\t" << norm_inf_rhs << "\t\t" << krylov_res << "\t\t" << assemble_time << "\t\t\t" << time*pressure_load << "\n";
125  }
126  }
127 
128  if(norm_inf_rhs<norm_inf_tol){
129  if (iter<=iter_min){
130  delta = success*delta;
131  }
132  if (iter>=iter_max){
133  delta = delta/failure;
134  }
135  FLAG1=1;
136  break;
137  }
138 
139  if(norm_inf_rhs>norm_inf_max||iter==iter_max){
140  nb_bis++;
141  if (nb_bis<nb_bis_max){
142  delta /= failure;
143  time -= delta;
144  *x = *epetra_y;
145  if (MyPID==0){
146  std::cout << "Bisecting increment: " << nb_bis << "\n";
147  }
148  }
149  else{
150  if (MyPID==0){
151  std::cout << "Bisection number exceeds.\n";
152  }
153  return 2;
154  }
155  FLAG2=1;
156  FLAG3=1;
157  break;
158  }
159 
160  }
161 
162  epetra_rhsv = epetra_rhs;
163  epetra_lhs->PutScalar(0.0);
164 
165  Comm->Barrier();
166  if (time==time_init){
167  Thyra::initializeOp<double>(*lowsFactory, thyra_A, lows.ptr());
168  }
169  else{
170  Thyra::uninitializeOp<double>(*lowsFactory, lows.ptr());
171  Thyra::initializeAndReuseOp<double>(*lowsFactory, thyra_A, lows.ptr());
172  }
173  status = Thyra::solve<double>(*lows, Thyra::NOTRANS, *thyra_rhs, thyra_lhs.ptr());
174  /*if (status.solveStatus){
175  if (Comm->MyPID()==0){
176  std::cout << "STRATIMIKOS FAILED TO CONVERGE.\n";
177  std::cout << status.message << "\n";
178  }
179  }*/
180  //krylov_its = -1; //not sure that thyra_lhs will be copied into epetra_lhs
181  krylov_res = status.achievedTol;
182  Comm->Barrier();
183  x->Update(1.0,*epetra_lhs,1.0);
184 
185  FLAG3=1;
186  }
187  }
188  }
189 
190  return 0;
191 }
192 
194 
195  Epetra_Time Time(*Comm);
196 
197  Epetra_LinearProblem problem;
198  AztecOO solver;
199 
200  Epetra_FECrsMatrix stiffness(Copy,*interface->FEGraph);
201  Epetra_FEVector rhs(*interface->StandardMap);
202  Epetra_Vector lhs(*interface->StandardMap);
203  Epetra_Vector y(*interface->StandardMap);
204 
205  double Assemble_time;
206  double Aztec_time;
207  double displacement;
208  double norm_inf_rhs;
209  double time_max = 1.0;
210  double Krylov_res = 0;
211  int FLAG1, FLAG2, FLAG3, nb_bis, iter;
212  int Krylov_its = 0;
213 
214  time = 0.0;
215 
216  std::string solver_its = "GMRES_its";
217  std::string solver_res = "GMRES_res";
218 
219  FLAG1=1;
220  while (FLAG1==1){
221 
222  FLAG1=0;
223  FLAG2=1;
224  FLAG3=1;
225  nb_bis = 0;
226  time += delta;
227  y = *x;
228 
229  while (FLAG2==1){
230  FLAG2=0;
231  if(time-time_max>eps){
232  if(time_max+delta-time>eps){
233  delta=time_max+delta-time;
234  time=time_max;
235  }
236  else{
237  FLAG1=0;
238  break;
239  }
240  }
241 
243 
244  iter = 0;
245  while (FLAG3==1){
246 
247  FLAG3=0;
248  iter++;
249 
250  if(iter>iter_max){
251  if (MyPID==0){std::cout << "Iteration limit exceeds.\n";}
252  return 1;
253  }
254 
255  Time.ResetStartTime();
256  interface->get_matrix_and_rhs(*x, stiffness, rhs);
257  Assemble_time = Time.ElapsedTime();
258 
259  if (iter==1){
260  displacement = delta*bc_disp;
261  }
262  else{
263  displacement = 0.0;
264  }
265 
266  interface->apply_dirichlet_conditions(stiffness, rhs, displacement);
267 
268  if(iter>1){
269 
270  rhs.NormInf(&norm_inf_rhs);
271 
272  if (MyPID==0 && print){
273  if(iter>2){
274  std::cout << "\t\t\t" << iter << "\t" << norm_inf_rhs << "\t" << Krylov_its << "\t\t" << Krylov_res << "\t\t" << Assemble_time << "\t\t\t" << Aztec_time << "\t\t\t" << time*pressure_load << "\n";
275  }
276  else{
277  std::cout << "\n Time" << "\t" << "Timestep" << "\t" << "Iter" << "\t" << "NormInf" << "\t\t" << solver_its << "\t" << solver_res << "\t\t" << "assemble_time" << "\t\t" << "aztec_time" << "\t\t" << "pressure_load [kPa]" << "\n";
278  std::cout << " " << time << "\t" << delta << "\t\t" << iter << "\t" << norm_inf_rhs << "\t" << Krylov_its << "\t\t" << Krylov_res << "\t\t" << Assemble_time << "\t\t\t" << Aztec_time << "\t\t\t" << time*pressure_load << "\n";
279  }
280  }
281 
282  if(norm_inf_rhs<norm_inf_tol){
283  if (iter<=iter_min){
284  delta = success*delta;
285  }
286  if (iter>=iter_max){
287  delta = delta/failure;
288  }
289  FLAG1=1;
290  //std::string name="Newton_Solution_Time" + std::to_string(time) + ".mtx";
291  //print_newton_solution(name);
292  break;
293  }
294 
295  if(norm_inf_rhs>norm_inf_max||iter==iter_max){
296  nb_bis++;
297  if (nb_bis<nb_bis_max){
298  delta /= failure;
299  time -= delta;
300  *x = y;
301  if (MyPID==0){
302  std::cout << "Bisecting increment: " << nb_bis << "\n";
303  }
304  }
305  else{
306  if (MyPID==0){
307  std::cout << "Bisection number exceeds.\n";
308  }
309  return 2;
310  }
311  FLAG2=1;
312  FLAG3=1;
313  break;
314  }
315 
316  }
317 
318  lhs.PutScalar(0.0);
319  problem.SetOperator(&stiffness);
320  problem.SetLHS(&lhs);
321  problem.SetRHS(&rhs);
322  solver.SetProblem(problem);
323  solver.SetParameters(*Krylov);
324 
325  Time.ResetStartTime();
326  solver.Iterate(2000,tol);
327  Aztec_time = Time.ElapsedTime();
328  Krylov_its = solver.NumIters();
329  Krylov_res = solver.TrueResidual();
330  x->Update(1.0,lhs,1.0);
331 
332  FLAG3=1;
333 
334  }
335  }
336  }
337  return 0;
338 }
339 
340 
341 int newtonRaphson::print_newton_solution(std::string fileName){
342 
343  int NumTargetElements = 0;
344  if (MyPID==0){
345  NumTargetElements = 3*interface->Mesh->n_nodes;
346  }
347  Epetra_Map MapOnRoot(-1,NumTargetElements,0,*Comm);
348  Epetra_Export ExportOnRoot(*interface->StandardMap,MapOnRoot);
349  Epetra_MultiVector lhs_root(MapOnRoot,true);
350  lhs_root.Export(*x,ExportOnRoot,Insert);
351 
352  int error = EpetraExt::MultiVectorToMatrixMarketFile(fileName.c_str(),lhs_root,0,0,false);
353 
354  return error;
355 }
356 
358  x->PutScalar(0.0);
359 }
360 
361 void newtonRaphson::setInitialization(Epetra_Vector & init){
362  *x = init;
363 }
364 
366 }
Epetra_Comm * Comm
int Solve_with_Aztec(bool print)
Teuchos::ParameterList * Krylov
Epetra_FECrsGraph * FEGraph
void setInitialization(Epetra_Vector &init)
Epetra_Vector * x
nonLinearFiniteElementProblem * interface
void setParameters(Teuchos::ParameterList &Parameters)
newtonRaphson(nonLinearFiniteElementProblem &Interface, Teuchos::ParameterList &Parameters)
Epetra_Map * StandardMap
int print_newton_solution(std::string fileName)
Epetra_Comm * Comm
int n_nodes
Definition: meshpp.hpp:87
virtual void apply_dirichlet_conditions(Epetra_FECrsMatrix &K, Epetra_FEVector &F, double &displacement)=0
virtual void get_matrix_and_rhs(Epetra_Vector &x, Epetra_FECrsMatrix &K, Epetra_FEVector &F)=0
int Solve_with_Stratimikos(Teuchos::RCP< Teuchos::ParameterList > solverBuilderSL)
double pressure_load