/// <summary> /// performs one timestep /// </summary> /// <param name="dt">size of timestep</param> public override double Perform(double dt) { using (var tr = new ilPSP.Tracing.FuncTrace()) { if (TimeStepConstraints != null) { dt = CalculateTimeStep(); } double[][] k = new double[m_Scheme.Stages][]; for (int i = 0; i < m_Scheme.Stages; i++) { k[i] = new double[Mapping.LocalLength]; } double[] y0 = new double[Mapping.LocalLength]; DGCoordinates.CopyTo(y0, 0); // logging tr.Info("Runge-Kutta Scheme with " + m_Scheme.Stages + " stages."); double time0 = m_Time; tr.Info("time = " + time0 + ", dt = " + dt); // berechne k[0] ComputeChangeRate(k[0], m_Time, 0);// invokes MPI communication for (int s = 1; s < m_Scheme.Stages; s++) { PerformStage(y0, s, k, dt); m_Time = time0 + m_Scheme.c[s] * dt; ComputeChangeRate(k[s], m_Time, m_Scheme.c[s] * dt);// invokes MPI communication } // next timestep DGCoordinates.Clear(); DGCoordinates.CopyFrom(y0, 0); Array.Clear(y0, 0, y0.Length); for (int s = 0; s < m_Scheme.Stages; s++) { if (m_Scheme.b[s] != 0.0) { BLAS.daxpy(y0.Length, -m_Scheme.b[s] * dt, k[s], 1, y0, 1); } } DGCoordinates.axpy <double[]>(y0, 1.0); base.ApplyFilter(dt); m_Time = time0 + dt; } return(dt); }
protected override double[] ComputesUpdatedDGCoordinates(double[] completeChangeRate) { double[] y0 = new double[Mapping.LocalLength]; DGCoordinates.CopyTo(y0, 0); DGCoordinates.axpy <double[]>(completeChangeRate, -1); // Speciality for IBM: Do the extrapolation speciesMap.Agglomerator.Extrapolate(DGCoordinates.Mapping); double[] upDGC = DGCoordinates.ToArray(); upDGC = OrderValuesBySgrd(upDGC); // DGCoordinates should be untouched after calling this method DGCoordinates.Clear(); DGCoordinates.CopyFrom(y0, 0); return(upDGC); }
/// <summary> /// performs one Explicit Euler timestep /// </summary> /// <param name="dt">size of timestep</param> public virtual double Perform(double dt) { using (new ilPSP.Tracing.FuncTrace()) { if (TimeStepConstraints != null) { dt = CalculateTimeStep(); } double[] k = new double[Mapping.LocalLength]; ComputeChangeRate(k, m_Time, 0); DGCoordinates.axpy <double[]>(k, -dt); ApplyFilter(dt); m_Time += dt; } return(dt); }
/// <summary> /// Performs a single stage of a timestep. /// </summary> /// <param name="y0">Initial DG coordinates</param> /// <param name="s">The current stage</param> /// <param name="k">The current change rate</param> /// <param name="dt">The size of the timestep</param> protected virtual void PerformStage(double[] y0, int s, double[][] k, double dt) { DGCoordinates.Clear(); DGCoordinates.axpy <double[]>(y0, 1.0); double relTime = 0; for (int r = 0; r < s; r++) { if (m_Scheme.a[s, r] != 0.0) { DGCoordinates.axpy <double[]>(k[r], -dt * m_Scheme.a[s, r]); relTime += dt * m_Scheme.a[s, r]; } } base.ApplyFilter(dt * relTime); }
/// <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); }
/// <summary> /// performs one time step /// </summary> /// <param name="dt">size of time step</param> public override double Perform(double dt) { using (new ilPSP.Tracing.FuncTrace()) { if (TimeStepConstraints != null) { dt = CalculateTimeStep(); } // new array object needed, because currentChangeRate from last time steps are stored in historyCR queue (in queues are only references of the array) CurrentChangeRate = new double[Mapping.LocalLength]; CompleteChangeRate = new double[Mapping.LocalLength]; // AB only possible if history with "order-1" entries exists // e.g: order=3 needs t_n (currentChangeRate), t_n-1 (history(2)), t_n-2 (history(1)) --> history has 2 entries if (HistoryChangeRate.Count >= order - 1) { ABCoefficients = ComputeCoefficients(dt, HistoryTime.ToArray()); ComputeChangeRate(CurrentChangeRate, m_Time, 0); //y <-- alpha*x + y BLAS.daxpy(CompleteChangeRate.Length, ABCoefficients[0], CurrentChangeRate, 1, CompleteChangeRate, 1); // calculate completeChangeRate int i = 1; foreach (double[] oldRate in HistoryChangeRate) { BLAS.daxpy(CompleteChangeRate.Length, ABCoefficients[i], oldRate, 1, CompleteChangeRate, 1); i++; } // perform time step DGCoordinates.axpy <double[]>(CompleteChangeRate, -1); m_Time += dt; HistoryTime.Enqueue(m_Time); HistoryTime.Dequeue(); HistoryChangeRate.Enqueue(CurrentChangeRate); HistoryChangeRate.Dequeue(); } else { if (HistoryTime.Count == 0) { HistoryTime.Enqueue(RungeKuttaScheme.Time); } // Needed for the history ComputeChangeRate(CurrentChangeRate, m_Time, 0); // RungeKutta with order+1 starts the time stepping RungeKuttaScheme.Perform(dt); // Disposal RK after "order" of time steps if (HistoryChangeRate.Count == order - 1) { RungeKuttaScheme = null; } m_Time = RungeKuttaScheme.Time; HistoryTime.Enqueue(RungeKuttaScheme.Time); HistoryChangeRate.Enqueue(CurrentChangeRate); } } return(dt); }