# coding: utf-8 # # Loopy: Transforming a PDE to Code # In[1]: import pymbolic.primitives as p u = p.Variable("u") # We'll write code that evaluates $\triangle u$ using finite differences. # # To that end, we define a new expression 'thing': An operator for the Laplacian. # In[2]: class Laplacian(p.Expression): def __init__(self, child): self.child = child def __getinitargs__(self): return (self.child,) mapper_method = "map_laplacian" pde = Laplacian(u)+u**2-1 pde # Now we'll write code to turn Laplacians into their discrete finite difference forms, using `i` and `j` as formal indices, using # # $$f''(x) \approx \frac{f(x+h) - 2 f(x) + f(x-h)}{h^{2}}$$ # # Pay close attention to indexing! # In[3]: from pymbolic.mapper import IdentityMapper i = p.Variable("i") j = p.Variable("j") ii = i+1 jj = j+1 # In[7]: class FDMapper(IdentityMapper): def map_variable(self, expr): return expr[ii, jj] def map_laplacian(self, expr): var = expr.child return (-4*var[ii,jj] + var[ii+1,jj] + var[ii-1,jj] + var[ii,jj+1] + var[ii,jj-1]) # In[8]: fd_mapper = FDMapper() print(fd_mapper(pde)) # ---- # # Now let's generate some code for this, using `loopy`: # In[9]: import loopy as lp result = p.Variable("result") # Observe the two parts of the `loopy` kernel description: # # * Polyhedral loop domain # * Instructions # In[12]: knl = lp.make_kernel( "{[i,j]: 0<=i,j