void LgmSwaptionEngineAD::calculate() const { // collect data needed for core computation routine QL_REQUIRE(arguments_.settlementType == Settlement::Physical, "cash-settled swaptions not yet implemented ..."); Date settlement = model_->termStructure()->referenceDate(); if (arguments_.exercise->dates().back() <= settlement) { // swaption is expired, possibly generated swap is not // valued results_.value = 0.0; return; } int idxMax = static_cast<int>(arguments_.exercise->dates().size()) - 1; int minIdxAlive = static_cast<int>( std::upper_bound(arguments_.exercise->dates().begin(), arguments_.exercise->dates().end(), settlement) - arguments_.exercise->dates().begin()); VanillaSwap swap = *arguments_.swap; int callput = arguments_.type == VanillaSwap::Payer ? 1 : -1; Schedule fixedSchedule = swap.fixedSchedule(); Schedule floatSchedule = swap.floatingSchedule(); Date expiry0; std::vector<int> fix_startidxes, float_startidxes; std::vector<Date> expiryDates; for (int idx = minIdxAlive; idx <= idxMax; ++idx) { expiry0 = arguments_.exercise->dates()[idx]; expiryDates.push_back(expiry0); Size j1 = std::upper_bound(fixedSchedule.dates().begin(), fixedSchedule.dates().end(), expiry0 - 1) - fixedSchedule.dates().begin(); Size k1 = std::upper_bound(floatSchedule.dates().begin(), floatSchedule.dates().end(), expiry0 - 1) - floatSchedule.dates().begin(); fix_startidxes.push_back(j1); float_startidxes.push_back(k1); } std::vector<double> float_mults, index_acctimes, float_spreads, fix_cpn; std::vector<Date> floatt1Dates, floatt2Dates, floattpDates; std::vector<Date> fixtpDates; for (Size i = 0; i < arguments_.floatingFixingDates.size(); ++i) { float_mults.push_back(arguments_.nominal * arguments_.floatingAccrualTimes[i]); float_spreads.push_back(arguments_.floatingSpreads[i]); boost::shared_ptr<IborIndex> index = arguments_.swap->iborIndex(); Date d1 = index->valueDate(arguments_.floatingFixingDates[i]); Date d2 = index->maturityDate(d1); double acctime = index->dayCounter().yearFraction(d1, d2, d1, d2); floatt1Dates.push_back(d1); floatt2Dates.push_back(d2); floattpDates.push_back(arguments_.floatingPayDates[i]); index_acctimes.push_back(acctime); } for (Size i = 0; i < arguments_.fixedCoupons.size(); ++i) { fix_cpn.push_back(arguments_.fixedCoupons[i]); fixtpDates.push_back(arguments_.fixedPayDates[i]); } // join all dates and fill index vectors std::vector<Date> allDates; std::vector<double> allTimes; // with settlement as first entry ! std::vector<int> expiries, floatt1s, floatt2s, floattps, fixtps; std::vector<double> modpar; allDates.reserve(expiryDates.size() + floatt1Dates.size() + floatt2Dates.size() + floattpDates.size() + fixtpDates.size()); allTimes.reserve(allDates.size()); modpar.reserve(3 * allDates.size()); allDates.push_back(settlement); allDates.insert(allDates.end(), expiryDates.begin(), expiryDates.end()); allDates.insert(allDates.end(), floatt1Dates.begin(), floatt1Dates.end()); allDates.insert(allDates.end(), floatt2Dates.begin(), floatt2Dates.end()); allDates.insert(allDates.end(), floattpDates.begin(), floattpDates.end()); allDates.insert(allDates.end(), fixtpDates.begin(), fixtpDates.end()); std::sort(allDates.begin(), allDates.end()); allDates.erase(unique(allDates.begin(), allDates.end()), allDates.end()); for (Size i = 0; i < allDates.size(); ++i) { allTimes.push_back( model_->termStructure()->timeFromReference(allDates[i])); } for (Size i = 0; i < allDates.size(); ++i) { modpar.push_back(model_->parametrization()->H(allTimes[i])); } for (Size i = 0; i < allDates.size(); ++i) { modpar.push_back(model_->parametrization()->zeta(allTimes[i])); } for (Size i = 0; i < allDates.size(); ++i) { modpar.push_back(model_->termStructure()->discount(allTimes[i])); } for (Size i = 0; i < expiryDates.size(); ++i) { expiries.push_back( std::find(allDates.begin(), allDates.end(), expiryDates[i]) - allDates.begin()); } for (Size i = 0; i < floatt1Dates.size(); ++i) { floatt1s.push_back( std::find(allDates.begin(), allDates.end(), floatt1Dates[i]) - allDates.begin()); } for (Size i = 0; i < floatt2Dates.size(); ++i) { floatt2s.push_back( std::find(allDates.begin(), allDates.end(), floatt2Dates[i]) - allDates.begin()); } for (Size i = 0; i < floattpDates.size(); ++i) { floattps.push_back( std::find(allDates.begin(), allDates.end(), floattpDates[i]) - allDates.begin()); } for (Size i = 0; i < fixtpDates.size(); ++i) { fixtps.push_back( std::find(allDates.begin(), allDates.end(), fixtpDates[i]) - allDates.begin()); } // call core computation routine and set results int ntimes = allTimes.size(); int nexpiries = expiries.size(); int nfloats = floatt1s.size(); int nfixs = fix_cpn.size(); double res = 0.0; std::vector<Real> dres(3*ntimes); int integration_pts = integrationPoints_; double std_devs = stddevs_; lgm_swaption_engine_ad_(&ntimes, &allTimes[0], &modpar[0], &nexpiries, &expiries[0], &callput, &nfloats, &float_startidxes[0], &float_mults[0], &index_acctimes[0], &float_spreads[0], &floatt1s[0], &floatt2s[0], &floattps[0], &fix_startidxes[0], &nfixs, &fix_cpn[0], &fixtps[0], &integration_pts, &std_devs, &res, &dres[0]); results_.value = res; std::vector<Real> H_sensitivity(dres.begin(),dres.begin()+ntimes); std::vector<Real> zeta_sensitivity(dres.begin()+ntimes,dres.begin()+2*ntimes); std::vector<Real> discount_sensitivity(dres.begin()+2*ntimes,dres.begin()+3*ntimes); results_.additionalResults["sensitivityTimes"] = allTimes; results_.additionalResults["sensitivityH"] = H_sensitivity; results_.additionalResults["sensitivityZeta"] = zeta_sensitivity; results_.additionalResults["sensitivityDiscount"] = discount_sensitivity; }
void tet_hp::rsdl(int stage) { /* ONLY NEED TO CALL FOR MOVEMENT BETWEEN MESHES INHERIT FROM THIS FOR SPECIFIC PHYSICS */ // if (mmovement == coupled_deformable && stage == gbl->nstage && log2p == 0) r_tet_mesh::rsdl(); FLT oneminusbeta = 1.0-gbl->beta(stage); gbl->res.v(Range(0,npnt-1),Range::all()) = 0.0; gbl->res_r.v(Range(0,npnt-1),Range::all()) *= oneminusbeta; if (basis::tet(log2p).em) { gbl->res.e(Range(0,nseg-1),Range(0,basis::tet(log2p).em-1),Range::all()) = 0.0; gbl->res_r.e(Range(0,nseg-1),Range(0,basis::tet(log2p).em-1),Range::all()) *= oneminusbeta; if (basis::tet(log2p).fm) { gbl->res.f(Range(0,ntri-1),Range(0,basis::tet(log2p).fm-1),Range::all()) = 0.0; gbl->res_r.f(Range(0,ntri-1),Range(0,basis::tet(log2p).fm-1),Range::all()) *= oneminusbeta; if (basis::tet(log2p).im) { gbl->res.i(Range(0,ntet-1),Range(0,basis::tet(log2p).im-1),Range::all()) = 0.0; gbl->res_r.i(Range(0,ntet-1),Range(0,basis::tet(log2p).im-1),Range::all()) *= oneminusbeta; } } } for(int i=0;i<nfbd;++i) hp_fbdry(i)->rsdl(stage); for(int i=0;i<nebd;++i) hp_ebdry(i)->rsdl(stage); for(int i=0;i<nvbd;++i) hp_vbdry(i)->rsdl(stage); helper->rsdl(stage); Array<TinyVector<FLT,MXTM>,1> lf_re(NV),lf_im(NV); for(int tind = 0; tind<ntet;++tind) { /* LOAD SOLUTION COEFFICIENTS FOR THIS ELEMENT */ ugtouht(tind); /* call rsdl for element */ element_rsdl(tind,stage,uht,lf_re,lf_im); /* load imaginary local residual into global residual */ for (int m = 0; m < basis::tet(log2p).tm; ++m) for (int n = 0; n < NV; ++n) lf(n)(m) = lf_im(n)(m); lftog(tind,gbl->res); /* load real local residual into global residual */ for (int m = 0; m < basis::tet(log2p).tm; ++m) for (int n = 0; n < NV; ++n) lf(n)(m) = lf_re(n)(m); lftog(tind,gbl->res_r); } /* ADD IN VISCOUS/DISSIPATIVE FLUX */ gbl->res.v(Range(0,npnt-1),Range::all()) += gbl->res_r.v(Range(0,npnt-1),Range::all()); if (basis::tet(log2p).em > 0) { gbl->res.e(Range(0,nseg-1),Range(0,basis::tet(log2p).em-1),Range::all()) += gbl->res_r.e(Range(0,nseg-1),Range(0,basis::tet(log2p).em-1),Range::all()); if (basis::tet(log2p).fm > 0) { gbl->res.f(Range(0,ntri-1),Range(0,basis::tet(log2p).fm-1),Range::all()) += gbl->res_r.f(Range(0,ntri-1),Range(0,basis::tet(log2p).fm-1),Range::all()); if (basis::tet(log2p).im > 0) { gbl->res.i(Range(0,ntet-1),Range(0,basis::tet(log2p).im-1),Range::all()) += gbl->res_r.i(Range(0,ntet-1),Range(0,basis::tet(log2p).im-1),Range::all()); } } } #ifdef DEBUG if (coarse_flag) { for(int i=0;i<npnt;++i) { printf("rsdl v: %d ",i); for (int n=0;n<NV;++n) printf("%e ",gbl->res.v(i,n)); printf("\n"); } for(int i=0;i<nseg;++i) { for(int m=0;m<basis::tet(log2p).em;++m) { printf("rsdl s: %d %d ",i,m); for(int n=0;n<NV;++n) printf("%e ",gbl->res.e(i,m,n)); printf("\n"); } } for(int i=0;i<ntri;++i) { for(int m=0;m<basis::tet(log2p).fm;++m) { printf("rsdl i: %d %d ",i,m); for(int n=0;n<NV;++n) printf("%e \n",gbl->res.f(i,m,n)); printf("\n"); } } } #endif /*********************************************/ /* MODIFY RESIDUALS ON COARSER MESHES */ /*********************************************/ if (coarse_flag) { /* CALCULATE DRIVING TERM ON FIRST ENTRY TO COARSE MESH */ if(isfrst) { dres(log2p).v(Range(0,npnt-1),Range::all()) = fadd*gbl->res0.v(Range(0,npnt-1),Range::all()) -gbl->res.v(Range(0,npnt-1),Range::all()); if (basis::tet(log2p).em) dres(log2p).e(Range(0,nseg-1),Range(0,basis::tet(log2p).em-1),Range::all()) = fadd*gbl->res0.e(Range(0,nseg-1),Range(0,basis::tet(log2p).em-1),Range::all()) -gbl->res.e(Range(0,nseg-1),Range(0,basis::tet(log2p).em-1),Range::all()); if (basis::tet(log2p).fm) dres(log2p).f(Range(0,ntri-1),Range(0,basis::tet(log2p).fm-1),Range::all()) = fadd*gbl->res0.f(Range(0,ntri-1),Range(0,basis::tet(log2p).fm-1),Range::all()) -gbl->res.f(Range(0,ntri-1),Range(0,basis::tet(log2p).fm-1),Range::all()); if (basis::tet(log2p).im) dres(log2p).i(Range(0,ntet-1),Range(0,basis::tet(log2p).im-1),Range::all()) = fadd*gbl->res0.i(Range(0,ntet-1),Range(0,basis::tet(log2p).im-1),Range::all()) -gbl->res.i(Range(0,ntet-1),Range(0,basis::tet(log2p).im-1),Range::all()); isfrst = false; } gbl->res.v(Range(0,npnt-1),Range::all()) += dres(log2p).v(Range(0,npnt-1),Range::all()); if (basis::tet(log2p).em) gbl->res.e(Range(0,nseg-1),Range(0,basis::tet(log2p).em-1),Range::all()) += dres(log2p).e(Range(0,nseg-1),Range(0,basis::tet(log2p).em-1),Range::all()); if (basis::tet(log2p).fm) gbl->res.f(Range(0,ntri-1),Range(0,basis::tet(log2p).fm-1),Range::all()) += dres(log2p).f(Range(0,ntri-1),Range(0,basis::tet(log2p).fm-1),Range::all()); if (basis::tet(log2p).im) gbl->res.i(Range(0,ntet-1),Range(0,basis::tet(log2p).im-1),Range::all()) += dres(log2p).i(Range(0,ntet-1),Range(0,basis::tet(log2p).im-1),Range::all()); } return; }