Index: trunk/npstat/nm/HeatEq1DNeumannBoundary.cc =================================================================== --- trunk/npstat/nm/HeatEq1DNeumannBoundary.cc (revision 694) +++ trunk/npstat/nm/HeatEq1DNeumannBoundary.cc (revision 695) @@ -1,238 +1,241 @@ #include #include #include #include #include #include "npstat/nm/HeatEq1DNeumannBoundary.hh" #include "npstat/nm/ArrayND.hh" #include "npstat/stat/WeightedStatAccumulator.hh" namespace npstat { HeatEq1DNeumannBoundary::HeatEq1DNeumannBoundary( const double* thermalDiffusivity, const unsigned nx, const double h, const double i_dt) : gammas_(nx), D_(nx), DL_(nx-1U), DU_(nx-1U), DU2_(nx-2U), m0_(nx, nx, 1), m1_(nx, nx), IPIV_(nx), dt_(i_dt), intervalWidth_(h), cnt_(0), nx_(nx) { if (nx < 3U) throw std::invalid_argument( "In npstat::HeatEq1DNeumannBoundary constructor: " "not enough spatial discretization cells"); if (h <= 0.0) throw std::invalid_argument( "In npstat::HeatEq1DNeumannBoundary constructor: " "spatial step must be positive"); if (i_dt <= 0.0) throw std::invalid_argument( "In npstat::HeatEq1DNeumannBoundary constructor: " "time step must be positive"); assert(thermalDiffusivity); const double r = i_dt/h/h; for (unsigned i=0; i *gf, *rhs; if (cnt_ % 2) { gf = &m1_; rhs = &m0_; } else { gf = &m0_; rhs = &m1_; } const unsigned nxm1 = nx_ - 1U; for (unsigned cell=0; cell(rhs->data()), &N, &INFO, 1); Private::check_lapack_status(INFO, "npstat::HeatEq1DNeumannBoundary::step", "DGTTRS"); ++cnt_; } Matrix HeatEq1DNeumannBoundary::GF() const { const Matrix* gf; if (cnt_ % 2) gf = &m1_; else gf = &m0_; return gf->T(); } double HeatEq1DNeumannBoundary::gfWidth(const unsigned cell) const { if (cell >= nx_) throw std::invalid_argument( "In npstat::HeatEq1DNeumannBoundary::gfWidth: " "cell index out of range"); const Matrix* gf; if (cnt_ % 2) gf = &m1_; else gf = &m0_; const double* u = (*gf)[cell]; WeightedStatAccumulator acc; for (unsigned j=0; j 0.0) acc.accumulate(j*intervalWidth_, u[j]); const double effco = acc.count(); - return acc.stdev()*sqrt((effco - 1.0)/effco); + if (effco > 1.0) + return acc.stdev()*sqrt((effco - 1.0)/effco); + else + return 0.0; } Matrix HeatEq1DNeumannBoundary::doublyStochasticGF( const double tol, const unsigned maxIter) const { const Matrix* gf; if (cnt_ % 2) gf = &m1_; else gf = &m0_; if (maxIter) { Matrix gfc(gf->T()); gfc *= nx_; const unsigned long len = gfc.length(); ArrayND arr(nx_, nx_); arr.setData(gfc.data(), len); arr.makeCopulaSteps(tol, maxIter); gfc.setData(arr.data(), len); gfc /= nx_; return gfc; } else { Matrix Jn(nx_, nx_); Jn.constFill(1.0/nx_); Matrix W(nx_, nx_, 1); W -= Jn; return W*gf->T()*W + Jn; } } Matrix HeatEq1DNeumannBoundary::diffScheme() const { Matrix lmat(nx_, nx_, 0); const unsigned nxm1 = nx_ - 1U; const unsigned nxm2 = nx_ - 2U; lmat[0][0] = 1.0 + gammas_[0]/2.0 + (gammas_[1]-gammas_[0])/8.0; for (unsigned i=1; i rmat(nx_, nx_, 0); rmat[0][0] = 1.0 - gammas_[0]/2.0 - (gammas_[1]-gammas_[0])/8.0; for (unsigned i=1; i& L = diffScheme(); std::vector > eigen(nx_); L.genEigen(&eigen[0], nx_); double maxEigen = -DBL_MAX; for (unsigned i=0; i maxEigen) maxEigen = absval; } return maxEigen; } }