final double volShift = 1e-4;
final LocalVolatilitySurfaceStrike localVolatilityUp = new LocalVolatilitySurfaceStrike(SurfaceShiftFunctionFactory.getShiftedSurface(localVolatility.getSurface(), volShift, true));
final LocalVolatilitySurfaceStrike localVolatilityDown = new LocalVolatilitySurfaceStrike(SurfaceShiftFunctionFactory.getShiftedSurface(localVolatility.getSurface(), -volShift, true));
final PDEFullResults1D pdeRes = runForwardPDESolver(forwardCurve, localVolatility, isCall, _theta, expiry, _maxAbsProxyDelta,
_timeSteps, _spaceSteps, _timeGridBunching, _spaceGridBunching, 1.0);
final PDEFullResults1D pdeResForwardUp = runForwardPDESolver(forwardCurve.withFractionalShift(forwardShift), localVolatility, isCall,
_theta, expiry, _maxAbsProxyDelta, _timeSteps, _spaceSteps, _timeGridBunching, _spaceGridBunching, 1.0);
final PDEFullResults1D pdeResForwardDown = runForwardPDESolver(forwardCurve.withFractionalShift(-forwardShift), localVolatility, isCall,
_theta, expiry, _maxAbsProxyDelta, _timeSteps, _spaceSteps, _timeGridBunching, _spaceGridBunching, 1.0);
final PDEFullResults1D pdeResVolUp = runForwardPDESolver(forwardCurve, localVolatilityUp, isCall, _theta, expiry, _maxAbsProxyDelta,
_timeSteps, _spaceSteps, _timeGridBunching, _spaceGridBunching, 1.0);
final PDEFullResults1D pdeResVolDown = runForwardPDESolver(forwardCurve, localVolatilityDown, isCall, _theta, expiry, _maxAbsProxyDelta,
_timeSteps, _spaceSteps, _timeGridBunching, _spaceGridBunching, 1.0);
final PDEResults1D pdeResForwardUpVolUp = runForwardPDESolver(forwardCurve.withFractionalShift(forwardShift), localVolatilityUp, isCall, _theta, expiry, _maxAbsProxyDelta,
_timeSteps, _spaceSteps, _timeGridBunching, _spaceGridBunching, 1.0);
final PDEFullResults1D pdeResForwardUpVolDown = runForwardPDESolver(forwardCurve.withFractionalShift(forwardShift), localVolatilityDown, isCall, _theta, expiry, _maxAbsProxyDelta,
_timeSteps, _spaceSteps, _timeGridBunching, _spaceGridBunching, 1.0);
final PDEFullResults1D pdeResForwardDownVolUp = runForwardPDESolver(forwardCurve.withFractionalShift(-forwardShift), localVolatilityUp, isCall, _theta, expiry, _maxAbsProxyDelta,
_timeSteps, _spaceSteps, _timeGridBunching, _spaceGridBunching, 1.0);
final PDEFullResults1D pdeResForwardDownVolDown = runForwardPDESolver(forwardCurve.withFractionalShift(-forwardShift), localVolatilityDown, isCall, _theta, expiry, _maxAbsProxyDelta,
_timeSteps, _spaceSteps, _timeGridBunching, _spaceGridBunching, 1.0);
final double[] timeNodes = pdeRes.getGrid().getTimeNodes();
final double[] spaceNodes = pdeRes.getGrid().getSpaceNodes();
final int n = pdeRes.getNumberSpaceNodes();