Numerical Modelling With Python and XML
Numerical Modelling With Python and XML
1. Introduction
These days numerical simulation is a team effort combining a variety of skills. In
a very simple approach we can identify four groups of people being involved: re-
searchers using numerical simulation techniques to improve the understanding and
predict phenomenas in science and engineering, modelers developing and validating
mathematical models, computational scientists implementing the underlying nu-
merical methods, software engineers implementing and optimizing algorithms for a
particular architecture. Each of these skill levels uses their individual terminology:
researcher is using terms such stress, temperature and constitutive laws, while
the modeler is expressing his models through functions and partial differential
equations. The computational scientist is working with grids, matrices. Software
engineers is working with arrays and data structures. Finally, an object such as
stress used by a researcher is represented as a suitable, maybe platform dependent,
2 Gross, Mühlhaus, Thorne and Steube
data structure after the modeler has interpreted as a function of spatial coordi-
nates and the computational scientists as values at the center of elements in a
finite element mesh. When moving from the software engineer’s view towards the
view of the researcher the data structures undergo an abstraction process finally
only seeing the concept of stress but ignoring the fact that it is a function in the
L2 Sobolev space and represented by using a finite element mesh.
It is also important to point out that each of these layers has an appropriate
user environment. For the researcher, this is a set input files describing the prob-
lem to be solved, typically in XML [5]. Modelers, mostly not trained as software
engineers, prefer to work in script-based environments, such as python [7] while
computational scientists and software engineers are are working in C and C++ to
achieve best possible computational efficiency.
Various efforts have been made to provide tools for computational scientists
to develop numerical algorithms, for instance PETSc [13] which is widely used.
These tools provide linear algebra concepts such as vectors and matrices and hid-
ing data structures from the user. The need of researchers for an easy to use
environment has been addressed through various developments in problem solving
environments (PSEs) [8] which is some case can be a simple graphical user inter-
face. There were only a rather small number of activities towards environments
for modelers. Two examples for partial differential equation (PDE) based mod-
elling are ELLPACK [11] and FASTFLO [12]. Both products are using there own
programming language which is not powerful enough to deal with complex and
coupled problems in an easy and efficient way.
The escript module [1, 2] which embedded into python is an environment in
which modelers can develop PDE based models. It is designed to solve general,
coupled, time-dependent, non-linear systems of PDEs. It is a fundamental design
feature of escript that is not tight to a particular spatial discretization technique
or PDE solver library. It is seamlessly linked with other tools such as linear algebra
tools [14] and visualization tools [15].
In this paper we will give an overview into the basic concepts of escript
from a modellers point of view We will illustrate its usage for implementing the
Drucker–Prager flow model. In the second part we will present the modelframe
module within escript. It provides a framework to implement mathematical models
as python objects which then can be plugged together to build simulations. We
illustrate this approach for the Drucker–Prager flow and show how this model can
be linked with a temperature advection–diffusion model without modifying the
codes for any of the models. We will then discuss how XML can be used to set
simulation parameters but also to define an entire simulation from existing models.
The XML files provide an ideal method to build simulations out of PSEs or from
web services. The presented implementation of the Drucker-Prager flow has been
validated on some test problems but as it not the purpose of the paper to discuss
models no results are presented.
Numerical Modelling with Python and XML 3
dt :
kduk∞ ≤ ζiter kuk∞ (2.1)
where k.k∞ denotes the maximum norm and ζiter is a given positive relative tol-
erance. Alternatively, one can check the change stress.
The keep the relative time integration error below the given tolerance ζtime
the time step dt for the next time step should be kept below dtmax given by
dt kuk∞
dtmax = ζtime . (2.2)
kv − v − k∞
which controls an estimate of the local time discretization error for the total dis-
placement u.
The stretching Dij and spin Wij are given as the symmetric and non-symmetric
part of the the gradient of dui :
1
Dij = (dui,j + duj,i ) (2.3)
2
1
Wij = (dui,j − duj,i ) (2.4)
2
where where for any function Z Z,i denotes the derivative of Z with respect to xi .
To calculate the displacement increment dui one has to solve a partial dif-
ferential equation on the deformed domain Ω− which takes in tensor notation the
form
−
−(Sijkl duk,l ),j = (σij − K ǫth δij ),j + fi (2.5)
where K is the bulk modulus and Sijkl is the tangential tensor which depends
on the rheology that is used. The argument of divergence expression in the right
4 Gross, Mühlhaus, Thorne and Steube
−
hand side is the Cauchy stress at time t − dt with the mechanical stress σij at time
th
t − dt. The term K ǫ δij is the thermal stress where the thermal volume strain
ǫth is given as
ǫth = θ (T − Tref ) (2.6)
with thermal expansion coefficient θ and current temperature T and the reference
temperature Tref . In geoscience applications, fi typically takes the form of the
gravitational force
fi = −ρ gδid (2.7)
which acts oppositely to the positive d direction. The constants g is the gravity
constant and ρ is the density which is often given in the form
ρ = ρ0 (1 − θ(T − T0 )) (2.8)
where ρ0 is the density at reference temperature T0 .
The displacement increment has to fulfill the conditions
−
nj (Sijkl duk,l + σij − K ǫth δij ) = gi (2.9)
on the boundary of the domain where gi is a possibly time-dependent surface load.
Moreover, the displacement increment has to meet a constraint of the form
du = dt · Vi on Γi (2.10)
where Γi is a subset of the boundary of the domain. At the first iteration step Vi
gives the i-th velocity component acting at the subset Γi of the deformed domain
and is set to zero for the following steps.
again a given function of the plastic shear stress γ p , we set the plastic shear stress
increment to
F
λ=χ (2.17)
h + G + βK
We then can calculate a new stress as
τ = τ e − λG (2.18)
τ e ′
σij = e (σij ) − (pe + λβK)δij (2.19)
τ
Finally we can update the plastic shear stress
γ p = γ p− + λ (2.20)
3. Implementation
The key problem in the Drucker-Prager model is to solve a linear, steady partial
differential equation. The coefficients of the PDE are given by arithmetic expres-
sions of the PDE solutions. In this chapter we outline the concept of the python
module escript [1, 2] and demonstrate its usage in the Drucker-Prager model.
6 Gross, Mühlhaus, Thorne and Steube
-swap_axes(sXk3,1,2) \
+swap_axes(sXk3,1,3) ) \
- outer(chi/(h+G+alpha*beta*K)*(tmp+beta*K*k3),tmp+alpha*K*k3)
return S
The values chi, s_dev and tau calculated in a call of getStress could used in
this calculation of the new stress could be reduced in getTangentialTensor.
4. Modelling Framework
From the functions presented in the previous section 3 one can easily build a
time integrations scheme to implement a Drucker-Prager flow model through two
nested loops. The outer loop progresses in time while the inner loop iterates at
time step until the stopping criterion (2.1) is fulfilled. The time step size is con-
trolled by criterion 2.2. This straight-forward approach has the drawback that the
code has to modified when the temperature dependence becomes time-dependent.
Then a advection-diffusion model for the temperature has to be worked into the
code which may use a different time step size. In addition, the thermal strain ǫth
is changing over time but also material parameters, for instance density, see equa-
tion (2.8), may become temperature-dependent. The coding effort to implement
these components is not large but has the big drawback that the submodel, such
as the Drucker-Prager model, the temperature advection-diffusion model and the
material property tables, loose their independence. However, from a software de-
velopment point of view it is highly desirable to keep the models independent in
order to test and maintain them separately and reuse models in another context.
target object is returned. If the value is callable, the value is called and the result
is returned. So, similar to a pointer in C, a Link class object defines another name
for a target value, and is updated along with the target object.
A LinkableObjects class object is a standard python object with a modified
__getattr__ method: when accessing its attributes it behaves like a usual python
object except if the value is a Link class object. In this case, the link is followed,
that means the value is called and the result returned. The mechanism allows to
link an attribute of LinkableObjects class object with the attribute of another
target object such that at any time the object uses the value of the target object.
The following script shows how a gravity force in flow model can be defined
where the density of the gravity model is temperature-dependent:
mat=MaterialTable()
mat.T_0=20
temp=Temperature()
g=Gravity()
flow=DruckerPrager()
mat.T=Link(temp,"temperature")
g.density=Link(mat,"rho")
flow.force=Link(g,"force")
The four classes MaterialProperties Temperature, Gravity and DruckerPrager
implementing a material property table, a temperature advection-diffusion model,
a gravity force model and a Drucker-Prager flow model. The temperature parame-
ter T of the material property table is provided by the temperature model attribute
temperature. The density rho provided by the material property table is fed into
the gravity model which then provides the external force for the flow model.
The model (2.8) of a temperature-dependent density can be implemented in
the following way:
class MaterialProperties(LinkableObject):
def rho(self):
return self.rho_0*(1.-self.theta*(self.T-self.T_0))
If the temperature T is linked to a time-dependent temperature model via a Link
object the method rho will always use the most recent value of the temperature
even if it is updated by the target temperature model. On the other hand, if an
attribute of another model, for instance the attribute density of a Gravity class
object, is linked against the method rho of an instance of the MaterialProperties
class, accessing the attribute will call the the method rho and use its return value
calculated for the current temperature. Through the chain of links the Drucker-
Prager flow model is coupled with the temperature modules. It is pointed out that
if the temperature model considers advection, the velocity updated by Drucker-
Prager flow model is referenced by the temperature model which produces a loop
of references requiring an iteration on a time step.
Numerical Modelling with Python and XML 11
4.2. Models
Implementing models as LinkableObject class objects solves the problem of defin-
ing the data flow of coupled models but we also need an execution scheme for
individual models in order to be able to execute a set of coupled models with-
out changing any of involved models. An appropriate execution scheme is defined
through the Model class of the modelframe module. The Model class which is a
subclass of the LinkableObject class provides a template for a set of methods
that have to be implemented for a particular model. The Model class methods are
as follows:
• doInitialization: This method is used to initialize the time integration
process. For the flow model this method initializes displacements and stress
for time t = 0 and to create an instance of the LinearPDE object used to
update the displacement through equation (2.5).
• getSafeTimeStepSize: This method returns the maximum time step size
that can be used to safely execute the next time step of the model. For the
flow model the time step size defined by condition (2.2)) is returned.
• doStepPreprocessing: This method prepares the iterative process to be ex-
ecuted on a time step. Typically, this function will set an initial guess for the
iterative process to run on a time step.
• doStep: This method performs a single iteration step to update state variables
controlled by the model due to changes in input parameters controlled by
other models. For the Drucker–Prager flow model the doStep perform a single
iteration step by solving the PDE (2.5) and updating the stress via (2.19).
• terminateIteration: The method returns True if the iterative process on a
time step can be terminated. Typically, a stopping criterion of the form (2.1)
is checked.
• doStepPostprocessing: This method finalizes a time step, typically by shift-
ing the current values of state variables into the buffer of the previous time
step.
• finalize: The method returns True is the time integration is finalized. Typ-
ically this method checks the current time against a given end time.
• doFinalization: This method finalizes the whole modeling run, typically by
closing files and cleaning up.
Any Model class object is run in the following way:
m=Model()
m.doInitialization()
while not finalize():
dt=m.getSafeTimeStepSize(dt)
m.doStepPreprocessing(dt)
while not m.terminateIteration(): m.doStep(dt)
m.doStepPostprocessing(dt)
m.doFinalization()
12 Gross, Mühlhaus, Thorne and Steube
This scheme is executed by the Simulation class, which will be discussed in the
next section 4.3.
The following sub-class of the Model class implements the Drucker–Prager
flow model:
class DruckerPrager(Model):
def doInitialization(self):
self.pde=LinearPDE(self.domain)
self.stress=Tensor(0.,Function(self.doamin))
self.displacement=Vector(0.,Solution(self.doamin))
self.velocity=Vector(0.,Solution(self.doamin))
self.t=0
def getSafeTimeStepSize(self):
return dt*Lsup(u)/Lsup(self.velocity-self.velocity_old)*self.zeta
def doStep(self,dt):
S=self.getTangentialTensor()
pde.setValue(A=S, X=self.stress,Y=self.force)
self.du=self.pde.getSolution()
self.displacement=self.displacement+self.du
self.velocity=(self.displacement-self.displacement_old)/dt
self.stress=self.getStress()
def terminateIteration(self,dt):
return Lsup(self.du)<=self.zeta*Lsup(self.displacement)
def doStepPostprocessing(self,dt):
self.velocity_old=self.velocity
self.t+=dt
def finalize(self):
return self.t<self.t_end
Omitted Model class methods are empty. The functions getStress and getTangentialTensor
introduced in section 3.2 are turned into class methods. Function parameters are
now accessed as class attributes.
4.3. Simulations
The Simulation class controls the execution of a list of submodels. It is an imple-
mentation of the Model class, where each Model method executes the corresponding
method of all the submodels: The getSafeTimeStepSize returns the minimum of
all step sizes required by the submodels. If all submodels terminate their iterative
process terminateIteration returns True. The simulation is terminated by the
finalize method if any of the submodels is to be finalized. The doStep method
iterates over all submodels until all submodel indicate convergence.
The following script outlines the usage of the Simulation class for construct-
ing and running a coupled temperature diffusion and Drucker-Prager flow model:
mat=MaterialTable()
temp=Temperature()
Numerical Modelling with Python and XML 13
g=Gravity()
flow=DruckerPrager()
s=Simulation([temp,mat,g,flow])
s.run()
The couplings between the models as shown in section 4.1 have been omitted. The
run method of the Simulation class executes its Model methods as shown in the
previous section 4.2. At a time step, the simulation iterates over the submodels
until all submodels have converged. The execution order is defined by the order of
the models in Simulation class argument. Alternatively, one can iterate over the
flow model only and use the temperature from the previous time step. This can
be achieved through
Simulation([temp,mat,g,Simulation([flow])).run()
where the convergence tolerance in the temperature model has to be chosen appro-
priately. Note that visualization functionality, for instance to create a movie of the
velocity field, can be implemented as a Model class where in the doStepPostprocessing
method the velocity field is rendered after for each time step, while the doFinalization
method creates the movie from the frames.
It is pointed that the coupling of the models does not require any knowledge
of the algorithms being used to implement the model. Furthermore, the codes
implementing a model are not altered to perform the coupling. The coupling is
based purely on the submodel parameters. This high-level approach is possible
because of the abstraction level that is provided by the escript environment.
self.declareParameters(domain=None, force=0., \
stress=0., displacement=0., \
velocity=0.)
This explicit declaration restricts the necessary input and output parameters that
are exposed on a user-interface level. The XML representation of a Model class
object includes all parameters and their current values, which could be Link class
objects. The python implementation of a model itself is not stored in XML, only
the data and the links between models.
A Simulation class object can be written into a XML file using the EsysXML.
This includes all submodels, their external parameter and values and possibly links
between the submodels. This file can be edited using any text editor to change
value of external parameters, introduce new models and set or remove couplings
between models. A Simulation class object can be build from the XML file. The
parser uses the standard python XML tools, packaged in PyXML [9]. Primarily,
minidom is used to parse and generate XML content. It is a lightweight, simple
implementation of the standard Document Object Model (DOM) interface, and
is fast. An important application of writing Simulation class objects to XML is
automated check-pointing.
6. Conclusion
The design we have chosen for escript simplifies the development of complex yet
efficient models by breaking them down into a series of simpler steps. In the ex-
ample above, we developed a Drucker-Prager flow model and a gravity model, and
Numerical Modelling with Python and XML 15
Acknowledgment
Project work is supported by Australian Commonwealth Government through
the Australian Computational Earth Systems Simulator Major National Research
Facility and the Australian Partnership for Advanced Computing, Queensland
State Government through the Smart State Research Facility Fund, The University
of Queensland, the Queensland Cyberinfrastructure Foundation and SGI Ltd.
References
[1] Gross, L. and Cochrane, P. and Davies, M. and Mühlhaus, H. and Smillie J.: Es-
cript: numerical modelling in python. Proceedings of the Third APAC Conference on
Advanced Computing, Grid Applications and e-Research (APAC05),(2005).
[2] Davies, M. and Gross, L. and Mühlhaus, H. -B.: Scripting high-performance Earth
systems simulations on the SGI Altix 3700. Proceedings of the 7th international con-
ference on high-performance computing and grid in the Asia Pacific region, (2004).
[3] Zienkiewicz, O. C. and Taylor, R. L.: The Finite Element Method. 5th Edition, But-
terworth Heinemann, (2000).
[4] R. E. Williamson: Differential Equations and Dynamical Systems, McGrawHall
(2001).
[5] http://www.w3.org/XML/ (2006), [on-line].
[6] C. M. Sperberg-McQueen and H. Thompson: XML Schema,
www.w3.org/XML/Schema (2006), [on-line].
[7] M. Lutz, Programming Python, 2nd Edition O’Reilly (2001).
[8] E. N. Houstis, E. Gallopoulos, J.R. Rice, R. Bramley: Enabling Technologies for Com-
putational Science Kluwer Academic Publishers (2000).
[9] http://pyxml.sourceforge.net/ (2006), [on-line].
[10] D. J. Higham, N. J. Higham, MATLAB Guide., SIAM (2000).
[11] J. R. Rice, R .F. Boisvert, Solving Elliptic Problems Using ELLPACK. Springer
Series in Computational Software 2 (1985).
16 Gross, Mühlhaus, Thorne and Steube
[12] X.–L. Luo, A. N. Stokes, N. G. Barton, Turbulent flow around a car body - report of
Fastflo solutions Proc. WUA-CFD Conference, Freiburg (1996).
[13] P. Pacheco, Parallel Programming with MPI., Morgan-Kaufmann (1997).
[14] P. Greenfield, J. T. Miller, J. Hsu, R. L. White. An Array Module for Python. in
Astronomical Data Analysis Software and Systems XI (2001).
[15] The Kitware, Inc.: Visualization Toolkit User’s Guide. Kitware, Inc publishers.
Lutz Gross
Earth Systems Science Computational Center
The University of Queensland
St. Lucia., QLD 4072
Australia
e-mail: l.gross@uq.edu.au
Hans Mühlhaus
Earth Systems Science Computational Center
The University of Queensland
St. Lucia., QLD 4072
Australia
e-mail: h.muhlhaus@uq.edu.au
Elspeth Thorne
Earth Systems Science Computational Center
The University of Queensland
St. Lucia., QLD 4072
Australia
e-mail: e.thorne@uq.edu.au
Ken Steube
Earth Systems Science Computational Center
The University of Queensland
St. Lucia., QLD 4072
Australia
e-mail: k.steube@uq.edu.au
Numerical Modelling with Python and XML 17