Esempio n. 1
0
        /// <summary>
        /// Prolongation/Injection operator to finer grid level.
        /// </summary>
        public BlockMsrMatrix GetProlongationOperator(MultigridMapping finerLevel)
        {
            using (new FuncTrace()) {
                // Argument checking
                // =================

                if (!object.ReferenceEquals(finerLevel.AggGrid, this.AggGrid.ParentGrid))
                {
                    throw new ArgumentException("Only prolongation/injection to next level is supported.");
                }
                if (finerLevel.AggBasis.Length != this.AggBasis.Length)
                {
                    throw new ArgumentException("");
                }
                int NoOfVar = this.AggBasis.Length;

                MultidimensionalArray[][] InjOp = new MultidimensionalArray[NoOfVar][];
                AggregationGridBasis[]    B     = new AggregationGridBasis[NoOfVar];
                bool[] useX        = new bool[NoOfVar];
                int[]  DegreeS     = new int[NoOfVar];
                int[]  DegreeSfine = new int[NoOfVar];

                for (int iVar = 0; iVar < NoOfVar; iVar++)
                {
                    InjOp[iVar]       = this.AggBasis[iVar].InjectionOperator;
                    B[iVar]           = AggBasis[iVar];
                    DegreeS[iVar]     = this.DgDegree[iVar];
                    DegreeSfine[iVar] = finerLevel.DgDegree[iVar];
                    if (DegreeSfine[iVar] < DegreeS[iVar])
                    {
                        throw new ArgumentException("Lower DG degree on finer grid is not supported by this method ");
                    }
                    useX[iVar] = this.AggBasis[iVar] is XdgAggregationBasis;
                    if (useX[iVar] != (finerLevel.AggBasis[iVar] is XdgAggregationBasis))
                    {
                        throw new ArgumentException("XDG / DG mismatch between this and finer level for " + iVar + "-th variable.");
                    }
                }

                XdgAggregationBasis XB  = null;
                XdgAggregationBasis XBf = null;
                int[][,] spcIdxMap = null;
                SpeciesId[][] spc = null;
                //SpeciesId[][] spcf = null;
                for (int iVar = 0; iVar < NoOfVar; iVar++)
                {
                    if (useX[iVar])
                    {
                        XB        = (XdgAggregationBasis)(B[iVar]);
                        XBf       = (XdgAggregationBasis)(finerLevel.AggBasis[iVar]);
                        spcIdxMap = XB.SpeciesIndexMapping;
                        spc       = XB.AggCellsSpecies;
                        //spcf = XBf.AggCellsSpecies;
                        break;
                    }
                }

                int[] Np      = this.AggBasis[0].GetNp();
                int[] Np_fine = finerLevel.AggBasis[0].GetNp();



                // create matrix
                // =============

                // init retval
                var PrlgMtx = new BlockMsrMatrix(finerLevel, this);

                int[][] C2F     = this.AggGrid.jCellCoarse2jCellFine;
                int     JCoarse = this.AggGrid.iLogicalCells.NoOfLocalUpdatedCells;
                //Debug.Assert((JCoarse == C2F.Length) || ());
                for (int jc = 0; jc < JCoarse; jc++)  // loop over coarse cells...
                {
                    int[] AggCell = C2F[jc];
                    int   I       = AggCell.Length;

                    for (int iVar = 0; iVar < NoOfVar; iVar++)
                    {
                        int DgDeg  = DegreeS[iVar];
                        int DgDegF = DegreeSfine[iVar];
                        MultidimensionalArray Inj_iVar_jc = InjOp[iVar][jc];
                        Debug.Assert(Inj_iVar_jc.GetLength(0) == I);

                        bool useX_iVar = false;
                        if (useX[iVar])
                        {
                            if (spcIdxMap[jc] != null)
                            {
                                useX_iVar = true;
                            }
                        }


                        if (useX_iVar)
                        {
                            //throw new NotImplementedException("todo");

                            int NoOfSpc = XB.GetNoOfSpecies(jc);
                            int Np_col  = Np[DgDeg];
                            Debug.Assert(Np_col * NoOfSpc == B[iVar].GetLength(jc, DgDeg));

                            for (int iSpc = 0; iSpc < NoOfSpc; iSpc++)  // loop over species
                            {
                                SpeciesId spc_jc_i = spc[jc][iSpc];

                                int Col0 = this.GlobalUniqueIndex(iVar, jc, Np_col * iSpc);


                                for (int i = 0; i < I; i++)   // loop over finer cells
                                {
                                    int jf = AggCell[i];

                                    int iSpc_Row = XBf.GetSpeciesIndex(jf, spc_jc_i);
                                    if (iSpc_Row < 0)
                                    {
                                        // nothing to do
                                        continue;
                                    }

                                    int Np_row = Np_fine[DgDegF];
                                    Debug.Assert(Np_row * XBf.GetNoOfSpecies(jf) == finerLevel.AggBasis[iVar].GetLength(jf, DgDegF));

                                    int Row0 = finerLevel.GlobalUniqueIndex(iVar, jf, Np_row * iSpc_Row);

                                    //if(Row0 <= 12 &&  12 < Row0 + Np_row) {
                                    //    if(Col0 <= 3 && 3 < Col0 + Np_col) {
                                    //        Debugger.Break();
                                    //    }
                                    //}
                                    PrlgMtx.AccBlock(Row0, Col0, 1.0, Inj_iVar_jc.ExtractSubArrayShallow(new[] { i, 0, 0 }, new[] { i - 1, Np_row - 1, Np_col - 1 }));
                                }
                            }
                        }
                        else
                        {
                            // ++++++++++++++++++
                            // standard DG branch
                            // ++++++++++++++++++

                            int Np_col = Np[DgDeg];
                            Debug.Assert(Np_col == B[iVar].GetLength(jc, DgDeg));
                            int Col0 = this.GlobalUniqueIndex(iVar, jc, 0);

                            for (int i = 0; i < I; i++)  // loop over finer cells
                            {
                                int jf     = AggCell[i];
                                int Np_row = Np_fine[DgDegF];
                                Debug.Assert(Np_row == finerLevel.AggBasis[iVar].GetLength(jf, DgDegF));

                                int Row0 = finerLevel.GlobalUniqueIndex(iVar, jf, 0);

                                PrlgMtx.AccBlock(Row0, Col0, 1.0, Inj_iVar_jc.ExtractSubArrayShallow(new[] { i, 0, 0 }, new[] { i - 1, Np_row - 1, Np_col - 1 }));
                                //if(Row0 <= 12 &&  12 < Row0 + Np_row) {
                                //        if(Col0 <= 3 && 3 < Col0 + Np_col) {
                                //            Debugger.Break();
                                //        }
                                //    }
                            }
                        }
                    }
                }


                // return
                // ======

                return(PrlgMtx);
            }
        }
Esempio n. 2
0
        /// <summary>
        /// The core of the masking
        /// Generates index lists and the Ni0-struct-list corresponding to mask
        /// and is called by the child classes: local and external mask
        /// Note: the smallest unit are DG sub blocks!
        /// </summary>
        protected void GenerateAllMasks()
        {
            int NoOfCells     = m_NoOfCells;
            int NoOfVariables = m_NoOfVariables;

            int[][] NoOfSpecies = m_NoOfSpecies;
            int[]   DGdegreeP1  = m_DGdegree.CloneAs();
            for (int iDG = 0; iDG < DGdegreeP1.Length; iDG++)
            {
                DGdegreeP1[iDG] += 1;
            }

            List <extNi0> ListNi0     = new List <extNi0>();
            List <int>    Globalint   = new List <int>();
            List <int>    Localint    = new List <int>();
            List <int>    SubBlockIdx = new List <int>();

            int SubOffset = m_SubBlockOffset; // 0 for local mask and BMLoc.LocalDof for external mask
            int Ni0Length = 0;
            int MaskLen   = 0;
            int prevLocie = m_map.LocalNoOfBlocks;
            var tmpCell   = new List <extNi0[][][]>();

            // local caching of filter functions
            // ensures that functions are not re-allocated during the loops
            var  CellInstruction = m_sbs.CellFilter;
            var  VarInstruction  = m_sbs.VariableFilter;
            var  SpecInstruction = m_sbs.SpeciesFilter;
            var  ModeInstruction = m_sbs.ModeFilter;
            bool emptysel        = true;

            // loop over cells...
            for (int iLoc = 0; iLoc < NoOfCells; iLoc++)
            {
                int jLoc = m_CellOffset + iLoc;     //to address correctly, external cells offset has to be concidered, you know ...
                emptysel &= !CellInstruction(jLoc); //for testing if the entire selection is empty, which hopefully only can happen at the level of cells
                if (!CellInstruction(jLoc))
                {
                    continue;
                }
                var tmpVar = new List <extNi0[][]>();

                // loop over variables...
                for (int iVar = 0; iVar < NoOfVariables; iVar++)
                {
                    if (!VarInstruction(jLoc, iVar))
                    {
                        continue;
                    }
                    var tmpSpc = new List <extNi0[]>();

                    // loop over species...
                    for (int iSpc = 0; iSpc < NoOfSpecies[iLoc][iVar]; iSpc++)
                    {
                        if (!SpecInstruction(jLoc, iVar, iSpc))
                        {
                            continue;
                        }
                        int GlobalOffset = m_map.GlobalUniqueIndex(iVar, jLoc, iSpc, 0);
                        int LocalOffset  = m_map.LocalUniqueIndex(iVar, jLoc, iSpc, 0);
                        var tmpMod       = new List <extNi0>();

                        // loop over polynomial degrees...
                        for (int degree = 0; degree < DGdegreeP1[iVar]; degree++)
                        {
                            if (ModeInstruction(jLoc, iVar, iSpc, degree))
                            {
                                int GlobalModeOffset = m_Ni0[degree].i0 + GlobalOffset;
                                int LocalModeOffset  = m_Ni0[degree].i0 + LocalOffset;
                                int ModeLength       = m_Ni0[degree].N;
                                var newNi0           = new extNi0(LocalModeOffset, GlobalModeOffset, SubOffset, ModeLength);
                                SubOffset += ModeLength;
                                // Fill int lists
                                for (int i = 0; i < newNi0.N; i++)
                                {
                                    Globalint.Add(newNi0.Gi0 + i);
                                    Localint.Add(newNi0.Li0 + i);
                                    SubBlockIdx.Add(newNi0.Si0 + i);
                                    MaskLen++;
                                }
                                // Fill Ni0 Lists
                                tmpMod.Add(newNi0);
                                Ni0Length++;
                                ListNi0.Add(newNi0);
                                Debug.Assert(m_map.LocalUniqueIndex(iVar, jLoc, iSpc, GetNp(degree) - 1) == LocalModeOffset + ModeLength - 1);
                            }
                        }
                        if (tmpMod.Count > 0)
                        {
                            tmpSpc.Add(tmpMod.ToArray());
                        }
                    }
                    if (tmpSpc.Count > 0)
                    {
                        tmpVar.Add(tmpSpc.ToArray());
                    }
                }
                if (tmpVar.Count > 0)
                {
                    tmpCell.Add(tmpVar.ToArray());
                }
            }
            var tmpStructNi0 = tmpCell.ToArray();

            int NumOfNi0 = 0;

#if DEBUG
            for (int iCell = 0; iCell < tmpStructNi0.Length; iCell++)
            {
                for (int iVar = 0; iVar < tmpStructNi0[iCell].Length; iVar++)
                {
                    for (int iSpc = 0; iSpc < tmpStructNi0[iCell][iVar].Length; iSpc++)
                    {
                        NumOfNi0 += tmpStructNi0[iCell][iVar][iSpc].Length;
                    }
                }
            }
#endif
            // an empty selection is allowed,
            // e.g. consider a combination of empty external and non empty local mask
            if (!emptysel)
            {
                Debug.Assert(ListNi0.GroupBy(x => x.Li0).Any(g => g.Count() == 1));
                Debug.Assert(ListNi0.GroupBy(x => x.Gi0).Any(g => g.Count() == 1));
                Debug.Assert(ListNi0.Count() == NumOfNi0);
                Debug.Assert(MaskLen <= m_LocalLength);
                Debug.Assert(Localint.GroupBy(x => x).Any(g => g.Count() == 1));
                Debug.Assert(Globalint.GroupBy(x => x).Any(g => g.Count() == 1));
                Debug.Assert(Localint.Count() == MaskLen);
                Debug.Assert(SubBlockIdx.Count() == MaskLen);
                Debug.Assert(SubBlockIdx.GroupBy(x => x).Any(g => g.Count() == 1));
            }

            m_GlobalMask    = Globalint;
            m_LocalMask     = Localint;
            m_StructuredNi0 = tmpStructNi0;
            m_MaskLen       = MaskLen;
            m_Ni0Len        = Ni0Length;
            m_SubBlockMask  = SubBlockIdx;
        }