This page was generated from unit-5.5-cuda/poisson_cuda.ipynb.

# 5.5 Solving the Poisson Equation using CUDAΒΆ

We use the **ngscuda** library to move compute intense linear algebra operations onto a GPU. The library is now included in NGSolve Linux - distributions, and can be used whenever an accelerator card by NVIDIA is available, and the cuda-runtime is installed.

```
[1]:
```

```
from ngsolve import *
```

```
[2]:
```

```
mesh = Mesh(unit_square.GenerateMesh(maxh=0.1))
for l in range(4):
mesh.Refine()
fes = H1(mesh, order=2, dirichlet=".*")
print ("ndof =", fes.ndof)
u, v = fes.TnT()
with TaskManager():
a = BilinearForm(grad(u)*grad(v)*dx+u*v*dx).Assemble()
f = LinearForm(x*v*dx).Assemble()
gfu = GridFunction(fes)
jac = a.mat.CreateSmoother(fes.FreeDofs())
with TaskManager():
inv_host = CGSolver(a.mat, jac, maxsteps=2000)
gfu.vec.data = inv_host * f.vec
```

```
ndof = 119425
```

Now we import the NGSolve - cuda library.

It provides

an

`UnifiedVector`

, which allocates memory on both, host and device. The data is updated on demand either on host, or on device.NGSolve - matrices can create their counterparts on the device. In the following, the conjugate gradients iteration runs on the host, but all operations involving big data are performed on the accelerator.

```
[3]:
```

```
try:
from ngsolve.ngscuda import *
fdev = UnifiedVector(f.vec)
adev = a.mat.CreateDeviceMatrix()
jacdev = jac.CreateDeviceMatrix()
inv = CGSolver(adev, jacdev, maxsteps=2000)
res = (inv * fdev).Evaluate()
diff = Norm(gfu.vec - res)
print ("diff = ", diff)
except:
print ("no CUDA library or device available")
```

```
no CUDA library or device available
```