public override Vector locations(int direction) { Vector retVal = new Vector(layout_.size()); FdmLinearOpIterator endIter = layout_.end(); for (FdmLinearOpIterator iter = layout_.begin(); iter != endIter; ++iter) { retVal[iter.index()] = mesher_[direction].locations()[iter.coordinates()[direction]]; } return(retVal); }
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); }
public FdmLinearOpIterator iter_neighbourhood(FdmLinearOpIterator iterator, int i, int offset) { List <int> coordinates = iterator.coordinates(); int coorOffset = coordinates[i] + offset; if (coorOffset < 0) { coorOffset = -coorOffset; } else if (coorOffset >= dim_[i]) { coorOffset = 2 * (dim_[i] - 1) - coorOffset; } coordinates[i] = coorOffset; FdmLinearOpIterator retVal = new FdmLinearOpIterator(dim_, coordinates, index(coordinates)); return(retVal); }
public TripleBandLinearOp(int direction, FdmMesher mesher) { direction_ = direction; i0_ = new InitializedList <int>(mesher.layout().size()); i2_ = new InitializedList <int>(mesher.layout().size()); reverseIndex_ = new InitializedList <int>(mesher.layout().size()); lower_ = new InitializedList <double>(mesher.layout().size()); diag_ = new InitializedList <double>(mesher.layout().size()); upper_ = new InitializedList <double>(mesher.layout().size()); mesher_ = mesher; FdmLinearOpLayout layout = mesher.layout(); FdmLinearOpIterator endIter = layout.end(); int tmp; List <int> newDim = new List <int>(layout.dim()); tmp = newDim[direction_]; newDim[direction_] = newDim[0]; newDim[0] = tmp; List <int> newSpacing = new FdmLinearOpLayout(newDim).spacing(); tmp = newSpacing[direction_]; newSpacing[direction_] = newSpacing[0]; newSpacing[0] = tmp; for (FdmLinearOpIterator iter = layout.begin(); iter != endIter; ++iter) { int i = iter.index(); i0_[i] = layout.neighbourhood(iter, direction, -1); i2_[i] = layout.neighbourhood(iter, direction, 1); List <int> coordinates = iter.coordinates(); int newIndex = coordinates.inner_product(0, coordinates.Count, 0, newSpacing, 0); reverseIndex_[newIndex] = i; } }
public override double avgInnerValue(FdmLinearOpIterator iter, double t) { if (avgInnerValues_.empty()) { // calculate caching values avgInnerValues_ = new InitializedList <double>(mesher_.layout().dim()[direction_]); List <bool> initialized = new InitializedList <bool>(avgInnerValues_.Count, false); FdmLinearOpLayout layout = mesher_.layout(); FdmLinearOpIterator endIter = layout.end(); for (FdmLinearOpIterator new_iter = layout.begin(); new_iter != endIter; ++new_iter) { int xn = new_iter.coordinates()[direction_]; if (!initialized[xn]) { initialized[xn] = true; avgInnerValues_[xn] = avgInnerValueCalc(new_iter, t); } } } return(avgInnerValues_[iter.coordinates()[direction_]]); }
public override double location(FdmLinearOpIterator iter, int direction) { return(mesher_[direction].location(iter.coordinates()[direction])); }
public SecondOrderMixedDerivativeOp(int d0, int d1, FdmMesher mesher) : base(d0, d1, mesher) { FdmLinearOpLayout layout = mesher.layout(); FdmLinearOpIterator endIter = layout.end(); for (FdmLinearOpIterator iter = layout.begin(); iter != endIter; ++iter) { int i = iter.index(); double?hm_d0 = mesher.dminus(iter, d0_); double?hp_d0 = mesher.dplus(iter, d0_); double?hm_d1 = mesher.dminus(iter, d1_); double?hp_d1 = mesher.dplus(iter, d1_); double?zetam1 = hm_d0 * (hm_d0 + hp_d0); double?zeta0 = hm_d0 * hp_d0; double?zetap1 = hp_d0 * (hm_d0 + hp_d0); double?phim1 = hm_d1 * (hm_d1 + hp_d1); double?phi0 = hm_d1 * hp_d1; double?phip1 = hp_d1 * (hm_d1 + hp_d1); int c0 = iter.coordinates()[d0_]; int c1 = iter.coordinates()[d1_]; if (c0 == 0 && c1 == 0) { // lower left corner a00_[i] = a01_[i] = a02_[i] = a10_[i] = a20_[i] = 0.0; a11_[i] = a22_[i] = 1.0 / (hp_d0.Value * hp_d1.Value); a21_[i] = a12_[i] = -a11_[i]; } else if (c0 == layout.dim()[d0_] - 1 && c1 == 0) { // upper left corner a22_[i] = a21_[i] = a20_[i] = a10_[i] = a00_[i] = 0.0; a01_[i] = a12_[i] = 1.0 / (hm_d0.Value * hp_d1.Value); a11_[i] = a02_[i] = -a01_[i]; } else if (c0 == 0 && c1 == layout.dim()[d1_] - 1) { // lower right corner a00_[i] = a01_[i] = a02_[i] = a12_[i] = a22_[i] = 0.0; a10_[i] = a21_[i] = 1.0 / (hp_d0.Value * hm_d1.Value); a20_[i] = a11_[i] = -a10_[i]; } else if (c0 == layout.dim()[d0_] - 1 && c1 == layout.dim()[d1_] - 1) { // upper right corner a20_[i] = a21_[i] = a22_[i] = a12_[i] = a02_[i] = 0.0; a00_[i] = a11_[i] = 1.0 / (hm_d0.Value * hm_d1.Value); a10_[i] = a01_[i] = -a00_[i]; } else if (c0 == 0) { // lower side a00_[i] = a01_[i] = a02_[i] = 0.0; a10_[i] = hp_d1.Value / (hp_d0.Value * phim1.Value); a20_[i] = -a10_[i]; a21_[i] = (hp_d1.Value - hm_d1.Value) / (hp_d0.Value * phi0.Value); a11_[i] = -a21_[i]; a22_[i] = hm_d1.Value / (hp_d0.Value * phip1.Value); a12_[i] = -a22_[i]; } else if (c0 == layout.dim()[d0_] - 1) { // upper side a20_[i] = a21_[i] = a22_[i] = 0.0; a00_[i] = hp_d1.Value / (hm_d0.Value * phim1.Value); a10_[i] = -a00_[i]; a11_[i] = (hp_d1.Value - hm_d1.Value) / (hm_d0.Value * phi0.Value); a01_[i] = -a11_[i]; a12_[i] = hm_d1.Value / (hm_d0.Value * phip1.Value); a02_[i] = -a12_[i]; } else if (c1 == 0) { // left side a00_[i] = a10_[i] = a20_[i] = 0.0; a01_[i] = hp_d0.Value / (zetam1.Value * hp_d1.Value); a02_[i] = -a01_[i]; a12_[i] = (hp_d0.Value - hm_d0.Value) / (zeta0.Value * hp_d1.Value); a11_[i] = -a12_[i]; a22_[i] = hm_d0.Value / (zetap1.Value * hp_d1.Value); a21_[i] = -a22_[i]; } else if (c1 == layout.dim()[d1_] - 1) { // right side a22_[i] = a12_[i] = a02_[i] = 0.0; a00_[i] = hp_d0.Value / (zetam1.Value * hm_d1.Value); a01_[i] = -a00_[i]; a11_[i] = (hp_d0.Value - hm_d0.Value) / (zeta0.Value * hm_d1.Value); a10_[i] = -a11_[i]; a21_[i] = hm_d0.Value / (zetap1.Value * hm_d1.Value); a20_[i] = -a21_[i]; } else { a00_[i] = hp_d0.Value * hp_d1.Value / (zetam1.Value * phim1.Value); a10_[i] = -(hp_d0.Value - hm_d0.Value) * hp_d1.Value / (zeta0.Value * phim1.Value); a20_[i] = -hm_d0.Value * hp_d1.Value / (zetap1.Value * phim1.Value); a01_[i] = -hp_d0.Value * (hp_d1.Value - hm_d1.Value) / (zetam1.Value * phi0.Value); a11_[i] = (hp_d0.Value - hm_d0.Value) * (hp_d1.Value - hm_d1.Value) / (zeta0.Value * phi0.Value); a21_[i] = hm_d0.Value * (hp_d1.Value - hm_d1.Value) / (zetap1.Value * phi0.Value); a02_[i] = -hp_d0.Value * hm_d1.Value / (zetam1.Value * phip1.Value); a12_[i] = hm_d1.Value * (hp_d0.Value - hm_d0.Value) / (zeta0.Value * phip1.Value); a22_[i] = hm_d0.Value * hm_d1.Value / (zetap1.Value * phip1.Value); } } }
public override double location(FdmLinearOpIterator iter, int direction) { return(locations_[direction][iter.coordinates()[direction]]); }