void EigenExecutionerBase::nonlinearSolve(Real rel_tol, Real abs_tol, Real pfactor, Real & k) { makeBXConsistent(k); // turn on nonlinear flag so that eigen kernels opterate on the current solutions _eigen_sys.eigenKernelOnCurrent(); // set nonlinear solver controls Real tol1 = _problem.es().parameters.get<Real> ("nonlinear solver absolute residual tolerance"); Real tol2 = _problem.es().parameters.get<Real> ("linear solver tolerance"); Real tol3 = _problem.es().parameters.get<Real> ("nonlinear solver relative residual tolerance"); _problem.es().parameters.set<Real> ("nonlinear solver absolute residual tolerance") = abs_tol; _problem.es().parameters.set<Real> ("nonlinear solver relative residual tolerance") = rel_tol; _problem.es().parameters.set<Real> ("linear solver tolerance") = pfactor; // call nonlinear solve _problem.solve(); k = _source_integral; _eigenvalue = k; _problem.es().parameters.set<Real> ("nonlinear solver absolute residual tolerance") = tol1; _problem.es().parameters.set<Real> ("linear solver tolerance") = tol2; _problem.es().parameters.set<Real> ("nonlinear solver relative residual tolerance") = tol3; }
void EigenExecutionerBase::nonlinearSolve(Real rel_tol, Real abs_tol, Real pfactor, Real & k) { PostprocessorName bxp = getParam<PostprocessorName>("bx_norm"); if ( _problem.getUserObject<UserObject>(bxp).execFlag() != EXEC_RESIDUAL) mooseError("rhs postprocessor for the nonlinear eigenvalue solve must be executed on residual"); makeBXConsistent(k); // turn on nonlinear flag so that RHS kernels opterate on the current solutions _eigen_sys.eigenKernelOnCurrent(); // set nonlinear solver controls Real tol1 = _problem.es().parameters.get<Real> ("nonlinear solver absolute residual tolerance"); Real tol2 = _problem.es().parameters.get<Real> ("linear solver tolerance"); Real tol3 = _problem.es().parameters.get<Real> ("nonlinear solver relative residual tolerance"); _problem.es().parameters.set<Real> ("nonlinear solver absolute residual tolerance") = abs_tol; _problem.es().parameters.set<Real> ("nonlinear solver relative residual tolerance") = rel_tol; _problem.es().parameters.set<Real> ("linear solver tolerance") = pfactor; // call nonlinear solve _problem.solve(); k = _source_integral; _eigenvalue = k; _problem.es().parameters.set<Real> ("nonlinear solver absolute residual tolerance") = tol1; _problem.es().parameters.set<Real> ("linear solver tolerance") = tol2; _problem.es().parameters.set<Real> ("nonlinear solver relative residual tolerance") = tol3; }
void EigenExecutionerBase::init() { if (_app.isRecovering()) { _console << "\nCannot recover eigenvalue solves!\nExiting...\n" << std::endl; return; } checkIntegrity(); _eigen_sys.buildSystemDoFIndices(EigenSystem::EIGEN); if (getParam<bool>("auto_initialization")) { // Initialize the solution of the eigen variables // Note: initial conditions will override this if there is any by _problem.initialSetup() _eigen_sys.initSystemSolution(EigenSystem::EIGEN, 1.0); } _problem.initialSetup(); _eigen_sys.initSystemSolutionOld(EigenSystem::EIGEN, 0.0); // check when the postprocessors are evaluated ExecFlagType bx_execflag = _problem.getUserObject<UserObject>(getParam<PostprocessorName>("bx_norm")).execBitFlags(); if ((bx_execflag & EXEC_LINEAR) == EXEC_NONE) mooseError("Postprocessor "+getParam<PostprocessorName>("bx_norm")+" requires execute_on = 'linear'"); if (isParamValid("normalization")) _norm_execflag = _problem.getUserObject<UserObject>(getParam<PostprocessorName>("normalization")).execBitFlags(); else _norm_execflag = bx_execflag; // check if _source_integral has been evaluated during initialSetup() if ((bx_execflag & EXEC_INITIAL) == EXEC_NONE) { _problem.computeUserObjects(EXEC_LINEAR, UserObjectWarehouse::PRE_AUX); _problem.computeAuxiliaryKernels(EXEC_LINEAR); _problem.computeUserObjects(EXEC_LINEAR, UserObjectWarehouse::POST_AUX); } if (_source_integral==0.0) mooseError("|Bx| = 0!"); // normalize solution to make |Bx|=_eigenvalue, _eigenvalue at this point has the initialized value makeBXConsistent(_eigenvalue); /* a time step check point */ _problem.onTimestepEnd(); Moose::setup_perf_log.push("Output Initial Condition","Setup"); // Write the initial. // Note: We need to tempararily change the system time to make the output system work properly. _problem.timeStep() = 0; Real t = _problem.time(); _problem.time() = _problem.timeStep(); _problem.outputStep(EXEC_INITIAL); _problem.time() = t; Moose::setup_perf_log.pop("Output Initial Condition","Setup"); }
void EigenExecutionerBase::init() { if (_app.isRecovering()) { _console << "\nCannot recover eigenvalue solves!\nExiting...\n" << std::endl; return; } checkIntegrity(); _eigen_sys.buildSystemDoFIndices(EigenSystem::EIGEN); if (getParam<bool>("auto_initialization")) { // Initialize the solution of the eigen variables // Note: initial conditions will override this if there is any by _problem.initialSetup() _eigen_sys.initSystemSolution(EigenSystem::EIGEN, 1.0); } _problem.initialSetup(); if (_source_integral==0.0) mooseError("|Bx| = 0!"); _eigen_sys.initSystemSolutionOld(EigenSystem::EIGEN, 0.0); // check when the postprocessors are evaluated // TODO: Multiple execFlags support _bx_execflag = _problem.getUserObject<UserObject>(getParam<PostprocessorName>("bx_norm")).execFlags()[0]; if (_solution_diff) _xdiff_execflag = _problem.getUserObject<UserObject>(getParam<PostprocessorName>("xdiff")).execFlags()[0]; else _xdiff_execflag = EXEC_TIMESTEP; if (isParamValid("normalization")) _norm_execflag = _problem.getUserObject<UserObject>(getParam<PostprocessorName>("normalization")).execFlags()[0]; else _norm_execflag = _bx_execflag; // normalize solution to make |Bx|=_eigenvalue, _eigenvalue at this point has the initialized value makeBXConsistent(_eigenvalue); /* a time step check point */ _problem.onTimestepEnd(); Moose::setup_perf_log.push("Output Initial Condition","Setup"); // Write the initial. // Note: We need to tempararily change the system time to make the output system work properly. _problem.timeStep() = 0; Real t = _problem.time(); _problem.time() = _problem.timeStep(); _output_warehouse.outputInitial(); _problem.time() = t; Moose::setup_perf_log.pop("Output Initial Condition","Setup"); }
void EigenExecutionerBase::inversePowerIteration(unsigned int min_iter, unsigned int max_iter, Real pfactor, bool cheb_on, Real tol_eig, bool echo, PostprocessorName xdiff, Real tol_x, Real & k, Real & initial_res) { mooseAssert(max_iter>=min_iter, "Maximum number of power iterations must be greater than or equal to its minimum"); mooseAssert(pfactor>0.0, "Invaid linear convergence tolerance"); mooseAssert(tol_eig>0.0, "Invalid eigenvalue tolerance"); mooseAssert(tol_x>0.0, "Invalid solution norm tolerance"); // obtain the solution diff const PostprocessorValue * solution_diff = NULL; if (xdiff != "") { solution_diff = &getPostprocessorValueByName(xdiff); ExecFlagType xdiff_execflag = _problem.getUserObject<UserObject>(xdiff).execBitFlags(); if ((xdiff_execflag & EXEC_LINEAR) == EXEC_NONE) mooseError("Postprocessor "+xdiff+" requires execute_on = 'linear'"); } // not perform any iteration when max_iter==0 if (max_iter==0) return; // turn off nonlinear flag so that RHS kernels opterate on previous solutions _eigen_sys.eigenKernelOnOld(); // FIXME: currently power iteration use old and older solutions, // so save old and older solutions before they are changed by the power iteration _eigen_sys.saveOldSolutions(); // save solver control parameters to be modified by the power iteration Real tol1 = _problem.es().parameters.get<Real> ("linear solver tolerance"); unsigned int num1 = _problem.es().parameters.get<unsigned int>("nonlinear solver maximum iterations"); // every power iteration is a linear solve, so set nonlinear iteration number to one _problem.es().parameters.set<Real> ("linear solver tolerance") = pfactor; _problem.es().parameters.set<unsigned int>("nonlinear solver maximum iterations") = 1; if (echo) { _console << std::endl; _console << " Power iterations starts" << std::endl; _console << " ________________________________________________________________________________ " << std::endl; } // some iteration variables Real k_old = 0.0; Real & source_integral_old = getPostprocessorValueOld("bx_norm"); Real saved_source_integral_old = source_integral_old; Chebyshev_Parameters chebyshev_parameters; std::vector<Real> keff_history; std::vector<Real> diff_history; unsigned int iter = 0; // power iteration loop... // Note: |Bx|/k will stay constant one! makeBXConsistent(k); while (true) { if (echo) _console << " Power iteration= "<< iter << std::endl; // important: solutions of aux system is also copied _problem.advanceState(); k_old = k; source_integral_old = _source_integral; preIteration(); _problem.solve(); postIteration(); // save the initial residual if (iter==0) initial_res = _eigen_sys._initial_residual_before_preset_bcs; // update eigenvalue k = k_old * _source_integral / source_integral_old; _eigenvalue = k; if (echo) { // output on screen the convergence history only when we want to and MOOSE output system is not used keff_history.push_back(k); if (solution_diff) diff_history.push_back(*solution_diff); std::stringstream ss; if (solution_diff) { ss << std::endl; ss << " +================+=====================+=====================+\n"; ss << " | iteration | eigenvalue | solution_difference |\n"; ss << " +================+=====================+=====================+\n"; unsigned int j = 0; if (keff_history.size()>10) { ss << " : : : :\n"; j = keff_history.size()-10; } for (; j<keff_history.size(); j++) ss << " | " << std::setw(14) << j << " | " << std::setw(19) << std::scientific << std::setprecision(8) << keff_history[j] << " | " << std::setw(19) << std::scientific << std::setprecision(8) << diff_history[j] << " |\n"; ss << " +================+=====================+=====================+\n" << std::flush; } else { ss << std::endl; ss << " +================+=====================+\n"; ss << " | iteration | eigenvalue |\n"; ss << " +================+=====================+\n"; unsigned int j = 0; if (keff_history.size()>10) { ss << " : : :\n"; j = keff_history.size()-10; } for (; j<keff_history.size(); j++) ss << " | " << std::setw(14) << j << " | " << std::setw(19) << std::scientific << std::setprecision(8) << keff_history[j] << " |\n"; ss << " +================+=====================+\n" << std::flush; ss << std::endl; } _console << ss.str() << std::endl; } // increment iteration number here iter++; if (cheb_on) { chebyshev(chebyshev_parameters, iter, solution_diff); if (echo) _console << " Chebyshev step: " << chebyshev_parameters.icheb << std::endl; } if (echo) _console << " ________________________________________________________________________________ " << std::endl; // not perform any convergence check when number of iterations is less than min_iter if (iter>=min_iter) { // no need to check convergence of the last iteration if (iter!=max_iter) { bool converged = true; Real keff_error = fabs(k_old-k)/k; if (keff_error>tol_eig) converged = false; if (solution_diff) if (*solution_diff > tol_x) converged = false; if (converged) break; } else break; } } source_integral_old = saved_source_integral_old; // restore parameters changed by the executioner _problem.es().parameters.set<Real> ("linear solver tolerance") = tol1; _problem.es().parameters.set<unsigned int>("nonlinear solver maximum iterations") = num1; //FIXME: currently power iteration use old and older solutions, so restore them _eigen_sys.restoreOldSolutions(); }
void EigenExecutionerBase::inversePowerIteration(unsigned int min_iter, unsigned int max_iter, Real pfactor, bool cheb_on, Real tol_eig, Real tol_x, bool echo, bool output_convergence, Real time_base, Real & k, Real & initial_res) { mooseAssert(max_iter>=min_iter, "Maximum number of power iterations must be greater than or equal to its minimum"); mooseAssert(pfactor>0.0, "Invaid linear convergence tolerance"); mooseAssert(tol_eig>0.0, "Invalid eigenvalue tolerance"); mooseAssert(tol_x>0.0, "Invalid solution norm tolerance"); if ( _bx_execflag != EXEC_TIMESTEP && _bx_execflag != EXEC_RESIDUAL) mooseError("rhs postprocessor for the power method has to be executed on timestep or residual"); if ( _xdiff_execflag != EXEC_TIMESTEP && _xdiff_execflag != EXEC_RESIDUAL) mooseError("xdiff postprocessor for the power method has to be executed on timestep or residual"); // not perform any iteration when max_iter==0 if (max_iter==0) return; // turn off nonlinear flag so that RHS kernels opterate on previous solutions _eigen_sys.eigenKernelOnOld(); // FIXME: currently power iteration use old and older solutions, // so save old and older solutions before they are changed by the power iteration _eigen_sys.saveOldSolutions(); // _es.parameters.print(Moose::out); // save solver control parameters to be modified by the power iteration Real tol1 = _problem.es().parameters.get<Real> ("linear solver tolerance"); unsigned int num1 = _problem.es().parameters.get<unsigned int>("nonlinear solver maximum iterations"); // every power iteration is a linear solve, so set nonlinear iteration number to one _problem.es().parameters.set<Real> ("linear solver tolerance") = pfactor; _problem.es().parameters.set<unsigned int>("nonlinear solver maximum iterations") = 1; if (echo) { Moose::out << std::endl; Moose::out << " Power iterations starts" << std::endl; Moose::out << " ________________________________________________________________________________ " << std::endl; } // some iteration variables Real k_old = 0.0; std::vector<Real> keff_history; std::vector<Real> diff_history; unsigned int iter = 0; // power iteration loop... // Note: |Bx|/k will stay constant one! makeBXConsistent(k); while (true) { if (echo) Moose::out << " Power iteration= "<< iter << std::endl; // important: solutions of aux system is also copied _problem.copyOldSolutions(); _problem.updateMaterials(); k_old = k; // FIXME: timestep needs to be changed to step _problem.onTimestepBegin(); // this will copy postprocessors to old _problem.timestepSetup(); _problem.computeUserObjects(EXEC_TIMESTEP_BEGIN, UserObjectWarehouse::PRE_AUX); _problem.computeAuxiliaryKernels(EXEC_TIMESTEP_BEGIN); _problem.computeUserObjects(EXEC_TIMESTEP_BEGIN, UserObjectWarehouse::POST_AUX); preIteration(); _problem.solve(); postIteration(); // FIXME: timestep needs to be changed to step _problem.computeUserObjects(EXEC_TIMESTEP, UserObjectWarehouse::PRE_AUX); _problem.computeAuxiliaryKernels(EXEC_TIMESTEP); _problem.computeUserObjects(EXEC_TIMESTEP, UserObjectWarehouse::POST_AUX); _problem.onTimestepEnd(); // save the initial residual if (iter==0) initial_res = _eigen_sys._initial_residual; // update eigenvalue k = k_old * _source_integral / _source_integral_old; // synchronize _eigenvalue with |Bx| for output purpose // Note: if using MOOSE output system, eigenvalue output will be one iteration behind. // Also this will affect EigenKernels with eigen=false. _eigenvalue = k; if (echo && (!output_convergence)) { // output on screen the convergence history only when we want to and MOOSE output system is not used keff_history.push_back(k); if (_solution_diff) diff_history.push_back(*_solution_diff); std::ios_base::fmtflags flg = Moose::out.flags(); std::streamsize pcs = Moose::out.precision(); if (_solution_diff) { Moose::out << std::endl; Moose::out << " +================+=====================+=====================+\n"; Moose::out << " | iteration | eigenvalue | solution_difference |\n"; Moose::out << " +================+=====================+=====================+\n"; unsigned int j = 0; if (keff_history.size()>10) { Moose::out << " : : : :\n"; j = keff_history.size()-10; } for (; j<keff_history.size(); j++) Moose::out << " | " << std::setw(14) << j << " | " << std::setw(19) << std::scientific << std::setprecision(8) << keff_history[j] << " | " << std::setw(19) << std::scientific << std::setprecision(8) << diff_history[j] << " |\n"; Moose::out << " +================+=====================+=====================+\n" << std::flush; Moose::out << std::endl; } else { Moose::out << std::endl; Moose::out << " +================+=====================+\n"; Moose::out << " | iteration | eigenvalue |\n"; Moose::out << " +================+=====================+\n"; unsigned int j = 0; if (keff_history.size()>10) { Moose::out << " : : :\n"; j = keff_history.size()-10; } for (; j<keff_history.size(); j++) Moose::out << " | " << std::setw(14) << j << " | " << std::setw(19) << std::scientific << std::setprecision(8) << keff_history[j] << " |\n"; Moose::out << " +================+=====================+\n" << std::flush; Moose::out << std::endl; } Moose::out.flags(flg); Moose::out.precision(pcs); } // increment iteration number here iter++; if (cheb_on) { chebyshev(iter); if (echo) Moose::out << " Chebyshev step: " << chebyshev_parameters.icheb << std::endl; } if (echo) Moose::out << " ________________________________________________________________________________ " << std::endl; // not perform any convergence check when number of iterations is less than min_iter if (iter>=min_iter) { // no need to check convergence of the last iteration if (iter!=max_iter) { bool converged = true; Real keff_error = fabs(k_old-k)/k; if (keff_error>tol_eig) converged = false; if (_solution_diff) if (*_solution_diff > tol_x) converged = false; if (converged) break; } else break; } // use output system to dump iteration history if (output_convergence) { // we need to tempararily change system time to obtain the right output // FIXME: if 'step' capability is available, we will not need to do this. Real t = _problem.time(); _problem.time() = time_base + Real(iter)/max_iter; _output_warehouse.outputStep(); _problem.time() = t; } } // restore parameters changed by the executioner _problem.es().parameters.set<Real> ("linear solver tolerance") = tol1; _problem.es().parameters.set<unsigned int>("nonlinear solver maximum iterations") = num1; //FIXME: currently power iteration use old and older solutions, so restore them _eigen_sys.restoreOldSolutions(); }