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

📄 monoadaptivenewtonsolver.cpp

📁 利用C
💻 CPP
字号:
// Copyright (C) 2005-2008 Anders Logg.// Licensed under the GNU LGPL Version 2.1.//// First added:  2005-01-28// 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/uBlasKrylovSolver.h>#include <dolfin/la/uBlasLUSolver.h>#include <dolfin/la/KrylovSolver.h>#include <dolfin/la/LUSolver.h>#include "Alloc.h"#include "ODE.h"#include "Method.h"#include "MonoAdaptiveTimeSlab.h"#include "MonoAdaptiveNewtonSolver.h"#include <dolfin/common/timing.h>using namespace dolfin;//-----------------------------------------------------------------------------MonoAdaptiveNewtonSolver::MonoAdaptiveNewtonSolver(MonoAdaptiveTimeSlab& timeslab, bool implicit)  : TimeSlabSolver(timeslab), implicit(implicit),    piecewise(ode.get("ODE matrix piecewise constant")),    ts(timeslab), A(timeslab, implicit, piecewise),    krylov(0), lu(0), krylov_g(0), lu_g(0){  // Initialize product M*u0 for implicit system  if ( implicit )  {    Mu0.init(ts.N);    Mu0.zero();  }  // Choose linear solver  chooseLinearSolver();}//-----------------------------------------------------------------------------MonoAdaptiveNewtonSolver::~MonoAdaptiveNewtonSolver(){  if ( krylov )    delete krylov;  if ( lu )    delete lu;  if ( krylov_g )    delete krylov_g;  if ( lu_g )    delete lu_g;}//-----------------------------------------------------------------------------void MonoAdaptiveNewtonSolver::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);  // Initialize computation of Jacobian  A.init();  // Precompute product M*u0  if (implicit)    ode.M(ts.u0, Mu0, ts.u0, ts.starttime());  //debug();  //A.disp(true, 10);}//-----------------------------------------------------------------------------real MonoAdaptiveNewtonSolver::iteration(real tol, uint iter, real d0, real d1){  // Evaluate b = -F(x) at current x  Feval(b);  if (krylov)  {    const real r = b.norm(linf) + DOLFIN_EPS;    b /= r;    num_local_iterations += krylov->solve(A, dx, b);    dx *= r;  }  else  {    // FIXME: Implement a better check    if (d1 >= 0.5*d0)      A.update();    lu->solve(A.matrix(), dx, b);  }  // Save norm of old solution  xnorm = ts.x.norm(linf);  // Update solution x <- x + dx (note: b = -F)  ts.x += dx;    // Return maximum increment  return dx.norm(linf);}//-----------------------------------------------------------------------------dolfin::uint MonoAdaptiveNewtonSolver::size() const{  return ts.nj;}//-----------------------------------------------------------------------------void MonoAdaptiveNewtonSolver::Feval(uBlasVector& F){  if ( implicit )    FevalImplicit(F);  else    FevalExplicit(F);}//-----------------------------------------------------------------------------void MonoAdaptiveNewtonSolver::FevalExplicit(uBlasVector& F){  // Compute size of time step  const real k = ts.length();  // Evaluate right-hand side at all quadrature points  for (uint m = 0; m < method.qsize(); m++)    ts.feval(m);  // Update the values at each stage  for (uint n = 0; n < method.nsize(); n++)  {    const uint noffset = n * ts.N;    // Reset values to initial data    for (uint i = 0; i < ts.N; i++)      F[noffset + i] = ts.u0[i];        // Add weights of right-hand side    for (uint m = 0; m < method.qsize(); m++)    {      const real tmp = k * method.nweight(n, m);      const uint moffset = m * ts.N;      for (uint i = 0; i < ts.N; i++)        F[noffset + i] += tmp * ts.fq[moffset + i];    }  }  // Subtract current values  F -= ts.x;}//-----------------------------------------------------------------------------void MonoAdaptiveNewtonSolver::FevalImplicit(uBlasVector& F){  // Use vectors from Jacobian for storing multiplication  uBlasVector& xx = A.xx;  uBlasVector& yy = A.yy;  // Compute size of time step  const real a = ts.starttime();  const real k = ts.length();  // Evaluate right-hand side at all quadrature points  for (uint m = 0; m < method.qsize(); m++)    ts.feval(m);  // Update the values at each stage  for (uint n = 0; n < method.nsize(); n++)  {    const uint noffset = n * ts.N;    // Reset values to initial data    for (uint i = 0; i < ts.N; i++)      F[noffset + i] = Mu0[i];        // Add weights of right-hand side    for (uint m = 0; m < method.qsize(); m++)    {      const real tmp = k * method.nweight(n, m);      const uint moffset = m * ts.N;      for (uint i = 0; i < ts.N; i++)        F[noffset + i] += tmp * ts.fq[moffset + i];    }  }    // Subtract current values  for (uint n = 0; n < method.nsize(); n++)  {    const uint noffset = n * ts.N;    // Copy values to xx    ts.copy(ts.x, noffset, xx, 0, ts.N);    // Do multiplication    if ( piecewise )    {      ode.M(xx, yy, ts.u0, a);    }    else    {      const real t = a + method.npoint(n) * k;      ts.copy(ts.x, noffset, ts.u, 0, ts.N);      ode.M(xx, yy, ts.u, t);    }    // Copy values from yy    for (uint i = 0; i < ts.N; i++)      F[noffset + i] -= yy[i];  }}//-----------------------------------------------------------------------------void MonoAdaptiveNewtonSolver::chooseLinearSolver(){  const std::string linear_solver = ode.get("ODE linear solver");    // First determine if we should use a direct solver  bool direct = false;    if ( linear_solver == "direct" )    direct = true;  else if ( linear_solver == "iterative" )    direct = false;  else if ( linear_solver == "auto" )  {    /*    const uint ode_size_threshold = ode.get("ODE size threshold");    if ( ode.size() > ode_size_threshold )      direct = false;    else      direct = true;    */    // FIXME: Seems to be a bug (check stiff demo)    // so we go with the iterative solver for now    direct = false;  }  // Initialize linear solver  if ( direct )  {    message("Using uBlas direct solver.");    lu = new uBlasLUSolver();  }  else  {    message("Using uBlas Krylov solver with no preconditioning.");    const real ktol = ode.get("ODE discrete Krylov tolerance factor");    // FIXME: Check choice of tolerances    krylov = new uBlasKrylovSolver(none);    krylov->set("Krylov report", monitor);    krylov->set("Krylov relative tolerance", ktol);    krylov->set("Krylov absolute tolerance", ktol*tol);    message("Using BiCGStab Krylov solver for matrix Jacobian");    krylov_g = new KrylovSolver(bicgstab, ilu);    krylov_g->set("Krylov report", monitor);    krylov_g->set("Krylov relative tolerance", ktol);    krylov_g->set("Krylov absolute tolerance", ktol*tol);  }}//-----------------------------------------------------------------------------void MonoAdaptiveNewtonSolver::debug(){  const uint n = ts.nj;  uBlasSparseMatrix B(n, n);  ublas_sparse_matrix& _B = B.mat();  uBlasVector F1(n), F2(n);  // Iterate over the columns of B  for (uint j = 0; j < n; j++)  {    const real xj = ts.x[j];    real dx = std::max(DOLFIN_SQRT_EPS, DOLFIN_SQRT_EPS * std::abs(xj));		      ts.x[j] -= 0.5*dx;    Feval(F1);    ts.x[j] = xj + 0.5*dx;    Feval(F2);        ts.x[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 + -