Esempio n. 1
0
        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()] = locations_[direction][iter.coordinates()[direction]];
            }

            return(retVal);
        }
Esempio n. 2
0
        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);
        }
Esempio n. 3
0
        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);
        }
Esempio n. 4
0
        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;
            }
        }
Esempio n. 5
0
        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_]]);
        }
Esempio n. 6
0
 public override double location(FdmLinearOpIterator iter,
                                 int direction)
 {
     return(locations_[direction][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);
                }
            }
        }
Esempio n. 8
0
 public override double location(FdmLinearOpIterator iter,
                                 int direction)
 {
     return(mesher_[direction].location(iter.coordinates()[direction]));
 }