Esempio n. 1
0
        public void testDerivativeWeightsOnNonUniformGrids()
        {
            Fdm1dMesher mesherX =
                new Concentrating1dMesher(-2.0, 3.0, 50, new Pair <double?, double?>(0.5, 0.01));
            Fdm1dMesher mesherY =
                new Concentrating1dMesher(0.5, 5.0, 25, new Pair <double?, double?>(0.5, 0.1));
            Fdm1dMesher mesherZ =
                new Concentrating1dMesher(-1.0, 2.0, 31, new Pair <double?, double?>(1.5, 0.01));

            FdmMesher meshers =
                new FdmMesherComposite(mesherX, mesherY, mesherZ);

            FdmLinearOpLayout   layout  = meshers.layout();
            FdmLinearOpIterator endIter = layout.end();

            double tol = 1e-13;

            for (int direction = 0; direction < 3; ++direction)
            {
                SparseMatrix dfdx
                    = new FirstDerivativeOp(direction, meshers).toMatrix();
                SparseMatrix d2fdx2
                    = new SecondDerivativeOp(direction, meshers).toMatrix();

                Vector gridPoints = meshers.locations(direction);

                for (FdmLinearOpIterator iter = layout.begin();
                     iter != endIter; ++iter)
                {
                    int c       = iter.coordinates()[direction];
                    int index   = iter.index();
                    int indexM1 = layout.neighbourhood(iter, direction, -1);
                    int indexP1 = layout.neighbourhood(iter, direction, +1);

                    // test only if not on the boundary
                    if (c == 0)
                    {
                        Vector twoPoints = new Vector(2);
                        twoPoints[0] = 0.0;
                        twoPoints[1] = gridPoints[indexP1] - gridPoints[index];

                        Vector ndWeights1st = new NumericalDifferentiation(x => x, 1, twoPoints).weights();

                        double beta1  = dfdx[index, index];
                        double gamma1 = dfdx[index, indexP1];
                        if (Math.Abs((beta1 - ndWeights1st[0]) / beta1) > tol ||
                            Math.Abs((gamma1 - ndWeights1st[1]) / gamma1) > tol)
                        {
                            QAssert.Fail("can not reproduce the weights of the "
                                         + "first order derivative operator "
                                         + "on the lower boundary"
                                         + "\n expected beta:    " + ndWeights1st[0]
                                         + "\n calculated beta:  " + beta1
                                         + "\n difference beta:  "
                                         + (beta1 - ndWeights1st[0])
                                         + "\n expected gamma:   " + ndWeights1st[1]
                                         + "\n calculated gamma: " + gamma1
                                         + "\n difference gamma: "
                                         + (gamma1 - ndWeights1st[1]));
                        }

                        // free boundary condition by default
                        double beta2  = d2fdx2[index, index];
                        double gamma2 = d2fdx2[index, indexP1];

                        if (Math.Abs(beta2) > Const.QL_EPSILON ||
                            Math.Abs(gamma2) > Const.QL_EPSILON)
                        {
                            QAssert.Fail("can not reproduce the weights of the "
                                         + "second order derivative operator "
                                         + "on the lower boundary"
                                         + "\n expected beta:    " + 0.0
                                         + "\n calculated beta:  " + beta2
                                         + "\n expected gamma:   " + 0.0
                                         + "\n calculated gamma: " + gamma2);
                        }
                    }
                    else if (c == layout.dim()[direction] - 1)
                    {
                        Vector twoPoints = new Vector(2);
                        twoPoints[0] = gridPoints[indexM1] - gridPoints[index];
                        twoPoints[1] = 0.0;

                        Vector ndWeights1st = new NumericalDifferentiation(x => x, 1, twoPoints).weights();

                        double alpha1 = dfdx[index, indexM1];
                        double beta1  = dfdx[index, index];
                        if (Math.Abs((alpha1 - ndWeights1st[0]) / alpha1) > tol ||
                            Math.Abs((beta1 - ndWeights1st[1]) / beta1) > tol)
                        {
                            QAssert.Fail("can not reproduce the weights of the "
                                         + "first order derivative operator "
                                         + "on the upper boundary"
                                         + "\n expected alpha:   " + ndWeights1st[0]
                                         + "\n calculated alpha: " + alpha1
                                         + "\n difference alpha: "
                                         + (alpha1 - ndWeights1st[0])
                                         + "\n expected beta:    " + ndWeights1st[1]
                                         + "\n calculated beta:  " + beta1
                                         + "\n difference beta:  "
                                         + (beta1 - ndWeights1st[1]));
                        }

                        // free boundary condition by default
                        double alpha2 = d2fdx2[index, indexM1];
                        double beta2  = d2fdx2[index, index];

                        if (Math.Abs(alpha2) > Const.QL_EPSILON ||
                            Math.Abs(beta2) > Const.QL_EPSILON)
                        {
                            QAssert.Fail("can not reproduce the weights of the "
                                         + "second order derivative operator "
                                         + "on the upper boundary"
                                         + "\n expected alpha:   " + 0.0
                                         + "\n calculated alpha: " + alpha2
                                         + "\n expected beta:    " + 0.0
                                         + "\n calculated beta:  " + beta2);
                        }
                    }
                    else
                    {
                        Vector threePoints = new Vector(3);
                        threePoints[0] = gridPoints[indexM1] - gridPoints[index];
                        threePoints[1] = 0.0;
                        threePoints[2] = gridPoints[indexP1] - gridPoints[index];

                        Vector ndWeights1st = new NumericalDifferentiation(x => x, 1, threePoints).weights();

                        double alpha1 = dfdx[index, indexM1];
                        double beta1  = dfdx[index, index];
                        double gamma1 = dfdx[index, indexP1];

                        if (Math.Abs((alpha1 - ndWeights1st[0]) / alpha1) > tol ||
                            Math.Abs((beta1 - ndWeights1st[1]) / beta1) > tol ||
                            Math.Abs((gamma1 - ndWeights1st[2]) / gamma1) > tol)
                        {
                            QAssert.Fail("can not reproduce the weights of the "
                                         + "first order derivative operator"
                                         + "\n expected alpha:   " + ndWeights1st[0]
                                         + "\n calculated alpha: " + alpha1
                                         + "\n difference alpha: "
                                         + (alpha1 - ndWeights1st[0])
                                         + "\n expected beta:    " + ndWeights1st[1]
                                         + "\n calculated beta:  " + beta1
                                         + "\n difference beta:  "
                                         + (beta1 - ndWeights1st[1])
                                         + "\n expected gamma:   " + ndWeights1st[2]
                                         + "\n calculated gamma: " + gamma1
                                         + "\n difference gamma: "
                                         + (gamma1 - ndWeights1st[2]));
                        }

                        Vector ndWeights2nd = new NumericalDifferentiation(x => x, 2, threePoints).weights();

                        double alpha2 = d2fdx2[index, indexM1];
                        double beta2  = d2fdx2[index, index];
                        double gamma2 = d2fdx2[index, indexP1];
                        if (Math.Abs((alpha2 - ndWeights2nd[0]) / alpha2) > tol ||
                            Math.Abs((beta2 - ndWeights2nd[1]) / beta2) > tol ||
                            Math.Abs((gamma2 - ndWeights2nd[2]) / gamma2) > tol)
                        {
                            QAssert.Fail("can not reproduce the weights of the "
                                         + "second order derivative operator"
                                         + "\n expected alpha:   " + ndWeights2nd[0]
                                         + "\n calculated alpha: " + alpha2
                                         + "\n difference alpha: "
                                         + (alpha2 - ndWeights2nd[0])
                                         + "\n expected beta:    " + ndWeights2nd[1]
                                         + "\n calculated beta:  " + beta2
                                         + "\n difference beta:  "
                                         + (beta2 - ndWeights2nd[1])
                                         + "\n expected gamma:   " + ndWeights2nd[2]
                                         + "\n calculated gamma: " + gamma2
                                         + "\n difference gamma: "
                                         + (gamma2 - ndWeights2nd[2]));
                        }
                    }
                }
            }
        }
Esempio n. 2
0
        public void testTripleBandMapSolve()
        {
            int[]      dims = new int[] { 100, 400 };
            List <int> dim  = new List <int>(dims);

            FdmLinearOpLayout layout = new FdmLinearOpLayout(dim);

            List <Pair <double?, double?> > boundaries = new List <Pair <double?, double?> > ();

            boundaries.Add(new Pair <double?, double?>(0, 1.0));
            boundaries.Add(new Pair <double?, double?>(0, 1.0));

            FdmMesher mesher = new UniformGridMesher(layout, boundaries);

            FirstDerivativeOp dy = new FirstDerivativeOp(1, mesher);

            dy.axpyb(new Vector(1, 2.0), dy, dy, new Vector(1, 1.0));

            // check copy constructor
            FirstDerivativeOp copyOfDy = new FirstDerivativeOp(dy);

            Vector u = new Vector(layout.size());

            for (int i = 0; i < layout.size(); ++i)
            {
                u[i] = Math.Sin(0.1 * i) + Math.Cos(0.35 * i);
            }

            Vector t = new Vector(dy.solve_splitting(copyOfDy.apply(u), 1.0, 0.0));

            for (int i = 0; i < u.size(); ++i)
            {
                if (Math.Abs(u[i] - t[i]) > 1e-6)
                {
                    QAssert.Fail("solve and apply are not consistent "
                                 + "\n expected      : " + u[i]
                                 + "\n calculated    : " + t[i]);
                }
            }

            FirstDerivativeOp dx = new FirstDerivativeOp(0, mesher);

            dx.axpyb(new Vector(), dx, dx, new Vector(1, 1.0));

            FirstDerivativeOp copyOfDx = new FirstDerivativeOp(0, mesher);

            // check assignment
            copyOfDx = dx;

            t = dx.solve_splitting(copyOfDx.apply(u), 1.0, 0.0);
            for (int i = 0; i < u.size(); ++i)
            {
                if (Math.Abs(u[i] - t[i]) > 1e-6)
                {
                    QAssert.Fail("solve and apply are not consistent "
                                 + "\n expected      : " + u[i]
                                 + "\n calculated    : " + t[i]);
                }
            }

            SecondDerivativeOp dxx = new SecondDerivativeOp(0, mesher);

            dxx.axpyb(new Vector(1, 0.5), dxx, dx, new Vector(1, 1.0));

            // check of copy constructor
            SecondDerivativeOp copyOfDxx = new SecondDerivativeOp(dxx);

            t = dxx.solve_splitting(copyOfDxx.apply(u), 1.0, 0.0);

            for (int i = 0; i < u.size(); ++i)
            {
                if (Math.Abs(u[i] - t[i]) > 1e-6)
                {
                    QAssert.Fail("solve and apply are not consistent "
                                 + "\n expected      : " + u[i]
                                 + "\n calculated    : " + t[i]);
                }
            }

            //check assignment operator
            copyOfDxx.add(new SecondDerivativeOp(1, mesher));
            copyOfDxx = dxx;

            t = dxx.solve_splitting(copyOfDxx.apply(u), 1.0, 0.0);

            for (int i = 0; i < u.size(); ++i)
            {
                if (Math.Abs(u[i] - t[i]) > 1e-6)
                {
                    QAssert.Fail("solve and apply are not consistent "
                                 + "\n expected      : " + u[i]
                                 + "\n calculated    : " + t[i]);
                }
            }
        }
Esempio n. 3
0
        public void testSecondDerivativesMapApply()
        {
            int[]      dims = new int[] { 50, 50, 50 };
            List <int> dim  = new List <int>(dims);

            FdmLinearOpLayout index = new FdmLinearOpLayout(dim);

            List <Pair <double?, double?> > boundaries = new List <Pair <double?, double?> > ();

            boundaries.Add(new Pair <double?, double?>(0, 0.5));
            boundaries.Add(new Pair <double?, double?>(0, 0.5));
            boundaries.Add(new Pair <double?, double?>(0, 0.5));

            FdmMesher mesher = new UniformGridMesher(index, boundaries);

            Vector r = new Vector(mesher.layout().size());
            FdmLinearOpIterator endIter = index.end();

            for (FdmLinearOpIterator iter = index.begin(); iter != endIter; ++iter)
            {
                double x = mesher.location(iter, 0);
                double y = mesher.location(iter, 1);
                double z = mesher.location(iter, 2);

                r[iter.index()] = Math.Sin(x) * Math.Cos(y) * Math.Exp(z);
            }

            Vector t = new SecondDerivativeOp(0, mesher).apply(r);

            double tol = 5e-2;

            for (FdmLinearOpIterator iter = index.begin(); iter != endIter; ++iter)
            {
                int    i = iter.index();
                double x = mesher.location(iter, 0);
                double y = mesher.location(iter, 1);
                double z = mesher.location(iter, 2);

                double d = -Math.Sin(x) * Math.Cos(y) * Math.Exp(z);
                if (iter.coordinates()[0] == 0 || iter.coordinates()[0] == dims[0] - 1)
                {
                    d = 0;
                }

                if (Math.Abs(d - t[i]) > tol)
                {
                    QAssert.Fail("numerical derivative in dx^2 deviation is too big"
                                 + "\n  found at " + x + " " + y + " " + z);
                }
            }

            t = new SecondDerivativeOp(1, mesher).apply(r);
            for (FdmLinearOpIterator iter = index.begin(); iter != endIter; ++iter)
            {
                int    i = iter.index();
                double x = mesher.location(iter, 0);
                double y = mesher.location(iter, 1);
                double z = mesher.location(iter, 2);

                double d = -Math.Sin(x) * Math.Cos(y) * Math.Exp(z);
                if (iter.coordinates()[1] == 0 || iter.coordinates()[1] == dims[1] - 1)
                {
                    d = 0;
                }

                if (Math.Abs(d - t[i]) > tol)
                {
                    QAssert.Fail("numerical derivative in dy^2 deviation is too big"
                                 + "\n  found at " + x + " " + y + " " + z);
                }
            }

            t = new SecondDerivativeOp(2, mesher).apply(r);
            for (FdmLinearOpIterator iter = index.begin(); iter != endIter; ++iter)
            {
                int    i = iter.index();
                double x = mesher.location(iter, 0);
                double y = mesher.location(iter, 1);
                double z = mesher.location(iter, 2);

                double d = Math.Sin(x) * Math.Cos(y) * Math.Exp(z);
                if (iter.coordinates()[2] == 0 || iter.coordinates()[2] == dims[2] - 1)
                {
                    d = 0;
                }

                if (Math.Abs(d - t[i]) > tol)
                {
                    QAssert.Fail("numerical derivative in dz^2 deviation is too big"
                                 + "\n  found at " + x + " " + y + " " + z);
                }
            }
        }