void Fdm2dBlackScholesOp::setTime(Time t1, Time t2) { opX_.setTime(t1, t2); opY_.setTime(t1, t2); if (localVol1_) { const boost::shared_ptr<FdmLinearOpLayout> layout=mesher_->layout(); const FdmLinearOpIterator endIter = layout->end(); Array vol1(layout->size()), vol2(layout->size()); for (FdmLinearOpIterator iter = layout->begin(); iter!=endIter; ++iter) { const Size i = iter.index(); if (illegalLocalVolOverwrite_ < 0.0) { vol1[i] = localVol1_->localVol(0.5*(t1+t2), x_[i], true); vol2[i] = localVol2_->localVol(0.5*(t1+t2), y_[i], true); } else { try { vol1[i] = localVol1_->localVol(0.5*(t1+t2), x_[i],true); } catch (Error&) { vol1[i] = illegalLocalVolOverwrite_; } try { vol2[i] = localVol2_->localVol(0.5*(t1+t2), y_[i],true); } catch (Error&) { vol2[i] = illegalLocalVolOverwrite_; } } } corrMapT_ = corrMapTemplate_.mult(vol1*vol2); } else { const Real vol1 = p1_ ->blackVolatility()->blackForwardVol(t1, t2, p1_->x0()); const Real vol2 = p2_ ->blackVolatility()->blackForwardVol(t1, t2, p2_->x0()); corrMapT_ = corrMapTemplate_ .mult(Array(mesher_->layout()->size(), vol1*vol2)); } currentForwardRate_ = p1_->riskFreeRate() ->forwardRate(t1, t2, Continuous).rate(); }
ASMmxBase::VolumeVec ASMmxBase::establishBases(Go::SplineVolume* svol, MixedType type) { VolumeVec result(2); // With mixed methods we need two separate spline spaces if (type == FULL_CONT_RAISE_BASIS1 || type == FULL_CONT_RAISE_BASIS2) { // basis1 should be one degree higher than basis2 and C^p-1 continuous int ndim = svol->dimension(); Go::BsplineBasis b1 = svol->basis(0).extendedBasis(svol->order(0)+1); Go::BsplineBasis b2 = svol->basis(1).extendedBasis(svol->order(1)+1); Go::BsplineBasis b3 = svol->basis(2).extendedBasis(svol->order(2)+1); /* To lower order and regularity this can be used instead std::vector<double>::const_iterator first = ++surf->basis(0).begin(); std::vector<double>::const_iterator last = --surf->basis(0).end(); Go::BsplineBasis b1 = Go::BsplineBasis(surf->order_u()-1,first,last); first = ++surf->basis(1).begin(); last = --surf->basis(1).end(); Go::BsplineBasis b2 = Go::BsplineBasis(surf->order_v()-1,first,last); */ // Compute parameter values of the Greville points size_t i; RealArray ug(b1.numCoefs()), vg(b2.numCoefs()), wg(b3.numCoefs()); for (i = 0; i < ug.size(); i++) ug[i] = b1.grevilleParameter(i); for (i = 0; i < vg.size(); i++) vg[i] = b2.grevilleParameter(i); for (i = 0; i < wg.size(); i++) wg[i] = b3.grevilleParameter(i); if (svol->rational()) { std::vector<double> rCoefs(svol->rcoefs_begin(), svol->rcoefs_end()); // we normally would set coefs as (x*w, y*w, w) // however, gotools use this representation internally already. // instance a Bspline surface in ndim+1 Go::SplineVolume vol2(svol->basis(0), svol->basis(1), svol->basis(2), rCoefs.begin(), ndim+1, false); // interpolate the Bspline surface onto new basis RealArray XYZ((ndim+1)*ug.size()*vg.size()*wg.size()); vol2.gridEvaluator(XYZ,ug,vg,wg); std::unique_ptr<Go::SplineVolume> svol3(Go::VolumeInterpolator::regularInterpolation(b1,b2,b3,ug,vg,wg,XYZ,ndim+1,false,XYZ)); // new rational coefs are (x/w', y/w', w') // apparently gotools will rescale coeffs on surface creation. result[0].reset(new Go::SplineVolume(svol3->basis(0), svol3->basis(1), svol3->basis(2), svol3->coefs_begin(), ndim, true)); } else { RealArray XYZ(ndim*ug.size()*vg.size()*wg.size()); // Evaluate the spline surface at all points svol->gridEvaluator(ug,vg,wg,XYZ); // Project the coordinates onto the new basis (the 2nd XYZ is dummy here) result[0].reset(Go::VolumeInterpolator::regularInterpolation(b1,b2,b3, ug,vg,wg,XYZ,ndim, false,XYZ)); } result[1].reset(new Go::SplineVolume(*svol)); } else if (type == REDUCED_CONT_RAISE_BASIS1 || type == REDUCED_CONT_RAISE_BASIS2) { // Order-elevate basis1 such that it is of one degree higher than basis2 // but only C^p-2 continuous result[0].reset(new Go::SplineVolume(*svol)); result[0]->raiseOrder(1,1,1); result[1].reset(new Go::SplineVolume(*svol)); } else if (ASMmxBase::Type == ASMmxBase::DIV_COMPATIBLE) { result.resize(4); // basis1 should be one degree higher than basis2 and C^p-1 continuous int ndim = svol->dimension(); Go::BsplineBasis a1 = svol->basis(0); Go::BsplineBasis a2 = svol->basis(1); Go::BsplineBasis a3 = svol->basis(2); Go::BsplineBasis b1 = svol->basis(0).extendedBasis(svol->order(0)+1); Go::BsplineBasis b2 = svol->basis(1).extendedBasis(svol->order(1)+1); Go::BsplineBasis b3 = svol->basis(2).extendedBasis(svol->order(2)+1); // Compute parameter values of the Greville points size_t i; RealArray u0(a1.numCoefs()), v0(a2.numCoefs()), w0(a3.numCoefs()); for (i = 0; i < u0.size(); i++) u0[i] = a1.grevilleParameter(i); for (i = 0; i < v0.size(); i++) v0[i] = a2.grevilleParameter(i); for (i = 0; i < w0.size(); i++) w0[i] = a3.grevilleParameter(i); RealArray ug(b1.numCoefs()), vg(b2.numCoefs()), wg(b3.numCoefs()); for (i = 0; i < ug.size(); i++) ug[i] = b1.grevilleParameter(i); for (i = 0; i < vg.size(); i++) vg[i] = b2.grevilleParameter(i); for (i = 0; i < wg.size(); i++) wg[i] = b3.grevilleParameter(i); // Evaluate the spline surface at all points // Project the coordinates onto the new basis (the 2nd XYZ is dummy here) RealArray XYZ0(ndim*ug.size()*v0.size()*w0.size()), XYZ1(ndim*u0.size()*vg.size()*w0.size()), XYZ2(ndim*u0.size()*v0.size()*wg.size()); svol->gridEvaluator(ug,v0,w0,XYZ0); svol->gridEvaluator(u0,vg,w0,XYZ1); svol->gridEvaluator(u0,v0,wg,XYZ2); result[0].reset(Go::VolumeInterpolator::regularInterpolation(b1,a2,a3, ug,v0,w0,XYZ0,ndim, false,XYZ0)); result[1].reset(Go::VolumeInterpolator::regularInterpolation(a1,b2,a3, u0,vg,w0,XYZ1,ndim, false,XYZ1)); result[2].reset(Go::VolumeInterpolator::regularInterpolation(a1,a2,b3, u0,v0,wg,XYZ2,ndim, false,XYZ2)); result[3].reset(new Go::SplineVolume(*svol)); geoBasis = 4; } if (type == FULL_CONT_RAISE_BASIS2 || type == REDUCED_CONT_RAISE_BASIS2) std::swap(result[0], result[1]); return result; }