3 #include "../../include/matrixFreePDE.h" 4 #include <deal.II/lac/solver_cg.h> 7 template <
int dim,
int degree>
11 computing_timer.enter_section(
"matrixFreePDE: solveIncrements");
16 if (hasExplicitEquation && !skip_time_dependent){
22 for(
unsigned int fieldIndex=0; fieldIndex<fields.size(); fieldIndex++){
23 currentFieldIndex = fieldIndex;
34 unsigned int invM_size = invM.local_size();
35 for (
unsigned int dof=0; dof<solutionSet[fieldIndex]->local_size(); ++dof){
36 solutionSet[fieldIndex]->local_element(dof)= \
37 invM.local_element(dof%invM_size)*residualSet[fieldIndex]->local_element(dof);
40 if (has_Dirichlet_BCs){
41 constraintsDirichletSet[fieldIndex]->distribute(*solutionSet[fieldIndex]);
44 solutionSet[fieldIndex]->update_ghost_values();
48 if (currentIncrement%userInputs.skip_print_steps==0){
49 double solution_L2_norm = solutionSet[fieldIndex]->l2_norm();
51 sprintf(buffer,
"field '%2s' [explicit solve]: current solution: %12.6e, current residual:%12.6e\n", \
52 fields[fieldIndex].name.c_str(), \
54 residualSet[fieldIndex]->l2_norm());
57 if (!numbers::is_finite(solution_L2_norm)){
58 sprintf(buffer,
"ERROR: field '%s' solution is NAN. exiting.\n\n",
59 fields[fieldIndex].name.c_str());
71 if (hasNonExplicitEquation){
73 bool nonlinear_it_converged =
false;
74 unsigned int nonlinear_it_index = 0;
76 while (!nonlinear_it_converged){
77 nonlinear_it_converged =
true;
83 computeNonexplicitRHS();
85 for(
unsigned int fieldIndex=0; fieldIndex<fields.size(); fieldIndex++){
86 currentFieldIndex = fieldIndex;
90 if (currentIncrement%userInputs.skip_print_steps==0 && userInputs.var_nonlinear[fieldIndex]){
91 sprintf(buffer,
"field '%2s' [nonlinear solve]: current solution: %12.6e, current residual:%12.6e\n", \
92 fields[fieldIndex].name.c_str(), \
93 solutionSet[fieldIndex]->l2_norm(), \
94 residualSet[fieldIndex]->l2_norm());
98 dealii::parallel::distributed::Vector<double> solution_diff = *solutionSet[fieldIndex];
103 for (std::map<types::global_dof_index, double>::const_iterator it=valuesDirichletSet[fieldIndex]->begin(); it!=valuesDirichletSet[fieldIndex]->end(); ++it){
104 if (residualSet[fieldIndex]->in_local_range(it->first)){
105 (*residualSet[fieldIndex])(it->first) = 0.0;
111 if (userInputs.linear_solver_parameters.getToleranceType(fieldIndex) ==
ABSOLUTE_RESIDUAL){
112 tol_value = userInputs.linear_solver_parameters.getToleranceValue(fieldIndex);
115 tol_value = userInputs.linear_solver_parameters.getToleranceValue(fieldIndex)*residualSet[fieldIndex]->l2_norm();
118 SolverControl solver_control(userInputs.linear_solver_parameters.getMaxIterations(fieldIndex), tol_value);
121 SolverCG<vectorType> solver(solver_control);
125 if (fields[fieldIndex].type ==
SCALAR){
127 solver.solve(*
this, dU_scalar, *residualSet[fieldIndex], IdentityMatrix(solutionSet[fieldIndex]->size()));
131 solver.solve(*
this, dU_vector, *residualSet[fieldIndex], IdentityMatrix(solutionSet[fieldIndex]->size()));
135 pcout <<
"\nWarning: implicit solver did not converge as per set tolerances. consider increasing maxSolverIterations or decreasing solverTolerance.\n";
138 if (userInputs.var_nonlinear[fieldIndex]){
141 double damping_coefficient;
143 if (userInputs.nonlinear_solver_parameters.getBacktrackDampingFlag(fieldIndex)){
144 vectorType solutionSet_old = *solutionSet[fieldIndex];
145 double residual_old = residualSet[fieldIndex]->l2_norm();
147 damping_coefficient = 1.0;
148 bool damping_coefficient_found =
false;
149 while (!damping_coefficient_found){
150 if (fields[fieldIndex].type ==
SCALAR){
151 solutionSet[fieldIndex]->sadd(1.0,damping_coefficient,dU_scalar);
154 solutionSet[fieldIndex]->sadd(1.0,damping_coefficient,dU_vector);
157 computeNonexplicitRHS();
159 for (std::map<types::global_dof_index, double>::const_iterator it=valuesDirichletSet[fieldIndex]->begin(); it!=valuesDirichletSet[fieldIndex]->end(); ++it){
160 if (residualSet[fieldIndex]->in_local_range(it->first)){
161 (*residualSet[fieldIndex])(it->first) = 0.0;
165 double residual_new = residualSet[fieldIndex]->l2_norm();
167 if (currentIncrement%userInputs.skip_print_steps==0){
168 pcout <<
" Old residual: " << residual_old <<
" Damping Coeff: " << damping_coefficient <<
" New Residual: " << residual_new << std::endl;
172 if ( (residual_new < (residual_old*userInputs.nonlinear_solver_parameters.getBacktrackResidualDecreaseCoeff(fieldIndex))) || damping_coefficient < 1.0e-4){
173 damping_coefficient_found =
true;
176 damping_coefficient *= userInputs.nonlinear_solver_parameters.getBacktrackStepModifier(fieldIndex);
177 *solutionSet[fieldIndex] = solutionSet_old;
182 damping_coefficient = userInputs.nonlinear_solver_parameters.getDefaultDampingCoefficient(fieldIndex);
184 if (fields[fieldIndex].type ==
SCALAR){
185 solutionSet[fieldIndex]->sadd(1.0,damping_coefficient,dU_scalar);
188 solutionSet[fieldIndex]->sadd(1.0,damping_coefficient,dU_vector);
192 if (currentIncrement%userInputs.skip_print_steps==0){
194 if (fields[fieldIndex].type ==
SCALAR){
195 dU_norm = dU_scalar.l2_norm();
198 dU_norm = dU_vector.l2_norm();
200 sprintf(buffer,
"field '%2s' [implicit solve]: initial residual:%12.6e, current residual:%12.6e, nsteps:%u, tolerance criterion:%12.6e, solution: %12.6e, dU: %12.6e\n", \
201 fields[fieldIndex].name.c_str(), \
202 residualSet[fieldIndex]->l2_norm(), \
203 solver_control.last_value(), \
204 solver_control.last_step(), solver_control.tolerance(), solutionSet[fieldIndex]->l2_norm(), dU_norm);
212 if (fields[fieldIndex].type ==
SCALAR){
213 diff = dU_scalar.l2_norm();
216 diff = dU_vector.l2_norm();
218 if (currentIncrement%userInputs.skip_print_steps==0){
219 pcout <<
"Relative difference between nonlinear iterations: " << diff <<
" " << nonlinear_it_index <<
" " << currentIncrement << std::endl;
222 if (diff > userInputs.nonlinear_solver_parameters.getToleranceValue(fieldIndex) && nonlinear_it_index < userInputs.nonlinear_solver_parameters.getMaxIterations()){
223 nonlinear_it_converged =
false;
227 std::cerr <<
"PRISMS-PF Error: Nonlinear solver tolerance types other than ABSOLUTE_CHANGE have yet to be implemented." << std::endl;
231 if (nonlinear_it_index ==0){
233 if (fields[fieldIndex].type ==
SCALAR){
234 *solutionSet[fieldIndex] += dU_scalar;
237 *solutionSet[fieldIndex] += dU_vector;
240 if (currentIncrement%userInputs.skip_print_steps==0){
242 if (fields[fieldIndex].type ==
SCALAR){
243 dU_norm = dU_scalar.l2_norm();
246 dU_norm = dU_vector.l2_norm();
248 sprintf(buffer,
"field '%2s' [implicit solve]: initial residual:%12.6e, current residual:%12.6e, nsteps:%u, tolerance criterion:%12.6e, solution: %12.6e, dU: %12.6e\n", \
249 fields[fieldIndex].name.c_str(), \
250 residualSet[fieldIndex]->l2_norm(), \
251 solver_control.last_value(), \
252 solver_control.last_step(), solver_control.tolerance(), solutionSet[fieldIndex]->l2_norm(), dU_norm);
259 else if (fields[fieldIndex].pdetype ==
AUXILIARY){
261 if (userInputs.var_nonlinear[fieldIndex] || nonlinear_it_index == 0){
264 if (userInputs.var_nonlinear[fieldIndex]){
265 if (fields[fieldIndex].type ==
SCALAR){
266 dU_scalar = *solutionSet[fieldIndex];
269 dU_vector = *solutionSet[fieldIndex];
275 unsigned int invM_size = invM.local_size();
276 for (
unsigned int dof=0; dof<solutionSet[fieldIndex]->local_size(); ++dof){
277 solutionSet[fieldIndex]->local_element(dof)= \
278 invM.local_element(dof%invM_size)*residualSet[fieldIndex]->local_element(dof);
282 constraintsDirichletSet[fieldIndex]->distribute(*solutionSet[fieldIndex]);
283 solutionSet[fieldIndex]->update_ghost_values();
286 if (currentIncrement%userInputs.skip_print_steps==0){
287 sprintf(buffer,
"field '%2s' [auxiliary solve]: current solution: %12.6e, current residual:%12.6e\n", \
288 fields[fieldIndex].name.c_str(), \
289 solutionSet[fieldIndex]->l2_norm(), \
290 residualSet[fieldIndex]->l2_norm());
295 if (userInputs.var_nonlinear[fieldIndex]){
300 if (fields[fieldIndex].type ==
SCALAR){
301 dU_scalar -= *solutionSet[fieldIndex];
302 diff = dU_scalar.l2_norm();
305 dU_vector -= *solutionSet[fieldIndex];
306 diff = dU_vector.l2_norm();
308 if (currentIncrement%userInputs.skip_print_steps==0){
309 pcout <<
"Relative difference between nonlinear iterations: " << diff <<
" " << nonlinear_it_index <<
" " << currentIncrement << std::endl;
312 if (diff > userInputs.nonlinear_solver_parameters.getToleranceValue(fieldIndex) && nonlinear_it_index < userInputs.nonlinear_solver_parameters.getMaxIterations()){
313 nonlinear_it_converged =
false;
318 std::cerr <<
"PRISMS-PF Error: Nonlinear solver tolerance types other than ABSOLUTE_CHANGE have yet to be implemented." << std::endl;
325 if (!numbers::is_finite(solutionSet[fieldIndex]->l2_norm())){
326 sprintf(buffer,
"ERROR: field '%s' solution is NAN. exiting.\n\n",
327 fields[fieldIndex].name.c_str());
334 nonlinear_it_index++;
338 if (currentIncrement%userInputs.skip_print_steps==0){
339 pcout <<
"wall time: " << time.wall_time() <<
"s\n";
342 computing_timer.exit_section(
"matrixFreePDE: solveIncrements");
346 #include "../../include/matrixFreePDE_template_instantiations.h"
virtual void solveIncrement(bool skip_time_dependent)
dealii::parallel::distributed::Vector< double > vectorType