/// <summary> /// assigns the cell index of the aggregated cell <em>j</em> to all (fine) grid cells that /// the aggregated cell <em>j</em> consists of. /// </summary> static public void ColorDGField(this AggregationGrid ag, DGField f) { if (!object.ReferenceEquals(f.GridDat, ag.AncestorGrid)) { throw new ArgumentException("mismatch in base grid."); } f.Clear(); int J = ag.iLogicalCells.NoOfLocalUpdatedCells; for (int j = 0; j < J; j++) // loog over logical/aggregate cells { int[] Neighs = ag.iLogicalCells.CellNeighbours[j]; var NeighColors = Neighs.Select(jNeigComp => (int)Math.Round(f.GetMeanValue(ag.iLogicalCells.AggregateCellToParts[jNeigComp][0]))); int iCol = 1; for (iCol = 1; iCol < 2 * J; iCol++) { if (!NeighColors.Contains(iCol)) { break; } } foreach (int jGeom in ag.iLogicalCells.AggregateCellToParts[j]) { f.SetMeanValue(jGeom, iCol); //f.SetMeanValue(jGeom, j); } } }
public ExtensionVelocityBDFMover(LevelSetTracker LSTrk, SinglePhaseField LevelSet, VectorField <SinglePhaseField> LevelSetGradient, VectorField <DGField> Velocity, EllipticExtVelAlgoControl Control, IncompressibleBoundaryCondMap bcMap, int BDForder, VectorField <SinglePhaseField> VectorExtension, double[] Density = null, bool AssumeDivergenceFreeVelocity = false, SubGrid subGrid = null) { this.GridDat = LSTrk.GridDat; D = GridDat.SpatialDimension; this.LevelSetGradient = LevelSetGradient; this.LSTrk = LSTrk; this.LevelSet = LevelSet; this.Velocity = Velocity; this.OldRHS = LevelSet.CloneAs(); this.AdvectionSpatialOperator = CreateAdvectionSpatialOperator(bcMap); this.subGrid = subGrid; this.nearfield = subGrid != null; Basis NonXVelocityBasis; if (Velocity == null) { throw new ArgumentException("Velocity Field not initialized!"); } // Initialize Extension Velocity Algorithm double PenaltyBase = Control.PenaltyMultiplierInterface * ((double)((LevelSet.Basis.Degree + 1) * (LevelSet.Basis.Degree + D))) / ((double)D); ILevelSetForm InterfaceFlux; //VectorExtension = new VectorField<SinglePhaseField>(D, Velocity[0].Basis, "ExtVel", SinglePhaseField.Factory); if (Velocity[0].GetType() == typeof(SinglePhaseField)) { NonXVelocityBasis = ((SinglePhaseField)Velocity[0]).Basis; InterfaceFlux = new SingleComponentInterfaceForm(PenaltyBase, LSTrk); } else if (Velocity[0].GetType() == typeof(XDGField)) { NonXVelocityBasis = ((XDGField)Velocity[0]).Basis.NonX_Basis; InterfaceFlux = new DensityWeightedExtVel(PenaltyBase, LSTrk, Density); } else { throw new ArgumentException("VelocityField must be either a SinglePhaseField or a XDGField!"); }; //VectorExtension = new VectorField<SinglePhaseField>(D, NonXVelocityBasis, "ExtVel", SinglePhaseField.Factory); this.VectorExtension = VectorExtension; VelocityExtender = new Extender[D]; for (int d = 0; d < D; d++) { VelocityExtender[d] = new Extender(VectorExtension[d], LSTrk, InterfaceFlux, new List <DGField> { Velocity[d] }, LevelSetGradient, Control); VelocityExtender[d].ConstructExtension(new List <DGField> { Velocity[d] }, Control.subGridRestriction); } #if DEBUG VectorExtension.CheckForNanOrInf(); #endif // Initialize Advection Algorithm divU = new SinglePhaseField(NonXVelocityBasis); divU.Identification = "Divergence"; divU.Clear(); divU.Divergence(1.0, VectorExtension); MeanVelocity = new VectorField <SinglePhaseField>(D.ForLoop(d => new SinglePhaseField(new Basis(GridDat, 0), VariableNames.Velocity0MeanVector(D)[d]))); MeanVelocity.Clear(); MeanVelocity.AccLaidBack(1.0, VectorExtension); myBDFTimestepper = new BDFTimestepper(AdvectionSpatialOperator, new List <DGField>() { LevelSet }, ArrayTools.Cat(VectorExtension, this.MeanVelocity, this.divU), BDForder, Control.solverFactory, false, subGrid); }
/// <summary> /// assigns the cell index of the aggregated cell <em>j</em> to all (fine) grid cells that /// the aggregated cell <em>j</em> consists of. /// </summary> static public void ColorDGField(this AggregationGridData ag, DGField f) { IGridData Anc = f.GridDat; if (!IsAnc(Anc, ag)) { throw new ArgumentException("Field 'f' must be defined on an ancestor grid of 'ag'."); } f.Clear(); int Jag = ag.iLogicalCells.NoOfLocalUpdatedCells; int Janc = Anc.iLogicalCells.NoOfLocalUpdatedCells; Debug.Assert(Anc.iGeomCells.Count == ag.iGeomCells.Count); int[] jG2jL = Anc.iGeomCells.GeomCell2LogicalCell; int[] Colors = new int[Jag]; BitArray Marked = new BitArray(Janc); for (int j = 0; j < Jag; j++) // loop over logical/aggregate cells // determine colors of neighbor cells { int[] Neighs = ag.iLogicalCells.CellNeighbours[j]; var NeighColors = Neighs.Select(jN => Colors[jN]); // select color for cell 'j' int iCol = 1; for (iCol = 1; iCol < 2 * Jag; iCol++) { if (!NeighColors.Contains(iCol)) { break; } } Colors[j] = iCol; // color all logical cells in ancestor grid // idea: convert to geometrical and back to logical // in this way we can e.g. skip multiple grid levels foreach (int jGeom in ag.iLogicalCells.AggregateCellToParts[j]) { int jLogAnc; if (jG2jL != null) { jLogAnc = jG2jL[jGeom]; } else { jLogAnc = jGeom; } if (!Marked[jLogAnc]) { f.SetMeanValue(jLogAnc, iCol); Marked[jLogAnc] = true; } else { // nop } } } }
/// <summary> /// Loads the DG coordinates after grid adaptation. /// </summary> /// <param name="f"></param> /// <param name="Reference"> /// Unique string reference under which data has been stored before grid-redistribution. /// </param> public override void RestoreDGField(DGField f, string Reference) { using (new FuncTrace()) { //if(f.Identification == "TestData") { // Console.WriteLine("using oasch"); // Oasch = true; //} else { // Oasch = false; //} int newJ = this.m_newJ; GridData NewGrid = (GridData)m_NewGrid; int pDeg = f.Basis.Degree; // Refined_TestData.Basis.Degree; if (!object.ReferenceEquals(NewGrid, f.Basis.GridDat)) { throw new ArgumentException("DG field must be assigned to new grid."); } f.Clear(); int[][] TargMappingIdx = m_Old2NewCorr.GetTargetMappingIndex(NewGrid.CellPartitioning); double[][][] ReDistDGCoords = m_newDGFieldData_GridAdapta[Reference]; Debug.Assert(ReDistDGCoords.Length == newJ); if (f is ConventionalDGField) { // +++++++++++++++ // normal DG field // +++++++++++++++ int Np = f.Basis.Length; double[] temp = new double[Np]; double[] acc = new double[Np]; for (int j = 0; j < newJ; j++) { if (TargMappingIdx[j] == null) { // unchanged cell Debug.Assert(ReDistDGCoords[j].Length == 1); double[] Coord = ReDistDGCoords[j][0]; Debug.Assert(Coord.Length == Np); BckTrafo(Coord, Np, 0, NewGrid, j, pDeg, 1.0); f.Coordinates.SetRow(j, Coord); } else { int L = ReDistDGCoords[j].Length; for (int l = 0; l < L; l++) { DoCellj(j, f, NewGrid, pDeg, TargMappingIdx[j], ReDistDGCoords[j], l, m_Old2NewCorr, 0, 0, Np, temp, acc); } } } } else if (f is XDGField) { // +++++++++++++++++++++++ // treatment of XDG fields // +++++++++++++++++++++++ // (as always, more difficult) XDGField xf = f as XDGField; LevelSetTracker lsTrk = xf.Basis.Tracker; int Np = xf.Basis.NonX_Basis.Length; double[] temp = new double[Np]; double[] acc = new double[Np]; if (!object.ReferenceEquals(m_NewTracker, lsTrk)) { throw new ArgumentException("LevelSetTracker seems duplicate, or something."); } for (int j = 0; j < newJ; j++) { int NoOfSpc = lsTrk.Regions.GetNoOfSpecies(j); f.Coordinates.ClearRow(j); if (TargMappingIdx[j] == null) { // + + + + + + + + + // unchanged cell // + + + + + + + + + Debug.Assert(ReDistDGCoords[j].Length == 1); double[] ReDistDGCoords_jl = ReDistDGCoords[j][0]; //Debug.Assert(ReDistDGCoords_jl.Length == NoOfSpc*Np + NoOfSpc + 1); //Debug.Assert(ReDistDGCoords_jl[0] == NoOfSpc); int NoOfSpcR = (int)(ReDistDGCoords_jl[0]); // Number of species received! int c = 1; for (int iSpcR = 0; iSpcR < NoOfSpcR; iSpcR++) // loop over received species... //#if DEBUG // SpeciesId rcvSpc; // rcvSpc.cntnt = (int) ReDistDGCoords_jl[c]; // Debug.Assert(rcvSpc == lsTrk.Regions.GetSpeciesIdFromIndex(j, iSpc)); //#endif { SpeciesId rcvSpc; rcvSpc.cntnt = (int)ReDistDGCoords_jl[c]; c++; int iSpcTarg = lsTrk.Regions.GetSpeciesIndex(rcvSpc, j); if (iSpcTarg >= 0) { for (int n = 0; n < Np; n++) { f.Coordinates[j, n + Np * iSpcTarg] = ReDistDGCoords_jl[c]; c++; } } else { //double testNorm = 0; for (int n = 0; n < Np; n++) { //testNorm += ReDistDGCoords_jl[c].Pow2(); c++; } } } Debug.Assert(c == ReDistDGCoords_jl.Length); } else { // + + + + + + + + + + + + + // coarsening or refinement // + + + + + + + + + + + + + int L = ReDistDGCoords[j].Length; for (int l = 0; l < L; l++) { double[] ReDistDGCoords_jl = ReDistDGCoords[j][l]; int NoSpcOrg = (int)ReDistDGCoords_jl[0]; // no of species in original cells int c = 1; for (int iSpcRecv = 0; iSpcRecv < NoSpcOrg; iSpcRecv++) // loop over species in original cell { SpeciesId rcvSpc; rcvSpc.cntnt = (int)ReDistDGCoords_jl[c]; c++; int iSpc = lsTrk.Regions.GetSpeciesIndex(rcvSpc, j); // species index in new cell //Debug.Assert(iSpcRecv == iSpc || L > 1); int N0rcv = c; c += Np; if (iSpc >= 0) { DoCellj(j, xf, NewGrid, pDeg, TargMappingIdx[j], ReDistDGCoords[j], l, m_Old2NewCorr, N0rcv, Np * iSpc, Np, temp, acc); } } Debug.Assert(c == ReDistDGCoords_jl.Length); } } } } else { throw new NotImplementedException(); } } }
public void LimitFieldValues(IEnumerable <DGField> ConservativeVariables, IEnumerable <DGField> DerivedFields) { var GridData = ConservativeVariables.First().GridDat; // Make sure primitive fields are up-to-date for (int d = 0; d < CompressibleEnvironment.NumberOfDimensions; d++) { CNSVariables.Velocity[d].UpdateFunction( DerivedFields.Single(f => f.Identification == CNSVariables.Velocity[d].Name), CellMask.GetFullMask(GridData), program); } CNSVariables.Pressure.UpdateFunction( DerivedFields.Single(f => f.Identification == CNSVariables.Pressure.Name), CellMask.GetFullMask(GridData), program); // Limit and store primitive fields string[] primitiveFieldNames = { CompressibleVariables.Density, CNSVariables.Velocity.xComponent, CNSVariables.Velocity.yComponent, CNSVariables.Pressure }; DGField[] primitiveFields = new DGField[primitiveFieldNames.Length]; CellMask shockedCells = Sensor.GetShockedCellMask(GridData, sensorLimit, cellSize, dgDegree); int k = 0; foreach (string name in primitiveFieldNames) { DGField field = ConservativeVariables. Concat(DerivedFields). Where(f => f.Identification.Equals(name)). Single(); foreach (Chunk chunk in shockedCells) { foreach (int cell in chunk.Elements) { for (int j = 1; j < field.Coordinates.NoOfCols; j++) { field.Coordinates[cell, j] = 0.0; } } } primitiveFields[k] = field; k++; } // Update conservative variables by using limited primitive variables only in shocked cells int D = CompressibleEnvironment.NumberOfDimensions; for (int d = 0; d < D; d++) { DGField mom_d = ConservativeVariables.Single(f => f.Identification == CompressibleVariables.Momentum[d].Name); mom_d.Clear(shockedCells); mom_d.ProjectFunction( 1.0, (X, U, j) => U[0] * U[1 + d], new CellQuadratureScheme(true, shockedCells), primitiveFields); } // Update total energy DGField Energy = ConservativeVariables.Single(f => f.Identification == CompressibleVariables.Energy.Name); Energy.Clear(shockedCells); Energy.ProjectFunction( 1.0, delegate(double[] X, double[] U, int jCell) { double K = 0.0; for (int d = 0; d < D; d++) { K += U[d + 1] * U[d + 1]; } return(U[D + 1] / (program.Control.EquationOfState.HeatCapacityRatio - 1.0) + 0.5 * U[0] * K); }, new CellQuadratureScheme(true, shockedCells), primitiveFields); }