/// <summary> /// Solves the linear system (diag(1/<paramref name="dt"/>) + /// <em>M</em>) * x = /// <see cref="ImplicitTimeStepper.CurrentState"/> / /// <paramref name="dt"/> - /// <see cref="ImplicitTimeStepper.m_AffineOffset1"/> and writes the /// result to <see cref="ImplicitTimeStepper.CurrentState"/>. /// </summary> /// <param name="dt">The length of the timestep</param> protected override void PerformTimeStep(double dt) { using (var tr = new ilPSP.Tracing.FuncTrace()) { int n = Mapping.LocalLength; int np = m_diagVecOneSec.Length; double[] diag = new double[n]; for (int i = 0; i < n; i++) { diag[i] = m_diagVecOneSec[i % np]; } BLAS.dscal(n, 1.0 / dt, diag, 1); double[] rhs = (double[])m_AffineOffset1.Clone(); BLAS.dscal(n, -1.0, rhs, 1); for (int i = 0; i < n; i++) { rhs[i] += diag[i] * CurrentState[i]; } tr.Info("Calling solver"); LastSolverResult = m_Solver.Solve <double[], CoordinateVector, double[]>(1.0, diag, CurrentState, rhs); } }
/// <summary> /// computes the change rate for the time evolution problem; /// </summary> /// <param name="k"> /// the "change rate" is <b>accumulated</b> here;<br/> /// Indices into this array can be computed by <see cref="Mapping"/>; /// </param> /// <param name="AbsTime"> /// absolute time at which the change rate will be evaluated /// </param> /// <param name="RelTime"> /// time, relative to the point of time at which the initial value holds. /// </param> /// <remarks> /// Assume an ODE /// <br/> /// d/dt u = f(u) /// <br/> /// which is discretized by an explicit Euler scheme /// <br/> /// (u_1 - u_0)/delta_t = f(u_0). /// <br/> /// Here, f(u) denotes the discretization of the spatial operator by the DG method. /// The purpose of this method is to evaluate f(u_0).<br/> /// It does so by calling <see cref="SpatialOperator.Evaluator.Evaluate{Tout}"/> /// of <see cref="Evaluator"/>.<br/> /// Override this method e.g. for the implementation of (some types of) limiters. /// </remarks> virtual internal protected void ComputeChangeRate(double[] k, double AbsTime, double RelTime, double[] edgeFluxes = null) { using (var tr = new ilPSP.Tracing.FuncTrace()) { RaiseOnBeforeComputechangeRate(AbsTime, RelTime); // k += F(u0) Evaluator.Evaluate <double[]>(1.0, 1.0, k, AbsTime, outputBndEdge: edgeFluxes); } }
/// <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]; CurrentState.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 CurrentState.Clear(); CurrentState.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); } } CurrentState.axpy <double[]>(y0, 1.0); base.ApplyFilter(dt); m_Time = time0 + dt; } return(dt); }
/// <summary> /// solves the equation system; /// there is no solution output, /// the solution is written to the fields in <see cref="Mapping"/>; /// </summary> /// <param name="rhs">optional right-hand-side, can be null;</param> /// <returns>the basic statistics of the sparse solver</returns> /// <remarks> /// If an right-hand-side operator has been specified, i.e. /// <see cref="RhsEvaluator"/> is not null, it is evaluated prior /// to the sparse solver call; /// The result of this right-hand-side operator, added to <paramref name="rhs"/>, /// can be monitored by consuming the <see cref="RHSEvaluated"/>-event. /// </remarks> virtual public SolverResult Solve(IList <double> rhs) { // initial stuff // ============= using (var tr = new ilPSP.Tracing.FuncTrace()) { // prepare right-hand-side // ======================= // clone or allocate memory double[] _rhs; GetTotalRHS(rhs, out _rhs); //// testcode //{ // Field f = new SinglePhaseField(m_Context, new Basis(m_Context, 2)); // int J = f.Coordinates.NoOfRows; // int N = f.Coordinates.NoOfCols; // int cnt = 0; // for( int j = 0; j < J; j++) // for (int nn = 0; nn < N; nn++) { // f.Coordinates[j, nn] = _rhs[cnt]; // cnt++; // } // double InfNrm = f.LinfNorm(); // double TwoNorm = f.L2Norm(); // Console.WriteLine("rhs L2: " + TwoNorm + " inf: " + InfNrm); // //Array.Copy(_rhs, f.Coordinates.C, _rhs.Length); // BoSSS.Solution.Tecplot.Tecplot.PlotFields(new Field[] { f }, null, m_Context, "rhs", "---", 0, 0); //} // call solver // =========== tr.Info("entering linear solver:"); SolverResult ret = m_Solver.Solve <CoordinateVector, double[]>(m_DGCoordinates, (double[])_rhs.Clone()); tr.Info("no. of iterations: " + ret.NoOfIterations); tr.Info("converged? : " + ret.Converged); tr.Info("Pure solver runtime: " + ret.RunTime.TotalSeconds + " sec."); // finalize // ======== return(ret); } }
/* * /// <summary> * /// Solves the linear system (diag(1/<paramref name="dt"/>) + * /// <em>M</em>) * x = * /// <see cref=" SubgridMapping.subgridCoordinates"/> / * /// <paramref name="dt"/> - * /// <see cref="ImplicitTimeStepper.m_AffineOffset1"/> and writes the * /// result to <see cref=" SubgridMapping.subgridCoordinates"/>. * /// </summary> * /// <param name="dt">The lenght of the timestep</param> * protected override void PerformTimeStep(double dt) { * using (var tr = new ilPSP.Tracing.FuncTrace()) { * * int n = SubgridMapping.SubgridNUpdate * SubgridMapping.MaxTotalNoOfCoordinatesPerCell; * * double[] rhs = (double[])m_CompressedAffine.Clone(); * BLAS.dscal(rhs.Length, -1.0, rhs, 1); * * for (int i = 0; i < n; i++) { * rhs[i] += 1.0 / dt * SubgridDGCoordinates[i]; * } * * tr.Info("Calling solver"); * * LastSolverResult = m_Solver.Solve<double[], double[]>(SubgridDGCoordinates, rhs); * //Console.WriteLine(LastSolverResult.NoOfIterations); * SubgridMapping.subgridCoordinates = SubgridDGCoordinates; * * } * }*/ protected override void PerformTimeStep(double dt) { using (var tr = new ilPSP.Tracing.FuncTrace()) { int[] cells = m_Subgrid.SubgridIndex2LocalCellIndex; // int n = SubgridMapping.SubgridNUpdate * SubgridMapping.MaxTotalNoOfCoordinatesPerCell; int CoordinateOffset = 0; double[] rhs = (double[])m_CompressedAffine.Clone(); // BLAS.dscal(rhs.Length, -1.0, rhs, 1); /* for (int j = 0; j < cells.Length; j++) { * CoordinateOffset = 0; * for (int g = 0; g < temporalOp.Length; g++) { * * if (temporalOp[g]) {*/ for (int g = 0; g < temporalOp.Length; g++) { if (temporalOp[g]) { for (int j = 0; j < cells.Length; j++) { int loc = j * m_SubgridMapping.MaxTotalNoOfCoordinatesPerCell + CoordinateOffset; for (int i = 0; i < m_SubgridMapping.Fields[g].Basis.MaximalLength; i++) { rhs[loc] += 1.0 / dt * SubgridDGCoordinates[loc]; loc++; } } } CoordinateOffset += m_SubgridMapping.Fields[g].Basis.MaximalLength; } tr.Info("Calling solver"); LastSolverResult = m_Solver.Solve <double[], double[]>(SubgridDGCoordinates, rhs); SubgridMapping.subgridCoordinates = SubgridDGCoordinates; Console.WriteLine("Solver" + LastSolverResult.NoOfIterations); if (LastSolverResult.Converged) { Console.WriteLine("SolverConverged?:Yes"); } else { Console.WriteLine("SolverConverged?:No"); } } }
/// <summary> /// performs one timestep /// </summary> /// <param name="dt">size of timestep</param> public override void Perform(double dt) { using (var tr = new ilPSP.Tracing.FuncTrace()) { double[][] k = new double[m_RKscheme.Stages][]; for (int i = 0; i < m_RKscheme.Stages; i++) { k[i] = new double[m_SubgridMapping.subgridCoordinates.Length]; } double[] y0 = new double[m_SubgridMapping.subgridCoordinates.Length]; m_DGCoordinates.CopyTo(y0, 0); // logging tr.Info("Runge-Kutta Scheme with " + m_RKscheme.Stages + " stages."); double time0 = m_Time; tr.Info("time = " + time0 + ", dt = " + dt); // berechne k[0] Evaluate(k[0], m_Time);// invokes MPI communication for (int s = 1; s < m_RKscheme.Stages; s++) { PerformStage(y0, s, k, dt); m_Time = time0 + m_RKscheme.c[s] * dt; //ComputeChangeRate(k[s], m_Time, m_RKscheme.c[s] * dt);// invokes MPI communication Evaluate(k[s], m_Time); } // next timestep y0.CopyTo(m_DGCoordinates, 0); Array.Clear(y0, 0, y0.Length); for (int s = 0; s < m_RKscheme.Stages; s++) { BLAS.daxpy(y0.Length, -m_RKscheme.b[s] * dt, k[s], 1, y0, 1); } //m_DGCoordinates.axpy<double[]>(y0, 1.0); BLAS.daxpy(m_DGCoordinates.Length, 1.0, y0, 1, m_DGCoordinates, 1); m_Time = time0 + dt; } }
/// <summary> /// Solves the linear system (diag(1/<paramref name="dt"/>) + /// <em>M</em> / 2) * x = /// <see cref="ImplicitTimeStepper.CurrentState"/> / /// <paramref name="dt"/> - /// <em>M</em> * /// <see cref="ImplicitTimeStepper.CurrentState"/> / 2 - /// 0.5*(<see cref="ImplicitTimeStepper.m_AffineOffset1"/> + /// <see cref="m_AffineOffset0"/> ) /// and writes the /// result do <see cref="ImplicitTimeStepper.CurrentState"/>. /// </summary> /// <param name="dt">The length of the timestep</param> protected override void PerformTimeStep(double dt) { using (var tr = new ilPSP.Tracing.FuncTrace()) { if (m_Theta <= 0 || m_Theta > 1) { throw new ApplicationException("m_Theta out of range; must be betwwen 0.0 (including) and 1.0 (including), but m_Theta = " + m_Theta); } int n = Mapping.LocalLength; int np = m_diagVecOneSec.Length; double[] diag = new double[n]; for (int i = 0; i < n; i++) { diag[i] = m_diagVecOneSec[i % np]; } BLAS.dscal(n, 1.0 / (m_Theta * dt), diag, 1); double[] rhs; if (m_AffineOffset0 != null) { rhs = m_AffineOffset0; BLAS.dscal(rhs.Length, -(1.0 - m_Theta) / m_Theta, rhs, 1); BLAS.daxpy(rhs.Length, -1.0, m_AffineOffset1, 1, rhs, 1); } else { rhs = (double[])m_AffineOffset1.Clone(); } if (m_Theta != 1.0) { // if m_Theta == 0.0, this has no effect and is a waste of comp. power ISparseMatrix eM = m_Solver.GetMatrix(); eM.SpMV <CoordinateVector, double[]>(-(1.0 - m_Theta) / m_Theta, CurrentState, 1.0, rhs); } for (int i = 0; i < n; i++) { rhs[i] += diag[i] * CurrentState[i]; // fraglich } tr.Info("Calling solver"); LastSolverResult = m_Solver.Solve <double[], CoordinateVector, double[]>(1.0, diag, CurrentState, rhs); tr.Info("no. of iterations: " + LastSolverResult.NoOfIterations); tr.Info("converged? : " + LastSolverResult.Converged); tr.Info("Pure solver runtime: " + LastSolverResult.RunTime.TotalSeconds + " sec."); /* * int n = Mapping.LocalLength; * int np = m_diagVecOneSec.Length; * * double[] diag = new double[n]; * for (int i = 0; i < n; i++) { * diag[i] = m_diagVecOneSec[i % np]; * } * BLAS.dscal(n, 1.0 / dt, diag, 1); * * double[] rhs = (double[])m_AffineOffset1.Clone(); * BLAS.dscal(n, -1.0, rhs, 1); * * for (int i = 0; i < n; i++) { * rhs[i] += diag[i] * DGCoordinates[i]; * } * * m_Context.IOMaster.tracer.Message(ht, "Calling solver"); * LastSolverResult = m_Solver.Solve<double[], CoordinateVector, double[]>(1.0, diag, DGCoordinates, rhs); */ } }
/// <summary> /// Performs a sub-step /// </summary> /// <param name="dt">size of time step</param> public override double Perform(double dt) { using (var tr = new ilPSP.Tracing.FuncTrace()) { // Checking History if (HistoryDGCoordinate.Count >= order) { HistoryDGCoordinate.Dequeue(); } if (HistoryChangeRate.Count >= order) { HistoryChangeRate.Dequeue(); HistoryBoundaryFluxes.Dequeue(); } // Compute AB Coefficents if (adaptive) { if (historyTimePerCell.Count > order - 1) { historyTimePerCell.Dequeue(); } ABCoefficientsPerCell = new double[ABSubGrid.LocalNoOfCells][]; for (int cell = 0; cell < ABSubGrid.LocalNoOfCells; cell++) { double[] historyTimeArray = new double[order]; int i = 0; foreach (double[] historyPerCell in historyTimePerCell) { historyTimeArray[i] = historyPerCell[cell]; i++; } historyTimeArray[i] = m_Time; ABCoefficientsPerCell[cell] = ComputeCoefficients(dt, historyTimeArray); } } else { double[] historyTimeArray = HistoryTime.ToArray(); ABCoefficients = ComputeCoefficients(dt, historyTimeArray); } double[] upDGC; CurrentChangeRate = new double[Mapping.LocalLength]; currentBndFluxes = new double[numOfEdges * Mapping.Fields.Count]; ComputeChangeRate(CurrentChangeRate, m_Time, 0, currentBndFluxes); ////////////// Calculate complete change rate with older steps MakeABStep(); // Update DGCoordinates for History // (Hint: calls extra function to gives the ability to modify the update procedure, i.e in IBM case) upDGC = ComputesUpdatedDGCoordinates(CompleteChangeRate); // Keeps track of histories HistoryDGCoordinate.Enqueue(upDGC); HistoryChangeRate.Enqueue(CurrentChangeRate); HistoryBoundaryFluxes.Enqueue(currentBndFluxes); UpdateTimeHistory(dt); // Update local sub-grid time m_Time = m_Time + dt; } return(dt); }