Thursday, May 30, 2013

AMBER: GPU-accelerated 2-D Chebyshev collocation methods for elliptic equations


Purpose
  • The package "Amber" provides a GPU-accelerated Chebyshev collocation method for solving the single elliptic equation with Dirichlet, Neumann, or Robin boundary conditions on a 2-D rectangular domain.

Specifications
  • Name: Amber.
  • Author: Feng Chen.
  • Finishing date: 04/15/2012.
  • Languages: CUDA C++, Fortran 90.
  • Required libraries: BLAS, LAPACK, CUBLAS.

Simple Example
  • Equation: αu(β1uxx+β2uyy)=f,in Ω,au+bun=c,on Ω.
  • Parameters: Ω=(1,1)2,α=2,β1=3,β2=4,a=1,b=1.
  • Exact solution and input functions: u(x,y)=ex+y,
    then f(x,y) and c(x,y) are calculated accordingly.

Quick Start
  • Compiling and running:
    cd ./Amber
    make library
    nvcc Amber_Main.cu -llibrary -llapack -lblas
    ./a.out
    
  • Output:
    N = 2^3, GPU time = 1.5e-04
    N = 2^4, GPU time = 4.7e-05
    N = 2^5, GPU time = 5.3e-05
    N = 2^6, GPU time = 6.8e-05
    ...
    
  • CPU: Intel(R) Xeon(R) CPU X5630 @2.53GHz.
  • GPU: Nvidia Tesla M2050.
  • OS: CentOS release 6.4 (Final).
  • Compiler: nvcc 4.2.9, gcc/gfortran 4.5.1.

References
Code Highlights
    
    // 
    // Point-wise inversion in the frequency space
    // Input:  alpha, betax, betay (coefficients)
    //         lambdax, lambday (eigenvalues)
    //         nx, ny (number of quadrature points)
    //         f (input function)
    // Output: f (output function)
    //
    __global__ void Mercury_Kernel(double alpha, 
     int nx, double betax, double* lambdax, 
     int ny, double betay, double* lambday, 
     double* f) {
     
     // index of the current thread
     int i = threadIdx.x + blockIdx.x * blockDim.x;
     int j = threadIdx.y + blockIdx.y * blockDim.y;
     
     // index of the element to be inversed
     int i2;
     
     // wave number
     double sigma;
     
     if ( (i < nx) && (j < ny) ) {  
      sigma = alpha - betax*lambdax[i] - betay*lambday[j];  
      // for homogeneous Neumann condition and alpha=0 
      if (fabs(sigma) < 1e-8) {
       sigma = 1.0;
      }  
      // point-wise inversion
      i2 = c2(i,j,nx);
      f[i2] = f[i2]/sigma;
     }        
    }
    
    

No comments:

Post a Comment