FDM solvers in Python – a framework Europython, 7-9 June 2004 Åsmund Ødegård Simula Research Laboratory About me Motivation Building blocks Putting it together About me Name: Åsmund Ødegård Position: Ph.D student, IT-manager at Simula Research Laboratory AS, Norway. Research interests Object Oriented numerics, focus on PDEs Parallel computing Linux clusters Motivation - math ut (x, t) = ∇2 u(x, t) Motivation - math ut (x, t) = ∇2 u(x, t) Example, simple model of heat transfer Motivation - math ut (x, t) = ∇2 u(x, t) Apply FDM Example, simple model of heat transfer −uki uk+1 i ∆t = uki−1 −2uki +uki+1 ∆x2 Motivation - math ut (x, t) = ∇2 u(x, t) Apply FDM Example, simple model of heat transfer −uki uk+1 i ∆t k + = u uk+1 i i = uki−1 −2uki +uki+1 ∆x2 ∆t k (u i−1 ∆x2 − 2uki + uki+1 ) Motivation - math ut (x, t) = ∇2 u(x, t) Apply FDM Example, simple model of heat transfer −uki uk+1 i ∆t k + = u uk+1 i i = uki−1 −2uki +uki+1 ∆x2 ∆t k (u i−1 ∆x2 − 2uki + uki+1 ) Add boundary and initial conditions Motivation Motivation Related work: - Cogito, K. Åhlander et.al - A++/P++, Dan. Quinlan et.al - And many others contributions Priorities 1. Abstractions 2. Parallelization 3. Efficiency Motivation Related work: - Cogito, K. Åhlander et.al - A++/P++, Dan. Quinlan et.al - And many others contributions Priorities 1. Abstractions 2. Parallelization 3. Efficiency Part of the SciTools project Building blocks Grid Basic abstraction Number of dimensions Domain and partition Methods: – setSize – innerPoints – boundary – corners Building blocks Grid Stencil Main abstraction Define action of the PDE in one point. Same stencil in many points, e.g all inner-points and all boundary points. Stencils may (easily) be defined dimension–independent. k + uk+1 = u i i ∆t k (u 2 i−1 ∆x 1 − 2uki + uki+1 ) 1 -4 1 1 Building blocks Grid from Stencil import Stencil s = Stencil(1,1) # 1D, variable coefficients Stencil s.addNode((-1),[lambda x: 0.5*x*x]) s.addNode((1),[lambda x: 0.5*x*x]) s.addNode((0),[lambda x: 2]) 1 This is the simple usage – It may also be convenient to subclass Stencil. 1 -4 1 1 Building blocks Grid Stencil bi = map(lambda x: 0,range(self.nsd)) dx = grid.division for i in xrange(self.nsd): # copy the basic index into changeable object cbi = copy(bi) # add "left" node cbi[i]=-1 ti=tuple(cbi) value = 1.0/(dx[i]*dx[i]) 1 self.addNode(ti,value) # add "right" node cbi[i]=1 1 -4 ti=tuple(cbi) self.addNode(ti,value) # add "center" 1 cbi[i]=0 ti=tuple(cbi) value=-2.0/(dx[i]*dx[i]) self.addNode(ti,value) 1 Building blocks Grid Stencil StencilList StencilList – Main abstraction Build the action of the PDE as a list of stencils. Hold two lists: – List of Stencils – List of iterators! Iterators define points where each Stencil will be applied. 1 1 -4 1 1 -4 2 1 1 Building blocks Grid Field – Basic abstraction Data, a Numeric array Pointer to a Grid object Stencil Methods: – get and set item StencilList – fill, taking some function as argument – plot, ... Field Building blocks Grid 1 -4 1 2 Stencil 1 1 StencilList -4 1 1 1 Field One explicit step: un+1 = stencillist(un ) Building blocks An important issue: How to traverse the grid? Building blocks An important issue: How to traverse the grid? Our solution: Use iterators! - Benefit: We don’t need to create list for all indices in memory. - Drawback: speed - Simplest case: (1,1,...) - (n-1,m-1,...), which represent all inner nodes in the grid. Can also be done with list-comprehension (but that will produce the list in memory) – <code>: simpletuple.py Building blocks What if you want a Neumann–condition on part of the boundary? 1 -4 2 1 Building blocks What if you want a Neumann–condition on part of the boundary? 1 -4 1 2 We have implemented a generator which provide an iterator for each part of the boundary, with necessary auxiliary information. – <code>: advancedtuple.py An example Consider a simple Heat equation: u t = ∇2 u u(x, 0) = f (x), ux (x, t) = g(x, t), x∈Ω x∈Ω x ∈ ∂Ω Assume further that we want to solve this on the unit square with f and g given as initialfunc and neumanncond, respectively. An example (run it!) g = Grid(([0.0,1.0],[0.0,1.0]),(100,100)) u = Field(g) t = 0; ∆t = T/n; sl = StencilList(g) innerstencil = Identity(g) + ∆t*Laplace(g) innerind = sl.addStencil(innerstencil,g.innerPoints()) sl += NeumannBoundary.create(sl[innerind],g,neumanncond) u.fill(initialfunc) for t < T: u = sl(u) t += ∆t Conclusions We have created a framework suitable for experimenting with FDM. The syntax is compact. It can be used both interactively in a “matlab” kind of style, or you can create solver classes utilizing the presented abstractions. Some Future steps Today, the framework only support explicit methods – implicit methods must also be addressed. We need to couple with a linear algebra library. Automatic parallelization. The stencils provide the communication pattern. More geometry! More focus on performance, e.g. vectorization of operators, implementing c or fortran modules for certain operations.