GeMA
The GeMA main application
III - Simulation Files

A GeMA simulation file is composed of a set of declarations that together will provide information about all the objects that form a GeMA simulation. These include model data objects (state variables, meshes, boundary conditions, user functions, and property sets), detailed in sections IV - Model data 1 and V - Model data 2, solution method objects (physics, numeric solvers and the orchestration script), detailed in section VI - Solution method and results monitor objects, detailed in the section IX - Results monitor.

These declarations reside in a single text file with a rather plain syntax. As an example, the file line below will declare that 'T' is a state variable whose values are expressed in degrees Celsius.

StateVar{id = 'T', description = 'Temperature', unit = 'degC'}

One can easily write simulation files regarding them as simple text files, but knowing that in fact they really are one big script written in the Lua language can open several opportunities for those brave enough, enabling, for example, model parameterization or dynamically creation of meshes. Since Lua is a full programming language, there are really not many limits imposed as the simulation model is loaded by being run as a script.

There is no need to learn the Lua language to follow this tutorial or to create simulation files, although that is extremely interesting for those who want to create advanced models. In general, the syntax is straight forward enough and the tutorial will try to cover the basics whenever needed. If you do want to learn more about Lua, the language reference manual is both very informative and concise. The GeMA framework uses Lua version 5.2, and its manual can be found here. There is also the excellent Programming in Lua book, by the language authors.

More commonly, the full set of declarations will be split into several text files, each one corresponding to one of the three main components of the simulation: model data, solution method, and results monitor, plus a master file to group the others. The "master file" of our simulation example, described on section II - Example problem, is given below.

-- Simulation metadata
Simulation
{
name = 'Conduction test',
modelVersion = '1.0',
description = 'A simple heat conduction model for a square plate with different\n'..
'prescribed border temperatures. The plate is discretized in triangle elements.\n'..
'Reference: "Fundamentals of the Finite Element Method for Heat and Fluid Flow"\n'..
' Lewis et al., example 5.2.1'
}
-- Load model data an solution method
dofile('$SIMULATIONDIR/$SIMULATIONNAME_model.lua')
dofile('$SIMULATIONDIR/$SIMULATIONNAME_solution.lua')

On this script, the Simulation declaration defines some metadata about our example simulation. It is followed by two calls to the dofile() function. This is a Lua function used to load other files, much like an #include in C, and allows us to split our model into several files as discussed before.

The dofile() function receives as parameter the name of the file to be loaded. The $SIMULATIONDIR and $SIMULATIONNAME macros are expanded by GeMA onto the path and name of the current "master file", so if the master file is called "cond.lua" and resides in the "c:\temp" directory, the first loaded file will be named "c:/temp/cond_model.lua" and the second "c:/temp/cond_solution.lua". Those files will, respectively, contain the object declarations forming the model data and the solution method. In this example, no result monitor declarations are loaded (those are optional).

For those new to Lua, comments begin with "--" and run until the end of the line, so lines 1 and 11 in our example are comments. Character string values can be enclosed either in single quotes ('a string') or in double quotes ("another string"). This makes it easy to create a string with embedded quotes. The ".." operator found at the end of lines 5, 6 and 7 is a simple string concatenation operator used here to join several text lines.

For those already familiar with Lua, who might be asking themselves how a statement like StateVar{ ... } or Simulation{ ... } is valid Lua syntax, those constructs work since StateVar and Simulation are predefined functions that receive a table as argument. Those functions will check the table syntax and store it in the model data structure.

Tables are Lua's sole data structure component. Each table is delimited by curly braces and stores a set of pairs composed of a key and a value. Keys and values can be any language supported type, but in our context, the relevant ones are numeric and string keys and numeric, string, boolean, functions and table values. A value can also be equal to nil, a special value that means "nothing" or "empty" (much like a NULL pointer in C). When a table has a string key, this entry is often called a table field. In the example, the table passed to the Simulation function has three fields, name, modelVersion and description, all of them storing string values. Since tables are used a lot in our model definitions, the code below shows some more table examples and also how we can access table values.

-- Table examples
--
-- In the example below, myVar1 stores a reference to a table that contains four fields.
-- Field 'a' contains the number 3.14 (all numbers are real values). Field 'b' contains the
-- boolean value true and field 'c' contains a string. Field 'd' contains a function that
-- receives as parameters two numbers and returs their sum.
--
myVar1 = { a = 3.14, b = true, c = 'my string', d = function(x, y) return x + y end }
--
-- In this other example, myVar2 now references a table that has three numeric values associated
-- to the numeric keys 1, 2 and 3. When building a table, if a field name is not given, the key
-- will be the next integer index starting at 1.
--
myVar2 = { 10, 20, 30 }
--
-- Now we see an example where a table stores other tables. It also shows that fields and
-- numeric keys can be freely mixed. On this tables, indices 1 and 2 are each a subtable with
-- three values, while the field n stores the number 2.
--
myVar3 = { n = 2, {10, 20, 30}, {40, 50, 60} }
--
-- Table fields are accessed with a dot between the table name and the field. Numeric values are
-- accessed with an array syntax, using []. Fileds can also be accessed through the [] syntax.
--
print(myVar1.a) -- Will print '3.14'
print(myVar1.b) -- Will print 'true'
print(myVar1.d(2, 3)) -- Will call the function stored in field 'd' and print the result '5'
print(myVar2[1], myVar2[3]) -- Will print '10 30' (the print function accepts multiple arguments)
print(myVar3.n) -- Will print '2'
print(myVar3['n']) -- Will also print '2'. Notice the set of quotes around 'n'
print(myVar3[1]) -- Will print 'table' followed by a memory addres since myVar3[1] is a sub-table value
print(myVar3[1][2]) -- Will print '20', the value at the second key on the first sub-table

Go to the next section, previous section or return to the index.