1
$\begingroup$

My coworkers and I have developed a c++ library implementing a "3D Geological Model" class. Goal of this library is to provide a data structure that is used in computational codes (such as Finite Element codes etc...)

This model class contains "Entities" (i.e. Corner, Line, Surface, Volume). Each Entities own a Mesh, which contains vertices in a 3D space and the connectivity informations.

We would like to handle also "2D Geological Model", which has the same structure (i.e. it contains set of Corner, Line, Surface). But this time, these Entities own a Mesh which contains vertices in a 2D space.

One objective is to give the user the ability to run their computational codes with the same API, even if it is on 3D or 2D "Geological Model".

Does someone here have faced the same problem ? One solution is to template all the classes by the space dimension, but it seems a bit heavy.

Cheers,

$\endgroup$
  • $\begingroup$ I think dealii uses template in the same fashion to handle the dimensionnality of the mesh. @Wolfgangbangerth could answer this question in a good fashion I believe. $\endgroup$ – BlaB May 16 '17 at 17:53
2
$\begingroup$

I use C++ template to parameterize dimension in a fluid simulation project. It is not directly related to your application, but I think some general ideas would be the same.

  • Vectorize operations for vector/array/point/vertices.

    I believe you already have this implemented.

  • Provide iterators to access topology in a model.

    In this way you can abstract(hide) dimensional details, such as "how many adjacent faces/edges do I have for a given element?".

  • Prefer the Structure-Of-Array(SOA) memory layout.

    In SOA layout you put the same attributes from different objects in an array.

    For example, this is a common way to define vertices:

    struct Vertex {
        VECTOR<D> position;
        double weight;
        // other attributes
    };
    std::vector<Vertex> vertices;
    

    This is called Array-Of-Structure. One potential issue of this is that the layout could vary for different dimensions. As a result you might have alignment problems.

    Instead, I would suggest the SOA way:

      struct Vertices {
          std::vector<VECTOR<D>> positions;
          // or
          // std::vector<double> px;
          // std::vector<double> py;
          // ...
          std::vector<double> weights;
          // other attribute arrays
      };
      Vertices vertices;
    

    You should have less alignment issues when all attributes of same type are stored together.

  • Instantiate the template class in .cpp files.

    In C++ a template class will not be instantiated when the compiler does not see a use of it.

    If your lib and your user code are compiled separately, your lib will not include your class implementation because it does not see its use, and the compiler will throw undefined reference errors in your user project.

    So remember to instantiate your class for each dimension you care(usually 2 and 3) manually in .cpp files.

One solution is to template all the classes by the space dimension, but it seems a bit heavy.

I am not sure what do you mean by "heavy". Indeed, instantiating the template classes for each dimension will increase the code size. But I have not seen this is a problem in practice.

$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.