public void testFlatSurface() { final double theta = 0.5; final double ft = FORWARD_CURVE.getForward(EXPIRY); final double fL = Math.log(ft / 5.0); final double fH = Math.log(5.0 * ft); final ConvectionDiffusionPDESolver solver = new ThetaMethodFiniteDifference(theta, false); final BoundaryCondition lower = new NeumannBoundaryCondition(1.0, fL, true); final BoundaryCondition upper = new NeumannBoundaryCondition(1.0, fH, false); final MeshingFunction timeMesh = new ExponentialMeshing(0, EXPIRY, 100, 0.0); final MeshingFunction spaceMesh = new ExponentialMeshing(fL, fH, 101, 0.0); final PDEGrid1D grid = new PDEGrid1D(timeMesh, spaceMesh); final PDE1DDataBundle<ConvectionDiffusionPDE1DCoefficients> db = new PDE1DDataBundle<>(PDE, INITIAL_COND, lower, upper, grid); final PDEResults1D res = solver.solve(db); final int n = res.getNumberSpaceNodes(); final double kVol = Math.sqrt(-2 * (res.getFunctionValue(n / 2) - Math.log(ft)) / EXPIRY); assertEquals(FLAT_VOL, kVol, 1e-6); final YieldAndDiscountCurve yieldCurve = new YieldCurve("test", ConstantDoublesCurve.from(DRIFT)); final AffineDividends ad = AffineDividends.noDividends(); final EquityVarianceSwapBackwardsPurePDE backSolver = new EquityVarianceSwapBackwardsPurePDE(); final PureLocalVolatilitySurface plv = new PureLocalVolatilitySurface(ConstantDoublesSurface.from(FLAT_VOL)); final double[] res2 = backSolver.expectedVariance(SPOT, yieldCurve, ad, EXPIRY, plv); final double kVol2 = Math.sqrt(res2[0] / EXPIRY); assertEquals(FLAT_VOL, kVol2, 1e-6); }