public Vector solve_splitting(Vector r, double a, double b = 1.0) { FdmLinearOpLayout layout = mesher_.layout(); Utils.QL_REQUIRE(r.size() == layout.size(), () => "inconsistent size of rhs"); for (FdmLinearOpIterator iter = layout.begin(); iter != layout.end(); ++iter) { List <int> coordinates = iter.coordinates(); Utils.QL_REQUIRE(coordinates[direction_] != 0 || lower_[iter.index()] == 0, () => "removing non zero entry!"); Utils.QL_REQUIRE(coordinates[direction_] != layout.dim()[direction_] - 1 || upper_[iter.index()] == 0, () => "removing non zero entry!"); } Vector retVal = new Vector(r.size()), tmp = new Vector(r.size()); // Thomson algorithm to solve a tridiagonal system. // Example code taken from Tridiagonalopertor and // changed to fit for the triple band operator. int rim1 = reverseIndex_[0]; double bet = 1.0 / (a * diag_[rim1] + b); Utils.QL_REQUIRE(bet != 0.0, () => "division by zero"); retVal[reverseIndex_[0]] = r[rim1] * bet; for (int j = 1; j <= layout.size() - 1; j++) { int ri = reverseIndex_[j]; tmp[j] = a * upper_[rim1] * bet; bet = b + a * (diag_[ri] - tmp[j] * lower_[ri]); Utils.QL_REQUIRE(bet != 0.0, () => "division by zero"); //QL_ENSURE bet = 1.0 / bet; retVal[ri] = (r[ri] - a * lower_[ri] * retVal[rim1]) * bet; rim1 = ri; } // cannot be j>=0 with Size j for (int j = layout.size() - 2; j > 0; --j) { retVal[reverseIndex_[j]] -= tmp[j + 1] * retVal[reverseIndex_[j + 1]]; } retVal[reverseIndex_[0]] -= tmp[1] * retVal[reverseIndex_[1]]; return(retVal); }
protected Vector getLeverageFctSlice(double t1, double t2) { FdmLinearOpLayout layout = mesher_.layout(); Vector v = new Vector(layout.size(), 1.0); if (leverageFct_ == null) { return(v); } double t = 0.5 * (t1 + t2); double time = Math.Min(leverageFct_ == null ? 1000.0 : leverageFct_.maxTime(), t); FdmLinearOpIterator endIter = layout.end(); for (FdmLinearOpIterator iter = layout.begin(); iter != endIter; ++iter) { int nx = iter.coordinates()[0]; if (iter.coordinates()[1] == 0) { double x = Math.Exp(mesher_.location(iter, 0)); double spot = Math.Min(leverageFct_ == null ? 100000.0 : leverageFct_.maxStrike(), Math.Max(leverageFct_ == null ? -100000.0 : leverageFct_.minStrike(), x)); v[nx] = Math.Max(0.01, leverageFct_ == null ? 0.0 : leverageFct_.localVol(time, spot, true)); } else { v[iter.index()] = v[nx]; } } return(v); }
public override Vector apply(Vector r) { FdmLinearOpLayout index = mesher_.layout(); Utils.QL_REQUIRE(r.size() == index.size(), () => "inconsistent length of r"); Vector retVal = new Vector(r.size()); //#pragma omp parallel for for (int i = 0; i < index.size(); ++i) { retVal[i] = r[i0_[i]] * lower_[i] + r[i] * diag_[i] + r[i2_[i]] * upper_[i]; } return(retVal); }
public override SparseMatrix toMatrix() { FdmLinearOpLayout index = mesher_.layout(); int n = index.size(); SparseMatrix retVal = new SparseMatrix(n, n); for (int i = 0; i < index.size(); ++i) { retVal[i, i00_[i]] += a00_[i]; retVal[i, i01_[i]] += a01_[i]; retVal[i, i02_[i]] += a02_[i]; retVal[i, i10_[i]] += a10_[i]; retVal[i, i] += a11_[i]; retVal[i, i12_[i]] += a12_[i]; retVal[i, i20_[i]] += a20_[i]; retVal[i, i21_[i]] += a21_[i]; retVal[i, i22_[i]] += a22_[i]; } return(retVal); }
public override Vector apply(Vector r) { FdmLinearOpLayout index = mesher_.layout(); Utils.QL_REQUIRE(r.size() == index.size(), () => "inconsistent length of r " + r.size() + " vs " + index.size()); Vector retVal = new Vector(r.size()); //#pragma omp parallel for for (int i = 0; i < retVal.size(); ++i) { retVal[i] = a00_[i] * r[i00_[i]] + a01_[i] * r[i01_[i]] + a02_[i] * r[i02_[i]] + a10_[i] * r[i10_[i]] + a11_[i] * r[i] + a12_[i] * r[i12_[i]] + a20_[i] * r[i20_[i]] + a21_[i] * r[i21_[i]] + a22_[i] * r[i22_[i]]; } return(retVal); }
public override SparseMatrix toMatrix() { FdmLinearOpLayout index = mesher_.layout(); int n = index.size(); SparseMatrix retVal = new SparseMatrix(n, n); for (int i = 0; i < n; ++i) { retVal[i, i0_[i]] += lower_[i]; retVal[i, i] += diag_[i]; retVal[i, i2_[i]] += upper_[i]; } return(retVal); }
public TripleBandLinearOp multR(Vector u) { FdmLinearOpLayout layout = mesher_.layout(); int size = layout.size(); Utils.QL_REQUIRE(u.size() == size, () => "inconsistent size of rhs"); TripleBandLinearOp retVal = new TripleBandLinearOp(direction_, mesher_); for (int i = 0; i < size; ++i) { double sm1 = i > 0 ? u[i - 1] : 1.0; double s0 = u[i]; double sp1 = i < size - 1 ? u[i + 1] : 1.0; retVal.lower_[i] = lower_[i] * sm1; retVal.diag_[i] = diag_[i] * s0; retVal.upper_[i] = upper_[i] * sp1; } return(retVal); }
//! Time \f$t1 <= t2\f$ is required public override void setTime(double t1, double t2) { double r = rTS_.forwardRate(t1, t2, Compounding.Continuous).rate(); double q = qTS_.forwardRate(t1, t2, Compounding.Continuous).rate(); if (localVol_ != null) { FdmLinearOpLayout layout = mesher_.layout(); FdmLinearOpIterator endIter = layout.end(); Vector v = new Vector(layout.size()); for (FdmLinearOpIterator iter = layout.begin(); iter != endIter; ++iter) { int i = iter.index(); if (illegalLocalVolOverwrite_ == null) { double t = localVol_.localVol(0.5 * (t1 + t2), x_[i], true); v[i] = t * t; } else { try { double t = localVol_.localVol(0.5 * (t1 + t2), x_[i], true); v[i] = t * t; } catch { v[i] = illegalLocalVolOverwrite_.Value * illegalLocalVolOverwrite_.Value; } } } if (quantoHelper_ != null) { mapT_.axpyb(r - q - 0.5 * v - quantoHelper_.quantoAdjustment(Vector.Sqrt(v), t1, t2), dxMap_, dxxMap_.mult(0.5 * v), new Vector(1, -r)); } else { mapT_.axpyb(r - q - 0.5 * v, dxMap_, dxxMap_.mult(0.5 * v), new Vector(1, -r)); } } else { double vv = volTS_.blackForwardVariance(t1, t2, strike_) / (t2 - t1); if (quantoHelper_ != null) { mapT_.axpyb(new Vector(1, r - q - 0.5 * vv) - quantoHelper_.quantoAdjustment(new Vector(1, Math.Sqrt(vv)), t1, t2), dxMap_, dxxMap_.mult(0.5 * new Vector(mesher_.layout().size(), vv)), new Vector(1, -r)); } else { mapT_.axpyb(new Vector(1, r - q - 0.5 * vv), dxMap_, dxxMap_.mult(0.5 * new Vector(mesher_.layout().size(), vv)), new Vector(1, -r)); } } }