Esempio n. 1
0
        /// <summary>
        /// Approximate H1 distance (difference in the H1 norm) between two DG fields; this also supports DG fields on different meshes,
        /// it could be used for convergence studies.
        /// </summary>
        /// <param name="A"></param>
        /// <param name="B"></param>
        /// <param name="scheme">
        /// a cell quadrature scheme on the coarse of the two meshes
        /// </param>
        /// <returns></returns>
        static public double H1Distance(this ConventionalDGField A, ConventionalDGField B, CellQuadratureScheme scheme = null)
        {
            if (A.GridDat.SpatialDimension != B.GridDat.SpatialDimension)
            {
                throw new ArgumentException("Both fields must have the same spatial dimension.");
            }

            int D = A.GridDat.SpatialDimension;

            double Acc = 0.0;

            Acc += L2Distance(A, B, false, scheme).Pow2();
            for (int d = 0; d < D; d++)
            {
                ConventionalDGField dA_dd = new SinglePhaseField(A.Basis);
                dA_dd.Derivative(1.0, A, d, scheme != null ? scheme.Domain : null);

                ConventionalDGField dB_dd = new SinglePhaseField(B.Basis);
                dB_dd.Derivative(1.0, B, d, scheme != null ? scheme.Domain : null);

                Acc += L2Distance(dA_dd, dB_dd, false, scheme).Pow2();
            }

            return(Acc.Sqrt());
        }
Esempio n. 2
0
 /// <summary>
 /// Sensor field
 /// </summary>
 public PerssonSensor(DGField fieldToTest)
 {
     sensorVariable = fieldToTest.Identification;
     sensorField    = new SinglePhaseField(
         new Basis(fieldToTest.GridDat, 0), "sensor");
     fieldToTestRestricted = new SinglePhaseField(
         new Basis(fieldToTest.GridDat, fieldToTest.Basis.Degree - 1));
 }
Esempio n. 3
0
            public void createNodes(int[,] TrafoIdx, SinglePhaseField Phi, ConventionalDGField ExtProperty)
            {
                int     iTrafo    = TrafoIdx[associatedNeighbour.Item2, associatedNeighbour.Item3];
                NodeSet CellNodes = this.EdgeNodes.GetVolumeNodeSet(this.Solver_Grid, iTrafo);

                //Writes Phi and ExtProperty values at edge nodes into the respective Buffer
                Phi.Evaluate(associatedNeighbour.Item1, 1, CellNodes, this.PhiEdgeEvalBuffer);
                ExtProperty.Evaluate(associatedNeighbour.Item1, 1, CellNodes, this.ExtEdgeEvalBuffer);

                //Writes the corresponding nodes into CellNodesGlobalBuffer
                this.Solver_Grid.TransformLocal2Global(this.EdgeNodes.GetVolumeNodeSet(this.Solver_Grid, iTrafo), this.EdgeNodesGlobal, associatedNeighbour.Item1);
            }
Esempio n. 4
0
        /// <summary>
        /// projects some DG field onto this
        /// </summary>
        /// <param name="alpha"></param>
        /// <param name="DGField"></param>
        public void ProjectDGFieldMaximum(double alpha, ConventionalDGField DGField)
        {
            DGField.MPIExchange();

            //var multiplicity = new int[this.m_Basis.NoOfLocalNodes];

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

            int[] _K = m_Basis.NodesPerCell;
            int   L  = m_Basis.ContainingDGBasis.Length;

            double[][] _NodalCoordinates = _K.Select(K => new double[K]).ToArray();
            double[]   ModalCoordinates  = new double[L];


            for (int j = 0; j < J; j++)   // loop over cells...
            {
                int      iKref            = CellData.GetRefElementIndex(j);
                double[] NodalCoordinates = _NodalCoordinates[iKref];
                int      K = _K[iKref];

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


                // transform
                DGField.Coordinates.GetRow(j, ModalCoordinates);
                MtxN2M[iKref].gemv(alpha * Trafo[j], ModalCoordinates, 0.0, NodalCoordinates);


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

            using (var trx = new Transceiver(this.Basis)) {
                trx.MaxGather(m_Coordinates);
                trx.Scatter(m_Coordinates);
            }
        }
Esempio n. 5
0
        /// <summary>
        /// accumulate this field to a DG field
        /// </summary>
        /// <param name="alpha"></param>
        /// <param name="DGField"></param>
        /// <param name="mask">optional cell mask</param>
        public void AccToDGField(double alpha, ConventionalDGField DGField, CellMask mask = null)
        {
            if (!DGField.Basis.Equals(this.m_Basis.ContainingDGBasis))
            {
                throw new ArgumentException("Basis does not match.");
            }

            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;

            int[] _K = m_Basis.NodesPerCell;
            int   L  = m_Basis.ContainingDGBasis.Length;

            double[][] _NodalCoordinates = _K.Select(K => new double[K]).ToArray();
            double[]   ModalCoordinates  = new double[L];

            if (mask == null)
            {
                mask = CellMask.GetFullMask(this.Basis.GridDat);
            }

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

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

                    // transform
                    DGField.Coordinates.GetRow(j, ModalCoordinates);
                    MtxM2N[iKref].gemv(alpha / Trafo[j], NodalCoordinates, 1.0, ModalCoordinates);

                    // save
                    DGField.Coordinates.SetRow(j, ModalCoordinates);
                }
            }
        }
Esempio n. 6
0
        /// <summary>
        /// Finds the new Extension Property and overwrites the respective field.
        /// </summary>
        /// <param name="Phi"></param> The LevelSetFunction /field
        /// <param name="ExtProperty"></param> Extension property that will be updated
        /// <param name="Accepted_Mutuable"></param> Mapping of accepted Cells
        /// <param name="jCell"></param> Name of the cell, in which we find the extension Property
        /// <param name="signMod"></param> Information on the sign of LevelSetFunction Phi
        public void ExtVelSolve_Geometric(SinglePhaseField Phi, ConventionalDGField ExtProperty, BitArray Accepted_Mutuable, int jCell, double signMod)
        {
            GridData grid = (GridData)Phi.GridDat;

            numberOfUsedEdges = 0;

            //Find neighbors that define the cells edges
            //Scheme: find used edges, associate a neighbouring edge to each used edge, count the number of used edges.
            Tuple <int, int, int>[] neighbors = this.GridDat.GetCellNeighboursViaEdges(jCell);
            foreach (Tuple <int, int, int> neighbor in neighbors)
            {
                if (Accepted_Mutuable[neighbor.Item1] == true)
                {
                    edgesOfCell[numberOfUsedEdges].AssociatedNeighbour = neighbor; //NumberOfEdges is incremented in class Edge
                    numberOfUsedEdges++;
                }
            }

            //Create nodes on the accepted neighbor edges, clear the buffered values.
            int[,] TrafoIdx = this.GridDat.Edges.Edge2CellTrafoIndex;
            for (int i = 0; i < numberOfUsedEdges; i++)   // loop over accepted neighbours
            {
                edgesOfCell[i].clearBuffer();
                edgesOfCell[i].createNodes(TrafoIdx, Phi, ExtProperty);
            }

            //Create cell which holds information about:
            //The quadraturenodes, i.e. value and position
            Cell cell = new Cell(jCell, QuadNodesGlobal, GridDat, DaRuleS);

            //Find new values for the nodes in the cell
            foreach (Node quadNode in cell)
            {
                int[] selectedNode = findCorrelatingNode(quadNode, edgesOfCell, signMod);
                //Get Edge value at selectedNode (node with smallest difference in Phi)
                double valueOfSelectedNode = edgesOfCell[selectedNode[0]].getExtEdgeValue(selectedNode[1]);
                //Write the found value for Ext into the array, which holds the value of each Node. This array will be used to to update ExtProperty
                cell.setExtAtQuadNode(valueOfSelectedNode, quadNode);
            }

            //update ExtProperty by projection
            updateExtProperty(ExtProperty, cell);
        }
Esempio n. 7
0
        /// <summary>
        /// Updates the ExtProperty field via projection. Needs more work.
        /// </summary>
        /// <param name="ExtProperty"></param> Field that will be updated
        /// <param name="cell"></param> The cell that will be updated. Cell holds the new values etc.
        void updateExtProperty(ConventionalDGField ExtProperty, Cell cell)
        {
            int jCell             = cell.jCell;
            int iKref             = cell.iKref;
            int numberOfQuadNodes = cell.numberOfQuadNodes;
            MultidimensionalArray ExtAtQuadNodes = cell.ExtAtQuadNodes;

            MultidimensionalArray weighted_ExtAtQuadNodes = MultidimensionalArray.Create(numberOfQuadNodes);

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

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

            if (this.GridDat.Cells.IsCellAffineLinear(jCell))
            {
                int N  = this.SolverBasis.GetLength(jCell);
                int N2 = ExtProperty.Basis.GetLength(jCell);

                MultidimensionalArray Phi_1 = MultidimensionalArray.Create(N);
                double scale = this.GridDat.Cells.JacobiDet[jCell];
                Phi_1.Multiply(scale, BasisValues, weighted_ExtAtQuadNodes, 0.0, "m", "km", "k");
                for (int n = 0; n < N; n++)
                {
                    ExtProperty.Coordinates[jCell, n] = Phi_1[n];
                }
                for (int n = N; n < N2; n++)
                {
                    ExtProperty.Coordinates[jCell, n] = 0;
                }
            }
            else
            {
                throw new NotImplementedException("not implemented for curved cells");
            }
        }
Esempio n. 8
0
        static void SetTestValue(ConventionalDGField f)
        {
            switch (f.Basis.Degree)
            {
            case 0:
                f.ProjectField(((x, y) => 1.0));
                break;

            case 1:
                f.ProjectField(((x, y) => 1.0 + x - y));
                break;

            case 2:
                f.ProjectField(((x, y) => 1.0 + x - y + x * y));
                break;

            case 3:
                f.ProjectField(((x, y) => x * x * x + 3.2 * x * y * y - 2.4 * y * y * y));
                break;

            default:
                throw new NotImplementedException();
            }
        }
Esempio n. 9
0
        /// <summary>
        /// projects some DG field onto this
        /// </summary>
        /// <param name="alpha"></param>
        /// <param name="DGField"></param>
        public void ProjectDGFieldCheaply(double alpha, ConventionalDGField DGField)
        {
            DGField.MPIExchange();

            //var multiplicity = new int[this.m_Basis.NoOfLocalNodes];

            var gdat     = m_Basis.GridDat;
            int J        = gdat.Cells.NoOfLocalUpdatedCells;
            var Trafo    = gdat.ChefBasis.Scaling;
            var C2N      = m_Basis.CellNode_To_Node;
            var MtxN2M   = m_Basis.m_Nodal2Modal;
            var CellData = gdat.Cells;

            int[] _K   = m_Basis.NodesPerCell;
            int   L    = m_Basis.ContainingDGBasis.Length;
            int   pDeg = m_Basis.ContainingDGBasis.Degree;

            double[][] _NodalCoordinates = _K.Select(K => new double[K]).ToArray();
            double[]   ModalCoordinates  = new double[L];
            double[]   IntermCoordinates = new double[L];


            for (int j = 0; j < J; j++)   // loop over cells...
            {
                int      iKref            = CellData.GetRefElementIndex(j);
                double[] NodalCoordinates = _NodalCoordinates[iKref];
                int      K = _K[iKref];

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

                // transform
                DGField.Coordinates.GetRow(j, ModalCoordinates);
                if (CellData.IsCellAffineLinear(j))
                {
                    MtxN2M[iKref].GEMV(alpha * Trafo[j], ModalCoordinates, 0.0, NodalCoordinates);
                }
                else
                {
                    var OnbTrafo = gdat.ChefBasis.OrthonormalizationTrafo.GetValue_Cell(j, 1, pDeg).ExtractSubArrayShallow(0, -1, -1);
                    OnbTrafo.GEMV(alpha, ModalCoordinates, 0.0, IntermCoordinates);
                    MtxN2M[iKref].GEMV(1.0, IntermCoordinates, 0.0, NodalCoordinates);
                }

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

            using (var trx = new Transceiver(this.Basis)) {
                trx.AccumulateGather(m_Coordinates);


                var multiplicity = this.Basis.NodeMultiplicity;
                int I            = this.Basis.NoOfLocalOwnedNodes;
                for (int i = 0; i < I; i++)
                {
                    Debug.Assert(multiplicity[i] > 0);
                    m_Coordinates[i] *= 1.0 / multiplicity[i];
                }

                trx.Scatter(m_Coordinates);
            }
        }
Esempio n. 10
0
        /// <summary>
        /// Projects a DG field <paramref name="source"/>, which may be defined on some different mesh,
        /// onto the DG field <paramref name="target"/>.
        /// </summary>
        static public void ProjectFromForeignGrid(this ConventionalDGField target, double alpha, ConventionalDGField source, CellQuadratureScheme scheme = null)
        {
            using (new FuncTrace()) {
                Console.WriteLine(string.Format("Projecting {0} onto {1}... ", source.Identification, target.Identification));
                int maxDeg       = Math.Max(target.Basis.Degree, source.Basis.Degree);
                var CompQuadRule = scheme.SaveCompile(target.GridDat, maxDeg * 3 + 3); // use over-integration
                int D            = target.GridDat.SpatialDimension;



                if (object.ReferenceEquals(source.GridDat, target.GridDat))
                {
                    // +++++++++++++++++
                    // equal grid branch
                    // +++++++++++++++++

                    target.ProjectField(alpha, source.Evaluate, CompQuadRule);
                }
                else
                {
                    // +++++++++++++++++++++
                    // different grid branch
                    // +++++++++++++++++++++

                    if (source.GridDat.SpatialDimension != D)
                    {
                        throw new ArgumentException("Spatial Dimension Mismatch.");
                    }

                    var eval = new FieldEvaluation(GridHelper.ExtractGridData(source.GridDat));


                    //
                    // Difficulty with MPI parallelism:
                    // While the different meshes may represent the same geometrical domain,
                    // their MPI partitioning may be different.
                    //
                    // Solution Approach: we circulate unlocated points among all MPI processes.
                    //

                    int MPIsize = target.GridDat.MpiSize;


                    // pass 1: collect all points
                    // ==========================
                    MultidimensionalArray allNodes = null;
                    void CollectPoints(MultidimensionalArray input, MultidimensionalArray output)
                    {
                        Debug.Assert(input.Dimension == 2);
                        Debug.Assert(input.NoOfCols == D);

                        if (allNodes == null)
                        {
                            allNodes = input.CloneAs();
                        }
                        else
                        {
                            /*
                             * var newNodes = MultidimensionalArray.Create(allNodes.NoOfRows + input.NoOfRows, D);
                             * newNodes.ExtractSubArrayShallow(new[] { 0, 0 }, new[] { allNodes.NoOfRows - 1, D - 1 })
                             *  .Acc(1.0, allNodes);
                             * newNodes.ExtractSubArrayShallow(new[] {  allNodes.NoOfRows, 0 }, new[] { newNodes.NoOfRows - 1, D - 1 })
                             *  .Acc(1.0, allNodes);
                             */
                            allNodes = allNodes.CatVert(input);
                        }
                        Debug.Assert(allNodes.NoOfCols == D);
                    }

                    target.ProjectField(alpha, CollectPoints, CompQuadRule);

                    int L = allNodes != null?allNodes.GetLength(0) : 0;

                    // evaluate
                    // ========

                    //allNodes = MultidimensionalArray.Create(2, 2);
                    //allNodes[0, 0] = -1.5;
                    //allNodes[0, 1] = 2.0;
                    //allNodes[1, 0] = -0.5;
                    //allNodes[1, 1] = 2.0;
                    //L = 2;
                    var Res           = L > 0 ? MultidimensionalArray.Create(L, 1) : default(MultidimensionalArray);
                    int NoOfUnlocated = eval.EvaluateParallel(1.0, new DGField[] { source }, allNodes, 0.0, Res);

                    int TotalNumberOfUnlocated = NoOfUnlocated.MPISum();
                    if (TotalNumberOfUnlocated > 0)
                    {
                        Console.Error.WriteLine($"WARNING: {TotalNumberOfUnlocated} unlocalized points in 'ProjectFromForeignGrid(...)'");
                    }

                    // perform the real projection
                    // ===========================


                    int lc = 0;
                    void ProjectionIntegrand(MultidimensionalArray input, MultidimensionalArray output)
                    {
                        Debug.Assert(input.Dimension == 2);
                        Debug.Assert(input.NoOfCols == D);

                        int LL = input.GetLength(0);

                        output.Set(Res.ExtractSubArrayShallow(new int[] { lc, 0 }, new int[] { lc + LL - 1, -1 }));
                        lc += LL;
                    }

                    target.ProjectField(alpha, ProjectionIntegrand, CompQuadRule);
                }
            }
        }
Esempio n. 11
0
        /// <summary>
        /// Approximate L2 distance between two DG fields; this also supports DG fields on different meshes,
        /// it could be used for convergence studies.
        /// </summary>
        /// <param name="A"></param>
        /// <param name="B"></param>
        /// <param name="IgnoreMeanValue">
        /// if true, the mean value (mean over entire domain) will be subtracted - this mainly useful for comparing pressures
        /// </param>
        /// <param name="scheme">
        /// a cell quadrature scheme on the coarse of the two meshes
        /// </param>
        /// <returns></returns>
        static public double L2Distance(this ConventionalDGField A, ConventionalDGField B, bool IgnoreMeanValue = false, CellQuadratureScheme scheme = null)
        {
            int maxDeg    = Math.Max(A.Basis.Degree, B.Basis.Degree);
            int quadOrder = maxDeg * 3 + 3;

            if (A.GridDat.SpatialDimension != B.GridDat.SpatialDimension)
            {
                throw new ArgumentException("Both fields must have the same spatial dimension.");
            }

            if (object.ReferenceEquals(A.GridDat, B.GridDat) && false)
            {
                // ++++++++++++++
                // equal meshes
                // ++++++++++++++
                CellMask domain = scheme != null ? scheme.Domain : null;

                double errPow2 = A.L2Error(B, domain).Pow2();

                if (IgnoreMeanValue)
                {
                    // domain volume
                    double Vol = 0;
                    int    J   = A.GridDat.iGeomCells.NoOfLocalUpdatedCells;
                    for (int j = 0; j < J; j++)
                    {
                        Vol += A.GridDat.iGeomCells.GetCellVolume(j);
                    }
                    Vol = Vol.MPISum();

                    // mean value
                    double mean = A.GetMeanValueTotal(domain) - B.GetMeanValueTotal(domain);

                    // Note: for a field p, we have
                    // || p - <p> ||^2 = ||p||^2 - <p>^2*vol
                    return(Math.Sqrt(errPow2 - mean * mean * Vol));
                }
                else
                {
                    return(Math.Sqrt(errPow2));
                }
            }
            else
            {
                // ++++++++++++++++++
                // different meshes
                // ++++++++++++++++++


                DGField fine, coarse;
                if (A.GridDat.CellPartitioning.TotalLength > B.GridDat.CellPartitioning.TotalLength)
                {
                    fine   = A;
                    coarse = B;
                }
                else
                {
                    fine   = B;
                    coarse = A;
                }

                var CompQuadRule = scheme.SaveCompile(coarse.GridDat, maxDeg * 3 + 3); // use over-integration

                var eval = new FieldEvaluation(GridHelper.ExtractGridData(fine.GridDat));

                void FineEval(MultidimensionalArray input, MultidimensionalArray output)
                {
                    int L = input.GetLength(0);

                    Debug.Assert(output.GetLength(0) == L);

                    eval.Evaluate(1.0, new DGField[] { fine }, input, 0.0, output.ResizeShallow(L, 1));
                }

                double errPow2 = coarse.LxError(FineEval, (double[] X, double fC, double fF) => (fC - fF).Pow2(), CompQuadRule, Quadrature_ChunkDataLimitOverride: int.MaxValue);

                if (IgnoreMeanValue == true)
                {
                    // domain volume
                    double Vol = 0;
                    int    J   = coarse.GridDat.iGeomCells.NoOfLocalUpdatedCells;
                    for (int j = 0; j < J; j++)
                    {
                        Vol += coarse.GridDat.iGeomCells.GetCellVolume(j);
                    }
                    Vol = Vol.MPISum();

                    // mean value times domain volume
                    double meanVol = coarse.LxError(FineEval, (double[] X, double fC, double fF) => fC - fF, CompQuadRule, Quadrature_ChunkDataLimitOverride: int.MaxValue);


                    // Note: for a field p, we have
                    // || p - <p> ||^2 = ||p||^2 - <p>^2*vol
                    return(Math.Sqrt(errPow2 - meanVol * meanVol / Vol));
                }
                else
                {
                    return(Math.Sqrt(errPow2));
                }
            }
        }
Esempio n. 12
0
        /// <summary>
        /// Solution of the extension problem on a single cell in the far-region
        /// </summary>
        /// <param name="Phi">Input;</param>
        /// <param name="GradPhi">Input;</param>
        /// <param name="ExtProperty"></param>
        /// <param name="ExtPropertyMin">Input/Output: lower threshold.</param>
        /// <param name="ExtPropertyMax">Input/Output: upper threshold.</param>
        /// <param name="jCell"></param>
        /// <param name="Accepted"></param>
        /// <param name="signMod"></param>
        public void ExtVelSolve_Far(SinglePhaseField Phi, VectorField <SinglePhaseField> GradPhi, ConventionalDGField ExtProperty, ref double ExtPropertyMin, ref double ExtPropertyMax, int jCell, CellMask Accepted, double signMod)
        {
            GridData gDat = (GridData)(Phi.GridDat);

            Debug.Assert(signMod.Abs() == 1.0);
            Debug.Assert(ExtPropertyMin <= ExtPropertyMax);


            // define cell- and edge-mask for re-compute
            // =========================================

            CellMask cM = new CellMask(gDat, Chunk.GetSingleElementChunk(jCell));

            int[] Edges = gDat.iLogicalCells.Cells2Edges[jCell].CloneAs();
            for (int i = 0; i < Edges.Length; i++)
            {
                Edges[i] = Math.Abs(Edges[i]) - 1;
            }

            EdgeMask eM = new EdgeMask(gDat, FromIndEnum(Edges, gDat.iLogicalEdges.Count)); // won't scale.

            // solve the linear extension problem for 'jCell', eventually increase
            // diffusion until we are satisfied with the solution
            // ===================================================================

            bool   MaximumPrincipleFulfilled = false;
            double DiffusionCoeff = 0; // initially: try without diffusion
            double mini = double.NaN, maxi = double.NaN;
            int    count = 0;

            while (MaximumPrincipleFulfilled == false)  // as long as we are satisfied with the solution
            {
                count++;

                // compute operator in 'jCell'
                // ---------------------------

                int N   = ExtProperty.Basis.GetLength(jCell);
                int i0G = ExtProperty.Mapping.GlobalUniqueCoordinateIndex(0, jCell, 0);
                int i0L = ExtProperty.Mapping.GlobalUniqueCoordinateIndex(0, jCell, 0);

                for (int n = 0; n < N; n++)
                {
                    this.m_ExtvelMatrix.ClearRow(i0G + n);
                    this.m_ExtvelAffine[i0L + n] = 0;
                }

                double penaltyBase = ((double)(ExtProperty.Basis.Degree + 1)).Pow2();
                var    Flux        = new ExtensionVelocityForm(Accepted.GetBitMask(), signMod, penaltyBase, gDat.Cells.h_min, jCell, DiffusionCoeff);
                var    op          = (Flux).Operator(DegreeOfNonlinearity: 2);

                // increase diffusion coefficient for next cycle
                if (DiffusionCoeff == 0)
                {
                    DiffusionCoeff = 1.0e-3; // should this be minus or plus?
                }
                else
                {
                    DiffusionCoeff *= 10;
                }

                op.ComputeMatrixEx(ExtProperty.Mapping, ArrayTools.Cat <DGField>(new DGField[] { ExtProperty, Phi }, GradPhi), ExtProperty.Mapping,
                                   this.m_ExtvelMatrix, this.m_ExtvelAffine,
                                   OnlyAffine: false,
                                   volQuadScheme: (new CellQuadratureScheme(true, cM)),
                                   edgeQuadScheme: (new EdgeQuadratureScheme(true, eM)),
                                   ParameterMPIExchange: false);

                // extract operator matrix and RHS
                // -------------------------------

                // the matrix must only have entries in the block-diagonal!

                MultidimensionalArray Mtx = MultidimensionalArray.Create(N, N);
                //MultidimensionalArray rhs = MultidimensionalArray.Create(N);
                double[] rhs = new double[N];

                for (int n = 0; n < N; n++)
                {
#if DEBUG
                    int      Lr;
                    int[]    row_cols = null;
                    double[] row_vals = null;
                    Lr = this.m_ExtvelMatrix.GetRow(i0G + n, ref row_cols, ref row_vals);
                    for (int lr = 0; lr < Lr; lr++)
                    {
                        int    ColIndex = row_cols[lr];
                        double Value    = row_vals[lr];
                        Debug.Assert((ColIndex >= i0G && ColIndex < i0G + N) || (Value == 0.0), "Matrix is expected to be block-diagonal.");
                    }
#endif
                    for (int m = 0; m < N; m++)
                    {
                        Mtx[n, m] = this.m_ExtvelMatrix[i0G + n, i0G + m];
                    }
                    rhs[n] = -this.m_ExtvelAffine[i0L + n];
                }

                // Solve the system, i.e. the local extension-velocity equation
                // ------------------------------------------------------------

                double[] ep = new double[N];
                Mtx.Solve(ep, rhs);

                for (int n = 0; n < N; n++)
                {
                    ExtProperty.Coordinates[jCell, n] = ep[n];
                }

                // detect violation of maximum principle
                // -------------------------------------

                ExtProperty.GetExtremalValuesInCell(out mini, out maxi, jCell);

                // define relaxed bounds...
                double compExtPropertyMin = ExtPropertyMin - (1.0e-8 + ExtPropertyMax - ExtPropertyMin) * 0.2;
                double compExtPropertyMax = ExtPropertyMax + (1.0e-8 + ExtPropertyMax - ExtPropertyMin) * 0.2;

                // test if extension velocity solution is within bounds
                MaximumPrincipleFulfilled = (mini >= compExtPropertyMin) && (maxi <= compExtPropertyMax);

                if (count > 5)
                {
                    break;
                }
            }
            if (count > 4)
            {
                Console.WriteLine(" ExtVel, cell #{0}, Diff coeff {1}, extremal p. holds? {2} (min/max soll = {3:e4}/{4:e4}, ist = {5:e4}/{6:e4})", jCell, DiffusionCoeff, MaximumPrincipleFulfilled, ExtPropertyMin, ExtPropertyMax, mini, maxi);
            }

            // record maxima and minima
            // ========================
            ExtPropertyMax = Math.Max(ExtPropertyMax, maxi);
            ExtPropertyMin = Math.Min(ExtPropertyMin, mini);
        }
Esempio n. 13
0
        /// <summary>
        /// Injects a DG field from a coarser grid to a fine grid.
        /// </summary>
        public static void InjectDGField(int[] CellIdxFine2Coarse, ConventionalDGField onFineGrid, ConventionalDGField onCoarseGrid, CellMask subGrd = null)
        {
            if (subGrd == null)
            {
                subGrd = CellMask.GetFullMask(onFineGrid.GridDat);
            }
            if (onFineGrid.Basis.GridDat.iGeomCells.RefElements.Length != 1)
            {
                throw new NotImplementedException("todo");
            }
            var QR = onFineGrid.Basis.GridDat.iGeomCells.RefElements[0].GetQuadratureRule(onFineGrid.Basis.Degree * 2);

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

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

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

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

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

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

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

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

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


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

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

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


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


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

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

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

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

                    // set DG coordinates
                    onFineGrid.Coordinates.SetRow(_2, u2);
                }
            }
        }
Esempio n. 14
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);
        }
Esempio n. 15
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);
        }
Esempio n. 16
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;
                        }
                    }
                }
            });
        }
Esempio n. 17
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);
            }
        }
Esempio n. 18
0
        /// <summary>
        /// Update Forces and Torque acting from fluid onto the particle
        /// </summary>
        /// <param name="U"></param>
        /// <param name="P"></param>
        /// <param name="LsTrk"></param>
        /// <param name="muA"></param>
        public void UpdateForcesAndTorque(VectorField <SinglePhaseField> U, SinglePhaseField P, LevelSetTracker LsTrk, double muA, double dt, double fluidDensity, bool NotFullyCoupled)
        {
            if (skipForceIntegration)
            {
                skipForceIntegration = false;
                return;
            }
            HydrodynamicForces[0][0] = 0;
            HydrodynamicForces[0][1] = 0;
            HydrodynamicTorque[0]    = 0;
            int RequiredOrder = U[0].Basis.Degree * 3 + 2;

            Console.WriteLine("Forces coeff: {0}, order = {1}", LsTrk.CutCellQuadratureType, RequiredOrder);
            double[]            Forces = new double[SpatialDim];
            SinglePhaseField[]  UA     = U.ToArray();
            ConventionalDGField pA     = null;

            pA = P;
            if (IncludeTranslation)
            {
                for (int d = 0; d < SpatialDim; d++)
                {
                    void ErrFunc(int CurrentCellID, int Length, NodeSet Ns, MultidimensionalArray result)
                    {
                        int NumberOfNodes = result.GetLength(1);
                        MultidimensionalArray Grad_UARes = MultidimensionalArray.Create(Length, NumberOfNodes, SpatialDim, SpatialDim);
                        MultidimensionalArray pARes      = MultidimensionalArray.Create(Length, NumberOfNodes);
                        var Normals = LsTrk.DataHistories[0].Current.GetLevelSetNormals(Ns, CurrentCellID, Length);

                        for (int i = 0; i < SpatialDim; i++)
                        {
                            UA[i].EvaluateGradient(CurrentCellID, Length, Ns, Grad_UARes.ExtractSubArrayShallow(-1, -1, i, -1), 0, 1);
                        }
                        pA.Evaluate(CurrentCellID, Length, Ns, pARes);
                        for (int j = 0; j < Length; j++)
                        {
                            for (int k = 0; k < NumberOfNodes; k++)
                            {
                                result[j, k] = ForceIntegration.CalculateStressTensor(Grad_UARes, pARes, Normals, muA, k, j, this.SpatialDim, d);
                            }
                        }
                    }

                    var SchemeHelper         = LsTrk.GetXDGSpaceMetrics(new[] { LsTrk.GetSpeciesId("A") }, RequiredOrder, 1).XQuadSchemeHelper;
                    CellQuadratureScheme cqs = SchemeHelper.GetLevelSetquadScheme(0, CutCells_P(LsTrk));
                    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)
                    {
                        Forces[d] = ParticleAuxillary.ForceTorqueSummationWithNeumaierArray(Forces[d], ResultsOfIntegration, Length);
                    }
                                                 ).Execute();
                }
            }

            double Torque = 0;

            if (IncludeRotation)
            {
                void ErrFunc2(int j0, int Len, NodeSet Ns, MultidimensionalArray result)
                {
                    int K = result.GetLength(1); // No nof Nodes
                    MultidimensionalArray Grad_UARes = MultidimensionalArray.Create(Len, K, SpatialDim, SpatialDim);;
                    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 < SpatialDim; 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++)
                    {
                        MultidimensionalArray tempArray = Ns.CloneAs();
                        LsTrk.GridDat.TransformLocal2Global(Ns, tempArray, j0 + j);
                        for (int k = 0; k < K; k++)
                        {
                            result[j, k] = ForceIntegration.CalculateTorqueFromStressTensor2D(Grad_UARes, pARes, Normals, tempArray, muA, k, j, Position[0]);
                        }
                    }
                }

                var SchemeHelper2         = LsTrk.GetXDGSpaceMetrics(new[] { LsTrk.GetSpeciesId("A") }, RequiredOrder, 1).XQuadSchemeHelper;
                CellQuadratureScheme cqs2 = SchemeHelper2.GetLevelSetquadScheme(0, CutCells_P(LsTrk));
                CellQuadrature.GetQuadrature(new int[] { 1 }, LsTrk.GridDat,
                                             cqs2.Compile(LsTrk.GridDat, RequiredOrder),
                                             delegate(int i0, int Length, QuadRule QR, MultidimensionalArray EvalResult)
                {
                    ErrFunc2(i0, Length, QR.Nodes, EvalResult.ExtractSubArrayShallow(-1, -1, 0));
                },
                                             delegate(int i0, int Length, MultidimensionalArray ResultsOfIntegration)
                {
                    Torque = ParticleAuxillary.ForceTorqueSummationWithNeumaierArray(Torque, ResultsOfIntegration, Length);
                }
                                             ).Execute();
            }
            // add gravity
            {
                Forces[1] += (particleDensity - fluidDensity) * Area_P * GravityVertical;
            }
            // Sum forces and moments over all MPI processors
            // ==============================================
            {
                int      NoOfVars    = 1 + SpatialDim;
                double[] StateBuffer = new double[NoOfVars];
                StateBuffer[0] = Torque;
                for (int d = 0; d < SpatialDim; d++)
                {
                    StateBuffer[1 + d] = Forces[d];
                }
                double[] GlobalStateBuffer = StateBuffer.MPISum();
                Torque = GlobalStateBuffer[0];
                for (int d = 0; d < SpatialDim; d++)
                {
                    Forces[d] = GlobalStateBuffer[1 + d];
                }
            }
            if (neglectAddedDamping == false)
            {
                double fest = Forces[0];
                Forces[0] = Forces[0] + AddedDampingCoefficient * dt * (AddedDampingTensor[0, 0] * TranslationalAcceleration[0][0] + AddedDampingTensor[1, 0] * TranslationalAcceleration[0][1] + AddedDampingTensor[0, 2] * RotationalAcceleration[0]);
                Forces[1] = Forces[1] + AddedDampingCoefficient * dt * (AddedDampingTensor[0, 1] * TranslationalAcceleration[0][0] + AddedDampingTensor[1, 1] * TranslationalAcceleration[0][1] + AddedDampingTensor[1, 2] * RotationalAcceleration[0]);
                Torque   += AddedDampingCoefficient * dt * (AddedDampingTensor[2, 0] * TranslationalAcceleration[0][0] + AddedDampingTensor[2, 1] * TranslationalAcceleration[0][1] + AddedDampingTensor[2, 2] * RotationalAcceleration[0]);
            }

            if (iteration_counter_P == -1 || NotFullyCoupled || iteration_counter_P == 250 || stupidcounter == 0)
            {
                Console.WriteLine();
                if (iteration_counter_P == 1)
                {
                    Console.WriteLine("First iteration of the current timestep, all relaxation factors are set to 1");
                }
                if (iteration_counter_P == 250)
                {
                    Console.WriteLine("250 iterations, I'm trying to jump closer to the real solution");
                }
                for (int d = 0; d < SpatialDim; d++)
                {
                    HydrodynamicForces[0][d] = 0;
                    if (Math.Abs(Forces[d]) < ForceAndTorque_convergence * 1e-2 && ClearSmallValues == true)
                    {
                        Forces[d] = 0;
                    }
                    HydrodynamicForces[0][d] = Forces[d];
                }
                HydrodynamicTorque[0] = 0;
                if (Math.Abs(Torque) < ForceAndTorque_convergence * 1e-2 && ClearSmallValues == true)
                {
                    Torque = 0;
                }
                HydrodynamicTorque[0] = Torque;
                stupidcounter         = 1;
            }
            else
            {
                double[] RelaxatedForceAndTorque = Underrelaxation.RelaxatedForcesAndTorque(Forces, Torque, ForcesPrevIteration, TorquePrevIteration, ForceAndTorque_convergence, underrelaxation_factor, ClearSmallValues, AddaptiveUnderrelaxation, AverageDistance, iteration_counter_P);
                for (int d = 0; d < SpatialDim; d++)
                {
                    HydrodynamicForces[0][d] = RelaxatedForceAndTorque[d];
                }
                HydrodynamicTorque[0] = RelaxatedForceAndTorque[SpatialDim];
            }
            //for (int d = 0; d < SpatialDim; d++)// changes sign depending on the sign of Forces[d], should increase the convergence rate. (testing needed)
            //{
            //    if (Math.Abs(HydrodynamicForces[0][d] - Forces[0]) > Math.Abs(Forces[d]))
            //    {
            //        HydrodynamicForces[0][d] *= -1;
            //    }
            //}
            if (double.IsNaN(HydrodynamicForces[0][0]) || double.IsInfinity(HydrodynamicForces[0][0]))
            {
                throw new ArithmeticException("Error trying to calculate hydrodynamic forces (x). Value:  " + HydrodynamicForces[0][0]);
            }
            if (double.IsNaN(HydrodynamicForces[0][1]) || double.IsInfinity(HydrodynamicForces[0][1]))
            {
                throw new ArithmeticException("Error trying to calculate hydrodynamic forces (y). Value:  " + HydrodynamicForces[0][1]);
            }
            if (double.IsNaN(HydrodynamicTorque[0]) || double.IsInfinity(HydrodynamicTorque[0]))
            {
                throw new ArithmeticException("Error trying to calculate hydrodynamic torque. Value:  " + HydrodynamicTorque[0]);
            }
        }
Esempio n. 19
0
        /// <summary>
        /// accumulate this field to a DG field
        /// </summary>
        /// <param name="alpha"></param>
        /// <param name="DGField"></param>
        /// <param name="mask">optional cell mask</param>
        public void AccToDGField(double alpha, ConventionalDGField DGField, CellMask mask = null)
        {
            if (!DGField.Basis.Equals(this.m_Basis.ContainingDGBasis))
            {
                throw new ArgumentException("Basis does not match.");
            }

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

            int[] _K   = m_Basis.NodesPerCell;
            int   L    = m_Basis.ContainingDGBasis.Length;
            int   pDeg = m_Basis.ContainingDGBasis.Degree;

            double[][] _NodalCoordinates = _K.Select(K => new double[K]).ToArray();
            double[]   ModalCoordinates  = new double[L];
            double[]   InterCoordinates  = new double[L]; // only used for curved cells

            if (mask == null)
            {
                mask = CellMask.GetFullMask(this.Basis.GridDat);
            }

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

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

                    // transform
                    DGField.Coordinates.GetRow(j, ModalCoordinates);
                    if (CellData.IsCellAffineLinear(j))
                    {
                        MtxM2N[iKref].GEMV(alpha / Trafo[j], NodalCoordinates, 1.0, ModalCoordinates);
                    }
                    else
                    {
                        MtxM2N[iKref].GEMV(alpha, NodalCoordinates, 0.0, InterCoordinates);

                        var OnbTrafo = gdat.ChefBasis.OrthonormalizationTrafo.GetValue_Cell(j, 1, pDeg).ExtractSubArrayShallow(0, -1, -1);
                        //OnbTrafo.GetInverse().gemv(1.0, InterCoordinates, 0.0, ModalCoordinates);
                        OnbTrafo.Solve(ModalCoordinates, InterCoordinates);
                    }
                    // save
                    DGField.Coordinates.SetRow(j, ModalCoordinates);
                }
            }
        }
Esempio n. 20
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="jCell"></param>
        /// <param name="Stencil_jCell"></param>
        /// <param name="input">input</param>
        /// <param name="output">result</param>
        static void FilterStencilProjection(SinglePhaseField output, int jCell, int[] Stencil_jCells, ConventionalDGField input)
        {
            // implementation notes: Fk, persönliche Notizen, 17oct13
            // ------------------------------------------------------
            if (output.Basis.Degree < output.Basis.Degree)
            {
                throw new ArgumentException();
            }

            int N = output.Basis.Length;   // Basis dimension of 'g' in cell 'jCell'
            int K = Stencil_jCells.Length; // number of cells in stencil

            var ExPolMtx = MultidimensionalArray.Create(K, N, N);

            int[,] CellPairs = new int[K, 2];
            for (int k = 0; k < K; k++)
            {
                CellPairs[k, 0] = jCell;
                CellPairs[k, 1] = Stencil_jCells[k];
            }
            output.Basis.GetExtrapolationMatrices(CellPairs, ExPolMtx, null);

            MultidimensionalArray MassMatrix = MultidimensionalArray.Create(N, N);

            MassMatrix.AccEye(1.0); // Mass matrix in jCell itself

            //for (int k = 0; k < K; k++) { // over stencil members ...
            //    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 += ExPolMtx[k, i, m]*ExPolMtx[k, i, l];
            //            }

            //            MassMatrix[l, m] += mass_lm;
            //        }
            //    }
            //}
            MassMatrix.Multiply(1.0, ExPolMtx, ExPolMtx, 1.0, "lm", "kim", "kil");


            double[] RHS = new double[N];
            double[] f2  = new double[N];
            for (int n = Math.Min(input.Basis.Length, N) - 1; n >= 0; n--)
            {
                RHS[n] = input.Coordinates[jCell, n];
            }
            for (int k = 0; k < K; k++)
            {
                for (int n = Math.Min(input.Basis.Length, N) - 1; n >= 0; n--)
                {
                    f2[n] = input.Coordinates[Stencil_jCells[k], n];
                }
                for (int l = 0; l < N; l++)
                {
                    double acc = 0;
                    for (int i = 0; i < N; i++)
                    {
                        acc += ExPolMtx[k, i, l] * f2[i];
                    }
                    RHS[l] += acc;
                }
            }

            double[] g1 = new double[N];
            MassMatrix.Solve(g1, RHS);

            output.Coordinates.SetRow(jCell, g1);
        }
Esempio n. 21
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);
        }
Esempio n. 22
0
        /// <summary>
        /// Update forces and torque acting from fluid onto the particle
        /// </summary>
        /// <param name="U"></param>
        /// <param name="P"></param>
        /// <param name="LsTrk"></param>
        /// <param name="muA"></param>
        public void UpdateForcesAndTorque(VectorField <SinglePhaseField> U, SinglePhaseField P,
                                          LevelSetTracker LsTrk,
                                          double muA)
        {
            if (skipForceIntegration)
            {
                skipForceIntegration = false;
                return;
            }

            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;

            #region Force
            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());
                CellQuadratureScheme cqs = SchemeHelper.GetLevelSetquadScheme(0, this.cutCells_P(LsTrk));


                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();
            }
            #endregion

            #region Torque
            double           torque   = 0;
            ScalarFunctionEx ErrFunc2 = 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);
                }

                //var trafo = LsTrk.GridDat.Edges.Edge2CellTrafos;
                //var trafoIdx = LsTrk.GridDat.TransformLocal2Global(Ns)
                //var transFormed = trafo[trafoIdx].Transform(Nodes);
                //var newVertices = transFormed.CloneAs();
                //GridData.TransformLocal2Global(transFormed, newVertices, jCell);


                MultidimensionalArray tempArray = Ns.CloneAs();

                LsTrk.GridDat.TransformLocal2Global(Ns, tempArray, j0);

                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] * this.radius_P;
                        acc *= -Normals[j, k, 1] * (this.currentPos_P[0][1] - tempArray[k, 1]).Abs();


                        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] * this.radius_P;
                        acc2 *= Normals[j, k, 0] * (this.currentPos_P[0][0] - tempArray[k, 0]).Abs();

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

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

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

                                         ).Execute();

            double   underrelaxationFT = 1.0;
            double[] temp_underR       = new double[D + 1];
            for (int k = 0; k < D + 1; k++)
            {
                temp_underR[k] = underrelaxation_factor;
            }
            if (iteration_counter_P == 0)
            {
                underrelaxationFT = 1;
            }
            else if (underrelaxationFT_constant == true)
            {
                underrelaxationFT = underrelaxation_factor * Math.Pow(10, underrelaxationFT_exponent);
            }
            else if (underrelaxationFT_constant == false)
            {
                //double[] temp_underR = new double[D + 1];
                bool underrelaxation_ok = false;
                underrelaxationFT_exponent = 1;
                for (int j = 0; j < D; j++)
                {
                    underrelaxation_ok = false;
                    temp_underR[j]     = underrelaxation_factor;
                    for (int i = 0; underrelaxation_ok == false; i++)
                    {
                        if (Math.Abs(temp_underR[j] * forces[j]) > Math.Abs(forces_P[0][j]))
                        {
                            underrelaxationFT_exponent -= 1;
                            temp_underR[j]              = underrelaxation_factor * Math.Pow(10, underrelaxationFT_exponent);
                        }
                        else
                        {
                            underrelaxation_ok = true;
                            if (underrelaxationFT_exponent > -0)
                            {
                                underrelaxationFT_exponent = -0;
                                temp_underR[j]             = underrelaxation_factor * Math.Pow(10, underrelaxationFT_exponent);
                            }
                        }
                    }
                }
                underrelaxation_ok = false;
                temp_underR[D]     = underrelaxation_factor;
                for (int i = 0; underrelaxation_ok == false; i++)
                {
                    if (Math.Abs(temp_underR[D] * torque) > Math.Abs(torque_P[0]))
                    {
                        underrelaxationFT_exponent -= 1;
                        temp_underR[D]              = underrelaxation_factor * Math.Pow(10, underrelaxationFT_exponent);
                    }
                    else
                    {
                        underrelaxation_ok = true;
                        if (underrelaxationFT_exponent > -0)
                        {
                            underrelaxationFT_exponent = -0;
                            temp_underR[D]             = underrelaxation_factor * Math.Pow(10, underrelaxationFT_exponent);
                        }
                    }
                }
            }

            double[] forces_underR = new double[D];
            for (int i = 0; i < D; i++)
            {
                forces_underR[i] = temp_underR[i] * forces[i] + (1 - temp_underR[i]) * forces_P[0][i];
            }
            double torque_underR = temp_underR[D] * torque + (1 - temp_underR[D]) * torque_P[0];
            this.forces_P.Insert(0, forces_underR);
            forces_P.Remove(forces_P.Last());
            this.torque_P.Remove(torque_P.Last());
            this.torque_P.Insert(0, torque_underR);

            #endregion
        }
Esempio n. 23
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);
        }
        static void ComputeErrors(Func <ConventionalDGField, ConventionalDGField, double> distFunc,
                                  IEnumerable <string> FieldsToCompare,
                                  IEnumerable <ITimestepInfo> timestepS,
                                  out double[] GridRes,
                                  out Dictionary <string, int[]> __DOFs,
                                  out Dictionary <string, double[]> Errors,
                                  out Guid[] timestepIds)
        {
            using (var tr = new FuncTrace()) {
                if (FieldsToCompare == null || FieldsToCompare.Count() <= 0)
                {
                    throw new ArgumentException("empty list of field names.");
                }
                if (timestepS == null || timestepS.Count() < 1)
                {
                    throw new ArgumentException("requiring at least two different solutions.");
                }

                // load the DG-Fields
                List <IEnumerable <DGField> > fields = new List <IEnumerable <DGField> >(); // 1st index: grid / 2nd index: enumeration
                int i = 1;
                foreach (var timestep in timestepS)
                {
                    //Console.WriteLine("Loading timestep {0} of {1}, ({2})...", i, timestepS.Count(), timestep.ID);
                    fields.Add(timestep.Fields);
                    i++;
                    //Console.WriteLine("done (Grid has {0} cells).", fields.Last().First().GridDat.CellPartitioning.TotalLength);
                }


                // sort according to grid resolution
                {
                    var s         = fields.OrderBy(f => f.First().GridDat.CellPartitioning.TotalLength).ToArray();
                    var orgfields = fields.ToArray();
                    fields.Clear();
                    fields.AddRange(s);
                    s = null;

                    // filter equal grids:
                    while (fields.Count >= 2 &&
                           (fields[fields.Count - 1].First().GridDat.CellPartitioning.TotalLength
                            == fields[fields.Count - 2].First().GridDat.CellPartitioning.TotalLength))
                    {
                        fields.RemoveAt(fields.Count - 2);
                    }

                    // extract timestep Id's
                    timestepIds = new Guid[fields.Count];
                    for (int z = 0; z < timestepIds.Length; z++)
                    {
                        int idx = orgfields.IndexOf(fields[z], (f1, f2) => object.ReferenceEquals(f1, f2));
                        timestepIds[z] = timestepS.ElementAt(idx).ID;
                    }
                }

                // grids and resolution
                GridData[] gDataS = fields.Select(fc => GridHelper.ExtractGridData(fc.First().GridDat)).ToArray();
                GridRes = gDataS.Take(gDataS.Length - 1).Select(gd => gd.Cells.h_minGlobal).ToArray();

                // compute the errors
                Errors = new Dictionary <string, double[]>();
                __DOFs = new Dictionary <string, int[]>();
                foreach (string Identification in FieldsToCompare)
                {
                    double[] L2Error = new double[gDataS.Length - 1];
                    int[]    dof     = new int[gDataS.Length - 1];

                    for (int iLevel = 0; iLevel < gDataS.Length - 1; iLevel++)
                    {
                        //Console.WriteLine("Computing L2 error of '{0}' on level {1} ...", Identification, iLevel);
                        tr.Info(string.Format("Computing L2 error of '{0}' on level {1} ...", Identification, iLevel));

                        ConventionalDGField fine   = (ConventionalDGField)(fields.Last().Single(fi => fi.Identification == Identification));
                        ConventionalDGField coarse = (ConventionalDGField)(fields.ElementAt(iLevel).Single(fi => fi.Identification == Identification));

                        L2Error[iLevel] = distFunc(coarse, fine);
                        dof[iLevel]     = coarse.Mapping.TotalLength;

                        //Console.WriteLine("done (Error is {0:0.####E-00}).", L2Error[iLevel]);
                        tr.Info(string.Format("done (Error is {0:0.####E-00}).", L2Error[iLevel]));
                    }

                    Errors.Add(Identification, L2Error);
                    __DOFs.Add(Identification, dof);
                }
            }
        }
Esempio n. 25
0
        /// <summary>
        ///  Take density-weighted mean value in cut-cells
        /// </summary>
        /// <param name="EvoVelocity"></param>
        /// <returns></returns>
        protected ConventionalDGField[] GetMeanVelocityFromXDGField(DGField[] EvoVelocity)
        {
            int D = EvoVelocity.Length;

            ConventionalDGField[] meanVelocity;

            Debug.Assert(this.XDGvelocity != null);

            meanVelocity = new ConventionalDGField[D];

            double   rho_A = this.Control.PhysicalParameters.rho_A, rho_B = this.Control.PhysicalParameters.rho_B;
            double   mu_A = this.Control.PhysicalParameters.mu_A, mu_B = this.Control.PhysicalParameters.mu_B;
            CellMask CC      = this.LsTrk.Regions.GetCutCellMask4LevSet(0);
            CellMask Neg     = this.LsTrk.Regions.GetLevelSetWing(0, -1).VolumeMask;
            CellMask Pos     = this.LsTrk.Regions.GetLevelSetWing(0, +1).VolumeMask;
            CellMask posNear = this.LsTrk.Regions.GetNearMask4LevSet(0, 1).Except(Neg);
            CellMask negNear = this.LsTrk.Regions.GetNearMask4LevSet(0, 1).Except(Pos);

            for (int d = 0; d < D; d++)
            {
                Basis b = this.XDGvelocity.Velocity[d].Basis.NonX_Basis;
                meanVelocity[d] = new SinglePhaseField(b);


                foreach (string spc in this.LsTrk.SpeciesNames)
                {
                    double rhoSpc;
                    double muSpc;
                    switch (spc)
                    {
                    case "A": rhoSpc = rho_A; muSpc = mu_A; break;

                    case "B": rhoSpc = rho_B; muSpc = mu_B; break;

                    default: throw new NotSupportedException("Unknown species name '" + spc + "'");
                    }

                    double scale = 1.0;
                    switch (this.Control.InterAverage)
                    {
                    case XBase_Control.InterfaceAveraging.mean: {
                        scale = 0.5;
                        break;
                    }

                    case XBase_Control.InterfaceAveraging.density: {
                        scale = rhoSpc / (rho_A + rho_B);
                        break;
                    }

                    case XBase_Control.InterfaceAveraging.viscosity: {
                        scale = muSpc / (mu_A + mu_B);
                        break;
                    }
                    }

                    meanVelocity[d].Acc(scale, ((XDGField)EvoVelocity[d]).GetSpeciesShadowField(spc), CC);
                    switch (spc)
                    {
                    //case "A": meanVelocity[d].Acc(1.0, ((XDGField)EvoVelocity[d]).GetSpeciesShadowField(spc), Neg.Except(CC)); break;
                    case "A": meanVelocity[d].Acc(1.0, ((XDGField)EvoVelocity[d]).GetSpeciesShadowField(spc), negNear); break;

                    case "B": meanVelocity[d].Acc(1.0, ((XDGField)EvoVelocity[d]).GetSpeciesShadowField(spc), posNear); break;

                    default: throw new NotSupportedException("Unknown species name '" + spc + "'");
                    }
                }
            }

            return(meanVelocity);
        }
Esempio n. 26
0
 public void ExtVelSolve_Cut(SinglePhaseField Phi, VectorField <SinglePhaseField> GradPhi, ConventionalDGField ExtProperty, ref double ExtPropertyMin, ref double ExtPropertyMax, int jCell, CellMask Accepted, double signMod)
 {
 }