Example #1
0
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;
}
Example #2
0
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;
}
Example #3
0
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");
}
Example #4
0
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");
}
Example #5
0
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();
}
Example #6
0
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();
}