Exemplo n.º 1
0
        protected override SayeQuadRule SetGaussQuadratureNodes(SayeSquare arg)
        {
            //Aquire needed data
            //------------------------------------------------------------------------------------------------------------
            QuadRule gaussRule_2D = Square.Instance.GetQuadratureRule(order);
            MultidimensionalArray nodes_GaussRule_2D   = ((MultidimensionalArray)gaussRule_2D.Nodes).CloneAs();
            MultidimensionalArray weights_GaussRule_2D = gaussRule_2D.Weights.CloneAs();

            double[] diameters = arg.Diameters;
            MultidimensionalArray centerArr = arg.GetCellCenter().ExtractSubArrayShallow(new int[] { 0, -1 });
            double jacobian = diameters[0] * diameters[1];

            //AffineTransformation of nodes, scale weights
            //------------------------------------------------------------------------------------------------------------
            //Scale Nodes
            for (int i = 0; i < 2; ++i)
            {
                nodes_GaussRule_2D.ColScale(i, diameters[i]);
            }
            //Scale Weights
            weights_GaussRule_2D.Scale(jacobian);
            //Move Nodes
            int[] index = new int[] { 0, -1 };
            for (int i = 0; i < gaussRule_2D.NoOfNodes; ++i)
            {
                index[0] = i;
                nodes_GaussRule_2D.AccSubArray(1, centerArr, index);
            }

            //Set return data
            //------------------------------------------------------------------------------------------------------------
            SayeQuadRule transformed_GaussRule_2D = new SayeQuadRule(nodes_GaussRule_2D, weights_GaussRule_2D);

            return(transformed_GaussRule_2D);
        }
        static void SymmInv(MultidimensionalArray M, MultidimensionalArray L, MultidimensionalArray R)
        {
            L.Clear();
            R.Clear();
            L.AccEye(1.0);
#if DEBUG
            var Mbefore = M.CloneAs();
#endif

            int n = M.NoOfRows;
            for (int i = 0; i < n; i++)
            {
                double M_ii = M[i, i];
                if (M_ii == 0.0)
                {
                    throw new ArithmeticException("Zero diagonal element at " + i + "-th row.");
                }
                double scl = 1.0 / Math.Sqrt(Math.Abs(M_ii));
                M.RowScale(i, scl);
                L.RowScale(i, scl);
                M.ColScale(i, scl);

                double diagsign = Math.Sign(M[i, i]);
                if (diagsign == 0.0)
                {
                    throw new ArithmeticException("Zero diagonal element at " + i + "-th row.");
                }
                if (Math.Abs(Math.Abs(M[i, i]) - 1.0) > 1.0e-8)
                {
                    throw new ArithmeticException("Unable to create diagonal 1.0.");
                }

                for (int k = i + 1; k < n; k++)
                {
                    double M_ki = M[k, i];

                    M.RowAdd(i, k, -M_ki * diagsign);
                    L.RowAdd(i, k, -M_ki * diagsign);
                    M.ColAdd(i, k, -M_ki * diagsign);

                    Debug.Assert(Math.Abs(M[k, i]) < 1.0e-8);
                    Debug.Assert(Math.Abs(M[i, k]) < 1.0e-8);
                }
            }

            L.TransposeTo(R);

#if DEBUG
            var Test = MultidimensionalArray.Create(M.Lengths);
            //var Q = MultidimensionalArray.Create(M.Lengths);
            //Test.AccEye(1.0);
            Test.Multiply(-1.0, L, Mbefore, R, 1.0, "ij", "ik", "kl", "lj");
            for (int i = 0; i < n; i++)
            {
                //Debug.Assert((Test[i, i].Abs() - 1.0).Abs() < 1.0e-8);
                //Test[i, i] -= Math.Sign(Test[i, i]);
                Test[i, i] = 0;
            }

            double TestNorm = Test.InfNorm();
            double scale    = Math.Max(Mbefore.InfNorm(), R.InfNorm());
            Debug.Assert(TestNorm / scale < 1.0e-4);

            /*
             * if(TestNorm / scale >= 1.0e-8) {
             *  var MM = Mbefore.CloneAs();
             *  MultidimensionalArray Lo = MultidimensionalArray.Create(n, n);
             *
             *  for(int j = 0; j < n; j++) {
             *      double Lo_jj = MM[j, j];
             *      for(int k = 0; k < j; k++) {
             *          Lo_jj -= Lo[j, k].Pow2();
             *      }
             *
             *      double sig = Math.Abs(Lo_jj);
             *      Lo[j, j] = Math.Sqrt(Lo_jj * sig);
             *
             *
             *      for(int i = j; i < n; i++) {
             *          double acc = MM[i, j];
             *          for(int k = 0; k < j; k++) {
             *              acc -= Lo[i, k] * Lo[j, k];
             *          }
             *
             *          Lo[i, j] = (1 / (Lo[j, j] * sig)) * acc;
             *      }
             *  }
             *
             *  int info = 0;
             *  unsafe {
             *      fixed(double* B_entries = Lo.Storage) {
             *
             *          int UPLO = 'L', DIAG = 'N';
             *          LAPACK.F77_LAPACK.DTRTRI_(ref UPLO, ref DIAG, ref n, B_entries, ref n, out info);
             *      }
             *  }
             *
             *  MultidimensionalArray Up = MultidimensionalArray.Create(n, n);
             *  Lo.TransposeTo(Up);
             *  Test.Clear();
             *  Test.Multiply(-1.0, Lo, Mbefore, R, 1.0, "ij", "ik", "kl", "lj");
             *
             *
             *  for(int i = 0; i < n; i++) {
             *      //Debug.Assert((Test[i, i].Abs() - 1.0).Abs() < 1.0e-8);
             *      Test[i, i] -= Math.Sign(Test[i, i]);
             *  }
             *
             *  double TestNorm1 = Test.InfNorm();
             *  //double scale = Math.Max(Mbefore.InfNorm(), R.InfNorm());
             *  Console.WriteLine(TestNorm1);
             *
             * }
             */
#endif
        }