Exemplo n.º 1
0
        public ParticleLevelSet(VectorField <SinglePhaseField> Velocity_New, VectorField <SinglePhaseField> Velocity_Old,
                                SinglePhaseField Interface, LevelSetTracker InterfaceTrck, VectorField <SinglePhaseField> LevelSetGradient,
                                int TargetNbrParticlesPerCell, int UpperLimitParticlesPerCell, int LowerLimitParticlesPerCell, double Band_max, double Band_min,
                                double Radius_max, double Radius_min, int max_AddandAttract_Iteration, int NarrowBandWidth, IGridData Grid,
                                bool LevelSetCorrectionWithNeighbourCells, int ReseedingInterval, MinimalDistanceSearchMode LevelSetCorrection,
                                TopologyMergingMode TopologyMerging, NormalVectorDampingMode NormalVectorDamping)

            : base(Velocity_New, Velocity_Old, Interface, InterfaceTrck, LevelSetGradient, NarrowBandWidth, Grid, ReseedingInterval, LevelSetCorrection,
                   TopologyMerging, NormalVectorDamping, TargetNbrParticlesPerCell, UpperLimitParticlesPerCell, LowerLimitParticlesPerCell)
        {
            if (TargetNbrParticlesPerCell <= 0)
            {
                throw new Exception("Target number of particles per cell must not be lower than 1.");
            }
            if (TargetNbrParticlesPerCell > UpperLimitParticlesPerCell)
            {
                throw new Exception("The upper limit of particles per cell must be equal or higher than the target number of particles per cell.");
            }
            if (TargetNbrParticlesPerCell < LowerLimitParticlesPerCell)
            {
                throw new Exception("The lower limit of particles per cell must be equal or lower than the target number of particles per cell.");
            }
            this.Band_max   = Band_max;
            this.Band_min   = Band_min;
            this.Radius_max = Radius_max;
            this.Radius_min = Radius_min;
            this.max_AddandAttract_Iteration = max_AddandAttract_Iteration;
            CorrectionCells  = InterfaceTracker.Regions.GetNearFieldMask(1);
            ReseedingWdith   = NarrowBandWidth;
            Reinitialization = new FastMarchReinit(Interface.Basis);
        }
Exemplo n.º 2
0
        /// <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);
            }
        }
Exemplo n.º 3
0
        /// <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);
            }
        }