예제 #1
0
        /// <summary>
        /// Find the cell which contains some point <paramref name="pt"/>;
        /// If <paramref name="pt"/> is not within any cell, the cell with its
        /// center nearest to <paramref name="pt"/> is returned and in this
        /// case, <paramref name="IsInside"/> is false.
        /// </summary>
        /// <param name="pt"></param>
        /// <param name="GlobalId">
        /// the Global ID of the found cell;
        /// </param>
        /// <param name="GlobalIndex">
        /// the Global index of the found cell;
        /// </param>
        /// <param name="IsInside">
        /// true, if <paramref name="pt"/> is within the cell identified by
        /// <paramref name="GlobalId"/>;
        /// otherwise, false;
        /// </param>
        /// <param name="OnThisProcess">
        /// If true, the cell <paramref name="GlobalId"/> is located on the current MPI process.
        /// </param>
        /// <param name="CM">
        /// optional cell mask to restrict the search region
        /// </param>
        /// <remarks>
        /// This operation is relatively costly, as it needs to perform a sweep
        /// over all cells, it should not be used for performance-critical
        /// tasks.<br/>
        /// This operation is MPI-collective, the output-values are equal on
        /// all MPI-processors.
        /// </remarks>
        static public void LocatePoint(this IGridData gdat, double[] pt, out long GlobalId, out long GlobalIndex, out bool IsInside, out bool OnThisProcess, CellMask CM = null)
        {
            using (new FuncTrace()) {
                if (pt.Length != gdat.SpatialDimension)
                {
                    throw new ArgumentException("length must be equal to spatial dimension", "pt");
                }
                ilPSP.MPICollectiveWatchDog.Watch(MPI.Wrappers.csMPI.Raw._COMM.WORLD);

                int MpiRank = gdat.CellPartitioning.MpiRank;
                int MpiSize = gdat.CellPartitioning.MpiSize;

                int J = gdat.iLogicalCells.NoOfLocalUpdatedCells;
                int D = gdat.SpatialDimension;

                MultidimensionalArray center = MultidimensionalArray.Create(1, 1, D);  // cell center in global coordinates

                MultidimensionalArray _pt = MultidimensionalArray.Create(1, D);        // point to search for
                for (int d = 0; d < D; d++)
                {
                    _pt[0, d] = pt[d];
                }
                MultidimensionalArray _pt_local = MultidimensionalArray.Create(1, 1, D); // .. in cell-local coordinate
                double[] pt_local = new double[D];


                // sweep over locally updated cells ...
                // ====================================

                int    jL_MinDistCel = 0; // logical cell with minimum distance
                int    jG_MinDistCel = 0; // geometrical cell with minimum distance
                double MinDist       = double.MaxValue;

                int j_Within = -1;
                if (CM == null)
                {
                    CM = CellMask.GetFullMask(gdat);
                }

                foreach (int jL in CM.ItemEnum)
                {
                    foreach (int j in gdat.GetGeometricCellIndices(jL))
                    {
                        // compute distance
                        // ================
                        {
                            var smplx = gdat.iGeomCells.GetRefElement(j);
                            gdat.TransformLocal2Global(smplx.Center, j, 1, center, 0);

                            double dist = 0;
                            for (int d = 0; d < D; d++)
                            {
                                double del = pt[d] - center[0, 0, d];
                                dist += del * del;
                            }

                            dist = Math.Sqrt(dist);

                            if (dist < MinDist)
                            {
                                MinDist       = dist;
                                jL_MinDistCel = jL;
                                jG_MinDistCel = j;
                            }
                        }

                        // transform back into cell
                        // ========================
                        {
                            try {
                                gdat.TransformGlobal2Local(_pt, _pt_local, j, 1, 0);
                                for (int d = 0; d < D; d++)
                                {
                                    pt_local[d] = _pt_local[0, 0, d];
                                }

                                var smplx = gdat.iGeomCells.GetRefElement(j);

                                if (smplx.IsWithin(pt_local))
                                {
                                    j_Within = j;
                                }
                            } catch (ArithmeticException) {
                                // probably outside...
                            }
                        }
                    }
                }

                // ========================================
                // First case: point is inside of some cell
                // ========================================

                int lowestWithinRank = j_Within >= 0 ? MpiRank : int.MaxValue;
                lowestWithinRank = lowestWithinRank.MPIMin(); // lowest rank which found a cell that contains the point:
                //                                               this rank will be the official finder!

                if (lowestWithinRank < MpiSize)
                {
                    LocatPointHelper(gdat, lowestWithinRank, j_Within, out GlobalId, out GlobalIndex, out OnThisProcess);
                    IsInside = true;
                    return;
                }


                // ========================================
                // Second case: point is outside of all cells
                // ========================================

                double MinDistGlobal     = MinDist.MPIMin();
                int    lowestMinimumRank = MinDistGlobal == MinDist ? MpiRank : int.MaxValue;
                lowestMinimumRank = lowestMinimumRank.MPIMin(); // find minimum rank on which the global minimum was reached.
                if (lowestMinimumRank < 0 || lowestMinimumRank >= MpiSize)
                {
                    throw new ApplicationException();
                }

                LocatPointHelper(gdat, lowestMinimumRank, jL_MinDistCel, out GlobalId, out GlobalIndex, out OnThisProcess);
                IsInside = false;
                return;
            }
        }
예제 #2
0
        /// <summary>
        /// computes a global time-step length ("delta t") according to the
        /// Courant-Friedrichs-Lax - criterion, based on a velocity
        /// vector (<paramref name="velvect"/>) and the cell size
        /// this.<see cref="Cells"/>.<see cref="CellData.h_min"/>;
        /// </summary>
        /// <param name="velvect">
        /// components of a velocity vector
        /// </param>
        /// <param name="max">
        /// an upper maximum for the return value; This is useful if the velocity
        /// defined by <paramref name="velvect"/> is 0 or very small everywhere;
        /// </param>
        /// <param name="cm">
        /// optional restriction of domain.
        /// </param>
        /// <returns>
        /// the minimum (over all cells j in all processes) of <see cref="CellData.h_min"/>[j]
        /// over v, where v is the Euclidean norm of a vector build from
        /// <paramref name="velvect"/>;
        /// This vector is evaluated at cell center and all cell vertices.
        /// The return value is the same on all processes;
        /// </returns>
        static public double ComputeCFLTime <T>(this IGridData __gdat, IEnumerable <T> velvect, double max, CellMask cm = null)
            where T : DGField //
        {
            using (var tr = new FuncTrace()) {
                GridData gdat = (GridData)__gdat;

                ilPSP.MPICollectiveWatchDog.Watch(MPI.Wrappers.csMPI.Raw._COMM.WORLD);

                T[] _velvect = velvect.ToArray();

                if (cm == null)
                {
                    cm = CellMask.GetFullMask(gdat);
                }

                int D     = gdat.SpatialDimension;
                var KrefS = gdat.Grid.RefElements;

                // find cfl number on this processor
                // ---------------------------------

                var m_CFL_EvalPoints = new NodeSet[KrefS.Length];
                for (int i = 0; i < KrefS.Length; i++)
                {
                    var Kref = KrefS[i];
                    int N    = Kref.NoOfVertices + 1;

                    MultidimensionalArray vert = MultidimensionalArray.Create(N, D);
                    vert.SetSubArray(Kref.Vertices, new int[] { 0, 0 }, new int[] { N - 2, D - 1 });

                    m_CFL_EvalPoints[i] = new NodeSet(Kref, vert);
                }



                // evaluators an memory for result
                int       VecMax  = 1000;
                DGField[] evalers = new DGField[_velvect.Length];
                MultidimensionalArray[] fieldValues = new MultidimensionalArray[_velvect.Length];
                for (int i = 0; i < _velvect.Length; i++)
                {
                    evalers[i]     = _velvect[i];
                    fieldValues[i] = MultidimensionalArray.Create(VecMax, m_CFL_EvalPoints[0].NoOfNodes);
                }

                var    h_min   = gdat.Cells.h_min;
                int    K       = _velvect.Length;
                double cflhere = max;

                //for (int j = 0; j < J; j += VectorSize) {
                foreach (Chunk chk in cm)
                {
                    int VectorSize = VecMax;
                    for (int j = chk.i0; j < chk.JE; j += VectorSize)
                    {
                        if (j + VectorSize > chk.JE + 1)
                        {
                            VectorSize = chk.JE - j;
                        }
                        VectorSize = gdat.Cells.GetNoOfSimilarConsecutiveCells(CellInfo.RefElementIndex_Mask, j, VectorSize);


                        int iKref = gdat.Cells.GetRefElementIndex(j);
                        int N     = m_CFL_EvalPoints[iKref].GetLength(0);

                        if (fieldValues[0].GetLength(0) != VectorSize)
                        {
                            for (int i = 0; i < _velvect.Length; i++)
                            {
                                fieldValues[i].Allocate(VectorSize, N);
                            }
                        }

                        for (int k = 0; k < K; k++)
                        {
                            evalers[k].Evaluate(j, VectorSize, m_CFL_EvalPoints[iKref], fieldValues[k], 0, 0.0);
                        }

                        // loop over cells ...
                        for (int jj = j; jj < j + VectorSize; jj++)
                        {
                            // loop over nodes ...
                            for (int n = 0; n < N; n++)
                            {
                                double velabs = 0;

                                // loop over velocity components ...
                                for (int k = 0; k < K; k++)
                                {
                                    double v = fieldValues[k][jj - j, n];
                                    velabs += v * v;
                                }

                                velabs = Math.Sqrt(velabs);

                                double cfl = h_min[jj] / velabs;
                                cflhere = Math.Min(cfl, cflhere);
                            }
                        }
                    }
                }

                // find the minimum over all processes via MPI and return
                // ------------------------------------------------------
                double cfltotal;
                unsafe {
                    csMPI.Raw.Allreduce((IntPtr)(&cflhere), (IntPtr)(&cfltotal), 1, csMPI.Raw._DATATYPE.DOUBLE, csMPI.Raw._OP.MIN, csMPI.Raw._COMM.WORLD);
                }
                tr.Info("computed CFL timestep: " + cfltotal);
                return(cfltotal);
            }
        }