Architecture (4.x version)

Introduction

This part deals with the description of the Code_TYMPAN architecture. Each section represents a part of the code and describes how it is organized:

  • main organization of the code and the different parts

  • some dependencies between these different parts

  • what kind of objects you will find in the different part

Description

Code_TYMPAN is made of different parts:

  • core&tools

  • graphical user interface

  • business logic

  • geometric libraries

  • solvers

An API in Python is used to communicate between the Graphical User Interface (GUI) and the solvers.

Three classes of users may interact differently with Code_TYMPAN:

  • The basic user will use the GUI which builds the data models and run a calculation through the API

  • The advanced user may drop the GUI and runs a build the model/run the calculation with the API

  • At least, the programer will add new solvers/features on the C++ solver part and the API part

_images/4xSplitting.png

Parts separation in the 4.x architecture and how different users interact with Code_TYMPAN

_images/BasicUser.png

Sequence example for a basic user

If we have a look on the source directories (folders) of the differents parts, the main relations in the current architecture are:

_images/Architecture_Tympan.png

Current architecture schema

Here a second graph about the splitting between site elements (business logic) and the computation (solvers). It separates the business logic related to a site with the way to solve the acoustic problem (tympan::AcousticProblemModel). This solver data model, which can be used by any solver, is built from the Python subprocess by going through the current site and extracting relevant data: a computation needs triangles with materials from a site triangulation, acoustic sources/receptors and an altimetry.

_images/SiteBDM.png

Target architecture schema

At the Tympan sources root, we find five directories:
  • core: Several tools classes

  • models: Data model for solvers and business logic

  • gui: Graphical User Interface

  • geometric_methods: Geometric methods

  • solvers: Solvers

doxygen/dir_0a699452fb3f72206b671d5471a45d39_dep.png

Main directories and dependencies

As several dependency graphs will be used below, we explain how it should be read:

_images/DoxygenRules.png

Doxygen rules for dependency graph

Core and Tools

See the core and gui/tools directories and some sub-directories in models directories:

  • models/business: the main base class TYElement used for every business logic objects. Also implements an interface for the solvers and some XML tools in order to export/import a Code_TYMPAN study ;

  • models/common: common objects used by the Business Logic objects: point, vector, matrix, etc.

doxygen/dir_5dbfaf92f958cca7bf9f388ebf56af42_dep.png

models directories and dependencies

The rationale behind the creation of models/common is to provide basic representations and utilities which do not depend upon TYElement nor OPrototype. Typically such representations and utilities are likely to be shared between the main application and the solvers.

The way the CGAL library is used deserves a special explanation. CGAL is a very powerful but quite complex templates-based library. As such dependency to CGAL appears in the headers of the client code and this has a heavy impact on compilation time and apparent code complexity.

In order to mitigate those drawbacks while benefiting from the CGAL features a variant of the classical Bridge* design pattern is used (For design pattern the key reference is [DPGoF] ).

Namely the cgal_tools module in models/common builds some high-level functionality (constrained triangulations and domain meshing) upon CGAL features ; its API relies on CGAL types and does not depend on other Tympan types.

The cgal_bridge module in models/business exposes interfaces to those features expressed with the main Tympan datatypes and ensures the conversions.

This allows independent development and testing and reduces compilation times by breaking header dependencies propagation thanks to the bridge between the interfaces seen by the client code and the implementation.

DPGoF

Design Patterns E. Gamma, R. Helm, R. Johnson, J. Vlissides - Adisson-Wesley

Models data

See the different sub-directories in models:

  • business: objects which describe a site, acoustic objects (sources, receptor, paths), materials, machines, etc.

  • solver: the current work which describes a data model for the solvers.

Business Logic

Note

Business Logic is the part of the code which is not technical. Deal with “real life” models: buildings, machine, fields, etc.

Code_TYMPAN offers a way to build the business objects from a string representing their class name. This feature (mostly used during XML deserialization) is implemented in the OPrototype class through a factory pattern. To use this facility, it is first necessary to register all the objects that will need it. This is handled by the init_registry() method (from models/business/init_registry.h), that must be ran before any call to the methods specified by OPrototype interface.

For now, the splitting between the business logic objects and the Graphical User Interface is not clear. In other words, you can have a strong dependency between models/business and graphical widgets described in gui/widgets. One of the objectives described in the section is to split these parts.

Solvers

It makes a dedicated data model for the solver part (see class tympan::AcousticProblemModel), i.e. create elementary objects (as opposed to business objects) such as acoustic sources and receptors, triangles related to a material, spectrums, etc. in order to define a model that can be used by any solver.

Graphical User Interface

See in Tympan/gui and its four sub-directories:

  • tools: common tools and objects used for the GUI ;

  • widgets: widgets such as buttons, boxes and some widgets dedicated to a specific business logic objets such as a building, a field, a spectrum, etc. ;

  • gl: 3D representation of business logic objects such as a building, a machine, etc ;

  • app: GUI main classes.

doxygen/dir_96acfafdf97aa4a7b901cb1116c77380_dep.png

GUI directories and dependencies

App

The app package is the place where the simulation workflow is split in order to delegate some of the processing to a Python subprocess (see launch() method from TYCalculManager class). When asked to perform a simulation, the computation manager:

  • Serializes the current project to a XML file

  • Calls a subprocess running solve_project.py python script that uses Tympan libraries to:

    • Read the serialized file

    • Build a data model representing the acoustic problem

    • Run the simulation

    • Serialize the computed project (with the results)

  • Reads the simulation results from the file serialized by the Python subprocess

  • Updates the current project with these results

Rendering

The OpenGL API is used to render the scene geometry. The application uses immediate mode and display lists, these methods are from an old specification of OpenGL and are now deprecated. When immediate mode is used, the server (GPU) wait for the client (CPU) to send the geometry. This method is slow because the GPU has to wait for all the data to be transferred. The rendering function of each business logic object is located in gui/gl and simple geometry rendering can be found at gui/tools.

In order to make the rendering faster, the OpenGL commands can be compiled and stored on the GPU. That way, the CPU simply has to tell the GPU to render this display list instead of sending the geometry on each frame. The use of displayList can be found at gui/app/TYOpenGLRenderer.cpp. It simply encapsulates all the rendering function (immediate mode) of the scene.

The modern way to render things in OpenGL relies on the use of VBO’s (Vertex Buffer Object). The idea is to store the geometry on the GPU as compact arrays (of vertices, indices, normals, …). One advantage over the display list is that you can access these buffers and edit the data in a dynamic way, whereas display lists are static, in a sense that when the geometry changes you have to recompile/send the whole display list again.

The matrix management of the application relies on the OpenGL matrices, by using functions such as glRotate(), glTranslate(), … Additionally, the matrix management of OpenGL features a stack of matrices (glPushMatrix(), glPopMatrix()). The goal of OpenGL is to take advantages of the “GPU”, but all the functions that implies matrix operations are done on the “CPU”, they are now deprecated and should be done by the application itself and not the OpenGL API. There exist many libraries that feature matrix management (CGAL? Qt?).

Picking

The picking is entirely done on the GPU by using a name stack and a selection buffer. This method relies on OpenGL deprecated functions and the steps are as follows:

  1. We define a small “picking window”(5 pixel width) and we enter selection mode (a mode where the resulting rendering won’t be displayed).

  2. We give a “name” (an integer) to each object we are willing to pick/draw.

  3. The objects are then rendered. If a primitive falls inside the “picking window”, a “hit” occurs.

  4. For each “hit”, the primitive with the smallest z-value (the closest one) is chosen.

The algorithm is located in the gui/app/TYElementPicker.cpp file.

Note

Actually, numerous names can be given to a primitive, that’s the reason why a stack is used. It enables the programmer to pick objects as a hierarchical structure.

There are two principal different ways of doing picking :

  • color picking ;

  • ray intersection.

The color picking uses entirely the GPU once again. We render every objects with an unique color, then we read the color of the pixel under the mouse. This technique is straightforward and should be simple to implement, however we can’t get the coordinate of the intersection point.

The other method consists of a ray that we cast on the scene, and then perform ray-intersection test against the object of our scene. Usually, the ray go through an acceleration structure (e.g. grid, octree, k-d tree, etc), before being tested with the bounding box of the object. This method usually run on the CPU and is independant of the rendering API. It is easy to know the exact intersection point between our ray and the picked object.

Note

It might be possible to re-use the acceleration structures from models/geometric_methods/AcousticRaytracer/Accelerator for the ray-intersection method.

Geometric libraries

Three librairies are located inside the directory geometric_methods :

  • AnalyticRayTracer Library used by ANIME3DSolver only

  • ConvexHullFinder Library used by the default solver only

  • AcousticRaytracer Library used mainly by ANIME3DSolver (Only few methods used by the default solver for altimetry computation)

The last library is now completely independant from Code Tympan.

doxygen/dir_98d3433d81079253c810b6dce02ef6ef_dep.png

Geometric methods directories and dependencies

AnalyticRayTracer

doxygen/dir_2b59eb025b97d897256cc3ac4b11bfba_dep.png

Dependencies

The collaboration graph [legend] of the AnalyticRayTracer classes are:


doxygen/classDefaultCurvRayEngine__coll__graph.png

DefaultCurvRayEngine class


doxygen/classIGeometryModifier__coll__graph.png

IGeometryModifier class


doxygen/classmeteoLin__coll__graph.png

meteoLin class


doxygen/classLancer__coll__graph.png

Lancer class


doxygen/classRayCourb__coll__graph.png

RayCourb class


doxygen/classStep__coll__graph.png

Step class

ConvexHullFinder

doxygen/dir_7fbd2483b1241a8d1582b5d60506e18c_dep.png

Dependencies

AcousticRaytracer

doxygen/dir_fb094394a0534c962971de1bbd49216d_dep.png

Dependencies

As AcousticRaytracer is now an independant geometric library for ray tracing, it is interesting to detail some of its classes. Here is the hierarchy of some of the mains classes of the library [legend]:


First, the Base classes which gather a lot of objects which constitutes the scene:

doxygen/classBase__inherit__graph.png

Base classes


The Sampler classes deal with the ray generators:

doxygen/classSampler__inherit__graph.png

Samplers


The Engine classes is for the different ways to run the ray tracing method (sequential, parallel, …):

doxygen/classEngine__inherit__graph.png

Engines


The Accelerator classes are used to select an efficient method for primitives classification:

doxygen/classAccelerator__inherit__graph.png

Accelerators


The Selector classes offers different criterias to keep or disable rays during tracing:

doxygen/classSelector__inherit__graph.png

Selectors

Solvers

All directories in solvers :
  • DefaultSolver Default solver using convex hull method

  • ANIME3DSolver Solver using 3D ray tracing

doxygen/dir_635e4428492daafdf6f24946a20daf56_dep.png

Solvers directories and dependencies

DefaultSolver

doxygen/dir_10590c5f2acff4ddadc30b2c4b19f30a_dep.png

Dependencies

The collaboration graph [legend] of the DefaultSolver classes are:


doxygen/classTYSolver__coll__graph.png

TYSolver class


doxygen/classTYAcousticModel__coll__graph.png

TYAcousticModel class


doxygen/classTYAcousticPathFinder__coll__graph.png

TYAcousticPathFinder class


doxygen/classTYFaceSelector__coll__graph.png

TYFaceSelector class


doxygen/classTYTask__coll__graph.png

TYTask class


doxygen/classTYChemin__coll__graph.png

TYChemin class


doxygen/classTYEtape__coll__graph.png

TYEtape class


doxygen/classTYTrajet__coll__graph.png

TYTrajet class

ANIME3DSolver

doxygen/dir_4f2d479a47b44efcc67dc699ba3f6fb7_dep.png

Dependencies

The collaboration graph [legend] of the ANIME3DSolver classes are:


doxygen/classTYANIME3DSolver__coll__graph.png

TYANIME3DSolver class


doxygen/classTYANIME3DFaceSelector__coll__graph.png

TYANIME3DFaceSelector class

doxygen/classTYANIME3DAcousticPathFinder__coll__graph.png

TYANIME3DAcousticPathFinder class


doxygen/classTYANIME3DAcousticModel__coll__graph.png

TYANIME3DAcousticModel class


doxygen/classTYANIME3DRayTracerSolverAdapter__coll__graph.png

TYANIME3DRayTracerSolverAdapter class

Call graphs for Tympan solvers

First, it should be noticed than in the following Doxygen the order of calls graphs is NOT always from the top to the bottom.

The complete call graph for the default solver can be find here .

A simplified call graph is (click to enlarge):

_images/TYSolverCallGraph.png

Default solver call graph

For the ANIME3D solver, the complete call graph is there . A simplified call graph is (click to enlarge):

_images/TYANIME3DSolverCallGraph.png

ANIME3D solver call graph

Python call graph to C++ solver TYANIME3DSolver (click to enlarge):

_images/PythonCallGraph.png

Python call graph