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

📄 multiadaptivetimeslab.cpp

📁 利用C
💻 CPP
📖 第 1 页 / 共 2 页
字号:
// Copyright (C) 2005-2008 Anders Logg.// Licensed under the GNU LGPL Version 2.1.//// Modified by Garth N. Wells//// First added:  2005-01-27// Last changed: 2008-06-11#include <string>#include <algorithm>#include <dolfin/common/constants.h>#include <dolfin/log/dolfin_log.h>#include <dolfin/parameter/parameters.h>#include "ODE.h"#include "Dependencies.h"#include "Method.h"#include "MultiAdaptiveFixedPointSolver.h"#include "MultiAdaptiveNewtonSolver.h"#include "MultiAdaptiveTimeSlab.h"using namespace dolfin;//-----------------------------------------------------------------------------MultiAdaptiveTimeSlab::MultiAdaptiveTimeSlab(ODE& ode) :   TimeSlab(ode),  sa(0), sb(0), ei(0), es(0), ee(0), ed(0), jx(0), de(0),  ns(0), ne(0), nj(0), nd(0), solver(0), adaptivity(ode, *method), partition(N),  elast(0), f0(0), emax(0), kmin(0){  // Choose solver  solver = chooseSolver();  // Initialize elast  elast = new int[N];  for (uint i = 0; i < N; i++)    elast[i] = -1;  // Initialize f at left end-point for cG  if ( method->type() == Method::cG )    f0 = new real[N];  // Initialize vector for u  u.init(N);  u.zero();  // Initialize transpose of dependencies if necessary  message("Computing transpose (inverse) of dependency pattern.");  if ( ode.dependencies.sparse() && !ode.transpose.sparse() )    ode.transpose.transp(ode.dependencies);}//-----------------------------------------------------------------------------MultiAdaptiveTimeSlab::~MultiAdaptiveTimeSlab(){  if ( sa ) delete [] sa;  if ( sb ) delete [] sb;  if ( ei ) delete [] ei;  if ( es ) delete [] es;  if ( ee ) delete [] ee;  if ( ed ) delete [] ed;  if ( jx ) delete [] jx;  if ( de ) delete [] de;  if ( solver ) delete solver;  if ( elast ) delete [] elast;  if ( f0 ) delete [] f0;}//-----------------------------------------------------------------------------real MultiAdaptiveTimeSlab::build(real a, real b){  //cout << "Multi-adaptive time slab: building between "  //     << a << " and " << b << endl;    // Allocate data  allocData(a, b);  // Reset elast  for (uint i = 0; i < N; i++)    elast[i] = -1;  // Create time slab recursively  kmin = ode.endtime();  b = createTimeSlab(a, b, 0);  //cout << "de = "; Alloc::disp(de, nd);    // Save start and end time  _a = a;  _b = b;  //cout << "Multi-adaptive time slab: finished building between "  //     << a << " and " << b << ": K = " << b - a << ", nj = " << nj << endl;  // Update at t = 0.0  if ( a < DOLFIN_EPS )    ode.update(u0, a, false);  return b;}//-----------------------------------------------------------------------------bool MultiAdaptiveTimeSlab::solve(){  //message("Solving time slab system on [%f, %f].", _a, _b);  // Copy u0 to u. This happens automatically in feval if user has set  // dependencies correctly, but you never know...  for (unsigned int i = 0; i < N; i++)    u[i] = u0[i];  // Compute f at left end-point for cG  if ( method->type() == Method::cG )  {    for (uint i = 0; i < N; i++)      f0[i] = ode.f(u0, _a, i);  }  // Solve system  return solver->solve();  //for (uint i = 0; i < N; i++)  // {  //  real endval = jx[elast[i] * method->nsize() + method->nsize() - 1];  //  message("i = %d: u = %.16e", i, endval);  // }}//-----------------------------------------------------------------------------bool MultiAdaptiveTimeSlab::check(bool first){  // Compute new time steps  adaptivity.update(*this, _b, first);  // Check if current solution can be accepted  return adaptivity.accept();}//-----------------------------------------------------------------------------bool MultiAdaptiveTimeSlab::shift(bool end){  // Cover end time  coverTime(_b);  // Update the solution vector at the end time for each component  for (uint i = 0; i < N; i++)  {    // Get last element of component    const int e = elast[i];    dolfin_assert(e != -1);    dolfin_assert(sb[es[e]] == _b);        // Get end-time value of component    const int j = e * method->nsize();    u[i] = jx[j + method->nsize() - 1];  }  // Write solution at final time if we should  if ( save_final && end )    write(u);  // Let user update ODE  if ( !ode.update(u, _b, end) )    return false;  // Set initial value to end-time value  for (uint i = 0; i < N; i++)    u0[i] = u[i];  return true;}//-----------------------------------------------------------------------------void MultiAdaptiveTimeSlab::reset(){  // Iterate over all elements  uint j = 0;  for (uint e = 0; e < ne; e++)  {    // Get component index    const uint i = ei[e];    // Iterate over degrees of freedom on element    for (uint n = 0; n < method->nsize(); n++)      jx[j + n] = u0[i];    // Step to next element    j += method->nsize();  }}//-----------------------------------------------------------------------------void MultiAdaptiveTimeSlab::sample(real t){  // Cover the given time  coverTime(t);  //cout << "t = " << t << " elast: ";  //for (uint i = 0; i < N; i++)  //  cout << elast[i] << " ";  //cout << endl;}//-----------------------------------------------------------------------------real MultiAdaptiveTimeSlab::usample(uint i, real t){  // Get element  const int e = elast[i];  dolfin_assert(e != -1);  // Get element data  const uint s = es[e];  const uint j = e * method->nsize();  const real a = sa[s];  const real b = sb[s];  const real k = b - a;  // Get initial value for element (only necessary for cG)  const int ep = ee[e];  const uint jp = ep * method->nsize();  const real x0 = ( ep != -1 ? jx[jp + method->nsize() - 1] : u0[i] );    // Evaluate solution  const real tau = (t - a) / k;  const real value = method->ueval(x0, jx + j, tau);  return value;}//-----------------------------------------------------------------------------real MultiAdaptiveTimeSlab::ksample(uint i, real t){  // Get element  const int e = elast[i];  dolfin_assert(e != -1);  // Get element data  const uint s = es[e];  const real a = sa[s];  const real b = sb[s];  // Compute time step  const real k = b - a;  return k;}//-----------------------------------------------------------------------------real MultiAdaptiveTimeSlab::rsample(uint i, real t){  /*  // Note that the residual is always sampled at the end-time    // Cover end time  coverTime(_b);    // Update the solution vector at the end time for each dependent component    // Get list of dependencies for component  const Array<uint>& deps = ode.dependencies[i];    // Iterate over dependencies  for (uint pos = 0; pos < deps.size(); pos++)  {    // Get last element of component    const int e = elast[pos];    dolfin_assert(e != -1);    dolfin_assert(sb[es[e]] == _b);        // Get end-time value of component    const int j = e * method->nsize();    u[pos] = jx[j + method->nsize() - 1];  }    // Compute residual    // Get last element of component  const int e = elast[i];  dolfin_assert(e != -1);    // Get element data  const uint s = es[e];  const uint j = e * method->nsize();  const real a = sa[s];  const real b = sb[s];  const real k = b - a;    // Get initial value for element (only necessary for cG)  const int ep = ee[e];  const uint jp = ep * method->nsize();  const real x0 = ( ep != -1 ? jx[jp + method->nsize() - 1] : u0(i) );    // Evaluate right-hand side at end-point (u is already updated)  const real f = ode.f(u, b, i);    // Compute residual  const real r = method->residual(x0, jx + j, f, k);  */  // Just return previously computed maximum in time slab for component  return adaptivity.residual(i);}//-----------------------------------------------------------------------------void MultiAdaptiveTimeSlab::disp() const{  cout << "--------------------------------------------------------" << endl;  message("s: size = %d alloc = %d", ns, size_s.size);  message("e: size = %d alloc = %d", ne, size_e.size);  message("j: size = %d alloc = %d", nj, size_j.size);  message("d: size = %d alloc = %d", nd, size_d.size);  cout << "sa = "; Alloc::disp(sa, ns);  cout << "sb = "; Alloc::disp(sb, ns);   cout << endl;  cout << "ei = "; Alloc::disp(ei, ne);  cout << "es = "; Alloc::disp(es, ne);    cout << "ee = "; Alloc::disp(ee, ne);  cout << "ed = "; Alloc::disp(ed, ne);  cout << endl;  cout << "jx = "; Alloc::disp(jx, nj);  cout << endl;  cout << "de = "; Alloc::disp(de, nd);}//-----------------------------------------------------------------------------void MultiAdaptiveTimeSlab::allocData(real a, real b){   // Use u to keep track of the latest time value for each component here  for (uint i = 0; i < N; i++)    u[i] = a;    // Recursively compute data size  ns = ne = nj = nd = 0;  computeDataSize(a, b, 0);  // Allocate data  alloc_s(ns);  alloc_e(ne);  alloc_j(nj);  alloc_d(nd);  // Reset mapping de  for (uint d = 0; d < nd; d++)    de[d] = -1;}//-----------------------------------------------------------------------------real MultiAdaptiveTimeSlab::createTimeSlab(real a, real b, uint offset){  // Compute end time of this sub slab  uint end = 0;  b = computeEndTime(a, b, offset, end);  //cout << "Creating sub slab between a = " << a << " and b = " << b << endl;  // Create sub slab  create_s(a, b, offset, end);  // Recursively create sub slabs for components with small time steps  real t = a;  while ( t < b && end < partition.size() )    t = createTimeSlab(t, b, end);    return b;}//-----------------------------------------------------------------------------void MultiAdaptiveTimeSlab::create_s(real a0, real b0, uint offset, uint end){  dolfin_assert(size_s.next < size_s.size);    // Get next available position  uint pos = size_s.next++;  // Create new sub slab  sa[pos] = a0;  sb[pos] = b0;  // Create elements for sub slab  for (uint n = offset; n < end; n++)    create_e(partition.index(n), pos, a0, b0);  // Create mapping ed  for (uint n = offset; n < end; n++)  {    const uint index = partition.index(n);    const int element = elast[index];    dolfin_assert(element != -1);    // Count number of dependencies from element    size_d.next += countDependencies(index, b0);    // Update mapping ed    if ( element == 0 )      ed[element] = 0;    if ( element < static_cast<int>(ne - 1) )      ed[element + 1] = size_d.next;  }}//-----------------------------------------------------------------------------void MultiAdaptiveTimeSlab::create_e(uint index, uint subslab, real a, real b){  dolfin_assert(size_e.next < size_e.size);    // Get next available position  uint pos = size_e.next++;  //message("  Creating element e = %d for i = %d at [%f, %f]", pos, index, a, b);    //if ( index == 145 )  //  cout << "Modified: " << b - a << endl << endl;  // Create new element  ei[pos] = index;  es[pos] = subslab;  ee[pos] = elast[index];  // Create dofs for element  create_j(index);  // Create dependencies to element  create_d(index, pos, subslab, a, b);  // Update elast for component  elast[index] = pos;}//-----------------------------------------------------------------------------void MultiAdaptiveTimeSlab::create_j(uint index){  dolfin_assert((size_j.next + method->nsize() - 1) < size_j.size);  // Get next available position  uint pos = size_j.next;  size_j.next += method->nsize();  // Create dofs  for (uint n = 0; n < method->nsize(); n++)    jx[pos + n] = u0[index];}//-----------------------------------------------------------------------------void MultiAdaptiveTimeSlab::create_d(uint i0, uint e0, uint s0, real a0, real b0){  // Add dependencies to elements that depend on the given element if the  // depending elements use larger time steps    //message("Checking dependencies to element %d (component %d)", element, index);  // Get list of components depending on current component  const Array<uint>& deps = ode.transpose[i0];    // Iterate over dependencies  for (uint pos = 0; pos < deps.size(); pos++)  {    // Get component index of other component    const uint i1 = deps[pos];            // Get other element    const int e1 = elast[i1];        //cout << "  Other element: " << e1 << endl;        // Skip elements which have not been created (use smaller time steps)    if ( e1 == -1 )      continue;        // Get data of other element    const uint s1 = es[e1];    const real a1 = sa[s1];    const real b1 = sb[s1];    const real k1 = b1 - a1;        // Only add dependencies from components with larger time steps    if ( !within(a0, b0, a1, b1) || s0 == s1 )      continue;        //message("  Checking element %d (component %d)", e1, i1);        // Iterate over dofs for element    for (uint n = 0; n < method->nsize(); n++)    {      //const uint j = j1 + n;      const real t = a1 + k1*method->npoint(n);            //message("    Checking dof at t = %f", t);            // Check if dof is contained in the current element      if ( within(t, a0, b0) )      {	// Search for an empty position	bool found = false;		//cout << "    --- Creating dependency to element = " << element << endl;	//cout << "    --- Starting at ed = " << ed[e1] << endl;	//cout << "    de = "; Alloc::disp(ed, ne);	//cout << "    nd = "; Alloc::disp(de, nd);		for (uint d = ed[e1]; d < ed[e1 + 1]; d++)	{	  if ( de[d] == -1 )	  {	    de[d] = e0;	    found = true;	    break;	  }	}	dolfin_assert(found);      }    }  }}//-----------------------------------------------------------------------------void MultiAdaptiveTimeSlab::alloc_s(uint newsize){  size_s.next = 0;  if ( newsize <= size_s.size ) return;  //message("Reallocating: ns = %d", newsize);  Alloc::realloc(&sa, size_s.size, newsize);  Alloc::realloc(&sb, size_s.size, newsize);  size_s.size = newsize;}//-----------------------------------------------------------------------------void MultiAdaptiveTimeSlab::alloc_e(uint newsize){  size_e.next = 0;  if ( newsize <= size_e.size ) return;  //message("Reallocating: ne = %d", newsize);  Alloc::realloc(&ei, size_e.size, newsize);

⌨️ 快捷键说明

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