/// <summary> /// Returns the index of species '<paramref name="_SpeciesId"/>' in the cell '<paramref name="jCell"/>'. /// </summary> /// <param name="jCell"> /// a local cell index /// </param> /// <param name="_SpeciesId"> /// species identification /// </param> public int GetSpeciesIndex(SpeciesId _SpeciesId, int jCell) { ReducedRegionCode rrc; int NoOfSpc = this.GetNoOfSpecies(jCell, out rrc); return(m_owner.GetSpeciesIndex(rrc, _SpeciesId)); }
/// <summary> /// Interior quadrature for the surface elements, i.e. for each cut background-cell \f$ K_j \f$ a quadrature to approximate /// \f[ /// \oint_{K_j \cap \mathfrak{I} } \ldots \mathrm{dS} . /// \f] /// </summary> public CellQuadratureScheme Get_SurfaceElement_VolumeQuadScheme(SpeciesId sp) { if (!this.SpeciesList.Contains(sp)) { throw new ArgumentException("Given species (id = " + sp.cntnt + ") is not supported."); } var spdom = XDGSpaceMetrics.LevelSetRegions.GetSpeciesMask(sp); var IntegrationDom = XDGSpaceMetrics.LevelSetRegions.GetCutCellMask().Intersect(spdom); var LevSetQrIns = new CellQuadratureScheme(false, IntegrationDom); foreach (var Kref in XDGSpaceMetrics.GridDat.Grid.RefElements) { for (int iLevSet = 0; iLevSet < XDGSpaceMetrics.NoOfLevelSets; iLevSet++) // loop over level sets... { var surfaceFactory = this.XDGSpaceMetrics.XQuadFactoryHelper.GetSurfaceFactory(iLevSet, Kref); LevSetQrIns = LevSetQrIns.AddFactory(surfaceFactory, XDGSpaceMetrics.LevelSetRegions.GetCutCellMask4LevSet(iLevSet)); } } return(LevSetQrIns); }
/// <summary> /// Creates an execution mask (volume mask) which only contains cells /// that are at least partly occupied by species /// <paramref name="speciesId"/>; /// </summary> /// <remarks> /// Note: The method is so complex because we do <b>not</b> want to /// consider the whole narrow-band because it may contain additional /// cells on the "other" side of the level set! /// </remarks> /// <param name="speciesId"> /// The name of the species /// </param> /// <returns> /// A volume mask containing only cells with at least a portion of /// species <paramref name="speciesId"/> /// </returns> public CellMask GetSpeciesMask(SpeciesId speciesId) { if (m_SpeciesMask == null) { m_SpeciesMask = new Dictionary <SpeciesId, CellMask>(); } if (!m_SpeciesMask.ContainsKey(speciesId)) { int J = m_owner.m_gDat.Grid.NoOfUpdateCells; BitArray mask = new BitArray(J); LevelSetSignCode[] signCodes = m_owner.GetLevelSetSignCodes(speciesId); if (signCodes.Length == 0) { throw new ArgumentException("Unknown species " + speciesId, "speciesName"); } for (int jCell = 0; jCell < J; jCell++) { bool matchesOne = IsSpeciesPresentInCell(speciesId, jCell); // mask[i] = matches would also do it but a set operation on // a BitMask is heavier than this ugly additional if statement if (matchesOne) { mask[jCell] = true; } } m_SpeciesMask.Add(speciesId, new CellMask(m_owner.m_gDat, mask)); } return(m_SpeciesMask[speciesId]); }
/// <summary> /// ctor /// </summary> public SpeciesShadowField(XDGField owner, SpeciesId specId) : base(new Basis(owner.GridDat, owner.m_CCBasis.Degree), owner.Identification + "-" + owner.m_CCBasis.Tracker.GetSpeciesName(specId)) { m_Coordinates = new SpeciesCoordinates(owner, specId); m_Owner = owner; }
/// <summary> /// All edges that have to be considered for the integration of species <paramref name="sp"/>. /// </summary> /// <param name="sp"></param> /// <param name="IntegrationDomainRestriction">Optional restriction to the integration domain.</param> public EdgeMask GetEdgeMask(SpeciesId sp, EdgeMask IntegrationDomainRestriction = null) { if (!this.SpeciesList.Contains(sp)) { throw new ArgumentException("Given species ( id = " + sp.cntnt + ") is not supported."); } EdgeMask allRelevantEdges; if (IntegrationDomainRestriction == null) { allRelevantEdges = this.m_SpeciesSubgrid_InnerAndDomainEdges[sp]; } else { // user provides integration domain, intersect with that allRelevantEdges = this.m_SpeciesSubgrid_InnerAndDomainEdges[sp].Intersect(IntegrationDomainRestriction); } //// optionally, exclude edges between agglomerated cells //EdgeMask AggEdges = (this.CellAgglomeration != null) ? (this.CellAgglomeration.GetAgglomerator(sp).AggInfo.AgglomerationEdges) : (default(EdgeMask)); //if (AggEdges != null && AggEdges.NoOfItemsLocally > 0) // allRelevantEdges = allRelevantEdges.Except(AggEdges); return(allRelevantEdges); }
public MiniMapping(UnsetteledCoordinateMapping Map, SpeciesId spId, LevelSetTracker.LevelSetRegions r) { m_Map = Map; m_spId = spId; m_LsRegion = r; Basis[] BS = Map.BasisS.ToArray(); NS = new int[BS.Length]; VarIsXdg = new bool[BS.Length]; NoOfVars = BS.Length; for (int iVar = 0; iVar < BS.Length; iVar++) { XDGBasis xBasis = BS[iVar] as XDGBasis; if (xBasis != null) { NS[iVar] = xBasis.NonX_Basis.Length; //m_LsTrk = xBasis.Tracker; VarIsXdg[iVar] = true; } else { NS[iVar] = BS[iVar].Length; VarIsXdg[iVar] = false; } MaxDeg = Math.Max(MaxDeg, BS[iVar].Degree); } }
/// <summary> /// ctor; /// </summary> internal SpeciesCoordinates(XDGField _owner, SpeciesId _SpeciesId) { owner = _owner; NSep = this.owner.m_CCBasis.DOFperSpeciesPerCell; LsTrk = this.owner.m_CCBasis.Tracker; m_SpecisId = _SpeciesId; }
/* * /// <summary> * /// initialized by the constructor to avoid MPI-deadlocks; * /// </summary> * Dictionary<RefElement, EdgeMask> m_Subgrid4Kref_AllEdges = new Dictionary<RefElement, EdgeMask>(); */ //LevelSetTracker lsTrk { // get { // return XDGSpaceMetrics.Tracker; // } //} public EdgeQuadratureScheme Get_SurfaceElement_EdgeQuadScheme(SpeciesId sp) { if (!this.SpeciesList.Contains(sp)) { throw new ArgumentException("Given species (id = " + sp.cntnt + ") is not supported."); } //var allRelevantEdges = this.m_SpeciesSubgrid_InnerAndDomainEdges[sp].Intersect(this.m_CutCellSubgrid_InnerEdges); var innerCutCellEdges = this.XDGSpaceMetrics.LevelSetRegions.GetCutCellSubGrid().InnerEdgesMask; var boundaryCutCellEdges = ExecutionMask.Intersect(this.XDGSpaceMetrics.LevelSetRegions.GetCutCellSubGrid().BoundaryEdgesMask, this.XDGSpaceMetrics.GridDat.BoundaryEdges); var allRelevantEdges = this.m_SpeciesSubgrid_InnerAndDomainEdges[sp].Intersect(ExecutionMask.Union(innerCutCellEdges, boundaryCutCellEdges)); //EdgeMask AggEdges = this.CellAgglomeration != null ? this.CellAgglomeration.GetAgglomerator(sp).AggInfo.AgglomerationEdges : null; //if (AggEdges != null && AggEdges.NoOfItemsLocally > 0) // allRelevantEdges = allRelevantEdges.Except(AggEdges); var edgeQrIns = new EdgeQuadratureScheme(false, allRelevantEdges); foreach (var Kref in XDGSpaceMetrics.GridDat.Grid.RefElements) { for (int iLevSet = 0; iLevSet < XDGSpaceMetrics.NoOfLevelSets; iLevSet++) // loop over level sets... { EdgeMask cutEdges = this.GetCutEdges(Kref, iLevSet); var factory = this.XDGSpaceMetrics.XQuadFactoryHelper.GetSurfaceElement_BoundaryRuleFactory(iLevSet, Kref); edgeQrIns.AddFactory(factory, cutEdges); } } return(edgeQrIns); }
/// <summary> /// ctor /// </summary> /// <param name="lsTrk">level set tracker</param> /// <param name="spcId">species which should be framed</param> /// <param name="__FullMap"></param> /// <param name="SupportExternal"> /// true: support also indices related to external/ghost cells /// </param> public FrameBase(LevelSetTracker.LevelSetRegions regions, SpeciesId spcId, UnsetteledCoordinateMapping __FullMap, bool SupportExternal) { m_Regions = regions; m_spcId = spcId; FrameMap = CreateMap(__FullMap); FullMap = __FullMap; m_supportExternal = SupportExternal; Setup_Frame2Full(); // Frame2Full is almost used every time, so we set it up immediately // (in contrast, Full2Frame is set up on demand) }
/// <summary> /// Equivalent to <see cref="GetSpeciesSubGrid(string)"/> /// </summary> public SubGrid GetSpeciesSubGrid(SpeciesId specId) { MPICollectiveWatchDog.Watch(); if (m_SpeciesSubGrids == null) { m_SpeciesSubGrids = new Dictionary <SpeciesId, SubGrid>(); } if (!m_SpeciesSubGrids.ContainsKey(specId)) { CellMask cm = GetSpeciesMask(specId); m_SpeciesSubGrids.Add(specId, new SubGrid(cm)); } return(this.m_SpeciesSubGrids[specId]); }
/* * /// <summary> * /// computes the mass matrices for a given mapping. * /// </summary> * /// <param name="mapping"> * /// </param> * /// <param name="alpha"> * /// 'Fine-grained' scaling for blocks, for each species and each variable in the <paramref name="mapping"/>. * /// The default value of null maps to 1.0 for each species and variable. * /// </param> * /// <param name="VariableAgglomerationSwitch"> * /// Switch to turn agglomeration on/off for each variable; default=null=on. * /// </param> * /// <param name="inverse"> * /// Return the inverse mass matrix. * /// </param> * public BlockDiagonalMatrix GetMassMatrix_depr(UnsetteledCoordinateMapping mapping, IDictionary<SpeciesId, IEnumerable<double>> alpha = null, bool inverse = false, bool[] VariableAgglomerationSwitch = null) { * if (alpha == null) { * int NoVar = mapping.NoOfVariables; * alpha = new Dictionary<SpeciesId, IEnumerable<double>>(); * double[] AllOne = new double[NoVar]; * AllOne.SetAll(1.0); * foreach (var spc in this.m_LsTrk.SpeciesIdS) { * alpha.Add(spc, AllOne); * } * } * var Return = new BlockDiagonalMatrix(mapping.LocalLength, mapping.MaxTotalNoOfCoordinatesPerCell); * AccMassMatrix(Return, mapping, alpha, inverse, VariableAgglomerationSwitch); * return Return; * } */ /// <summary> /// Provides access to a 'raw' form of the mass matrix, where only blocks for the cut cells /// are stored /// </summary> /// <returns> /// don't mess with those values /// </returns> public MassMatrixBlockContainer GetMassMatrixBlocks(Basis b, SpeciesId spc) { if (!b.IsSubBasis(this.MaxBasis)) { throw new NotSupportedException("requested basis exceeds maximally supported basis."); } UpdateBlocks(b.Degree, new SpeciesId[] { spc }); var MMB = this.MassBlocks[spc]; //#if DEBUG // { // var CCBit = XDGSpaceMetrics.LevelSetRegions.GetCutCellMask().GetBitMask(); // //var AggCells = this.Agglomerator.GetAgglomerator(spc).AggInfo.SourceCells; // //var AggCellsBit = AggCells.GetBitMask(); // //var AggAffectedBit = this.Agglomerator.GetAgglomerator(spc).AggInfo.AllAffectedCells.GetBitMaskWithExternal(); // int J = XDGSpaceMetrics.GridDat.Cells.NoOfLocalUpdatedCells; // int JSUB = MMB.jSub2jCell.Length; // for (int jSub = 0; jSub < JSUB; jSub++) { // var Block = MMB.MassMatrixBlocks.ExtractSubArrayShallow(jSub, -1, -1); // int jCell = MMB.jSub2jCell[jSub]; // double BlockNorm = Block.InfNorm(); // //if (jCell < J) { // // Debug.Assert(CCBit[jCell] || AggAffectedBit[jCell]); // // Debug.Assert(AggCellsBit[jCell] == (BlockNorm == 0)); // //} // } // //foreach (var jCellAgg in AggCells.ItemEnum) { // // int jSub = MMB.jCell2jSub[jCellAgg]; // // var Block = MMB.MassMatrixBlocks.ExtractSubArrayShallow(jSub, -1, -1); // // double BlockNorm = Block.InfNorm(); // // Debug.Assert(BlockNorm == 0.0); // //} // } //#endif return(MMB); }
/// <summary> /// Fills up the volume scheme for species <paramref name="sp"/>. /// </summary> public CellQuadratureScheme GetVolumeQuadScheme(SpeciesId sp, bool UseDefaultFactories = true, CellMask IntegrationDomain = null, int?fixedOrder = null) { if (!this.SpeciesList.Contains(sp)) { throw new ArgumentException("Given species (id = " + sp.cntnt + ") is not supported."); } if (IntegrationDomain != null) { if (IntegrationDomain.MaskType != MaskType.Logical) { throw new ArgumentException(); } } CellMask CellMask = GetCellMask(sp, IntegrationDomain); /// Debugging Code //if (IntegrationDomain != null) { // CellMask.ToTxtFile("VolDom-" + this.lsTrk.GridDat.MyRank + "of" + this.lsTrk.GridDat.Size + ".csv", false); //} // default rule for "normal" cells var volQrIns = (new CellQuadratureScheme(UseDefaultFactories, CellMask)); // now: rules for the cut-cells: for (int iLevSet = 0; iLevSet < XDGSpaceMetrics.NoOfLevelSets; iLevSet++) // loop over level sets { var cutDom = XDGSpaceMetrics.LevelSetRegions.GetCutCellMask4LevSet(iLevSet).ToGeometicalMask(); var cutCells = cutDom.Intersect(CellMask); var jmp = IdentifyWing(iLevSet, sp); for (int iKref = 0; iKref < XDGSpaceMetrics.GridDat.Grid.RefElements.Length; iKref++) { RefElement Kref = XDGSpaceMetrics.GridDat.Grid.RefElements[iKref]; var _cutDom = cutCells.Intersect(XDGSpaceMetrics.GridDat.Cells.GetCells4Refelement(iKref)); var factory = this.XDGSpaceMetrics.XQuadFactoryHelper.GetVolRuleFactory(iLevSet, jmp, Kref); volQrIns.AddFactoryDomainPair(factory, _cutDom, fixedOrder); } } return(volQrIns); }
/// <summary> /// writes the dammed result of the integration to the sparse matrix /// </summary> protected override void SaveIntegrationResults(int i0, int Length, MultidimensionalArray ResultsOfIntegration) { int GAMMA = this.m_CodomainMap.BasisS.Count; // GAMMA: number of codom/row/test variables LECQuadratureLevelSet <IMutableMatrixEx, double[]> .CompOffsets(i0, Length, out int[] offsetRow, out int[] RowNonxN, m_CodomainMap); SpeciesId[] spcS = new[] { this.SpeciesA, this.SpeciesB }; int[] _i0aff = new int[2]; int[] _iEaff = new int[2]; // loop over cells... for (int i = 0; i < Length; i++) { int jCell = i + i0; #if DEBUG Debug.Assert(RowNonxN.ListEquals(m_CodomainMap.GetNonXBasisLengths(jCell))); #endif _i0aff[0] = i; _iEaff[0] = -1; for (int gamma = 0; gamma < GAMMA; gamma++) // loop over rows... { for (int cr = 0; cr < 2; cr++) // loop over neg/pos species row... { SpeciesId rowSpc = spcS[cr]; int Row0 = m_CodomainMap.LocalUniqueCoordinateIndex(m_lsTrk, gamma, jCell, rowSpc, 0); _i0aff[1] = offsetRow[gamma] + RowNonxN[gamma] * cr; // the 'RowXbSw' is 0 for non-xdg, so both species will be added _iEaff[1] = _i0aff[1] + RowNonxN[gamma] - 1; var BlockRes = ResultsOfIntegration.ExtractSubArrayShallow(_i0aff, _iEaff); for (int r = BlockRes.GetLength(0) - 1; r >= 0; r--) { ResultVector[Row0 + r] += BlockRes[r]; } } } } }
/// <summary> /// Boundary quadrature for the surface elements, i.e. for each cut background-cell \f$ K_j \f$ a quadrature to approximate /// \f[ /// \int_{\partial K_j \cap \mathfrak{I} } \ldots \mathrm{dS} . /// \f] /// </summary> public EdgeQuadratureScheme GetEdgeQuadScheme(SpeciesId sp, bool UseDefaultFactories = true, EdgeMask IntegrationDomain = null, int?fixedOrder = null) { if (!this.SpeciesList.Contains(sp)) { throw new ArgumentException("Given species (id = " + sp.cntnt + ") is not supported."); } // determine domain // ================ var allRelevantEdges = GetEdgeMask(sp, IntegrationDomain); // create quadrature scheme // ======================== { // default rules for all edges: EdgeQuadratureScheme edgeQrIns = new EdgeQuadratureScheme(UseDefaultFactories, allRelevantEdges); // overwrite with cut-cell-rules in cut-cells: foreach (var Kref in XDGSpaceMetrics.GridDat.Grid.RefElements) { for (int iLevSet = 0; iLevSet < XDGSpaceMetrics.NoOfLevelSets; iLevSet++) // loop over level sets... { EdgeMask cutEdges = this.GetCutEdges(Kref, iLevSet).Intersect(allRelevantEdges); #if DEBUG CellMask difference = cutEdges.GetAdjacentCells(XDGSpaceMetrics.GridDat).Except(XDGSpaceMetrics.LevelSetRegions.GetCutCellMask4LevSet(iLevSet)); if (difference.Count() > 0) { throw new ArithmeticException("Edges of the Cells" + difference.GetSummary() + " are detected as cut, but these cells are not contained in the cut Cell-Mask of the Level-Set-Tracker"); } #endif var jmp = IdentifyWing(iLevSet, sp); var factory = this.XDGSpaceMetrics.XQuadFactoryHelper.GetEdgeRuleFactory(iLevSet, jmp, Kref); edgeQrIns.AddFactoryDomainPair(factory, cutEdges, fixedOrder); } } return(edgeQrIns); } }
private CellMask GetCellMask(SpeciesId sp, CellMask IntegrationDomain) { if (!this.SpeciesList.Contains(sp)) { throw new ArgumentException("Given species (sp = " + sp.cntnt + ") is not supported."); } CellMask OutCellMask; if (IntegrationDomain == null) { OutCellMask = XDGSpaceMetrics.LevelSetRegions.GetSpeciesMask(sp); } else { OutCellMask = XDGSpaceMetrics.LevelSetRegions.GetSpeciesMask(sp).Intersect(IntegrationDomain); } return(OutCellMask); }
/// <summary> /// stores XDG coordinates species-wise and retains backward compatibility using a mysterious magic header /// </summary> public override double[] SerializeDGcoords(int j) { int Ndg = this.Basis.NonX_Basis.GetLength(j); var trk = this.Basis.Tracker; int NoOfSpc = trk.Regions.GetNoOfSpecies(j); double[] Ret = new double[4 + NoOfSpc * (Ndg + 1)]; // write the magic header Ret[0] = double.NegativeInfinity; Ret[1] = double.MaxValue; Ret[2] = double.NaN; Ret[3] = Ndg; int Ptr = 4; for (int iSpc = 0; iSpc < NoOfSpc; iSpc++) { int n0 = iSpc * Ndg; SpeciesId spc = trk.Regions.GetSpeciesIdFromIndex(j, iSpc); if (trk.Regions.IsSpeciesPresentInCell(spc, j)) { Ret[Ptr] = spc.cntnt; Ptr++; for (int n = 0; n < Ndg; n++) { Ret[Ptr] = this.Coordinates[j, n + n0]; Ptr++; } } } if (Ptr < Ret.Length) { Array.Resize(ref Ret, Ptr); } return(Ret); }
/// <summary> /// Tests if a species \f$\mathfrak{s}\f$ is actually \f$ \emph{present} \f$ in some cell \f$K_{\text{\tt jCell}}\f$, /// i.e. if /// the measure of the species in the cell is positive, i.e. /// \f[ /// \int_{K_{\text{\tt jCell}} \cap \mathfrak{s} } 1 \dV > 0 /// \f] /// </summary> /// <param name="speciesId">The id of species \mathfrak{s}.</param> /// <param name="jCell">a cell index</param> /// <returns></returns> /// <remarks> /// Note that /// a species may not be 'present' in some cell /// although /// the index of a species (e.g. obtained by <see cref="GetSpeciesIndex(SpeciesId,int)"/>) /// may be positive. /// In the near-field however, some species index may be allocated (on the 'other' side of the level-set), /// but the species may not be present. /// </remarks> public bool IsSpeciesPresentInCell(SpeciesId speciesId, int jCell) { bool matchesOne = false; LevelSetSignCode[] signCodes = m_owner.GetLevelSetSignCodes(speciesId); // Check if at least one of the sign codes matches the // situation in the current cell for (int k = 0; k < signCodes.Length; k++) { bool matches = true; for (int j = 0; j < m_owner.NoOfLevelSets; j++) { int sign = Math.Sign(DecodeLevelSetDist(m_LevSetRegions[jCell], j)); // Cell is cut, both signs exist and thus the mask // matches for sure if (sign == 0) { continue; } int signCodeEntry = (signCodes[k].val & 0x1 << j) >> j; // Code translation: 2 * {0, 1} - 1 = {-1, 1} if (sign != 2 * signCodeEntry - 1) { matches = false; break; } } matchesOne = matchesOne || matches; } return(matchesOne); }
private CellMask GetCellMask(SpeciesId sp, CellMask IntegrationDomain) { if (!this.SpeciesList.Contains(sp)) { throw new ArgumentException("Given species (sp = " + sp.cntnt + ") is not supported."); } Debug.Assert(IntegrationDomain == null || IntegrationDomain.MaskType == MaskType.Logical); CellMask OutCellMask; if (IntegrationDomain == null) { OutCellMask = XDGSpaceMetrics.LevelSetRegions.GetSpeciesMask(sp); Debug.Assert(OutCellMask.MaskType == MaskType.Logical); } else { OutCellMask = XDGSpaceMetrics.LevelSetRegions.GetSpeciesMask(sp).Intersect(IntegrationDomain); } OutCellMask = OutCellMask.ToGeometicalMask(); return(OutCellMask); }
void ILinearLevelSetComponent_V.LevelSetForm_V(LevSetIntParams inp, MultidimensionalArray Koeff_V) { int j0 = inp.i0; int Len = inp.Len; int N = inp.X.GetLength(1); // nodes per cell int D = inp.X.GetLength(2); // spatial dim. int NoOfVars = this.ArgumentOrdering.Count; LevelSetTracker lsTrk = m_LsTrk; // check dimension of input array Koeff_V.CheckLengths(Len, N, 2); // create temp mem: double[] node = new double[D]; double[] normal = new double[D]; int NP = (this.ParameterOrdering != null) ? this.ParameterOrdering.Count : 0; double[] ParamsPos = new double[NP]; double[] ParamsNeg = new double[NP]; CommonParamsLs cp = default(CommonParamsLs); cp.n = normal; cp.x = node; cp.ParamsNeg = ParamsNeg; cp.ParamsPos = ParamsPos; cp.time = inp.time; // temp mem. double[] uA = new double[NoOfVars]; double[] uB = new double[NoOfVars]; double[,] Grad_uA = new double[NoOfVars, D]; double[,] Grad_uB = new double[NoOfVars, D]; double vA = 0; double vB = 0; double[] Grad_vA = new double[D]; double[] Grad_vB = new double[D]; var h_min = this.m_LsTrk.GridDat.Cells.h_min; //LevelSetSignCode pos; //LevelSetSignCode neg; //GetSignCode(out neg, out pos); SpeciesId posSpc = this.PositiveSpecies; SpeciesId negSpc = this.NegativeSpecies; var Reg = lsTrk.Regions; for (int j = 0; j < Len; j++) // loop over items... { ReducedRegionCode rrc; int NoOf = Reg.GetNoOfSpecies(j + inp.i0, out rrc); Debug.Assert(NoOf == 2); //int iSpcPos = lsTrk.GetSpeciesIndex(rrc, pos); //int iSpcNeg = lsTrk.GetSpeciesIndex(rrc, neg); int iSpcPos = lsTrk.GetSpeciesIndex(rrc, posSpc); int iSpcNeg = lsTrk.GetSpeciesIndex(rrc, negSpc); cp.jCell = j + inp.i0; if (inp.PosCellLengthScale != null) { cp.PosCellLengthScale = inp.PosCellLengthScale[cp.jCell]; } else { cp.PosCellLengthScale = double.NaN; } if (inp.NegCellLengthScale != null) { cp.NegCellLengthScale = inp.NegCellLengthScale[cp.jCell]; } else { cp.NegCellLengthScale = double.NaN; } for (int n = 0; n < N; n++) // loop over nodes... { inp.Normal.CopyTo(normal, j, n, -1); inp.X.CopyTo(node, j, n, -1); for (int i = 0; i < NP; i++) { ParamsPos[i] = inp.ParamsPos[i][j, n]; ParamsNeg[i] = inp.ParamsNeg[i][j, n]; } Koeff_V[j, n, iSpcNeg] = GetSourceCoeff(ref vA, ref cp, uA, uB, Grad_uA, Grad_uB, ref vA, ref vB, Grad_vA, Grad_vB); Koeff_V[j, n, iSpcPos] = GetSourceCoeff(ref vB, ref cp, uA, uB, Grad_uA, Grad_uB, ref vA, ref vB, Grad_vA, Grad_vB); } } }
static bool IsCellCut(int iEdge, int[,] E2C, LevelSetTracker.LevelSetRegions regions, SpeciesId mySp) { int jCell0 = E2C[iEdge, 0]; int iSpc_cell0 = regions.GetSpeciesIndex(mySp, jCell0); if (iSpc_cell0 != 0) { return(true); } int jCell1 = E2C[iEdge, 1]; if (jCell1 >= 0) { int iSpc_cell1 = regions.GetSpeciesIndex(mySp, jCell1); if (iSpc_cell1 != 0) { return(true); } } return(false); }
/// <summary> /// Initializes <see cref="CellLengthScales"/>. /// </summary> void LengthScaleAgg() { SpeciesId[] species = this.SpeciesList.ToArray(); int J = this.Tracker.GridDat.Cells.NoOfLocalUpdatedCells; int JE = this.Tracker.GridDat.Cells.Count; int[][] C2E = this.Tracker.GridDat.Cells.Cells2Edges; var CellLengthScalesMda = MultidimensionalArray.Create(JE, species.Length, 2); // 1st index: cell, 2nd index: species var CellVolumeFracMda = MultidimensionalArray.Create(JE, species.Length); // 1st index: cell, 2nd index: species for (int iSpc = 0; iSpc < species.Length; iSpc++) { SpeciesId spc = species[iSpc]; var agginfo = this.GetAgglomerator(spc).AggInfo; BitArray aggEdgesBitMask = agginfo.AgglomerationEdges.GetBitMask(); MultidimensionalArray CellSurface = CellLengthScalesMda.ExtractSubArrayShallow(-1, iSpc, 0); MultidimensionalArray CellVolume = CellLengthScalesMda.ExtractSubArrayShallow(-1, iSpc, 1); MultidimensionalArray CellVolume2 = CellVolumeFracMda.ExtractSubArrayShallow(-1, iSpc); CellSurface.Set(this.NonAgglomeratedMetrics.InterfaceArea[spc]); CellVolume.Set(this.NonAgglomeratedMetrics.CutCellVolumes[spc]); CellVolume2.Set(this.NonAgglomeratedMetrics.CutCellVolumes[spc]); MultidimensionalArray EdgeArea = this.NonAgglomeratedMetrics.CutEdgeAreas[spc]; // accumulate cell surface for (int j = 0; j < J; j++) { int[] edges = C2E[j]; int NE = edges.Length; for (int ne = 0; ne < NE; ne++) { int iEdg = Math.Abs(edges[ne]) - 1; Debug.Assert(this.Tracker.GridDat.Edges.CellIndices[iEdg, 0] == j || this.Tracker.GridDat.Edges.CellIndices[iEdg, 1] == j); if (!aggEdgesBitMask[iEdg]) { Debug.Assert(!(double.IsNaN(CellSurface[j]) || double.IsInfinity(CellSurface[j]))); Debug.Assert(!(double.IsNaN(EdgeArea[iEdg]) || double.IsInfinity(EdgeArea[iEdg]))); CellSurface[j] += EdgeArea[iEdg]; Debug.Assert(!(double.IsNaN(CellSurface[j]) || double.IsInfinity(CellSurface[j]))); } } } } // MPI exchange // Needed, such that all ExternalCells (i.e. Ghost cells) have the correct CellSurface CellLengthScalesMda.Storage.MPIExchange(this.Tracker.GridDat); CellVolumeFracMda.Storage.MPIExchange(this.Tracker.GridDat); var AggCellLengthScalesMda = MultidimensionalArray.Create(JE, species.Length); // 1st index: cell, 2nd index: species for (int iSpc = 0; iSpc < species.Length; iSpc++) { SpeciesId spc = species[iSpc]; var agginfo = this.GetAgglomerator(spc).AggInfo; MultidimensionalArray CellSurface = CellLengthScalesMda.ExtractSubArrayShallow(-1, iSpc, 0); MultidimensionalArray CellVolume = CellLengthScalesMda.ExtractSubArrayShallow(-1, iSpc, 1); MultidimensionalArray CellVolume2 = CellVolumeFracMda.ExtractSubArrayShallow(-1, iSpc); // sum agglomeration sources to targets foreach (var agg_pair in agginfo.AgglomerationPairs) { CellSurface[agg_pair.jCellTarget] += CellSurface[agg_pair.jCellSource]; CellVolume[agg_pair.jCellTarget] += CellVolume[agg_pair.jCellSource]; } MultidimensionalArray LengthScales = AggCellLengthScalesMda.ExtractSubArrayShallow(-1, iSpc); // Loop includes external cells for (int j = 0; j < JE; j++) { LengthScales[j] = CellVolume[j] / CellSurface[j]; CellVolume2[j] = CellVolume2[j] / this.Tracker.GridDat.Cells.GetCellVolume(j); } // set values in agglomeration sources to be equal to agglomeration targets foreach (var agg_pair in agginfo.AgglomerationPairs) { LengthScales[agg_pair.jCellSource] = LengthScales[agg_pair.jCellTarget]; CellVolume2[agg_pair.jCellSource] = CellVolume2[agg_pair.jCellTarget]; } if (this.AgglomerationThreshold <= 1e-6) { // special treatment for no agglomeration -- which is anyway not recommended at all // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ CellMask spcDom = this.Tracker.Regions.GetSpeciesMask(spc); foreach (int j in spcDom.ItemEnum) { double unCut = this.Tracker.GridDat.Cells.GetCellVolume(j); double Fraction = CellVolume[j] / unCut; if (Fraction <= 1.0e-10) LengthScales[j] = 1e10; } } #if DEBUG foreach (int jCell in this.Tracker.Regions.GetSpeciesMask(spc).ItemEnum) { Debug.Assert(!(double.IsNaN(LengthScales[jCell]) || double.IsInfinity(LengthScales[jCell]))); } #endif } // MPI exchange -> Is it really needed now??? AggCellLengthScalesMda.Storage.MPIExchange(this.Tracker.GridDat); // store this.CellLengthScales = new Dictionary<SpeciesId, MultidimensionalArray>(); this.CellVolumeFrac = new Dictionary<SpeciesId, MultidimensionalArray>(); for (int iSpc = 0; iSpc < species.Length; iSpc++) { SpeciesId spc = species[iSpc]; this.CellLengthScales.Add(spc, AggCellLengthScalesMda.ExtractSubArrayShallow(-1, iSpc).CloneAs()); this.CellVolumeFrac.Add(spc, CellVolumeFracMda.ExtractSubArrayShallow(-1, iSpc).CloneAs()); } }
/// <summary> /// Not implemented yet. /// </summary> public override void EvaluateEdge(int e0, int Len, NodeSet NS, MultidimensionalArray ValueIN, MultidimensionalArray ValueOT, MultidimensionalArray MeanValueIN, MultidimensionalArray MeanValueOT, MultidimensionalArray GradientIN, MultidimensionalArray GradientOT, int ResultIndexOffset, double ResultPreScale) { // check arguments // =============== int D = GridDat.SpatialDimension; // spatial dimension int N = m_Basis.Length; // number of coordinates per cell int K = NS.NoOfNodes; // number of nodes { if ((ValueIN != null) != (ValueOT != null)) { throw new ArgumentException(); } if ((MeanValueIN != null) != (MeanValueOT != null)) { throw new ArgumentException(); } if ((GradientIN != null) != (GradientOT != null)) { throw new ArgumentException(); } if (ValueIN != null) { if (ValueIN.Dimension != 2) { throw new ArgumentException("result", "dimension of result array must be 2"); } if (Len > ValueIN.GetLength(0) + ResultIndexOffset) { throw new ArgumentException("mismatch between Len and 0-th length of result"); } if (ValueIN.GetLength(1) != K) { throw new ArgumentException(); } if (ValueOT.Dimension != 2) { throw new ArgumentException("result", "dimension of result array must be 2"); } if (Len > ValueOT.GetLength(0) + ResultIndexOffset) { throw new ArgumentException("mismatch between Len and 0-th length of result"); } if (ValueOT.GetLength(1) != K) { throw new ArgumentException(); } if (!(ResultIndexOffset == 0 && Len == ValueIN.GetLength(0))) { ValueIN = ValueIN.ExtractSubArrayShallow(new int[] { ResultIndexOffset, 0 }, new int[] { ResultIndexOffset + Len - 1, K - 1 }); } if (!(ResultIndexOffset == 0 && Len == ValueOT.GetLength(0))) { ValueOT = ValueOT.ExtractSubArrayShallow(new int[] { ResultIndexOffset, 0 }, new int[] { ResultIndexOffset + Len - 1, K - 1 }); } } if (MeanValueIN != null) { if (MeanValueIN.Dimension != 1) { throw new ArgumentException("Dimension of mean-value result array must be 1."); } if (Len > MeanValueIN.GetLength(0) + ResultIndexOffset) { throw new ArgumentException("mismatch between Len and 0-th length of result"); } if (MeanValueOT.Dimension != 1) { throw new ArgumentException("Dimension of mean-value result array must be 1."); } if (Len > MeanValueOT.GetLength(0) + ResultIndexOffset) { throw new ArgumentException("mismatch between Len and 0-th length of result"); } if (!(ResultIndexOffset == 0 && Len == MeanValueIN.GetLength(0))) { MeanValueIN = MeanValueIN.ExtractSubArrayShallow(new int[] { ResultIndexOffset }, new int[] { ResultIndexOffset + Len - 1 }); } if (!(ResultIndexOffset == 0 && Len == MeanValueOT.GetLength(0))) { MeanValueOT = MeanValueOT.ExtractSubArrayShallow(new int[] { ResultIndexOffset }, new int[] { ResultIndexOffset + Len - 1 }); } } if (GradientIN != null) { if (GradientIN.Dimension != 3) { throw new ArgumentException("Dimension of gradient result array must be 3."); } if (Len > GradientIN.GetLength(0) + ResultIndexOffset) { throw new ArgumentException("mismatch between Len and 0-th length of result"); } if (GradientIN.GetLength(1) != K) { throw new ArgumentException(); } if (GradientIN.GetLength(2) != D) { throw new ArgumentException(); } if (GradientOT.Dimension != 3) { throw new ArgumentException("Dimension of gradient result array must be 3."); } if (Len > GradientOT.GetLength(0) + ResultIndexOffset) { throw new ArgumentException("mismatch between Len and 0-th length of result"); } if (GradientOT.GetLength(1) != K) { throw new ArgumentException(); } if (GradientOT.GetLength(2) != D) { throw new ArgumentException(); } if (!(ResultIndexOffset == 0 && Len == GradientIN.GetLength(0))) { GradientIN = GradientIN.ExtractSubArrayShallow(new int[] { ResultIndexOffset, 0, 0 }, new int[] { ResultIndexOffset + Len - 1, K - 1, D - 1 }); } if (!(ResultIndexOffset == 0 && Len == GradientOT.GetLength(0))) { GradientOT = GradientOT.ExtractSubArrayShallow(new int[] { ResultIndexOffset, 0, 0 }, new int[] { ResultIndexOffset + Len - 1, K - 1, D - 1 }); } } var coöSys = NS.GetNodeCoordinateSystem(this.GridDat); if (coöSys != NodeCoordinateSystem.EdgeCoord) { throw new ArgumentOutOfRangeException(); } } // real evaluation int[,] E2C = this.GridDat.iGeomEdges.CellIndices; // geometric edges to geometric cells int[][] cellL2C = this.GridDat.iLogicalCells.AggregateCellToParts; // logical cells to geometrical if (cellL2C != null) { throw new NotImplementedException("todo"); } int[,] TrfIdx = this.GridDat.iGeomEdges.Edge2CellTrafoIndex; LevelSetTracker lsTrk = this.Owner.Basis.Tracker; var regions = lsTrk.Regions; var gdat = this.GridDat; SpeciesId mySp = this.SpeciesId; int i = 0; while (i < Len) { int ChunkLen = 1; int iEdge = i + e0; bool CutOrNot = IsCellCut(iEdge, E2C, regions, mySp); if (CutOrNot == false) { // both Neighbor cells are *not* cut // standard evaluation // try to find vectorization while ((ChunkLen + i < Len) && (IsCellCut(iEdge + ChunkLen, E2C, regions, mySp) == false)) { ChunkLen++; } //EvaluateEdgeInternal(iEdge, ChunkLen, NS, m_Owner.Basis.NonX_Basis, // m_Owner.m_Coordinates // ) } else { // one or both neighbors are cut cells; // non-vectorized evaluation Debug.Assert(ChunkLen == 1); } Debug.Assert(i + ChunkLen <= Len); int I0 = ResultIndexOffset + i; int IE = ResultIndexOffset + i + ChunkLen - 1; MultidimensionalArray chunkValueIN, chunkValueOT; if (ValueIN != null) { chunkValueIN = ValueIN.ExtractSubArrayShallow(new[] { I0, 0 }, new[] { IE, K - 1 }); chunkValueOT = ValueOT.ExtractSubArrayShallow(new[] { I0, 0 }, new[] { IE, K - 1 }); } else { chunkValueIN = ValueIN; chunkValueOT = ValueOT; } MultidimensionalArray chunkMeanValueIN, chunkMeanValueOT; if (MeanValueIN != null) { chunkMeanValueIN = MeanValueIN.ExtractSubArrayShallow(new[] { I0 }, new[] { IE }); chunkMeanValueOT = MeanValueOT.ExtractSubArrayShallow(new[] { I0 }, new[] { IE }); } else { chunkMeanValueIN = MeanValueIN; chunkMeanValueOT = MeanValueOT; } MultidimensionalArray chunkGradientIN, chunkGradientOT; if (GradientIN != null) { chunkGradientIN = GradientIN.ExtractSubArrayShallow(new[] { I0, 0, 0 }, new[] { IE, K - 1, D - 1 }); chunkGradientOT = GradientOT.ExtractSubArrayShallow(new[] { I0, 0, 0 }, new[] { IE, K - 1, D - 1 }); } else { chunkGradientIN = GradientIN; chunkGradientOT = GradientOT; } if (CutOrNot) { Debug.Assert(ChunkLen == 1); int jCell0 = E2C[iEdge, 0]; int jCell1 = E2C[iEdge, 1]; NodeSet NSvol0, NSvol1; NSvol0 = NS.GetVolumeNodeSet(gdat, TrfIdx[iEdge, 0]); if (jCell1 >= 0) { NSvol1 = NS.GetVolumeNodeSet(gdat, TrfIdx[iEdge, 1]); } else { NSvol1 = null; } if (ValueIN != null) { this.Evaluate(jCell0, 1, NSvol0, chunkValueIN, ResultPreScale); } if (ValueOT != null && jCell1 >= 0) { this.Evaluate(jCell1, 1, NSvol1, chunkValueOT, ResultPreScale); } if (MeanValueIN != null) { this.EvaluateMean(jCell0, 1, chunkMeanValueIN, 0, ResultPreScale); } if (MeanValueOT != null && jCell1 >= 0) { this.EvaluateMean(jCell1, 1, chunkMeanValueOT, 0, ResultPreScale); } if (GradientIN != null) { this.EvaluateGradient(jCell0, 1, NSvol0, chunkGradientIN, 0, ResultPreScale); } if (GradientOT != null && jCell1 >= 0) { this.EvaluateGradient(jCell1, 1, NSvol1, chunkGradientOT, 0, ResultPreScale); } } else { // for edges 'iEdge' through 'iEdge + ChunkLen - 1', this shadow field is the 0-th species for IN and OT cell EvaluateEdgeInternal(iEdge, ChunkLen, NS, m_Owner.Basis.NonX_Basis, m_Owner.m_Coordinates.BaseStorageMda, chunkValueIN, chunkValueOT, chunkMeanValueIN, chunkMeanValueOT, chunkGradientIN, chunkGradientOT, ResultPreScale); } i += ChunkLen; } Debug.Assert(i == Len); }
/// <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()); }
/// <summary> /// computes a local unique coordinate index ("local" means local on this processor); /// this index is unique over all fields (in this mapping), over all cells, over all basis functions, /// but it's only locally (on this processor) valid. /// A local index in the update range (smaller than <see cref="NUpdate"/>) can be converted into /// a global index by adding <see cref="Partitioning.i0"/>. /// </summary> /// <param name="find"> /// the field or basis index (see <see cref="BasisS"/>); /// </param> /// <param name="j">local cell index</param> /// <param name="n">DG mode index</param> /// <param name="lsTrk"></param> /// <param name="map"></param> /// <param name="spc">species</param> public static int LocalUniqueCoordinateIndex(this UnsetteledCoordinateMapping map, LevelSetTracker lsTrk, int find, int j, SpeciesId spc, int n) { int spcIdx = lsTrk.Regions.GetSpeciesIndex(spc, j); return(LocalUniqueCoordinateIndex(map, lsTrk, find, j, spcIdx, n)); }
/* * * static int Jmp2Idx(JumpTypes jmp) { * switch (jmp) { * case JumpTypes.OneMinusHeaviside: * return 0; * case JumpTypes.Heaviside: * return 1; * default: * throw new NotSupportedException(); * } * } * * static internal double Jmp2Sign(JumpTypes jmp) { * return (double)Math.Sign(((double)Jmp2Idx(jmp)) - 0.5); * } */ ///// <summary> ///// Writes diagnostic information about quadrature rules into csv-textfiles. ///// </summary> //public void RuleInfo(string spc, string volruleName, string levsetRuleName, string cellBndRule, string edgeRuleName, int order) { // RuleInfo(lsTrk.GetSpeciesId(spc), volruleName, levsetRuleName, cellBndRule, edgeRuleName, order); //} /// <summary> /// Writes diagnostic information about quadrature rules into csv-textfiles. /// </summary> public void RuleInfo(SpeciesId spc, string volruleName, string levsetRuleName, string cellBndRule, string edgeRuleName, int order, int iLevSet) { var _Context = this.XDGSpaceMetrics.GridDat; // test parameters var jmp = Foundation.XDG.Quadrature.HMF.JumpTypes.Heaviside; var sch = this.XDGSpaceMetrics.XQuadFactoryHelper; var spNm = this.XDGSpaceMetrics.LevelSetRegions.GetSpeciesName(spc); //var spId = LsTrk.GetSpeciesId(spNm); var DomainOfInterest = XDGSpaceMetrics.LevelSetRegions.GetCutCellSubgrid4LevSet(iLevSet); if (volruleName != null) { int J = _Context.Cells.NoOfLocalUpdatedCells; double[] TotWeights = new double[J]; foreach (var Kref in this.XDGSpaceMetrics.GridDat.Grid.RefElements) { var volfactory = sch.GetVolRuleFactory(0, jmp, Kref); var qrset = volfactory.GetQuadRuleSet(DomainOfInterest.VolumeMask, order); foreach (var chk in qrset) { for (int j = chk.Chunk.i0; j < chk.Chunk.JE; j++) { TotWeights[j] = chk.Rule.Weights.Sum(); } } } DomainOfInterest.VolumeMask.SaveToTextFile(volruleName + "-" + spNm + ".csv", false, delegate(double[] x, int jL, int iG) { return(TotWeights[jL]); }); } if (levsetRuleName != null) { int J = _Context.Cells.NoOfLocalUpdatedCells; double[] TotWeights = new double[J]; foreach (var Kref in this.XDGSpaceMetrics.GridDat.Grid.RefElements) { var levsetFactory = sch.GetSurfaceFactory(0, Kref); var qrset = levsetFactory.GetQuadRuleSet(DomainOfInterest.VolumeMask, order); foreach (var chk in qrset) { for (int j = chk.Chunk.i0; j < chk.Chunk.JE; j++) { TotWeights[j] = chk.Rule.Weights.Sum(); } } } DomainOfInterest.VolumeMask.SaveToTextFile(levsetRuleName + "-" + spNm + ".csv", false, delegate(double[] x, int jL, int iG) { return(TotWeights[jL]); }); } { int NoEdg = this.XDGSpaceMetrics.GridDat.Edges.Count; double[] TotWeights = new double[NoEdg]; foreach (var Kref in this.XDGSpaceMetrics.GridDat.Grid.RefElements) { var edgeFactory = sch.GetEdgeRuleFactory(0, jmp, Kref); var qrset = edgeFactory.GetQuadRuleSet(DomainOfInterest.AllEdgesMask, order); foreach (var chk in qrset) { for (int j = chk.Chunk.i0; j < chk.Chunk.JE; j++) { TotWeights[j] = chk.Rule.Weights.Sum(); } } } DomainOfInterest.AllEdgesMask.SaveToTextFile(edgeRuleName + "-" + spNm + ".csv", false, delegate(double[] x, int jL, int iG) { return(TotWeights[jL]); }); } // */ /* * if (cellBndRule != null) { * int J = _Context.Cells.NoOfLocalUpdatedCells; * var FaceWeightSum = MultidimensionalArray.Create(J, this.lsTrk.GridDat.Grid.RefElements.Max(Kref => Kref.NoOfFaces)); * * foreach (var Kref in this.lsTrk.GridDat.Grid.RefElements) { * var ruleConv = sch.GetVolumeEdgeRuleFactory(0, Kref); * var qrset = ruleConv.GetQuadRuleSet(DomainOfInterest.VolumeMask, order); * * * int F = Kref.NoOfFaces; * * * foreach (var chk in qrset) { * for (int j = chk.Chunk.i0; j < chk.Chunk.JE; j++) { * var Rule = chk.Rule; * var NodesPerFace = Rule.NumbersOfNodesPerFace; * * int N0 = 0; * * for (int f = 0; f < F; f++) { * for (int n = N0; n < N0 + NodesPerFace[f]; n++) { * FaceWeightSum[j, f] += Rule.Weights[n]; * } * N0 += NodesPerFace[f]; * } * } * } * } * * //DomainOfInterest.VolumeMask.ToTxtFile("cellBndRule-" + jmp + ".csv", false, * // delegate(double[] x, int j) { return FaceWeightSum[j, 0]; }, * // delegate(double[] x, int j) { return FaceWeightSum[j, 1]; }, * // delegate(double[] x, int j) { return FaceWeightSum[j, 2]; }, * // delegate(double[] x, int j) { return FaceWeightSum[j, 3]; }); * * ToTxtFile(cellBndRule + ".csv", FaceWeightSum, DomainOfInterest.VolumeMask); * }*/ }
/// <summary> /// Creates an subgrid which only contains cells /// that are at least partly occupied by species /// <paramref name="speciesName"/>; /// </summary> /// <param name="speciesName"> /// The name of the species /// </param> /// <returns> /// A subgrid containing only cells with at least a portion of /// species <paramref name="speciesName"/> /// </returns> public SubGrid GetSpeciesSubGrid(string speciesName) { SpeciesId id = m_owner.GetSpeciesId(speciesName); return(GetSpeciesSubGrid(id));// this.SubGrids[id]; }
/// <summary> /// see <see cref="GetSpeciesMask(SpeciesId)"/> /// </summary> /// <param name="speciesName"></param> /// <returns></returns> public CellMask GetSpeciesMask(string speciesName) { SpeciesId id = m_owner.GetSpeciesId(speciesName); return(GetSpeciesMask(id)); }
/// <summary> /// Quadrature scheme which is used for the penalty components in <see cref="XSpatialOperator.GhostEdgesOperator"/>, for species <paramref name="sp"/>. /// </summary> public EdgeQuadratureScheme GetEdgeGhostScheme(SpeciesId sp, EdgeMask IntegrationDomainRestriction = null) { if (!this.SpeciesList.Contains(sp)) { throw new ArgumentException("Given species (" + sp.cntnt + ") is not supported."); } // select all edges for species sp with a positive measure // ======================================================= var EdgBitMask = this.GetEdgeMask(sp, IntegrationDomainRestriction).GetBitMask().CloneAs(); var EdgArea = this.NonAgglomeratedMetrics.CutEdgeAreas[sp]; int L = EdgBitMask.Length; for (int e = 0; e < L; e++) { if (EdgArea[e] <= 0) { EdgBitMask[e] = false; } } // return // ====== return(new EdgeQuadratureScheme(true, new EdgeMask(this.XDGSpaceMetrics.GridDat, EdgBitMask))); /* * * if (!this.GhostSupport) * throw new NotSupportedException(); * * * // determine domain * // ================ * * var allRelevantEdges = this.GhostIntegrationDomain[sp]; * if (IntegrationDomain != null) { * allRelevantEdges = allRelevantEdges.Intersect(IntegrationDomain); * } * * // special treatment for the edges of agglomerated cells * // ===================================================== * EdgeMask fuckedEdges = null; * { * * var AggCells = this.CellAgglomeration.GetAgglomerator(sp).AggInfo.SourceCells; * if (AggCells != null && AggCells.NoOfItemsLocally > 0) { * //int EdgB4 = allRelevantEdges.NoOfItemsGlobally; * * //allRelevantEdges = allRelevantEdges.Except(AggCellsSgrd.InnerEdgesMask); // option 1 * //allRelevantEdges = allRelevantEdges.Except(AggCellsSgrd.AllEdgesMask); // option 2 * // option 3: überhaupt nix * * fuckedEdges = allRelevantEdges.Intersect(this.CellAgglomeration.GetAgglomerator(sp).AggInfo.SourceCellsEdges); * } * } * * // create Scheme * // ============= * { * var GhostScheme = new EdgeQuadratureScheme(true, allRelevantEdges); * * // use the HMF-rule on the edges of the agglomerated cells: * if (fuckedEdges != null) { * foreach (var Kref in lsTrk.GridDat.Grid.RefElements) { * for (int iLevSet = 0; iLevSet < lsTrk.LevelSets.Count; iLevSet++) { // loop over level sets... * var cutEdges = fuckedEdges; * cutEdges = cutEdges.Intersect(this.m_Subgrid4Kref_AllEdges[Kref]); * var jmp = IdentifyWing(iLevSet, sp); * var factory = this.lsTrk.GetXQuadFactoryHelper(MomentFittingVariant).GetEdgeRuleFactory(iLevSet, jmp, Kref); * GhostScheme.AddFactory(factory, cutEdges); * } * } * } * * // return * return GhostScheme; * } */ }
/// <summary> /// For some species <paramref name="sp"/>, /// this function computes on which side/wing /// of level-set no. <paramref name="levSetIdx"/>) /// the species is located. /// </summary> /// <remarks> /// Nur ein Provisorium, das ganze Konzept ist noch etwas unausgereift. (Habe einen Nachmittag lang darueber nachgedacht, keinen bessere Idee gehabt, /// und darum...). /// </remarks> public JumpTypes IdentifyWing(int levSetIdx, SpeciesId sp) { int NoOfLevSets = this.XDGSpaceMetrics.NoOfLevelSets; if (levSetIdx < 0 || levSetIdx > NoOfLevSets) { throw new ArgumentOutOfRangeException(); } if (NoOfLevSets == 1) { string[] speciesTable = (string[])(this.XDGSpaceMetrics.LevelSetRegions.SpeciesTable); Debug.Assert(speciesTable.Length == 2); string spN = this.XDGSpaceMetrics.LevelSetRegions.GetSpeciesName(sp); if (spN == speciesTable[0]) { return(JumpTypes.OneMinusHeaviside); } else if (spN == speciesTable[1]) { return(JumpTypes.Heaviside); } else { throw new Exception("should not happen."); } } else if (NoOfLevSets == 2) { string[,] speciesTable = (string[, ])(this.XDGSpaceMetrics.LevelSetRegions.SpeciesTable); Debug.Assert(speciesTable.GetLength(0) == 2); Debug.Assert(speciesTable.GetLength(1) == 2); string spN = this.XDGSpaceMetrics.LevelSetRegions.GetSpeciesName(sp); int cnt = 0; JumpTypes jmpRet = JumpTypes.Implicit; int[] _i = new int[2]; for (_i[0] = 0; _i[0] < 2; _i[0]++) // loop over signs of level-set 0 ... { for (_i[1] = 0; _i[1] < 2; _i[1]++) // loop over signs of level-set 1 ... { if (speciesTable[_i[0], _i[1]] == spN) { cnt++; if (_i[levSetIdx] == 0) { jmpRet = JumpTypes.OneMinusHeaviside; } else if (_i[levSetIdx] == 1) { jmpRet = JumpTypes.Heaviside; } else { throw new ApplicationException(); } } } } if (cnt != 1) { throw new NotImplementedException("unable to identify."); } return(jmpRet); } else { throw new NotImplementedException(); } }
/// <summary> /// Equal to <see cref="LevelSetTracker.GetSpeciesName(SpeciesId)"/>. /// </summary> public String GetSpeciesName(SpeciesId id) { return(m_owner.GetSpeciesName(id)); }