Beispiel #1
0
        /// <summary>
        /// Constructor
        /// </summary>
        /// <param name="__ProblemMapping">
        /// Mapping of original problem, equal to <see cref="ProblemMapping"/>.
        /// </param>
        /// <param name="__aggGrdB">
        /// Sequence of aggregation grid DG basis objects, correlates to original mapping
        /// </param>
        /// <param name="DgDegrees"></param>
        public MultigridMapping(UnsetteledCoordinateMapping __ProblemMapping, AggregationGridBasis[] __aggGrdB, int[] DgDegrees)
        {
            using (new FuncTrace()) {
                // check args
                // ===========


                if (__aggGrdB.Length != __ProblemMapping.BasisS.Count)
                {
                    throw new ArgumentException("Mismatch between number of multigrid basis objects and number of variables in problem mapping.");
                }

                var mgGrid = __aggGrdB[0].AggGrid;
                for (int iVar = 0; iVar < __aggGrdB.Length; iVar++)
                {
                    if (__ProblemMapping.BasisS[iVar] is BoSSS.Foundation.XDG.XDGBasis)
                    {
                        if (!(__aggGrdB[iVar] is XdgAggregationBasis))
                        {
                            throw new ArgumentException();
                        }
                    }
                    else if (__ProblemMapping.BasisS[iVar] is BoSSS.Foundation.Basis)
                    {
                        //if((__aggGrdB[iVar] is XdgAggregationBasis))
                        //    throw new ArgumentException();
                    }

                    if (!object.ReferenceEquals(mgGrid, __aggGrdB[iVar].AggGrid))
                    {
                        throw new ArgumentException("Basis object must all be defined on the same grid.");
                    }
                }

                // find basis with maximum degree
                // ==============================
                this.ProblemMapping = __ProblemMapping;
                //this.MaxBasis = ProblemMapping.BasisS.ElementAtMax(basis => basis.Degree);
                this.m_DgDegree = DgDegrees.CloneAs();
                //if(!this.MaxBasis.IsSubBasis(__aggGrdB.DGBasis)) {
                //    throw new ArgumentException("Basis on aggregation grid is insufficient;");
                //}

                if (m_DgDegree.Length != __ProblemMapping.BasisS.Count())
                {
                    throw new ArgumentException("Wrong number of DG degrees.");
                }
                for (int i = 0; i < m_DgDegree.Length; i++)
                {
                    if (m_DgDegree[i] < 0)
                    {
                        throw new ArgumentException("DG degree must be greater of equal to 0.");
                    }
                    if (m_DgDegree[i] > __ProblemMapping.BasisS[i].Degree)
                    {
                        throw new ArgumentException("DG degree on sub-level can not exceed DG degree of the original problem.");
                    }
                }

                // create basis for this level
                // ===========================
                this.AggBasis = __aggGrdB;

                // min/max length
                // ==============
                {
                    int Smin     = 0;
                    int Smax     = 0;
                    int Nofields = this.m_DgDegree.Length;
                    for (int ifld = 0; ifld < Nofields; ifld++)
                    {
                        Smin += this.AggBasis[ifld].GetMinimalLength(this.m_DgDegree[ifld]);
                        Smax += this.AggBasis[ifld].GetMaximalLength(this.m_DgDegree[ifld]);
                    }
                    this.MinimalLength = Smin;
                    this.MaximalLength = Smax;
                }

                // offsets
                // =======
                if (this.MinimalLength != this.MaximalLength)
                {
                    int   JAGGloc = this.AggGrid.iLogicalCells.NoOfLocalUpdatedCells;
                    int   JAGGtot = this.AggGrid.iLogicalCells.Count;
                    int[] __i0Tmp = new int[JAGGtot];

                    HashSet <int> BlockLen = new HashSet <int>();

                    int LL = 0;
                    for (int jag = 0; jag < JAGGloc; jag++)
                    {
                        int S = 0;
                        for (int i = 0; i < m_DgDegree.Length; i++)
                        {
                            S += this.AggBasis[i].GetLength(jag, m_DgDegree[i]);
                        }

                        if (jag < JAGGloc - 1)
                        {
                            __i0Tmp[jag + 1] = __i0Tmp[jag] + S;
                        }
                        else
                        {
                            LL = __i0Tmp[jag] + S;
                        }

                        BlockLen.Add(S);
                    }
                    Partitioning = new Partitioning(LL);
                    int i0Part = Partitioning.i0;
                    m_i0 = new int[JAGGtot + 1];
                    for (int jag = 0; jag < JAGGloc; jag++)
                    {
                        m_i0[jag]     = __i0Tmp[jag]; // store local i0 index
                        __i0Tmp[jag] += i0Part;       // convert to global index
                    }
                    m_i0[JAGGloc] = LL;
                    __i0Tmp.MPIExchange(this.AggGrid);

                    // compute global cell i0's in the external range
                    m_i0_ExtGlob = new int[JAGGtot - JAGGloc];
                    Array.Copy(__i0Tmp, JAGGloc, m_i0_ExtGlob, 0, JAGGtot - JAGGloc);

                    // compute local cell i0's in the external range (very confusing)
                    for (int jag = JAGGloc; jag < JAGGtot; jag++)
                    {
                        int S = 0;
                        for (int i = 0; i < m_DgDegree.Length; i++)
                        {
                            S += this.AggBasis[i].GetLength(jag, m_DgDegree[i]);
                        }
                        m_i0[jag + 1] = this.m_i0[jag] + S;

                        BlockLen.Add(S);
                    }

                    // build look-up for block types
                    m_Len2SublockType = new Dictionary <int, int>();
                    m_Subblk_i0       = new int[BlockLen.Count][];
                    m_SubblkLen       = new int[BlockLen.Count][];
                    int type = 0;
                    foreach (int S in BlockLen)
                    {
                        m_Subblk_i0[type] = new int[] { 0 };
                        m_SubblkLen[type] = new int[] { S };
                        m_Len2SublockType.Add(S, type);
                        type++;
                    }

#if DEBUG
                    for (int jag = JAGGloc; jag < JAGGtot; jag++)
                    {
                        Debug.Assert(Partitioning.IsInLocalRange(m_i0_ExtGlob[jag - JAGGloc]) == false);
                    }
#endif
                }
                else
                {
                    m_Subblk_i0 = new int[][] { new int[] { 0 } };
                    m_SubblkLen = new int[][] { new int[] { this.MaximalLength } };

                    Partitioning = new Partitioning(this.AggGrid.iLogicalCells.NoOfLocalUpdatedCells * this.MaximalLength);
                }


                Debug.Assert(Partitioning != null);
                Debug.Assert(Partitioning.LocalLength == this.LocalLength);
            }
        }