/[escript]/trunk/doc/user/escript.tex
ViewVC logotype

Contents of /trunk/doc/user/escript.tex

Parent Directory Parent Directory | Revision Log Revision Log


Revision 599 - (show annotations)
Fri Mar 17 05:48:59 2006 UTC (14 years, 2 months ago) by gross
File MIME type: application/x-tex
File size: 43543 byte(s)
update on escript function
1
2 % $Id$
3
4 \chapter{The module \escript}
5
6 \declaremodule{extension}{escript}
7 \modulesynopsis{Data manipulation}
8
9 \begin{figure}
10 \includegraphics[width=\textwidth]{figures/EscriptDiagram1.eps}
11 \caption{\label{ESCRIPT DEP}Dependency of Function Spaces. An arrow indicates that a function in the
12 function space at the starting point can be interpreted as a function in the function space of the arrow target.}
13 \end{figure}
14
15 \escript is an extension of Python to handle functions represented by their values on
16 \DataSamplePoints for the geometrical region on which
17 the function is defined. The region as well as the method which is used
18 to interpolate value on the \DataSamplePoints is defined by
19 \Domain class objects. For instance when using
20 the finite element method (FEM) \index{finite element method}
21 \Domain object holds the information about the FEM mesh, eg.
22 a table of nodes and a table of elements. Although \Domain contains
23 the discretization method to be used \escript does not use this information directly.
24 \Domain objects are created from a module which want to make use
25 \escript, e.g. \finley.
26
27 The solution of a PDE is a function of its location in the domain of interest $\Omega$.
28 When solving a partial differential equation \index{partial differential equation} (PDE) using FEM
29 the solution is (piecewise) differentiable but, in general, its gradient
30 is discontinuous. To reflect these different degrees of smoothness different
31 representations of the functions are used. For instance; in FEM
32 the displacement field is represented by its values at the nodes of the mesh, while the
33 strain, which is the symmetric part of the gradient of the displacement field, is stored on the
34 element centers. To be able to classify functions with respect to their smoothness, \escript has the
35 concept of the "function space". A function space is described by a \FunctionSpace object.
36 The following statement generates the object \var{solution_space} which is
37 a \FunctionSpace object and provides access to the function space of
38 PDE solutions on the \Domain \var{mydomain}:
39 \begin{python}
40 solution_space=Solution(mydomain)
41 \end{python}
42 The following generators for function spaces on a \Domain \var{mydomain} are available:
43 \begin{itemize}
44 \item \var{Solution(mydomain)}: solutions of a PDE.
45 \item \var{ReducedSolution(mydomain)}: solutions of a PDE with a reduced smoothness requirement.
46 \item \var{ContinuousFunction(mydomain)}: continuous functions, eg. a temperature distribution.
47 \item \var{Function(mydomain)}: general functions which are not necessarily continuous, eg. a stress field.
48 \item \var{FunctionOnBoundary(mydomain)}: functions on the boundary of the domain, eg. a surface pressure.
49 \item \var{FunctionOnContact0(mydomain)}: functions on side $0$ of the discontinuity.
50 \item \var{FunctionOnContact1(mydomain)}: functions on side $1$ of the discontinuity.
51 \end{itemize}
52 The reduced smoothness for PDE solution is often used to fulfill the Ladyzhenskaya–-Babuska–-Brezzi condition \cite{LBB} when
53 solving saddle point problems \index{saddle point problems}, eg. the Stokes equation.
54 A discontinuity \index{discontinuity} is a region within the domain across which functions may be discontinuous.
55 The location of discontinuity is defined in the \Domain object.
56 \fig{ESCRIPT DEP} shows the dependency between the types of function spaces.
57 The solution of a PDE is a continuous function. Any continuous function can be seen as a general function
58 on the domain and can be restricted to the boundary as well as to any side of the
59 discontinuity (the result will be different depending on
60 which side is chosen). Functions on any side of the
61 discontinuity can be seen as a function on the corresponding other side.
62 A function on the boundary or on one side of
63 the discontinuity cannot be seen as a general function on the domain as there are no values
64 defined for the interior. For most PDE solver libraries
65 the space of the solution and continuous functions is identical, however in some cases, eg.
66 when periodic boundary conditions are used in \finley, a solution
67 fulfils periodic boundary conditions while a continuous function does not have to be periodic.
68
69 The concept of function spaces describes the properties of
70 functions and allows abstraction from the actual representation
71 of the function in the context of a particular application. For instance,
72 in the FEM context a
73 function in the \Function function space
74 is typically represented by its values at the element center,
75 but in a finite difference scheme the edge midpoint of cells is preferred.
76 Using the concept of function spaces
77 allows the user to run the same script on different
78 PDE solver libraries by just changing the creator of the \Domain object.
79 Changing the function space of a particular function
80 will typically lead to a change of its representation.
81 So, when seen as a general function,
82 a continuous function which is typically represented by its values
83 on the node of the FEM mesh or finite difference grid
84 must be interpolated to the element centers or the cell edges,
85 respectively.
86
87 \Data class objects store functions of the location in a domain.
88 The function is represented through its values on \DataSamplePoints where
89 the \DataSamplePoints are chosen according to the function space
90 of the function.
91 \Data class objects are used to define the coefficients
92 of the PDEs to be solved by a PDE solver library
93 and to store the returned solutions.
94
95 The values of the function have a rank which gives the
96 number of indices, and a \Shape defining the range of each index.
97 The rank in \escript is limited to the range $0$ through $4$ and
98 it is assumed that the rank and \Shape is the same for all \DataSamplePoints.
99 The \Shape of a \Data object is a tuple \var{s} of integers. The length
100 of \var{s} is the rank of the \Data object and \var{s[i]} is the maximum
101 value for the \var{i}-th index.
102 For instance, a stress field has rank $2$ and
103 \Shape $(d,d)$ where $d$ is the spatial dimension.
104 The following statement creates the \Data object
105 \var{mydat} representing a
106 continuous function with values
107 of \Shape $(2,3)$ and rank $2$:
108 \begin{python}
109 mydat=Data(value=1,what=ContinuousFunction(myDomain),shape=(2,3))
110 \end{python}
111 The initial value is the constant $1$ for all \DataSamplePoints and
112 all components.
113
114 \Data objects can also be created from any \numarray
115 array or any object, such as a list of floating point numbers,
116 that can be converted into a \numarray.NumArray \Ref{NUMARRAY}.
117 The following two statements
118 create objects which are equivalent to \var{mydat}:
119 \begin{python}
120 mydat1=Data(value=numarray.ones((2,3)),what=ContinuousFunction(myDomain))
121 mydat2=Data(value=[[1,1],[1,1],[1,1]],what=ContinuousFunction(myDomain))
122 \end{python}
123 In the first case the initial value is \var{numarray.ones((2,3))}
124 which generates a $2 \times 3$ matrix as a \numarray.NumArray
125 filled with ones. The \Shape of the created \Data object
126 it taken from the \Shape of the array. In the second
127 case, the creator converts the initial value, which is a list of lists,
128 and converts it into a \numarray.NumArray before creating the actual
129 \Data object.
130
131 For convenience \escript provides creators for the most common types
132 of \Data objects in the following forms (\var{d} defines the
133 spatial dimension):
134 \begin{itemize}
135 \item \var{Scalar(0,Function(mydomain))} is the same as \var{Data(0,Function(myDomain),(,))},
136 e.g a temperature field.
137 \item \var{Vector(0,Function(mydomain))}is the same as \var{Data(0,Function(myDomain),(d))}, e.g
138 a velocity field.
139 \item \var{Tensor(0,Function(mydomain))} is the same as \var{Data(0,Function(myDomain),(d,d))},
140 eg. a stress field.
141 \item \var{Tensor4(0,Function(mydomain))} is the same as \var{Data(0,Function(myDomain),(d,d,d,d))}
142 eg. a Hook tensor field.
143 \end{itemize}
144 Here the initial value is $0$ but any object that can be converted into a \numarray.NumArray and whose \Shape
145 is consistent with \Shape of the \Data object to be created can be used as the initial value.
146
147 \Data objects can be manipulated by applying unitary operations (eg. cos, sin, log)
148 and can be combined by applying binary operations (eg. +, - ,* , /).
149 It is to be emphasized that \escript itself does not handle any spatial dependencies as
150 it does not know how values are interpreted by the processing PDE solver library.
151 However \escript invokes interpolation if this is needed during data manipulations.
152 Typically, this occurs in binary operation when both arguments belong to different
153 function spaces or when data are handed over to a PDE solver library
154 which requires functions to be represented in a particular way.
155
156 The following example shows the usage of {\tt Data} objects: Assume we have a
157 displacement field $u$ and we want to calculate the corresponding stress field
158 $\sigma$ using the linear--elastic isotropic material model
159 \begin{eqnarray}\label{eq: linear elastic stress}
160 \sigma\hackscore {ij}=\lambda u\hackscore {k,k} \delta\hackscore {ij} + \mu ( u\hackscore {i,j} + u\hackscore {j,i})
161 \end{eqnarray}
162 where $\delta\hackscore {ij}$ is the Kronecker symbol and
163 $\lambda$ and $\mu$ are the Lame coefficients. The following function
164 takes the displacement {\tt u} and the Lame coefficients
165 \var{lam} and \var{mu} as arguments and returns the corresponding stress:
166 \begin{python}
167 from esys.escript import *
168 def getStress(u,lam,mu):
169 d=u.getDomain().getDim()
170 g=grad(u)
171 stress=lam*trace(g)*kronecker(d)+mu*(g+transpose(g))
172 return stress
173 \end{python}
174 The variable
175 \var{d} gives the spatial dimension of the
176 domain on which the displacements are defined.
177 \var{kronecker} returns the Kronecker symbol with indexes
178 $i$ and $j$ running from $0$ to \var{d}-1. The call \var{grad(u)} requires
179 the displacement field \var{u} to be in the \var{Solution} or \ContinuousFunction
180 function space. The result \var{g} as well as the returned stress will be in the \Function function space.
181 If \var{u} is available, eg. by solving a PDE, \var{getStress} might be called
182 in the following way:
183 \begin{python}
184 s=getStress(u,1.,2.)
185 \end{python}
186 However \var{getStress} can also be called with \Data objects as values for
187 \var{lam} and \var{mu} which,
188 for instance in the case of a temperature dependency, are calculated by an expression.
189 The following call is equivalent to the previous example:
190 \begin{python}
191 lam=Scalar(1.,ContinuousFunction(mydomain))
192 mu=Scalar(2.,Function(mydomain))
193 s=getStress(u,lam,mu)
194 \end{python}
195 The function \var{lam} belongs to the \ContinuousFunction function space
196 but with \var{g} the function \var{trace(g)} is in the \Function function space.
197 Therefore the evaluation of the product \var{lam*trace(g)} in the stress calculation
198 produces a problem, as both functions are represented differently, eg. in FEM
199 \var{lam} by its values on the node, and in \var{trace(g)} by its values at the element centers.
200 In the case of inconsistent function spaces of arguments in a binary operation, \escript
201 interprets the arguments in the appropriate function space according to the inclusion
202 defined in Table~\ref{ESCRIPT DEP}. In this example that means
203 \escript sees \var{lam} as a function of the \Function function space.
204 In the context of FEM this means the nodal values of
205 \var{lam} are interpolated to the element centers. Behind the scenes
206 \escript calls the appropriate function from the PDE solver library.
207
208 \begin{figure}
209 \includegraphics[width=\textwidth]{figures/EscriptDiagram2.eps}
210 \caption{\label{Figure: tag}Element Tagging. A rectangular mesh over a region with two rock types {\it white} and {\it gray}.
211 The number in each cell refers to the major rock type present in the cell ($1$ for {\it white} and $2$ for {\it gray}).
212 }
213 \end{figure}
214
215 Material parameters such as the Lame coefficients are typically dependent on rock types present in the
216 area of interest. A common technique to handle these kinds of material parameters is "tagging". \fig{Figure: tag}
217 shows an example. In this case two rock types {\it white} and {\it gray} can be found in the domain. The domain
218 is subdivided into triangular shaped cells. Each
219 cell has a tag indicating the rock type predominately found in this cell. Here $1$ is used to indicate
220 rock type {\it white} and $2$ for rock type {\it gray}. The tags are assigned at the time when the cells are generated
221 and stored in the \Domain class object. The following statements show how for the
222 example of \fig{Figure: tag} and the stress calculation discussed before tagged values are used for
223 \var{lam}:
224 \begin{python}
225 lam=Scalar(value=2.,what=Function(mydomain))
226 lam.setTaggedValue(1,30.)
227 lam.setTaggedValue(2,5000.)
228 s=getStress(u,lam,2.)
229 \end{python}
230 In this example \var{lam} is set to $30$ for those cells with tag $1$ and to $5000.$ for those cells
231 with tag $2$. The initial value $2$ of \var{lam} is used as a default value for the case when a tag
232 is encountered which has not been linked with a value. Note that the \var{getStress} method
233 is called without modification. \escript resolves the tags when \var{lam*trace(g)} is calculated.
234
235 The \Data class provides a transparent interface to various data representations and the
236 translations between them. As shown in the example of stress calculation, this allows the user to
237 develop and test algorithms for a simple case (for instance with the Lame coefficients as constants)
238 and then without further modifications of the program code to apply the algorithm in a
239 more complex application (for instance a definition of the Lame coefficients using tags).
240 As described here, there are three ways in which \Data objects are represented internally, constant,
241 tagged, and expanded (other representations will become available in later versions of \escript):
242 In the constant case, if the same value is used at each sample point a single value is stored to save memory and compute time.
243 Any operation on this constant data will only be performed on the single value.
244 In the expanded case, each sample point has an individual value, eg. the solution of a PDE,
245 and the values are stored as a complete array. The tagged case has already been discussed above.
246
247 Values are accessed through a sample reference number. Operations on expanded \Data
248 objects have to be performed for each sample point individually. If tagged values are used values are
249 held in a dictionary. Operations on tagged data require processing the set of tagged values only, rather than
250 processing the value for each individual sample point.
251 \escript allows use of constant, tagged and expanded data in a single expression.
252
253 \section{\Domain class}
254 \begin{classdesc}{Domain}{}
255 A \Domain object is used to describe a geometrical region together with
256 a way of representing functions over this region.
257 The \Domain class provides an abstract access to the domain of \FunctionSpace and \Data objects.
258 \Domain itself has no initialization but implementations of \Domain are
259 instantiated by numerical libraries making use of \Data objects.
260 \end{classdesc}
261 The following methds are available:
262 \begin{methoddesc}[Domain]{getDim}{}
263 returns the spatial dimension of the \Domain.
264 \end{methoddesc}
265
266 \begin{methoddesc}[Domain]{getX}{}
267 returns the locations in the \Domain. The \FunctionSpace of the returned
268 \Data object is chosen by the \Domain implementation. Typically it will be
269 in the \Function.
270 \end{methoddesc}
271
272 \begin{methoddesc}[Domain]{setX}{newX}
273 assigns a new location to the \Domain. \var{newX} has to have \Shape $(d,)$
274 where $d$ is the spatial dimension of the domain. Typically \var{newX} must be
275 in the \ContinuousFunction but the space actually to be used depends on the \Domain implementation.
276 \end{methoddesc}
277
278 \begin{methoddesc}[Domain]{getNormal}{}
279 returns the surface normals on the boundary of the \Domain as \Data object.
280 \end{methoddesc}
281
282 \begin{methoddesc}[Domain]{getSize}{}
283 returns the local sample size, e.g. the element diameter, as \Data object.
284 \end{methoddesc}
285
286 \begin{methoddesc}[Domain]{__eq__}{arg}
287 returns \True of the \Domain \var{arg} describes the same domain. Otherwise
288 \False is returned.
289 \end{methoddesc}
290
291 \begin{methoddesc}[Domain]{__ne__}{arg}
292 returns \True of the \Domain \var{arg} does not describe the same domain.
293 Otherwise \False is returned.
294 \end{methoddesc}
295
296 \begin{methoddesc}[Domain]{__str__}{g}
297 returns string represention of the \Domain.
298 \end{methoddesc}
299
300 \section{\Domain class}
301 \begin{classdesc}{FunctionSpace}{}
302 \FunctionSpace objects are used to define properties of \Data objects, such as continuity. \FunctionSpace objects
303 are instantiated by generator functions. \Data objects in particular \FunctionSpace are
304 represented by their values at \DataSamplePoints which are defined by the type and the \Domain of the
305 \FunctionSpace.
306 \end{classdesc}
307 The following methds are available:
308 \begin{methoddesc}[FunctionSpace]{getDim}{}
309 returns the spatial dimension of the \Domain of the \FunctionSpace.
310 \end{methoddesc}
311
312 \begin{methoddesc}[FunctionSpace]{getX}{}
313 returns the location of the \DataSamplePoints.
314 \end{methoddesc}
315
316 \begin{methoddesc}[FunctionSpace]{getNormal}{}
317 If the domain of functions in the \FunctionSpace
318 is a hypermanifold (e.g. the boundary of a domain)
319 the method returns the outer normal at each of the
320 \DataSamplePoints. Otherwise an exception is raised.
321 \end{methoddesc}
322
323 \begin{methoddesc}[FunctionSpace]{getSize}{}
324 returns a \Data objects measuring the spacing of the \DataSamplePoints.
325 The size may be zero.
326 \end{methoddesc}
327
328 \begin{methoddesc}[FunctionSpace]{getDomain}{}
329 returns the \Domain of the \FunctionSpace.
330 \end{methoddesc}
331
332 \begin{methoddesc}[FunctionSpace]{__eq__}{arg}
333 returns \True of the \Domain \var{arg} describes the same domain. Otherwise
334 \False is returned.
335 \end{methoddesc}
336
337 \begin{methoddesc}[FunctionSpace]{__ne__}{arg}
338 returns \True of the \Domain \var{arg} describes the note same domain.
339 Otherwise \False is returned.
340 \end{methoddesc}
341
342 \begin{methoddesc}[Domain]{__str__}{g}
343 returns string represention of the \Domain.
344 \end{methoddesc}
345
346 The following function provide generators for \FunctionSpace objects:
347 \begin{funcdesc}{Function}{domain}
348 returns the \Function on the \Domain \var{domain}. \Data objects in this type of \Function
349 are defined over the whole geometrical region defined by \var{domain}.
350 \end{funcdesc}
351
352 \begin{funcdesc}{ContinuousFunction}{domain}
353 returns the \ContinuousFunction on the \Domain domain. \Data objects in this type of \Function
354 are defined over the whole geometrical region defined by \var{domain} and assumed to represent
355 a continuous function.
356 \end{funcdesc}
357
358 \begin{funcdesc}{FunctionOnBoundary}{domain}
359 returns the \ContinuousFunction on the \Domain domain. \Data objects in this type of \Function
360 are defined on the boundary of the geometrical region defined by \var{domain}.
361 \end{funcdesc}
362
363 \begin{funcdesc}{FunctionOnContactZero}{domain}
364 returns the \FunctionOnContactZero the \Domain domain. \Data objects in this type of \Function
365 are defined on side 0 of a discontinutiy within the geometrical region defined by \var{domain}.
366 The discontinutiy is defined when \var{domain} is instantiated.
367 \end{funcdesc}
368
369 \begin{funcdesc}{FunctionOnContactOne}{domain}
370 returns the \FunctionOnContactOne on the \Domain domain.
371 \Data objects in this type of \Function
372 are defined on side 1 of a discontinutiy within the geometrical region defined by \var{domain}.
373 The discontinutiy is defined when \var{domain} is instantiated.
374 \end{funcdesc}
375
376 \begin{funcdesc}{Solution}{domain}
377 returns the \SolutionFS on the \Domain domain. \Data objects in this type of \Function
378 are defined on geometrical region defined by \var{domain} and are solutions of
379 partial differential equations \index{partial differential equation}.
380 \end{funcdesc}
381
382 \begin{funcdesc}{ReducedSolution}{domain}
383 returns the \ReducedSolutionFS on the \Domain domain. \Data objects in this type of \Function
384 are defined on geometrical region defined by \var{domain} and are solutions of
385 partial differential equations \index{partial differential equation} with a reduced smoothness
386 for the solution approximation.
387 \end{funcdesc}
388
389 \section{\Data Class}
390 \label{SEC ESCRIPT DATA}
391
392 The following table shows binary and unitary operations that can be applied to
393 \Data objects:
394 \begin{tableii}{l|l}{textrm}{expression}{Description}
395 \lineii{+\var{arg1}} {just \var{arg} \index{+}}
396 \lineii{-\var{arg1}} {swapping the sign\index{-}}
397 \lineii{\var{arg1}+\var{arg2}} {adds \var{arg1} and \var{arg2} \index{+}}
398 \lineii{\var{arg1}*\var{arg2}} {multiplies \var{arg1} and \var{arg2} \index{*}}
399 \lineii{\var{arg1}-\var{arg2}} {difference \var{arg2} from\var{arg2} \index{-}}
400 \lineii{\var{arg1}/\var{arg2}} {ratio \var{arg1} by \var{arg2} \index{/}}
401 \lineii{\var{arg1}**\var{arg2}} {raises \var{arg1} to the power of \var{arg2} \index{**}}
402 \end{tableii}
403 At least one of the arguments \var{arg1} or \var{arg2} must be a
404 \Data object. One of the arguments may be an object that can be
405 converted into a \Data object. If \var{arg1} or \var{arg2} are
406 defined on different \FunctionSpace an attempt is made to embed \var{arg1}
407 into the \FunctionSpace of \var{arg2} or to embed \var{arg2} into
408 the \FunctionSpace of \var{arg1}. Boths arguments must have the same
409 \Shape or one of the arguments my be of rank 0 or \Shape (1,). In the
410 latter case it is assumed that the particular argument is of the same
411 \Shape as the other argument but constant over all components.
412
413 The returned \Data object has the same \Shape and is defined on
414 the \DataSamplePoints as \var{arg1} or \var{arg2}.
415
416 The following table shows the update operations that can be applied to
417 \Data objects:
418 \begin{tableii}{l|l}{textrm}{expression}{Description}
419 \lineii{\var{arg1}+=\var{arg2}} {adds \var{arg1} to \var{arg2} \index{+}}
420 \lineii{\var{arg1}*=\var{arg2}} {multiplies \var{arg1} with \var{arg2} \index{*}}
421 \lineii{\var{arg1}-=\var{arg2}} {subtracts \var{arg2} from\var{arg2} \index{-}}
422 \lineii{\var{arg1}/=\var{arg2}} {divides \var{arg1} by \var{arg2} \index{/}}
423 \end{tableii}
424 \var{arg1} must be a \Data object. \var{arg1} must be a
425 \Data object or an object that can be converted into a
426 \Data object. \var{arg1} must have the same \Shape like
427 \var{arg1} or has rank 0 or \Shape (1,). In the latter case it is
428 assumed that the values of \var{arg1} are constant for all
429 components. \var{arg2} must be defined on the same \DataSamplePoints as
430 \var{arg1} or it must be possible to interpolate \var{arg2} onto the
431 \DataSamplePoints where \var{arg1} is held.
432
433 The \Data class supports getting slices as well as assigning new values to components in an existing
434 \Data object. \index{slicing}
435 The following expression for getting (expression on the right hand side of the
436 equal sign) and setting slices (expression on the left hand side of the
437 equal sign) are valid:
438 \begin{tableiii}{l|ll}{textrm}{rank of \var{arg}}{slicing expression}{\Shape of returned and assigned object}
439 \lineiii{0}{ no slicing } {-}
440 \lineiii{1}{\var{arg[l0:u0]}} {(\var{u0}-\var{l0},)}
441 \lineiii{2}{\var{arg[l0:u0,l1:u1]}} {(\var{u0}-\var{l0},\var{u1}-\var{l1})}
442 \lineiii{3}{\var{arg[l0:u0,l1:u1,l2:u2]} } {(\var{u0}-\var{l0},\var{u1}-\var{l1},\var{u2}-\var{l2})}
443 \lineiii{4}{\var{arg[l0:u0,l1:u1,l2:u2,l3:u3]}} {(\var{u0}-\var{l0},\var{u1}-\var{l1},\var{u2}-\var{l2},\var{u3}-\var{l3})}
444 \end{tableiii}
445 where
446 $0 \le \var{l0} \le \var{u0} \le \var{s[0]}$,
447 $0 \le \var{l1} \le \var{u1} \le \var{s[1]}$,
448 $0 \le \var{l2} \le \var{u2} \le \var{s[2]}$,
449 $0 \le \var{l3} \le \var{u3} \le \var{s[3]}$ and \var{s} the \Shape if \var{arg}.
450 Any of the lower indexes \var{l0}, \var{l1}, \var{l2} and \var{l3} may not be present in which case
451 $0$ is assumed.
452 Any of the upper indexes \var{u0}, \var{u1}, \var{u2} and \var{u3} may not be present in which case
453 \var{s} is assumed. The lower and upper index may be identical, in which case the column and the lower or upper
454 index may be dropped. In the returned or in the object assigned to a slice the corresponding component is dropped,
455 i.e. the rank is reduced by one in comparison to \var{arg}.
456 The following examples show slicing usage:
457 \begin{python}
458 t=Data(1.,(4,4,6,6),Function(mydomain))
459 t[1,1,1,0]=9.
460 s=t[:2,:,2:6,5] # s has rank 3
461 s[:,:,1]=1.
462 t[:2,:2,5,5]=s[2:4,1,:2]
463 \end{python}
464
465 \subsection{Generation of \Data class objects}
466 \begin{classdesc}{Data}{value=0,shape=(,),what=FunctionSpace(),expand=\False}
467 creates a \Data object with \Shape \var{shape} in the \FunctionSpace \var{what}.
468 The values at all \DataSamplePoints are set to the double value \var{value}. If \var{expanded} is \True
469 the \Data object is represented in expanded from.
470 \end{classdesc}
471
472 \begin{classdesc}{Data}{value,what=FunctionSpace(),expand=\False}
473 creates a \Data object in the \FunctionSpace \var{what}.
474 The value for each \DataSamplePoints is set to \numarray, \Data object \var{value} or a dictionary of
475 \numarray or floating point numbers. In the latter case the keys muts be integers and are used
476 as tags.
477 The \Shape of the returned object is equal to the \Shape of \var{value}. If \var{expanded} is \True
478 the \Data object is represented in expanded from.
479 \end{classdesc}
480
481 \begin{classdesc}{Data}{}
482 creates an \EmptyData object. The \EmptyData object is used to indicate that an argument is not present
483 where a \Data object is required.
484 \end{classdesc}
485
486 \begin{funcdesc}{Scalar}{value=0.,what=escript::FunctionSpace(),expand=\False}
487 returns a \Data object of rank 0 in the \FunctionSpace \var{what}.
488 Values are initialed with the double \var{value}. If \var{expanded} is \True
489 the \Data object is represented in expanded from.
490 \end{funcdesc}
491
492 \begin{funcdesc}{Vector}{value=0.,what=escript::FunctionSpace(),expand=\False}
493 returns a \Data object of \Shape \var{(d,)} in the \FunctionSpace \var{what}
494 where \var{d} is the spatial dimension of the \Domain of \var{what}.
495 Values are initialed with the double \var{value}. If \var{expanded} is \True
496 the \Data object is represented in expanded from.
497 \end{funcdesc}
498
499 \begin{funcdesc}{Tensor}{value=0.,what=escript::FunctionSpace(),expand=\False}
500 returns a \Data object of \Shape \var{(d,d)} in the \FunctionSpace \var{what}
501 where \var{d} is the spatial dimension of the \Domain of \var{what}.
502 Values are initialed with the double \var{value}. If \var{expanded} is \True
503 the \Data object is represented in expanded from.
504 \end{funcdesc}
505
506 \begin{funcdesc}{Tensor3}{value=0.,what=escript::FunctionSpace(),expand=\False}
507 returns a \Data object of \Shape \var{(d,d,d)} in the \FunctionSpace \var{what}
508 where \var{d} is the spatial dimension of the \Domain of \var{what}.
509 Values are initialed with the double \var{value}. If \var{expanded} is \True
510 the \Data object is re\var{arg}presented in expanded from.
511 \end{funcdesc}
512
513 \begin{funcdesc}{Tensor4}{value=0.,what=escript::FunctionSpace(),expand=\False}
514 returns a \Data object of \Shape \var{(d,d,d,d)} in the \FunctionSpace \var{what}
515 where \var{d} is the spatial dimension of the \Domain of \var{what}.
516 Values are initialed with the double \var{value}. If \var{expanded} is \True
517 the \Data object is represented in expanded from.
518 \end{funcdesc}
519
520 \subsection{\Data class methods}
521 This is a list of frequently used methods of the
522 \Data class. A complete list can be fond on \ReferenceGuide.
523 \begin{methoddesc}[Data]{getFunctionSpace}{}
524 returns the \FunctionSpace of the object.
525 \end{methoddesc}
526
527 \begin{methoddesc}[Data]{getDomain}{}
528 returns the \Domain of the object.
529 \end{methoddesc}
530
531 \begin{methoddesc}[Data]{getShape}{}
532 returns the \Shape of the object as a \class{tuple} of
533 integers.
534 \end{methoddesc}
535
536 \begin{methoddesc}[Data]{getRank}{}
537 returns the rank of the data on each data point. \index{rank}
538 \end{methoddesc}
539
540 \begin{methoddesc}[Data]{isEmpty}{}
541 returns \True id the \Data object is the \EmptyData object.
542 Otherwise \False is returned.
543 \end{methoddesc}
544
545 \begin{methoddesc}[Data]{setTaggedValue}{tag,value}
546 assigns the \var{value} to all \DataSamplePoints which have the tag
547 \var{tag}. \var{value} must be an object of class
548 \class{numarray.NumArray} or must be convertible into a
549 \class{numarray.NumArray} object. \var{value} (or the corresponding
550 \class{numarray.NumArray} object) must be of rank $0$ or must have the
551 same rank like the object.
552 If a value has already be defined for tag \var{tag} within the object
553 it is overwritten by the new \var{value}. If the object is expanded,
554 the value assigned to \DataSamplePoints with tag \var{tag} is replaced by
555 \var{value}.
556 \end{methoddesc}
557
558 \begin{methoddesc}[Data]{__str__}{}
559 returns a string representation of the object.
560 \end{methoddesc}
561
562 \section{Functions of \Data class objects}
563 This section lists the most important functions for \Data class objects \var{a}.
564 A complete list and a more detailed description of the functionality can be fond on \ReferenceGuide.
565 \begin{funcdesc}{saveVTK}{filename,**kwdata}
566 writes \Data defined by keywords in the file with \var{filename} using the
567 vtk file format \VTK file format. The key word is used as an identifier. The statement
568 \begin{python}
569 saveVTK("out.xml",temperature=T,velocity=v)
570 \end{python}
571 will write the scalar \var{T} as \var{temperature} and the vector \var{v} as \var{velocity} into the
572 file \file{out.xml}. Restrictions on the allowed combinations of \FunctionSpace apply.
573 \end{funcdesc}
574 \begin{funcdesc}{saveDX}{filename,**kwdata}
575 writes \Data defined by keywords in the file with \var{filename} using the
576 vtk file format \OpenDX file format. The key word is used as an identifier. The statement
577 \begin{python}
578 saveDX("out.dx",temperature=T,velocity=v)
579 \end{python}
580 will write the scalar \var{T} as \var{temperature} and the vector \var{v} as \var{velocity} into the
581 file \file{out.dx}. Restrictions on the allowed combinations of \FunctionSpace apply.
582 \end{funcdesc}
583 \begin{funcdesc}{kronecker}{d}
584 returns a \RankTwo \Data object in \FunctionSpace \var{d} such that
585 \begin{equation}
586 \code{kronecker(d)}\left[ i,j\right] = \left\{
587 \begin{array}{cc}
588 1 & \mbox{ if } i=j \\
589 0 & \mbox{ otherwise }
590 \end{array}
591 \right.
592 \end{equation}
593 If \var{d} is an integer a $(d,d)$ \numarray array is returned.
594 \end{funcdesc}
595 \begin{funcdesc}{identityTensor}{d}
596 returns a \RankTwo \Data object in \FunctionSpace \var{d} such that
597 \begin{equation}
598 \code{identityTensor(d)}\left[ i,j\right] = \left\{
599 \begin{array}{cc}
600 1 & \mbox{ if } i=j \\
601 0 & \mbox{ otherwise }
602 \end{array}
603 \right.
604 \end{equation}
605 If \var{d} is an integer a $(d,d)$ \numarray array is returned.
606 \end{funcdesc}
607 \begin{funcdesc}{identityTensor4}{d}
608 returns a \RankFour \Data object in \FunctionSpace \var{d} such that
609 \begin{equation}
610 \code{identityTensor(d)}\left[ i,j,k,l\right] = \left\{
611 \begin{array}{cc}
612 1 & \mbox{ if } i=k \mbox{ and } j=l\\
613 0 & \mbox{ otherwise }
614 \end{array}
615 \right.
616 \end{equation}
617 If \var{d} is an integer a $(d,d,d,d)$ \numarray array is returned.
618 \end{funcdesc}
619 \begin{funcdesc}{unitVector}{i,d}
620 returns a \RankOne \Data object in \FunctionSpace \var{d} such that
621 \begin{equation}
622 \code{identityTensor(d)}\left[ j \right] = \left\{
623 \begin{array}{cc}
624 1 & \mbox{ if } j=i\\
625 0 & \mbox{ otherwise }
626 \end{array}
627 \right.
628 \end{equation}
629 If \var{d} is an integer a $(d,)$ \numarray array is returned.
630
631 \end{funcdesc}
632
633 \begin{funcdesc}{Lsup}{a}
634 returns the $L^{sup}$ norm of \var{arg}. This is the maximum of the absolute values
635 over all components and all \DataSamplePoints of \var{a}.
636 \end{funcdesc}
637
638 \begin{funcdesc}{sup}{a}
639 returns the maximum value over all components and all \DataSamplePoints of \var{a}.
640 \end{funcdesc}
641
642 \begin{funcdesc}{inf}{a}
643 returns the minimum value over all components and all \DataSamplePoints of \var{a}
644 \end{funcdesc}
645
646 \begin{funcdesc}{sin}{a}
647 applies sine function to \var{a}.
648 \end{funcdesc}
649
650 \begin{funcdesc}{cos}{a}
651 applies cosine function to \var{a}.
652 \end{funcdesc}
653
654 \begin{funcdesc}{tan}{a}
655 applies tangent function to \var{a}.
656 \end{funcdesc}
657
658 \begin{funcdesc}{asin}{a}
659 applies arc (inverse) sine function to \var{a}.
660 \end{funcdesc}
661
662 \begin{funcdesc}{acos}{a}
663 applies arc (inverse) cosine function to \var{a}.
664 \end{funcdesc}
665
666 \begin{funcdesc}{atan}{a}
667 applies arc (inverse) tangent function to \var{a}.
668 \end{funcdesc}
669
670 \begin{funcdesc}{sinh}{a}
671 applies hyperbolic sine function to \var{a}.
672 \end{funcdesc}
673
674 \begin{funcdesc}{cosh}{a}
675 applies hyperbolic cosine function to \var{a}.
676 \end{funcdesc}
677
678 \begin{funcdesc}{tanh}{a}
679 applies hyperbolic tangent function to \var{a}.
680 \end{funcdesc}
681
682 \begin{funcdesc}{asinh}{a}
683 applies arc (inverse) hyperbolic sine function to \var{a}.
684 \end{funcdesc}
685
686 \begin{funcdesc}{acosh}{a}
687 applies arc (inverse) hyperbolic cosine function to \var{a}.
688 \end{funcdesc}
689
690 \begin{funcdesc}{atanh}{a}
691 applies arc (inverse) hyperbolic tangent function to \var{a}.
692 \end{funcdesc}
693
694 \begin{funcdesc}{exp}{a}
695 applies exponential function to \var{a}.
696 \end{funcdesc}
697
698 \begin{funcdesc}{sqrt}{a}
699 applies square root function to \var{a}.
700 \end{funcdesc}
701
702 \begin{funcdesc}{log}{a}
703 applies the natural logarithm to \var{a}.
704 \end{funcdesc}
705
706 \begin{funcdesc}{log10}{a}
707 applies the base-$10$ logarithm to \var{a}.
708 \end{funcdesc}
709
710 \begin{funcdesc}{sign}{a}
711 applies the sign function to \var{a}, that is $1$ where \var{a} is positive,
712 $-1$ where \var{a} is negative and $0$ otherwise.
713 \end{funcdesc}
714
715 \begin{funcdesc}{wherePositive}{a}
716 returns a function which is $1$ where \var{a} is positive and $0$ otherwise.
717 \end{funcdesc}
718
719 \begin{funcdesc}{whereNegative}{a}
720 returns a function which is $1$ where \var{a} is negative and $0$ otherwise.
721 \end{funcdesc}
722
723 \begin{funcdesc}{whereNonNegative}{a}
724 returns a function which is $1$ where \var{a} is non--negative and $0$ otherwise.
725 \end{funcdesc}
726
727 \begin{funcdesc}{whereNonPositive}{a}
728 returns a function which is $1$ where \var{a} is non--positive and $0$ otherwise.
729 \end{funcdesc}
730
731 \begin{funcdesc}{whereZero}{a\optional{, tol=0.}}
732 returns a function which is $1$ where \var{a} equals zero with tolerance \var{tol} and $0$ otherwise.
733 \end{funcdesc}
734
735 \begin{funcdesc}{whereNonZero}{a\optional{, tol=0.}}
736 returns a function which is $1$ where \var{a} different from zero with tolerance \var{tol} and $0$ otherwise.
737 \end{funcdesc}
738
739 \begin{funcdesc}{minval}{a}
740 returns at each \DataSamplePoints the minumum value over all components.
741 \end{funcdesc}
742
743 \begin{funcdesc}{maxval}{a}
744 returns at each \DataSamplePoints the maximum value over all components.
745 \end{funcdesc}
746
747 \begin{funcdesc}{length}{a}
748 returns at Euclidean norm at each \DataSamplePoints. For a \RankFour function \var{a} this is
749 \begin{equation}
750 \code{length(a)}=\sqrt{\sum\hackscore{ijkl} \var{a} \left[i,j,k,l\right]^2}
751 \end{equation}
752 \end{funcdesc}
753 \begin{funcdesc}{trace}{a\optional{,axis_offset=0}}
754 returns the trace of \var{a}. This is the sum over components \var{axis_offset} and \var{axis_offset+1} with the same index. For instance in the
755 case of a \RankTwo function and this is
756 \begin{equation}
757 \code{trace(a)}=\sum\hackscore{i} \var{a} \left[i,i\right]
758 \end{equation}
759 and for a \RankFour function and \code{axis_offset=1} this is
760 \begin{equation}
761 \code{trace(a,1)}\left[i,j\right]=\sum\hackscore{k} \var{a} \left[i,k,k,j\right]
762 \end{equation}
763 \end{funcdesc}
764 \begin{funcdesc}{transpose}{a\optional{, axis_offset=None}}
765 returns the transpose of \var{a}. This swaps the first \var{axis_offset} components of \var{a} with the rest. If \var{axis_offset} is not
766 present \code{int(r/2)} is used where \var{r} is the rank of \var{a}.
767 the sum over components \var{axis_offset} and \var{axis_offset+1} with the same index. For instance in the
768 case of a \RankTwo function and this is
769 \begin{equation}
770 \code{transpose(a)}\left[i,j\right]=\var{a} \left[j,i\right]
771 \end{equation}
772 and for a \RankFour function and \code{axis_offset=1} this is
773 \begin{equation}
774 \code{transpose(a,1)}\left[i,j,k,l\right]=\var{a} \left[j,k,l,i\right]
775 \end{equation}
776 \end{funcdesc}
777 \begin{funcdesc}{symmetric}{a}
778 returns the symmetric part of \var{a}. This is \code{(a+transpose(a))/2}.
779 \end{funcdesc}
780 \begin{funcdesc}{nonsymmetric}{a}
781 returns the non--symmetric part of \var{a}. This is \code{(a-transpose(a))/2}.
782 \end{funcdesc}
783 \begin{funcdesc}{inverse}{a}
784 return the inverse of \var{a}. This is
785 \begin{equation}
786 \code{matrixmult(inverse(a),a)=kronecker(d)}
787 \end{equation}
788 if \var{a} has shape \code{(d,d)}. The current implementation is restricted to arguments of shape
789 \code{(2,2)} and \code{(3,3)}.
790 \end{funcdesc}
791 \begin{funcdesc}{eigenvalues}{a}
792 return the eigenvalues of \var{a}. This is
793 \begin{equation}
794 \code{matrixmult(a,V)=e[i]*V}
795 \end{equation}
796 where \code{e=eigenvalues(a)} and \var{V} is suitable non--zero vector \var{V}.
797 The eigenvalues are ordered in increasing size.
798 The argument \var{a} has to be the symmetric, ie. \code{a=symmetric(a)}.
799 The current implementation is restricted to arguments of shape
800 \code{(2,2)} and \code{(3,3)}.
801 \end{funcdesc}
802 \begin{funcdesc}{eigenvalues_and_eigenvectors}{a}
803 return the eigenvalues and eigenvectors of \var{a}. This is
804 \begin{equation}
805 \code{matrixmult(a,V[:,i])=e[i]*V[:,i]}
806 \end{equation}
807 where \code{e,V=eigenvalues_and_eigenvectors(a)}. The eigenvectors \var{V} are orthogonal and normalized, ie.
808 \begin{equation}
809 \code{matrixmult(transpose(V),V)=kronecker(d)}
810 \end{equation}
811 if \var{a} has shape \code{(d,d)}. The eigenvalues are ordered in increasing size.
812 The argument \var{a} has to be the symmetric, ie. \code{a=symmetric(a)}.
813 The current implementation is restricted to arguments of shape
814 \code{(2,2)} and \code{(3,3)}.
815 \end{funcdesc}
816 \begin{funcdesc}{maximum}{*a}
817 returns the maximum value over all arguments at all \DataSamplePoints and for each component.
818 For instance
819 \begin{equation}
820 \code{maximum(a0,a1)}\left[i,j\right]=max(\var{a0} \left[i,j\right],\var{a1} \left[i,j\right])
821 \end{equation}
822 at all \DataSamplePoints.
823 \end{funcdesc}
824 \begin{funcdesc}{minimum}{*a}
825 returns the minimum value over all arguments at all \DataSamplePoints and for each component.
826 For instance
827 \begin{equation}
828 \code{minimum(a0,a1)}\left[i,j\right]=min(\var{a0} \left[i,j\right],\var{a1} \left[i,j\right])
829 \end{equation}
830 at all \DataSamplePoints.
831 \end{funcdesc}
832
833 \begin{funcdesc}{clip}{a\optional{, minval=0.}\optional{, maxval=1.}}
834 cuts back \var{a} into the range between \var{minval} and \var{maxval}. A value in the returned object equals
835 \var{minval} if the corresponding value of \var{a} is less than \var{minval}, equals \var{maxval} if the
836 corresponding value of \var{a} is greater than \var{maxval}
837 or corresponding value of \var{a} otherwise.
838 \end{funcdesc}
839 \begin{funcdesc}{inner}{a0,a1}
840 returns the inner product of \var{a0} and \var{a1}. For instance in the
841 case of \RankTwo arguments and this is
842 \begin{equation}
843 \code{inner(a)}=\sum\hackscore{ij}\var{a0} \left[j,i\right] \cdot \var{a1} \left[j,i\right]
844 \end{equation}
845 and for a \RankFour arguments this is
846 \begin{equation}
847 \code{inner(a)}=\sum\hackscore{ijkl}\var{a0} \left[i,j,k,l\right] \cdot \var{a1} \left[j,i,k,l\right]
848 \end{equation}
849 \end{funcdesc}
850 \begin{funcdesc}{matrixmult}{a0,a1}
851 returns the matrix product of \var{a0} and \var{a1}. If \var{a1} is \RankOne this is
852 \begin{equation}
853 \code{matrixmult(a)}\left[i\right]=\sum\hackscore{k}\var{a0} \cdot \left[i,k\right]\var{a1} \left[k\right]
854 \end{equation}
855 and if \var{a1} is \RankTwo this is
856 \begin{equation}
857 \code{matrixmult(a)}\left[i,j\right]=\sum\hackscore{k}\var{a0} \cdot \left[i,k\right]\var{a1} \left[k,j\right]
858 \end{equation}
859 \end{funcdesc}
860 \begin{funcdesc}{outer}{a0,a1}
861 returns the outer product of \var{a0} and \var{a1}. For instance if \var{a0} and \var{a1} both are \RankOne then
862 \begin{equation}
863 \code{outer(a)}\left[i,j\right]=\var{a0} \left[i\right] \cdot \var{a1}\left[j\right]
864 \end{equation}
865 and if \var{a0} is \RankOne and \var{a1} is \RankThree
866 \begin{equation}
867 \code{outer(a)}\left[i,j,k\right]=\var{a0} \left[i\right] \cdot \var{a1}\left[j,k\right]
868 \end{equation}
869 \end{funcdesc}
870 \begin{funcdesc}{tensormult}{a0,a1}
871 returns the tensor product of \var{a0} and \var{a1}. If \var{a1} is \RankTwo this is
872 \begin{equation}
873 \code{tensormult(a)}\left[i,j\right]=\sum\hackscore{kl}\var{a0}\left[i,j,k,l\right] \cdot \var{a1} \left[k,l\right]
874 \end{equation}
875 and if \var{a1} is \RankFour this is
876 \begin{equation}
877 \code{tensormult(a)}\left[i,j,k,l\right]=\sum\hackscore{mn}\var{a0} \left[i,j,m,n\right] \cdot \var{a1} \left[m,n,k,l\right]
878 \end{equation}
879 \end{funcdesc}
880 \begin{funcdesc}{grad}{a\optional{, where=None}}
881 returns the gradient of \var{a}. If \var{where} is present the gradient will be calculated in \FunctionSpace \var{where} otherwise a
882 default \FunctionSpace is used. In case that \var{a} has \RankTwo one has
883 \begin{equation}
884 \code{grad(a)}\left[i,j,k\right]=\frac{\partial \var{a} \left[i,j\right]}{\partial x\hackscore{k}}
885 \end{equation}
886 \end{funcdesc}
887 \begin{funcdesc}{integrate}{a\optional{ ,where=None}}
888 returns the integral of \var{a} where the domain of integration is defined by the \FunctionSpace of \var{a}. If \var{where} is
889 present the argument is interpolated into \FunctionSpace \var{where} before integration. For instance in the case of
890 a \RankTwo argument in \ContinuousFunction it is
891 \begin{equation}
892 \code{integrate(a)}\left[i,j\right]=\int\hackscore{\Omega}\var{a} \left[i,j\right] \; d\Omega
893 \end{equation}
894 where $\Omega$ is the spatial domain and $d\Omega$ volume integration. To integrate over the boundary of the domain one uses
895 \begin{equation}
896 \code{integrate(a,where=FunctionOnBoundary(a.getDomain))}\left[i,j\right]=\int\hackscore{\partial \Omega} a\left[i,j\right] \; ds
897 \end{equation}
898 where $\partial \Omega$ is the surface of the spatial domain and $ds$ area or line integration.
899 \end{funcdesc}
900 \begin{funcdesc}{interpolate}{a,where}
901 interpolates argument \var{a} into the \FunctionSpace \var{where}.
902 \end{funcdesc}
903 \begin{funcdesc}{div}{a\optional{ ,where=None}}
904 returns the divergence of \var{a}. This
905 \begin{equation}
906 \code{div(a)}=trace(grad(a),where)
907 \end{equation}
908 \end{funcdesc}
909 \begin{funcdesc}{jump}{a\optional{ ,domain=None}}
910 returns the jump of \var{a} over the discontinuity in its domain or if \Domain \var{domain} is present
911 in \var{domain}.
912 \begin{equation}
913 \code{jump(a)}=interpolate(a,FunctionOnContactOne(domain))-interpolate(a,FunctionOnContactZero(domain))
914 \end{equation}
915 \end{funcdesc}
916 \begin{funcdesc}{L2}{a}
917 returns the $L^2$-norm of \var{a} in its function space. This is
918 \begin{equation}
919 \code{L2(a)}=integrate(length(a)^2) \; .
920 \end{equation}
921 \end{funcdesc}
922
923 \section{\Operator Class}
924 The \Operator class provides an abstract access to operators build
925 within the \LinearPDE class. \Operator objects are created
926 when a PDE is handed over to a PDE solver library and handled
927 by the \LinearPDE class defining the PDE. The user can gain access
928 to the \Operator of a \LinearPDE object through the \var{getOperator}
929 method.
930
931 \begin{classdesc}{Operator}{}
932 creates an empty \Operator object.
933 \end{classdesc}
934
935 \begin{methoddesc}[Operator]{isEmpty}{fileName}
936 returns \True is the object is empty. Otherwise \True is returned.
937 \end{methoddesc}
938
939 \begin{methoddesc}[Operator]{setValue}{value}
940 resets all entires in the obeject representation to \var{value}
941 \end{methoddesc}
942
943 \begin{methoddesc}[Operator]{solves}{rhs}
944 solves the operator equation with right hand side \var{rhs}
945 \end{methoddesc}
946
947 \begin{methoddesc}[Operator]{of}{u}
948 applies the operator to the \Data object \var{u}
949 \end{methoddesc}
950
951 \begin{methoddesc}[Operator]{saveMM}{fileName}
952 saves the object to a matrix market format file of name
953 \var{fileName}, see
954 \ulink{maths.nist.gov/MatrixMarket}{\url{http://maths.nist.gov/MatrixMarket}}.
955 \index{Matrix Market}
956 \end{methoddesc}
957

Properties

Name Value
svn:eol-style native
svn:keywords Author Date Id Revision

  ViewVC Help
Powered by ViewVC 1.1.26