# A Novel GPU-Based Acceleration Algorithm for a Longwave Radiative Transfer Model
## 5 Algorithm Implementation
### Inatm_d  
The implementations of CUDA-based 2D \(inatm\_d1\), \(inatm\_d2\), and \(inatm\_d5\) are similar to the procedure in Algorithm 5. Here, \(threadIdx\%x\) identifies a unique thread inside a thread block in the \(x\) dimension, \(blockIdx\%x\) identifies a unique thread block inside a kernel grid in the \(x\) dimension, and \(blockDim\%x\) identifies the number of threads in a thread block in the \(x\) dimension. In the same way, \(threadIdx\%y\), \(blockIdx\%y\), and \(blockDim\%y\) identify the corresponding configuration in the \(y\) dimension. Please note that the \"%\" symbol in Fortran is the access to fields of a structure and not the modulus operator. In addition, \(iplon\), the coordinate of the horizontal grid points, represents the ID of a global thread in the \(x\) dimension, which can be expressed as \(iplon\)=(\(blockIdx\%x\)-1)\(\times blockDim\%x\)+\(threadIdx\%x\). The coordinate of the vertical direction, \(lay\), also represents the ID of a global thread in the \(y\) dimension, which can be expressed as \(lay\)=(\(blockIdx\%y\)-1)\(\times blockDim\%y\)+\(threadIdx\%y\). Thus, a grid point in the horizontal and vertical directions can be identified by the \(iplon\) and \(lay\) variables as 2D linear data.  
The implementation of \(inatm\_d3\) is illustrated in Algorithm 6. Here, \(threadIdx\%z\) identifies a unique thread inside a thread block in the \(z\) dimension, \(blockIdx\%z\) identifies a unique thread block inside a kernel grid in the \(z\) dimension, and \(blockDim\%z\) identifies the number of threads in a thread block in the \(z\) dimension. The coordinate of the \(g\) points, \(ig\), also represents the ID of a global thread in the \(x\) dimension, which can be expressed as \(ig\)=(\(blockIdx\%x\)-1)\(\times blockDim\%x\)+\(threadIdx\%x\). Furthermore, \(inatm\_d3\) is used to assign a value to the four 3D arrays.  
The implementation of 1D \(inatm\_d4\) is illustrated in Algorithm 7.  
```
attributes(global) subroutine\(inatm\_d\)(parameters) 1. \(iplon\)=(blockIdx\%x-1)\(\times\)blockDim%x+threadIdx%x 2. \(lay\)=(blockIdx\%y-1)\(\times\)blockDim%y+threadIdx%y //nlayers=nlay + 1, nlay is number of model layers 3. if((\(iplon\)\(\geq\)1.and. \(iplon\)\(\leq\)ncol).and. (\(lay\)\(\geq\)1.and. \(lay\)\(\leq\)nlayers-1 or nlayers or nlayers+1)) then
4 Initialize variable arrays or do some computational work for them 5. endif end subroutine
```  
**Algorithm 5**Implementation of 2D \(inatm\_d\).  
```
attributes(global) subroutine\(inatm\_d3\)(parameters) 1. \(ig\)=(blockIdx\(\%x\)-1)\(\times\)blockDim%x+threadIdx%x 2. \(iplon\)=(blockIdx\(\%y\)-1)\(\times\)blockDim%y+threadIdx%y 3. \(lay\)=(blockIdx\%z-1)\(\times\)blockDim%z+threadIdx%z //ngptlw is total number of reduced g-intervals 4. if((\(iplon\)\(\geq\)1.and. \(iplon\)\(\leq\)ncol).and. (\(lay\)\(\geq\)1.and. \(lay\)\(\leq\)nlayers-1).and. (\(ig\)\(\geq\)1.and. \(ig\)\(\leq\)ngptlw)) then
5 cldfmc(ig, iplon, lay) = cldfmcLd(ig, iplon, nlayers-lay)
6 taucmc(ig, iplon, lay) = taucml_d(ig, iplon, nlayers-lay)
7 ciwpmc(ig, iplon, lay) = ciwpmcl_d(ig, iplon, nlayers-lay)
8 clwpmc(ig, iplon, lay) = clwpmcl_d(ig, iplon, nlayers-lay)
9 endif end subroutine
```  
**Algorithm 6**Implementation of \(inatm\_d3\).