public static void monogrid_poisson_1d(int n, double a, double b, double ua, double ub, Func <double, double> force, Func <double, double> exact, ref int it_num, ref double[] u) //****************************************************************************80 // // Purpose: // // MONOGRID_POISSON_1D solves a 1D PDE, using the Gauss-Seidel method. // // Discussion: // // This routine solves a 1D boundary value problem of the form // // - U''(X) = F(X) for A < X < B, // // with boundary conditions U(A) = UA, U(B) = UB. // // The Gauss-Seidel method is used. // // This routine is provided primarily for comparison with the // multigrid solver. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 26 July 2014 // // Author: // // John Burkardt // // Reference: // // William Hager, // Applied Numerical Linear Algebra, // Prentice-Hall, 1988, // ISBN13: 978-0130412942, // LC: QA184.H33. // // Parameters: // // Input, int N, the number of intervals. // // Input, double A, B, the endpoints. // // Input, double UA, UB, the boundary values at the endpoints. // // Input, double FORCE ( double x ), the name of the function // which evaluates the right hand side. // // Input, double EXACT ( double x ), the name of the function // which evaluates the exact solution. // // Output, int &IT_NUM, the number of iterations. // // Output, double U[N+1], the computed solution. // { double d1 = 0; int i; // // Initialization. // const double tol = 0.0001; // // Set the nodes. // double[] x = typeMethods.r8vec_linspace_new(n + 1, a, b); // // Set the right hand side. // double[] r = new double[n + 1]; r[0] = ua; double h = (b - a) / n; for (i = 1; i < n; i++) { r[i] = h * h * force(x[i]); } r[n] = ub; for (i = 0; i <= n; i++) { u[i] = 0.0; } it_num = 0; // // Gauss-Seidel iteration. // for (;;) { it_num += 1; GaussSeidel.gauss_seidel(n + 1, r, ref u, ref d1); if (d1 <= tol) { break; } } }
public static void multigrid_poisson_1d(int n, double a, double b, double ua, double ub, Func <double, double> force, Func <double, double> exact, ref int it_num, ref double[] u) //****************************************************************************80 // // Purpose: // // MULTIGRID_POISSON_1D solves a 1D PDE using the multigrid method. // // Discussion: // // This routine solves a 1D boundary value problem of the form // // - U''(X) = F(X) for A < X < B, // // with boundary conditions U(A) = UA, U(B) = UB. // // The multigrid method is used. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 26 July 2014 // // Author: // // Original FORTRAN77 version by William Hager. // C++ version by John Burkardt. // // Reference: // // William Hager, // Applied Numerical Linear Algebra, // Prentice-Hall, 1988, // ISBN13: 978-0130412942, // LC: QA184.H33. // // Parameters: // // Input, int N, the number of intervals. // N must be a power of 2. // // Input, double A, B, the endpoints. // // Input, double UA, UB, the boundary values at the endpoints. // // Input, double FORCE ( double x ), the name of the function // which evaluates the right hand side. // // Input, double EXACT ( double x ), the name of the function // which evaluates the exact solution. // // Output, int &IT_NUM, the number of iterations. // // Output, double U[N+1], the computed solution. // { int i; // // Determine if we have enough storage. // int k = (int)Math.Log2(n); if (Math.Abs(n - Math.Pow(2, k)) > double.Epsilon) { Console.WriteLine(""); Console.WriteLine("MULTIGRID_POISSON_1D - Fatal error!"); Console.WriteLine(" N is not a power of 2."); return; } int nl = n + n + k - 2; // // Initialization. // const int it = 4; it_num = 0; const double tol = 0.0001; const double utol = 0.7; int m = n; // // Set the nodes. // double[] x = typeMethods.r8vec_linspace_new(n + 1, a, b); // // Set the right hand side. // double[] r = new double[nl]; r[0] = ua; double h = (b - a) / n; for (i = 1; i < n; i++) { r[i] = h * h * force(x[i]); } r[n] = ub; double[] uu = new double[nl]; for (i = 0; i < nl; i++) { uu[i] = 0.0; } // // L points to first entry of solution // LL points to penultimate entry. // int l = 0; int ll = n - 1; // // Gauss-Seidel iteration // double d1 = 0.0; int j = 0; for (;;) { double d0 = d1; j += 1; GaussSeidel.gauss_seidel(n + 1, r, ref uu, ref d1, rIndex: +l, uIndex: +l); it_num += 1; // // Do at least 4 iterations at each level. // if (j < it) { } // // Enough iterations, satisfactory decrease, on finest grid, exit. // else if (d1 < tol && n == m) { break; } // // Enough iterations, satisfactory convergence, go finer. // else if (d1 < tol) { Transfer.ctof(n + 1, uu, n + n + 1, ref uu, ucIndex: +l, ufIndex: +(l - 1 - n - n)); n += n; ll = l - 2; l = l - 1 - n; j = 0; } // // Enough iterations, slow convergence, 2 < N, go coarser. // else if (utol * d0 <= d1 && 2 < n) { Transfer.ftoc(n + 1, uu, r, n / 2 + 1, ref uu, ref r, ufIndex: +l, rfIndex: +l, ucIndex: +(l + n + 1), rcIndex: +(l + n + 1)); n /= 2; l = ll + 2; ll = ll + n + 1; j = 0; } } for (i = 0; i < n + 1; i++) { u[i] = uu[i]; } }