⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 multiadaptivenewtonsolver.cpp

📁 利用C
💻 CPP
字号:
// Copyright (C) 2005-2008 Anders Logg.// Licensed under the GNU LGPL Version 2.1.//// First added:  2005-01-27// Last changed: 2008-04-22#include <dolfin/common/constants.h>#include <dolfin/log/dolfin_log.h>#include <dolfin/math/dolfin_math.h>#include <dolfin/parameter/parameters.h>#include <dolfin/la/uBlasSparseMatrix.h>#include "Alloc.h"#include "ODE.h"#include "Method.h"#include "MultiAdaptiveTimeSlab.h"#include "MultiAdaptiveJacobian.h"#include "UpdatedMultiAdaptiveJacobian.h"#include "MultiAdaptiveNewtonSolver.h"using namespace dolfin;//-----------------------------------------------------------------------------MultiAdaptiveNewtonSolver::MultiAdaptiveNewtonSolver(MultiAdaptiveTimeSlab& timeslab)  : TimeSlabSolver(timeslab), ts(timeslab), A(0),    mpc(timeslab, method), solver(mpc), f(0), u(0), num_elements(0), num_elements_mono(0),    updated_jacobian(ode.get("ODE updated jacobian")){  // Initialize local arrays  f = new real[method.qsize()];  u = new real[method.nsize()];    // Don't report number of GMRES iteration if not asked to  solver.set("Krylov report", monitor);  solver.set("Krylov absolute tolerance", 0.01);  solver.set("Krylov relative tolerance", 0.01*tol);    // Initialize Jacobian  if ( updated_jacobian )    A = new UpdatedMultiAdaptiveJacobian(*this, timeslab);  else    A = new MultiAdaptiveJacobian(*this, timeslab);}//-----------------------------------------------------------------------------MultiAdaptiveNewtonSolver::~MultiAdaptiveNewtonSolver(){  // Compute multi-adaptive efficiency index  if ( num_elements > 0 )  {    const real alpha = num_elements_mono / static_cast<real>(num_elements);    message("Multi-adaptive efficiency index: %.3f", alpha);  }    // Delete local arrays  if ( f ) delete [] f;  if ( u ) delete [] u;  // Delete Jacobian  delete A;}//-----------------------------------------------------------------------------void MultiAdaptiveNewtonSolver::end(){  num_elements += ts.ne;  num_elements_mono += ts.length() / ts.kmin * static_cast<real>(ts.ode.size());}//-----------------------------------------------------------------------------void MultiAdaptiveNewtonSolver::start(){  // Get size of system  int nj = static_cast<int>(ts.nj);  // Initialize increment vector  dx.init(nj);  // Initialize right-hand side  b.init(nj);    // Recompute Jacobian on each time slab  A->init();  //debug();  //A->disp(true, 10);}//-----------------------------------------------------------------------------real MultiAdaptiveNewtonSolver::iteration(real tol, uint iter,					  real d0, real d1){  // Evaluate b = -F(x) at current x  Feval(b);   // FIXME: Scaling needed for PETSc Krylov solver, but maybe not for uBlas?  // Save norm of old solution  xnorm = 0.0;  for (uint j = 0; j < ts.nj; j++)    xnorm = std::max(xnorm, std::abs(ts.jx[j]));    // Solve linear system  const real r = b.norm(linf) + DOLFIN_EPS;  b /= r;  num_local_iterations += solver.solve(*A, dx, b);  dx *= r;  // Update solution x -> x + dx (note: b = -F)  for (uint j = 0; j < ts.nj; j++)    ts.jx[j] += dx[j];  // Compute maximum increment  real max_increment = 0.0;  for (uint j = 0; j < ts.nj; j++)  {    const real increment = fabs(dx[j]);    if ( increment > max_increment )      max_increment = increment;  }  return max_increment;}//-----------------------------------------------------------------------------dolfin::uint MultiAdaptiveNewtonSolver::size() const{  return ts.nj;}//-----------------------------------------------------------------------------void MultiAdaptiveNewtonSolver::Feval(uBlasVector& F){  // Reset dof  uint j = 0;  // Reset current sub slab  int s = -1;  // Reset elast  for (uint i = 0; i < ts.N; i++)    ts.elast[i] = -1;  // Iterate over all elements  for (uint e = 0; e < ts.ne; e++)  {    // Cover all elements in current sub slab    s = ts.coverNext(s, e);    // Get element data    const uint i = ts.ei[e];    const real a = ts.sa[s];    const real b = ts.sb[s];    const real k = b - a;    // Get initial value for element    const int ep = ts.ee[e];    const real x0 = ( ep != -1 ? ts.jx[ep*method.nsize() + method.nsize() - 1] : ts.u0[i] );    // Evaluate right-hand side at quadrature points of element    if ( method.type() == Method::cG )      ts.cGfeval(f, s, e, i, a, b, k);    else      ts.dGfeval(f, s, e, i, a, b, k);      //cout << "f = "; Alloc::disp(f, method.qsize());    // Update values on element using fixed-point iteration    method.update(x0, f, k, u);        // Subtract current values    for (uint n = 0; n < method.nsize(); n++)      F[j + n] = u[j] - ts.jx[j + n];    // Update dof    j += method.nsize();  }}//-----------------------------------------------------------------------------void MultiAdaptiveNewtonSolver::debug(){  const uint n = ts.nj;  uBlasSparseMatrix B(n, n);  uBlasVector F1(n), F2(n);  ublas_sparse_matrix& _B = B.mat();  // Iterate over the columns of B  for (uint j = 0; j < n; j++)  {    const real xj = ts.jx[j];    real dx = std::max(DOLFIN_SQRT_EPS, DOLFIN_SQRT_EPS * std::abs(xj));		      ts.jx[j] -= 0.5*dx;    Feval(F1);    ts.jx[j] = xj + 0.5*dx;    Feval(F2);    ts.jx[j] = xj;    for (uint i = 0; i < n; i++)    {      real dFdx = (F1[i] - F2[i]) / dx;      if ( fabs(dFdx) > DOLFIN_EPS )        _B(i, j) = dFdx;    }  }  B.disp();}//-----------------------------------------------------------------------------

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -