Skip to content

benchmarks

Ondrej Meca edited this page Mar 15, 2021 · 2 revisions

The benchmarks directory contains a basic set of examples for integrity testing of both mesio and espreso libraries. All tests are executed daily for the 'master' branch and if all tests pass, the branch is published to the 'release' repository on github. Hence, the github repository always contains a checked version.

Run automatic testing

Testing is based on tool nose. One can start all tests from benchmarks directory by the following command:

$ nosetests -v benchmarks

You can also specify an arbitrary sub-directory to restrict testing to a particular set only. Currently, there are the following sets:

  • advectionDiffusion2D, advectionDiffusion3D - testing of the heat transfer module with translation motions (it generates non-symmetric matrices for linear solver)
  • diffusion2D, diffusion3D - testing of the heat transfer module (it generates symmetric matrices for linear solver)
  • linearElasticity2D, linearElasticity3D - testing of the structural mechanics module
  • contact - testing of searching for a contact interface among mesh bodies
  • dummy - really simple (and fast) tests of the library
  • feti4i - testing of the espreso API
  • fetisolver - exhausting testing of the FETI solver (Cartesian product all parameters)
  • input - testing of the mesio input module (loader and parsers)
  • output - testing of the mesio output module

Create a new test

Whenever you implement a new feature, you should create tests for it! Usually, adding of a test include these steps:

  1. Create an ECF file with a new feature (usually the ECF file that you created during development)
  2. Run espreso with the ECF to produce output logs (with monitors that sufficiently check your feature)
  3. Create a new directory within an appropriate directory from the list above
  4. Copy the ECF file and output logs into the created directory
  5. Create file tested.py in the directory and write the test (see examples below)
Example 1: test mesio with new (hypothetical) parameter FILTER

Let we have an Ansys CDB database stored in cube.dat and configuration file conf.ecf that applies a filter to the loaded geometry according to parameter FILTER with possible values HEXA, TETRA, PRISMA, and PYRAMID. Since the filter parameter is an input parameter, we create directory filter in benchmarks/input/ and copy files cube.dat and conf.ecf into this directory. Then, we edit parameter FILTER to value [ARG0] in the conf.ecf configuration file. It allows reading FILTER's value as the first command-line argument. Hence, it is possible to run mesio e.g. with FILTER=HEXA in the following way:

$ mesio -c conf.ecf HEXA

Now, we have to produce output logs for all valid FILTER values. Since the correctness of the filtration will be checked according to the output log, we have to run mesio with the additional parameter that allows later parsing:

$ mesio -c conf.ecf HEXA --OUTPUT::LOGGER=PARSER

Since different filter settings can produce different mesh parameters, we run mesio with all values and store particular logs as HEXA.log, TETRA.log, PRISMA.log, and PYRAMID.log into the directory with our test.

At the end, we create files __init__.py (this file has to be put to all sub-directories inside the benchmarks directory) and tested.py. The init file is used during traversing the benchmarks directory and has to occur in all benchmarks's subdirectories (you can use this file for setup and teardown functions). File tested.py contains functions with tests. The following code shows a possible content of this file:

import os
from nose.tools import istest
from estest import ESPRESOTest

def setup():
    ESPRESOTest.path = os.path.dirname(__file__) # test will be executed from this directory
    ESPRESOTest.args = [ "filter" ] # test has 1 command line argument

def teardown():
    ESPRESOTest.clean() # remove all files generated by this test

@istest
def by(): # function does not start with 'test' -> use nose decorator 'istest'
    for processes in range(1, 16):
        for filter in [ "HEXA", "TETRA", "PRISMA", "PYRAMID" ]:
            yield run, processes, filter # call test with parameters 'processes' and 'filter'

def run(processes, filter):
    ESPRESOTest.processes = processes
    ESPRESOTest.args[0] = filter
    log = ESPRESOTest.run() # run test and store produced log
    ESPRESOTest.compare_mesh(".".join([filter, "log"], log) # compare produced and stored logs

The test utilizes ESPRESOTest class defined in benchmarks/estest.py and the ability of the nose tool to generate the same test with several parameters. The above file generates tests for FILTER = { HEXA, TETRA, PRISMA, PYRAMID }. Each filter value will be tested with the number of MPI processes from range <1, 16>.

Example 2: test espreso with new (hypothetical) boundary condition FOO

Let we have an Ansys CDB database stored in cube.dat and configuration file conf.ecf with boundary condition FOO defined for the heat transfer module. We create directory foo in benchmarks/diffusion3D/simple and copy files cube.dat and conf.ecf into this directory. Since the boundary condition is not dependent on any parameter, it is sufficient to run espreso at once and store produced conf.emr to the test directory. Similarly to the previous example, we create files __init__.py and tested.py with the following content (since the test is performed for different solvers and methods, both parameters should be set to [ARG0] and [ARG1] in the configuration file):

import os
from nose.tools import istest
from estest import ESPRESOTest

def setup():
    ESPRESOTest.path = os.path.dirname(__file__) # test will be executed from this directory
    ESPRESOTest.args = [ "solver", "method" ] # test has 2 command line argument

def teardown():
    ESPRESOTest.clean() # remove all files generated by this test

@istest
def by(): # function does not start with 'test' -> use nose decorator 'istest'
    for processes in range(1, 16):
        yield run, "HYPRE", "0"
        yield run, "MKLPDSS", "0"
        yield run, "FETI", "TOTAL_FETI"
        yield run, "FETI", "HYBRID_FETI"

def run(solver, method):
    ESPRESOTest.args[0] = solver
    ESPRESOTest.args[1] = method
    ESPRESOTest.run() # run test
    ESPRESOTest.compare_emr(".".join([etype, "emr"])) # compare monitoring reports