示例#1
0
 /// <summary>
 /// ctor
 /// </summary>
 internal CellData(GridData _owner)
 {
     m_owner = _owner;
 }
示例#2
0
 /// <summary>
 /// ctor
 /// </summary>
 internal _BasisData(GridData o) : base(o)
 {
     m_Owner = o;
 }
示例#3
0
        /// <summary>
        /// Computes the maximum admissible step-size according to
        /// GassnerEtAl2008, equation 67.
        /// </summary>
        /// <param name="i0"></param>
        /// <param name="Length"></param>
        /// <returns></returns>
        protected override double GetCFLStepSize(int i0, int Length)
        {
            BoSSS.Foundation.Grid.Classic.GridData __gridData = (BoSSS.Foundation.Grid.Classic.GridData)(this.gridData);

            int    iKref                = __gridData.Cells.GetRefElementIndex(i0);
            int    noOfNodesPerCell     = base.EvaluationPoints[iKref].NoOfNodes;
            double scaling              = Math.Max(4.0 / 3.0, config.EquationOfState.HeatCapacityRatio / config.PrandtlNumber);
            MultidimensionalArray hmin  = __gridData.Cells.h_min;
            DGField artificialViscosity = workingSet.ParameterFields.Where(c => c.Identification.Equals(CNSVariables.ArtificialViscosity)).Single();
            double  cfl = double.MaxValue;

            switch (speciesMap)
            {
            case ImmersedSpeciesMap ibmMap: {
                MultidimensionalArray levelSetValues = ibmMap.Tracker.DataHistories[0].Current.GetLevSetValues(base.EvaluationPoints[iKref], i0, Length);
                SpeciesId             species        = ibmMap.Tracker.GetSpeciesId(ibmMap.Control.FluidSpeciesName);
                MultidimensionalArray hminCut        = ibmMap.CellAgglomeration.CellLengthScales[species];

                for (int i = 0; i < Length; i++)           // loop over cells...
                {
                    int cell = i0 + i;

                    double hminLocal = double.NaN;

                    // Return double.MaxValue in all IBM source cells
                    //if (ibmMap.sourceCells[cell]) {
                    //    cfl = double.MaxValue;
                    //    break;
                    //} else if (ibmMap.cutCellsThatAreNotSourceCells[cell]) {

                    if (ibmMap.cutCellsThatAreNotSourceCells[cell])
                    {
                        hminLocal = hminCut[cell];
                    }
                    else
                    {
                        hminLocal = hmin[cell];
                    }
                    Debug.Assert(double.IsNaN(hminLocal) == false, "Hmin is NaN");
                    Debug.Assert(double.IsInfinity(hminLocal) == false, "Hmin is Inf");

                    double nu = artificialViscosity.GetMeanValue(cell) / config.ReynoldsNumber;
                    Debug.Assert(!double.IsNaN(nu), "IBM ArtificialViscosityCFLConstraint: nu is NaN");
                    Debug.Assert(nu >= 0.0, "IBM ArtificialViscosityCFLConstraint: nu is negative");

                    bool setCFL = false;
                    for (int node = 0; node < noOfNodesPerCell; node++)
                    {
                        if (levelSetValues[i, node].Sign() != (double)ibmMap.Control.FluidSpeciesSign)
                        {
                            continue;
                        }
                        else if (setCFL == false)
                        {
                            setCFL = true;
                        }
                    }

                    if (nu != 0 && setCFL)
                    {
                        double cflhere = hminLocal * hminLocal / scaling / nu;
                        Debug.Assert(!double.IsNaN(cflhere), "Could not determine CFL number");

                        cfl = Math.Min(cfl, cflhere);
                    }
                }
            }
            break;

            default: {
                for (int i = 0; i < Length; i++)
                {
                    int      cell = i0 + i;
                    double   hminLocal;
                    CellData cellData = __gridData.Cells;

                    //if (!cellData.IsCellAffineLinear(cell)) {
                    //    //hminLocal = cellData.CellLengthScale[cell] * 2;
                    //    hminLocal = cellData.GetCellVolume(cell) / cellData.CellSurfaceArea[cell];
                    //} else {
                    hminLocal = hmin[cell];
                    //}

                    Debug.Assert(double.IsNaN(hminLocal) == false, "Hmin is NaN");
                    Debug.Assert(double.IsInfinity(hminLocal) == false, "Hmin is Inf");

                    double nu = artificialViscosity.GetMeanValue(cell) / config.ReynoldsNumber;
                    Debug.Assert(!double.IsNaN(nu), "ArtificialViscosityCFLConstraint: nu is NaN");
                    Debug.Assert(nu >= 0.0, "IBM ArtificialViscosityCFLConstraint: nu is negative");

                    if (nu != 0)
                    {
                        double cflhere = hminLocal * hminLocal / scaling / nu;
                        Debug.Assert(!double.IsNaN(cflhere), "Could not determine CFL number");

                        cfl = Math.Min(cfl, cflhere);
                    }
                }
            }
            break;
            }

            if (cfl == double.MaxValue)
            {
                return(cfl);
            }
            else
            {
                int degree      = workingSet.ConservativeVariables.Max(f => f.Basis.Degree);
                int twoNPlusOne = 2 * degree + 1;
                return(cfl * GetBetaMax(degree) / twoNPlusOne / twoNPlusOne / Math.Sqrt(CompressibleEnvironment.NumberOfDimensions));
            }
        }
示例#4
0
        /// <summary>
        /// Usually used after <see cref="MergeLogically(GridCommons, GridCommons)"/>; this method finds element boundaries
        /// which intersect geometrically, but not logically and inserts a <see cref="CellFaceTag"/> which connects those cells.
        /// </summary>
        /// <param name="g"></param>
        /// <param name="upsampling"></param>
        /// <returns></returns>
        public static GridCommons Seal(GridCommons g, int upsampling = 4)
        {
            GridCommons R = g.CloneAs();

            g = null;
            GridData gdat = new GridData(R);
            int      D    = gdat.SpatialDimension;
            int      J    = gdat.Cells.NoOfLocalUpdatedCells;

            if (R.CellPartitioning.MpiSize > 1)
            {
                throw new NotSupportedException("Not supported in MPI-parallel mode.");
            }

            //NodeSet[] TestNodes = gdat.Edges.EdgeRefElements.Select(KrefEdge => KrefEdge.GetSubdivisionTree(upsampling).GlobalVertice).ToArray();
            NodeSet[] TestNodes = gdat.Edges.EdgeRefElements.Select(KrefEdge => KrefEdge.GetBruteForceQuadRule(upsampling, 1).Nodes).ToArray();
            // Its better to use vertices in the interior of the element; if we use vertices at the corners, we might get
            // intersection of edges that just share one point.


            // Define all edges that will be tested (set to boundary edges)
            // ============================================================
            int[] UnknownEdges = gdat.BoundaryEdges.ItemEnum.ToArray();
            int   L            = UnknownEdges.Sum(iEdg => TestNodes[gdat.Edges.GetRefElementIndex(iEdg)].NoOfNodes);

            // Transform nodes on edges (that should be tested) to global coordinates
            // ======================================================================

            MultidimensionalArray TestNodesGlobal = MultidimensionalArray.Create(L, D);
            MultidimensionalArray NormalsGlobal   = MultidimensionalArray.Create(L, D);

            int[] NodeToEdge = new int[L]; // pointer l -> Edge index, where l is the first index into 'TestNodesGlobal' & 'NormalsGlobal'


            int[,] E2C = gdat.Edges.CellIndices;
            int cnt = 0;

            foreach (int iEdg in UnknownEdges)
            {
                int     iKref = gdat.Edges.GetRefElementIndex(iEdg);
                NodeSet Ns    = TestNodes[iKref];
                int     K     = Ns.NoOfNodes;

                int[] I0 = new int[] { cnt, 0 };
                int[] IE = new int[] { cnt + K - 1, D - 1 };

                MultidimensionalArray TN = gdat.GlobalNodes.GetValue_EdgeSV(Ns, iEdg, 1);
                TestNodesGlobal.SetSubArray(TN.ExtractSubArrayShallow(0, -1, -1), I0, IE);

                MultidimensionalArray N1 = gdat.Edges.NormalsCache.GetNormals_Edge(Ns, iEdg, 1);
                NormalsGlobal.SetSubArray(N1.ExtractSubArrayShallow(0, -1, -1), I0, IE);

                for (int i = cnt; i < cnt + K; i++)
                {
                    NodeToEdge[i] = iEdg;
                }

                cnt += K;
            }

            // binary tree to speed up point localization
            int[]             pl_Permutation = new int[L];
            PointLocalization pl             = new PointLocalization(TestNodesGlobal, 0.01, pl_Permutation);

            Debug.Assert(!object.ReferenceEquals(pl.Points, TestNodesGlobal));

            // compare search edges to all other nodes
            // =======================================

            // mapping: cell --> Neighbour cell index, face index
            // 1st index: Cell index;
            // 2nd index: enumeration
            List <Tuple <int, int> >[] FoundPairings = new List <Tuple <int, int> > [gdat.Cells.NoOfCells];

            int[][] C2E = gdat.Cells.Cells2Edges;
            byte[,] E2F = gdat.Edges.FaceIndices;

            int cnt2 = 0;

            for (int iEdgC = 0; iEdgC < UnknownEdges.Length; iEdgC++)   // loop over edges that may get sealed
            {
                int     iEdg  = UnknownEdges[iEdgC];
                int     iKref = gdat.Edges.GetRefElementIndex(iEdg);
                NodeSet Ns    = TestNodes[iKref];
                int     K     = Ns.NoOfNodes;

                int jCell1 = E2C[iEdg, 0];
                Debug.Assert(E2C[iEdg, 1] < 0);
                int iFace1 = E2F[iEdg, 0];
                Debug.Assert(E2F[iEdg, 1] == byte.MaxValue);


                int[] I0 = new int[] { cnt2, 0 };
                int[] IE = new int[] { cnt2 + K - 1, D - 1 };
                MultidimensionalArray TN = TestNodesGlobal.ExtractSubArrayShallow(I0, IE);
                //MultidimensionalArray N1 = NormalsGlobal.ExtractSubArrayShallow(I0, IE);

                // find bounding box for edge
                BoundingBox bbEdge = new BoundingBox(TN);
                if (bbEdge.h_min / bbEdge.h_max < 1.0e-5)
                {
                    // very thin bounding box, thicken slightly
                    double delta = bbEdge.h_max * 1.0e-5;
                    for (int d = 0; d < D; d++)
                    {
                        bbEdge.Min[d] -= delta;
                        bbEdge.Max[d] += delta;
                    }
                }
                bbEdge.ExtendByFactor(0.01);

                // determine binary code for bounding box
                int bbEdgeSigBits;
                GeomBinTreeBranchCode bbEdgeCode = GeomBinTreeBranchCode.Combine(
                    GeomBinTreeBranchCode.CreateFormPoint(pl.PointsBB, bbEdge.Min),
                    GeomBinTreeBranchCode.CreateFormPoint(pl.PointsBB, bbEdge.Max),
                    out bbEdgeSigBits);

                // determine all points in bounding box
                int iP0, Len;
                pl.GetPointsInBranch(bbEdgeCode, bbEdgeSigBits, out iP0, out Len);

                // determine all edged which potentially overlap with edge 'iEdg'
                HashSet <int> PotOvrlap = new HashSet <int>(); // a set of edge indices
                for (int n = 0; n < Len; n++)
                {
                    int l   = iP0 + n;
                    int iPt = pl_Permutation[l];
                    Debug.Assert(GenericBlas.L2DistPow2(pl.Points.GetRow(l), TestNodesGlobal.GetRow(iPt)) <= 0);

                    int iOvlpEdge = NodeToEdge[iPt];
                    if (iOvlpEdge != iEdg)
                    {
                        PotOvrlap.Add(iOvlpEdge);
                    }
                }
                //int[] PotOvrlap = UnknownEdges.CloneAs();


                // determine actually overlapping boundary edges:
                foreach (int iOvrlapEdge in PotOvrlap)
                {
                    int jCell2 = E2C[iOvrlapEdge, 0];
                    Debug.Assert(E2C[iOvrlapEdge, 1] < 0);
                    if (jCell2 == jCell1)
                    {
                        continue;
                    }
                    int iFace2 = E2F[iOvrlapEdge, 0];
                    Debug.Assert(E2F[iOvrlapEdge, 1] == byte.MaxValue);


                    int AllreadyFound = FoundPairings[jCell1] == null ?
                                        0 : FoundPairings[jCell1].Where(tp => tp.Item1 == jCell2 && tp.Item2 == iFace1).Count();
                    if (AllreadyFound > 1)
                    {
                        throw new ApplicationException("Error in algorithmus.");
                    }
                    if (AllreadyFound > 0)
                    {
                        continue;
                    }

                    var    Kref_j2 = gdat.Cells.GetRefElement(jCell2);
                    double h       = Kref_j2.GetMaxDiameter();

                    MultidimensionalArray LocVtx_j2 = MultidimensionalArray.Create(K, D);
                    bool[] NewtonConvervence        = new bool[K];
                    gdat.TransformGlobal2Local(TN, LocVtx_j2, jCell2, NewtonConvervence);

                    for (int k = 0; k < K; k++)   // loop over all transformed points
                    {
                        if (!NewtonConvervence[k])
                        {
                            continue;
                        }

                        double[] pt      = LocVtx_j2.GetRow(k);
                        double[] ptClose = new double[D];
                        double   dist    = Kref_j2.ClosestPoint(pt, ptClose);

                        if (dist > h * 1.0e-8)
                        {
                            continue;
                        }

                        AffineManifold Face     = Kref_j2.GetFacePlane(iFace2);
                        double         FaceDist = Face.PointDistance(pt);

                        if (FaceDist.Abs() > 1.0e-8 * h)
                        {
                            continue;
                        }


                        NodeSet Ns2 = new NodeSet(Kref_j2, pt);
                        MultidimensionalArray Normals2 = MultidimensionalArray.Create(1, D);
                        gdat.Edges.GetNormalsForCell(Ns2, jCell2, iFace2, Normals2);

                        double[] N1d = NormalsGlobal.GetRow(cnt2 + k);
                        double[] N2d = Normals2.GetRow(0);


                        //Check if face normals points exactly in the opposite direction, 2 ways:
                        // 1) calculate angle between both normals -> bad choice because of Math.Acos
                        // 2) inner product of two opposite vectors is -1
                        //if (Math.Abs(Math.Abs(Math.Acos(GenericBlas.InnerProd(N1d, N2d))) - Math.PI) > 1.0e-8)
                        if (Math.Abs(GenericBlas.InnerProd(N1d, N2d) + 1.0) > 1.0e-8)
                        {
                            continue;
                        }



                        // if we reach this point, jCell1 should match with jCell2/iFace2
                        if (FoundPairings[jCell1] == null)
                        {
                            FoundPairings[jCell1] = new List <Tuple <int, int> >();
                        }
                        if (FoundPairings[jCell2] == null)
                        {
                            FoundPairings[jCell2] = new List <Tuple <int, int> >();
                        }
                        FoundPairings[jCell1].Add(new Tuple <int, int>(jCell2, iFace1));
                        FoundPairings[jCell2].Add(new Tuple <int, int>(jCell1, iFace2));
                        break; // no need to test jCell1 vs. jCell2 anymore
                    }
                }

                cnt2 += K;
            }

            // add the newly found pairings to the grid
            for (int j = 0; j < J; j++)
            {
                var fp = FoundPairings[j];
                if (fp != null)
                {
                    foreach (var t in fp)
                    {
                        ArrayTools.AddToArray(new CellFaceTag()
                        {
                            EdgeTag               = 0,
                            FaceIndex             = t.Item2,
                            ConformalNeighborship = false,
                            NeighCell_GlobalID    = gdat.CurrentGlobalIdPermutation.Values[t.Item1]
                        }, ref R.Cells[j].CellFaceTags);
                    }
                }
            }

            return(R);
        }