void Fd2dBlackScholesVanillaEngine::calculate() const {
        // 1. Payoff
        const ext::shared_ptr<BasketPayoff> payoff =
            ext::dynamic_pointer_cast<BasketPayoff>(arguments_.payoff);

        // 2. Mesher
        const Time maturity = p1_->time(arguments_.exercise->lastDate());
        const ext::shared_ptr<Fdm1dMesher> em1(
            new FdmBlackScholesMesher(
                    xGrid_, p1_, maturity, p1_->x0(), 
                    Null<Real>(), Null<Real>(), 0.0001, 1.5, 
                    std::pair<Real, Real>(p1_->x0(), 0.1)));

        const ext::shared_ptr<Fdm1dMesher> em2(
            new FdmBlackScholesMesher(
                    yGrid_, p2_, maturity, p2_->x0(),
                    Null<Real>(), Null<Real>(), 0.0001, 1.5, 
                    std::pair<Real, Real>(p2_->x0(), 0.1)));

        const ext::shared_ptr<FdmMesher> mesher (
            new FdmMesherComposite(em1, em2));

        // 3. Calculator
        const ext::shared_ptr<FdmInnerValueCalculator> calculator(
                                new FdmLogBasketInnerValue(payoff, mesher));

        // 4. Step conditions
        const ext::shared_ptr<FdmStepConditionComposite> conditions =
            FdmStepConditionComposite::vanillaComposite(
                                    DividendSchedule(), arguments_.exercise, 
                                    mesher, calculator, 
                                    p1_->riskFreeRate()->referenceDate(),
                                    p1_->riskFreeRate()->dayCounter());

        // 5. Boundary conditions
        const FdmBoundaryConditionSet boundaries;

        // 6. Solver
        const FdmSolverDesc solverDesc = { mesher, boundaries,
                                           conditions, calculator,
                                           maturity, tGrid_, dampingSteps_ };

        ext::shared_ptr<Fdm2dBlackScholesSolver> solver(
                new Fdm2dBlackScholesSolver(
                             Handle<GeneralizedBlackScholesProcess>(p1_),
                             Handle<GeneralizedBlackScholesProcess>(p2_),
                             correlation_, solverDesc, schemeDesc_,
                             localVol_, illegalLocalVolOverwrite_));

        const Real x = p1_->x0();
        const Real y = p2_->x0();

        results_.value = solver->valueAt(x, y);
        results_.delta = solver->deltaXat(x, y) + solver->deltaYat(x, y);
        results_.gamma = solver->gammaXat(x, y) + solver->gammaYat(x, y)
             + 2*solver->gammaXYat(x, y);
        results_.theta = solver->thetaAt(x, y);
    }
    void FdExtOUJumpVanillaEngine::calculate() const {
        // 1. Layout

        std::vector<Size> dim;
        dim.push_back(xGrid_);
        dim.push_back(yGrid_);
        const boost::shared_ptr<FdmLinearOpLayout> layout(
                                            new FdmLinearOpLayout(dim));

        // 2. Mesher
        const Time maturity 
            = rTS_->dayCounter().yearFraction(rTS_->referenceDate(),
                                              arguments_.exercise->lastDate());
        const boost::shared_ptr<StochasticProcess1D> ouProcess(
                              process_->getExtendedOrnsteinUhlenbeckProcess());
        const boost::shared_ptr<Fdm1dMesher> xMesher(
                     new FdmSimpleProcess1dMesher(xGrid_, ouProcess,maturity));

        const boost::shared_ptr<Fdm1dMesher> yMesher(
            new ExponentialJump1dMesher(yGrid_, 
                                        process_->beta(), 
                                        process_->jumpIntensity(),
                                        process_->eta()));

        std::vector<boost::shared_ptr<Fdm1dMesher> > meshers;
        meshers.push_back(xMesher);
        meshers.push_back(yMesher);
        const boost::shared_ptr<FdmMesher> mesher (
                                   new FdmMesherComposite(layout, meshers));

        // 3. Calculator
        const boost::shared_ptr<FdmInnerValueCalculator> calculator(
                    new FdmExtOUJumpModelInnerValue(arguments_.payoff, mesher));

        // 4. Step conditions
        const boost::shared_ptr<FdmStepConditionComposite> conditions =
            FdmStepConditionComposite::vanillaComposite(
                                DividendSchedule(), arguments_.exercise, 
                                mesher, calculator, 
                                rTS_->referenceDate(), rTS_->dayCounter());

        // 5. Boundary conditions
        const std::vector<boost::shared_ptr<FdmDirichletBoundary> > boundaries;
        
        // 6. set-up solver
        FdmSolverDesc solverDesc = { mesher, boundaries, conditions,
                                    calculator, maturity, tGrid_, 0 };

        const boost::shared_ptr<FdmExtOUJumpSolver> solver(
            new FdmExtOUJumpSolver(Handle<ExtOUWithJumpsProcess>(process_), 
                                   rTS_, solverDesc, schemeDesc_));
      
        const Real x = process_->initialValues()[0];
        const Real y = process_->initialValues()[1];
        results_.value = solver->valueAt(x, y);      
    }
    void FdHullWhiteSwaptionEngine::calculate() const {
        const Handle<YieldTermStructure> ts = model_->termStructure();

        // 1. Layout
        const boost::shared_ptr<FdmLinearOpLayout> layout(
            new FdmLinearOpLayout(std::vector<Size>(1u, xGrid_)));

        // 2. Mesher
        const DayCounter dc = ts->dayCounter();
        const Date referenceDate = ts->referenceDate();
        const Time maturity = dc.yearFraction(referenceDate,
                                              arguments_.exercise->lastDate());


        const boost::shared_ptr<OrnsteinUhlenbeckProcess> process(
            new OrnsteinUhlenbeckProcess(model_->a(), model_->sigma()));

        const boost::shared_ptr<Fdm1dMesher> shortRateMesher(
            new FdmSimpleProcess1dMesher(xGrid_, process, maturity,1,invEps_));

        const boost::shared_ptr<FdmMesher> mesher(
            new FdmMesherComposite(layout,
                std::vector<boost::shared_ptr<Fdm1dMesher> >(
                    1, shortRateMesher)));

        // 3. Inner Value Calculator
        const std::vector<Date>& exerciseDates = arguments_.exercise->dates();
        std::map<Time, Date> t2d;

        for (Size i=0; i < exerciseDates.size(); ++i) {
            const Time t = dc.yearFraction(referenceDate, exerciseDates[i]);
            QL_REQUIRE(t >= 0, "exercise dates must not contain past date");

            t2d[t] = exerciseDates[i];
        }

        const Handle<YieldTermStructure> disTs = model_->termStructure();
        const Handle<YieldTermStructure> fwdTs
            = arguments_.swap->iborIndex()->forwardingTermStructure();

        QL_REQUIRE(fwdTs->dayCounter() == disTs->dayCounter(),
                "day counter of forward and discount curve must match");
        QL_REQUIRE(fwdTs->referenceDate() == disTs->referenceDate(),
                "reference date of forward and discount curve must match");

        const boost::shared_ptr<HullWhite> fwdModel(
            new HullWhite(fwdTs, model_->a(), model_->sigma()));

        const boost::shared_ptr<FdmInnerValueCalculator> calculator(
             new FdmAffineModelSwapInnerValue<HullWhite>(
                 model_.currentLink(), fwdModel,
                 arguments_.swap, t2d, mesher, 0));

        // 4. Step conditions
        const boost::shared_ptr<FdmStepConditionComposite> conditions =
             FdmStepConditionComposite::vanillaComposite(
                 DividendSchedule(), arguments_.exercise,
                 mesher, calculator, referenceDate, dc);

        // 5. Boundary conditions
        const std::vector<boost::shared_ptr<FdmDirichletBoundary> > boundaries;

        // 6. Solver
        FdmSolverDesc solverDesc = { mesher, boundaries, conditions,
                                     calculator, maturity,
                                     tGrid_, dampingSteps_ };

        const boost::scoped_ptr<FdmHullWhiteSolver> solver(
            new FdmHullWhiteSolver(model_, solverDesc, schemeDesc_));

        results_.value = solver->valueAt(0.0);
    }