Пример #1
0
        /// <summary>
        /// returns global unique indices which correlate to a certain sub-set of ...
        /// <list type="bullet">
        /// <item>the mappings's basis (<paramref name="mapping"/>, <see cref="UnsetteledCoordinateMapping.BasisS"/>).</item>
        /// <item>species (<paramref name="_SpcIds"/>).</item>
        /// <item>cells (<paramref name="cm"/>).</item>
        /// </list>
        /// </summary>
        /// <param name="mapping">
        /// the mapping
        /// </param>
        /// <param name="Fields">
        /// determines which fields should be in the sub-vector-indices-list
        /// </param>
        /// <param name="_SpcIds">
        /// determines which species should be in the sub-vector-indices-list; null indicates all species.
        /// </param>
        /// <param name="cm">
        /// determines which cells should be in the sub-vector-indices-list; null indicates all cells.
        /// </param>
        /// <param name="regions">
        /// Determines which XDG-coordinate belongs to which species.
        /// </param>
        /// <param name="presenceTest">
        /// if true, cells where some species has zero measure are excluded from the sub-vector-indices-list.
        /// </param>
        /// <param name="drk">
        /// a cell-agglomeration object: if null, ignored; if provided,
        /// cells which are eliminated by the agglomeration are excluded from the sub-vector-indices-list
        /// </param>
        /// <returns>a list of global (over all MPI processes) unique indices.</returns>
        static public int[] GetSubvectorIndices(this UnsetteledCoordinateMapping mapping, LevelSetTracker.LevelSetRegions regions, int[] Fields,
                                                ICollection <SpeciesId> _SpcIds = null, CellMask cm = null, bool presenceTest = true, MultiphaseCellAgglomerator drk = null)
        {
            #region Check Arguments
            // =========
            SpeciesId[] SpcIds = null;
            if (_SpcIds == null)
            {
                // take all species, if arg is null
                SpcIds = regions.SpeciesIdS.ToArray();
            }
            else
            {
                SpcIds = _SpcIds.ToArray();
            }

            if (SpcIds.Length <= 0)
            {
                // return will be empty for no species
                return(new int[0]);
            }
            #endregion

            #region collect cells which are excluded by agglomeration
            // =================================================

            int[][] ExcludeLists;
            if (drk != null)
            {
                ExcludeLists = new int[regions.SpeciesIdS.Count][]; //  new Dictionary<SpeciesId, int[]>();
                foreach (var id in SpcIds)
                {
                    int[] ExcludeList = drk.GetAgglomerator(id).AggInfo.AgglomerationPairs.Select(pair => pair.jCellSource).ToArray();
                    Array.Sort(ExcludeList);
                    ExcludeLists[id.cntnt - LevelSetTracker.___SpeciesIDOffest] = ExcludeList;
                }
            }
            else
            {
                ExcludeLists = null;
            }
            #endregion

            #region determine over which cells we want to loop
            // ==========================================
            CellMask loopCells;
            if ((new HashSet <SpeciesId>(regions.SpeciesIdS)).SetEquals(new HashSet <SpeciesId>(SpcIds)))
            {
                if (cm == null)
                {
                    loopCells = CellMask.GetFullMask(regions.GridDat);
                }
                else
                {
                    loopCells = cm;
                }
            }
            else
            {
                loopCells = regions.GetSpeciesMask(SpcIds[0]);
                for (int i = 1; i < SpcIds.Length; i++)
                {
                    loopCells = loopCells.Intersect(regions.GetSpeciesMask(SpcIds[i]));
                }
                if (cm != null)
                {
                    loopCells = loopCells.Intersect(cm);
                }
            }
            #endregion

            #region build list
            // ==========

            var R = new List <int>();

            // which basis is XDG?
            var        _BasisS  = mapping.BasisS.ToArray();
            XDGBasis[] _XBasisS = new XDGBasis[_BasisS.Length];
            for (int i = 0; i < _BasisS.Length; i++)
            {
                _XBasisS[i] = _BasisS[i] as XDGBasis;
            }


            Tuple <int, SpeciesId>[] iSpcS = new Tuple <int, SpeciesId> [SpcIds.Length];
            int KK;
            int Len_iSpcS = iSpcS.Length;


            int[] ExcludeListsPointer = new int[regions.SpeciesIdS.Count];


            // loop over cells?
            foreach (int jCell in loopCells.ItemEnum)
            {
                int NoOfSpc = regions.GetNoOfSpecies(jCell);

                #region
                //
                // in cell 'jCell', for each species in 'SpcIds' ...
                // * is the species present in 'jCell'?
                // * what is the species index in 'jCell'?
                // * we also have to consider that due to agglomeration, the respective cut-cell for the species might have been agglomerated.
                // so we determine
                // * 'KK' is the number of species (from 'SpcIds') which is actually present and not agglomerated in 'jCell'
                // * for i in (0 ... KK-1), iSpcS[i] is a tuple of (Species-index-in-cell, SpeciesID)
                //
                // yes, the following code sucks:
                KK = 0;
                for (int k = 0; k < Len_iSpcS; k++)   // loop over all species (provided as argument)...
                {
                    SpeciesId id      = SpcIds[k];
                    int       __iSpcS = regions.GetSpeciesIndex(id, jCell);
                    if (__iSpcS >= 0)
                    {
                        // species index is non-negative, so indices for the species are allocated ...
                        if (!presenceTest || regions.IsSpeciesPresentInCell(id, jCell))
                        {
                            // species is also present (i.e. has a greater-than-zero measure ...

                            if (drk == null)
                            {
                                // no agglomeration exclution
                                iSpcS[KK] = new Tuple <int, SpeciesId>(__iSpcS, id);
                                KK++;
                            }
                            else
                            {
                                int q  = id.cntnt - LevelSetTracker.___SpeciesIDOffest;
                                var el = ExcludeLists[q];

                                while (ExcludeListsPointer[q] < el.Length &&
                                       el[ExcludeListsPointer[q]] < jCell)
                                {
                                    ExcludeListsPointer[q]++;
                                }
                                Debug.Assert(ExcludeListsPointer[q] >= el.Length || el[ExcludeListsPointer[q]] >= jCell);

                                if (ExcludeListsPointer[q] >= el.Length || el[ExcludeListsPointer[q]] != jCell)
                                {
                                    // cell is also not agglomerated ...
                                    iSpcS[KK] = new Tuple <int, SpeciesId>(__iSpcS, id);
                                    KK++;
                                }
                            }
                        }
                    }
                }
                if (KK > 1)
                {
                    Array.Sort <Tuple <int, SpeciesId> >(iSpcS, 0, KK, new ilPSP.FuncComparer <Tuple <int, SpeciesId> >((a, b) => a.Item1 - b.Item1));
                }
                // --------- esc (end of sucking code)
                #endregion

                for (int k = 0; k < KK; k++)   // loop over species in cell
                {
                    int iSpc = iSpcS[k].Item1;

                    for (int i = 0; i < Fields.Length; i++)
                    {
                        int iField = Fields[i];

                        if (_XBasisS[iField] == null)
                        {
                            int N  = _BasisS[iField].GetLength(jCell);
                            int i0 = mapping.LocalUniqueCoordinateIndex(iField, jCell, 0);
                            for (int n = 0; n < N; n++)
                            {
                                R.Add(i0 + n);
                            }
                        }
                        else
                        {
                            int N  = _XBasisS[iField].DOFperSpeciesPerCell;
                            int i0 = mapping.LocalUniqueCoordinateIndex(iField, jCell, 0) + iSpc * N;
                            for (int n = 0; n < N; n++)
                            {
                                R.Add(i0 + n);
                            }
                        }
                    }
                }
            }
            #endregion

            return(R.ToArray());
        }
Пример #2
0
        void Setup_Frame2Full()
        {
            //if (FrameMap.Rank == 0)
            //    Debugger.Launch();
            //csMPI.Raw.Barrier(csMPI.Raw._COMM.WORLD);
            //FrameMap.GridDat.Cells.NoOfLocalUpdatedCells


            int L = FrameMap.LocalLength;

            Frame2Full_Lookup = new int[L];


            Basis[]    BasisS  = FullMap.BasisS.ToArray();
            XDGBasis[] XBasisS = new XDGBasis[BasisS.Length];
            for (int i = 0; i < BasisS.Length; i++)
            {
                XBasisS[i] = BasisS[i] as XDGBasis;
            }



            var GridDat = this.FullMap.GridDat;

            Frame2Full_Lookup = new int[L];
            Frame2Full_Lookup.SetAll(int.MinValue);
            int Jup  = FrameMap.GridDat.iLogicalCells.NoOfLocalUpdatedCells;
            int Jtot = FrameMap.GridDat.iLogicalCells.NoOfCells;
            int G    = BasisS.Length;

            for (int j = 0; j < Jup; j++)   // loop over all cells ...
            {
                int NoOfSpc = m_Regions.GetNoOfSpecies(j);
                int iSpc    = m_Regions.GetSpeciesIndex(m_spcId, j);

                for (int g = 0; g < G; g++)   // loop over all basises
                {
                    Basis    b             = BasisS[g];
                    XDGBasis xb            = XBasisS[g];
                    bool     b_is_XDGbasis = (xb != null);

                    int n0, N;
                    if (b_is_XDGbasis)
                    {
                        if (iSpc < 0)
                        {
                            n0 = int.MaxValue;
                            N  = int.MinValue;
                        }
                        else
                        {
                            N  = xb.DOFperSpeciesPerCell;
                            n0 = N * iSpc;
                        }
                    }
                    else
                    {
                        n0 = 0;
                        N  = b.GetLength(j);
                    }

                    if (N >= 0)
                    {
                        int iFull = (int)FullMap.GlobalUniqueCoordinateIndex(g, j, n0);
                        int iLoc  = FrameMap.LocalUniqueCoordinateIndex(g, j, 0);

                        for (int n = 0; n < N; n++)
                        {
                            Frame2Full_Lookup[iLoc + n] = iFull + n;
                            Debug.Assert(Frame2Full_Lookup[iLoc + n] < 0 || FullMap.IsInLocalRange(Frame2Full_Lookup[iLoc + n]));
                        }
                    }
                }
            }

#if DEBUG
            var _Frame2Full_Lookup = new int[L];
            for (int iLoc = 0; iLoc < L; iLoc++)   // loop over all indices of the frame...
            {
                int j, g, n;
                FrameMap.LocalFieldCoordinateIndex(iLoc, out g, out j, out n);

                int      NoOfSpc       = m_Regions.GetNoOfSpecies(j);
                Basis    b             = BasisS[g];
                XDGBasis xb            = XBasisS[g];
                bool     b_is_XDGbasis = (xb != null);
                int      iSpc          = m_Regions.GetSpeciesIndex(m_spcId, j);

                if (b_is_XDGbasis)
                {
                    if (iSpc < 0)
                    {
                        _Frame2Full_Lookup[iLoc] = int.MinValue;
                    }
                    else
                    {
                        int Nsep = xb.DOFperSpeciesPerCell;
                        _Frame2Full_Lookup[iLoc] = (int)(FullMap.GlobalUniqueCoordinateIndex(g, j, iSpc * Nsep + n));
                    }
                }
                else
                {
                    _Frame2Full_Lookup[iLoc] = (int)(FullMap.GlobalUniqueCoordinateIndex(g, j, n));
                }
                Debug.Assert(_Frame2Full_Lookup[iLoc] == Frame2Full_Lookup[iLoc]);
            }

            for (int l = 0; l < L; l++)
            {
                Debug.Assert(Frame2Full_Lookup[l] < 0 || FullMap.IsInLocalRange(Frame2Full_Lookup[l]));
            }
#endif


            /*
             * if (m_supportExternal) {
             *  int[] PeerProcess = GridDat.Parallel.ProcessesToReceiveFrom;
             *  int TT = PeerProcess.Length;
             *  int DOFperCell = FrameMap.MaxTotalNoOfCoordinatesPerCell;
             *
             *  ExtRangeStart = new int[TT];
             *  ExtRangeLen = new int[TT];
             *  ExtRangeTrafo = new int[TT][];
             *
             *  for(int tt = 0; tt < TT; tt++) {
             *      int otherRank = PeerProcess[tt];
             *      int jFristCell = GridDat.Parallel.m_RcvCommListsInsertIndex[otherRank];
             *      int Jrank = GridDat.Parallel.m_RcvCommListsNoOfItems[otherRank];
             *
             *
             *      int offset = (int)(FrameMap.GlobalUniqueCoordinateIndex(0, jFristCell, 0));
             *      ExtRangeStart[tt] = offset;
             *      ExtRangeLen[tt] = Jrank*DOFperCell;
             *
             *
             *      ExtRangeTrafo[tt] = new int[ExtRangeLen[tt]];
             *      ExtRangeTrafo[tt].SetAll(int.MinValue);
             *
             *      for (int j = 0; j < Jrank; j++) { // loop over all external cells that this process receives from 'otherRank' ...
             *          int jCell = j + jFristCell;
             *          Debug.Assert(jCell >= Jup);
             *          Debug.Assert(jCell < Jtot);
             *          ReducedRegionCode rrc;
             *          int NoOfSpc = m_lsTrk.GetNoOfSpecies(jCell, out rrc);
             *          int iSpc = m_lsTrk.GetSpeciesIndexFromId(rrc, m_spcId);
             *
             *          for (int g = 0; g < G; g++) { // loop over all basises
             *              Basis b = BasisS[g];
             *              XDGBasis xb = XBasisS[g];
             *              bool b_is_XDGbasis = (xb != null);
             *
             *              int n0, N;
             *              if (b_is_XDGbasis) {
             *                  if (iSpc < 0) {
             *                      n0 = int.MaxValue;
             *                      N = int.MinValue;
             *                  } else {
             *                      N = xb.DOFperSpeciesPerCell;
             *                      n0 = N*iSpc;
             *                  }
             *              } else {
             *                  n0 = 0;
             *                  N = b.GetLength(j);
             *              }
             *
             *              if (N >= 0) {
             *                  int iFull = (int)(FullMap.GlobalUniqueCoordinateIndex(g, jCell, n0));
             *                  int iFrame = (int)(FrameMap.GlobalUniqueCoordinateIndex(g, jCell, 0));
             *
             *                  for (int n = 0; n < N; n++) {
             *                      ExtRangeTrafo[tt][iFrame + n - offset] = iFull + n;
             *                  }
             *              }
             *          }
             *      }
             *  }
             * }
             */

            {
                int NoOfSpc    = this.m_Regions.SpeciesIdS.Count;
                int N_frame    = this.FrameMap.MaxTotalNoOfCoordinatesPerCell;
                var FramBasisS = this.FrameMap.BasisS.ToArray();
                var FullBasisS = this.FullMap.BasisS.ToArray();


                int[] NBs = FramBasisS.Select(b => b.Length).ToArray();
                int[] NBf = FullBasisS.Select(b => b.MaximalLength).ToArray();

                Debug.Assert(NBf.Length == NBs.Length);
                for (int i = 0; i < NBf.Length; i++)
                {
                    Debug.Assert(NBf[i] % NBs[i] == 0);
                }

                bool[] XBasis = FullBasisS.Select(b => b is XDGBasis).ToArray();

                this.IndexTrafoWithinCell = new int[NoOfSpc, this.FrameMap.MaxTotalNoOfCoordinatesPerCell];

                for (int iSpc = 0; iSpc < NoOfSpc; iSpc++)   // loop over all possible species indices
                {
                    int n_frame = 0;
                    int n_full  = 0;

                    for (int ifld = 0; ifld < NBs.Length; ifld++)   // loop over all basises in the mapping

                    {
                        if (XBasis[ifld])
                        {
                            for (int n = 0; n < NBs[ifld]; n++)
                            {
                                this.IndexTrafoWithinCell[iSpc, n_frame + n] = n_full + iSpc * NBs[ifld] + n;
                            }
                        }
                        else
                        {
                            for (int n = 0; n < NBs[ifld]; n++)
                            {
                                this.IndexTrafoWithinCell[iSpc, n_frame + n] = n_full + n;
                            }
                        }

                        n_frame += NBs[ifld];
                        n_full  += NBf[ifld];
                    }
                }
            }
        }
Пример #3
0
        ///// <summary>
        ///// cached inverse mass-matrix blocks for cut-cells
        ///// </summary>
        //Dictionary<SpeciesId, MassMatrixFactory.MassMatrixBlockContainer> InverseMassBlocks;



        /// <summary>
        /// computes the mass matrices for a given mapping and accumulates the mass matrix to some other matrix.
        /// </summary>
        public void AccMassMatrix <T>(T M, UnsetteledCoordinateMapping mapping, IDictionary <SpeciesId, IEnumerable <double> > _alpha, bool inverse = false)
            where T : IMutableMatrixEx //
        {
            using (new FuncTrace()) {
                var _basisS = mapping.BasisS.ToArray();
                var ctx     = _basisS[0].GridDat;
                int J       = ctx.iLogicalCells.NoOfLocalUpdatedCells;

                //if (VariableAgglomerationSwitch == null) {
                //    VariableAgglomerationSwitch = new bool[mapping.BasisS.Count];
                //    VariableAgglomerationSwitch.SetAll(true);
                //} else {
                //    if (VariableAgglomerationSwitch.Length != mapping.BasisS.Count)
                //        throw new ArgumentException();
                //}

                //if(VariableAgglomerationSwitch.Any() && (agg == null)) {
                //    throw new ArgumentException("Cell Agglomerator is required.");
                //}

                if (!M.RowPartitioning.EqualsPartition(mapping))
                {
                    throw new ArgumentException("Mismatch in row mapping.");
                }
                if (!M.ColPartition.EqualsPartition(mapping))
                {
                    throw new ArgumentException("Mismatch in column mapping.");
                }

                if (!_alpha.Keys.IsSubsetOf(this.AvailableSpecies))
                {
                    throw new ArgumentException("trying to obtain mass matrix for species that is not supported by this factory.");
                }

                foreach (var __alpha in _alpha.Values)
                {
                    if (__alpha.Count() != _basisS.Length)
                    {
                        throw new ArgumentException("Number of alpha's must match number of variables/fields in mapping.");
                    }
                }

                LevelSetTracker.LevelSetRegions regions = null;// XDGSpaceMetrics.LevelSetRegions;


                // compute the Mass-Blocks for the cut cells...
                // --------------------------------------------
                int _MaxDeg          = _basisS.Max(b => b.Degree);
                var RequestedSpecies = _alpha.Keys;
                UpdateBlocks(_MaxDeg, RequestedSpecies);

                Dictionary <SpeciesId, MassMatrixBlockContainer>[] invBlocks = null;
                if (inverse)
                {
                    invBlocks = GetInverseMassMatrixBlocks(RequestedSpecies, mapping.BasisS.Select(b => b.Degree).ToArray());
                    //VariableAgglomerationSwitch = new bool[VariableAgglomerationSwitch.Length];
                    //VariableAgglomerationSwitch.SetAll(true); // we already took care about this in the 'GetInverseMassMatrixBlocks'
                }

                // set the matrix
                // --------------

                for (int fld = 0; fld < _basisS.Length; fld++)   // loop over Variables in mapping...

                // loop over species...
                {
                    foreach (var species in _alpha.Keys)
                    {
                        double alpha      = _alpha[species].ElementAt(fld);
                        int[]  jSub2jCell = this.MassBlocks[species].jSub2jCell;

                        if (alpha != 0.0)
                        {
                            // properties of the basis
                            XDGBasis Xbasis = _basisS[fld] as XDGBasis;
                            Basis    nonXbasis;
                            Basis    basis = _basisS[fld];
                            if (Xbasis != null)
                            {
                                nonXbasis = Xbasis.NonX_Basis;
                                regions   = Xbasis.Tracker.Regions; // compute species indices with respect to **actual** regions !!!!
                                //if (!object.ReferenceEquals(Xbasis.Tracker, this.XDGSpaceMetrics.))
                                //    throw new ArgumentException();
                            }
                            else
                            {
                                nonXbasis = _basisS[fld];
                            }
                            int N = nonXbasis.Length;

                            // get Mass-Matrix subblock
                            MultidimensionalArray Mass;
                            if (!inverse)
                            {
                                Mass = this.MassBlocks[species].MassMatrixBlocks;
                            }
                            else
                            {
                                Mass = invBlocks[fld][species].MassMatrixBlocks;
                                Debug.Assert(Mass.GetLength(1) == N);
                                Debug.Assert(Mass.GetLength(2) == N);
                            }

                            // set diagonal element 1.0 in all cells of the subgrid
                            // (later, we subtract 1.0 from the diagonal in cut cells)
                            var speciesMask = XDGSpaceMetrics.LevelSetRegions.GetSpeciesMask(species);
                            {
                                foreach (int jCell in speciesMask.ItemEnum)
                                {
                                    int iSpc = 0;
                                    if (Xbasis != null)
                                    {
                                        int NoOfSpc = regions.GetNoOfSpecies(jCell);
                                        iSpc = regions.GetSpeciesIndex(species, jCell);
                                    }

                                    int n0 = mapping.GlobalUniqueCoordinateIndex(fld, jCell, N * iSpc);

                                    for (int n = 0; n < N; n++)
                                    {
                                        M[n0 + n, n0 + n] += alpha;
                                    }
                                }
                            }

                            // now, set then Non-Identity blocks in the cut cells
                            var speciesBitMask = speciesMask.GetBitMask();
                            {
                                int JSUB = jSub2jCell.Length;

                                for (int jsub = 0; jsub < JSUB; jsub++)   // loop over cut cells

                                {
                                    int jCell = jSub2jCell[jsub];
                                    if (!speciesBitMask[jCell])
                                    {
                                        continue;
                                    }


                                    int iSpc = 0;
                                    if (Xbasis != null)
                                    {
                                        int NoOfSpc = regions.GetNoOfSpecies(jCell);
                                        iSpc = regions.GetSpeciesIndex(species, jCell);
                                    }

                                    var MassSub = Mass.ExtractSubArrayShallow(new int[] { jsub, 0, 0 }, new int[] { jsub - 1, N - 1, N - 1 });
                                    //MultidimensionalArray MassSub;
                                    //if (VariableAgglomerationSwitch[fld] || (Mass_B4Agglom[jsub] == null)) {
                                    //    // block with agglomeration
                                    //    MassSub = Mass.ExtractSubArrayShallow(new int[] { jsub, 0, 0 }, new int[] { jsub - 1, N - 1, N - 1 });
                                    //} else {
                                    //    // block without agglomeration

                                    //    Debug.Assert(VariableAgglomerationSwitch[fld] == false);
                                    //    Debug.Assert(Mass_B4Agglom[jsub] != null);
                                    //    MassSub = Mass_B4Agglom[jsub].ExtractSubArrayShallow(new int[] { 0, 0 }, new int[] { N - 1, N - 1 });
                                    //}


                                    int i0 = mapping.GlobalUniqueCoordinateIndex(fld, jCell, N * iSpc);

                                    for (int n = 0; n < N; n++)     // loop over rows (within block)
                                    {
                                        for (int m = 0; m < N; m++) // loop over columns (within block)
                                        {
                                            M[i0 + n, i0 + m] += alpha * MassSub[n, m] - (m == n ? alpha : 0.0);
                                        }
                                    }
                                }
                            }
                        }
                    }
                }

                //// cell-aglomeration
                //// -----------------

                //if (inverse == true)
                //    //throw new ApplicationException("todo: double-check with agglomeration");
                //    Console.WriteLine("todo: double-check with agglomeration");

                //this.m_agglomerator.ManipulateMassMatrix_Mk2(M, mapping);
            }
        }