Esempio n. 1
0
        public bool TryNewClustering(double dt)
        {
            bool reclustered = false;

            if (ABevolver[0].HistoryChangeRate.Count >= order - 1)
            {
                if (adaptive)
                {
                    if (TimeInfo.TimeStepNumber % reclusteringInterval == 0)
                    {
                        // Fix for update problem of artificial viscosity
                        RaiseOnBeforeComputechangeRate(Time, dt);
                        //#if DEBUG
                        Console.WriteLine("\n-------------------------------------------------------------------------------------------");
                        Console.WriteLine("### BUILD NEW CLUSTERING FOR TESTING ###");
                        //#endif
                        // Necessary in order to use the number of sub-grids specified by the user for the reclustering in each time step
                        // Otherwise the value could be changed by the constructor of the parent class (AdamsBashforthLTS.cs) --> CreateSubGrids()
                        Clusterer.Clustering newClustering = clusterer.CreateClustering(numberOfClustersInitial, this.TimeStepConstraints, this.SubGrid);
                        newClustering = clusterer.TuneClustering(newClustering, Time, this.TimeStepConstraints); // Might remove sub-grids when their time step sizes are too similar
                        reclustered   = clusterer.CheckForNewClustering(CurrentClustering, newClustering);

                        //#if DEBUG
                        //Console.WriteLine("########################################");
                        Console.WriteLine("-------------------------------------------------------------------------------------------");
                        //#endif

                        // After the intitial phase, activate adaptive mode for all ABevolve objects
                        foreach (ABevolve abE in ABevolver)
                        {
                            abE.adaptive = true;
                        }

                        if (reclustered)
                        {
                            Console.WriteLine("### RECLUSTERING ###");

                            CurrentClustering = newClustering;
                            ShortenHistories(ABevolver);
                            ABevolve[] oldABevolver = ABevolver;
                            CreateNewABevolver();
                            CopyHistoriesOfABevolver(oldABevolver);
                        }

                        GetBoundaryTopology();
                    }
                }
            }

            return(reclustered);
        }
Esempio n. 2
0
        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);
        }
Esempio n. 3
0
        //################# Hack for saving to database in every (A)LTS sub-step

        /// <summary>
        /// Standard constructor for the (adaptive) local time stepping algorithm
        /// </summary>
        /// <param name="spatialOp">Spatial operator</param>
        /// <param name="Fieldsmap">Coordinate mapping for the variable fields</param>
        /// <param name="Parameters">optional parameter fields, can be null if <paramref name="spatialOp"/> contains no parameters; must match the parameter field list of <paramref name="spatialOp"/>, see <see cref="BoSSS.Foundation.SpatialOperator.ParameterVar"/></param>
        /// <param name="order">LTS/AB order</param>
        /// <param name="numOfClusters">Amount of sub-grids/clusters to be used for LTS</param>
        /// <param name="timeStepConstraints">Time step constraints for later usage as metric</param>
        /// <param name="subGrid">Sub-grids, e.g., from previous time steps</param>
        /// <param name="fluxCorrection">Bool for triggering the fluss correction</param>
        /// <param name="reclusteringInterval">Interval for potential reclustering</param>
        /// <param name="saveToDBCallback">Hack for plotting all sub-steps</param>
        /// <remarks>Uses the k-Mean clustering, see <see cref="BoSSS.Solution.Utils.Kmeans"/>, to generate the element groups</remarks>
        public AdamsBashforthLTS(SpatialOperator spatialOp, CoordinateMapping Fieldsmap, CoordinateMapping Parameters, int order, int numOfClusters, IList <TimeStepConstraint> timeStepConstraints = null, SubGrid subGrid = null, bool fluxCorrection = true, int reclusteringInterval = 0, Action <TimestepNumber, double> saveToDBCallback = null, int initialTimestepNumber = 1)
            : base(spatialOp, Fieldsmap, Parameters, order, timeStepConstraints, subGrid)
        {
            if (reclusteringInterval != 0)
            {
                numberOfClustersInitial = numOfClusters;
                this.timestepNumber     = initialTimestepNumber;
                this.adaptive           = true;
            }

            // Add OnBeforeComputeChangeRate (AV) to start-up phase time stepper
            RungeKuttaScheme.OnBeforeComputeChangeRate += (t1, t2) => this.RaiseOnBeforeComputechangeRate(t1, t2);

            this.reclusteringInterval = reclusteringInterval;
            this.gridData             = Fieldsmap.Fields.First().GridDat;
            this.fluxCorrection       = fluxCorrection;

            NumberOfLocalTimeSteps = new List <int>(numOfClusters);

            clusterer         = new Clusterer(this.gridData, this.TimeStepConstraints);
            CurrentClustering = clusterer.CreateClustering(numOfClusters, this.SubGrid); // Might remove clusters when their centres are too close
            CurrentClustering = CalculateNumberOfLocalTS(CurrentClustering);             // Might remove clusters when time step sizes are too similar

            ABevolver = new ABevolve[CurrentClustering.NumberOfClusters];

            for (int i = 0; i < ABevolver.Length; i++)
            {
                ABevolver[i] = new ABevolve(spatialOp, Fieldsmap, Parameters, order, adaptive: this.adaptive, sgrd: CurrentClustering.Clusters[i]);
                ABevolver[i].OnBeforeComputeChangeRate += (t1, t2) => this.RaiseOnBeforeComputechangeRate(t1, t2);
            }

            GetBoundaryTopology();

#if DEBUG
            for (int i = 0; i < CurrentClustering.NumberOfClusters; i++)
            {
                Console.WriteLine("AB LTS Ctor: id=" + i + " -> sub-steps=" + NumberOfLocalTimeSteps[i] + " and elements=" + CurrentClustering.Clusters[i].GlobalNoOfCells);
            }
#endif

            // Saving time steps in subgrids
            //this.saveToDBCallback = saveToDBCallback;
        }
Esempio n. 4
0
        ////################# Hack for saving to database in every (A)LTS sub-step
        //private Action<TimestepNumber, double> saveToDBCallback;
        ////################# Hack for saving to database in every (A)LTS sub-step

        /// <summary>
        /// Standard constructor for the (adaptive) local time stepping algorithm
        /// </summary>
        /// <param name="spatialOp">Spatial operator</param>
        /// <param name="Fieldsmap">Coordinate mapping for the variable fields</param>
        /// <param name="Parameters">optional parameter fields, can be null if <paramref name="spatialOp"/> contains no parameters; must match the parameter field list of <paramref name="spatialOp"/>, see <see cref="BoSSS.Foundation.SpatialOperator.ParameterVar"/></param>
        /// <param name="order">LTS/AB order</param>
        /// <param name="numOfClusters">Amount of sub-grids/clusters to be used for LTS</param>
        /// <param name="timeStepConstraints">Time step constraints for later usage as metric</param>
        /// <param name="subGrid">Sub-grids, e.g., from previous time steps</param>
        /// <param name="fluxCorrection">Bool for triggering the fluss correction</param>
        /// <param name="reclusteringInterval">Interval for potential reclustering</param>
        /// <param name="saveToDBCallback">Hack for plotting all sub-steps</param>
        /// <remarks>Uses the k-Mean clustering, see <see cref="BoSSS.Solution.Utils.Kmeans"/>, to generate the element groups</remarks>
        public AdamsBashforthLTS(SpatialOperator spatialOp, CoordinateMapping Fieldsmap, CoordinateMapping Parameters, int order, int numOfClusters, IList <TimeStepConstraint> timeStepConstraints = null, SubGrid subGrid = null, bool fluxCorrection = true, int reclusteringInterval = 0, Action <TimestepNumber, double> saveToDBCallback = null, int maxNumOfSubSteps = 0, bool forceReclustering = false, bool logging = false, bool consoleOutput = false)
            : base(spatialOp, Fieldsmap, Parameters, order, timeStepConstraints, subGrid)
        {
            this.forceReclustering = forceReclustering;
            this.Logging           = logging;
            this.ConsoleOutput     = consoleOutput;

            if (reclusteringInterval != 0)
            {
                NumberOfClustersInitial = numOfClusters;
                this.adaptive           = true;
            }

            // Add OnBeforeComputeChangeRate (AV) to start-up phase time stepper
            RungeKuttaScheme.OnBeforeComputeChangeRate += (t1, t2) => this.RaiseOnBeforeComputechangeRate(t1, t2);

            this.reclusteringInterval = reclusteringInterval;
            this.gridData             = Fieldsmap.Fields.First().GridDat;
            this.fluxCorrection       = fluxCorrection;

            if (ConsoleOutput)
            {
                Console.WriteLine("### This is ABLTS ctor ###");
            }

            clusterer         = new Clusterer(this.gridData, maxNumOfSubSteps);
            CurrentClustering = clusterer.CreateClustering(numOfClusters, this.TimeStepConstraints, this.SubGrid); // Might remove clusters when their centres are too close
            CurrentClustering = clusterer.TuneClustering(CurrentClustering, Time, this.TimeStepConstraints);       // Might remove clusters when their time step sizes are too similar

            ABevolver = new ABevolve[CurrentClustering.NumberOfClusters];

            for (int i = 0; i < ABevolver.Length; i++)
            {
                ABevolver[i] = new ABevolve(spatialOp, Fieldsmap, Parameters, order, adaptive: this.adaptive, sgrd: CurrentClustering.Clusters[i]);
                ABevolver[i].OnBeforeComputeChangeRate += (t1, t2) => this.RaiseOnBeforeComputechangeRate(t1, t2);
            }

            GetBoundaryTopology();

            // Saving time steps in subgrids
            //this.saveToDBCallback = saveToDBCallback;
        }
Esempio n. 5
0
        /// <summary>
        /// Performs a time step
        /// </summary>
        /// <param name="dt">Time step size that equals -1, if no fixed time step is prescribed</param>
        public override double Perform(double dt)
        {
            using (new ilPSP.Tracing.FuncTrace()) {
                if (ABevolver[0].HistoryChangeRate.Count >= order - 1)
                {
                    bool reclustered = false;
                    if (adaptive)
                    {
                        if (timestepNumber % reclusteringInterval == 0)
                        {
                            // Fix for update problem of artificial viscosity
                            RaiseOnBeforeComputechangeRate(Time, dt);

                            Clusterer.Clustering oldClustering = CurrentClustering;

                            // Necessary in order to use the number of sub-grids specified by the user for the reclustering in each time step
                            // Otherwise the value could be changed by the constructor of the parent class (AdamsBashforthLTS.cs) --> CreateSubGrids()
                            CurrentClustering = clusterer.CreateClustering(numberOfClustersInitial, this.SubGrid);

                            CurrentClustering = CalculateNumberOfLocalTS(CurrentClustering); // Might remove sub-grids when time step sizes are too similar
                            reclustered       = clusterer.CheckForNewClustering(oldClustering, CurrentClustering);

                            // After the intitial phase, activate adaptive mode for all ABevolve objects
                            foreach (ABevolve abE in ABevolver)
                            {
                                abE.adaptive = true;
                            }

                            if (reclustered)
                            {
                                ShortenHistories(ABevolver);
                                ABevolve[] oldABevolver = ABevolver;
                                CreateNewABevolver();
                                CopyHistoriesOfABevolver(oldABevolver);
                            }

                            GetBoundaryTopology();
#if DEBUG
                            if (reclustered)
                            {
                                Console.WriteLine("RECLUSTERING");
                            }
#endif
                        }
                    }

                    // Number of substeps could have changed
                    if (TimeStepConstraints != null)
                    {
                        dt = CalculateTimeStep();
                    }

                    double[,] CorrectionMatrix = new double[CurrentClustering.NumberOfClusters, CurrentClustering.NumberOfClusters];

                    // Saves the results at t_n
                    double[] y0 = new double[Mapping.LocalLength];
                    DGCoordinates.CopyTo(y0, 0);

                    double time0 = m_Time;
                    double time1 = m_Time + dt;

                    TimestepNumber subTimestep = new TimestepNumber(timestepNumber - 1);

                    // Evolves each sub-grid with its own time step (only one step)
                    // (The result is not written to m_DGCoordinates!)
                    for (int i = 0; i < ABevolver.Length; i++)
                    {
                        //localABevolve[i].completeBndFluxes.Clear();
                        //if (localABevolve[i].completeBndFluxes.Any(x => x != 0.0)) Console.WriteLine("Not all Bnd fluxes were used in correction step!!!");
                        ABevolver[i].Perform(dt / (double)NumberOfLocalTimeSteps[i]);
                    }

                    // After evolving each cell update the time with dt_min
                    m_Time = m_Time + dt / (double)NumberOfLocalTimeSteps[CurrentClustering.NumberOfClusters - 1];

                    if (saveToDBCallback != null)
                    {
                        subTimestep = subTimestep.NextIteration();
                        saveToDBCallback(subTimestep, m_Time);
                    }

                    // Saves the history of DG_Coordinates for each cluster
                    Queue <double[]>[] historyDGC_Q = new Queue <double[]> [CurrentClustering.NumberOfClusters];
                    for (int i = 0; i < historyDGC_Q.Length; i++)
                    {
                        historyDGC_Q[i] = ABevolver[i].HistoryDGCoordinate;
                    }

                    if (!adaptive)
                    {
                        // Saves DtHistory for each cluster
                        historyTime_Q = new Queue <double> [CurrentClustering.NumberOfClusters];
                        for (int i = 0; i < historyTime_Q.Length; i++)
                        {
                            historyTime_Q[i] = ABevolver[i].HistoryTime;
                        }
                    }

                    // Perform the local time steps
                    for (int localTS = 1; localTS < NumberOfLocalTimeSteps.Last(); localTS++)
                    {
                        for (int id = 1; id < CurrentClustering.NumberOfClusters; id++)
                        {
                            //Evolve Condition: Is "ABevolve.Time" at "AB_LTS.Time"?
                            if ((ABevolver[id].Time - m_Time) < 1e-10)
                            {
                                double localDt = dt / NumberOfLocalTimeSteps[id];

                                foreach (Chunk chunk in CurrentClustering.Clusters[id].VolumeMask)
                                {
                                    foreach (int cell in chunk.Elements)
                                    {
                                        // f == each field
                                        // n == basis polynomial
                                        foreach (DGField f in Mapping.Fields)
                                        {
                                            for (int n = 0; n < f.Basis.GetLength(cell); n++)
                                            {
                                                int coordinateIndex = Mapping.LocalUniqueCoordinateIndex(f, cell, n);
                                                DGCoordinates[coordinateIndex] = historyDGC_Q[id].Last()[coordinateIndex];
                                            }
                                        }
                                    }
                                }

                                Dictionary <int, double> myDic = InterpolateBoundaryValues(historyDGC_Q, id, ABevolver[id].Time);

                                foreach (KeyValuePair <int, double> kvp in myDic)
                                {
                                    DGCoordinates[kvp.Key] = kvp.Value;
                                }

                                ABevolver[id].Perform(localDt);

                                m_Time = ABevolver.Min(s => s.Time);

                                if (saveToDBCallback != null)
                                {
                                    subTimestep = subTimestep.NextIteration();
                                    saveToDBCallback(subTimestep, m_Time);
                                }
                            }

                            // Are we at an (intermediate-) syncronization levels?
                            // For conservatvity, we have to correct the values of the larger cell cluster
                            if (fluxCorrection)
                            {
                                for (int idCoarse = 0; idCoarse < id; idCoarse++)
                                {
                                    if (Math.Abs(ABevolver[id].Time - ABevolver[idCoarse].Time) < 1e-10 &&
                                        !(Math.Abs(ABevolver[idCoarse].Time - CorrectionMatrix[idCoarse, id]) < 1e-10))
                                    {
                                        if (fluxCorrection)
                                        {
                                            CorrectFluxes(idCoarse, id, historyDGC_Q);
                                        }
                                        CorrectionMatrix[idCoarse, id] = ABevolver[idCoarse].Time;
                                    }
                                }
                            }
                        }
                    }

                    // Finalize step
                    // Use unmodified values in history of DGCoordinates (DGCoordinates could have been modified by
                    // InterpolateBoundaryValues, should be resetted afterwards)
                    DGCoordinates.Clear();
                    for (int id = 0; id < historyDGC_Q.Length; id++)
                    {
                        DGCoordinates.axpy <double[]>(historyDGC_Q[id].Last(), 1);
                    }

                    // Update time
                    m_Time = time0 + dt;
                }
                else
                {
                    double[] currentChangeRate = new double[Mapping.LocalLength];
                    double[] upDGC             = new double[Mapping.LocalLength];

                    // Save time history
                    if (adaptive)
                    {
                        for (int i = 0; i < ABevolver.Length; i++)
                        {
                            double[] currentTime = new double[ABevolver[i].ABSubGrid.LocalNoOfCells];
                            for (int j = 0; j < currentTime.Length; j++)
                            {
                                currentTime[j] = m_Time;
                            }
                            ABevolver[i].historyTimePerCell.Enqueue(currentTime);
                        }
                    }
                    else
                    {
                        if (ABevolver[0].HistoryTime.Count == 0)
                        {
                            for (int i = 0; i < ABevolver.Length; i++)
                            {
                                ABevolver[i].HistoryTime.Enqueue(m_Time);
                            }
                        }
                    }

                    // Needed for the history
                    for (int i = 0; i < CurrentClustering.NumberOfClusters; i++)
                    {
                        double[] localCurrentChangeRate = new double[currentChangeRate.Length];
                        double[] edgeFlux = new double[gridData.iGeomEdges.Count * Mapping.Fields.Count];
                        ABevolver[i].ComputeChangeRate(localCurrentChangeRate, m_Time, 0, edgeFlux);
                        ABevolver[i].HistoryChangeRate.Enqueue(localCurrentChangeRate);
                        ABevolver[i].HistoryBoundaryFluxes.Enqueue(edgeFlux);
                    }

                    dt = RungeKuttaScheme.Perform(dt);

                    DGCoordinates.CopyTo(upDGC, 0);

                    // Saves ChangeRateHistory for AB LTS
                    // Only entries for the specific cluster
                    for (int i = 0; i < CurrentClustering.NumberOfClusters; i++)
                    {
                        ABevolver[i].HistoryDGCoordinate.Enqueue(OrderValuesByCluster(CurrentClustering.Clusters[i], upDGC));
                        if (!adaptive)
                        {
                            ABevolver[i].HistoryTime.Enqueue(RungeKuttaScheme.Time);
                        }
                    }

                    // RK is a global timeStep
                    // -> time update for all other timeStepper with rk.Time
                    m_Time = RungeKuttaScheme.Time;
                    foreach (ABevolve ab in ABevolver)
                    {
                        ab.ResetTime(m_Time, timestepNumber);
                    }
                }
            }

            if (adaptive)
            {
                timestepNumber++;
            }

            return(dt);
        }