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(); }
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 az_lsp(float * a, /* input : LP filter coefficients */ float * lsp, /* output: Line spectral pairs (in the cosine domain) */ float * old_lsp /* input : LSP vector from past frame */ ) { int i, j, nf, ip; float xlow, ylow, xhigh, yhigh, xmid, ymid, xint; float *coef; float f1[NC + 1], f2[NC + 1]; /*-------------------------------------------------------------* * find the sum and diff polynomials F1(z) and F2(z) * * F1(z) = [A(z) + z^11 A(z^-1)]/(1+z^-1) * * F2(z) = [A(z) - z^11 A(z^-1)]/(1-z^-1) * *-------------------------------------------------------------*/ f1[0] = (float) 1.0; f2[0] = (float) 1.0; for (i = 1, j = M; i <= NC; i++, j--) { f1[i] = a[i] + a[j] - f1[i - 1]; f2[i] = a[i] - a[j] + f2[i - 1]; } /*---------------------------------------------------------------------* * Find the LSPs (roots of F1(z) and F2(z) ) using the * * Chebyshev polynomial evaluation. * * The roots of F1(z) and F2(z) are alternatively searched. * * We start by finding the first root of F1(z) then we switch * * to F2(z) then back to F1(z) and so on until all roots are found. * * * * - Evaluate Chebyshev pol. at grid points and check for sign change.* * - If sign change track the root by subdividing the interval * * NO_ITER times and ckecking sign change. * *---------------------------------------------------------------------*/ nf = 0; /* number of found frequencies */ ip = 0; /* flag to first polynomial */ coef = f1; /* start with F1(z) */ xlow = grid[0]; ylow = chebyshev(xlow, coef, NC); j = 0; while ((nf < M) && (j < GRID_POINTS)) { j++; xhigh = xlow; yhigh = ylow; xlow = grid[j]; ylow = chebyshev(xlow, coef, NC); if (ylow * yhigh <= (float) 0.0) { /* if sign change new root exists */ j--; /* divide the interval of sign change by 4 */ for (i = 0; i < 4; i++) { xmid = (float) 0.5 *(xlow + xhigh); ymid = chebyshev(xmid, coef, NC); if (ylow * ymid <= (float) 0.0) { yhigh = ymid; xhigh = xmid; } else { ylow = ymid; xlow = xmid; } } /* linear interpolation for evaluating the root */ xint = xlow - ylow * (xhigh - xlow) / (yhigh - ylow); lsp[nf] = xint; /* new root */ nf++; ip = 1 - ip; /* flag to other polynomial */ coef = ip ? f2 : f1; /* pointer to other polynomial */ xlow = xint; ylow = chebyshev(xlow, coef, NC); } } /* Check if M roots found */ /* if not use the LSPs from previous frame */ if (nf < M) { for (i = 0; i < M; i++) lsp[i] = old_lsp[i]; } return; }