Creating surface through .NET API

Hi!

Thanks for an amazing piece of software :slight_smile: I tried some pre/post processors for CalculiX and this one is the most clear and easiest!

I’ve been using the .NET API (CaeModel, CaeMesh, etc.) in C# to programmatically create models without the PrePoMax UI, run NetGen, assign loads and BCs, etc. - as well as to load results. It is mostly a pretty straightforward and clear process, and it allows us to integrate it into some of our parametric modelling workflows - this is fantastic.

What I am stuck at, is a way to create an FeSurface that uses element faces, from an imported .vol model that has individual surface IDs and surfaceelementsuv definitions.

  • Importing a .vol file keeps the individual surfaces - I can see that in the code and it ends up in the visualization data.
  • PrePoMax appears to use the visualization data to construct surfaces (a user can click on a surface in the UI), but I can’t seem to find this bit in the PrePoMax code.
  • There are plenty of functions in FeModel and FeMesh for getting all parts for a series of elements, or all nodes for a particular part, but I can’t see anything like GetElementFaces or similar for a visualization surface.

Is this possible? Or is there a work-around that doesn’t get too hairy? Any help would be much appreciated :slight_smile:

Much thanks!

Tom

Well, it is a bit of a mess since a lot of data was added over time.

The explanation could be long, so I prepared an example. If you know the surface id from the .vol file and if you know the part geometry type (solid, shell) and you know the part id you can compute the geometry id. Using it, you can call FeMesh.GetIdsFromGeometryIds to get face ids from geometry id. Then you can use AddSurface function in the Controller to create all the necessary element sets.

If you have a shell mesh, you must change the GeometryType from SolidSurface to the appropriate enum value.

In order for the bottom function TestCreateSurface to work (paste it in the Controller class), you have to change one line of the FeMesh function private void CreateSurfaceFaces(FeSurface surface) from

if (surface.CreatedFrom == FeSurfaceCreatedFrom.Selection)

to

if (surface.CreatedFrom == FeSurfaceCreatedFrom.Selection || surface.CreatedFrom == FeSurfaceCreatedFrom.Faces)

I have applied this change to the current source code.

The following code creates a complete FeSurface on a solid part with an id 1 from the visualization surface with an id 1.

public void TestCreateSurface()
{
    int surfaceId = 1;
    int surfaceType = (int)GeometryType.SolidSurface;
    int partId = 1;
    int geometryId = surfaceId * 100000 + surfaceType * 10000 + partId;
    int[] faceIds = _model.Mesh.GetIdsFromGeometryIds(new int[] { geometryId }, vtkSelectItem.Surface);
    //
    FeSurface surface = new FeSurface(_model.Mesh.Surfaces.GetNextNumberedKey("UserSurface"));
    surface.CreatedFrom = FeSurfaceCreatedFrom.Faces;
    surface.FaceIds = faceIds;
    AddSurface(surface);
}
1 Like

Thanks very much, Matej! I will try it out and see how it goes.

I will have to look a bit closer into what is a geometry ID versus all the other ID types (node, elements, etc.) - I’m still getting familiar with the code.

Hi Matej,

I had a go at adding a similar function for Model to avoid using the Controller class, so I can operate on a model directly.

It basically shortcuts some of the functions like AddSurface(surface) and AddSurfaceAndElementFaces(surface) and looks like this:

public FeSurface TestCreateSurface(int partId = 1, int surfaceId = 1, string name = "UserSurface")
{
    int surfaceType = (int)GeometryType.SolidSurface;
    int geometryId = surfaceId * 100000 + surfaceType * 10000 + partId;
    int[] faceIds = this.Mesh.GetIdsFromGeometryIds(new int[] { geometryId }, vtkSelectItem.Surface);
    //
    FeSurface surface = new FeSurface(this.Mesh.Surfaces.GetNextNumberedKey(name));
    surface.CreatedFrom = FeSurfaceCreatedFrom.Faces;
    surface.FaceIds = faceIds;

    this.Mesh.CreateSurfaceItems(surface);
    this.Mesh.Surfaces.Add(surface.Name, surface);

    return surface;
}

Yes, if you do not use the Controller class, you have to add some additional lines of code.

1 Like

Out of curiosity, may you share, what kind of automation you perform using the .NET code?

We are looking at timber models where we derive material directions and knot areas from CT scans at the sawmill. We are trying to develop a way to cut boards from logs to match specific performance requirements from designed glulam elements. I.e. we try to match the strongest part of each lamella to the highest stress on the beam, and leave room for lower grade material where there is little stress.

The automation is so that we can extract many different boards from the CT scan of the log and get their stiffness profile - it would be a hassle to set it up by hand every time :stuck_out_tongue:

I’m also developing a way to set up a CalculiX model from our design software (Rhino) using the PrePoMax .NET code so we can run simulations from our design environment and visualize the results there as well.

In this sense, the fact that PrePoMax is written for .NET and has such a clear API (CaeModel, CaeMesh, CaeJob, etc.) is a real blessing!

For orthotropic material definitions and orientation distributions, I am injecting these cards directly into the output INP file before I run CalculiX. It would be great if PrePoMax would support this at some point, and I am happy to see if I can contribute something once I get more familiar with the code base!

Finally, let me know if there are any publications about PrePoMax or something that we could cite or reference when it comes to publishing things :slight_smile:

  1. Viewing the results of a timber board simulation with knots (red) and simulated material directions around the knots.
  2. A simulation of a timber beam in Rhino (using PrePoMax API) with applied loads and boundary conditions, also visualized in Rhino.
  3. Extracting board and knot geometry from a CT-scanned log with knot data.
1 Like

Thanks for sharing. This is really a nice project.

Unfortunately, a basic PrePoMax manuscript is still missing :frowning:

1 Like

really interesting, i’m also curious about to model a solid part (box and cone), boolean operations, etc.

is the task be done with OpenCascade or Netgen library?

I just started using OpenCascade to do the solid modelling - since it is great at volume splitting and keeping track of the internal parts. Rhino doesn’t really support geometry that shares features inside a volume or compound models.

I then use the NetGen that is included with PrePoMax to mesh it into elements. It is a shame that NetGen now is only available as a Python library… I wonder if it could be forked and run as a utility like before, or wrapped into a .NET library for usage without reading/writing files.


OpenCascade makes nice compound models, so the meshing is aligned between parts - the board (brown) and knots (red).

2 Likes