/// <summary> /// see <see cref="IMonkeyImplicitPrecond.DoPrecond"/> /// </summary> override public void DoPrecond() { m_PcOutput.CopyFrom(m_PcInput); // iterate // ======= for (int i = 1; i < m_NoOfIter; i++) { // Jacobi iteration // ================ //((CPU.RefMatrix)m_Matrix).useSingle = true; m_Matrix.SpMV_Expert(-1.0, _xComm, 0.0, tmp); // tmp = -M*x //((CPU.RefMatrix)m_Matrix).useSingle = true; tmp.Acc(1.0, m_PcInput); // tmp = -M*x + m_PcInput if (m_UnderRelaxationFactor != 1.0) { tmp.Scale(m_UnderRelaxationFactor); } if (m_UnderRelaxationFactor != 1.0) { tmp.Scale(m_UnderRelaxationFactor); } tmp.MultiplyElementWise(m_InvDiag); m_PcOutput.Acc(1.0, tmp); //m_PcOutput = m_PcOutput + tmp } }
/// <summary> /// this function implements the preconditioning according to the neumann preconditioner /// </summary> public override void DoPrecond() { mPcOutput.CopyFrom(mPcInput); for (int i = 1; i < m_NoOfIter; i++) { //_yNew = _yOld - m_matrix*_yOld; m_matrix.SpMV_Expert(-1.0, _yComm, 0.0, yNew); //yNew = -m_matrix * yComm = -m_Matrix*yOld yNew.Acc(1.0, yOld); //yNew = yOld - m_Matrix*yOld; mPcOutput.Acc(1.0, yNew); //mPcOutput = mPcOutput + yNew yOld.Swap(yNew); } }
/// <summary> /// executes the Jacobi iteration /// </summary> protected override void CallSolver(VectorBase x, VectorBase rhs, ref SolverResult stats) { // create objects // ============== VectorBase.CommVector _xComm = x.CreateCommVector(m_Matrix); VectorBase tmp = Device.CreateVector(x.Part); VectorBase InvDiag = CreateInvDiag(); // lock objects // ============ x.Lock(); m_Matrix.Lock(); rhs.Lock(); tmp.Lock(); InvDiag.Lock(); // iterate // ======= stats.Converged = false; stats.NoOfIterations = 0; double residualNorm = double.MaxValue; double r_0 = double.NaN; while (true) { // loop termination // ================ if (stats.NoOfIterations >= m_MinIterations) // do at least the minimum number of iterations { if (residualNorm <= m_Tolerance) { // success stats.Converged = true; break; } if (stats.NoOfIterations >= m_MaxIterations) { // terminate break; } } // Jacobi iteration // ================ m_Matrix.SpMV_Expert(-1.0, _xComm, 0.0, tmp); // tmp = -M*x tmp.Acc(1.0, rhs); // tmp = -M*x + rhs if (m_UnderRelaxationFactor != 1.0) { tmp.Scale(m_UnderRelaxationFactor); } double r = Math.Sqrt(tmp.TwoNormSquare()); if (stats.NoOfIterations == 0) { r_0 = r; } if (m_ConvergenceType == ConvergenceTypes.Absolute) { residualNorm = r; } else { residualNorm = r / r_0; } //Console.WriteLine("JACOBI: " + residualNorm); if (m_UnderRelaxationFactor != 1.0) { tmp.Scale(m_UnderRelaxationFactor); } tmp.MultiplyElementWise(InvDiag); x.Acc(1.0, tmp); stats.NoOfIterations++; } // unlock // ====== x.Unlock(); m_Matrix.Unlock(); rhs.Unlock(); InvDiag.Unlock(); }
//[DllImport("Kernel32.dll")] //static extern bool QueryPerformanceCounter(out long lpPerformanceCount); /// <summary> /// implementation of the CG algorithm /// </summary> /// <param name="x"></param> /// <param name="rhs"></param> /// <param name="stats"></param> protected override void CallSolver(VectorBase x, VectorBase rhs, ref SolverResult stats) { VectorBase P = Device.CreateVector(x.Part); VectorBase.CommVector commP = P.CreateCommVector(m_Matrix); VectorBase R = rhs; // rhs is only needed once, so we can use it to store residuals VectorBase V = Device.CreateVector(x.Part); // lock objects // ============ x.Lock(); P.Lock(); R.Lock(); V.Lock(); m_Matrix.Lock(); // compute P0, R0 // ============== // we only need to multiply x once by the Matrix, so we don't want to create // a seperate VectorBase.CommVector - object for x; // Instead, we're temporatily exchangeing the roles of x and P; P.Swap(x); x.CopyFrom(rhs); // x = rhs m_Matrix.SpMV_Expert(-1.0, commP, 1.0, x); // x = rhs - M*x P.Swap(x); R.CopyFrom(P); double alpha = R.TwoNormSquare(); double alpha_0 = alpha; double ResNorm; if (m_ConvergenceType == ConvergenceTypes.Absolute) { ResNorm = Math.Sqrt(alpha); } else if (m_ConvergenceType == ConvergenceTypes.Relative) { ResNorm = 1.0; } else { throw new NotImplementedException("unknown convergence type: " + m_ConvergenceType.ToString()); } //long total = 0; //long gemv = 0; //long rest = 0; //long st, en; // iterate // ======= stats.Converged = false; stats.NoOfIterations = 1; // one iteration has already been performed (P0, R0) for (int n = m_MaxIterations - 2; n >= 0; n--) { if (ResNorm <= m_Tolerance && stats.NoOfIterations >= base.m_MinIterations) { stats.Converged = true; break; } if (Math.Abs(alpha) <= double.Epsilon) { // numerical breakdown break; } m_Matrix.SpMV_Expert(1.0, commP, 0, V); double lambda = alpha / V.InnerProd(P); x.Acc(lambda, P); R.Acc(-lambda, V); double alpha_neu = R.TwoNormSquare(); // compute residual norm if (m_ConvergenceType == ConvergenceTypes.Absolute) { ResNorm = Math.Sqrt(alpha); } else { ResNorm = Math.Sqrt(alpha / alpha_0); } P.Scale(alpha_neu / alpha); P.Acc(1.0, R); alpha = alpha_neu; stats.NoOfIterations++; //QueryPerformanceCounter(out st); //rest += (st - en); } //Console.WriteLine("CG: R" + stats.NoOfIterations + " = " + ResNorm); // unlock objects // ============== x.Unlock(); P.Unlock(); R.Unlock(); V.Unlock(); m_Matrix.Unlock(); commP.Dispose(); P.Dispose(); V.Dispose(); }
/// <summary> /// implementation of the CG algorithm /// </summary> /// <param name="x"></param> /// <param name="rhs"></param> /// <param name="stats"></param> protected override void CallSolver(VectorBase x, VectorBase rhs, ref SolverResult stats) { VectorBase P = Device.CreateVector(x.Part); VectorBase.CommVector commP = P.CreateCommVector(m_Matrix); VectorBase R = rhs; // rhs is only needed once, so we can use it to store residuals VectorBase V = Device.CreateVector(x.Part); VectorBase Z = Device.CreateVector(x.Part); // lock objects // ============ x.Lock(); P.Lock(); R.Lock(); V.Lock(); Z.Lock(); m_Matrix.Lock(); // configure Precond // ================= if (m_NestedPrecond != null) { m_NestedPrecond.CreateTempObjects(Z, R, m_Matrix, this.Device); } // compute P0, R0 // ============== P.Swap(x); m_Matrix.SpMV_Expert(-1.0, commP, 1.0, R); P.Swap(x); if (m_NestedPrecond != null) { m_NestedPrecond.DoPrecond(); P.CopyFrom(Z); } else { P.CopyFrom(R); } double alpha = R.InnerProd(P); double alpha_0 = alpha; double ResNorm; if (m_ConvergenceType == ConvergenceTypes.Absolute) { ResNorm = Math.Sqrt(alpha); } else if (m_ConvergenceType == ConvergenceTypes.Relative) { ResNorm = 1.0; } else { throw new NotImplementedException("unknown convergence type: " + m_ConvergenceType.ToString()); } //long total = 0; //long gemv = 0; //long rest = 0; //long st, en; // iterate // ======= stats.Converged = false; stats.NoOfIterations = 1; // one iteration has allready been performed (P0, R0) for (int n = m_MaxIterations - 2; n >= 0; n--) { if (ResNorm <= m_Tolerance && stats.NoOfIterations >= base.m_MinIterations) { stats.Converged = true; break; } if (Math.Abs(alpha) <= double.Epsilon) { // numerical breakdown break; } m_Matrix.SpMV_Expert(1.0, commP, 0, V); double lambda = alpha / V.InnerProd(P); x.Acc(lambda, P); R.Acc(-lambda, V); if (m_IterationCallback != null) { // pass approx. sol and residual to callback function x.Unlock(); R.Unlock(); double[] x_approx = new double[x.Part.LocalLength]; x.CopyTo(x_approx, 0); double[] R_curr = new double[R.Part.LocalLength]; R.CopyTo(R_curr, 0); m_IterationCallback(stats.NoOfIterations, x_approx, R_curr); x.Lock(); R.Lock(); } if (m_NestedPrecond != null) { Z.Clear(); m_NestedPrecond.DoPrecond(); } else { Z.CopyFrom(R); } double alpha_neu = R.InnerProd(Z); // compute residual norm if (m_ConvergenceType == ConvergenceTypes.Absolute) { ResNorm = Math.Sqrt(alpha); } else { ResNorm = Math.Sqrt(alpha / alpha_0); } ResNorm = Math.Sqrt(R.TwoNormSquare()); P.Scale(alpha_neu / alpha); P.Acc(1.0, Z); alpha = alpha_neu; stats.NoOfIterations++; } // unlock objects // ============== if (m_NestedPrecond != null) { m_NestedPrecond.ReleaseTempObjects(); } x.Unlock(); P.Unlock(); R.Unlock(); V.Unlock(); m_Matrix.Unlock(); commP.Dispose(); P.Dispose(); }