Example #1
0
        /// <summary>
        /// Finds minimum and maximum value in cell <paramref name="jL"/>.
        /// </summary>
        /// <param name="min">On exit, the minimum value.</param>
        /// <param name="max">On exit, the maximum value.</param>
        /// <param name="jL">Local cell index.</param>
        public void GetExtremalValuesInCell(out double min, out double max, int jL)
        {
            // create node set
            InitExtremalProbeNS();

            double LocMax = -double.MaxValue, LocMin = double.MaxValue;

            foreach (int j in this.GridDat.GetGeometricCellIndices(jL))
            {
                // les storage
                int iKref = Basis.GridDat.iGeomCells.GetRefElementIndex(j);
                int N     = m_ExtremalProbeNS[iKref].NoOfNodes;
                MultidimensionalArray fieldValues = MultidimensionalArray.Create(1, N);

                // evaluate DG field
                this.Evaluate(j, 1, m_ExtremalProbeNS[iKref], fieldValues, 0.0);

                // loop over nodes ...
                for (int n = 0; n < N; n++)
                {
                    double vel = 0;
                    vel = fieldValues[0, n];
                    if (vel > LocMax)
                    {
                        LocMax = vel;
                    }
                    if (vel < LocMin)
                    {
                        LocMin = vel;
                    }
                }
            }

            // return
            min = LocMin;
            max = LocMax;
        }
Example #2
0
            public IEnumerable <IChunkRulePair <QuadRule> > GetQuadRuleSet(ExecutionMask mask, int order)
            {
                QuadRule fullRule = RefElement.GetQuadratureRule(order);
                int      L1       = fullRule.NoOfNodes;
                int      D        = fullRule.SpatialDim;

                var otherRule = m_orgrule.GetQuadRuleSet(mask, order);
                var ret       = new List <IChunkRulePair <QuadRule> >(otherRule.Count());

                foreach (var x in otherRule)
                {
                    Chunk    chk = x.Chunk;
                    QuadRule qr  = x.Rule;
                    int      L2  = qr.NoOfNodes;

                    Debug.Assert(qr.SpatialDim == fullRule.SpatialDim);

                    QuadRule compQr = new QuadRule();
                    compQr.OrderOfPrecision = qr.OrderOfPrecision;

                    compQr.Nodes   = new NodeSet(this.RefElement, L1 + L2, D);
                    compQr.Weights = MultidimensionalArray.Create(L1 + L2);


                    compQr.Nodes.SetSubArray(fullRule.Nodes, new int[] { 0, 0 }, new int[] { L1 - 1, D - 1 });
                    compQr.Weights.SetSubArray(fullRule.Weights, new int[] { 0 }, new int[] { L1 - 1 });

                    compQr.Nodes.SetSubArray(qr.Nodes, new int[] { L1, 0 }, new int[] { L1 + L2 - 1, D - 1 });
                    compQr.Weights.AccSubArray(-1, qr.Weights, new int[] { L1 }, new int[] { L1 + L2 - 1 });

                    compQr.Nodes.LockForever();

                    ret.Add(new ChunkRulePair <QuadRule>(chk, compQr));
                }

                return(ret);
            }
        public static MultidimensionalArray EvaluateRefNormalsOnEdge(LevelSetTracker.LevelSetData lsData, int cell, CellBoundaryQuadRule rule, int localEdge)
        {
            if (rule.NumbersOfNodesPerFace[localEdge] == 0)
            {
                return(null);
            }

            MultidimensionalArray gradients = EvaluateLevelSetReferenceGradientsOnEdge(lsData, cell, rule, localEdge);
            int noOfNodes = gradients.GetLength(0);
            int D         = lsData.GridDat.SpatialDimension;

            MultidimensionalArray normals = MultidimensionalArray.Create(noOfNodes, D);

            for (int i = 0; i < noOfNodes; i++)
            {
                double norm = 0.0;
                for (int d = 0; d < D; d++)
                {
                    norm         += gradients[i, d] * gradients[i, d];
                    normals[i, d] = gradients[i, d];
                }

                if (norm == 0.0)
                {
                    continue;
                }

                norm = Math.Sqrt(norm);
                for (int d = 0; d < D; d++)
                {
                    normals[i, d] /= norm;
                }
            }

            return(normals);
        }
Example #4
0
        /// <summary>
        ///
        /// </summary>
        public void AnalyzeOperators(out MultidimensionalArray ret)
        {
            ret = MultidimensionalArray.Create(1, 7);
            // MultidimensionalArray ret = MultidimensionalArray.Create(1, 4);
            Console.WriteLine("Calling MATLAB/Octave...");
            using (BatchmodeConnector bmc = new BatchmodeConnector()) {
                bmc.PutSparseMatrix(OpMatrix, "OpMatrix");
                bmc.Cmd("condNoOpMatrix = condest(OpMatrix)");
                bmc.Cmd("OpRank = rank(full(OpMatrix))");
                bmc.Cmd("OpSize = size(OpMatrix)");
                bmc.Cmd("eigiMaxi = eigs(OpMatrix,1,'lm')");
                bmc.Cmd("eigiMini = eigs(OpMatrix,1,'sm')");
                bmc.Cmd("lasterr");
                bmc.Cmd("[V,r]=chol(OpMatrix);");
                bmc.Cmd("ret = [condNoOpMatrix, eigiMaxi, eigiMini, r, OpRank, OpSize]");
                bmc.GetMatrix(ret, "ret");

                bmc.Execute(true);
            }

            double condNoOpMatrix = ret[0, 0];
            double eigiMaxi       = ret[0, 1];
            double eigiMini       = ret[0, 2];
            double posDef         = ret[0, 3] == 0 ? 1 : 0;

            Console.WriteLine("Condition number operator: {0:0.####E-00}", condNoOpMatrix);

            if (posDef == 0.0)
            {
                Console.WriteLine("WARNING: Operator matrix is not positive definite.");
            }
            else
            {
                Console.WriteLine("Good news: Operator matrix seems to be positive definite.");
            }
        }
        /// <summary>
        /// Passes the given parameters to <see cref="INonlinEdgeForm_V.InternalEdge"/>
        /// </summary>
        /// <param name="prm"></param>
        /// <param name="U"></param>
        /// <param name="GradU"></param>
        /// <param name="f"></param>
        void INonlinVolumeForm_V.Form(ref VolumFormParams prm, MultidimensionalArray[] U, MultidimensionalArray[] GradU, MultidimensionalArray f)
        {
            INonlinEdgeForm_V flux = fluxFunction;

            MultidimensionalArray[] UBoundary;
            MultidimensionalArray   normals;
            EdgeFormParams          efp;

            AdaptParameters(ref prm, U, GradU, out efp, out UBoundary, out normals);

            MultidimensionalArray[] GradUBoundary = GradU; // cf. SIPGFlux, line 206

            // Set fBoundary to zero
            MultidimensionalArray fBoundary = MultidimensionalArray.Create(
                U[0].GetLength(0), prm.Xglobal.GetLength(1));


            OptimizedSIPGEnergyFlux.EVIL_HACK_CELL_INDEX   = prm.j0;
            OptimizedSIPGMomentumFlux.EVIL_HACK_CELL_INDEX = prm.j0;
            fluxFunction.AdiabaticWall = this.adiaWall;
            flux.InternalEdge(ref efp, U, UBoundary, GradU, GradUBoundary, f, fBoundary);
            OptimizedSIPGEnergyFlux.EVIL_HACK_CELL_INDEX   = -1;
            OptimizedSIPGMomentumFlux.EVIL_HACK_CELL_INDEX = -1;
        }
Example #6
0
        internal static double GetMaxLocalMassMatrixDeterminant(ImmersedSpeciesMap speciesMap, CoordinateMapping mapping, CellMask cellMask, out int maxCondCell)
        {
            BlockMsrMatrix massMatrix = speciesMap.GetMassMatrixFactory(mapping).MassMatrix;
            Basis          maxBasis   = mapping.BasisS.ElementAtMax(b => b.Degree);

            MultidimensionalArray subMatrix = MultidimensionalArray.Create(
                maxBasis.Length, maxBasis.Length);

            double maxCond = 0.0;

            maxCondCell = -1;
            foreach (Chunk chunk in cellMask)
            {
                for (int i = 0; i < chunk.Len; i++)
                {
                    //IMatrix block = massMatrix.GetBlock(i + chunk.i0);
                    MultidimensionalArray block = GetBlock(massMatrix, i + chunk.i0);
                    for (int j = 0; j < maxBasis.Length; j++)
                    {
                        for (int k = 0; k < maxBasis.Length; k++)
                        {
                            subMatrix[j, k] = block[j, k];
                        }
                    }

                    double cond = subMatrix.cond();
                    if (cond > maxCond)
                    {
                        maxCond     = cond;
                        maxCondCell = i + chunk.i0;
                    }
                }
            }

            return(maxCond);
        }
Example #7
0
        void MapToDGSpace(int jCell, SinglePhaseField Phi)
        {
            int numberOfQuadNodes = (resolution - 2) * (resolution - 2);
            MultidimensionalArray PhiAtQuadNodes          = ConvertToQuadNodes(nodeGrid);
            MultidimensionalArray weighted_PhiAtQuadNodes = MultidimensionalArray.Create(numberOfQuadNodes);


            for (int i = 0; i < numberOfQuadNodes; i++)   // loop over all quadrature nodes
            {
                weighted_PhiAtQuadNodes[i] = PhiAtQuadNodes[i] * this.daRuleS[iKref].Weights[i];
            }

            var BasisValues = this.solutionBasis.CellEval(this.daRuleS[iKref].Nodes, jCell, 1).ExtractSubArrayShallow(0, -1, -1);

            if (this.gridDat.Cells.IsCellAffineLinear(jCell))
            {
                int N  = this.solutionBasis.GetLength(jCell);
                int N2 = Phi.Basis.GetLength(jCell);

                MultidimensionalArray Phi_1 = MultidimensionalArray.Create(N);
                double scale = this.gridDat.Cells.JacobiDet[jCell];
                Phi_1.Multiply(scale, BasisValues, weighted_PhiAtQuadNodes, 0.0, "m", "km", "k");
                for (int n = 0; n < N; n++)
                {
                    Phi.Coordinates[jCell, n] = Phi_1[n];
                }
                for (int n = N; n < N2; n++)
                {
                    Phi.Coordinates[jCell, n] = 0;
                }
            }
            else
            {
                throw new NotImplementedException("not implemented for curved cells");
            }
        }
Example #8
0
        /// <summary>
        /// Create clustering without boundary cells
        /// </summary>
        /// <param name="inputClustering">Input data which has to be a previous clustering</param>
        /// <returns>
        /// Clustering as <see cref="MultidimensionalArray"/>
        /// [0]: x, [1]: y, [2]: data, [3]: cellToCluster (e.g. cell 0 is in cluster 1), [4]: local cell index
        public MultidimensionalArray CreateClustering_Boundary(MultidimensionalArray inputClustering)
        {
            Console.WriteLine("CreateClustering_Boundary: START");

            var      gridData       = (GridData)Session.Timesteps.Last().Fields.First().GridDat;
            BitArray isBoundaryCell = gridData.GetBoundaryCells().GetBitMask();

            // Store values
            int numOfPoints = inputClustering.Lengths[0];

            int[] internalCells = new int[numOfPoints];
            int   count         = 0;

            for (int i = 0; i < numOfPoints; i++)
            {
                if (!isBoundaryCell[(int)inputClustering[i, 4]])
                {
                    internalCells[count] = i;
                    count++;
                }
            }
            Array.Resize(ref internalCells, count);

            MultidimensionalArray clustering = MultidimensionalArray.Create(count, inputClustering.Lengths[1]);

            for (int i = 0; i < internalCells.Length; i++)
            {
                int cell = internalCells[i];
                clustering.ExtractSubArrayShallow(i, -1).Acc(1.0, inputClustering.ExtractSubArrayShallow(cell, -1));
            }
            _clusterings.Add(clustering);

            Console.WriteLine("CreateClustering_Boundary: END");

            return(clustering);
        }
Example #9
0
        /// <summary>
        /// Create clustering based on the artificial viscosity (mean values)
        /// </summary>
        /// <param name="inputClustering">Input data which has to be a previous clustering</param>
        /// <param name="numOfClusters">Needed by <see cref="Kmeans"/></param>
        /// <param name="initialMeans">Needed by <see cref="Kmeans"/></param>
        /// <returns>
        /// Clustering as <see cref="MultidimensionalArray"/>
        /// [0]: x, [1]: y, [2]: data, [3]: cellToCluster (e.g. cell 0 is in cluster 1), [4]: local cell index
        /// </returns>
        public MultidimensionalArray CreateClustering_AV(MultidimensionalArray inputClustering, int numOfClusters, double[] initialMeans)
        {
            Console.WriteLine("CreateClustering_AV: START");

            // Get AV values
            var avField     = this.Session.Timesteps.Last().Fields.Where(f => f.Identification == "artificialViscosity").SingleOrDefault();
            int numOfPoints = inputClustering.Lengths[0];

            double[] data = new double[numOfPoints];
            for (int i = 0; i < data.Length; i++)
            {
                data[i] = avField.GetMeanValue((int)inputClustering[i, 4]);
            }

            // Kmeans
            Kmeans kmeans = new Kmeans(data, numOfClusters, initialMeans);

            int[] cellToCluster = kmeans.Cluster();

            // Store values
            MultidimensionalArray clustering = MultidimensionalArray.Create(data.Length, inputClustering.Lengths[1]);

            for (int i = 0; i < numOfPoints; i++)
            {
                clustering[i, 0] = inputClustering[i, 0];      // x
                clustering[i, 1] = inputClustering[i, 1];      // y
                clustering[i, 2] = data[i];                    // data value
                clustering[i, 3] = cellToCluster[i];           // cellToCluster (e.g. cell 0 is in cluster 1)
                clustering[i, 4] = inputClustering[i, 4];      // local cell index
            }
            _clusterings.Add(clustering);

            Console.WriteLine("CreateClustering_AV: END");

            return(clustering);
        }
        private static MultidimensionalArray EvaluateLevelSetGradientsOnEdge(LevelSetTracker.LevelSetData lsData, int cell, CellBoundaryQuadRule rule, int localEdge)
        {
            var gdat = lsData.GridDat;
            int edge = Math.Abs(gdat.Cells.Cells2Edges[cell][localEdge]) - 1;
            int D    = gdat.SpatialDimension;
            MultidimensionalArray volumeGradients = lsData.GetLevelSetGradients(rule.Nodes, cell, 1);

            int noOfNodes = rule.NumbersOfNodesPerFace[localEdge];

            if (noOfNodes == 0)
            {
                return(null);
            }

            int offset = rule.NumbersOfNodesPerFace.Take(localEdge).Sum();
            MultidimensionalArray normals = MultidimensionalArray.Create(noOfNodes, D);
            var NormalsForAffine          = gdat.Edges.NormalsForAffine;

            for (int i = 0; i < noOfNodes; i++)
            {
                double normalComponent = 0.0;
                for (int d = 0; d < D; d++)
                {
                    normalComponent += volumeGradients[0, offset + i, d] * NormalsForAffine[edge, d];
                }

                // Subtract normal component
                for (int d = 0; d < D; d++)
                {
                    normals[i, d] = volumeGradients[0, offset + i, d]
                                    - normalComponent * NormalsForAffine[edge, d];
                }
            }

            return(normals);
        }
        public static MultidimensionalArray GetMetricTermsOnEdge(LevelSetTracker.LevelSetData LevelSetData, int levSetIndex, CellBoundaryQuadRule rule, int cell, int localEdge)
        {
            if (rule.NumbersOfNodesPerFace[localEdge] == 0)
            {
                return(null);
            }

            MultidimensionalArray physGradients = EvaluateLevelSetGradientsOnEdge(LevelSetData, cell, rule, localEdge);
            MultidimensionalArray refGradients  = EvaluateLevelSetReferenceGradientsOnEdge(LevelSetData, cell, rule, localEdge);
            int noOfNodes = physGradients.GetLength(0);
            int D         = LevelSetData.GridDat.SpatialDimension;
            MultidimensionalArray result = MultidimensionalArray.Create(noOfNodes);

            int edge = Math.Abs(LevelSetData.GridDat.Cells.Cells2Edges[cell][localEdge]) - 1;

            var JacobiDet   = LevelSetData.GridDat.Cells.JacobiDet;
            var SqrtGramian = LevelSetData.GridDat.Edges.SqrtGramian;

            for (int j = 0; j < noOfNodes; j++)
            {
                double normPhys = 0.0;
                double normRef  = 0.0;

                for (int d = 0; d < D; d++)
                {
                    normPhys += physGradients[j, d] * physGradients[j, d];
                    normRef  += refGradients[j, d] * refGradients[j, d];
                }

                //result[j] = Math.Sqrt(normRef / normPhys) / SqrtGramian[edge] * Math.Sqrt(JacobiDet[cell]);
                result[j] = JacobiDet[cell] / SqrtGramian[edge];
                //    result[j] = Math.Sqrt(normRef / normPhys) / tracker.GridDat.Edges.SqrtGramian[edge] / tracker.Ctx.GridDat.OneOverSqrt_AbsDetTransformation[cell];
            }

            return(result);
        }
Example #12
0
        public void PeriodicBoundaryPairBoundaryOnEdge()
        {
            byte[] tags = { 1, 181, 1, 181 };
            SortedList <byte, string> tagNames = new SortedList <byte, string>(2)
            {
                { 181, "Periodic-X" },
                { 1, "Dirichlet" }
            };
            MultidimensionalArray nodes = MultidimensionalArray.Create(6, 2);

            nodes.SetRowPt(0, new Vector(-0.8, 0.6));
            nodes.SetRowPt(1, new Vector(-0.8, -0.6));
            nodes.SetRowPt(2, new Vector(-0.2, 0.0));
            nodes.SetRowPt(3, new Vector(0.2, 0.0));
            nodes.SetRowPt(4, new Vector(0.8, 0.6));
            nodes.SetRowPt(5, new Vector(0.8, -0.6));
            VoronoiBoundary gridBoundary = new VoronoiBoundary
            {
                Polygon      = GridShapes.Rectangle(2, 2),
                EdgeTags     = tags,
                EdgeTagNames = tagNames
            };
            VoronoiGrid grid = VoronoiGrid2D.Polygonal(nodes, gridBoundary, 0, 0);
        }
Example #13
0
        /// <summary>
        /// Computes the projection of all
        /// <see cref="SpatialDimension"/>-dimensional basis polynomials in
        /// <paramref name="basis"/> onto this line segment and stores the
        /// result in <see cref="ProjectedPolynomialCoefficients"/>
        /// </summary>
        /// <param name="basis">
        /// A basis containing the polynomials to be projected
        /// </param>
        /// <remarks>
        /// Don't ask me (B. Müller) how it works, so please don't touch it. I
        /// remember that I coded it but even at that time, I didn't fully
        /// understand <b>why</b> it works.
        /// </remarks>
        public void ProjectBasisPolynomials(Basis basis)
        {
            int NoOfRefElm      = 1;
            int iKref           = Array.IndexOf(basis.GridDat.iGeomCells.RefElements, this.m_Kref);
            int noOfPolynomials = basis.Polynomials[iKref].Count;
            int noOfCoefficientsPerDimension = basis.Degree + 1;

            MultidimensionalArray[] T = new MultidimensionalArray[SpatialDimension];
            ProjectedPolynomialCoefficients = MultidimensionalArray.Create(NoOfRefElm, noOfPolynomials, noOfCoefficientsPerDimension);

            // Construct transformations
            for (int d = 0; d < SpatialDimension; d++)
            {
                double a = 0.5 * (End[d] - Start[d]);
                double b = 0.5 * (Start[d] + End[d]);

                T[d] = MultidimensionalArray.Create(noOfCoefficientsPerDimension, noOfCoefficientsPerDimension);
                for (int i = 0; i < noOfCoefficientsPerDimension; i++)
                {
                    for (int j = 0; j < noOfCoefficientsPerDimension; j++)
                    {
                        if (i > j)
                        {
                            continue;
                        }

                        T[d][i, j] = j.Choose(i) * Math.Pow(a, i) * Math.Pow(b, j - i);
                    }
                }
            }

            {
                for (int p = 0; p < noOfPolynomials; p++)
                {
                    Polynomial currentPolynomial = basis.Polynomials[iKref][p];
                    double[]   coefficients      = new double[noOfCoefficientsPerDimension];

                    // Transform coefficients to D-dimensional "matrix"
                    MultidimensionalArray originalCoefficients = MultidimensionalArray.Create(
                        Enumerable.Repeat(noOfCoefficientsPerDimension, SpatialDimension).ToArray());
                    for (int j = 0; j < currentPolynomial.Coeff.Length; j++)
                    {
                        int[] exponents = ArrayTools.GetRow(currentPolynomial.Exponents, j);
                        originalCoefficients[exponents] += currentPolynomial.Coeff[j];
                    }

                    // Do projection
                    switch (SpatialDimension)
                    {
                    case 1:
                        T[0].GEMV(1.0, originalCoefficients.Storage, 0.0, coefficients);
                        break;

                    case 2:
                        MultidimensionalArray coefficientMatrix =
                            MultidimensionalArray.Create(noOfCoefficientsPerDimension, noOfCoefficientsPerDimension);
                        coefficientMatrix.Set(originalCoefficients);
                        coefficientMatrix = T[1] * (T[0] * coefficientMatrix).TransposeInPlace();

                        // Only left upper triangle can possibly be populated
                        for (int i = 0; i < noOfCoefficientsPerDimension; i++)
                        {
                            for (int j = 0; j < i + 1; j++)
                            {
                                coefficients[i] += coefficientMatrix[i - j, j];
                            }
                        }
                        break;

                    case 3:
                        MultidimensionalArray matrix = MultidimensionalArray.Create(
                            noOfCoefficientsPerDimension, noOfCoefficientsPerDimension);

                        MultidimensionalArray[] Ty = new MultidimensionalArray[noOfCoefficientsPerDimension];
                        for (int i = 0; i < noOfCoefficientsPerDimension; i++)
                        {
                            matrix.Set(originalCoefficients.ExtractSubArrayShallow(-1, -1, i));
                            Ty[i] = T[1] * (T[0] * matrix).TransposeInPlace();
                        }

                        // Only left upper triangle can possibly be populated
                        MultidimensionalArray tempCoefficients = MultidimensionalArray.Create(noOfCoefficientsPerDimension, Ty[0].NoOfRows);
                        for (int i = 0; i < Ty[0].NoOfRows; i++)
                        {
                            for (int j = 0; j < i + 1; j++)
                            {
                                int index = i - j;

                                for (int k = 0; k < noOfCoefficientsPerDimension; k++)
                                {
                                    tempCoefficients[k, i] += Ty[k][index, j];
                                }
                            }
                        }

                        MultidimensionalArray transformedTempCoefficients = T[2] * tempCoefficients;
                        for (int i = 0; i < noOfCoefficientsPerDimension; i++)
                        {
                            for (int j = 0; j < i + 1; j++)
                            {
                                coefficients[i] += transformedTempCoefficients[i - j, j];
                            }
                        }
                        break;

                    default:
                        throw new ApplicationException("Invalid spatial dimension");
                    }

                    ProjectedPolynomialCoefficients.ExtractSubArrayShallow(0, p, -1).AccVector(1.0, coefficients);
                }
            }
        }
Example #14
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);
        }
Example #15
0
        static ScalarFunctionEx GetEnergyBalanceFunc(XDGField P, VectorField <XDGField> U, ConventionalDGField[] Umean, SinglePhaseField C, double muA, double muB, double sigma, bool squared)
        {
            int D = P.Basis.GridDat.SpatialDimension;

            ConventionalDGField pA = P.GetSpeciesShadowField("A");
            ConventionalDGField pB = P.GetSpeciesShadowField("B");

            var UA = U.Select(u => u.GetSpeciesShadowField("A")).ToArray();
            var UB = U.Select(u => u.GetSpeciesShadowField("B")).ToArray();

            return(delegate(int i0, int Len, NodeSet nds, MultidimensionalArray result) {
                int K = result.GetLength(1); // No nof Nodes
                MultidimensionalArray pA_res = MultidimensionalArray.Create(Len, K);
                MultidimensionalArray pB_res = MultidimensionalArray.Create(Len, K);
                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 U_res = MultidimensionalArray.Create(Len, K, D);
                MultidimensionalArray GradU_res = MultidimensionalArray.Create(Len, K, D, D);
                MultidimensionalArray Curv_res = MultidimensionalArray.Create(Len, K);

                pA.Evaluate(i0, Len, nds, pA_res);
                pB.Evaluate(i0, Len, nds, pB_res);

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

                    UA[i].EvaluateGradient(i0, Len, nds, GradUA_res.ExtractSubArrayShallow(-1, -1, i, -1));
                    UB[i].EvaluateGradient(i0, Len, nds, GradUB_res.ExtractSubArrayShallow(-1, -1, i, -1));
                    Umean[i].EvaluateGradient(i0, Len, nds, GradU_res.ExtractSubArrayShallow(-1, -1, i, -1));
                }

                C.Evaluate(i0, Len, nds, Curv_res);

                var Normals = P.Basis.Tracker.DataHistories[0].Current.GetLevelSetNormals(nds, i0, 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++)
                        {
                            // enrgy jump at interface
                            acc -= (pB_res[j, k] * UB_res[j, k, d] - pA_res[j, k] * UA_res[j, k, d]) * Normals[j, k, d];

                            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
                            }

                            // surface energy changerate
                            //for (int dd = 0; dd < D; dd++) {
                            //    if (dd == d) {
                            //        acc += sigma * (1 - Normals[j, k, d] * Normals[j, k, dd]) * GradU_res[j, k, dd, d];
                            //    } else {
                            //        acc += sigma * (-Normals[j, k, d] * Normals[j, k, dd]) * GradU_res[j, k, dd, d];
                            //    }
                            //}

                            // curvature energy
                            acc -= sigma * Curv_res[j, k] * U_res[j, k, d] * Normals[j, k, d];
                        }

                        if (squared)
                        {
                            result[j, k] = acc.Pow2();
                        }
                        else
                        {
                            result[j, k] = acc;
                        }
                    }
                }
            });
        }
Example #16
0
        static ScalarFunctionEx GetInterfaceShearViscosityEnergyCRFunc(LevelSetTracker LsTrk, ConventionalDGField[] uI, bool squared)
        {
            int D = LsTrk.GridDat.SpatialDimension;

            return(delegate(int i0, int Len, NodeSet nds, MultidimensionalArray result) {
                int K = result.GetLength(1); // No nof Nodes
                MultidimensionalArray GradU_Res = MultidimensionalArray.Create(Len, K, D, D);

                for (int i = 0; i < D; i++)
                {
                    uI.ElementAt(i).EvaluateGradient(i0, Len, nds, GradU_Res.ExtractSubArrayShallow(-1, -1, i, -1));
                }

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

                for (int j = 0; j < Len; j++)
                {
                    for (int k = 0; k < K; k++)
                    {
                        MultidimensionalArray Nsurf = Normals.ExtractSubArrayShallow(j, k, -1);
                        double[,] Psurf = new double[D, D];
                        for (int d1 = 0; d1 < D; d1++)
                        {
                            for (int d2 = 0; d2 < D; d2++)
                            {
                                if (d2 == d1)
                                {
                                    Psurf[d1, d2] = (1 - Nsurf[d1] * Nsurf[d2]);
                                }
                                else
                                {
                                    Psurf[d1, d2] = (0 - Nsurf[d1] * Nsurf[d2]);
                                }
                            }
                        }

                        double[,] GradUsurf = new double[D, D];
                        for (int d1 = 0; d1 < D; d1++)
                        {
                            for (int d2 = 0; d2 < D; d2++)
                            {
                                for (int dd = 0; dd < D; dd++)
                                {
                                    GradUsurf[d1, d2] += Psurf[d1, dd] * GradU_Res[j, k, dd, d2];
                                }
                            }
                        }

                        double acc = 0.0;

                        // GradU
                        for (int d1 = 0; d1 < D; d1++)
                        {
                            for (int d2 = 0; d2 < D; d2++)
                            {
                                for (int dd = 0; dd < D; dd++)
                                {
                                    acc += Psurf[d1, dd] * GradUsurf[dd, d2] * GradUsurf[d1, d2];
                                }
                            }
                        }

                        // GradU transpose
                        double[,] Psurf2 = new double[D, D];
                        for (int d1 = 0; d1 < D; d1++)
                        {
                            for (int d2 = 0; d2 < D; d2++)
                            {
                                if (d2 == d1)
                                {
                                    Psurf2[d1, d2] = (1 - 2 * Nsurf[d1] * Nsurf[d2]);
                                }
                                else
                                {
                                    Psurf2[d1, d2] = (0 - 2 * Nsurf[d1] * Nsurf[d2]);
                                }
                            }
                        }

                        for (int d1 = 0; d1 < D; d1++)
                        {
                            for (int d2 = 0; d2 < D; d2++)
                            {
                                for (int dd = 0; dd < D; dd++)
                                {
                                    acc -= GradU_Res[j, k, d1, dd] * Psurf2[dd, d2] * GradUsurf[d1, d2];
                                }
                            }
                        }

                        if (squared)
                        {
                            result[j, k] = acc.Pow2();
                        }
                        else
                        {
                            result[j, k] = acc;
                        }
                    }
                }
            });
        }
Example #17
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];
                }
            }
        }
Example #18
0
 /// <summary>
 /// ctor;
 /// </summary>
 public SpecFemField(SpecFemBasis b)
 {
     m_Basis       = b;
     m_Coordinates = MultidimensionalArray.Create(m_Basis.NoOfLocalNodes);
 }
Example #19
0
        /// <summary>
        /// Calculates the drag (x-component) and lift (y-component) forces acting on a wall of a boundary fitted grid
        /// </summary>
        /// <param name="U"></param>
        /// <param name="P"></param>
        /// <param name="muA"></param>
        /// <returns></returns>
        static public double[] GetForces_BoundaryFitted(VectorField <SinglePhaseField> GradU, VectorField <SinglePhaseField> GradV, SinglePhaseField StressXX,
                                                        SinglePhaseField StressXY, SinglePhaseField StressYY, SinglePhaseField P, LevelSetTracker LsTrk, double muA, double beta)
        {
            int D = LsTrk.GridDat.SpatialDimension;

            if (D > 2)
            {
                throw new ArgumentException("Method GetForces_BoundaryFitted only implemented for 2D (viscoelastic)!");
            }
            // var UA = U.Select(u => u.GetSpeciesShadowField("A")).ToArray();
            //var UA = U.ToArray();
            MultidimensionalArray Grad_U = new MultidimensionalArray(D);
            var _GradU = GradU.ToArray();
            var _GradV = GradV.ToArray();


            int RequiredOrder = _GradU[0].Basis.Degree * 3 + 2;

            //int RequiredOrder = U[0].Basis.Degree * 3 + 2;
            //int RequiredOrder = LsTrk.GetXQuadFactoryHelper(momentFittingVariant).GetCachedSurfaceOrders(0).Max();
            //Console.WriteLine("Order reduction: {0} -> {1}", _RequiredOrder, RequiredOrder);

            //if (RequiredOrder > agg.HMForder)
            //    throw new ArgumentException();

            Console.WriteLine("Forces coeff: {0}, order = {1}", LsTrk.CutCellQuadratureType, RequiredOrder);

            SinglePhaseField _StressXX = StressXX;
            SinglePhaseField _StressXY = StressXY;
            SinglePhaseField _StressYY = StressYY;

            SinglePhaseField pA = null;

            //pA = P.GetSpeciesShadowField("A");
            pA = P;



            double[] forces = new double[D];
            for (int d = 0; d < D; d++)
            {
                ScalarFunctionEx ErrFunc = delegate(int j0, int Len, NodeSet Ns, MultidimensionalArray result) {
                    int K = result.GetLength(1); // No nof Nodes
                    MultidimensionalArray Grad_URes   = MultidimensionalArray.Create(Len, K, D);
                    MultidimensionalArray Grad_VRes   = MultidimensionalArray.Create(Len, K, D);
                    MultidimensionalArray pARes       = MultidimensionalArray.Create(Len, K);
                    MultidimensionalArray StressXXRes = MultidimensionalArray.Create(Len, K);
                    MultidimensionalArray StressXYRes = MultidimensionalArray.Create(Len, K);
                    MultidimensionalArray StressYYRes = MultidimensionalArray.Create(Len, K);

                    var Normals = LsTrk.GridDat.Edges.NormalsCache.GetNormals_Edge(Ns, j0, Len);
                    //var Normals = MultidimensionalArray.Create(1, Ns.Length, 1);
                    //var Normals = LsTrk.GridDat.Edges.NormalsForAffine;


                    for (int i = 0; i < D; i++)
                    {
                        _GradU[i].EvaluateEdge(j0, Len, Ns, Grad_URes.ExtractSubArrayShallow(-1, -1, i),
                                               Grad_URes.ExtractSubArrayShallow(-1, -1, i), ResultIndexOffset: 0, ResultPreScale: 1);

                        _GradV[i].EvaluateEdge(j0, Len, Ns, Grad_VRes.ExtractSubArrayShallow(-1, -1, i),
                                               Grad_VRes.ExtractSubArrayShallow(-1, -1, i), ResultIndexOffset: 0, ResultPreScale: 1);

                        //UA[i].EvaluateGradient(j0, Len, Ns, Grad_UARes.ExtractSubArrayShallow(-1, -1, i, -1), 0, 1);
                    }

                    //pA.Evaluate(j0, Len, Ns, pARes);
                    pA.EvaluateEdge(j0, Len, Ns, pARes, pARes, ResultIndexOffset: 0, ResultPreScale: 1);
                    _StressXX.EvaluateEdge(j0, Len, Ns, StressXXRes, StressXXRes, ResultIndexOffset: 0, ResultPreScale: 1);
                    _StressXY.EvaluateEdge(j0, Len, Ns, StressXYRes, StressXYRes, ResultIndexOffset: 0, ResultPreScale: 1);
                    _StressYY.EvaluateEdge(j0, Len, Ns, StressYYRes, StressYYRes, ResultIndexOffset: 0, ResultPreScale: 1);


                    //if (LsTrk.GridDat.SpatialDimension == 2)
                    //{

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

                            // pressure
                            switch (d)
                            {
                            case 0:
                                acc += pARes[j, k] * Normals[j, k, 0];
                                acc -= (2 * muA * beta) * Grad_URes[j, k, 0] * Normals[j, k, 0];
                                acc -= (muA * beta) * Grad_URes[j, k, 1] * Normals[j, k, 1];
                                acc -= (muA * beta) * Grad_VRes[j, k, 0] * Normals[j, k, 1];
                                acc -= (muA * (1 - beta)) * StressXXRes[j, k] * Normals[j, k, 0];
                                acc -= (muA * (1 - beta)) * StressXYRes[j, k] * Normals[j, k, 1];
                                break;

                            case 1:
                                acc += pARes[j, k] * Normals[j, k, 1];
                                acc -= (2 * muA * beta) * Grad_VRes[j, k, 1] * Normals[j, k, 1];
                                acc -= (muA * beta) * Grad_VRes[j, k, 0] * Normals[j, k, 0];
                                acc -= (muA * beta) * Grad_URes[j, k, 1] * Normals[j, k, 0];
                                acc -= (muA * (1 - beta)) * StressXYRes[j, k] * Normals[j, k, 0];
                                acc -= (muA * (1 - beta)) * StressYYRes[j, k] * Normals[j, k, 1];
                                break;

                            default:
                                throw new NotImplementedException();
                            }

                            result[j, k] = acc;
                        }
                    }

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

                    //            // pressure
                    //            switch (d)
                    //            {
                    //                case 0:
                    //                    acc += pARes[j, k] * Normals[j, k, 0];
                    //                    acc -= (2 * muA) * Grad_UARes[j, k, 0, 0] * Normals[j, k, 0];
                    //                    acc -= (muA) * Grad_UARes[j, k, 0, 2] * Normals[j, k, 2];
                    //                    acc -= (muA) * Grad_UARes[j, k, 0, 1] * Normals[j, k, 1];
                    //                    acc -= (muA) * Grad_UARes[j, k, 1, 0] * Normals[j, k, 1];
                    //                    acc -= (muA) * Grad_UARes[j, k, 2, 0] * Normals[j, k, 2];
                    //                    break;
                    //                case 1:
                    //                    acc += pARes[j, k] * Normals[j, k, 1];
                    //                    acc -= (2 * muA) * Grad_UARes[j, k, 1, 1] * Normals[j, k, 1];
                    //                    acc -= (muA) * Grad_UARes[j, k, 1, 2] * Normals[j, k, 2];
                    //                    acc -= (muA) * Grad_UARes[j, k, 1, 0] * Normals[j, k, 0];
                    //                    acc -= (muA) * Grad_UARes[j, k, 0, 1] * Normals[j, k, 0];
                    //                    acc -= (muA) * Grad_UARes[j, k, 2, 1] * Normals[j, k, 2];
                    //                    break;
                    //                case 2:
                    //                    acc += pARes[j, k] * Normals[j, k, 2];
                    //                    acc -= (2 * muA) * Grad_UARes[j, k, 2, 2] * Normals[j, k, 2];
                    //                    acc -= (muA) * Grad_UARes[j, k, 2, 0] * Normals[j, k, 0];
                    //                    acc -= (muA) * Grad_UARes[j, k, 2, 1] * Normals[j, k, 1];
                    //                    acc -= (muA) * Grad_UARes[j, k, 0, 2] * Normals[j, k, 0];
                    //                    acc -= (muA) * Grad_UARes[j, k, 1, 2] * Normals[j, k, 1];
                    //                    break;
                    //                default:
                    //                    throw new NotImplementedException();
                    //            }

                    //    result[j, k] = acc;
                    //}
                    //}
                    //}
                };


                var SchemeHelper = LsTrk.GetXDGSpaceMetrics(new[] { LsTrk.GetSpeciesId("A") }, RequiredOrder, 1).XQuadSchemeHelper;

                EdgeMask Mask = new EdgeMask(LsTrk.GridDat, "Wall_cylinder");

                EdgeQuadratureScheme eqs = SchemeHelper.GetEdgeQuadScheme(LsTrk.GetSpeciesId("A"), IntegrationDomain: Mask);

                EdgeQuadrature.GetQuadrature(new int[] { 1 }, LsTrk.GridDat,
                                             eqs.Compile(LsTrk.GridDat, RequiredOrder), //  agg.HMForder),
                                             delegate(int i0, int Length, QuadRule QR, MultidimensionalArray EvalResult) {
                    ErrFunc(i0, Length, QR.Nodes, EvalResult.ExtractSubArrayShallow(-1, -1, 0));
                },
                                             delegate(int i0, int Length, MultidimensionalArray ResultsOfIntegration) {
                    for (int i = 0; i < Length; i++)
                    {
                        forces[d] += ResultsOfIntegration[i, 0];
                    }
                }
                                             ).Execute();
            }

            //for (int i = 0; i < D; i++)
            //    forces[i] = MPI.Wrappers.MPIExtensions.MPISum(forces[i]);

            return(forces);
        }
Example #20
0
        /// <summary>
        /// Calculates the Torque around the center of mass
        /// </summary>
        /// <param name="U"></param>
        /// <param name="P"></param>
        /// <param name="momentFittingVariant"></param>
        /// <param name="muA"></param>
        /// <param name="particleRadius"></param>
        /// <returns></returns>
        static public void GetCellValues(VectorField <XDGField> U, XDGField P,
                                         double muA, double particleRadius, SinglePhaseField P_atIB, SinglePhaseField gradU_atIB, SinglePhaseField gradUT_atIB)
        {
            var LsTrk = U[0].Basis.Tracker;
            int D     = LsTrk.GridDat.SpatialDimension;
            var UA    = U.Select(u => u.GetSpeciesShadowField("A")).ToArray();

            if (D > 2)
            {
                throw new NotImplementedException("Currently only 2D cases supported");
            }

            int RequiredOrder = U[0].Basis.Degree * 3 + 2;

            //if (RequiredOrder > agg.HMForder)
            //    throw new ArgumentException();

            Console.WriteLine("Cell values calculated by: {0}, order = {1}", LsTrk.CutCellQuadratureType, RequiredOrder);

            ConventionalDGField pA = null;
            double circumference   = new double();

            pA = P.GetSpeciesShadowField("A");

            for (int n = 0; n < 4; n++)
            {
                ScalarFunctionEx ErrFunc_CellVal = delegate(int j0, int Len, NodeSet Ns, MultidimensionalArray result) {
                    int K = result.GetLength(1); // No nof Nodes
                    MultidimensionalArray Grad_UARes = MultidimensionalArray.Create(Len, K, D, D);;
                    MultidimensionalArray pARes      = MultidimensionalArray.Create(Len, K);

                    // Evaluate tangential velocity to level-set surface
                    var Normals = LsTrk.DataHistories[0].Current.GetLevelSetNormals(Ns, j0, Len);

                    for (int i = 0; i < D; i++)
                    {
                        UA[i].EvaluateGradient(j0, Len, Ns, Grad_UARes.ExtractSubArrayShallow(-1, -1, i, -1));
                    }

                    pA.Evaluate(j0, Len, Ns, pARes);

                    for (int j = 0; j < Len; j++)
                    {
                        for (int k = 0; k < K; k++)
                        {
                            double acc  = 0.0;
                            double acc2 = 0.0;
                            switch (n)
                            {
                            case 0:     // Pressure part


                                acc += pARes[j, k] * Normals[j, k, 0];
                                acc *= -Normals[j, k, 1] * particleRadius;


                                acc2 += pARes[j, k] * Normals[j, k, 1];
                                acc2 *= Normals[j, k, 0] * particleRadius;

                                result[j, k] = acc + acc2;
                                break;

                            case 1:                                                           // GradU part

                                acc -= (1 * muA) * Grad_UARes[j, k, 0, 0] * Normals[j, k, 0]; // Attention was 2 times
                                acc -= (muA) * Grad_UARes[j, k, 0, 1] * Normals[j, k, 1];
                                acc *= -Normals[j, k, 1] * particleRadius;

                                acc2 -= (1 * muA) * Grad_UARes[j, k, 1, 1] * Normals[j, k, 1];
                                acc2 -= (muA) * Grad_UARes[j, k, 1, 0] * Normals[j, k, 0];
                                acc2 *= Normals[j, k, 0] * particleRadius;

                                result[j, k] = acc + acc2;
                                break;

                            case 2:                                                           // GradU_T part

                                acc -= (1 * muA) * Grad_UARes[j, k, 0, 0] * Normals[j, k, 0]; // Attention was 2 times
                                acc -= (muA) * Grad_UARes[j, k, 1, 0] * Normals[j, k, 1];
                                acc *= -Normals[j, k, 1] * particleRadius;


                                acc2 -= (1 * muA) * Grad_UARes[j, k, 1, 1] * Normals[j, k, 1]; // Attention was 2 times
                                acc2 -= (muA) * Grad_UARes[j, k, 0, 1] * Normals[j, k, 0];
                                acc2 *= Normals[j, k, 0] * particleRadius;

                                result[j, k] = acc + acc2;
                                break;

                            case 3:     // Standardization with radians

                                result[j, k] = 1;
                                break;

                            default:
                                throw new NotImplementedException();
                            }
                        }
                    }
                };



                var SchemeHelper         = LsTrk.GetXDGSpaceMetrics(new[] { LsTrk.GetSpeciesId("A") }, RequiredOrder, 1).XQuadSchemeHelper; //   new XQuadSchemeHelper(LsTrk, momentFittingVariant, );
                CellQuadratureScheme cqs = SchemeHelper.GetLevelSetquadScheme(0, LsTrk.Regions.GetCutCellMask());

                CellQuadrature.GetQuadrature(new int[] { 1 }, LsTrk.GridDat,
                                             cqs.Compile(LsTrk.GridDat, RequiredOrder),
                                             delegate(int i0, int Length, QuadRule QR, MultidimensionalArray EvalResult) {
                    ErrFunc_CellVal(i0, Length, QR.Nodes, EvalResult.ExtractSubArrayShallow(-1, -1, 0));
                },
                                             delegate(int i0, int Length, MultidimensionalArray ResultsOfIntegration) {
                    for (int i = 0; i < Length; i++)
                    {
                        switch (n)
                        {
                        case 0:
                            P_atIB.SetMeanValue(i0, ResultsOfIntegration[i, 0]);
                            break;

                        case 1:
                            gradU_atIB.SetMeanValue(i0, ResultsOfIntegration[i, 0]);
                            break;

                        case 2:
                            gradUT_atIB.SetMeanValue(i0, ResultsOfIntegration[i, 0]);
                            break;

                        case 3:
                            circumference += ResultsOfIntegration[i, 0];
                            P_atIB.SetMeanValue(i0, P_atIB.GetMeanValue(i0) / ResultsOfIntegration[i, 0]);
                            gradU_atIB.SetMeanValue(i0, gradU_atIB.GetMeanValue(i0) / ResultsOfIntegration[i, 0]);
                            gradUT_atIB.SetMeanValue(i0, gradUT_atIB.GetMeanValue(i0) / ResultsOfIntegration[i, 0]);
                            break;

                        default:
                            throw new NotImplementedException();
                        }
                    }
                }

                                             ).Execute();
            }

            Console.WriteLine("Circle circumference: " + circumference);
        }
Example #21
0
        /// <summary>
        /// Calculates the Torque around the center of mass
        /// </summary>
        /// <param name="U"></param>
        /// <param name="P"></param>
        /// <param name="muA"></param>
        /// <param name="particleRadius"></param>
        /// <returns></returns>
        static public double GetTorque(VectorField <SinglePhaseField> U, SinglePhaseField P,
                                       LevelSetTracker LsTrk,
                                       double muA, double particleRadius)
        {
            var _LsTrk = LsTrk;
            int D      = _LsTrk.GridDat.SpatialDimension;
            var UA     = U.ToArray();

            //if (D > 2) throw new NotImplementedException("Currently only 2D cases supported");

            int RequiredOrder = U[0].Basis.Degree * 3;

            //if (RequiredOrder > agg.HMForder)
            //    throw new ArgumentException();

            Console.WriteLine("Torque coeff: {0}, order = {1}", LsTrk.CutCellQuadratureType, RequiredOrder);

            ConventionalDGField pA = null;
            double force           = new double();

            pA = P;

            ScalarFunctionEx ErrFunc = delegate(int j0, int Len, NodeSet Ns, MultidimensionalArray result) {
                int K = result.GetLength(1); // No nof Nodes
                MultidimensionalArray Grad_UARes = MultidimensionalArray.Create(Len, K, D, D);;
                MultidimensionalArray pARes      = MultidimensionalArray.Create(Len, K);

                // Evaluate tangential velocity to level-set surface
                var Normals = _LsTrk.DataHistories[0].Current.GetLevelSetNormals(Ns, j0, Len);

                for (int i = 0; i < D; i++)
                {
                    UA[i].EvaluateGradient(j0, Len, Ns, Grad_UARes.ExtractSubArrayShallow(-1, -1, i, -1), 0, 1);
                }

                pA.Evaluate(j0, Len, Ns, pARes);

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


                        // Calculate the torque around a circular particle with a given radius (Paper Wan and Turek 2005)

                        acc += pARes[j, k] * Normals[j, k, 0];
                        acc -= (2 * muA) * Grad_UARes[j, k, 0, 0] * Normals[j, k, 0];
                        acc -= (muA) * Grad_UARes[j, k, 0, 1] * Normals[j, k, 1];
                        acc -= (muA) * Grad_UARes[j, k, 1, 0] * Normals[j, k, 1];
                        acc *= -Normals[j, k, 1] * particleRadius;


                        acc2 += pARes[j, k] * Normals[j, k, 1];
                        acc2 -= (2 * muA) * Grad_UARes[j, k, 1, 1] * Normals[j, k, 1];
                        acc2 -= (muA) * Grad_UARes[j, k, 1, 0] * Normals[j, k, 0];
                        acc2 -= (muA) * Grad_UARes[j, k, 0, 1] * Normals[j, k, 0];
                        acc2 *= Normals[j, k, 0] * particleRadius;

                        result[j, k] = acc + acc2;
                    }
                }
            };

            var SchemeHelper = LsTrk.GetXDGSpaceMetrics(new[] { LsTrk.GetSpeciesId("A") }, RequiredOrder, 1).XQuadSchemeHelper;
            //var SchemeHelper = new XQuadSchemeHelper(_LsTrk, momentFittingVariant, _LsTrk.GetSpeciesId("A"));
            CellQuadratureScheme cqs = SchemeHelper.GetLevelSetquadScheme(0, _LsTrk.Regions.GetCutCellMask());

            CellQuadrature.GetQuadrature(new int[] { 1 }, _LsTrk.GridDat,
                                         cqs.Compile(_LsTrk.GridDat, RequiredOrder),
                                         delegate(int i0, int Length, QuadRule QR, MultidimensionalArray EvalResult) {
                ErrFunc(i0, Length, QR.Nodes, EvalResult.ExtractSubArrayShallow(-1, -1, 0));
            },
                                         delegate(int i0, int Length, MultidimensionalArray ResultsOfIntegration) {
                for (int i = 0; i < Length; i++)
                {
                    force += ResultsOfIntegration[i, 0];
                }
            }

                                         ).Execute();


            return(force);
        }
Example #22
0
        public AggregationGridBasis(Basis b, AggregationGrid ag)
        {
            using (new FuncTrace()) {
                if (!object.ReferenceEquals(b.GridDat, GetGridData(ag)))
                {
                    throw new ArgumentException("mismatch in grid data object.");
                }
                this.DGBasis = b;
                this.AggGrid = ag;
                int N = b.Length;

                int JAGG = ag.iLogicalCells.NoOfLocalUpdatedCells;
                CompositeBasis = new MultidimensionalArray[JAGG];

                for (int jAgg = 0; jAgg < JAGG; jAgg++)   // loop over agglomerated cells...
                {
                    var compCell = ag.iLogicalCells.AggregateCellToParts[jAgg];


                    if (compCell.Length == 1)
                    {
                        CompositeBasis[jAgg] = MultidimensionalArray.Create(1, N, N);
                        for (int n = 0; n < N; n++)
                        {
                            CompositeBasis[jAgg][0, n, n] = 1.0;
                        }
                    }
                    else
                    {
                        // compute extrapolation basis
                        // ===========================

                        int I = compCell.Length - 1;
                        int[,] CellPairs = new int[I, 2];

                        for (int i = 0; i < I; i++)
                        {
                            CellPairs[i, 0] = compCell[0];
                            CellPairs[i, 1] = compCell[i + 1];
                        }
                        var ExpolMtx = MultidimensionalArray.Create(I + 1, N, N);
                        b.GetExtrapolationMatrices(CellPairs, ExpolMtx.ExtractSubArrayShallow(new int[] { 1, 0, 0 }, new int[] { I, N - 1, N - 1 }));
                        for (int n = 0; n < N; n++)
                        {
                            ExpolMtx[0, n, n] = 1.0;
                        }

                        // compute mass matrix
                        // ===================

                        var MassMatrix = MultidimensionalArray.Create(N, N);
                        MassMatrix.Multiply(1.0, ExpolMtx, ExpolMtx, 0.0, "lm", "kim", "kil");


                        // change to orthonormal basis
                        // ===========================
                        MultidimensionalArray B = MultidimensionalArray.Create(N, N);
                        MassMatrix.SymmetricLDLInversion(B, default(double[]));


                        CompositeBasis[jAgg] = MultidimensionalArray.Create(ExpolMtx.Lengths);
                        CompositeBasis[jAgg].Multiply(1.0, ExpolMtx, B, 0.0, "imn", "imk", "kn");

                        // check
                        // =====
#if DEBUG
                        MassMatrix.Clear();
                        for (int k = 0; k <= I; k++)
                        {
                            for (int l = 0; l < N; l++)     // over rows of mass matrix ...
                            {
                                for (int m = 0; m < N; m++) // over columns of mass matrix ...

                                {
                                    double mass_lm = 0.0;

                                    for (int i = 0; i < N; i++)
                                    {
                                        mass_lm += CompositeBasis[jAgg][k, i, m] * CompositeBasis[jAgg][k, i, l];
                                    }

                                    MassMatrix[l, m] += mass_lm;
                                }
                            }
                        }

                        MassMatrix.AccEye(-1.0);
                        Debug.Assert(MassMatrix.InfNorm() < 1.0e-9);
#endif
                    }
                }
            }
        }
Example #23
0
        public void Init(MultigridOperator op)
        {
            int D     = op.Mapping.GridData.SpatialDimension;
            var M     = op.OperatorMatrix;
            var MgMap = op.Mapping;

            this.m_mgop = op;

            if (!M.RowPartitioning.EqualsPartition(MgMap.Partitioning))
            {
                throw new ArgumentException("Row partitioning mismatch.");
            }
            if (!M.ColPartition.EqualsPartition(MgMap.Partitioning))
            {
                throw new ArgumentException("Column partitioning mismatch.");
            }

            Uidx = MgMap.ProblemMapping.GetSubvectorIndices(true, D.ForLoop(i => i));
            Pidx = MgMap.ProblemMapping.GetSubvectorIndices(true, D);

            int Upart = Uidx.Length;
            int Ppart = Pidx.Length;

            ConvDiff = new MsrMatrix(Upart, Upart, 1, 1);
            pGrad    = new MsrMatrix(Upart, Ppart, 1, 1);
            divVel   = new MsrMatrix(Ppart, Upart, 1, 1);
            var PxP = new MsrMatrix(Ppart, Ppart, 1, 1);

            M.AccSubMatrixTo(1.0, ConvDiff, Uidx, default(int[]), Uidx, default(int[]));
            M.AccSubMatrixTo(1.0, pGrad, Uidx, default(int[]), Pidx, default(int[]));
            M.AccSubMatrixTo(1.0, divVel, Pidx, default(int[]), Uidx, default(int[]));
            M.AccSubMatrixTo(1.0, PxP, Pidx, default(int[]), Pidx, default(int[]));

            Mtx = M;

            int L = M.RowPartitioning.LocalLength;

            int i0 = Mtx.RowPartitioning.i0;

            P = new MsrMatrix(Mtx);
            P.Clear();

            // Debugging output
            //ConvDiff.SaveToTextFileSparse("ConvDiff");
            //divVel.SaveToTextFileSparse("divVel");
            //pGrad.SaveToTextFileSparse("pGrad");
            //PxP.SaveToTextFileSparse("PxP");


            velMassMatrix = new MsrMatrix(Upart, Upart, 1, 1);
            op.MassMatrix.AccSubMatrixTo(1.0, velMassMatrix, Uidx, default(int[]), Uidx, default(int[]));

            switch (SchurOpt)
            {
            case SchurOptions.exact:
            {
                // Building complete Schur and Approximate Schur
                MultidimensionalArray Poisson       = MultidimensionalArray.Create(Pidx.Length, Pidx.Length);
                MultidimensionalArray SchurConvPart = MultidimensionalArray.Create(Pidx.Length, Pidx.Length);
                MultidimensionalArray Schur         = MultidimensionalArray.Create(Pidx.Length, Pidx.Length);
                using (BatchmodeConnector bmc = new BatchmodeConnector())
                {
                    bmc.PutSparseMatrix(ConvDiff, "ConvDiff");
                    bmc.PutSparseMatrix(velMassMatrix, "MassMatrix");
                    bmc.PutSparseMatrix(divVel, "divVel");
                    bmc.PutSparseMatrix(pGrad, "pGrad");
                    bmc.Cmd("Qdiag = diag(diag(MassMatrix))");
                    bmc.Cmd("invT= inv(Qdiag)");
                    bmc.Cmd("Poisson = full(invT)*pGrad");
                    bmc.Cmd("ConvPart = ConvDiff*Poisson");
                    bmc.Cmd("ConvPart= full(invT)*ConvPart");
                    bmc.Cmd("ConvPart= divVel*ConvPart");
                    bmc.Cmd("Poisson = divVel*Poisson");
                    bmc.Cmd("ConvDiffInv = inv(full(ConvDiff))");
                    bmc.Cmd("Schur = divVel*ConvDiffInv");
                    bmc.Cmd("Schur = Schur*pGrad");
                    bmc.GetMatrix(Poisson, "Poisson");
                    bmc.GetMatrix(SchurConvPart, "ConvPart");
                    bmc.GetMatrix(Schur, "-Schur");
                    bmc.Execute(false);
                }
                PoissonMtx_T = Poisson.ToMsrMatrix();
                PoissonMtx_H = Poisson.ToMsrMatrix();
                SchurConvMtx = SchurConvPart.ToMsrMatrix();
                SchurMtx     = Schur.ToMsrMatrix();
                SchurMtx.Acc(PxP, 1);

                ConvDiff.AccSubMatrixTo(1.0, P, default(int[]), Uidx, default(int[]), Uidx);
                pGrad.AccSubMatrixTo(1.0, P, default(int[]), Uidx, default(int[]), Pidx);
                SchurMtx.AccSubMatrixTo(1.0, P, default(int[]), Pidx, default(int[]), Pidx);
                return;
            }

            case SchurOptions.decoupledApprox:
            {
                // Do assembly for approximate Schur inverse
                invVelMassMatrix = velMassMatrix.CloneAs();
                invVelMassMatrix.Clear();
                invVelMassMatrixSqrt = invVelMassMatrix.CloneAs();
                for (int i = velMassMatrix.RowPartitioning.i0; i < velMassMatrix.RowPartitioning.iE; i++)
                {
                    if (ApproxScaling)
                    {
                        invVelMassMatrix.SetDiagonalElement(i, 1 / (velMassMatrix[i, i]));
                        invVelMassMatrixSqrt.SetDiagonalElement(i, 1 / (Math.Sqrt(velMassMatrix[i, i])));
                    }
                    else
                    {
                        invVelMassMatrix.SetDiagonalElement(i, 1);
                        invVelMassMatrixSqrt.SetDiagonalElement(i, 1);
                    }
                }

                //invVelMassMatrix.SaveToTextFileSparse("invVelMassMatrix");
                //velMassMatrix.SaveToTextFileSparse("velMassMatrix");


                //ConvDiffPoissonMtx = MsrMatrix.Multiply(ConvDiff, pGrad);
                //ConvDiffPoissonMtx = MsrMatrix.Multiply(divVel, ConvDiffPoissonMtx);

                // Inverse of mass matrix in Matlab
                //MultidimensionalArray temp = MultidimensionalArray.Create(Uidx.Length, Uidx.Length);
                //using (BatchmodeConnector bmc = new BatchmodeConnector())
                //{
                //    bmc.PutSparseMatrix(velMassMatrix, "velMassMatrix");
                //    bmc.Cmd("invVelMassMatrix = inv(full(velMassMatrix))");
                //    bmc.GetMatrix(temp, "invVelMassMatrix");
                //    bmc.Execute(false);
                //}
                //invVelMassMatrix = temp.ToMsrMatrix();

                //ConvDiffPoissonMtx = MsrMatrix.Multiply(ConvDiffPoissonMtx, PoissonMtx);
                //ConvDiffPoissonMtx = MsrMatrix.Multiply(PoissonMtx, ConvDiffPoissonMtx);

                //ConvDiff.AccSubMatrixTo(1.0, P, default(int[]), Uidx, default(int[]), Uidx);
                //pGrad.AccSubMatrixTo(1.0, P, default(int[]), Uidx, default(int[]), Pidx);
                //ConvDiffPoissonMtx.AccSubMatrixTo(1.0, P, default(int[]), Pidx, default(int[]), Pidx);

                //op.MassMatrix.SaveToTextFileSparse("MassMatrix");
                //velMassMatrix.SaveToTextFileSparse("velMassMatrix2");


                // Possion scaled by inverse of the velocity mass matrix
                PoissonMtx_T = MsrMatrix.Multiply(invVelMassMatrix, pGrad);
                PoissonMtx_T = MsrMatrix.Multiply(divVel, PoissonMtx_T);
                ////PoissonMtx_T.Acc(PxP, 1); // p.379

                // Poisson scaled by sqrt of inverse of velocity mass matrix
                PoissonMtx_H = MsrMatrix.Multiply(invVelMassMatrixSqrt, pGrad);
                PoissonMtx_H = MsrMatrix.Multiply(divVel, PoissonMtx_H);
                //PoissonMtx_H.Acc(PxP, 1); // p.379
                return;
            }

            case SchurOptions.SIMPLE:
            {
                var invdiag_ConvDiff = ConvDiff.CloneAs();
                invdiag_ConvDiff.Clear();
                for (int i = ConvDiff.RowPartitioning.i0; i < ConvDiff.RowPartitioning.iE; i++)
                {
                    invdiag_ConvDiff[i, i] = 1 / ConvDiff[i, i];
                }

                simpleSchur = MsrMatrix.Multiply(invdiag_ConvDiff, pGrad);
                simpleSchur = MsrMatrix.Multiply(divVel, simpleSchur);

                return;
            }

            default:
                throw new NotImplementedException("SchurOption");
            }


            //var ConvDiffInvMtx = ConvDiffInv.ToMsrMatrix();


            //// x= inv(P)*b !!!!! To be done with approximate Inverse
            // P.SpMV(1, B, 0, X);
        }
Example #24
0
        protected MultidimensionalArray GaußAnsatzRHS(DivergenceFreeBasis TestBasis, CellBoundaryQuadratureScheme cellBndScheme, CellMask _mask, int order)
        {
            var _Context = this.tracker.GridDat;
            int D        = this.tracker.GridDat.Grid.SpatialDimension;
            int N        = TestBasis.Count;
            var coordSys = CoordinateSystem.Reference;
            var LsTrk    = this.tracker;
            int Nrhs     = _mask.NoOfItemsLocally;

            Debug.Assert(N % D == 0);
            N /= D;
            MultidimensionalArray RHS = MultidimensionalArray.Create(N, Nrhs);

            var splx      = this.Kref;
            int NoOfFaces = splx.NoOfFaces;
            //var normals = _Context.GridDat.Normals;
            CellBoundaryQuadrature <CellBoundaryQuadRule> qBnd = null;

            int jSgrd = 0;

            qBnd = CellBoundaryQuadrature <CellBoundaryQuadRule> .GetQuadrature(new int[] { N },
                                                                                _Context, cellBndScheme.Compile(_Context, order),
                                                                                delegate(int i0, int Length, CellBoundaryQuadRule QR, MultidimensionalArray EvalResult) { // Evaluate
                NodeSet Nodes = QR.Nodes;
                MultidimensionalArray BasisValues;
                if (coordSys == CoordinateSystem.Physical)
                {
                    //BasisValues = TestBasis.CellEval(Nodes, i0, Length);
                    throw new NotImplementedException("todo");
                }
                else if (coordSys == CoordinateSystem.Reference)
                {
                    BasisValues = TestBasis.Values.GetValues(Nodes);
                }
                else
                {
                    throw new NotImplementedException();
                }

                for (int i = 0; i < Length; i++)       // loop over cells

                {
                    CellBoundaryQuadRule cR = qBnd.CurrentRule;
                    int[] NodesPerEdge      = cR.NumbersOfNodesPerFace;
                    Debug.Assert(object.ReferenceEquals(splx, cR.RefElement));

                    int iNode = 0;

                    Debug.Assert(NoOfFaces == NodesPerEdge.Length);
                    for (int e = 0; e < NoOfFaces; e++)              // loop over the faces of the cell
                    {
                        for (int _n = 0; _n < NodesPerEdge[e]; _n++) // loop over nodes in one edge
                        {
                            for (int n = 0; n < N; n++)              // loop over Test polynomials (the same as the basis polynomials)
                            {
                                double acc = 0;
                                for (int d = 0; d < D; d++)       // loop over spatial directions

                                {
                                    if (coordSys == CoordinateSystem.Physical)
                                    {
                                        throw new NotImplementedException("todo");
                                        //int q = _Context.GridDat.LocalCellIndexToEdges[i+i0, e];
                                        //int iEdge = Math.Abs(q) - 1;
                                        //double Nsign = Math.Sign(q);
                                        //double Nd = normals[iEdge, d];
                                        //EvalResult[i, iNode, n, d] = BasisValues[i, iNode, n]*Nd*Nsign;
                                    }
                                    else
                                    {
                                        Debug.Assert(coordSys == CoordinateSystem.Reference);
                                        double Nd = splx.FaceNormals[e, d];
                                        //Debug.Assert(Nd == normals[iEdge, d]*Nsign);
                                        acc += BasisValues[iNode, n *D + d] * Nd;
                                    }
                                }
                                EvalResult[i, iNode, n] = acc;
                            }

                            iNode++;
                        }
                    }
                    Debug.Assert(iNode == EvalResult.GetLength(1));
                }
            },
                                                                                delegate(int i0, int Length, MultidimensionalArray ResultsOfIntegration) { // SaveIntegrationResults
                for (int i = 0; i < Length; i++)
                {
                    var ResPart = RHS.ExtractSubArrayShallow(new int[] { 0, jSgrd }, new int[] { N - 1, jSgrd - 1 });

                    for (int e = 0; e < NoOfFaces; e++)
                    {
                        var ip = ResultsOfIntegration.ExtractSubArrayShallow(new int[] { i, e, 0 }, new int[] { i - 1, e - 1, N - 1 });
                        ResPart.Acc(1.0, ip);
                    }
                    jSgrd++;
                }
            },
                                                                                cs : coordSys);

            qBnd.Execute();


            return(RHS);
        }
Example #25
0
        /// <summary>
        /// modifies a matrix <paramref name="Mtx"/> and a right-hand-side <paramref name="rhs"/>
        /// in order to fix the pressure at some reference point
        /// </summary>
        /// <param name="map">row mapping for <paramref name="Mtx"/> as well as <paramref name="rhs"/></param>
        /// <param name="iVar">the index of the pressure variable in the mapping <paramref name="map"/>.</param>
        /// <param name="LsTrk"></param>
        /// <param name="Mtx"></param>
        /// <param name="rhs"></param>
        static public void SetPressureReferencePoint <T>(UnsetteledCoordinateMapping map, int iVar, LevelSetTracker LsTrk, BlockMsrMatrix Mtx, T rhs)
            where T : IList <double>
        {
            using (new FuncTrace()) {
                var GridDat = map.GridDat;

                if (rhs.Count != map.LocalLength)
                {
                    throw new ArgumentException();
                }
                if (!Mtx.RowPartitioning.EqualsPartition(map) || !Mtx.ColPartition.EqualsPartition(map))
                {
                    throw new ArgumentException();
                }

                Basis PressureBasis = (Basis)map.BasisS[iVar];
                int   D             = GridDat.SpatialDimension;

                long GlobalID, GlobalCellIndex;
                bool IsInside, onthisProc;
                GridDat.LocatePoint(new double[D], out GlobalID, out GlobalCellIndex, out IsInside, out onthisProc, LsTrk.Regions.GetCutCellSubGrid().VolumeMask.Complement());

                int iRowGl = -111;
                if (onthisProc)
                {
                    int jCell = (int)GlobalCellIndex - GridDat.CellPartitioning.i0;


                    NodeSet CenterNode = new NodeSet(GridDat.iGeomCells.GetRefElement(jCell), new double[D]);
                    MultidimensionalArray LevSetValues = LsTrk.DataHistories[0].Current.GetLevSetValues(CenterNode, jCell, 1);;


                    MultidimensionalArray CenterNodeGlobal = MultidimensionalArray.Create(1, D);
                    GridDat.TransformLocal2Global(CenterNode, CenterNodeGlobal, jCell);
                    //Console.WriteLine("Pressure Ref Point @( {0:0.###E-00} | {1:0.###E-00} )", CenterNodeGlobal[0,0], CenterNodeGlobal[0,1]);


                    LevelSetSignCode  scode = LevelSetSignCode.ComputeLevelSetBytecode(LevSetValues[0, 0]);
                    ReducedRegionCode rrc;
                    int No   = LsTrk.Regions.GetNoOfSpecies(jCell, out rrc);
                    int iSpc = LsTrk.GetSpeciesIndex(rrc, scode);

                    iRowGl = (int)map.GlobalUniqueCoordinateIndex_FromGlobal(iVar, GlobalCellIndex, 0);
                }
                iRowGl = iRowGl.MPIMax();


                // clear row
                // ---------
                if (onthisProc)
                {
                    // ref. cell is on local MPI process
                    int jCell = (int)GlobalCellIndex - GridDat.CellPartitioning.i0;

                    ReducedRegionCode rrc;
                    int NoOfSpc = LsTrk.Regions.GetNoOfSpecies(jCell, out rrc);

                    // set matrix row to identity
                    Mtx.ClearRow(iRowGl);
                    Mtx.SetDiagonalElement(iRowGl, 1.0);


                    // clear RHS
                    int iRow = iRowGl - Mtx.RowPartitioning.i0;
                    rhs[iRow] = 0;
                }

                // clear column
                // ------------
                {
                    for (int i = Mtx.RowPartitioning.i0; i < Mtx.RowPartitioning.iE; i++)
                    {
                        if (i != iRowGl)
                        {
                            Mtx[i, iRowGl] = 0;
                        }
                    }
                }
            }
        }
Example #26
0
        MultidimensionalArray StokesAnsatzMatrix(Basis TestBasis, NodeSet surfaceNodes, int jCell)
        {
            int N         = TestBasis.Length;
            int NoOfNodes = surfaceNodes.GetLength(0);
            int D         = surfaceNodes.GetLength(1);
            var GridDat   = this.tracker.GridDat;

            Debug.Assert(D == GridDat.SpatialDimension);
            int iKref    = GridDat.Cells.GetRefElementIndex(jCell);
            var scalings = GridDat.Cells.JacobiDet;
            int iLevSet  = this.LevelSetIndex;

            if (!GridDat.Cells.IsCellAffineLinear(jCell))
            {
                throw new NotSupportedException();
            }


            //var Phi = TestBasis.Evaluate(0);              // reference
            //var GradPhi = TestBasis.EvaluateGradient(0);  // reference
            var Phi     = TestBasis.CellEval(surfaceNodes, jCell, 1).ExtractSubArrayShallow(0, -1, -1);              // physical
            var GradPhi = TestBasis.CellEvalGradient(surfaceNodes, jCell, 1).ExtractSubArrayShallow(0, -1, -1, -1);  // physical

            //var LevsetNormal = this.LsTrk.GetLevelSetReferenceNormals(iLevSet, 0, jCell, 1);  // reference
            //var Curvature = this.LsTrk.GetLevelSetReferenceCurvature(iLevSet, 0, jCell, 1);   // reference
            var LevsetNormal = this.LevelSetData.GetLevelSetNormals(surfaceNodes, jCell, 1).ExtractSubArrayShallow(0, -1, -1); // physical
            var Curvature    = MultidimensionalArray.Create(1, NoOfNodes);                                                     // physical

            ((LevelSet)(this.tracker.LevelSets[iLevSet])).EvaluateTotalCurvature(jCell, 1, surfaceNodes, Curvature);           // physical

            var Coeffs = MultidimensionalArray.Create(D, N, NoOfNodes);

            if (D == 2)
            {
                for (int k = 0; k < NoOfNodes; k++)   // loop over nodes
                {
                    double Nx    = LevsetNormal[k, 0];
                    double Ny    = LevsetNormal[k, 1];
                    double kappa = Curvature[0, k];


                    double Prj_11 = 1.0 - Nx * Nx, Prj_12 = -Nx * Ny,
                           Prj_21 = -Ny * Nx, Prj_22 = 1.0 - Ny * Ny;

                    for (int n = 0; n < N; n++)
                    {
                        double Phi_kn     = Phi[k, n];
                        double dPhi_dx_kn = GradPhi[k, n, 0];
                        double dPhi_dy_kn = GradPhi[k, n, 1];

                        Coeffs[0, n, k] = -Phi_kn * kappa * Nx + Prj_11 * dPhi_dx_kn + Prj_12 * dPhi_dy_kn;
                        Coeffs[1, n, k] = -Phi_kn * kappa * Ny + Prj_21 * dPhi_dx_kn + Prj_22 * dPhi_dy_kn;
                    }
                }
            }
            else if (D == 3)
            {
                throw new NotImplementedException("to do.");
            }
            else
            {
                throw new NotSupportedException("Unknown spatial dimension.");
            }

            Coeffs.Scale(scalings[jCell]);  // physical

            return(Coeffs.ResizeShallow(N * D, NoOfNodes));
        }
Example #27
0
        static public double[] GetParticleForces(VectorField <SinglePhaseField> U, SinglePhaseField P,
                                                 LevelSetTracker LsTrk,
                                                 double muA)
        {
            int D = LsTrk.GridDat.SpatialDimension;
            // var UA = U.Select(u => u.GetSpeciesShadowField("A")).ToArray();
            var UA = U.ToArray();

            int RequiredOrder = U[0].Basis.Degree * 3 + 2;

            //int RequiredOrder = LsTrk.GetXQuadFactoryHelper(momentFittingVariant).GetCachedSurfaceOrders(0).Max();
            //Console.WriteLine("Order reduction: {0} -> {1}", _RequiredOrder, RequiredOrder);

            //if (RequiredOrder > agg.HMForder)
            //    throw new ArgumentException();

            Console.WriteLine("Forces coeff: {0}, order = {1}", LsTrk.CutCellQuadratureType, RequiredOrder);


            ConventionalDGField pA = null;

            //pA = P.GetSpeciesShadowField("A");
            pA = P;

            double[] forces = new double[D];
            for (int d = 0; d < D; d++)
            {
                ScalarFunctionEx ErrFunc = delegate(int j0, int Len, NodeSet Ns, MultidimensionalArray result) {
                    int K = result.GetLength(1); // No nof Nodes
                    MultidimensionalArray Grad_UARes = MultidimensionalArray.Create(Len, K, D, D);;
                    MultidimensionalArray pARes      = MultidimensionalArray.Create(Len, K);

                    // Evaluate tangential velocity to level-set surface
                    var Normals = LsTrk.DataHistories[0].Current.GetLevelSetNormals(Ns, j0, Len);


                    for (int i = 0; i < D; i++)
                    {
                        UA[i].EvaluateGradient(j0, Len, Ns, Grad_UARes.ExtractSubArrayShallow(-1, -1, i, -1), 0, 1);
                    }

                    pA.Evaluate(j0, Len, Ns, pARes);

                    if (LsTrk.GridDat.SpatialDimension == 2)
                    {
                        for (int j = 0; j < Len; j++)
                        {
                            for (int k = 0; k < K; k++)
                            {
                                double acc = 0.0;

                                // pressure
                                switch (d)
                                {
                                case 0:
                                    acc += pARes[j, k] * Normals[j, k, 0];
                                    acc -= (2 * muA) * Grad_UARes[j, k, 0, 0] * Normals[j, k, 0];
                                    acc -= (muA) * Grad_UARes[j, k, 0, 1] * Normals[j, k, 1];
                                    acc -= (muA) * Grad_UARes[j, k, 1, 0] * Normals[j, k, 1];
                                    break;

                                case 1:
                                    acc += pARes[j, k] * Normals[j, k, 1];
                                    acc -= (2 * muA) * Grad_UARes[j, k, 1, 1] * Normals[j, k, 1];
                                    acc -= (muA) * Grad_UARes[j, k, 1, 0] * Normals[j, k, 0];
                                    acc -= (muA) * Grad_UARes[j, k, 0, 1] * Normals[j, k, 0];
                                    break;

                                default:
                                    throw new NotImplementedException();
                                }

                                result[j, k] = acc;
                            }
                        }
                    }
                    else
                    {
                        for (int j = 0; j < Len; j++)
                        {
                            for (int k = 0; k < K; k++)
                            {
                                double acc = 0.0;

                                // pressure
                                switch (d)
                                {
                                case 0:
                                    acc += pARes[j, k] * Normals[j, k, 0];
                                    acc -= (2 * muA) * Grad_UARes[j, k, 0, 0] * Normals[j, k, 0];
                                    acc -= (muA) * Grad_UARes[j, k, 0, 2] * Normals[j, k, 2];
                                    acc -= (muA) * Grad_UARes[j, k, 0, 1] * Normals[j, k, 1];
                                    acc -= (muA) * Grad_UARes[j, k, 1, 0] * Normals[j, k, 1];
                                    acc -= (muA) * Grad_UARes[j, k, 2, 0] * Normals[j, k, 2];
                                    break;

                                case 1:
                                    acc += pARes[j, k] * Normals[j, k, 1];
                                    acc -= (2 * muA) * Grad_UARes[j, k, 1, 1] * Normals[j, k, 1];
                                    acc -= (muA) * Grad_UARes[j, k, 1, 2] * Normals[j, k, 2];
                                    acc -= (muA) * Grad_UARes[j, k, 1, 0] * Normals[j, k, 0];
                                    acc -= (muA) * Grad_UARes[j, k, 0, 1] * Normals[j, k, 0];
                                    acc -= (muA) * Grad_UARes[j, k, 2, 1] * Normals[j, k, 2];
                                    break;

                                case 2:
                                    acc += pARes[j, k] * Normals[j, k, 2];
                                    acc -= (2 * muA) * Grad_UARes[j, k, 2, 2] * Normals[j, k, 2];
                                    acc -= (muA) * Grad_UARes[j, k, 2, 0] * Normals[j, k, 0];
                                    acc -= (muA) * Grad_UARes[j, k, 2, 1] * Normals[j, k, 1];
                                    acc -= (muA) * Grad_UARes[j, k, 0, 2] * Normals[j, k, 0];
                                    acc -= (muA) * Grad_UARes[j, k, 1, 2] * Normals[j, k, 1];
                                    break;

                                default:
                                    throw new NotImplementedException();
                                }

                                result[j, k] = acc;
                            }
                        }
                    }
                };

                var SchemeHelper = LsTrk.GetXDGSpaceMetrics(new[] { LsTrk.GetSpeciesId("A") }, RequiredOrder, 1).XQuadSchemeHelper;
                //var SchemeHelper = new XQuadSchemeHelper(LsTrk, momentFittingVariant, );
                CellQuadratureScheme cqs = SchemeHelper.GetLevelSetquadScheme(0, LsTrk.Regions.GetCutCellMask());

                CellQuadrature.GetQuadrature(new int[] { 1 }, LsTrk.GridDat,
                                             cqs.Compile(LsTrk.GridDat, RequiredOrder), //  agg.HMForder),
                                             delegate(int i0, int Length, QuadRule QR, MultidimensionalArray EvalResult) {
                    ErrFunc(i0, Length, QR.Nodes, EvalResult.ExtractSubArrayShallow(-1, -1, 0));
                },
                                             delegate(int i0, int Length, MultidimensionalArray ResultsOfIntegration) {
                    for (int i = 0; i < Length; i++)
                    {
                        forces[d] += ResultsOfIntegration[i, 0];
                    }
                }
                                             ).Execute();
            }

            for (int i = 0; i < D; i++)
            {
                forces[i] = MPI.Wrappers.MPIExtensions.MPISum(forces[i]);
            }

            return(forces);
        }
Example #28
0
        MultidimensionalArray StokesAnsatzRHS(Basis TestBasis, CellBoundaryQuadratureScheme cellBndSchme, CellMask _mask, int order)
        {
            var GridDat = this.tracker.GridDat;
            CellBoundaryQuadrature <CellBoundaryQuadRule> qBnd = null;

            int N = TestBasis.Length;
            int D = GridDat.SpatialDimension;
            MultidimensionalArray RHS = MultidimensionalArray.Create(D, N, _mask.NoOfItemsLocally);

            double[] CellN       = new double[D]; // cell normal
            double[] SurfN       = new double[D]; // level-set normal
            double[] OutwardTang = new double[D]; // level-set tangent, outward of cell

            if (D != 2)
            {
                throw new NotSupportedException("Currently only supported for spatial dimension of 2.");
            }

            //MultidimensionalArray Nudes = null;
            int jSgrd = 0;

            qBnd = CellBoundaryQuadrature <CellBoundaryQuadRule> .GetQuadrature(new int[] { D, N },
                                                                                GridDat, cellBndSchme.Compile(GridDat, order),
                                                                                delegate(int i0, int Length, CellBoundaryQuadRule NS, MultidimensionalArray EvalResult) { // Evaluate
                //MultidimensionalArray BasisValues = TestBasis.Evaluate(0);                 // reference
                //var LSNormals = LsTrk.GetLevelSetReferenceNormals(iLevSet, 0, i0, Length); // reference
                MultidimensionalArray BasisValues = TestBasis.CellEval(NS.Nodes, i0, Length);                   // physical
                MultidimensionalArray LSNormals   = this.LevelSetData.GetLevelSetNormals(NS.Nodes, i0, Length); // physical

                for (int i = 0; i < Length; i++)                                                                // loop over cells
                //if(i0 + i == 1) {
                //    EvalResult.ExtractSubArrayShallow(i, -1, -1, -1).Clear();
                //    continue;
                //}

                {
                    CellBoundaryQuadRule cR = qBnd.CurrentRule;
                    int[] NodesPerEdge      = cR.NumbersOfNodesPerFace;
                    var Kref      = cR.RefElement;
                    int NoOfFaces = Kref.NoOfFaces;
                    int iNode     = 0;

                    Debug.Assert(NoOfFaces == NodesPerEdge.Length);
                    for (int e = 0; e < NoOfFaces; e++)       // loop over the faces of the cell

                    {
                        if (NodesPerEdge[e] <= 0)
                        {
                            continue;
                        }

                        // reference:
                        //for (int d = 0; d < D; d++) {
                        //    CellN[d] = Kref.FaceNormals[e, d];
                        //}
                        // ~~~~

                        // physical:
                        var FaceNodes   = new NodeSet(Kref, cR.Nodes.ExtractSubArrayShallow(new int[] { iNode, 0 }, new int[] { iNode + NodesPerEdge[e] - 1, D - 1 }));
                        var FaceNormals = MultidimensionalArray.Create(NodesPerEdge[e], D);
                        GridDat.Edges.GetNormalsForCell(FaceNodes, i0, e, FaceNormals);
                        // ~~~~

                        for (int _n = 0; _n < NodesPerEdge[e]; _n++)       // loop over nodes in one edge
                        {
                            for (int d = 0; d < D; d++)
                            {
                                SurfN[d] = LSNormals[i, iNode, d];
                                CellN[d] = FaceNormals[_n, d];     // physical
                            }
                            tangente(SurfN, CellN, OutwardTang);

                            for (int n = 0; n < N; n++)                                                     // loop over Test polynomials (the same as the basis polynomials)
                            {
                                for (int d = 0; d < D; d++)                                                 // loop over spatial direction
                                {
                                    EvalResult[i, iNode, d, n] = BasisValues[i, iNode, n] * OutwardTang[d]; // physical
                                    //EvalResult[i, iNode, d, n] = BasisValues[iNode, n]*OutwardTang[d]; // reference
                                }
                            }

                            iNode++;
                        }
                    }
                    Debug.Assert(iNode == EvalResult.GetLength(1));
                }
            },
                                                                                delegate(int i0, int Length, MultidimensionalArray ResultsOfIntegration) { // SaveIntegrationResults
                for (int i = 0; i < Length; i++)
                {
                    var ResPart   = RHS.ExtractSubArrayShallow(new int[] { 0, 0, jSgrd }, new int[] { D - 1, N - 1, jSgrd - 1 });
                    int NoOfFaces = ResultsOfIntegration.GetLength(1);

                    for (int e = 0; e < NoOfFaces; e++)
                    {
                        var ip = ResultsOfIntegration.ExtractSubArrayShallow(new int[] { i, e, 0, 0 }, new int[] { i - 1, e - 1, D - 1, N - 1 });
                        ResPart.Acc(1.0, ip);
                    }
                    jSgrd++;
                }
            },
                                                                                cs : CoordinateSystem.Physical);

            qBnd.Execute();

            var ret = RHS.ResizeShallow(N * D, _mask.NoOfItemsLocally);

            return(ret);
        }
Example #29
0
        /// <summary>
        /// Returns an array with points on the surface of the particle.
        /// </summary>
        /// <param name="hMin">
        /// Minimal cell length. Used to specify the number of surface points.
        /// </param>
        override public MultidimensionalArray GetSurfacePoints(double dAngle, double searchAngle, int subParticleID)
        {
            if (SpatialDim != 2)
            {
                throw new NotImplementedException("Only two dimensions are supported.");
            }
            double angle = Motion.GetAngle(0);
            int    noOfCurrentPointAndNeighbours = 3;
            MultidimensionalArray SurfacePoints  = MultidimensionalArray.Create(noOfCurrentPointAndNeighbours, SpatialDim);

            for (int j = 0; j < noOfCurrentPointAndNeighbours; j++)
            {
                double verticalAxis;
                double horizontalAxis;
                double currentAngle = searchAngle + dAngle * (j - 1);
                if (currentAngle < 0)
                {
                    currentAngle += 2 * Math.PI;
                }
                if (currentAngle > 2 * Math.PI)
                {
                    currentAngle -= 2 * Math.PI;
                }
                if (searchAngle + dAngle * (j - 1) <= Math.PI / 2)
                {
                    verticalAxis   = m_Length * Math.Pow(Math.Abs(Math.Cos(searchAngle + dAngle * (j - 1))), 2 / m_Exponent);
                    horizontalAxis = m_Thickness * Math.Pow(Math.Abs(Math.Sin(searchAngle + dAngle * (j - 1))), 2 / m_Exponent);
                }
                else if (searchAngle + dAngle * (j - 1) > Math.PI / 2 && searchAngle + dAngle * (j - 1) <= Math.PI)
                {
                    verticalAxis = -m_Length *Math.Pow(Math.Abs(Math.Cos(searchAngle + dAngle * (j - 1))), 2 / m_Exponent);

                    horizontalAxis = m_Thickness * Math.Pow(Math.Abs(Math.Sin(searchAngle + dAngle * (j - 1))), 2 / m_Exponent);
                }
                else if (searchAngle + dAngle * (j - 1) > Math.PI && searchAngle + dAngle * (j - 1) <= 3 * Math.PI / 2)
                {
                    verticalAxis = -m_Length *Math.Pow(Math.Abs(Math.Cos(searchAngle + dAngle * (j - 1))), 2 / m_Exponent);

                    horizontalAxis = -m_Thickness *Math.Pow(Math.Abs(Math.Sin(searchAngle + dAngle * (j - 1))), 2 / m_Exponent);
                }
                else
                {
                    verticalAxis   = m_Length * Math.Pow(Math.Abs(Math.Cos(searchAngle + dAngle * (j - 1))), 2 / m_Exponent);
                    horizontalAxis = -m_Thickness *Math.Pow(Math.Abs(Math.Sin(searchAngle + dAngle * (j - 1))), 2 / m_Exponent);
                }
                SurfacePoints[j, 0] = (verticalAxis * Math.Cos(angle) - horizontalAxis * Math.Sin(angle));
                SurfacePoints[j, 1] = (verticalAxis * Math.Sin(angle) + horizontalAxis * Math.Cos(angle));
            }
            //int noOfCurrentPointWithNeighbours = 3;
            //MultidimensionalArray SurfacePoints = MultidimensionalArray.Create(noOfCurrentPointWithNeighbours, SpatialDim);
            //for (int j = 0; j < QuarterSurfacePoints; j++) {
            //    SurfacePoints[0, j, 0] = (Math.Pow(Math.Cos(Infinitisemalangle[j]), 2 / m_Exponent) * m_Length * Math.Cos(Motion.GetAngle(0)) - Math.Pow(Math.Sin(Infinitisemalangle[j]), 2 / m_Exponent) * m_Thickness * Math.Sin(Motion.GetAngle(0))) + Motion.GetPosition(0)[0];
            //    SurfacePoints[0, j, 1] = (Math.Pow(Math.Cos(Infinitisemalangle[j]), 2 / m_Exponent) * m_Length * Math.Sin(Motion.GetAngle(0)) + Math.Pow(Math.Sin(Infinitisemalangle[j]), 2 / m_Exponent) * m_Thickness * Math.Cos(Motion.GetAngle(0))) + Motion.GetPosition(0)[1];
            //    SurfacePoints[0, 2 * QuarterSurfacePoints + j - 1, 0] = (-(Math.Pow(Math.Cos(Infinitisemalangle[j]), 2 / m_Exponent) * m_Length) * Math.Cos(Motion.GetAngle(0)) + Math.Pow(Math.Sin(Infinitisemalangle[j]), 2 / m_Exponent) * m_Thickness * Math.Sin(Motion.GetAngle(0))) + Motion.GetPosition(0)[0];
            //    SurfacePoints[0, 2 * QuarterSurfacePoints + j - 1, 1] = (-(Math.Pow(Math.Cos(Infinitisemalangle[j]), 2 / m_Exponent) * m_Length) * Math.Sin(Motion.GetAngle(0)) - Math.Pow(Math.Sin(Infinitisemalangle[j]), 2 / m_Exponent) * m_Thickness * Math.Cos(Motion.GetAngle(0))) + Motion.GetPosition(0)[1]; ;
            //}
            //for (int j = 1; j < QuarterSurfacePoints; j++) {
            //    SurfacePoints[0, 2 * QuarterSurfacePoints - j - 1, 0] = (-(Math.Pow(Math.Cos(Infinitisemalangle[j]), 2 / m_Exponent) * m_Length) * Math.Cos(Motion.GetAngle(0)) - Math.Pow(Math.Sin(Infinitisemalangle[j]), 2 / m_Exponent) * m_Thickness * Math.Sin(Motion.GetAngle(0))) + Motion.GetPosition(0)[0];
            //    SurfacePoints[0, 2 * QuarterSurfacePoints - j - 1, 1] = (-(Math.Pow(Math.Cos(Infinitisemalangle[j]), 2 / m_Exponent) * m_Length) * Math.Sin(Motion.GetAngle(0)) + Math.Pow(Math.Sin(Infinitisemalangle[j]), 2 / m_Exponent) * m_Thickness * Math.Cos(Motion.GetAngle(0))) + Motion.GetPosition(0)[1];
            //    SurfacePoints[0, 4 * QuarterSurfacePoints - j - 2, 0] = (Math.Pow(Math.Cos(Infinitisemalangle[j]), 2 / m_Exponent) * m_Length * Math.Cos(Motion.GetAngle(0)) + Math.Pow(Math.Sin(Infinitisemalangle[j]), 2 / m_Exponent) * m_Thickness * Math.Sin(Motion.GetAngle(0))) + Motion.GetPosition(0)[0];
            //    SurfacePoints[0, 4 * QuarterSurfacePoints - j - 2, 1] = (Math.Pow(Math.Cos(Infinitisemalangle[j]), 2 / m_Exponent) * m_Length * Math.Sin(Motion.GetAngle(0)) - Math.Pow(Math.Sin(Infinitisemalangle[j]), 2 / m_Exponent) * m_Thickness * Math.Cos(Motion.GetAngle(0))) + Motion.GetPosition(0)[1];
            //}
            return(SurfacePoints);
        }
Example #30
0
        /// <summary>
        /// projects some DG field onto this
        /// </summary>
        /// <param name="alpha"></param>
        /// <param name="DGField"></param>
        /// <param name="_cm">optional restriction to computational domain</param>
        /// <remarks>
        /// This method computes an exact
        /// L2-projection of the DG-field onto the SpecFEM-space, so a global linear system, which contains all
        /// DOF's, has to be solved.
        /// In contrast, <see cref="ProjectDGFieldCheaply"/> performs an approximate projection which only involves
        /// local operations for each cell.
        /// </remarks>
        public void ProjectDGField(double alpha, ConventionalDGField DGField, CellMask _cm = null)
        {
            using (var trx = new Transceiver(this.Basis)) {
                CellMask cm = _cm;
                if (cm == null)
                {
                    cm = CellMask.GetFullMask(this.Basis.GridDat);
                }


                int J        = m_Basis.GridDat.Cells.NoOfLocalUpdatedCells;
                var Trafo    = m_Basis.GridDat.ChefBasis.Scaling;
                var C2N      = m_Basis.CellNode_To_Node;
                var MtxM2N   = m_Basis.m_Modal2Nodal;
                var CellData = this.Basis.GridDat.Cells;

                // compute RHS
                // ===========

                var b = MultidimensionalArray.Create(this.m_Basis.NoOfLocalNodes);
                {
                    int[]      _K = m_Basis.NodesPerCell;
                    int        L  = m_Basis.ContainingDGBasis.Length;
                    double[][] _NodalCoordinates = _K.Select(K => new double[K]).ToArray(); // temporary storage for nodal coordinates per cell
                                                                                            // 1st idx: ref. elm., 2nd idx: node index
                    double[] ModalCoordinates = new double[L];

                    foreach (Chunk cnk in cm)
                    {
                        int j0 = cnk.i0;
                        int jE = cnk.JE;
                        for (int j = j0; j < jE; j++)   // loop over cells...
                        {
                            int      iKref            = CellData.GetRefElementIndex(j);
                            double[] NodalCoordinates = _NodalCoordinates[iKref];
                            int      K = _K[iKref];

                            if (!CellData.IsCellAffineLinear(j))
                            {
                                throw new NotSupportedException();
                            }

                            // Get DG coordinates
                            Array.Clear(ModalCoordinates, 0, L);
                            int Lmin = Math.Min(L, DGField.Basis.GetLength(j));
                            for (int l = 0; l < Lmin; l++)
                            {
                                ModalCoordinates[l] = DGField.Coordinates[j, l];
                            }

                            var tr = 1.0 / Trafo[j];

                            // transform
                            //DGField.Coordinates.GetRow(j, ModalCoordinates);
                            ModalCoordinates.ClearEntries();
                            for (int l = 0; l < Lmin; l++)
                            {
                                ModalCoordinates[l] = DGField.Coordinates[j, l];
                            }
                            MtxM2N[iKref].GEMV(tr, ModalCoordinates, 0.0, NodalCoordinates, transpose: true);

                            // collect coordinates for cell 'j':
                            for (int k = 0; k < K; k++)
                            {
                                int _c2n = C2N[j, k];
                                b[_c2n] += NodalCoordinates[k];
                            }
                        }
                    }
                }

                trx.AccumulateGather(b);

                /*
                 *
                 * var bcheck = new double[b.Length];
                 * {
                 *  var polys = this.Basis.NodalBasis;
                 *
                 *
                 *  CellQuadrature.GetQuadrature(new int[] { K },
                 *      this.Basis.GridDat.Context,
                 *      (new CellQuadratureScheme()).Compile(this.Basis.GridDat, this.Basis.ContainingDGBasis.Degree*2),
                 *      delegate(MultidimensionalArray NodesUntransformed) { // Del_CreateNodeSetFamily
                 *          var NSC = this.Basis.GridDat.Context.NSC;
                 *          return new NodeSetController.NodeSetContainer[] { NSC.CreateContainer(NodesUntransformed) };
                 *      },
                 *      delegate(int i0, int Length, int _NoOfNodes, MultidimensionalArray EvalResult) {
                 *          var PolyAtNode = MultidimensionalArray.Create(K, _NoOfNodes);
                 *          for (int k = 0; k < K; k++) {
                 *              polys[k].Evaluate(PolyAtNode.ExtractSubArrayShallow(k, -1), this.Basis.GridDat.Context.NSC.Current_NodeSetFamily[0].NodeSet);
                 *          }
                 *
                 *          var DGFatNodes = MultidimensionalArray.Create(Length, _NoOfNodes);
                 *          DGField.Evaluate(i0, Length, 0, DGFatNodes);
                 *
                 *          //for(int i = 0; i < Length; i++) {
                 *          //    for (int n = 0; n < _NoOfNodes; n++) {
                 *          //        for (int k = 0; k < K; k++) {
                 *          //            for (int l = 0; l < K; l++) {
                 *          //                EvalResult[i, n, k, l] = PolyAtNode[k, n]*PolyAtNode[l, n];
                 *          //            }
                 *          //        }
                 *          //    }
                 *          //}
                 *
                 *          EvalResult.Multiply(1.0, PolyAtNode, DGFatNodes, 0.0, "jnk", "kn", "jn");
                 *
                 *          //double errSum = 0;
                 *          //for (int i = 0; i < Length; i++) {
                 *          //    for (int n = 0; n < _NoOfNodes; n++) {
                 *          //        for (int k = 0; k < K; k++) {
                 *          //            for (int l = 0; l < K; l++) {
                 *          //                double soll = PolyAtNode[k, n]*PolyAtNode[l, n];
                 *          //                errSum += Math.Abs(soll - EvalResult[i, n, k, l]);
                 *          //            }
                 *          //        }
                 *          //    }
                 *          //}
                 *          //Console.WriteLine("errsum = " + errSum);
                 *      },
                 *      delegate(int i0, int Length, MultidimensionalArray ResultsOfIntegration) { // SaveIntegrationResults
                 *          for (int i = 0; i < Length; i++) {
                 *              int jCell = i + i0;
                 *
                 *              for (int k = 0; k < K; k++) {
                 *                  bcheck[C2N[jCell, k]] += ResultsOfIntegration[i, k];
                 *              }
                 *
                 *              //CellMass[jCell] = new FullMatrix(K, K);
                 *              //CellMass[jCell].Initialize(ResultsOfIntegration.ExtractSubArrayShallow(i, -1, -1));
                 *          }
                 *      }).Execute();
                 *
                 *
                 *  double f**k = GenericBlas.L2Dist(b, bcheck);
                 *  Console.WriteLine("Distance error = " + f**k);
                 *
                 * }
                 *
                 *
                 */

                if (_cm == null)
                {
                    // full domain projection branch
                    // +++++++++++++++++++++++++++++


                    var x       = new double[this.Basis.NoOfLocalOwnedNodes];
                    var solStat = m_Basis.MassSolver.Solve(x, b.ExtractSubArrayShallow(new int[] { 0 }, new int[] { this.Basis.NoOfLocalOwnedNodes - 1 }).To1DArray());

                    {
                        if (solStat.Converged == false)
                        {
                            throw new ArithmeticException("DG -> SpecFEM Projection failed because the Mass matrix solver did not converge.");
                        }


                        double[] chk = b.ExtractSubArrayShallow(new int[] { 0 }, new int[] { this.Basis.NoOfLocalOwnedNodes - 1 }).To1DArray();
                        this.Basis.MassMatrix.SpMVpara(-1.0, x, 1.0, chk);
                        double chk_nomr = chk.L2Norm();

                        if (chk_nomr >= 1.0e-8)
                        {
                            throw new ArithmeticException(string.Format("DG -> SpecFEM Projection failed: solver converged, but with high residual {0}.", chk_nomr.ToStringDot()));
                        }
                    }

                    //m_Basis.MassMatrix.SpMV(1.0, b, 0.0, x);
                    m_Coordinates.ExtractSubArrayShallow(new int[] { 0 }, new int[] { this.Basis.NoOfLocalOwnedNodes - 1 }).AccVector(alpha, x);
                    //m_Coordinates.AccV(alpha, b);
                }
                else
                {
                    // restricted domain projection branch
                    // +++++++++++++++++++++++++++++++++++

                    List <int> OccupiedRows_Global = new List <int>();
                    //List<int> OccupiedRows_Local = new List<int>();

                    var MM = Basis.ComputeMassMatrix(cm);
                    int i0 = MM.RowPartitioning.i0, iE = MM.RowPartitioning.iE;
                    for (int i = i0; i < iE; i++)
                    {
                        if (MM.GetNoOfNonZerosPerRow(i) > 0)
                        {
                            OccupiedRows_Global.Add(i);
                            //OccupiedRows_Local.Add(i - i0);
                        }
                    }

                    var CompressedPart = new Partitioning(OccupiedRows_Global.Count);
                    var CompressedMM   = new MsrMatrix(CompressedPart);

                    MM.WriteSubMatrixTo(CompressedMM, OccupiedRows_Global, default(int[]), OccupiedRows_Global, default(int[]));

                    var b_sub = new double[OccupiedRows_Global.Count];
                    //try {
                    b_sub.AccV(1.0, b.To1DArray(), default(int[]), OccupiedRows_Global, b_index_shift: -i0);
                    //} catch(Exception e) {
                    //    Debugger.Launch();
                    //}
                    //csMPI.Raw.Barrier(csMPI.Raw._COMM.WORLD);

                    var x_sub = new double[b_sub.Length];

                    var solver = new ilPSP.LinSolvers.monkey.CG();
                    solver.MatrixType      = ilPSP.LinSolvers.monkey.MatrixType.CCBCSR;
                    solver.DevType         = ilPSP.LinSolvers.monkey.DeviceType.CPU;
                    solver.ConvergenceType = ConvergenceTypes.Absolute;
                    solver.Tolerance       = 1.0e-12;
                    solver.DefineMatrix(CompressedMM);

                    var solStat = solver.Solve(x_sub, b_sub.CloneAs());
                    {
                        if (solStat.Converged == false)
                        {
                            throw new ArithmeticException("DG -> SpecFEM Projection failed because the Mass matrix solver did not converge.");
                        }

                        var chk = b_sub;
                        CompressedMM.SpMVpara(-1.0, x_sub, 1.0, chk);
                        double chk_nomr = chk.L2Norm();

                        if (chk_nomr >= 1.0e-8)
                        {
                            throw new ArithmeticException(string.Format("DG -> SpecFEM Projection failed: solver converged, but with high residual {0}.", chk_nomr.ToStringDot()));
                        }
                    }

                    double[] x = new double[this.Basis.NoOfLocalOwnedNodes];
                    x.AccV(1.0, x_sub, OccupiedRows_Global, default(int[]), acc_index_shift: -i0);
                    m_Coordinates.ExtractSubArrayShallow(new int[] { 0 }, new int[] { this.Basis.NoOfLocalOwnedNodes - 1 }).AccVector(alpha, x);
                }

                trx.Scatter(this.m_Coordinates);
            }
        }