Exemplo n.º 1
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="interp_cartesian"></param>
        /// <returns></returns>
        internal MultidimensionalArray GetGeometricCenter(MultidimensionalArray interP_cartesian)
        {
            MultidimensionalArray cntr = center.CloneAs();
            int numSp = interP_cartesian.Lengths[0];

            // polygonal description of the interface
            MultidimensionalArray interPolygon = MultidimensionalArray.Create(numSp + 1, 2);

            for (int sp = 0; sp < numSp; sp++)
            {
                interPolygon[sp, 0] = interP_cartesian[sp, 0];
                interPolygon[sp, 1] = interP_cartesian[sp, 1];
            }
            interPolygon[numSp, 0] = interPolygon[0, 0];
            interPolygon[numSp, 1] = interPolygon[0, 1];

            //MultidimensionalArray center_rec = MultidimensionalArray.Create(1, 2);
            cntr.Clear();
            for (int p = 0; p < numSp; p++)
            {
                double a = interPolygon[p, 0] * interPolygon[p + 1, 1] - interPolygon[p + 1, 0] * interPolygon[p, 1];
                cntr[0, 0] += (interPolygon[p, 0] + interPolygon[p + 1, 0]) * a;
                cntr[0, 1] += (interPolygon[p, 1] + interPolygon[p + 1, 1]) * a;
            }
            double area = getPolygonalArea(interPolygon);

            cntr[0, 0] /= 6 * area;
            cntr[0, 1] /= 6 * area;

            return(cntr);
        }
Exemplo n.º 2
0
        /// <summary>
        /// Change-of-basis, in cell 0
        /// </summary>
        /// <param name="jCell"></param>
        /// <param name="pl"></param>
        public MultidimensionalArray GetChangeofBasisMatrix(int jCell, PolynomialList pl)
        {
            var m_Context = this.GridDat;
            int N         = this.Length;
            int M         = pl.Count;
            int J         = this.GridDat.iLogicalCells.NoOfLocalUpdatedCells;

            if (jCell < 0 || jCell >= J)
            {
                throw new ArgumentOutOfRangeException("cell index out of range");
            }
            MultidimensionalArray Mtx = MultidimensionalArray.Create(N, M);


            var cellMask = new CellMask(m_Context, new[] { new Chunk()
                                                           {
                                                               i0 = jCell, Len = 1
                                                           } }, MaskType.Geometrical);

            // we project the basis function from 'jCell1' onto 'jCell0'

            CellQuadrature.GetQuadrature(new int[2] {
                N, M
            }, m_Context,
                                         (new CellQuadratureScheme(true, cellMask)).Compile(m_Context, this.Degree + pl.MaxAbsoluteDegree), // integrate over target cell
                                         delegate(int i0, int Length, QuadRule QR, MultidimensionalArray _EvalResult) {
                NodeSet nodes_Cell0 = QR.Nodes;
                Debug.Assert(Length == 1);

                //NodesGlobal.Allocate(1, nodes_Cell0.GetLength(0), nodes_Cell0.GetLength(1));
                //m_Context.TransformLocal2Global(nodes_Cell0, jCell0, 1, NodesGlobal, 0);
                //var nodes_Cell1 = new NodeSet(GridDat.iGeomCells.GetRefElement(jCell1), nodes_Cell0.GetLength(0), nodes_Cell0.GetLength(1));
                //m_Context.TransformGlobal2Local(NodesGlobal.ExtractSubArrayShallow(0, -1, -1), nodes_Cell1, jCell1, null);
                //nodes_Cell1.LockForever();

                var phi_0 = this.CellEval(nodes_Cell0, jCell, 1).ExtractSubArrayShallow(0, -1, -1);
                MultidimensionalArray R = MultidimensionalArray.Create(QR.NoOfNodes, pl.Count);
                pl.Evaluate(nodes_Cell0, R);

                var EvalResult = _EvalResult.ExtractSubArrayShallow(0, -1, -1, -1);
                EvalResult.Multiply(1.0, R, phi_0, 0.0, "knm", "km", "kn");
            },
                                         delegate(int i0, int Length, MultidimensionalArray ResultsOfIntegration) {
                Debug.Assert(Length == 1);

                var res = ResultsOfIntegration.ExtractSubArrayShallow(0, -1, -1);
                Mtx.Clear();
                Mtx.Acc(1.0, res);
            }).Execute();

            return(Mtx);
        }
Exemplo n.º 3
0
            protected override void Evaluate(int i0, int Length, QuadRule rule, MultidimensionalArray EvalResult)
            {
                NodeSet NodesUntransformed = rule.Nodes;
                int     M = NodesUntransformed.GetLength(0);
                //int D = NodesUntransformed.GetLength(1);

                MultidimensionalArray fieldvalsA = EvalResult.ResizeShallow(new int[] { Length, NodesUntransformed.GetLength(0) });

                fieldvalsA.Clear();
                m_FieldA.Evaluate(i0, Length, NodesUntransformed, fieldvalsA, 1.0);
                fieldvalsB.Clear();
                m_FieldB.Evaluate(i0, Length, NodesUntransformed, fieldvalsB, 1.0);

                for (int j = 0; j < Length; j++)
                {
                    for (int m = 0; m < M; m++)
                    {
                        EvalResult[j, m, 0] = fieldvalsA[j, m] * fieldvalsB[j, m];
                    }
                }
            }
Exemplo n.º 4
0
        private static void ExtractBlock(
            int[] _i0s,
            int[] _Lns,
            bool Sp2Full,
            BlockMsrMatrix MtxSp, ref MultidimensionalArray MtxFl) //
        {
            Debug.Assert(_i0s.Length == _Lns.Length);
            int E = _i0s.Length;

            int NN = _Lns.Sum();

            if (MtxFl == null || MtxFl.NoOfRows != NN)
            {
                Debug.Assert(Sp2Full == true);
                MtxFl = MultidimensionalArray.Create(NN, NN);
            }
            else
            {
                if (Sp2Full)
                {
                    MtxFl.Clear();
                }
            }

            if (!Sp2Full)
            {
                Debug.Assert(MtxSp != null);
            }


            int i0Rowloc = 0;

            for (int eRow = 0; eRow < E; eRow++)   // loop over variables in configuration
            {
                int i0Row = _i0s[eRow];
                int NRow  = _Lns[eRow];

                int i0Colloc = 0;
                for (int eCol = 0; eCol < E; eCol++)   // loop over variables in configuration
                {
                    int i0Col = _i0s[eCol];
                    int NCol  = _Lns[eCol];

                    MultidimensionalArray MtxFl_blk;
                    if (i0Rowloc == 0 && NRow == MtxFl.GetLength(0) && i0Colloc == 0 && NCol == MtxFl.GetLength(1))
                    {
                        MtxFl_blk = MtxFl;
                    }
                    else
                    {
                        MtxFl_blk = MtxFl.ExtractSubArrayShallow(new[] { i0Rowloc, i0Colloc }, new[] { i0Rowloc + NRow - 1, i0Colloc + NCol - 1 });
                    }

                    if (Sp2Full)
                    {
                        if (MtxSp != null)
                        {
                            MtxSp.ReadBlock(i0Row, i0Col, MtxFl_blk);
                        }
                        else
                        {
                            MtxFl_blk.AccEye(1.0);
                        }
                    }
                    else
                    {
                        MtxSp.AccBlock(i0Row, i0Col, 1.0, MtxFl_blk, 0.0);
                    }
#if DEBUG
                    for (int n_row = 0; n_row < NRow; n_row++)     // row loop...
                    {
                        for (int n_col = 0; n_col < NCol; n_col++) // column loop...
                        {
                            Debug.Assert(MtxFl[n_row + i0Rowloc, n_col + i0Colloc] == ((MtxSp != null) ? (MtxSp[n_row + i0Row, n_col + i0Col]) : (n_col == n_row ? 1.0 : 0.0)));
                        }
                    }
#endif
                    i0Colloc += NCol;
                }
                i0Rowloc += NRow;
            }
        }
Exemplo n.º 5
0
        void BlockSol <V1, V2>(BlockMsrMatrix M, V1 X, V2 B)
            where V1 : IList <double>
            where V2 : IList <double> //
        {
            int i0 = M.RowPartitioning.i0;
            int iE = M.RowPartitioning.iE;

            var Part = M.RowPartitioning;

            Debug.Assert(Part.EqualsPartition(this.CurrentStateMapping));

            int J = m_LsTrk.GridDat.Cells.NoOfLocalUpdatedCells;

            double[] MtxVals = null;
            int[]    Indices = null;

            MultidimensionalArray Block = null;

            double[] x = null, b = null;
            for (int j = 0; j < J; j++)
            {
                int bS = this.CurrentStateMapping.LocalUniqueCoordinateIndex(0, j, 0);
                int Nj = this.CurrentStateMapping.GetTotalNoOfCoordinatesPerCell(j);

                if (Block == null || Block.NoOfRows != Nj)
                {
                    Block = MultidimensionalArray.Create(Nj, Nj);
                    x     = new double[Nj];
                    b     = new double[Nj];
                }
                else
                {
                    Block.Clear();
                }


                // extract block and part of RHS
                for (int iRow = 0; iRow < Nj; iRow++)
                {
                    bool ZeroRow = true;
                    //MsrMatrix.MatrixEntry[] row = M.GetRow(iRow + bS + i0);
                    int LR = M.GetRow(iRow + bS + i0, ref Indices, ref MtxVals);

                    //foreach (var entry in row) {
                    for (int lr = 0; lr < LR; lr++)
                    {
                        int    ColIndex = Indices[lr];
                        double Value    = MtxVals[lr];

                        Block[iRow, ColIndex - (bS + i0)] = Value;
                        if (Value != 0.0)
                        {
                            ZeroRow = false;
                        }
                    }
                    b[iRow] = B[iRow + bS];

                    if (ZeroRow)
                    {
                        if (b[iRow] != 0.0)
                        {
                            throw new ArithmeticException();
                        }
                        else
                        {
                            Block[iRow, iRow] = 1.0;
                        }
                    }
                }

                // solve
                Block.SolveSymmetric(x, b);

                // store solution
                for (int iRow = 0; iRow < Nj; iRow++)
                {
                    X[iRow + bS] = x[iRow];
                }
            }
        }
Exemplo n.º 6
0
        /// <summary>
        /// computes matrix and affine vector of the affine-linear transformation
        /// that maps the vectors in the <paramref name="preimage"/> to <paramref name="image"/>;
        /// </summary>
        /// <param name="preimage">
        /// The preimage: L vectors of dimension D_dom;
        /// <list type="bullet">
        ///   <item>1st index: vector/vertex index, length is L</item>
        ///   <item>2nd index: spatial dimension, length is D_dom</item>
        /// </list>
        /// Tip: use <see cref="ilPSP.Utils.ArrayTools.Transpose{t}(t[,],t[,])"/>
        /// if the sequence of indices is not appropriate;
        /// </param>
        /// <param name="image">
        /// The image: L vectors of dimension D_cod;
        /// <list type="bullet">
        ///   <item>1st index: vector/vertex index, length is L</item>
        ///   <item>2nd index: spatial dimension, length is D_cod</item>
        /// </list>
        /// </param>
        /// <remarks>
        /// L*D_cod == D_cod + L*D_dom
        /// </remarks>
        public static AffineTrafo FromPoints(double[,] preimage, double[,] image)
        {
            int D_dom = preimage.GetLength(1);
            int D_cod = image.GetLength(1);
            int L     = preimage.GetLength(0); // number of points

            int rows = L * D_cod;
            int cols = D_cod + D_cod * D_dom;

            if (image.GetLength(0) != preimage.GetLength(0))
            {
                throw new ArgumentException("number of points in image and preimage must be equal.");
            }
            if (rows < cols)
            {
                throw new ArgumentException("insufficient information - not enough points.");
            }
            if (rows > cols)
            {
                throw new ArgumentException("over-determined information - to many points.");
            }



            MultidimensionalArray M = MultidimensionalArray.Create(rows, cols);

            double[] rhs = new double[M.NoOfCols];
            double[] x   = (double[])rhs.Clone();

            // gesucht: affine lineare Transformation: "xi -> x"
            // preimage = xi, image = x;
            //
            //          x = Tr*xi + o
            //
            // Sei z.B. D=2 (andere D's ergeben sich analog)
            // x1 = (x11,x12)^T, x2 = (x21,x22)^T und x3 seien die Bilder von
            // xi1 = (xi11,xi12), xi2 sowie xi3.
            //
            // gesucht sind die Matrix Tr und der Vektor o = (o1,o2)^T,
            //
            //                   [ Tr11  Tr12 ]
            //              Tr = [            ],
            //                   [ Tr21  Tr22 ]
            //
            // welche mit einem Glsys. der folgenden Form berechnet werden:
            //
            // [ 1 0   xi11 xi12     0    0  ]   [ o1  ]   [ x11 ]
            // [ 0 1    0    0     xi11 xi12 ]   [ o2  ]   [ x12 ]
            // [                             ]   [     ]   [     ]
            // [ 1 0   xi21 xi22     0    0  ] * [ T11 ] = [ x21 ]
            // [ 0 1    0    0     xi21 xi22 ]   [ T12 ]   [ x22 ]
            // [                             ]   [     ]   [     ]
            // [ 1 0   xi31 xi32     0    0  ]   [ T21 ]   [ x31 ]
            // [ 0 1    0    0     xi31 xi32 ]   [ T22 ]   [ x31 ]
            //
            //

            // build rhs
            for (int l = 0; l < L; l++)   // loop over image points
            {
                for (int d = 0; d < D_cod; d++)
                {
                    rhs[l * D_cod + d] = image[l, d];
                }
            }

            // build matrix
            M.Clear();
            for (int l = 0; l < L; l++)   // loop over image points
            {
                for (int d = 0; d < D_cod; d++)
                {
                    M[l * D_cod + d, d] = 1.0;

                    for (int ddd = 0; ddd < D_dom; ddd++)
                    {
                        M[l * D_cod + d, D_cod + D_dom * d + ddd] = preimage[l, ddd];
                    }
                }
            }

            // solve Matrix
            M.Solve(x, rhs);

            // save results, return
            AffineTrafo Trafo = new AffineTrafo(D_dom, D_cod);

            for (int d = 0; d < D_cod; d++)
            {
                Trafo.Affine[d] = x[d];

                for (int dd = 0; dd < D_dom; dd++)
                {
                    Trafo.Matrix[d, dd] = x[D_cod + d * D_dom + dd];
                }
            }
            return(Trafo);
        }
Exemplo n.º 7
0
        public void LimitFieldValues(IEnumerable <DGField> ConservativeVariables, IEnumerable <DGField> DerivedFields)
        {
            //IProgram<CNSControl> program;
            //CNSFieldSet fieldSet = program.WorkingSet;

            DGField Density    = ConservativeVariables.Single(f => f.Identification == Variables.Density.Name);
            DGField Momentum_0 = ConservativeVariables.Single(f => f.Identification == Variables.Momentum[0].Name);
            DGField Momentum_1 = ConservativeVariables.Single(f => f.Identification == Variables.Momentum[1].Name);
            DGField Energy     = ConservativeVariables.Single(f => f.Identification == Variables.Energy.Name);

            foreach (var chunkRulePair in quadRuleSet)
            {
                if (chunkRulePair.Chunk.Len > 1)
                {
                    throw new System.Exception();
                }

                MultidimensionalArray densityValues = MultidimensionalArray.Create(chunkRulePair.Chunk.Len, chunkRulePair.Rule.NoOfNodes);
                Density.Evaluate(chunkRulePair.Chunk.i0, chunkRulePair.Chunk.Len, chunkRulePair.Rule.Nodes, densityValues);
                MultidimensionalArray m0Values = MultidimensionalArray.Create(chunkRulePair.Chunk.Len, chunkRulePair.Rule.NoOfNodes);
                Momentum_0.Evaluate(chunkRulePair.Chunk.i0, chunkRulePair.Chunk.Len, chunkRulePair.Rule.Nodes, m0Values);
                MultidimensionalArray m1Values = MultidimensionalArray.Create(chunkRulePair.Chunk.Len, chunkRulePair.Rule.NoOfNodes);
                Momentum_1.Evaluate(chunkRulePair.Chunk.i0, chunkRulePair.Chunk.Len, chunkRulePair.Rule.Nodes, m1Values);
                MultidimensionalArray energyValues = MultidimensionalArray.Create(chunkRulePair.Chunk.Len, chunkRulePair.Rule.NoOfNodes);
                Energy.Evaluate(chunkRulePair.Chunk.i0, chunkRulePair.Chunk.Len, chunkRulePair.Rule.Nodes, energyValues);

                for (int i = 0; i < chunkRulePair.Chunk.Len; i++)
                {
                    int cell = i + chunkRulePair.Chunk.i0;

                    CellMask             singleCellMask   = new CellMask(speciesMap.Tracker.GridDat, chunkRulePair.Chunk);
                    CellQuadratureScheme singleCellScheme = new CellQuadratureScheme(
                        new FixedRuleFactory <QuadRule>(chunkRulePair.Rule), singleCellMask);
                    var singleCellRule = singleCellScheme.Compile(speciesMap.Tracker.GridDat, 99);

                    SpeciesId species = speciesMap.Tracker.GetSpeciesId(speciesMap.Control.FluidSpeciesName);
                    double    volume  = speciesMap.QuadSchemeHelper.NonAgglomeratedMetrics.CutCellVolumes[species][cell];

                    double integralDensity = Density.LxError((ScalarFunction)null, (X, a, b) => a, singleCellRule);
                    double meanDensity     = integralDensity / volume;

                    if (meanDensity < epsilon)
                    {
                        throw new System.Exception();
                    }

                    double minDensity = double.MaxValue;
                    for (int j = 0; j < chunkRulePair.Rule.NoOfNodes; j++)
                    {
                        minDensity = Math.Min(minDensity, densityValues[i, j]);
                    }

                    double thetaDensity = Math.Min(1.0, (meanDensity - epsilon) / (meanDensity - minDensity));
                    if (thetaDensity < 1.0)
                    {
                        Console.WriteLine("Scaled density in cell {0}!", cell);
                    }

                    // Scale for positive density (Beware: Basis is not orthonormal on sub-volume!)
                    for (int j = 0; j < Density.Basis.Length; j++)
                    {
                        Density.Coordinates[cell, j] *= thetaDensity;
                    }
                    Density.AccConstant(meanDensity * (1.0 - thetaDensity), singleCellMask);

                    // Re-evaluate since inner energy has changed
                    densityValues.Clear();
                    Density.Evaluate(cell, 1, chunkRulePair.Rule.Nodes, densityValues);

#if DEBUG
                    // Probe 1
                    for (int j = 0; j < chunkRulePair.Rule.NoOfNodes; j++)
                    {
                        if (densityValues[i, j] - epsilon < -1e-15)
                        {
                            throw new System.Exception();
                        }
                    }
#endif

                    double integralMomentumX = Momentum_0.LxError((ScalarFunction)null, (X, a, b) => a, singleCellRule);
                    double meanMomentumX     = integralMomentumX / volume;
                    double integralMomentumY = Momentum_1.LxError((ScalarFunction)null, (X, a, b) => a, singleCellRule);
                    double meanMomentumY     = integralMomentumY / volume;
                    double integralEnergy    = Energy.LxError((ScalarFunction)null, (X, a, b) => a, singleCellRule);
                    double meanEnergy        = integralEnergy / volume;

                    double meanInnerEnergy = meanEnergy - 0.5 * (meanMomentumX * meanMomentumX + meanMomentumY * meanMomentumY) / meanDensity;
                    if (meanInnerEnergy < epsilon)
                    {
                        throw new System.Exception();
                    }

                    double minInnerEnergy = double.MaxValue;
                    for (int j = 0; j < chunkRulePair.Rule.NoOfNodes; j++)
                    {
                        double innerEnergy = energyValues[i, j] - 0.5 * (m0Values[i, j] * m0Values[i, j] + m1Values[i, j] * m1Values[i, j]) / densityValues[i, j];
                        minInnerEnergy = Math.Min(minInnerEnergy, innerEnergy);
                    }

                    // Scale for positive inner energy (Beware: Basis is not orthonormal on sub-volume!)
                    double thetaInnerEnergy = Math.Min(1.0, (meanInnerEnergy - epsilon) / (meanInnerEnergy - minInnerEnergy));
                    if (thetaInnerEnergy < 1.0)
                    {
                        Console.WriteLine("Scaled inner energy in cell {0}!", cell);
                    }


                    for (int j = 0; j < Density.Basis.Length; j++)
                    {
                        Density.Coordinates[chunkRulePair.Chunk.i0 + i, j]    *= thetaInnerEnergy;
                        Momentum_0.Coordinates[chunkRulePair.Chunk.i0 + i, j] *= thetaInnerEnergy;
                        Momentum_1.Coordinates[chunkRulePair.Chunk.i0 + i, j] *= thetaInnerEnergy;
                        Energy.Coordinates[chunkRulePair.Chunk.i0 + i, j]     *= thetaInnerEnergy;
                    }
                    Density.AccConstant(meanDensity * (1.0 - thetaInnerEnergy), singleCellMask);
                    Momentum_0.AccConstant(meanMomentumX * (1.0 - thetaInnerEnergy), singleCellMask);
                    Momentum_1.AccConstant(meanMomentumY * (1.0 - thetaInnerEnergy), singleCellMask);
                    Energy.AccConstant(meanEnergy * (1.0 - thetaInnerEnergy), singleCellMask);


#if DEBUG
                    // Probe 2
                    densityValues.Clear();
                    Density.Evaluate(chunkRulePair.Chunk.i0, chunkRulePair.Chunk.Len, chunkRulePair.Rule.Nodes, densityValues);
                    m0Values.Clear();
                    Momentum_0.Evaluate(chunkRulePair.Chunk.i0, chunkRulePair.Chunk.Len, chunkRulePair.Rule.Nodes, m0Values);
                    m1Values.Clear();
                    Momentum_1.Evaluate(chunkRulePair.Chunk.i0, chunkRulePair.Chunk.Len, chunkRulePair.Rule.Nodes, m1Values);
                    energyValues.Clear();
                    Energy.Evaluate(chunkRulePair.Chunk.i0, chunkRulePair.Chunk.Len, chunkRulePair.Rule.Nodes, energyValues);

                    for (int j = 0; j < chunkRulePair.Rule.NoOfNodes; j++)
                    {
                        StateVector state = new StateVector(
                            speciesMap.GetMaterial(1.0),
                            densityValues[i, j],
                            new Vector(m0Values[i, j], m1Values[i, j], 0.0),
                            energyValues[i, j]);
                        if (!state.IsValid)
                        {
                            throw new System.Exception();
                        }
                    }
#endif
                }
            }
        }
Exemplo n.º 8
0
        private double[] ComputeBenchmarkQuantities()
        {
            int order = 0;

            if (CorrectionLsTrk.GetCachedOrders().Count > 0)
            {
                order = CorrectionLsTrk.GetCachedOrders().Max();
            }
            else
            {
                order = 1;
            }
            var SchemeHelper = CorrectionLsTrk.GetXDGSpaceMetrics(CorrectionLsTrk.SpeciesIdS.ToArray(), order, 1).XQuadSchemeHelper;

            // area of bubble
            double    area  = 0.0;
            SpeciesId spcId = CorrectionLsTrk.SpeciesIdS[1];
            var       vqs   = SchemeHelper.GetVolumeQuadScheme(spcId);

            CellQuadrature.GetQuadrature(new int[] { 1 }, CorrectionLsTrk.GridDat,
                                         vqs.Compile(CorrectionLsTrk.GridDat, order),
                                         delegate(int i0, int Length, QuadRule QR, MultidimensionalArray EvalResult) {
                EvalResult.SetAll(1.0);
            },
                                         delegate(int i0, int Length, MultidimensionalArray ResultsOfIntegration) {
                for (int i = 0; i < Length; i++)
                {
                    area += ResultsOfIntegration[i, 0];
                }
            }
                                         ).Execute();
            area = area.MPISum();

            // surface
            double surface = 0.0;
            //CellQuadratureScheme cqs = SchemeHelper.GetLevelSetquadScheme(0, LsTrk.Regions.GetCutCellMask());
            var surfElemVol = SchemeHelper.Get_SurfaceElement_VolumeQuadScheme(spcId);

            CellQuadrature.GetQuadrature(new int[] { 1 }, CorrectionLsTrk.GridDat,
                                         surfElemVol.Compile(CorrectionLsTrk.GridDat, this.m_HMForder),
                                         delegate(int i0, int Length, QuadRule QR, MultidimensionalArray EvalResult) {
                EvalResult.SetAll(1.0);
            },
                                         delegate(int i0, int Length, MultidimensionalArray ResultsOfIntegration) {
                for (int i = 0; i < Length; i++)
                {
                    surface += ResultsOfIntegration[i, 0];
                }
            }
                                         ).Execute();
            surface = surface.MPISum();

            // circularity
            double diamtr_c  = Math.Sqrt(4 * area / Math.PI);
            double perimtr_b = surface;

            double circ = Math.PI * diamtr_c / perimtr_b;

            // total concentration, careful above values are "old" when CorrectionTracker is not updated, this value is always "new"
            double concentration = 0.0;
            var    tqs           = new CellQuadratureScheme();

            CellQuadrature.GetQuadrature(new int[] { 1 }, phi.GridDat,
                                         tqs.Compile(phi.GridDat, phi.Basis.Degree * 2 + 2),
                                         delegate(int i0, int Length, QuadRule QR, MultidimensionalArray EvalResult) {
                phi.Evaluate(i0, Length, QR.Nodes, EvalResult.ExtractSubArrayShallow(-1, -1, 0));
            },
                                         delegate(int i0, int Length, MultidimensionalArray ResultsOfIntegration) {
                for (int i = 0; i < Length; i++)
                {
                    concentration += ResultsOfIntegration[i, 0];
                }
            }
                                         ).Execute();
            concentration = concentration.MPISum();

            // total mixing energy
            double energy = 0.0;
            var    eqs    = new CellQuadratureScheme();

            int D = phi.GridDat.SpatialDimension;

            SinglePhaseField[] PhiGrad = new SinglePhaseField[D];
            for (int d = 0; d < D; d++)
            {
                PhiGrad[d] = new SinglePhaseField(phi.Basis, string.Format("G_{0}", d));
                PhiGrad[d].Derivative(1.0, phi, d);
            }

            MultidimensionalArray _Phi      = new MultidimensionalArray(2);
            MultidimensionalArray _GradPhi  = new MultidimensionalArray(3);
            MultidimensionalArray _NormGrad = new MultidimensionalArray(2);

            CellQuadrature.GetQuadrature(new int[] { 1 }, phi.GridDat,
                                         eqs.Compile(phi.GridDat, phi.Basis.Degree * 2 + 2),
                                         delegate(int i0, int Length, QuadRule QR, MultidimensionalArray EvalResult) {
                int K = EvalResult.GetLength(1);
                // alloc buffers
                // -------------

                if (_Phi.GetLength(0) != Length || _Phi.GetLength(1) != K)
                {
                    _Phi.Allocate(Length, K);
                    _GradPhi.Allocate(Length, K, D);
                    _NormGrad.Allocate(Length, K);
                }
                else
                {
                    _Phi.Clear();
                    _GradPhi.Clear();
                    _NormGrad.Clear();
                }

                // chemical potential
                phi.Evaluate(i0, Length, QR.Nodes, _Phi.ExtractSubArrayShallow(-1, -1));
                _Phi.ApplyAll(x => 0.25 / (this.Control.cahn.Pow2()) * (x.Pow2() - 1.0).Pow2());

                for (int d = 0; d < D; d++)
                {
                    PhiGrad[d].Evaluate(i0, Length, QR.Nodes, _GradPhi.ExtractSubArrayShallow(-1, -1, d));
                }

                // free surface energy
                for (int d = 0; d < D; d++)
                {
                    var GradPhi_d = _GradPhi.ExtractSubArrayShallow(-1, -1, d);
                    _NormGrad.Multiply(1.0, GradPhi_d, GradPhi_d, 1.0, "ik", "ik", "ik");
                }
                _NormGrad.ApplyAll(x => 0.5 * x);

                EvalResult.ExtractSubArrayShallow(-1, -1, 0).Acc(1.0, _Phi);
                EvalResult.ExtractSubArrayShallow(-1, -1, 0).Acc(1.0, _NormGrad);
            },
                                         delegate(int i0, int Length, MultidimensionalArray ResultsOfIntegration) {
                for (int i = 0; i < Length; i++)
                {
                    energy += ResultsOfIntegration[i, 0];
                }
            }
                                         ).Execute();
            energy = energy.MPISum();

            // replace 1.96 (RB_TC2) with actual surface tension
            // see Yue (2004)
            double lambda = this.Control.cahn.Pow2() * 1.96 * surface / energy;

            return(new double[] { area, surface, circ, concentration, energy, lambda, this.Control.diff });
        }
Exemplo n.º 9
0
        static internal void InvertMassMatrixBlocks(
            out Dictionary <SpeciesId, MassMatrixBlockContainer> MassMatrixBlocksInv,
            Dictionary <SpeciesId, MassMatrixBlockContainer> MassMatrixBlocks,
            int N)
        {
            using (new FuncTrace()) {
                MassMatrixBlocksInv = new Dictionary <SpeciesId, MassMatrixBlockContainer>();
                foreach (var Species in MassMatrixBlocks.Keys)
                {
                    var mblk = MassMatrixBlocks[Species].MassMatrixBlocks;
                    //var mblkB4agg = MassMatrixBlocks[Species].MassMatrixBlocks_B4Agglom;
                    var invmblk = MultidimensionalArray.Create(mblk.GetLength(0), N, N);
                    MassMatrixBlocksInv.Add(Species,
                                            new MassMatrixBlockContainer()
                    {
                        MassMatrixBlocks = invmblk,
                        //jCell2jSub = MassMatrixBlocks[Species].jCell2jSub,
                        jSub2jCell        = MassMatrixBlocks[Species].jSub2jCell,
                        IntegrationDomain = MassMatrixBlocks[Species].IntegrationDomain
                    });

                    int B = mblk.GetLength(0);
                    Debug.Assert(mblk.GetLength(2) >= N);

                    MultidimensionalArray blk     = MultidimensionalArray.Create(N, N);
                    MultidimensionalArray inv_Blk = MultidimensionalArray.Create(N, N);


                    // loop over all cut cells (mass matrix blocks)...
                    for (int b = 0; b < B; b++)
                    {
                        MultidimensionalArray _blk;
                        //if ((aggSw == true) || (mblkB4agg[b] == null)) {
                        _blk = mblk.ExtractSubArrayShallow(new int[] { b, 0, 0 }, new int[] { b - 1, N - 1, N - 1 });
                        //} else {
                        //    Debug.Assert(aggSw == false);
                        //    Debug.Assert(mblkB4agg[b] != null);
                        //    _blk = mblkB4agg[b].ExtractSubArrayShallow(new int[] { 0, 0 }, new int[] { N - 1, N - 1 });
                        //}

                        blk.Set(_blk);
                        if (blk.ContainsNanOrInf(true, true))
                        {
                            throw new ArithmeticException("NAN/INF in mass matrix.");
                        }

                        if (blk.InfNorm() == 0.0)
                        {
                            // a zero-block
                            invmblk.ExtractSubArrayShallow(b, -1, -1).Clear();
                        }
                        else
                        {
                            //blk.Invert(inv_Blk);
                            try {
                                inv_Blk.Clear();
                                inv_Blk.Acc(1.0, blk);
                                inv_Blk.InvertSymmetrical();

#if DEBUG
                                for (int n = 0; n < N; n++)
                                {
                                    for (int m = 0; m < N; m++)
                                    {
                                        Debug.Assert(inv_Blk[n, m] == inv_Blk[m, n]);
                                    }
                                }
#endif
                            } catch (ArithmeticException) {
                                Console.WriteLine("WARNING: indefinite mass matrix.");
                                blk.InvertTo(inv_Blk);
#if DEBUG
                                for (int n = 0; n < N; n++)
                                {
                                    for (int m = 0; m < N; m++)
                                    {
                                        Debug.Assert(Math.Abs(inv_Blk[n, m] - inv_Blk[m, n]) / (Math.Abs(inv_Blk[n, m]) + Math.Abs(inv_Blk[m, n])) <= 1.0e-9);
                                    }
                                }
#endif
                            }

                            if (blk.ContainsNanOrInf(true, true))
                            {
                                throw new ArithmeticException("NAN/INF in inverse mass matrix.");
                            }

                            invmblk.SetSubMatrix(inv_Blk, b, -1, -1);
                        }

                        /*
                         * bool Choleski_failed = false;
                         * bool Symmelim_failed = false;
                         * try {
                         *  blk.Initialize(_blk);
                         *  blk.InvertSymmetrical();
                         * } catch (ArithmeticException) {
                         *  Choleski_failed = true;
                         * }
                         * try {
                         *  blk.Initialize(_blk);
                         *  FullMatrix.TiredRoutine(blk);
                         * } catch (ArithmeticException) {
                         *  Symmelim_failed = true;
                         * }
                         *
                         * if (Choleski_failed || Symmelim_failed) {
                         *  Console.WriteLine("Mass matrix defect ({0},{1}): species {2}, jsub = {3};", Choleski_failed, Symmelim_failed,  LsTrk.GetSpeciesName(Species), b);
                         *
                         *  int J = LsTrk.Ctx.Grid.NoOfUpdateCells;
                         *  if (MassErrors == null) {
                         *      MassErrors = new Dictionary<SpeciesId, System.Collections.BitArray>();
                         *  }
                         *  if (!MassErrors.ContainsKey(Species)) {
                         *      MassErrors.Add(Species, new System.Collections.BitArray(J));
                         *  }
                         *  var _MassErrors = MassErrors[Species];
                         *
                         *  int[] globalIdx = cutted.SubgridIndex2LocalCellIndex;
                         *  int jCell = globalIdx[b];
                         *
                         *  _MassErrors[jCell] = true;
                         *
                         * }
                         * //*/
                    }
                }
            }
        }
Exemplo n.º 10
0
        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
        }
Exemplo n.º 11
0
        private static void ExtractBlock(int jCell,
                                         AggregationGridBasis basis, int[] Degrees,
                                         ChangeOfBasisConfig conf,
                                         int E, int[] _i0s, bool Sp2Full,
                                         BlockMsrMatrix MtxSp, ref MultidimensionalArray MtxFl)
        {
            int NN = conf.VarIndex.Sum(iVar => basis.GetLength(jCell, Degrees[iVar]));

            if (MtxFl == null || MtxFl.NoOfRows != NN)
            {
                Debug.Assert(Sp2Full == true);
                MtxFl = MultidimensionalArray.Create(NN, NN);
            }
            else
            {
                if (Sp2Full)
                {
                    MtxFl.Clear();
                }
            }

            if (!Sp2Full)
            {
                Debug.Assert(MtxSp != null);
            }


            int i0Rowloc = 0;

            for (int eRow = 0; eRow < E; eRow++)   // loop over variables in configuration
            {
                int i0Row   = _i0s[eRow];
                int iVarRow = conf.VarIndex[eRow];

                int NRow = basis.GetLength(jCell, Degrees[iVarRow]);

                int i0Colloc = 0;
                for (int eCol = 0; eCol < E; eCol++)   // loop over variables in configuration

                {
                    int i0Col   = _i0s[eCol];
                    int iVarCol = conf.VarIndex[eCol];

                    int NCol = basis.GetLength(jCell, Degrees[iVarCol]);

                    MultidimensionalArray MtxFl_blk;
                    if (i0Rowloc == 0 && NRow == MtxFl.GetLength(0) && i0Colloc == 0 && NCol == MtxFl.GetLength(1))
                    {
                        MtxFl_blk = MtxFl;
                    }
                    else
                    {
                        MtxFl_blk = MtxFl.ExtractSubArrayShallow(new[] { i0Rowloc, i0Colloc }, new[] { i0Rowloc + NRow - 1, i0Colloc + NCol - 1 });
                    }

                    /*
                     * for(int n_row = 0; n_row < NRow; n_row++) { // row loop...
                     *  for(int n_col = 0; n_col < NCol; n_col++) { // column loop...
                     *      if(Sp2Full) {
                     *          // copy from sparse to full
                     *          MtxFl[n_row + i0Rowloc, n_col + i0Colloc] = (MtxSp != null) ? ( MtxSp[n_row + i0Row, n_col + i0Col]) : (n_col == n_row ? 1.0 : 0.0);
                     *      } else {
                     *          // the other way around.
                     *          MtxSp[n_row + i0Row, n_col + i0Col] = MtxFl[n_row + i0Rowloc, n_col + i0Colloc];
                     *      }
                     *  }
                     * }
                     */

                    if (Sp2Full)
                    {
                        if (MtxSp != null)
                        {
                            MtxSp.ReadBlock(i0Row, i0Col, MtxFl_blk);
                        }
                        else
                        {
                            MtxFl_blk.AccEye(1.0);
                        }
                    }
                    else
                    {
#if DEBUG
                        Debug.Assert(MtxSp != null);
                        //for (int n_row = 0; n_row < NRow; n_row++) { // row loop...
                        //    for (int n_col = 0; n_col < NCol; n_col++) { // column loop...
                        //        Debug.Assert(MtxSp[n_row + i0Row, n_col + i0Col] == 0.0);
                        //    }
                        //}
#endif
                        MtxSp.AccBlock(i0Row, i0Col, 1.0, MtxFl_blk, 0.0);
                    }
#if DEBUG
                    for (int n_row = 0; n_row < NRow; n_row++)     // row loop...
                    {
                        for (int n_col = 0; n_col < NCol; n_col++) // column loop...
                        {
                            Debug.Assert(MtxFl[n_row + i0Rowloc, n_col + i0Colloc] == ((MtxSp != null) ? (MtxSp[n_row + i0Row, n_col + i0Col]) : (n_col == n_row ? 1.0 : 0.0)));
                        }
                    }
#endif


                    i0Colloc += NCol;
                }
                i0Rowloc += NRow;
            }
        }
Exemplo n.º 12
0
        /*
         *
         * /// <summary>
         * /// a vectorized evaluation of this polynomial
         * /// </summary>
         * /// <param name="result">
         * /// Dimension must be 1;
         * /// On exit, the k-th entry contains the value of the polynomial
         * /// at the point <paramref name="LocalPoints"/>[k,:];
         * /// </param>
         * /// <param name="LocalPoints">
         * /// Points at which the polynomial should be evaluated;
         * /// 1st index: Point index; 2nd index: spatial coordinate index,
         * /// 0,1 for 2D and 0,1,2 for 3D;
         * /// </param>
         * public void Evaluate(MultidimensionalArray result, MultidimensionalArray LocalPoints) {
         *  Evaluate(result, LocalPoints, GetMonomials(LocalPoints));
         * }
         *
         */


        /// <summary>
        /// A vectorized evaluation of this polynomial at specific nodes.
        /// </summary>
        /// <param name="result">
        /// Dimension must be 1;
        /// On exit, the k-th entry contains the value of the polynomial
        /// at the point <paramref name="LocalPoints"/>[k,:];
        /// </param>
        /// <param name="LocalPoints">
        /// Points at which the polynomial should be evaluated;
        /// 1st index: Point index; 2nd index: spatial coordinate index,
        /// 0,1 for 2D and 0,1,2 for 3D;
        /// </param>
        public void Evaluate(MultidimensionalArray result, NodeSet LocalPoints)
        {
            if (result.Dimension != 1)
            {
                throw new ArgumentException("dimension of result must be 1");
            }

            if (result.GetLength(0) != LocalPoints.GetLength(0))
            {
                throw new ArgumentException("length of result array must be equal to number of coordinates.");
            }

            result.Clear();

            // Empty polynomial, always zero
            if (this.Coeff.Length == 0)
            {
                return;
            }

            if (LocalPoints.GetLength(1) != this.SpatialDimension)
            {
                throw new ArgumentException("wrong spatial dimension;");
            }

            int iE = Coeff.Length;
            int L  = result.GetLength(0);
            int D  = SpatialDimension;

            MultidimensionalArray monomials = Caching.MonomialCache.Instance.GetMonomials(LocalPoints, this.AbsoluteDegree);

            // Required because the number of $monomials per point may be
            // higher than required by the $Degree of this polynomial
            int maxMonomialExponent = monomials.GetLength(2);

            unsafe
            {
                fixed(double *pResult = result.Storage, pCoeff = Coeff, pMonomials = monomials.Storage)
                {
                    fixed(int *pExponents = Exponents)
                    {
                        // loop over local points ...
                        double *pMonomialsCur = pMonomials;

                        for (int j = 0; j < L; j++)
                        {
                            // Beware: $result is not necessarily continuous so
                            // we cannot safely optimize this pointer evaluation
                            double *pResultCur = pResult + result.Index(j);

                            // loop over all exponents (with nonzero coefficients) ...
                            double *pCoeffCur     = pCoeff;
                            int *   pExponentsCur = pExponents;
                            double  acc           = 0;
                            for (int i = 0; i < iE; i++)
                            {
                                double monom = 1.0;

                                // loop over space dimensions ...
                                for (int k = 0; k < D; k++)
                                {
                                    monom *= *(pMonomialsCur + k * maxMonomialExponent + *(pExponentsCur++));
                                }

                                acc += monom * *(pCoeffCur++);
                            }
                            *pResultCur = acc;

                            pMonomialsCur += D * maxMonomialExponent;
                        }
                    }
                }
            }

            //// Reference implementation
            //// loop over local points ...
            //for (int j = 0; j < L; j++) {

            //    // loop over all exponents (with nonzero coeficients) ...
            //    for (int i = 0; i < iE; i++) {
            //        double monom = 1.0;

            //        // loop over space dimensions ...
            //        for (int k = 0; k < D; k++) {
            //            monom *= monomials[j, k, Exponents[i, k]];
            //        }

            //        monom *= Coeff[i];
            //        result[j] += monom;
            //    }
            //}
        }
Exemplo n.º 13
0
        void BlockSol <V1, V2>(BlockMsrMatrix M, V1 X, V2 B)
            where V1 : IList <double>
            where V2 : IList <double> //
        {
            Debug.Assert(X.Count == M.ColPartition.LocalLength);
            Debug.Assert(B.Count == M.RowPartitioning.LocalLength);

            var Part = M.RowPartitioning;

            Debug.Assert(Part.EqualsPartition(this.CurrentStateMapping));

            int J = m_LsTrk.GridDat.Cells.NoOfLocalUpdatedCells;

            Debug.Assert(J == M._RowPartitioning.LocalNoOfBlocks);
            Debug.Assert(J == M._ColPartitioning.LocalNoOfBlocks);

            var basisS   = this.CurrentStateMapping.BasisS.ToArray();
            int NoOfVars = basisS.Length;

            MultidimensionalArray Block = null;

            double[] x = null, b = null;
#if DEBUG
            var unusedIndex = new System.Collections.BitArray(B.Count);
#endif

            for (int j = 0; j < J; j++)   // loop over cells...

            {
                for (int iVar = 0; iVar < NoOfVars; iVar++)
                {
                    int bS = this.CurrentStateMapping.LocalUniqueCoordinateIndex(iVar, j, 0);
                    int Nj = basisS[iVar].GetLength(j);

                    if (Block == null || Block.NoOfRows != Nj)
                    {
                        Block = MultidimensionalArray.Create(Nj, Nj);
                        x     = new double[Nj];
                        b     = new double[Nj];
                    }
                    else
                    {
                        Block.Clear();
                    }

                    // extract block
                    M.ReadBlock(bS + M._RowPartitioning.i0, bS + M._ColPartitioning.i0, Block);

                    // extract part of RHS
                    for (int iRow = 0; iRow < Nj; iRow++)
                    {
                        bool ZeroRow = Block.GetRow(iRow).L2NormPow2() == 0;
                        b[iRow] = B[iRow + bS];

                        if (ZeroRow)
                        {
                            if (b[iRow] != 0.0)
                            {
                                throw new ArithmeticException();
                            }
                            else
                            {
                                Block[iRow, iRow] = 1.0;
                            }
                        }
#if DEBUG
                        unusedIndex[iRow + bS] = true;
#endif
                    }

                    // solve
                    Block.SolveSymmetric(x, b);

                    // store solution
                    for (int iRow = 0; iRow < Nj; iRow++)
                    {
                        X[iRow + bS] = x[iRow];
                    }
                }
            }
#if DEBUG
            for (int i = 0; i < unusedIndex.Length; i++)
            {
                if (unusedIndex[i] == false && B[i] != 0.0)
                {
                    throw new ArithmeticException("Non-zero entry in void region.");
                }
            }
#endif
        }
Exemplo n.º 14
0
        /// <summary>
        /// Algorithm to find an inflection point along a curve in the direction of the gradient
        /// </summary>
        /// <param name="gridData">The corresponding grid</param>
        /// <param name="field">The DG field, which shall be evalauted</param>
        /// <param name="results">
        /// The points along the curve (first point has to be user defined)
        /// Lenghts --> [0]: maxIterations + 1, [1]: 5
        /// [1]: x | y | function values | second derivatives | step sizes
        /// </param>
        /// <param name="iterations">The amount of iterations needed in order to find the inflection point</param>
        /// <param name="converged">Has an inflection point been found?</param>
        /// <param name = "jLocal" >Local cell index of the inflection point</ param >
        /// <param name="byFlux">Option for the calculation of the first and second order derivatives, default: true</param>
        private void WalkOnCurve(GridData gridData, SinglePhaseField field, MultidimensionalArray results, out int iterations, out bool converged, out int jLocal, bool byFlux = true)
        {
            // Init
            converged = false;

            // Current (global) point
            double[] currentPoint = new double[] { results[0, 0], results[0, 1] };

            // Compute global cell index of current point
            gridData.LocatePoint(currentPoint, out long GlobalId, out long GlobalIndex, out bool IsInside, out bool OnThisProcess);

            // Compute local node set
            NodeSet nodeSet = ShockFindingExtensions.GetLocalNodeSet(gridData, currentPoint, (int)GlobalIndex);

            // Get local cell index of current point
            int j0Grd = gridData.CellPartitioning.i0;

            jLocal = (int)(GlobalIndex - j0Grd);

            // Evaluate the second derivative
            try {
                if (byFlux)
                {
                    results[0, 3] = SecondDerivativeByFlux(field, jLocal, nodeSet);
                }
                else
                {
                    results[0, 3] = ShockFindingExtensions.SecondDerivative(field, jLocal, nodeSet);
                }
            } catch (NotSupportedException) {
                iterations = 0;
                return;
            }

            // Evaluate the function
            MultidimensionalArray f = MultidimensionalArray.Create(1, 1);

            field.Evaluate(jLocal, 1, nodeSet, f);
            results[0, 2] = f[0, 0];

            // Set initial step size to 0.5 * h_minGlobal
            results[0, 4] = 0.5 * gridData.Cells.h_minGlobal;

            int n = 1;

            while (n < results.Lengths[0])
            {
                // Evaluate the gradient of the current point
                double[] gradient;
                if (byFlux)
                {
                    gradient = NormalizedGradientByFlux(field, jLocal, nodeSet);
                }
                else
                {
                    gradient = ShockFindingExtensions.NormalizedGradient(field, jLocal, nodeSet);
                }

                // Compute new point along curve
                currentPoint[0] = currentPoint[0] + gradient[0] * results[n - 1, 4];
                currentPoint[1] = currentPoint[1] + gradient[1] * results[n - 1, 4];

                // New point has been calculated --> old node set is invalid
                nodeSet = null;

                // Check if new point is still in the same cell or has moved to one of its neighbours
                if (!gridData.Cells.IsInCell(currentPoint, jLocal))
                {
                    // Get indices of cell neighbours
                    gridData.GetCellNeighbours(jLocal, GetCellNeighbours_Mode.ViaVertices, out int[] cellNeighbours, out int[] connectingEntities);

                    double[] newLocalCoord = new double[currentPoint.Length];
                    bool     found         = false;
                    // Find neighbour
                    foreach (int neighbour in cellNeighbours)
                    {
                        if (gridData.Cells.IsInCell(currentPoint, neighbour, newLocalCoord))
                        {
                            // If neighbour has been found, update
                            jLocal  = neighbour + j0Grd;
                            nodeSet = ShockFindingExtensions.GetLocalNodeSet(gridData, currentPoint, jLocal);
                            found   = true;
                            break;
                        }
                    }

                    if (found == false)
                    {
                        iterations = n;
                        return;
                    }
                }
                else
                {
                    // New point is still in the same cell --> update only the coordiantes (local node set)
                    nodeSet = ShockFindingExtensions.GetLocalNodeSet(gridData, currentPoint, jLocal + j0Grd);
                }

                // Update output
                results[n, 0] = currentPoint[0];
                results[n, 1] = currentPoint[1];

                // Evaluate the function
                f.Clear();
                field.Evaluate(jLocal, 1, nodeSet, f);
                results[n, 2] = f[0, 0];

                // Evaluate the second derivative of the new point
                try {
                    if (byFlux)
                    {
                        results[n, 3] = SecondDerivativeByFlux(field, jLocal, nodeSet);
                    }
                    else
                    {
                        results[n, 3] = ShockFindingExtensions.SecondDerivative(field, jLocal, nodeSet);
                    }
                } catch (NotSupportedException) {
                    break;
                }

                // Check if sign of second derivative has changed
                // Halve the step size and change direction
                if (Math.Sign(results[n, 3]) != Math.Sign(results[n - 1, 3]))
                {
                    results[n, 4] = -results[n - 1, 4] / 2;
                }
                else
                {
                    results[n, 4] = results[n - 1, 4];
                }

                n++;

                // Termination criterion
                // Remark: n has already been incremented!
                double[] diff = new double[currentPoint.Length];
                diff[0] = results[n - 1, 0] - results[n - 2, 0];
                diff[1] = results[n - 1, 1] - results[n - 2, 1];
                if (diff.L2Norm() < 1e-12)
                {
                    converged = true;
                    break;
                }
            }

            iterations = n;
            return;
        }
Exemplo n.º 15
0
        /// <summary>
        /// evaluates the mean value over a cell;
        /// of course, the mean value doesn't depend on node set or anything like that,
        /// so no information about that has to be provided.
        /// </summary>
        /// <param name="j0">local index of the first cell to evaluate</param>
        /// <param name="Len">Number of cells to evaluate</param>
        /// <param name="result">
        /// on exit, result of the evaluations are accumulated there;
        /// the original content is scaled by <paramref name="ResultPreScale"/>;
        /// 1st index: cell index minus <paramref name="j0"/>;
        /// </param>
        /// <param name="ResultCellindexOffset">
        /// an offset for the first index of <paramref name="result"/>;
        /// </param>
        /// <param name="ResultPreScale">
        /// see <paramref name="result"/>
        /// </param>
        override public void EvaluateMean(int j0, int Len, MultidimensionalArray result, int ResultCellindexOffset, double ResultPreScale)
        {
            int D = GridDat.SpatialDimension; // spatial dimension

            if (result.Dimension != 1)
            {
                throw new ArgumentOutOfRangeException("dimension of result array must be 1");
            }
            if (Len > result.GetLength(0) + ResultCellindexOffset)
            {
                throw new ArgumentOutOfRangeException("mismatch between Len and 0-th length of result");
            }

            // we assume that the polynomial at index 0 is constant,
            // and that the mean value of all other polynomials is zero
            var Krefs = Basis.GridDat.iGeomCells.RefElements;
            MultidimensionalArray zerothOrderBasisValue = MultidimensionalArray.Create(1);

            double[] bv = new double[Krefs.Length];
            for (int l = 0; l < Krefs.Length; l++)
            {
                zerothOrderBasisValue.Clear();
                Debug.Assert(Basis.Polynomials[l][0].AbsoluteDegree == 0);
                Debug.Assert(Basis.Polynomials[l][0].Coeff.Length == 1);
                Basis.Polynomials[l][0].Evaluate(zerothOrderBasisValue, Krefs[l].Center);

                bv[l] = zerothOrderBasisValue[0];
            }

            MultidimensionalArray scales      = Basis.Data.Scaling;
            MultidimensionalArray nonLinOrtho = null;

            for (int j = 0; j < Len; j++)
            {
                int iKref = Basis.GridDat.iGeomCells.GetRefElementIndex(j + j0);

                double scaling;
                if (this.GridDat.iGeomCells.IsCellAffineLinear(j + j0))
                {
                    scaling = scales[j + j0];
                }
                else
                {
                    if (nonLinOrtho == null)
                    {
                        nonLinOrtho = this.GridDat.ChefBasis.OrthonormalizationTrafo.GetValue_Cell(j0, Len, 0);
                    }

                    scaling = Basis.Data.OrthonormalizationTrafo.GetValue_Cell(j, 1, 0)[0, 0, 0];
                }

                double value = 0.0;
                if (ResultPreScale != 0.0)
                {
                    value = result[j + ResultCellindexOffset] * ResultPreScale;
                }

                value += bv[iKref] * Coordinates[j + j0, 0] * scaling;

                result[j + ResultCellindexOffset] = value;
            }
        }
Exemplo n.º 16
0
        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;
            unsafe
            {
                void RowScale(double *pS, int i, double alpha, int RowCyc)
                {
                    pS += i * RowCyc;
                    for (int nn = 0; nn < n; nn++)
                    {
                        *pS *= alpha;
                        pS++;
                    }
                }

                void ColScale(double *pS, int i, double alpha, int RowCyc)
                {
                    pS += i;
                    for (int nn = 0; nn < n; nn++)
                    {
                        *pS *= alpha;
                        pS += RowCyc;
                    }
                }

                void RowAdd(double *pS, int iSrc, int iDst, double alpha, int RowCyc)
                {
                    double *pDest = pS + iDst * RowCyc;
                    double *pSrc  = pS + iSrc * RowCyc;

                    for (int l = 0; l < n; l++)
                    {
                        *pDest += *pSrc * alpha;
                        pDest++;
                        pSrc++;
                    }
                }

                void ColAdd(double *pS, int iSrc, int iDst, double alpha, int RowCyc)
                {
                    double *pDest = pS + iDst;
                    double *pSrc  = pS + iSrc;

                    for (int l = 0; l < n; l++)
                    {
                        *pDest += *pSrc * alpha;
                        pDest += RowCyc;
                        pSrc  += RowCyc;
                    }
                }

                fixed(double *_pL = L.Storage, _pM = M.Storage)
                {
                    int RowCycL = n > 1 ? (L.Index(1, 0) - L.Index(0, 0)) : 0;
                    int RowCycM = n > 1 ? (M.Index(1, 0) - M.Index(0, 0)) : 0;

                    double *pL = _pL + L.Index(0, 0);
                    double *pM = _pM + M.Index(0, 0);


                    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);
                        RowScale(pM, i, scl, RowCycM);
                        RowScale(pL, i, scl, RowCycL);
                        ColScale(pM, i, scl, RowCycM);

                        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];

                            RowAdd(pM, i, k, -M_ki * diagsign, RowCycM);
                            RowAdd(pL, i, k, -M_ki * diagsign, RowCycL);
                            ColAdd(pM, i, k, -M_ki * diagsign, RowCycM);

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

                        /*
                         * unsafe
                         * {
                         *  fixed (double* B_entries = Lo.Storage)
                         *  {
                         *
                         *      int UPLO = 'L', DIAG = 'N';
                         *      LAPACK.F77_LAPACK.DSYTRF_(ref UPLO, ref DIAG, ref n, B_entries, ref n, out info);
                         *  }
                         * }
                         */
                    }
                }
            }
            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
        }
Exemplo n.º 17
0
        /// <summary>
        /// Partial inversion of a matrix with zero rows and columns; not considered to be performance-critical,
        /// since it is only for treating pathological cases.
        /// </summary>
        static void RankDefInvert(MultidimensionalArray MtxIn, MultidimensionalArray MtxOt)
        {
            if (MtxIn.Dimension != 2)
            {
                throw new ArgumentOutOfRangeException("Expecting an 2D-array, i.e. a matrix.");
            }
            if (MtxOt.Dimension != 2)
            {
                throw new ArgumentOutOfRangeException("Expecting an 2D-array, i.e. a matrix.");
            }
            if (MtxIn.GetLength(0) != MtxOt.GetLength(0))
            {
                throw new ArgumentOutOfRangeException("input and output matrix must have same size");
            }
            if (MtxIn.GetLength(1) != MtxOt.GetLength(1))
            {
                throw new ArgumentOutOfRangeException("input and output matrix must have same size");
            }
            if (MtxIn.GetLength(0) != MtxOt.GetLength(1))
            {
                throw new ArgumentOutOfRangeException("matrix must be quadratic");
            }

            int M = MtxIn.GetLength(0);

            List <int> NonzeroIdx = new List <int>();

            for (int i = 0; i < M; i++)
            {
                double[] row_i = MtxIn.GetRow(i);

                if (row_i.L2NormPow2() == 0.0)
                {
                    double[] col_i = MtxIn.GetColumn(i);

                    if (col_i.L2NormPow2() != 0.0)
                    {
                        throw new ArgumentException("Row is zero, but column is not.");
                    }
                }
                else
                {
                    NonzeroIdx.Add(i);
                }
            }

            if (NonzeroIdx.Count == M)
            {
                throw new ArgumentException("Unable to find zero row/column.");
            }

            int Q = NonzeroIdx.Count;
            MultidimensionalArray TmpIn = MultidimensionalArray.Create(Q, Q);
            MultidimensionalArray TmpOt = MultidimensionalArray.Create(Q, Q);

            for (int i = 0; i < Q; i++)
            {
                for (int j = 0; j < Q; j++)
                {
                    TmpIn[i, j] = MtxIn[NonzeroIdx[i], NonzeroIdx[j]];
                }
            }

            TmpIn.InvertTo(TmpOt);

            MtxOt.Clear();
            for (int i = 0; i < Q; i++)
            {
                for (int j = 0; j < Q; j++)
                {
                    MtxOt[NonzeroIdx[i], NonzeroIdx[j]] = TmpOt[i, j];
                }
            }
        }
Exemplo n.º 18
0
        public void Solve <U, V>(U X, V B)
            where U : IList <double>
            where V : IList <double> //
        {
            int L = B.Count;

            if (X.Count != this.m_mgop.OperatorMatrix.ColPartition.LocalLength)
            {
                throw new ArgumentException("Wrong length of unknowns vector.", "X");
            }
            if (B.Count != this.m_mgop.OperatorMatrix.RowPartitioning.LocalLength)
            {
                throw new ArgumentException("Wrong length of RHS vector.", "B");
            }

            MultidimensionalArray H = MultidimensionalArray.Create(MaxKrylovDim + 1, MaxKrylovDim);

            double[] X0 = X.ToArray();
            double[] R0 = new double[B.Count];

            List <double[]> Vau = new List <double[]>();
            List <double[]> Zed = new List <double[]>();

            int iPrecond = 0; // counter which iterates through preconditioners

            int iIter = 0;

            while (true)
            {
                // init for Arnoldi
                // -----------------

                R0.SetV(B);
                this.m_mgop.OperatorMatrix.SpMV(-1.0, X0, 1.0, R0);

                if (this.IterationCallback != null)
                {
                    this.IterationCallback(iIter, X0.CloneAs(), R0.CloneAs(), this.m_mgop);
                }

                // termination condition
                if (iIter > MaxIter)
                {
                    break;
                }

                double beta = R0.L2NormPow2().MPISum().Sqrt();
                Vau.Add(R0.CloneAs());
                Vau[0].ScaleV(1.0 / beta);

                // inner iteration (Arnoldi)
                // --------------------------

                for (int j = 0; j < MaxKrylovDim; j++)
                {
                    Debug.Assert(Vau.Count == Zed.Count + 1);

                    double[] Zj = new double[L];
                    this.PrecondS[iPrecond].Solve(Zj, Vau[j]);
                    iPrecond++;
                    if (iPrecond >= this.PrecondS.Length)
                    {
                        iPrecond = 0;
                    }
                    iIter++; // we count preconditioner calls as iterations

                    Zed.Add(Zj);

                    double[] W = new double[L];
                    this.m_mgop.OperatorMatrix.SpMV(1.0, Zj, 0.0, W);

                    for (int i = 0; i <= j; i++)
                    {
                        double hij = GenericBlas.InnerProd(W, Vau[i]).MPISum();
                        H[i, j] = hij;
                        W.AccV(-hij, Vau[i]);
                    }

                    double wNorm = W.L2NormPow2().MPISum().Sqrt();
                    H[j + 1, j] = wNorm;
                    W.ScaleV(1.0 / wNorm); // W is now Vau[j + 1] !!

                    Vau.Add(W);

                    Debug.Assert(Vau.Count == Zed.Count + 1);
                }

                // compute minimized-Residual solution over 'Zed'-Vectors
                // -------------------------------------------------------
                double[] alpha;
                {
                    alpha = new double[MaxKrylovDim];
                    //var alpha2 = new double[MaxKrylovDim];


                    Debug.Assert(Vau.Count == H.NoOfRows);
                    Debug.Assert(Zed.Count == H.NoOfCols);

                    // solve small minimization problem
                    double[] minimiRHS = new double[MaxKrylovDim + 1];
                    minimiRHS[0] = beta;
                    H.LeastSquareSolve(alpha, minimiRHS);  // using LAPACK DGELSY
                    //H.CloneAs().LeastSquareSolve(alpha2, minimiRHS.CloneAs());

                    //var Q = H;  //
                    //var Qt = H.Transpose();
                    //var lhs = Qt.GEMM(Q);
                    //var rhs = new double[Qt.NoOfRows];
                    //Qt.gemv(1.0, minimiRHS, 0.0, rhs);
                    //lhs.Solve(alpha, rhs);

                    alpha.ClearEntries();
                    alpha[0] = beta;
                }

                for (int i = 0; i < MaxKrylovDim; i++)
                {
                    X0.AccV(alpha[i], Zed[i]);
                }
                // now, X0 = 'old X0' + sum(Z[i]*alpha[i]),
                // i.e. X0 is the new X for the next iteration


                // restart
                // -------
                Vau.Clear();
                Zed.Clear();
                H.Clear();
            }
        }
Exemplo n.º 19
0
        /// <summary>
        /// performs an integration over cells or edges in the composite rule provided to the constructor;
        /// </summary>
        public virtual void Execute()
        {
            using (var tr = new FuncTrace()) {
                // Init
                // ====

                // timers
                Stopwatch stpwSaveIntRes = new Stopwatch();
                stpwSaveIntRes.Reset();
                Stopwatch stpwQuad = new Stopwatch();
                stpwQuad.Reset();
                Stopwatch stpwEval = new Stopwatch();
                stpwEval.Reset();
                Stopwatch stpwAlloc = new Stopwatch();
                stpwAlloc.Reset();
                Stopwatch stpwNdSet = new Stopwatch();
                stpwNdSet.Reset();

                for (int i = CustomTimers.Length - 1; i >= 0; i--)
                {
                    CustomTimers[i].Reset();
                }

                // check input ...
                IGridData grd = gridData;

                // do quadrature
                // =============
                MultidimensionalArray lastQuadRuleNodes = null;
                int oldBulksize  = -1;
                int oldNoOfNodes = -1;
                int Bulkcnt      = 0;
                foreach (var chunkRulePair in m_compositeRule)
                {
                    Chunk chunk = chunkRulePair.Chunk;
                    m_CurrentRule = chunkRulePair.Rule;

                    //// init node set
                    stpwNdSet.Start();
                    if (!object.ReferenceEquals(m_CurrentRule.Nodes, lastQuadRuleNodes))
                    {
                        QuadNodesChanged(m_CurrentRule.Nodes);
                    }
                    stpwNdSet.Stop();

                    // define bulk size
                    int NoOfNodes = m_CurrentRule.Nodes.GetLength(0);
                    int ItemSize  = m_TotalNoOfIntegralsPerItem * NoOfNodes;
                    if (ItemSize <= 0)
                    {
                        continue;
                    }
                    int cdl = Quadrature_Bulksize.CHUNK_DATA_LIMIT;
                    if (ChunkDataLimitOverride > 0)
                    {
                        cdl = ChunkDataLimitOverride;
                    }
                    int MaxChunkLength = Quadrature_Bulksize.CHUNK_DATA_LIMIT / ItemSize;
                    if (MaxChunkLength < 1)
                    {
                        MaxChunkLength = 1;
                    }

                    //if (OberOasch && Bulkcnt == 0)
                    //    Console.WriteLine("Max Chunk length: " + MaxChunkLength);

                    int j           = chunk.i0;
                    int ChunkLength = MaxChunkLength;
                    int ChunkEnd    = chunk.i0 + chunk.Len;


                    while (j < ChunkEnd)
                    {
                        Bulkcnt++;

                        // limit bulksize
                        if ((j + ChunkLength) > ChunkEnd)
                        {
                            ChunkLength -= (j + ChunkLength - ChunkEnd);
                        }


                        // DEBUG check
#if DEBUG
                        CheckQuadratureChunk(j, ChunkLength, CurrentRuleRefElementIndex);
#endif

                        // reallocate buffers if bulksize was changed
                        stpwAlloc.Start();
                        if (ChunkLength != oldBulksize || m_CurrentRule.NoOfNodes != oldNoOfNodes)
                        {
                            AllocateBuffersInternal(ChunkLength, m_CurrentRule.Nodes);
                            AllocateBuffers(ChunkLength, m_CurrentRule.Nodes);
                            oldBulksize  = ChunkLength;
                            oldNoOfNodes = m_CurrentRule.NoOfNodes;
                        }
                        stpwAlloc.Stop();


                        if (this.m_ExEvaluate == null)
                        {
                            // evaluation of integrand
                            // =======================
                            stpwEval.Start();
                            m_EvalResults.Clear();
                            this.Evaluate(j, ChunkLength, this.CurrentRule, m_EvalResults);
                            stpwEval.Stop();

                            // quadrature
                            // ==========
                            stpwQuad.Start();
                            DoQuadrature(m_CurrentRule, j, ChunkLength);
                            stpwQuad.Stop();
                        }
                        else
                        {
                            Debug.Assert(this.m_Evaluate == null);

                            // evaluation of integrand
                            // =======================
                            stpwEval.Start();
                            this.m_ExEvaluate(j, ChunkLength, this.CurrentRule, m_QuadResults);
                            stpwEval.Stop();
                        }

                        // save results
                        // ============
                        stpwSaveIntRes.Start();
                        SaveIntegrationResults(j, ChunkLength, m_QuadResults);
                        stpwSaveIntRes.Stop();

                        // inc
                        j += ChunkLength;
                    }


                    lastQuadRuleNodes = m_CurrentRule.Nodes;
                }
                m_CurrentRule = null;

                //tr.Info("Quadrature performed in " + Bulkcnt + " chunk(s).");
                //Console.WriteLine("Quadrature performed in " + Bulkcnt + " chunk(s).");

                // finalize
                // ========

                {
                    // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
                    // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
                    //
                    // note that StopWatch.Elapsed.Ticks != StopWatch.ElapsedTicks
                    //
                    // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
                    // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

                    var mcrEval = tr.LogDummyblock(stpwEval.Elapsed.Ticks, "integrand_evaluation");
                    tr.LogDummyblock(stpwQuad.Elapsed.Ticks, "quadrature");
                    tr.LogDummyblock(stpwSaveIntRes.Elapsed.Ticks, "saving_results");
                    tr.LogDummyblock(stpwNdSet.Elapsed.Ticks, "node_set_management");
                    tr.LogDummyblock(stpwAlloc.Elapsed.Ticks, "buffer_allocation");

                    Debug.Assert(m_CustomTimers.Length == m_CustomTimers_Names.Length);
                    Debug.Assert(m_CustomTimers.Length == m_CustomTimers_RootPointer.Length);
                    MethodCallRecord[] mcrS = new MethodCallRecord[CustomTimers.Length];

                    for (int iTimer = 0; iTimer < mcrS.Length; iTimer++)
                    {
                        int pt = m_CustomTimers_RootPointer[iTimer];
                        MethodCallRecord OwnerMcr = pt >= 0 ? mcrS[pt] : mcrEval;
                        mcrS[iTimer] = OwnerMcr.AddSubCall(CustomTimers_Names[iTimer], m_CustomTimers[iTimer].Elapsed.Ticks);
                    }
                }
            }
        }
Exemplo n.º 20
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="CellPairs">
        /// 1st index: list of cells <br/>
        /// 2nd index: in {0, 1}
        /// </param>
        /// <param name="M">
        /// 1st index: corresponds with 1st index of <paramref name="CellPairs"/><br/>
        /// 2nd index: matrix row index <br/>
        /// 3rd index: matrix column index
        /// </param>
        /// <param name="Minv">the inverse of <paramref name="M"/></param>
        /// <remarks>
        /// Let \f$ K_j \f$ and \f$ K_i \f$ be two different cells with a linear-affine
        /// transformation to the reference element.
        /// Here, \f$ j \f$=<paramref name="CellPairs"/>[a,0] and \f$ i \f$=<paramref name="CellPairs"/>[a,1].
        /// The DG-basis in these cells can uniquely be represented as
        /// \f[
        /// \phi_{j n} (\vec{x}) = p_n (\vec{x}) \vec{1}_{K_j} (\vec{x})
        /// \textrm{ and }
        /// \phi_{i m} (\vec{x}) = q_m (\vec{x}) \vec{1}_{K_i} (\vec{x})
        /// \f]
        /// where \f$ \vec{1}_X \f$ denotes the characteristic function for set \f$ X \f$
        /// and \f$ p_n\f$  and \f$ p_m\f$  are polynomials.
        /// Then, for the output \f$ M \f$ =<paramref name="M"/>[a,-,-] fulfills
        /// \f[
        /// \phi_{j n} + \sum_{m} M_{m n} \phi_{i m}
        /// =
        /// p_n \vec{1}_{K_j \cup K_i}
        /// \f]
        /// </remarks>
        public void GetExtrapolationMatrices(int[,] CellPairs, MultidimensionalArray M, MultidimensionalArray Minv = null)
        {
            var m_Context = this.GridDat;
            int N         = this.Length;
            int Esub      = CellPairs.GetLength(0);
            int JE        = this.GridDat.iLogicalCells.Count;
            int J         = this.GridDat.iLogicalCells.NoOfLocalUpdatedCells;

            if (CellPairs.GetLength(1) != 2)
            {
                throw new ArgumentOutOfRangeException("second dimension is expected to be 2!");
            }
            if (M.Dimension != 3)
            {
                throw new ArgumentException();
            }
            if (M.GetLength(0) != Esub)
            {
                throw new ArgumentException();
            }
            if (M.GetLength(1) != N || M.GetLength(2) != N)
            {
                throw new ArgumentException();
            }
            if (Minv != null)
            {
                if (Minv.GetLength(0) != Esub)
                {
                    throw new ArgumentException();
                }
                if (Minv.GetLength(1) != N || Minv.GetLength(2) != N)
                {
                    throw new ArgumentException();
                }
            }

            MultidimensionalArray NodesGlobal = new MultidimensionalArray(3);
            MultidimensionalArray Minv_tmp    = MultidimensionalArray.Create(N, N);
            MultidimensionalArray M_tmp       = MultidimensionalArray.Create(N, N);


            for (int esub = 0; esub < Esub; esub++)   // loop over the cell pairs...

            {
                int jCell0 = CellPairs[esub, 0];
                int jCell1 = CellPairs[esub, 1];
                if (jCell0 < 0 || jCell0 >= JE)
                {
                    throw new ArgumentOutOfRangeException("Cell index out of range.");
                }
                if (jCell1 < 0 || jCell1 >= JE)
                {
                    throw new ArgumentOutOfRangeException("Cell index out of range.");
                }

                bool swap;
                if (jCell0 >= J)
                {
                    //if(true) {
                    swap = true;
                    int a = jCell0;
                    jCell0 = jCell1;
                    jCell1 = a;
                }
                else
                {
                    swap = false;
                }


                if (!m_Context.iGeomCells.IsCellAffineLinear(jCell0))
                {
                    throw new NotSupportedException("Currently not supported for curved cells.");
                }
                if (!m_Context.iGeomCells.IsCellAffineLinear(jCell1))
                {
                    throw new NotSupportedException("Currently not supported for curved cells.");
                }

                Debug.Assert(jCell0 < J);

                var cellMask = new CellMask(m_Context, new[] { new Chunk()
                                                               {
                                                                   i0 = jCell0, Len = 1
                                                               } }, MaskType.Geometrical);

                // we project the basis function from 'jCell1' onto 'jCell0'

                CellQuadrature.GetQuadrature(new int[2] {
                    N, N
                }, m_Context,
                                             (new CellQuadratureScheme(true, cellMask)).Compile(m_Context, this.Degree * 2), // integrate over target cell
                                             delegate(int i0, int Length, QuadRule QR, MultidimensionalArray _EvalResult) {
                    NodeSet nodes_Cell0 = QR.Nodes;
                    Debug.Assert(Length == 1);

                    NodesGlobal.Allocate(1, nodes_Cell0.GetLength(0), nodes_Cell0.GetLength(1));
                    m_Context.TransformLocal2Global(nodes_Cell0, jCell0, 1, NodesGlobal, 0);
                    var nodes_Cell1 = new NodeSet(GridDat.iGeomCells.GetRefElement(jCell1), nodes_Cell0.GetLength(0), nodes_Cell0.GetLength(1));
                    m_Context.TransformGlobal2Local(NodesGlobal.ExtractSubArrayShallow(0, -1, -1), nodes_Cell1, jCell1, null);
                    nodes_Cell1.LockForever();


                    var phi_0 = this.CellEval(nodes_Cell0, jCell0, 1).ExtractSubArrayShallow(0, -1, -1);
                    var phi_1 = this.CellEval(nodes_Cell1, jCell1, 1).ExtractSubArrayShallow(0, -1, -1);

                    var EvalResult = _EvalResult.ExtractSubArrayShallow(0, -1, -1, -1);

                    EvalResult.Multiply(1.0, phi_1, phi_0, 0.0, "kmn", "kn", "km");
                },
                                             /*_SaveIntegrationResults:*/ delegate(int i0, int Length, MultidimensionalArray ResultsOfIntegration) {
                    Debug.Assert(Length == 1);

                    var res = ResultsOfIntegration.ExtractSubArrayShallow(0, -1, -1);
                    Minv_tmp.Clear();
                    Minv_tmp.Acc(1.0, res);
                }).Execute();

                // compute the inverse
                Minv_tmp.InvertTo(M_tmp);

                // store
                if (!swap)
                {
                    M.ExtractSubArrayShallow(esub, -1, -1).AccMatrix(1.0, M_tmp);
                    if (Minv != null)
                    {
                        Minv.ExtractSubArrayShallow(esub, -1, -1).AccMatrix(1.0, Minv_tmp);
                    }
                }
                else
                {
                    M.ExtractSubArrayShallow(esub, -1, -1).AccMatrix(1.0, Minv_tmp);
                    if (Minv != null)
                    {
                        Minv.ExtractSubArrayShallow(esub, -1, -1).AccMatrix(1.0, M_tmp);
                    }
                }
            }
        }
Exemplo n.º 21
0
        /// <summary>
        /// Injects a DG field from a coarser grid to a fine grid.
        /// </summary>
        public static void InjectDGField(int[] CellIdxFine2Coarse, ConventionalDGField onFineGrid, ConventionalDGField onCoarseGrid, CellMask subGrd = null)
        {
            if (subGrd == null)
            {
                subGrd = CellMask.GetFullMask(onFineGrid.GridDat);
            }
            if (onFineGrid.Basis.GridDat.iGeomCells.RefElements.Length != 1)
            {
                throw new NotImplementedException("todo");
            }
            var QR = onFineGrid.Basis.GridDat.iGeomCells.RefElements[0].GetQuadratureRule(onFineGrid.Basis.Degree * 2);

            if (!object.ReferenceEquals(subGrd.GridData, onFineGrid.GridDat))
            {
                throw new ArgumentException();
            }

            int N = onFineGrid.Basis.Length;
            int K = QR.NoOfNodes;
            int D = onFineGrid.Basis.GridDat.SpatialDimension;

            NodeSet xi = QR.Nodes;                                           // quadrature nodes in local coordsys. of cell to extrapolate TO
            //MultidimensionalArray eta = MultidimensionalArray.Create(K, D);  // quadrature nodes in local coordsys. of cell to extrapolate FROM
            MultidimensionalArray tmp = MultidimensionalArray.Create(K, D);  // quadrature nodes in global coordinates
            MultidimensionalArray a   = MultidimensionalArray.Create(K, N);

            for (int n = 0; n < N; n++)
            {
                onFineGrid.Basis.Polynomials[0][n].Evaluate(a.ExtractSubArrayShallow(-1, n), xi);
                for (int k = 0; k < K; k++)
                {
                    a[k, n] *= QR.Weights[k];
                }
            }
            MultidimensionalArray v = MultidimensionalArray.Create(K, N);

            MultidimensionalArray[] v_ = new MultidimensionalArray[N];
            for (int n = 0; n < N; n++)
            {
                v_[n] = v.ExtractSubArrayShallow(-1, n);
            }

            double[,] eps = new double[N, N];
            double[] u2 = new double[N];
            double[] u1 = new double[N];

            //double[] ooScales = m_context.GridDat.OneOverSqrt_AbsDetTransformation;

            IGridData ctxFine = onFineGrid.Basis.GridDat;
            IGridData ctxCors = onCoarseGrid.Basis.GridDat;

            var ooScalesFine = ctxFine.ChefBasis.Scaling;
            var ooScalesCors = ctxCors.ChefBasis.Scaling;


            foreach (var chunk in subGrd)
            {
                for (int j = chunk.i0; j < chunk.JE; j++)
                {
                    int _1 = CellIdxFine2Coarse[j]; // cell to extrapolate FROM (on coarse grid)
                    int _2 = j;                     // cell to extrapolate TO   (on fine grid)

                    int iKref_1 = ctxCors.iGeomCells.GetRefElementIndex(_1);
                    int iKref_2 = ctxFine.iGeomCells.GetRefElementIndex(_2);

                    if (!ctxCors.iGeomCells.IsCellAffineLinear(_1))
                    {
                        throw new NotImplementedException("todo");
                    }
                    if (!ctxFine.iGeomCells.IsCellAffineLinear(_2))
                    {
                        throw new NotImplementedException("todo");
                    }


                    // get DG coordinates
                    onCoarseGrid.Coordinates.GetRow(_1, u1);


                    // transform quad. nodes from cell 2 (extrapolate to) to cell 1 (extrapolate FROM)
                    ctxFine.TransformLocal2Global(xi, tmp, _2);
                    NodeSet eta = new NodeSet(ctxFine.iGeomCells.GetRefElement(_2), K, D);
                    ctxCors.TransformGlobal2Local(tmp, eta, _1, null);
                    eta.LockForever();

                    // evaluate Polynomials of cell 1 (fine)
                    v.Clear();
                    for (int n = 0; n < N; n++)
                    {
                        if (n < onCoarseGrid.Basis.Length)
                        {
                            onCoarseGrid.Basis.Polynomials[iKref_1][n].Evaluate(v_[n], eta);
                        }
                        else
                        {
                            v_[n].Clear();
                        }
                    }

                    // perform quadrature
                    double scale = ooScalesCors[_1] / ooScalesFine[_2];
                    for (int m = 0; m < N; m++)
                    {
                        for (int n = 0; n < N; n++)
                        {
                            double eps_m_n = 0;
                            for (int k = 0; k < K; k++)
                            {
                                eps_m_n += a[k, m] * v[k, n];
                            }
                            eps[m, n] = eps_m_n * scale;
                        }
                    }

                    // new DG coordinates
                    for (int m = 0; m < N; m++)
                    {
                        double u2_m = 0;
                        for (int n = 0; n < N; n++)
                        {
                            u2_m += eps[m, n] * u1[n];
                        }
                        u2[m] = u2_m;
                    }

                    // set DG coordinates
                    onFineGrid.Coordinates.SetRow(_2, u2);
                }
            }
        }
Exemplo n.º 22
0
        /// <summary>
        /// %
        /// </summary>
        /// <param name="output"></param>
        /// <param name="input">input DG field; unchanged on </param>
        public void Perform(SinglePhaseField output, SinglePhaseField input)
        {
            if (!output.Basis.Equals(this.m_bOutput))
            {
                throw new ArgumentException("output basis mismatch");
            }
            if (!input.Basis.Equals(this.m_bInput))
            {
                throw new ArgumentException("output basis mismatch");
            }

            var GridDat = this.m_bOutput.GridDat;
            int N       = m_bOutput.Length;
            int Nin     = m_bInput.Length;
            int J       = GridDat.iLogicalCells.NoOfLocalUpdatedCells;

            diagnosis = new double[N * J];

            double[] RHS = new double[N];
            double[] f2  = new double[N];
            double[] g1  = new double[N];
            MultidimensionalArray Trf = MultidimensionalArray.Create(N, N);

            input.MPIExchange();


            for (int jCell = 0; jCell < J; jCell++)
            {
                Debug.Assert((this.AggregateBasisTrafo[jCell] != null) == (this.Stencils[jCell] != null));

                //FullMatrix invMassM = this.InvMassMatrix[jCell];
                MultidimensionalArray ExPolMtx = this.AggregateBasisTrafo[jCell];

                if (ExPolMtx != null)
                {
                    int[] Stencil_jCells = this.Stencils[jCell];
                    int   K = Stencil_jCells.Length;
                    Debug.Assert(Stencil_jCells[0] == jCell);

                    var coordIn = input.Coordinates;
                    //for(int n = Math.Min(Nin, N) - 1; n >= 0; n--) {
                    //    RHS[n] = coordIn[jCell, n];
                    //}
                    RHS.ClearEntries();
                    g1.ClearEntries();

                    var oldCoords = input.Coordinates.GetRow(jCell);

                    for (int k = 0; k < K; k++)
                    {
                        int jNeigh = Stencil_jCells[k];
                        for (int n = Math.Min(input.Basis.Length, N) - 1; n >= 0; n--)
                        {
                            f2[n] = input.Coordinates[jNeigh, n];
                        }
                        if (Nlim != null && Nlim[jNeigh] > 0)
                        {
                            for (int n = Nlim[jNeigh]; n < RHS.Length; n++)
                            {
                                f2[n] = 0;
                            }
                        }

                        for (int l = 0; l < N; l++)
                        {
                            double acc = 0;
                            for (int i = 0; i < N; i++)
                            {
                                acc += ExPolMtx[k, i, l] * f2[i];
                            }
                            RHS[l] += acc;
                        }
                    }

                    if (Nlim != null && Nlim[jCell] > 0)
                    {
                        for (int n = Nlim[jCell]; n < RHS.Length; n++)
                        {
                            RHS[n] = 0;
                        }
                    }

                    for (int l = 0; l < N; l++)
                    {
                        diagnosis[jCell * N + l] = RHS[l];
                    }

                    //invMassM.gemv(1.0, RHS, 0.0, g1);

                    Trf.Clear();
                    Trf.Acc(1.0, ExPolMtx.ExtractSubArrayShallow(0, -1, -1));

                    //Trf.Solve(FulCoords, AggCoords);
                    Trf.gemv(1.0, RHS, 0.0, g1);


                    if (Nlim != null && Nlim[jCell] > 0)
                    {
                        for (int n = Nlim[jCell]; n < RHS.Length; n++)
                        {
                            g1[n] = 0;
                        }
                    }

                    if (Nlim == null)
                    {
                        output.Coordinates.SetRow(jCell, g1);
                    }
                    else
                    {
                        if ((Nlim[jCell] <= 0 && this.notchangeunlim))
                        {
                            output.Coordinates.SetRow(jCell, oldCoords);
                        }
                        else
                        {
                            output.Coordinates.SetRow(jCell, g1);
                        }
                    }
                }
            }

            output.MPIExchange();
        }
Exemplo n.º 23
0
        /// <summary>
        /// Computation of mean curvature according to Bonnet's formula.
        /// </summary>
        /// <param name="scale"></param>
        /// <param name="Output">
        /// output.
        /// </param>
        /// <param name="quadScheme"></param>
        /// <param name="UseCenDiffUpTo">
        /// Either 0, 1, or 2:
        /// If 0, all derivatives are computed locally (broken derivative);
        /// if 1, the first order derivatives are computed by central
        /// differences, while the second order ones are computed locally,
        /// based on the first order ones;
        /// if 2, all derivatives are computed by central differences.
        /// </param>
        /// <param name="_1stDerivDegree">
        /// Relative DG polynomial degree for the 1st order derivatives, i.e.
        /// degree is <paramref name="_1stDerivDegree"/>+<em>p</em>, where
        /// <em>p</em> is the degree of this field.
        /// Only active if <paramref name="UseCenDiffUpTo"/> is greater than 0.
        /// </param>
        /// <param name="_2ndDerivDegree">
        /// Relative DG polynomial degree for the 2nd order derivatives, i.e.
        /// degree is <paramref name="_2ndDerivDegree"/>+<em>p</em>, where
        /// <em>p</em> is the degree of this field. Only active if
        /// <paramref name="UseCenDiffUpTo"/> is greater than 1.
        /// </param>
        /// <remarks>
        /// using central differences causes memory allocation: <em>D</em>
        /// fields for <paramref name="UseCenDiffUpTo"/>=1, and
        /// <em>D</em>*(<em>D</em>+1) for <paramref name="UseCenDiffUpTo"/>=2,
        /// where <em>D</em> notates the spatial dimension.
        /// </remarks>
        public void ProjectTotalcurvature2(
            double scale,
            SinglePhaseField Output,
            int UseCenDiffUpTo,
            int _1stDerivDegree             = 0,
            int _2ndDerivDegree             = 0,
            CellQuadratureScheme quadScheme = null)
        {
            using (new FuncTrace()) {
                if (UseCenDiffUpTo < 0 || UseCenDiffUpTo > 2)
                {
                    throw new ArgumentOutOfRangeException();
                }

                //int M = Output.Basis.Length;
                //int N = this.Basis.Length;
                int D = this.GridDat.SpatialDimension;
                //var NSC = m_context.NSC;

                SubGrid sgrd = null;
                SpatialOperator.SubGridBoundaryModes bndMode = SpatialOperator.SubGridBoundaryModes.InnerEdge;
                if (UseCenDiffUpTo >= 1 && quadScheme != null && quadScheme.Domain != null)
                {
                    sgrd    = new SubGrid(quadScheme.Domain);
                    bndMode = SpatialOperator.SubGridBoundaryModes.OpenBoundary;
                }

                // compute 1st order derivatives by central differences, if desired
                // ================================================================
                Basis B2 = new Basis(this.GridDat, this.Basis.Degree + _1stDerivDegree);

                SinglePhaseField[] GradientVector = null;
                if (UseCenDiffUpTo >= 1)
                {
                    GradientVector = new SinglePhaseField[D];
                    for (int d = 0; d < D; d++)
                    {
                        GradientVector[d] = new SinglePhaseField(B2);
                        GradientVector[d].DerivativeByFlux(1.0, this, d, sgrd, bndMode);
                    }
                }

                // compute 2nd order derivatives by central differences, if desired
                // ===============================================================
                Basis B3 = new Basis(this.GridDat, this.Basis.Degree + _2ndDerivDegree);

                SinglePhaseField[,] HessianTensor = null;
                if (UseCenDiffUpTo >= 2)
                {
                    HessianTensor = new SinglePhaseField[D, D];
                    for (int d1 = 0; d1 < D; d1++)
                    {
                        for (int d2 = 0; d2 < D; d2++)
                        {
                            HessianTensor[d1, d2] = new SinglePhaseField(B3);
                            HessianTensor[d1, d2].DerivativeByFlux(1.0, GradientVector[d1], d2, sgrd, bndMode);
                        }
                    }
                }

                // compute and project
                // ===================

                // buffers:
                MultidimensionalArray Phi     = new MultidimensionalArray(2);
                MultidimensionalArray GradPhi = new MultidimensionalArray(3);
                MultidimensionalArray HessPhi = new MultidimensionalArray(4);

                MultidimensionalArray ooNormGrad = new MultidimensionalArray(2);
                MultidimensionalArray Laplace    = new MultidimensionalArray(2);
                MultidimensionalArray Q          = new MultidimensionalArray(3);

                // evaluate/project:
                //double Erracc = 0;
                Output.ProjectField(scale,
                                    (ScalarFunctionEx) delegate(int j0, int Len, NodeSet NodeSet, MultidimensionalArray result) { // ScalarFunction2
                    Debug.Assert(result.Dimension == 2);
                    Debug.Assert(Len == result.GetLength(0));
                    int K = result.GetLength(1); // number of nodes


                    // alloc buffers
                    // -------------

                    if (Phi.GetLength(0) != Len || Phi.GetLength(1) != K)
                    {
                        Phi.Allocate(Len, K);
                        GradPhi.Allocate(Len, K, D);
                        HessPhi.Allocate(Len, K, D, D);
                        ooNormGrad.Allocate(Len, K);
                        Laplace.Allocate(Len, K);
                        Q.Allocate(Len, K, D);
                    }
                    else
                    {
                        Phi.Clear();
                        GradPhi.Clear();
                        HessPhi.Clear();
                        ooNormGrad.Clear();
                        Laplace.Clear();
                        Q.Clear();
                    }

                    // evaluate Gradient and Hessian
                    // -----------------------------

                    if (UseCenDiffUpTo >= 1)
                    {
                        for (int d = 0; d < D; d++)
                        {
                            GradientVector[d].Evaluate(j0, Len, NodeSet, GradPhi.ExtractSubArrayShallow(-1, -1, d));
                        }
                    }
                    else
                    {
                        this.EvaluateGradient(j0, Len, NodeSet, GradPhi);
                    }

                    if (UseCenDiffUpTo == 2)
                    {
                        for (int d1 = 0; d1 < D; d1++)
                        {
                            for (int d2 = 0; d2 < D; d2++)
                            {
                                HessianTensor[d1, d2].Evaluate(j0, Len, NodeSet, HessPhi.ExtractSubArrayShallow(-1, -1, d1, d2));
                            }
                        }
                    }
                    else if (UseCenDiffUpTo == 1)
                    {
                        for (int d = 0; d < D; d++)
                        {
                            var GradientVector_d = GradientVector[d];
                            GradientVector_d.EvaluateGradient(j0, Len, NodeSet, HessPhi.ExtractSubArrayShallow(-1, -1, d, -1), 0, 0.0);
                        }
                    }
                    else if (UseCenDiffUpTo == 0)
                    {
                        this.EvaluateHessian(j0, Len, NodeSet, HessPhi);
                    }
                    else
                    {
                        Debug.Assert(false);
                    }

                    // compute the monstrous formula
                    // -----------------------------

                    // norm of Gradient:
                    for (int d = 0; d < D; d++)
                    {
                        var GradPhi_d = GradPhi.ExtractSubArrayShallow(-1, -1, d);
                        ooNormGrad.Multiply(1.0, GradPhi_d, GradPhi_d, 1.0, "ik", "ik", "ik");
                    }
                    ooNormGrad.ApplyAll(x => 1.0 / Math.Sqrt(x));

                    // laplacian of phi:
                    for (int d = 0; d < D; d++)
                    {
                        var HessPhi_d_d = HessPhi.ExtractSubArrayShallow(-1, -1, d, d);
                        Laplace.Acc(1.0, HessPhi_d_d);
                    }

                    // result = Laplacian(phi)/|Grad phi|
                    result.Multiply(1.0, Laplace, ooNormGrad, 0.0, "ik", "ik", "ik");


                    // result = Grad(1/|Grad(phi)|)
                    for (int d1 = 0; d1 < D; d1++)
                    {
                        var Qd = Q.ExtractSubArrayShallow(-1, -1, d1);

                        for (int d2 = 0; d2 < D; d2++)
                        {
                            var Grad_d2    = GradPhi.ExtractSubArrayShallow(-1, -1, d2);
                            var Hess_d2_d1 = HessPhi.ExtractSubArrayShallow(-1, -1, d2, d1);

                            Qd.Multiply(-1.0, Grad_d2, Hess_d2_d1, 1.0, "ik", "ik", "ik");
                        }
                    }

                    ooNormGrad.ApplyAll(x => x * x * x);

                    result.Multiply(1.0, GradPhi, Q, ooNormGrad, 1.0, "ik", "ikd", "ikd", "ik");

                    //for (int i = 0; i < Len; i++) {
                    //    for (int k = 0; k < K; k++) {
                    //        double acc = 0;
                    //        for (int d = 0; d < D; d++) {
                    //            acc += GradPhi[i,k,d]*Q[i,k,d]*ooNormGrad[i,k];
                    //        }

                    //        Erracc += (acc - result[i,k]).Abs();
                    //    }
                    //}
                },
                                    quadScheme.SaveCompile(this.GridDat, (Output.Basis.Degree + this.m_Basis.Degree * (this.m_Basis.Degree - 1) * D) * 2)
                                    );
            }
        }
Exemplo n.º 24
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="velocity"></param>
        /// <returns></returns>
        public override double[] ComputeChangerate(double dt, ConventionalDGField[] velocity, double[] current_FLSprop)
        {
            setMaterialInterfacePoints(current_FLSprop);

            GridData        grdat = (GridData)(velocity[0].GridDat);
            FieldEvaluation fEval = new FieldEvaluation(grdat);

            // Movement of the material interface points
            MultidimensionalArray VelocityAtSamplePointsXY = MultidimensionalArray.Create(current_interfaceP.Lengths);

            int outP = fEval.Evaluate(1, velocity, current_interfaceP, 0, VelocityAtSamplePointsXY);

            if (outP != 0)
            {
                throw new Exception("points outside the grid for fieldevaluation");
            }

            int numIp = current_interfaceP.Lengths[0];


            // change rate for the material points is the velocity at the points
            if (FourierEvolve == Fourier_Evolution.MaterialPoints)
            {
                double[] velAtP = new double[2 * numIp];
                for (int sp = 0; sp < numIp; sp++)
                {
                    velAtP[sp * 2]       = VelocityAtSamplePointsXY[sp, 0];
                    velAtP[(sp * 2) + 1] = VelocityAtSamplePointsXY[sp, 1];
                }
                return(velAtP);
            }

            // compute an infinitesimal change of sample points at the Fourier points/ change of Fourier modes
            MultidimensionalArray interfaceP_evo = current_interfaceP.CloneAs();
            double dt_infin = dt * 1e-3;

            interfaceP_evo.Acc(dt_infin, VelocityAtSamplePointsXY);

            // Movement of the center point
            MultidimensionalArray center_evo       = center.CloneAs();
            MultidimensionalArray VelocityAtCenter = center.CloneAs();

            switch (CenterMove)
            {
            case CenterMovement.None: {
                VelocityAtCenter.Clear();
                break;
            }

            case CenterMovement.Reconstructed: {
                center_evo = GetGeometricCenter(interfaceP_evo);
                //Console.WriteLine("center_evo = ({0}, {1}) / center = ({2}, {3})", center_evo[0, 0], center_evo[0, 1], center[0, 0], center[0, 1]);
                MultidimensionalArray center_change = center_evo.CloneAs();
                center_change.Acc(-1.0, center);
                center_change.Scale(1.0 / dt_infin);
                VelocityAtCenter[0, 0] = center_change[0, 0];
                VelocityAtCenter[0, 1] = center_change[0, 1];
                break;
            }

            case CenterMovement.VelocityAtCenter: {
                outP = fEval.Evaluate(1, velocity, center, 0, VelocityAtCenter);
                if (outP != 0)
                {
                    throw new Exception("center point outside the grid for fieldevaluation");
                }
                center_evo.Acc(dt_infin, VelocityAtCenter);
                break;
            }
            }
            //Console.WriteLine("Velocity at Center point = ({0}, {1})", VelocityAtCenter[0, 0], VelocityAtCenter[0, 1]);

            // transform to polar coordiantes
            MultidimensionalArray interP_evo_polar = interfaceP_polar.CloneAs();

            for (int sp = 0; sp < numIp; sp++)
            {
                double x_c = interfaceP_evo[sp, 0] - center_evo[0, 0];
                double y_c = interfaceP_evo[sp, 1] - center_evo[0, 1];

                double theta = Math.Atan2(y_c, x_c);
                if (theta < 0)
                {
                    theta = Math.PI * 2 + theta;
                }
                ;
                interP_evo_polar[sp, 0] = theta;
                interP_evo_polar[sp, 1] = Math.Sqrt(x_c.Pow2() + y_c.Pow2());
            }

            RearrangeOntoPeriodicDomain(interP_evo_polar);
            double[] samplP_change = current_samplP.CloneAs();
            InterpolateOntoFourierPoints(interP_evo_polar, samplP_change);

            if (FourierEvolve == Fourier_Evolution.FourierPoints)
            {
                samplP_change.AccV(-1.0, current_samplP);
                samplP_change.ScaleV(1.0 / dt_infin);
                double[] FPchange = new double[numFp + 2];
                FPchange[0] = VelocityAtCenter[0, 0];
                FPchange[1] = VelocityAtCenter[0, 1];
                for (int p = 0; p < numFp; p++)
                {
                    FPchange[p + 2] = samplP_change[p];
                }
                return(FPchange);
            }
            else
            if (FourierEvolve == Fourier_Evolution.FourierModes)
            {
                Complex[] samplP_complex = new Complex[numFp];
                for (int sp = 0; sp < numFp; sp++)
                {
                    samplP_complex[sp] = (Complex)samplP_change[sp];
                }
                //Complex[] DFTchange = DFT.NaiveForward(samplP_complex, FourierOptions.Matlab);
                Complex[] DFTchange = samplP_complex; samplP_complex = null;
                Fourier.Forward(DFTchange, FourierOptions.Matlab);
                double[] DFTchange_double = new double[2 * numFp + 2];
                DFTchange_double[0] = VelocityAtCenter[0, 0];
                DFTchange_double[1] = VelocityAtCenter[0, 1];
                for (int sp = 0; sp < numFp; sp++)
                {
                    DFTchange_double[2 + (sp * 2)]     = (DFTchange[sp].Real - DFT_coeff[sp].Real) / dt_infin;
                    DFTchange_double[2 + (sp * 2) + 1] = (DFTchange[sp].Imaginary - DFT_coeff[sp].Imaginary) / dt_infin;
                }
                return(DFTchange_double);
            }
            else
            {
                throw new ArgumentException();
            }
        }
Exemplo n.º 25
0
        public static ScalarFunctionEx GetEnergyJumpFunc(LevelSetTracker LsTrk, VectorField <XDGField> Velocity, XDGField Pressure, double muA, double muB, bool squared)
        {
            var UA = Velocity.Select(u => u.GetSpeciesShadowField("A")).ToArray();
            var UB = Velocity.Select(u => u.GetSpeciesShadowField("B")).ToArray();

            ConventionalDGField pA = null, pB = null;
            bool UsePressure = Pressure != null;

            if (UsePressure)
            {
                pA = Pressure.GetSpeciesShadowField("A");
                pB = Pressure.GetSpeciesShadowField("B");
            }

            int D = LsTrk.GridDat.SpatialDimension;

            ScalarFunctionEx EnergyJumpFunc = delegate(int j0, int Len, NodeSet Ns, MultidimensionalArray result) {
                int K = result.GetLength(1); // No nof Nodes
                MultidimensionalArray UA_res     = MultidimensionalArray.Create(Len, K, D);
                MultidimensionalArray UB_res     = MultidimensionalArray.Create(Len, K, D);
                MultidimensionalArray GradUA_res = MultidimensionalArray.Create(Len, K, D, D);
                MultidimensionalArray GradUB_res = MultidimensionalArray.Create(Len, K, D, D);
                MultidimensionalArray pA_res     = MultidimensionalArray.Create(Len, K);
                MultidimensionalArray pB_res     = MultidimensionalArray.Create(Len, K);

                for (int i = 0; i < D; i++)
                {
                    UA[i].Evaluate(j0, Len, Ns, UA_res.ExtractSubArrayShallow(-1, -1, i));
                    UB[i].Evaluate(j0, Len, Ns, UB_res.ExtractSubArrayShallow(-1, -1, i));

                    UA[i].EvaluateGradient(j0, Len, Ns, GradUA_res.ExtractSubArrayShallow(-1, -1, i, -1));
                    UB[i].EvaluateGradient(j0, Len, Ns, GradUB_res.ExtractSubArrayShallow(-1, -1, i, -1));
                }
                if (UsePressure)
                {
                    pA.Evaluate(j0, Len, Ns, pA_res);
                    pB.Evaluate(j0, Len, Ns, pB_res);
                }
                else
                {
                    pA_res.Clear();
                    pB_res.Clear();
                }

                var Normals = LsTrk.DataHistories[0].Current.GetLevelSetNormals(Ns, j0, Len);

                for (int j = 0; j < Len; j++)
                {
                    for (int k = 0; k < K; k++)
                    {
                        double acc = 0.0;

                        for (int d = 0; d < D; d++)
                        {
                            // pressure
                            if (UsePressure)
                            {
                                acc += (pB_res[j, k] * UB_res[j, k, d] - pA_res[j, k] * UA_res[j, k, d]) * Normals[j, k, d];
                            }

                            // Nabla U + (Nabla U) ^T
                            for (int dd = 0; dd < D; dd++)
                            {
                                acc -= (muB * GradUB_res[j, k, d, dd] * UB_res[j, k, dd] - muA * GradUA_res[j, k, d, dd] * UA_res[j, k, dd]) * Normals[j, k, d];
                                acc -= (muB * GradUB_res[j, k, dd, d] * UB_res[j, k, dd] - muA * GradUA_res[j, k, dd, d] * UA_res[j, k, dd]) * Normals[j, k, d];     // Transposed Term
                            }
                        }
                        if (squared)
                        {
                            result[j, k] = acc.Pow2();
                        }
                        else
                        {
                            result[j, k] = acc;
                        }
                    }
                }
            };

            return(EnergyJumpFunc);
        }
Exemplo n.º 26
0
            protected override void ComputeValues(NodeSet NS, int j0, int Len, MultidimensionalArray output)
            {
                Debug.Assert(CheckAll(j0, Len), "basis length must be equal for all cells from j0 to j0+Len");

                int l0  = m_Owner.GetLength(j0);
                var trk = m_Owner.Tracker;

                // evaluation of un-cut polynomials
                // ================================
                var BasisValues = NonXEval(NS, j0, Len);


                // evaluation of XDG
                // =================

                if (l0 == m_Owner.NonX_Basis.Length)
                {
                    // uncut region -> evaluation is equal to uncut basis
                    // ++++++++++++++++++++++++++++++++++++++++++++++++++

                    output.Set(BasisValues);
                }
                else
                {
                    // modulated basis polynomials
                    // +++++++++++++++++++++++++++

                    int NoOfLevSets = trk.LevelSets.Count;
                    int M           = output.GetLength(1); // number of nodes
                    output.Clear();

                    ReducedRegionCode rrc;
                    int NoOfSpecies = trk.Regions.GetNoOfSpecies(j0, out rrc);
                    int Nsep        = m_Owner.DOFperSpeciesPerCell;



                    for (int j = 0; j < Len; j++)   // loop over cells


                    {
                        int jCell = j + j0;

                        ushort RegionCode = trk.Regions.m_LevSetRegions[jCell];


                        int dist = 0;
                        for (int i = 0; i < NoOfLevSets; i++)
                        {
                            dist = LevelSetTracker.DecodeLevelSetDist(RegionCode, i);
                            if (dist == 0)
                            {
                                m_levSetVals[i] = trk.DataHistories[i].Current.GetLevSetValues(NS, jCell, 1);
                            }
                            else
                            {
                                //_levSetVals[i] = m_CCBasis.Tracker.GetLevSetValues(i, NodeSet, jCell, 1);
                                m_levSetVals[i] = null;
                                m_levSetSign[i] = dist;
                            }
                        }


                        LevelSetSignCode levset_bytecode;
                        int SpecInd;
                        if (dist != 0)
                        {
                            // near - field:
                            // Basis contains zero-entries
                            // ++++++++++++++++++++++++++++

                            levset_bytecode = LevelSetSignCode.ComputeLevelSetBytecode(m_levSetSign);
                            SpecInd         = trk.GetSpeciesIndex(rrc, levset_bytecode);
                        }
                        else
                        {
                            levset_bytecode = default(LevelSetSignCode);
                            SpecInd         = 0;
                        }


                        for (int m = 0; m < M; m++)   // loop over nodes

                        {
                            if (dist == 0)
                            {
                                // cut cells
                                // Modulation necessary
                                // +++++++++++++++++++++

                                for (int i = 0; i < NoOfLevSets; i++)
                                {
                                    if (m_levSetVals[i] != null)
                                    {
                                        m_levSetSign[i] = m_levSetVals[i][0, m];
                                    }
                                }

                                // re-compute species index
                                levset_bytecode = LevelSetSignCode.ComputeLevelSetBytecode(m_levSetSign);
                                SpecInd         = trk.GetSpeciesIndex(rrc, levset_bytecode);
                            }


                            // separate coordinates
                            {
                                int n0 = Nsep * SpecInd;
                                for (int n = 0; n < Nsep; n++)   // loop over basis polynomials
                                //output[j, m, n0 + n] = BasisValues[m, n];
                                {
                                    Operation(output, BasisValues, j, m, n0 + n, n);
                                }
                            }
                        }
                    }
                }
            }