public IBMAdamsBashforthLTS(SpatialOperator standardOperator, SpatialOperator boundaryOperator, CoordinateMapping fieldsMap, CoordinateMapping boundaryParameterMap, ISpeciesMap ibmSpeciesMap, IBMControl control, IList <TimeStepConstraint> timeStepConstraints, int reclusteringInterval, bool fluxCorrection) : base(standardOperator, fieldsMap, boundaryParameterMap, control.ExplicitOrder, control.NumberOfSubGrids, true, timeStepConstraints, reclusteringInterval: reclusteringInterval, fluxCorrection: fluxCorrection, subGrid: ibmSpeciesMap.SubGrid) { this.speciesMap = ibmSpeciesMap as ImmersedSpeciesMap; if (this.speciesMap == null) { throw new ArgumentException( "Only supported for species maps of type 'ImmersedSpeciesMap'", "speciesMap"); } this.standardOperator = standardOperator; this.boundaryOperator = boundaryOperator; this.boundaryParameterMap = boundaryParameterMap; this.fieldsMap = fieldsMap; this.control = control; agglomerationPatternHasChanged = true; cutCells = speciesMap.Tracker.Regions.GetCutCellMask(); cutAndTargetCells = cutCells.Union(speciesMap.Agglomerator.AggInfo.TargetCells); // Normal LTS constructor NumberOfLocalTimeSteps = new List <int>(control.NumberOfSubGrids); clusterer = new Clusterer(this.gridData, this.TimeStepConstraints); CurrentClustering = clusterer.CreateClustering(control.NumberOfSubGrids, speciesMap.SubGrid); CurrentClustering = CalculateNumberOfLocalTS(CurrentClustering); // Might remove sub-grids when time step sizes are too similar ABevolver = new IBMABevolve[CurrentClustering.NumberOfClusters]; for (int i = 0; i < ABevolver.Length; i++) { ABevolver[i] = new IBMABevolve(standardOperator, boundaryOperator, fieldsMap, boundaryParameterMap, speciesMap, control.ExplicitOrder, control.LevelSetQuadratureOrder, control.CutCellQuadratureType, sgrd: CurrentClustering.Clusters[i], adaptive: this.adaptive); ABevolver[i].OnBeforeComputeChangeRate += (t1, t2) => this.RaiseOnBeforeComputechangeRate(t1, t2); } GetBoundaryTopology(); #if DEBUG for (int i = 0; i < CurrentClustering.NumberOfClusters; i++) { Console.WriteLine("IBM AB LTS ctor: id=" + i + " -> sub-steps=" + NumberOfLocalTimeSteps[i] + " and elements=" + CurrentClustering.Clusters[i].GlobalNoOfCells); } #endif // Start-up phase needs an IBM Runge-Kutta time stepper RungeKuttaScheme = new IBMSplitRungeKutta(standardOperator, boundaryOperator, fieldsMap, boundaryParameterMap, speciesMap, timeStepConstraints); }
internal void BuildEvaluatorsAndMasks() { CellMask fluidCells = speciesMap.SubGrid.VolumeMask.Intersect(ABSubGrid.VolumeMask); cutCells = speciesMap.Tracker.Regions.GetCutCellMask().Intersect(ABSubGrid.VolumeMask); cutAndTargetCells = cutCells.Union(speciesMap.Agglomerator.AggInfo.TargetCells).Intersect(ABSubGrid.VolumeMask); IBMControl control = speciesMap.Control; SpeciesId species = speciesMap.Tracker.GetSpeciesId(control.FluidSpeciesName); CellQuadratureScheme volumeScheme = speciesMap.QuadSchemeHelper.GetVolumeQuadScheme( species, true, fluidCells, control.LevelSetQuadratureOrder); // Does _not_ include agglomerated edges EdgeMask nonVoidEdges = speciesMap.QuadSchemeHelper.GetEdgeMask(species); nonVoidEdges = nonVoidEdges.Intersect(ABSubGrid.AllEdgesMask.ToGeometicalMask()); EdgeQuadratureScheme edgeScheme = speciesMap.QuadSchemeHelper.GetEdgeQuadScheme( species, true, nonVoidEdges, control.LevelSetQuadratureOrder); this.m_Evaluator = new Lazy <IEvaluatorNonLin>(delegate() { this.Operator.EdgeQuadraturSchemeProvider = g => edgeScheme; this.Operator.VolumeQuadraturSchemeProvider = g => volumeScheme; var opi = this.Operator.GetEvaluatorEx( Mapping, boundaryParameterMap, Mapping); opi.ActivateSubgridBoundary(ABSubGrid.VolumeMask, subGridBoundaryTreatment: SubGridBoundaryModes.InnerEdgeLTS); return(opi); }); // Evaluator for boundary conditions at level set zero contour CellQuadratureScheme boundaryVolumeScheme = speciesMap.QuadSchemeHelper.GetLevelSetquadScheme( 0, cutCells, control.LevelSetQuadratureOrder); this.boundaryEvaluator = new Lazy <IEvaluatorNonLin>(delegate() { boundaryOperator.EdgeQuadraturSchemeProvider = g => null; // Contains no boundary terms --> PROBLEM?????????? boundaryOperator.VolumeQuadraturSchemeProvider = g => boundaryVolumeScheme; return(boundaryOperator.GetEvaluatorEx( Mapping, boundaryParameterMap, Mapping)); }); }
internal void BuildEvaluatorsAndMasks() { CellMask fluidCells = speciesMap.SubGrid.VolumeMask.Intersect(ABSubGrid.VolumeMask); cutCells = speciesMap.Tracker.Regions.GetCutCellMask().Intersect(ABSubGrid.VolumeMask); cutAndTargetCells = cutCells.Union(speciesMap.Agglomerator.AggInfo.TargetCells).Intersect(ABSubGrid.VolumeMask); IBMControl control = speciesMap.Control; SpeciesId species = speciesMap.Tracker.GetSpeciesId(control.FluidSpeciesName); CellQuadratureScheme volumeScheme = speciesMap.QuadSchemeHelper.GetVolumeQuadScheme( species, true, fluidCells, control.LevelSetQuadratureOrder); // Does _not_ include agglomerated edges EdgeMask nonVoidEdges = speciesMap.QuadSchemeHelper.GetEdgeMask(species); nonVoidEdges = nonVoidEdges.Intersect(ABSubGrid.AllEdgesMask); EdgeQuadratureScheme edgeScheme = speciesMap.QuadSchemeHelper.GetEdgeQuadScheme( species, true, nonVoidEdges, control.LevelSetQuadratureOrder); this.m_Evaluator = new Lazy <SpatialOperator.Evaluator>(() => this.Operator.GetEvaluatorEx( Mapping, boundaryParameterMap, Mapping, edgeScheme, volumeScheme, ABSubGrid, subGridBoundaryTreatment: SpatialOperator.SubGridBoundaryModes.InnerEdgeLTS)); // Evaluator for boundary conditions at level set zero contour CellQuadratureScheme boundaryVolumeScheme = speciesMap.QuadSchemeHelper.GetLevelSetquadScheme( 0, cutCells, control.LevelSetQuadratureOrder); this.boundaryEvaluator = new Lazy <SpatialOperator.Evaluator>(() => boundaryOperator.GetEvaluatorEx( Mapping, boundaryParameterMap, Mapping, null, // Contains no boundary terms --> PROBLEM?????????? boundaryVolumeScheme)); }
private void BuildEvaluatorsAndMasks() { CellMask fluidCells = speciesMap.SubGrid.VolumeMask; cutCells = speciesMap.Tracker.Regions.GetCutCellMask(); cutAndTargetCells = cutCells.Union(speciesMap.Agglomerator.AggInfo.TargetCells); IBMControl control = speciesMap.Control; SpeciesId species = speciesMap.Tracker.GetSpeciesId(control.FluidSpeciesName); CellQuadratureScheme volumeScheme = speciesMap.QuadSchemeHelper.GetVolumeQuadScheme( species, true, fluidCells, control.LevelSetQuadratureOrder); // Does _not_ include agglomerated edges EdgeMask nonVoidEdges = speciesMap.QuadSchemeHelper.GetEdgeMask(species); EdgeQuadratureScheme edgeScheme = speciesMap.QuadSchemeHelper.GetEdgeQuadScheme( species, true, nonVoidEdges, control.LevelSetQuadratureOrder); this.m_Evaluator = new Lazy <IEvaluatorNonLin>(delegate() { this.Operator.EdgeQuadraturSchemeProvider = g => edgeScheme; this.Operator.VolumeQuadraturSchemeProvider = g => volumeScheme; var opi = this.Operator.GetEvaluatorEx( Mapping, null, // TO DO: I SIMPLY REMOVE PARAMETERMAP HERE; MAKE THIS MORE PRETTY //this.boundaryParameterMap, // TO DO: I SIMPLY REMOVE PARAMETERMAP HERE; MAKE THIS MORE PRETTY Mapping); opi.ActivateSubgridBoundary(volumeScheme.Domain, subGridBoundaryTreatment: SubGridBoundaryModes.InnerEdgeLTS); //opi.ActivateSubgridBoundary(fluidCells, subGridBoundaryTreatment: SubGridBoundaryModes.InnerEdgeLTS); return(opi); }); // Evaluator for boundary conditions at level set zero contour CellQuadratureScheme boundaryVolumeScheme = speciesMap.QuadSchemeHelper.GetLevelSetquadScheme( 0, cutCells, control.LevelSetQuadratureOrder); this.boundaryEvaluator = new Lazy <IEvaluatorNonLin>(delegate() { boundaryOperator.EdgeQuadraturSchemeProvider = g => null; // Contains no boundary terms boundaryOperator.VolumeQuadraturSchemeProvider = g => boundaryVolumeScheme; return(boundaryOperator.GetEvaluatorEx( Mapping, boundaryParameterMap, Mapping)); }); }
protected void UpdateEvaluatorsAndMasks() { CellMask fluidCells = speciesMap.SubGrid.VolumeMask; cutCells = speciesMap.Tracker.Regions.GetCutCellMask(); cutAndTargetCells = cutCells.Union(speciesMap.Agglomerator.AggInfo.TargetCells); IBMControl control = speciesMap.Control; SpeciesId species = speciesMap.Tracker.GetSpeciesId(control.FluidSpeciesName); CellQuadratureScheme volumeScheme = speciesMap.QuadSchemeHelper.GetVolumeQuadScheme( species, true, fluidCells, control.LevelSetQuadratureOrder); // Does _not_ include agglomerated edges EdgeMask nonVoidEdges = speciesMap.QuadSchemeHelper.GetEdgeMask(species); EdgeQuadratureScheme edgeScheme = speciesMap.QuadSchemeHelper.GetEdgeQuadScheme( species, true, nonVoidEdges, control.LevelSetQuadratureOrder); this.m_Evaluator = new Lazy <IEvaluatorNonLin>(delegate() { var opi = this.Operator.GetEvaluatorEx( Mapping, boundaryParameterMap, Mapping, edgeScheme, volumeScheme); opi.ActivateSubgridBoundary(volumeScheme.Domain.ToLogicalMask(), subGridBoundaryTreatment: SpatialOperator.SubGridBoundaryModes.InnerEdgeLTS); return(opi); }); // Evaluator for boundary conditions at level set zero contour CellQuadratureScheme boundaryVolumeScheme = speciesMap.QuadSchemeHelper.GetLevelSetquadScheme( 0, cutCells, control.LevelSetQuadratureOrder); this.boundaryEvaluator = new Lazy <IEvaluatorNonLin>(() => boundaryOperator.GetEvaluatorEx( Mapping, boundaryParameterMap, Mapping, null, // Contains no boundary terms boundaryVolumeScheme)); }
/// <summary> /// compiles a cell mask from all cells with a specific color and their direct neighbors /// </summary> /// <param name="gridData"> /// the grid that this mask will be associated with /// </param> /// <param name="ColoredCellsSorted"> /// a list of all cells sorted by color /// </param> /// <param name="CurrentColor"> /// the color which is associated with the Cell Mask /// </param> /// /// <param name="J"> /// the number of locally updated cells /// </param> internal CellMask CellsOneColor(IGridData gridData, List <int[]> ColoredCellsSorted, int CurrentColor, int J, bool FindNeighbours = true) { int[] CellIDCurrentColor = FindCellIDs(ColoredCellsSorted, CurrentColor); BitArray ColoredCells = new BitArray(J); for (int i = 0; i < CellIDCurrentColor.Length; i++) { if (CellIDCurrentColor[i] < J) { ColoredCells[CellIDCurrentColor[i]] = true; } } CellMask ColoredCellMask = new CellMask(gridData, ColoredCells); if (FindNeighbours) { CellMask ColoredCellMaskNeighbour = ColoredCellMask.AllNeighbourCells(); ColoredCellMask = ColoredCellMask.Union(ColoredCellMaskNeighbour); } return(ColoredCellMask); }
protected void MoveLevelSetTo(double time) { LevelSet levelSet = speciesMap.Tracker.LevelSets[0].As <LevelSet>(); levelSet.Clear(); levelSet.ProjectField(X => speciesMap.Control.LevelSetFunction(X, time)); speciesMap.Tracker.UpdateTracker(); cutCells = speciesMap.Tracker.Regions.GetCutCellMask(); cutAndTargetCells = cutCells.Union(speciesMap.Agglomerator.AggInfo.TargetCells); // EVIL HACK SINCE UPDATE OF GRADIENT ONLY HAPPENS AFTER TIME-STEP SO FAR foreach (var gradientField in boundaryParameterMap.Fields) { int d = int.Parse(gradientField.Identification.Last().ToString()); gradientField.Clear(); gradientField.Derivative( -1.0, levelSet, d, cutCells); } }
/// <summary> /// Computes the new level set field at time <paramref name="Phystime"/> + <paramref name="dt"/>. /// This is a 'driver function' which provides a universal interface to the various level set evolution algorithms. /// It also acts as a callback to the time stepper (see <see cref="m_BDF_Timestepper"/> resp. <see cref="m_RK_Timestepper"/>), /// i.e. it matches the signature of /// <see cref="BoSSS.Solution.XdgTimestepping.DelUpdateLevelset"/>. /// </summary> /// <param name="Phystime"></param> /// <param name="dt"></param> /// <param name="CurrentState"> /// The current solution (velocity and pressure), since the complete solution is provided by the time stepper, /// only the velocity components(supposed to be at the beginning) are used. /// </param> /// <param name="underrelax"> /// </param> public double DelUpdateLevelSet(DGField[] CurrentState, double Phystime, double dt, double underrelax, bool incremental) { using (new FuncTrace()) { //dt *= underrelax; int D = base.Grid.SpatialDimension; int iTimestep = hack_TimestepIndex; DGField[] EvoVelocity = CurrentState.GetSubVector(0, D); // ======================================================== // Backup old level-set, in order to compute the residual // ======================================================== SinglePhaseField LsBkUp = new SinglePhaseField(this.LevSet.Basis); LsBkUp.Acc(1.0, this.LevSet); CellMask oldCC = LsTrk.Regions.GetCutCellMask(); // ==================================================== // set evolution velocity, but only on the CUT-cells // ==================================================== #region Calculate density averaged Velocity for each cell ConventionalDGField[] meanVelocity = GetMeanVelocityFromXDGField(EvoVelocity); #endregion // =================================================================== // backup interface properties (mass conservation, surface changerate) // =================================================================== #region backup interface props double oldSurfVolume = 0.0; double oldSurfLength = 0.0; double SurfChangerate = 0.0; if (this.Control.CheckInterfaceProps) { oldSurfVolume = XNSEUtils.GetSpeciesArea(this.LsTrk, LsTrk.GetSpeciesId("A")); oldSurfLength = XNSEUtils.GetInterfaceLength(this.LsTrk); SurfChangerate = EnergyUtils.GetSurfaceChangerate(this.LsTrk, meanVelocity, this.m_HMForder); } #endregion // ==================================================== // perform level-set evolution // ==================================================== #region level-set evolution // set up for Strang splitting SinglePhaseField DGLevSet_old; if (incremental) { DGLevSet_old = this.DGLevSet.Current.CloneAs(); } else { DGLevSet_old = this.DGLevSet[0].CloneAs(); } // set up for underrelaxation SinglePhaseField DGLevSet_oldIter = this.DGLevSet.Current.CloneAs(); //PlotCurrentState(hack_Phystime, new TimestepNumber(new int[] { hack_TimestepIndex, 0 }), 2); // actual evolution switch (this.Control.Option_LevelSetEvolution) { case LevelSetEvolution.None: throw new ArgumentException("illegal call"); case LevelSetEvolution.FastMarching: { NarrowMarchingBand.Evolve_Mk2( dt, this.LsTrk, DGLevSet_old, this.DGLevSet.Current, this.DGLevSetGradient, meanVelocity, this.ExtensionVelocity.Current.ToArray(), //new DGField[] { LevSetSrc }, this.m_HMForder, iTimestep); //FastMarchReinitSolver = new FastMarchReinit(DGLevSet.Current.Basis); //CellMask Accepted = LsTrk.Regions.GetCutCellMask(); //CellMask ActiveField = LsTrk.Regions.GetNearFieldMask(1); //CellMask NegativeField = LsTrk.Regions.GetSpeciesMask("A"); //FastMarchReinitSolver.FirstOrderReinit(DGLevSet.Current, Accepted, NegativeField, ActiveField); break; } case LevelSetEvolution.Fourier: { Fourier_Timestepper.moveLevelSet(dt, meanVelocity); if (incremental) { Fourier_Timestepper.updateFourierLevSet(); } Fourier_LevSet.ProjectToDGLevelSet(this.DGLevSet.Current, this.LsTrk); break; } case LevelSetEvolution.Prescribed: { this.DGLevSet.Current.Clear(); this.DGLevSet.Current.ProjectField(1.0, this.Control.Phi.Vectorize(Phystime + dt)); break; } case LevelSetEvolution.ScalarConvection: { var LSM = new LevelSetMover(EvoVelocity, this.ExtensionVelocity, this.LsTrk, XVelocityProjection.CutCellVelocityProjectiontype.L2_plain, this.DGLevSet, this.BcMap); int check1 = this.ExtensionVelocity.PushCount; int check2 = this.DGLevSet.PushCount; this.DGLevSet[1].Clear(); this.DGLevSet[1].Acc(1.0, DGLevSet_old); LSM.Advect(dt); if (check1 != this.ExtensionVelocity.PushCount) { throw new ApplicationException(); } if (check2 != this.DGLevSet.PushCount) { throw new ApplicationException(); } break; } case LevelSetEvolution.ExtensionVelocity: { DGLevSetGradient.Clear(); DGLevSetGradient.Gradient(1.0, DGLevSet.Current); ExtVelMover.Advect(dt); // Fast Marching: Specify the Domains first // Perform Fast Marching only on the Far Field if (this.Control.AdaptiveMeshRefinement) { int NoCells = ((GridData)this.GridData).Cells.Count; BitArray Refined = new BitArray(NoCells); for (int j = 0; j < NoCells; j++) { if (((GridData)this.GridData).Cells.GetCell(j).RefinementLevel > 0) { Refined[j] = true; } } CellMask Accepted = new CellMask(this.GridData, Refined); CellMask AcceptedNeigh = Accepted.AllNeighbourCells(); Accepted = Accepted.Union(AcceptedNeigh); CellMask ActiveField = Accepted.Complement(); CellMask NegativeField = LsTrk.Regions.GetSpeciesMask("A"); FastMarchReinitSolver.FirstOrderReinit(DGLevSet.Current, Accepted, NegativeField, ActiveField); } else { CellMask Accepted = LsTrk.Regions.GetNearFieldMask(1); CellMask ActiveField = Accepted.Complement(); CellMask NegativeField = LsTrk.Regions.GetSpeciesMask("A"); FastMarchReinitSolver.FirstOrderReinit(DGLevSet.Current, Accepted, NegativeField, ActiveField); } //SubGrid AcceptedGrid = new SubGrid(Accepted); //ReInitPDE.ReInitialize(Restriction: AcceptedGrid); //CellMask ActiveField = Accepted.Complement(); //CellMask NegativeField = LsTrk.Regions.GetSpeciesMask("A"); //FastMarchReinitSolver.FirstOrderReinit(DGLevSet.Current, Accepted, NegativeField, ActiveField); //ReInitPDE.ReInitialize(); break; } default: throw new ApplicationException(); } // performing underrelaxation if (underrelax < 1.0) { this.DGLevSet.Current.Scale(underrelax); this.DGLevSet.Current.Acc((1.0 - underrelax), DGLevSet_oldIter); } //PlotCurrentState(hack_Phystime, new TimestepNumber(new int[] { hack_TimestepIndex, 1 }), 2); #endregion // ====================== // postprocessing // ======================= if (this.Control.ReInitPeriod > 0 && hack_TimestepIndex % this.Control.ReInitPeriod == 0) { Console.WriteLine("Filtering DG-LevSet"); SinglePhaseField FiltLevSet = new SinglePhaseField(DGLevSet.Current.Basis); FiltLevSet.AccLaidBack(1.0, DGLevSet.Current); Filter(FiltLevSet, 2, oldCC); DGLevSet.Current.Clear(); DGLevSet.Current.Acc(1.0, FiltLevSet); Console.WriteLine("FastMarchReInit performing FirstOrderReInit"); FastMarchReinitSolver = new FastMarchReinit(DGLevSet.Current.Basis); CellMask Accepted = LsTrk.Regions.GetCutCellMask(); CellMask ActiveField = LsTrk.Regions.GetNearFieldMask(1); CellMask NegativeField = LsTrk.Regions.GetSpeciesMask("A"); FastMarchReinitSolver.FirstOrderReinit(DGLevSet.Current, Accepted, NegativeField, ActiveField); } #region ensure continuity // make level set continuous CellMask CC = LsTrk.Regions.GetCutCellMask4LevSet(0); CellMask Near1 = LsTrk.Regions.GetNearMask4LevSet(0, 1); CellMask PosFF = LsTrk.Regions.GetLevelSetWing(0, +1).VolumeMask; ContinuityEnforcer.MakeContinuous(this.DGLevSet.Current, this.LevSet, Near1, PosFF); if (this.Control.Option_LevelSetEvolution == LevelSetEvolution.FastMarching) { CellMask Nearband = Near1.Union(CC); this.DGLevSet.Current.Clear(Nearband); this.DGLevSet.Current.AccLaidBack(1.0, this.LevSet, Nearband); //ContinuityEnforcer.SetFarField(this.DGLevSet.Current, Near1, PosFF); } //PlotCurrentState(hack_Phystime, new TimestepNumber(new int[] { hack_TimestepIndex, 2 }), 2); #endregion for (int d = 0; d < D; d++) { this.XDGvelocity.Velocity[d].UpdateBehaviour = BehaveUnder_LevSetMoovement.AutoExtrapolate; } // =============== // tracker update // =============== this.LsTrk.UpdateTracker(Phystime + dt, incremental: true); // update near field (in case of adaptive mesh refinement) if (this.Control.AdaptiveMeshRefinement && this.Control.Option_LevelSetEvolution == LevelSetEvolution.FastMarching) { Near1 = LsTrk.Regions.GetNearMask4LevSet(0, 1); PosFF = LsTrk.Regions.GetLevelSetWing(0, +1).VolumeMask; ContinuityEnforcer.SetFarField(this.DGLevSet.Current, Near1, PosFF); ContinuityEnforcer.SetFarField(this.LevSet, Near1, PosFF); } // ================================================================== // check interface properties (mass conservation, surface changerate) // ================================================================== if (this.Control.CheckInterfaceProps) { double currentSurfVolume = XNSEUtils.GetSpeciesArea(this.LsTrk, LsTrk.GetSpeciesId("A")); double massChange = ((currentSurfVolume - oldSurfVolume) / oldSurfVolume) * 100; Console.WriteLine("Change of mass = {0}%", massChange); double currentSurfLength = XNSEUtils.GetInterfaceLength(this.LsTrk); double actualSurfChangerate = (currentSurfLength - oldSurfLength) / dt; Console.WriteLine("Interface divergence = {0}", SurfChangerate); Console.WriteLine("actual surface changerate = {0}", actualSurfChangerate); } // ================== // compute residual // ================== var newCC = LsTrk.Regions.GetCutCellMask(); LsBkUp.Acc(-1.0, this.LevSet); double LevSetResidual = LsBkUp.L2Norm(newCC.Union(oldCC)); return(LevSetResidual); } }
/// <summary> /// Computes Cell-volumes and edge areas before agglomeration. /// </summary> void ComputeNonAgglomeratedMetrics() { var gd = XDGSpaceMetrics.GridDat; int JE = gd.Cells.NoOfCells; int J = gd.Cells.NoOfLocalUpdatedCells; int D = gd.SpatialDimension; int EE = gd.Edges.Count; SpeciesId[] species = this.SpeciesList.ToArray(); int NoSpc = species.Count(); int[,] E2C = gd.Edges.CellIndices; var schH = new XQuadSchemeHelper(XDGSpaceMetrics); double[] vec_cellMetrics = new double[JE * NoSpc * 2]; // collect all per-cell-metrics in the same MultidimArry, for MPI-exchange // 1st index: cell // 2nd index: species // 3rd index: 0 for interface surface per cell, 1 for cut-cell-volume MultidimensionalArray cellMetrics = MultidimensionalArray.CreateWrapper(vec_cellMetrics, JE, NoSpc, 2); this.CutEdgeAreas = new Dictionary <SpeciesId, MultidimensionalArray>(); this.CutCellVolumes = new Dictionary <SpeciesId, MultidimensionalArray>(); this.InterfaceArea = new Dictionary <SpeciesId, MultidimensionalArray>(); //var schS = new List<CellQuadratureScheme>(); //var rulz = new List<ICompositeQuadRule<QuadRule>>(); // edges and volumes // ================= for (int iSpc = 0; iSpc < species.Length; iSpc++) { var cellVol = cellMetrics.ExtractSubArrayShallow(-1, iSpc, 1); var spc = species[iSpc]; MultidimensionalArray edgArea = MultidimensionalArray.Create(EE); this.CutEdgeAreas.Add(spc, edgArea); // compute cut edge area // --------------------- var edgeScheme = schH.GetEdgeQuadScheme(spc); var edgeRule = edgeScheme.Compile(gd, this.CutCellQuadratureOrder); BoSSS.Foundation.Quadrature.EdgeQuadrature.GetQuadrature( new int[] { 1 }, gd, edgeRule, _Evaluate : delegate(int i0, int Length, QuadRule QR, MultidimensionalArray EvalResult) // { EvalResult.SetAll(1.0); }, _SaveIntegrationResults : delegate(int i0, int Length, MultidimensionalArray ResultsOfIntegration) // { for (int i = 0; i < Length; i++) { int iEdge = i + i0; Debug.Assert(edgArea[iEdge] == 0); edgArea[iEdge] = ResultsOfIntegration[i, 0]; Debug.Assert(!(double.IsNaN(edgArea[iEdge]) || double.IsInfinity(edgArea[iEdge]))); } }).Execute(); // compute cut cell volumes // ------------------------ var volScheme = schH.GetVolumeQuadScheme(spc); var volRule = volScheme.Compile(gd, this.CutCellQuadratureOrder); //schS.Add(volScheme); //rulz.Add(volRule); BoSSS.Foundation.Quadrature.CellQuadrature.GetQuadrature( new int[] { 1 }, gd, volRule, _Evaluate : delegate(int i0, int Length, QuadRule QR, MultidimensionalArray EvalResult) // { EvalResult.SetAll(1.0); }, _SaveIntegrationResults : delegate(int i0, int Length, MultidimensionalArray ResultsOfIntegration) // { for (int i = 0; i < Length; i++) { int jCell = i + i0; Debug.Assert(cellVol[jCell] == 0); cellVol[jCell] = ResultsOfIntegration[i, 0]; Debug.Assert(!(double.IsNaN(cellVol[jCell]) || double.IsInfinity(cellVol[jCell]))); } }).Execute(); } // interface surface // ================= // loop over all possible pairs of species /* * for (int iSpcA = 0; iSpcA < species.Length; iSpcA++) { * var SpeciesA = species[iSpcA]; * var SpeciesADom = lsTrk.GetSpeciesMask(SpeciesA); * if (SpeciesADom.NoOfItemsLocally <= 0) * continue; * * for (int iSpcB = iSpcA + 1; iSpcB < species.Length; iSpcB++) { * var SpeciesB = species[iSpcB]; * var SpeciesBDom = lsTrk.GetSpeciesMask(SpeciesB); * if (SpeciesBDom.NoOfItemsLocally <= 0) * continue; * * var SpeciesCommonDom = SpeciesADom.Intersect(SpeciesBDom); * if (SpeciesCommonDom.NoOfItemsLocally <= 0) * continue; * * // loop over level-sets * int NoOfLs = lsTrk.LevelSets.Count; * for (int iLevSet = 0; iLevSet < NoOfLs; iLevSet++) { * * * var LsDom = lsTrk.GetCutCellMask4LevSet(iLevSet); * var IntegrationDom = LsDom.Intersect(SpeciesCommonDom); * * if (IntegrationDom.NoOfItemsLocally > 0) { * CellQuadratureScheme SurfIntegration = schH.GetLevelSetquadScheme(iLevSet, IntegrationDom); * var rule = SurfIntegration.Compile(gd, this.HMForder); * * * BoSSS.Foundation.Quadrature.CellQuadrature.GetQuadrature( * new int[] { 1 }, gd, * rule, * _Evaluate: delegate (int i0, int Length, QuadRule QR, MultidimensionalArray EvalResult) // * { * EvalResult.SetAll(1.0); * }, * _SaveIntegrationResults: delegate (int i0, int Length, MultidimensionalArray ResultsOfIntegration) // * { * for (int i = 0; i < Length; i++) { * int jCell = i + i0; * if (cellMetrics[jCell, iSpcA, 0] != 0.0) * throw new NotSupportedException("More than one zero-level-set per cell is not supported yet."); * if (cellMetrics[jCell, iSpcB, 0] != 0.0) * throw new NotSupportedException("More than one zero-level-set per cell is not supported yet."); * * cellMetrics[jCell, iSpcA, 0] = ResultsOfIntegration[i, 0]; * cellMetrics[jCell, iSpcB, 0] = ResultsOfIntegration[i, 0]; * } * }).Execute(); * } * } * } * }*/ // loop over level-sets if (species.Length > 0) { // find domain of all species: CellMask SpeciesCommonDom = XDGSpaceMetrics.LevelSetRegions.GetSpeciesMask(species[0]); for (int iSpc = 1; iSpc < species.Length; iSpc++) { SpeciesCommonDom = SpeciesCommonDom.Union(XDGSpaceMetrics.LevelSetRegions.GetSpeciesMask(species[iSpc])); } BitArray[] SpeciesBitMask = species.Select(spc => XDGSpaceMetrics.LevelSetRegions.GetSpeciesMask(spc).GetBitMask()).ToArray(); int NoOfLs = XDGSpaceMetrics.NoOfLevelSets; int NoOfSpc = species.Length; for (int iLevSet = 0; iLevSet < NoOfLs; iLevSet++) { var LsDom = XDGSpaceMetrics.LevelSetRegions.GetCutCellMask4LevSet(iLevSet); var IntegrationDom = LsDom.Intersect(SpeciesCommonDom); //if (IntegrationDom.NoOfItemsLocally > 0) { -> Doesn't work if Bjoerns HMF is used, eds up in an mpi dead lock // +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // this level-set is actually relevant for someone in 'species' // +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ CellQuadratureScheme SurfIntegration = schH.GetLevelSetquadScheme(iLevSet, IntegrationDom); var rule = SurfIntegration.Compile(gd, this.CutCellQuadratureOrder); BoSSS.Foundation.Quadrature.CellQuadrature.GetQuadrature( new int[] { 1 }, gd, rule, _Evaluate : delegate(int i0, int Length, QuadRule QR, MultidimensionalArray EvalResult) { EvalResult.SetAll(1.0); }, _SaveIntegrationResults : delegate(int i0, int Length, MultidimensionalArray ResultsOfIntegration) { for (int i = 0; i < Length; i++) { int jCell = i + i0; //if (cellMetrics[jCell, iSpcA, 0] != 0.0) // throw new NotSupportedException("More than one zero-level-set per cell is not supported yet."); //if (cellMetrics[jCell, iSpcB, 0] != 0.0) // throw new NotSupportedException("More than one zero-level-set per cell is not supported yet."); //cellMetrics[jCell, iSpcA, 0] = ResultsOfIntegration[i, 0]; //cellMetrics[jCell, iSpcB, 0] = ResultsOfIntegration[i, 0]; for (int iSpc = 0; iSpc < NoOfSpc; iSpc++) { if (SpeciesBitMask[iSpc][jCell]) { cellMetrics[jCell, iSpc, 0] += ResultsOfIntegration[i, 0]; Debug.Assert(!(double.IsNaN(cellMetrics[jCell, iSpc, 0]) || double.IsInfinity(cellMetrics[jCell, iSpc, 0]))); } } } }).Execute(); //} } } // MPI exchange & store // ==================== if (species.Length > 0) { vec_cellMetrics.MPIExchange(gd); } for (int iSpc = 0; iSpc < species.Length; iSpc++) { var spc = species[iSpc]; this.InterfaceArea.Add(spc, cellMetrics.ExtractSubArrayShallow(-1, iSpc, 0).CloneAs()); this.CutCellVolumes.Add(spc, cellMetrics.ExtractSubArrayShallow(-1, iSpc, 1).CloneAs()); } //Console.WriteLine("Erinn - debug code."); //for(int j = 0; j < J; j++) { // double totVol = gd.Cells.GetCellVolume(j); // double blaVol = 0; // for(int iSpc = 0; iSpc < species.Length; iSpc++) { // var spc = species[iSpc]; // var cellVolS = this.CutCellVolumes[spc][j]; // blaVol += cellVolS; // } // Debug.Assert(Math.Abs(totVol - blaVol) / totVol < 1.0e-8); //} }
/// <summary> /// Computes Cell-volumes and edge areas before agglomeration. /// </summary> void ComputeNonAgglomeratedMetrics() { using (new FuncTrace()) { MPICollectiveWatchDog.Watch(); var gd = XDGSpaceMetrics.GridDat; int JE = gd.iLogicalCells.Count; int J = gd.iLogicalCells.NoOfLocalUpdatedCells; int D = gd.SpatialDimension; int EE = gd.Edges.Count; SpeciesId[] species = this.SpeciesList.ToArray(); int NoSpc = species.Count(); int[,] E2C = gd.iLogicalEdges.CellIndices; var schH = new XQuadSchemeHelper(XDGSpaceMetrics); // collect all per-cell-metrics in the same MultidimArry, for MPI-exchange (only 1 exchange instead of three, saving some overhead) // 1st index: cell // 2nd index: species // 3rd index: 0 for interface surface per cell, 1 for cut-cell-volume, 2 for cut-cell surface double[] vec_cellMetrics = new double[JE * NoSpc * 3]; MultidimensionalArray cellMetrics = MultidimensionalArray.CreateWrapper(vec_cellMetrics, JE, NoSpc, 3); this.CutEdgeAreas = new Dictionary <SpeciesId, MultidimensionalArray>(); this.CutCellVolumes = new Dictionary <SpeciesId, MultidimensionalArray>(); this.InterfaceArea = new Dictionary <SpeciesId, MultidimensionalArray>(); this.CellSurface = new Dictionary <SpeciesId, MultidimensionalArray>(); //var schS = new List<CellQuadratureScheme>(); //var rulz = new List<ICompositeQuadRule<QuadRule>>(); // edges and volumes // ================= for (int iSpc = 0; iSpc < species.Length; iSpc++) { var cellVol = cellMetrics.ExtractSubArrayShallow(-1, iSpc, 1); var spc = species[iSpc]; // compute cut edge area // --------------------- MultidimensionalArray edgArea = MultidimensionalArray.Create(EE); this.CutEdgeAreas.Add(spc, edgArea); var edgeScheme = schH.GetEdgeQuadScheme(spc); var edgeRule = edgeScheme.Compile(gd, this.CutCellQuadratureOrder); BoSSS.Foundation.Quadrature.EdgeQuadrature.GetQuadrature( new int[] { 1 }, gd, edgeRule, _Evaluate : delegate(int i0, int Length, QuadRule QR, MultidimensionalArray EvalResult) // { EvalResult.SetAll(1.0); }, _SaveIntegrationResults : delegate(int i0, int Length, MultidimensionalArray ResultsOfIntegration) // { for (int i = 0; i < Length; i++) { int iEdge = i + i0; Debug.Assert(edgArea[iEdge] == 0); edgArea[iEdge] = ResultsOfIntegration[i, 0]; Debug.Assert(!(double.IsNaN(edgArea[iEdge]) || double.IsInfinity(edgArea[iEdge]))); } }).Execute(); // sum up edges for surface // ------------------------ var cellSurf = cellMetrics.ExtractSubArrayShallow(-1, iSpc, 2); for (int e = 0; e < EE; e++) { double a = edgArea[e]; int jCell0 = E2C[e, 0]; int jCell2 = E2C[e, 1]; cellSurf[jCell0] += a; if (jCell2 >= 0) { cellSurf[jCell2] += a; } } // compute cut cell volumes // ------------------------ var volScheme = schH.GetVolumeQuadScheme(spc); var volRule = volScheme.Compile(gd, this.CutCellQuadratureOrder); BoSSS.Foundation.Quadrature.CellQuadrature.GetQuadrature( new int[] { 1 }, gd, volRule, _Evaluate : delegate(int i0, int Length, QuadRule QR, MultidimensionalArray EvalResult) // { EvalResult.SetAll(1.0); }, _SaveIntegrationResults : delegate(int i0, int Length, MultidimensionalArray ResultsOfIntegration) // { for (int i = 0; i < Length; i++) { int jCell = i + i0; Debug.Assert(cellVol[jCell] == 0); cellVol[jCell] = ResultsOfIntegration[i, 0]; Debug.Assert(!(double.IsNaN(cellVol[jCell]) || double.IsInfinity(cellVol[jCell]))); } }).Execute(); } // interface surface // ================= // loop over level-sets if (species.Length > 0) { // find domain of all species: CellMask SpeciesCommonDom = XDGSpaceMetrics.LevelSetRegions.GetSpeciesMask(species[0]); for (int iSpc = 1; iSpc < species.Length; iSpc++) { SpeciesCommonDom = SpeciesCommonDom.Union(XDGSpaceMetrics.LevelSetRegions.GetSpeciesMask(species[iSpc])); } BitArray[] SpeciesBitMask = species.Select(spc => XDGSpaceMetrics.LevelSetRegions.GetSpeciesMask(spc).GetBitMask()).ToArray(); int NoOfLs = XDGSpaceMetrics.NoOfLevelSets; int NoOfSpc = species.Length; for (int iLevSet = 0; iLevSet < NoOfLs; iLevSet++) { var LsDom = XDGSpaceMetrics.LevelSetRegions.GetCutCellMask4LevSet(iLevSet); var IntegrationDom = LsDom.Intersect(SpeciesCommonDom); //if (IntegrationDom.NoOfItemsLocally > 0) { -> Doesn't work if Bjoerns HMF is used, eds up in an mpi dead lock // +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // this level-set is actually relevant for someone in 'species' // +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ CellQuadratureScheme SurfIntegration = schH.GetLevelSetquadScheme(iLevSet, IntegrationDom); var rule = SurfIntegration.Compile(gd, this.CutCellQuadratureOrder); BoSSS.Foundation.Quadrature.CellQuadrature.GetQuadrature( new int[] { 1 }, gd, rule, _Evaluate : delegate(int i0, int Length, QuadRule QR, MultidimensionalArray EvalResult) { EvalResult.SetAll(1.0); }, _SaveIntegrationResults : delegate(int i0, int Length, MultidimensionalArray ResultsOfIntegration) { for (int i = 0; i < Length; i++) { int jCell = i + i0; //if (cellMetrics[jCell, iSpcA, 0] != 0.0) // throw new NotSupportedException("More than one zero-level-set per cell is not supported yet."); //if (cellMetrics[jCell, iSpcB, 0] != 0.0) // throw new NotSupportedException("More than one zero-level-set per cell is not supported yet."); //cellMetrics[jCell, iSpcA, 0] = ResultsOfIntegration[i, 0]; //cellMetrics[jCell, iSpcB, 0] = ResultsOfIntegration[i, 0]; for (int iSpc = 0; iSpc < NoOfSpc; iSpc++) { if (SpeciesBitMask[iSpc][jCell]) { cellMetrics[jCell, iSpc, 0] += ResultsOfIntegration[i, 0]; Debug.Assert(!(double.IsNaN(cellMetrics[jCell, iSpc, 0]) || double.IsInfinity(cellMetrics[jCell, iSpc, 0]))); } } } }).Execute(); //} } } // MPI exchange & store // ==================== if (species.Length > 0) { #if DEBUG int NoOfSpc = species.Length; var cellMetricsB4 = cellMetrics.ExtractSubArrayShallow(new[] { 0, 0, 0 }, new[] { J - 1, NoOfSpc - 1, 1 }).CloneAs(); #endif vec_cellMetrics.MPIExchange(gd); #if DEBUG var cellMetricsComp = cellMetrics.ExtractSubArrayShallow(new[] { 0, 0, 0 }, new[] { J - 1, NoOfSpc - 1, 1 }).CloneAs(); cellMetricsComp.Acc(-1.0, cellMetricsB4); Debug.Assert(cellMetricsComp.L2Norm() == 0.0); #endif } for (int iSpc = 0; iSpc < species.Length; iSpc++) { var spc = species[iSpc]; this.InterfaceArea.Add(spc, cellMetrics.ExtractSubArrayShallow(-1, iSpc, 0).CloneAs()); this.CutCellVolumes.Add(spc, cellMetrics.ExtractSubArrayShallow(-1, iSpc, 1).CloneAs()); this.CellSurface.Add(spc, cellMetrics.ExtractSubArrayShallow(-1, iSpc, 2).CloneAs()); this.CellSurface[spc].Acc(1.0, this.InterfaceArea[spc]); } } }