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

📄 multiadaptivejacobian.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/math/dolfin_math.h>#include <dolfin/la/uBlasVector.h>#include "ODE.h"#include "Method.h"#include "MultiAdaptiveTimeSlab.h"#include "MultiAdaptiveNewtonSolver.h"#include "MultiAdaptiveJacobian.h"using namespace dolfin;//-----------------------------------------------------------------------------MultiAdaptiveJacobian::MultiAdaptiveJacobian(MultiAdaptiveNewtonSolver& newton,					     MultiAdaptiveTimeSlab& timeslab)  : TimeSlabJacobian(timeslab), newton(newton), ts(timeslab),    Jvalues(0), Jindices(0), Jlookup(0){  // Allocate Jacobian row indices  Jindices = new uint[ode.size()];    // Compute start of each row  uint sum = 0;  for (uint i = 0; i < ode.size(); i++)  {    Jindices[i] = sum;    sum += ode.dependencies[i].size();  }  // Allocate Jacobian values  Jvalues = new real[sum];  for (uint pos = 0; pos < sum; pos++)    Jvalues[pos] = 0.0;  message("Generated Jacobian data structure for %d dependencies.", sum);  // Compute maximum number of dependencies  uint maxsize = 0;  for (uint i = 0; i < ode.size(); i++)  {    const uint size = ode.dependencies[i].size();    if ( size > maxsize )      maxsize = size;  }  // Allocate lookup table for dependencies to components with small time steps  Jlookup = new real[std::max(static_cast<unsigned int>(1), maxsize - 1)];}//-----------------------------------------------------------------------------MultiAdaptiveJacobian::~MultiAdaptiveJacobian(){  if ( Jvalues ) delete [] Jvalues;  if ( Jindices ) delete [] Jindices;  if ( Jlookup ) delete [] Jlookup;}//-----------------------------------------------------------------------------dolfin::uint MultiAdaptiveJacobian::size(uint dim) const{  return ts.nj;}//-----------------------------------------------------------------------------void MultiAdaptiveJacobian::mult(const uBlasVector& x, uBlasVector& y) const{  // We iterate over all degrees of freedom j in the time slab and compute  // y_j = (Ax)_j for each degree of freedom of the system.  // Start with y = x, accounting for the derivative dF_j/dx_j = 1  y = x;  // Choose method  if ( method.type() == Method::cG )    cGmult(x, y);  else    dGmult(x, y);}//-----------------------------------------------------------------------------void MultiAdaptiveJacobian::init(){  // Compute Jacobian at the beginning of the slab  real t = ts.starttime();  //message("Recomputing Jacobian matrix at t = %f.", t);    // Compute Jacobian  for (uint i = 0; i < ode.size(); i++)  {    const Array<uint>& deps = ode.dependencies[i];    for (uint pos = 0; pos < deps.size(); pos++)      Jvalues[Jindices[i] + pos] = ode.dfdu(ts.u0, t, i, deps[pos]);  }  /*  // Compute Jacobian at the end of the slab  real t = ts.endtime();  //message("Recomputing Jacobian matrix at t = %f.", t);    // Compute Jacobian  for (uint i = 0; i < ode.size(); i++)  {    const Array<uint>& deps = ode.dependencies[i];    for (uint pos = 0; pos < deps.size(); pos++)      Jvalues[Jindices[i] + pos] = ode.dfdu(ts.u, t, i, deps[pos]);  }  */}//-----------------------------------------------------------------------------void MultiAdaptiveJacobian::cGmult(const uBlasVector& x, uBlasVector& y) const{  // Reset current sub slab  int s0 = -1;  // Reset elast  for (uint i = 0; i < ts.N; i++)    ts.elast[i] = -1;  // Iterate over all elements  for (uint e0 = 0; e0 < ts.ne; e0++)  {    // Cover all elements in current sub slab    s0 = ts.coverNext(s0, e0);        // Get element data    const uint i0 = ts.ei[e0];    const real a0 = ts.sa[s0];    const real b0 = ts.sb[s0];    const real k0 = b0 - a0;    const uint j0 = e0 * method.nsize();        // Add dependency on predecessor for all dofs of element    const int ep = ts.ee[e0];    if ( ep != -1 )    {      const real xp = x[ep*method.nsize() + method.nsize() - 1];      for (uint n = 0; n < method.nsize(); n++)	y[j0 + n] -= xp;    }    // Reset Jpos    uint Jpos = 0;    // Iterate over dependencies for the current component    const Array<uint>& deps = ode.dependencies[i0];    for (uint pos = 0; pos < deps.size(); pos++)    {      // Get derivative      const real dfdu = Jvalues[Jindices[i0] + pos];      // Skip elements which have not been covered      const uint i1 = deps[pos];      const int e1 = ts.elast[i1];            if ( e1 == -1 )      {	// Save dependency for later	Jlookup[Jpos++] = dfdu;	continue;      }      // Skip elements with smaller time steps      const uint s1 = ts.es[e1];      const real b1 = ts.sb[s1];      if ( b1 < (a0 + DOLFIN_EPS) )      {	// Save dependency for later	Jlookup[Jpos++] = dfdu;	// Add dependency to initial value for all dofs	const real tmp = k0 * dfdu * x[e1 * method.nsize() + method.nsize() - 1];	for (uint n = 0; n < method.nsize(); n++)	  y[j0 + n] -= tmp * method.nweight(n, 0);       	continue;      }            // Get first dof for other element      const uint j1 = e1 * method.nsize();            // Use fast evaluation for elements in the same sub slab      if ( s0 == static_cast<int>(s1) )      {	// Add dependency to dof of initial value if any	const int ep = ts.ee[e1];	const real tmp0 = k0 * dfdu;	if ( ep != -1 )	{	  const real tmp1 = tmp0 * x[ep * method.nsize() + method.nsize() - 1];	  for (uint n = 0; n < method.nsize(); n++)	    y[j0 + n] -= tmp1 * method.nweight(n, 0);	}		// Add dependencies to internal dofs	for (uint n = 0; n < method.nsize(); n++)	{	  real sum = 0.0;	  for (uint m = 0; m < method.nsize(); m++)	    sum += method.nweight(n, m + 1) * x[j1 + m];	  y[j0 + n] -= tmp0 * sum;	}      }      else      {	const real a1 = ts.sa[s1];	const real k1 = b1 - a1;		// Iterate over dofs of element	const real tmp0 = k0 * dfdu;	for (uint n = 0; n < method.nsize(); n++)	{	  // Iterate over quadrature points	  real sum = 0.0;	  for (uint m = 0; m < method.qsize(); m++)	  {	    const real tau = (a0 + k0*method.qpoint(m) - a1) / k1;	    const real tmp1 = method.nweight(n, m);	    dolfin_assert(tau >= -DOLFIN_EPS);	    dolfin_assert(tau <= 1.0 + DOLFIN_EPS);	    	    // Add dependency to dof of initial value if any	    const int ep = ts.ee[e1];	    if ( ep != -1 )	    {	      const real x0 = x[ep * method.nsize() + method.nsize() - 1];	      sum += tmp1 * method.eval(0, tau) * x0;	    }	    	    // Iterate over dofs of other element and add dependencies	    for (uint l = 0; l < method.nsize(); l++)	      sum += tmp1 * method.eval(l + 1, tau) * x[j1 + l];	  }	    	  // Add dependencies	  y[j0 + n] -= tmp0 * sum;	}      }          }        // At this point, we have added dependencies to the predecessor,    // to dofs in the same sub slab and to components with larger time    // steps. It remains to add dependencies to components with    // smaller time steps. We need to do this by iterating over    // quadrature points, since this is the order in which the    // dependencies are stored.    // Get first dependency to components with smaller time steps for element    uint d = ts.ed[e0];        // Compute number of such dependencies for each nodal point    const uint end = ( e0 < (ts.ne - 1) ? ts.ed[e0 + 1] : ts.nd );    const uint ndep = (end - d) / method.nsize();    dolfin_assert(ndep * method.nsize() == (end - d));    // Iterate over quadrature points of current element    for (uint m = 1; m < method.qsize(); m++)    {      // Compute quadrature point      const real t = a0 + k0*method.qpoint(m);      // Iterate over dependencies      for (uint dep = 0; dep < ndep; dep++)      {	// Get element data	const uint e1 = ts.de[d++];	const uint j1 = e1 * method.nsize();	const uint s1 = ts.es[e1];	//const uint i1 = ts.ei[e1];	const real a1 = ts.sa[s1];	const real b1 = ts.sb[s1];	const real k1 = b1 - a1;	const real tau = (t - a1) / k1;		// We don't know how to index Jvalues here and want to avoid	// searching, but we were clever enough to pick out the value	// before when we had the chance... :-)	const real dfdu = Jlookup[dep];	//message("Looks like df_%d/du_%d = %f", i0, i1, dfdu);      		// Iterate over quadrature points of other element	const real tmp0 = k0 * dfdu;	for (uint l = 0; l < method.qsize(); l++)	{	  real tmp1 = tmp0 * method.eval(l, tau);	  if ( l == 0 )	  {	    const int ep = ts.ee[e1];	    if ( ep != -1 )	    {	      // Iterate over dofs of current element	      tmp1 *= x[ep*method.nsize() + method.nsize() - 1];	      for (uint n = 0; n < method.nsize(); n++)		y[j0 + n] -= tmp1 * method.nweight(n, m);			    }	  }	  else	  {	    // Iterate over dofs of current element	    tmp1 *= x[j1 + l - 1];	    for (uint n = 0; n < method.nsize(); n++)	      y[j0 + n] -= tmp1 * method.nweight(n, m);			  }	}      }    }  }}//-----------------------------------------------------------------------------void MultiAdaptiveJacobian::dGmult(const uBlasVector& x, uBlasVector& y) const{  // Reset current sub slab  int s0 = -1;  // Reset elast  for (uint i = 0; i < ts.N; i++)    ts.elast[i] = -1;  // Iterate over all elements  for (uint e0 = 0; e0 < ts.ne; e0++)  {    // Cover all elements in current sub slab    s0 = ts.coverNext(s0, e0);        // Get element data    const uint i0 = ts.ei[e0];    const real a0 = ts.sa[s0];    const real b0 = ts.sb[s0];    const real k0 = b0 - a0;    const uint j0 = e0 * method.nsize();        // Add dependency on predecessor for all dofs of element    const int ep = ts.ee[e0];    if ( ep != -1 )    {      const real xp = x[ep*method.nsize() + method.nsize() - 1];      for (uint n = 0; n < method.nsize(); n++)	y[j0 + n] -= xp;    }    // Reset Jpos    uint Jpos = 0;    // Iterate over dependencies for the current component    const Array<uint>& deps = ode.dependencies[i0];    for (uint pos = 0; pos < deps.size(); pos++)    {      // Get derivative      const real dfdu = Jvalues[Jindices[i0] + pos];      // Skip elements which have not been covered      const uint i1 = deps[pos];      const int e1 = ts.elast[i1];            if ( e1 == -1 )      {	// Save dependency for later	Jlookup[Jpos++] = dfdu;	continue;      }      // Skip elements with smaller time steps      const uint s1 = ts.es[e1];      const real b1 = ts.sb[s1];      if ( b1 < (a0 + DOLFIN_EPS) )      {	// Save dependency for later	Jlookup[Jpos++] = dfdu;       	continue;      }            // Get first dof for other element      const uint j1 = e1 * method.nsize();            // Use fast evaluation for elements in the same sub slab      if ( s0 == static_cast<int>(s1) )      {	const real tmp = k0 * dfdu;	for (uint n = 0; n < method.nsize(); n++)	{	  real sum = 0.0;	  for (uint m = 0; m < method.qsize(); m++)	    sum += method.nweight(n, m) * x[j1 + m];	  y[j0 + n] -= tmp * sum;	}      }      else      {	const real a1 = ts.sa[s1];	const real k1 = b1 - a1;		// Iterate over dofs of element	const real tmp0 = k0 * dfdu;	for (uint n = 0; n < method.nsize(); n++)	{	  // Iterate over quadrature points	  real sum = 0.0;	  for (uint m = 0; m < method.qsize(); m++)	  {	    const real tau = (a0 + k0*method.qpoint(m) - a1) / k1;	    const real tmp1 = method.nweight(n, m);	    	    // Iterate over dofs of other element and add dependencies	    for (uint l = 0; l < method.nsize(); l++)	      sum += tmp1 * method.eval(l, tau) * x[j1 + l];	  }	  	  // Add dependencies	  y[j0 + n] -= tmp0 * sum;	}      }    }        // At this point, we have added dependencies to the predecessor,    // to dofs in the same sub slab and to components with larger time    // steps. It remains to add dependencies to components with    // smaller time steps. We need to do this by iterating over    // quadrature points, since this is the order in which the    // dependencies are stored.    // Get first dependency to components with smaller time steps for element    uint d = ts.ed[e0];        // Compute number of such dependencies for each nodal point    const uint end = ( e0 < (ts.ne - 1) ? ts.ed[e0 + 1] : ts.nd );    const uint ndep = (end - d) / method.nsize();    dolfin_assert(ndep * method.nsize() == (end - d));    // Iterate over quadrature points of current element    for (uint m = 0; m < method.qsize(); m++)    {      // Compute quadrature point      const real t = a0 + k0*method.qpoint(m);      // Iterate over dependencies      for (uint dep = 0; dep < ndep; dep++)      {	// Get element data	const uint e1 = ts.de[d++];	const uint j1 = e1 * method.nsize();	const uint s1 = ts.es[e1];	//const uint i1 = ts.ei[e1];	const real a1 = ts.sa[s1];	const real b1 = ts.sb[s1];	const real k1 = b1 - a1;	const real tau = (t - a1) / k1;		// We don't know how to index Jvalues here and want to avoid	// searching, but we were clever enough to pick out the value	// before when we had the chance... :-)	const real dfdu = Jlookup[dep];	//message("Looks like df_%d/du_%d = %f", i0, i1, dfdu);      		// Iterate over quadrature points of other element	const real tmp0 = k0 * dfdu;	for (uint l = 0; l < method.qsize(); l++)	{	  real tmp1 = tmp0 * method.eval(l, tau) * x[j1 + l];	  for (uint n = 0; n < method.nsize(); n++)	    y[j0 + n] -= tmp1 * method.nweight(n, m);	}      }    }  }}//-----------------------------------------------------------------------------

⌨️ 快捷键说明

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