void testNatural(const Spline &sp, const double *x, const double *y) { // test the common properties of splines testCommon(sp, x, y); static double eps = 1e-5; size_t n = sp.numSamples(); // make sure the second derivatives at both end points are 0 double d0 = sp.evalDerivative(x[0]); double d1 = sp.evalDerivative(x[0] + eps); double d2 = sp.evalDerivative(x[n-1] - eps); double d3 = sp.evalDerivative(x[n-1]); if (std::abs(d1 - d0)/eps > 1000*eps) OPM_THROW(std::runtime_error, "Invalid second derivative at beginning of interval: is " << (d1 - d0)/eps << " ought to be 0"); if (std::abs(d3 - d2)/eps > 1000*eps) OPM_THROW(std::runtime_error, "Invalid second derivative at end of interval: is " << (d3 - d2)/eps << " ought to be 0"); }
void testFull(const Spline &sp, const double *x, const double *y, double m0, double m1) { // test the common properties of splines testCommon(sp, x, y); static double eps = 1e-5; size_t n = sp.numSamples(); // make sure the derivative at both end points is correct double d0 = sp.evalDerivative(x[0]); double d1 = sp.evalDerivative(x[n-1]); if (std::abs(d0 - m0) > eps) OPM_THROW(std::runtime_error, "Invalid derivative at beginning of interval: is " << d0 << " ought to be " << m0); if (std::abs(d1 - m1) > eps) OPM_THROW(std::runtime_error, "Invalid derivative at end of interval: is " << d1 << " ought to be " << m1); }
void testCommon(const Spline &sp, const double *x, const double *y) { static double eps = 1e-10; static double epsFD = 1e-7; size_t n = sp.numSamples(); for (size_t i = 0; i < n; ++i) { // sure that we hit all sampling points double y0 = (i>0)?sp.eval(x[i]-eps):y[0]; double y1 = sp.eval(x[i]); double y2 = (i<n-1)?sp.eval(x[i]+eps):y[n-1]; if (std::abs(y0 - y[i]) > 100*eps || std::abs(y2 - y[i]) > 100*eps) OPM_THROW(std::runtime_error, "Spline seems to be discontinuous at sampling point " << i << "!"); if (std::abs(y1 - y[i]) > eps) OPM_THROW(std::runtime_error, "Spline does not capture sampling point " << i << "!"); // make sure the derivative is continuous (assuming that the // second derivative is smaller than 1000) double d1 = sp.evalDerivative(x[i]); double d0 = (i>0)?sp.evalDerivative(x[i]-eps):d1; double d2 = (i<n-1)?sp.evalDerivative(x[i]+eps):d1; if (std::abs(d1 - d0) > 1000*eps || std::abs(d2 - d0) > 1000*eps) OPM_THROW(std::runtime_error, "Spline seems to exhibit a discontinuous derivative at sampling point " << i << "!"); } // make sure the derivatives are consistent with the curve size_t np = 3*n; for (size_t i = 0; i < np; ++i) { double xMin = sp.xAt(0); double xMax = sp.xAt(sp.numSamples() - 1); double xval = xMin + (xMax - xMin)*i/np; // first derivative double y1 = sp.eval(xval+epsFD); double y0 = sp.eval(xval); double mFD = (y1 - y0)/epsFD; double m = sp.evalDerivative(xval); if (std::abs( mFD - m ) > 1000*epsFD) OPM_THROW(std::runtime_error, "Derivative of spline seems to be inconsistent with cuve" " (" << mFD << " - " << m << " = " << mFD - m << ")!"); // second derivative y1 = sp.evalDerivative(xval+epsFD); y0 = sp.evalDerivative(xval); mFD = (y1 - y0)/epsFD; m = sp.evalSecondDerivative(xval); if (std::abs( mFD - m ) > 1000*epsFD) OPM_THROW(std::runtime_error, "Second derivative of spline seems to be inconsistent with cuve" " (" << mFD << " - " << m << " = " << mFD - m << ")!"); // Third derivative y1 = sp.evalSecondDerivative(xval+epsFD); y0 = sp.evalSecondDerivative(xval); mFD = (y1 - y0)/epsFD; m = sp.evalThirdDerivative(xval); if (std::abs( mFD - m ) > 1000*epsFD) OPM_THROW(std::runtime_error, "Third derivative of spline seems to be inconsistent with cuve" " (" << mFD << " - " << m << " = " << mFD - m << ")!"); } }