protected override void CreateFields() { using (new FuncTrace()) { base.CreateFields(); int D = this.GridData.SpatialDimension; this.DGLevSet = new ScalarFieldHistory <SinglePhaseField>( new SinglePhaseField(new Basis(this.GridData, this.Control.FieldOptions["Phi"].Degree), "PhiDG")); if (this.Control.FieldOptions["PhiDG"].Degree >= 0 && this.Control.FieldOptions["PhiDG"].Degree != this.DGLevSet.Current.Basis.Degree) { throw new ApplicationException("Specification of polynomial degree for 'PhiDG' is not supportet, since it is induced by polynomial degree of 'Phi'."); } // ============================== // Initialize ContinuityProjection // if needed, if not , Option: None // ============================== this.LevSet = ContinuityProjection.CreateField( DGLevelSet: this.DGLevSet.Current, gridData: (GridData)GridData, Option: Control.LSContiProjectionMethod ); this.LsTrk = new LevelSetTracker((GridData)this.GridData, base.Control.CutCellQuadratureType, base.Control.LS_TrackerWidth, new string[] { "A", "B" }, this.LevSet); base.RegisterField(this.LevSet); this.LevSetGradient = new VectorField <SinglePhaseField>(D.ForLoop(d => new SinglePhaseField(this.LevSet.Basis, "dPhi_dx[" + d + "]"))); base.RegisterField(this.LevSetGradient); base.RegisterField(this.DGLevSet.Current); this.DGLevSetGradient = new VectorField <SinglePhaseField>(D.ForLoop(d => new SinglePhaseField(this.DGLevSet.Current.Basis, "dPhiDG_dx[" + d + "]"))); base.RegisterField(this.DGLevSetGradient); if (this.Control.CheckJumpConditions) { Basis basis = new Basis(this.GridData, 0); //Basis basis = new Basis(this.GridData, this.Control.FieldOptions[VariableNames.VelocityX].Degree); this.MassBalanceAtInterface = new SinglePhaseField(basis, "MassBalanceAtInterface"); base.RegisterField(this.MassBalanceAtInterface); //basis = new Basis(this.GridData, this.Control.FieldOptions[VariableNames.Pressure].Degree + this.Control.FieldOptions["Phi"].Degree); this.MomentumBalanceAtInterface = new VectorField <SinglePhaseField>(D.ForLoop(d => new SinglePhaseField(basis, d + "-MomentumBalanceAtInterface"))); base.RegisterField(this.MomentumBalanceAtInterface); //basis = new Basis(this.GridData, this.Control.FieldOptions[VariableNames.Pressure].Degree + this.Control.FieldOptions[VariableNames.VelocityX].Degree + this.Control.FieldOptions["Phi"].Degree); this.EnergyBalanceAtInterface = new SinglePhaseField(basis, "EnergyBalanceAtInterface"); base.RegisterField(this.EnergyBalanceAtInterface); } } }
/// <summary> /// Creates a continuous version of a DG level set field /// </summary> /// <param name="DGLevelSet">The input DG level set field</param> /// <param name="jCells">Local cell indices</param> /// <returns>A continuous level set <see cref="SinglePhaseField"/> with one order higher than the input</returns> public static SinglePhaseField ContinuousLevelSet(SinglePhaseField DGLevelSet, double[] jCells) { Console.WriteLine(String.Format("Continuity projection of field {0} started...", DGLevelSet.Identification)); // Init IGridData gridData = DGLevelSet.GridDat; SinglePhaseField continuousLevelSet = new SinglePhaseField(new Basis(gridData, DGLevelSet.Basis.Degree + 1), DGLevelSet.Identification + "_cont"); // Create narrow band List <int> allNeighbours = new List <int>(); foreach (int cell in jCells) { gridData.GetCellNeighbours(cell, GetCellNeighbours_Mode.ViaVertices, out int[] cellNeighbours, out int[] connectingEntities); allNeighbours.Add(cell); allNeighbours.AddRange(cellNeighbours); } List <int> narrowBandCells = allNeighbours.Distinct().ToList(); BitArray bitMaskNarrowBand = new BitArray(gridData.iLogicalCells.NoOfLocalUpdatedCells); foreach (int cell in narrowBandCells) { bitMaskNarrowBand[cell] = true; } CellMask narrowBand = new CellMask(gridData, bitMaskNarrowBand); // Create positive mask BitArray bitMaskPos = new BitArray(gridData.iLogicalCells.NoOfLocalUpdatedCells); for (int i = 0; i < gridData.iLogicalCells.NoOfLocalUpdatedCells; i++) { if (DGLevelSet.GetMeanValue(i) > 0 && !bitMaskNarrowBand[i]) { bitMaskPos[i] = true; } } CellMask posMask = new CellMask(gridData, bitMaskPos); // Continuity projection ContinuityProjection continuityProjection = new ContinuityProjection(continuousLevelSet.Basis, DGLevelSet.Basis, gridData, ContinuityProjectionOption.ConstrainedDG); continuityProjection.MakeContinuous(DGLevelSet, continuousLevelSet, narrowBand, posMask); Console.WriteLine("finished"); return(continuousLevelSet); }
/// <summary> /// setUp for the Level set initialization (Level-set algorithm, continuity, conservation) /// </summary> protected void InitLevelSet() { using (new FuncTrace()) { // check level-set if (this.LevSet.L2Norm() == 0) { throw new NotSupportedException("Level set is not initialized - norm is 0.0 - ALL cells will be cut, no gradient can be defined!"); } // tracker needs to be updated to get access to the cut-cell mask this.LsTrk.UpdateTracker(0.0); // ============================== // level-set initialization // ============================== //PlotCurrentState(0.0, new TimestepNumber(new int[] { 0, 0 }), 3); #region Initialize Level Set Evolution Algorithm switch (this.Control.Option_LevelSetEvolution) { case LevelSetEvolution.Fourier: InitFourier(); break; case LevelSetEvolution.None: if (this.Control.AdvancedDiscretizationOptions.SST_isotropicMode == SurfaceStressTensor_IsotropicMode.Curvature_Fourier) { Fourier_LevSet = FourierLevelSetFactory.Build(this.Control.FourierLevSetControl); Fourier_LevSet.ProjectToDGLevelSet(this.DGLevSet.Current, this.LsTrk); } else { goto default; } break; case LevelSetEvolution.ExtensionVelocity: { // Create ExtensionVelocity Motion Algorithm this.DGLevSet.Current.Clear(); this.DGLevSet.Current.AccLaidBack(1.0, this.LevSet); DGLevSetGradient.Gradient(1.0, DGLevSet.Current); //VectorField<SinglePhaseField> VectorExtVel = ExtensionVelocity.Current; base.RegisterField(ExtensionVelocity.Current); //ReInitPDE = new EllipticReInit(this.LsTrk, this.Control.ReInitControl, DGLevSet.Current); FastMarchReinitSolver = new FastMarchReinit(DGLevSet.Current.Basis); // full initial reinitialization //ReInitPDE.ReInitialize(Restriction: LsTrk.Regions.GetNearFieldSubgrid(1)); CellMask Accepted = LsTrk.Regions.GetNearFieldMask(1); CellMask ActiveField = Accepted.Complement(); CellMask NegativeField = LsTrk.Regions.GetSpeciesMask("A"); FastMarchReinitSolver.FirstOrderReinit(DGLevSet.Current, Accepted, NegativeField, ActiveField); //ReInitPDE.ReInitialize(); // setup extension velocity mover switch (this.Control.TimeSteppingScheme) { case TimeSteppingScheme.RK_CrankNic: case TimeSteppingScheme.CrankNicolson: { //do not instantiate rksch, use bdf instead bdfOrder = -1; break; } case TimeSteppingScheme.RK_ImplicitEuler: case TimeSteppingScheme.ImplicitEuler: { //do not instantiate rksch, use bdf instead bdfOrder = 1; break; } default: { if (this.Control.TimeSteppingScheme.ToString().StartsWith("BDF")) { //do not instantiate rksch, use bdf instead bdfOrder = Convert.ToInt32(this.Control.TimeSteppingScheme.ToString().Substring(3)); break; } else { throw new NotImplementedException(); } } } ExtVelMover = new ExtensionVelocityBDFMover(LsTrk, DGLevSet.Current, DGLevSetGradient, new VectorField <DGField>(XDGvelocity.Velocity.ToArray()), Control.EllipticExtVelAlgoControl, BcMap, bdfOrder, ExtensionVelocity.Current, new double[2] { Control.PhysicalParameters.rho_A, Control.PhysicalParameters.rho_B }); break; } case LevelSetEvolution.FastMarching: case LevelSetEvolution.Prescribed: case LevelSetEvolution.ScalarConvection: default: // evolution algorithms need a signed-distance level-set: // do some reinit at startup //BoSSS.Solution.LevelSetTools.Advection.NarrowMarchingBand.CutCellReinit(this.LsTrk, this.DGLevSet.Current); // apply only the minimal necessary change this.DGLevSet.Current.Clear(); this.DGLevSet.Current.AccLaidBack(1.0, this.LevSet); //FastMarchReinitSolver = new FastMarchReinit(DGLevSet.Current.Basis); break; } //PlotCurrentState(0.0, new TimestepNumber(new int[] { 0, 1 }), 3); #endregion // ========================================= // Enforcing the continuity of the level-set // ========================================= ContinuityEnforcer = new ContinuityProjection( ContBasis: this.LevSet.Basis, DGBasis: this.DGLevSet.Current.Basis, gridData: GridData, Option: Control.LSContiProjectionMethod ); //var CC = this.LsTrk.Regions.GetCutCellMask4LevSet(0); var Near1 = this.LsTrk.Regions.GetNearMask4LevSet(0, 1); var Near = this.LsTrk.Regions.GetNearMask4LevSet(0, this.Control.LS_TrackerWidth); var PosFF = this.LsTrk.Regions.GetLevelSetWing(0, +1).VolumeMask; if (this.Control.Option_LevelSetEvolution != LevelSetEvolution.ExtensionVelocity) { ContinuityEnforcer.SetFarField(this.DGLevSet.Current, Near1, PosFF); } ContinuityEnforcer.MakeContinuous(this.DGLevSet.Current, this.LevSet, Near, PosFF); //PlotCurrentState(0.0, new TimestepNumber(new int[] { 0, 2 }), 3); this.LsTrk.UpdateTracker(0.0); } }