Skip to content

CAD simulation: Parallelize meshing and solid recognition; feedback fixes - #15849

Open
sawenzel wants to merge 9 commits into
AliceO2Group:devfrom
sawenzel:swenzel/cad-converter-feedback-fixes
Open

sawenzel wants to merge 9 commits into
AliceO2Group:devfrom
sawenzel:swenzel/cad-converter-feedback-fixes

Conversation

@sawenzel

Copy link
Copy Markdown
Collaborator

This PR speeds up o2-cad-to-tgeo by meshing and recognising its parts in worker processes, gives
its long phases a progress report, and fixes the defects reported during the CAD tutorial user
session at the ALICE Upgrade Week. Both hot phases of a conversion are per-part loops over
independent solids, so each now runs one part per forked process under --jobs, defaulting to all
cores. A conversion of a large model takes about half the time it did.

The output does not depend on how many processes ran. The triangles, every sidecar and geom.C
are byte-identical between --jobs 1 and a pool, and the shape_*.root files are identical in
size, which is as far as a format carrying a per-file UUID and creation time can be compared.

Parallel meshing and CSG recognition

Processes rather than threads, for a measured reason: pythonOCC holds the GIL across an OCCT call,
so a thread pool gives no speed-up at all. Fork also inherits the live shapes, where a spawn
worker would have to pass them through a BRep WriteToString/ReadFromString round trip, which
perturbs the tessellation. A process that has already meshed in-process deadlocks on fork inside
OCCT's own threads, so both phases fall back to serial in that case.

A worker decides whether a part is accepted as CSG, but the parent writes the shape_*.root
files, in part order. A TFile records its streamer infos in the order its own process first
streamed them, so a pool would otherwise write a different byte layout for a geometrically
identical shape.

Progress reporting

Meshing, exact-surface extraction and CSG recognition each report how many parts are done, the
elapsed time and an ETA. On a terminal the line is redrawn in place; in a log it is printed every
ten per cent. In parallel the per-part evidence lines are replaced by that report, since output
from many workers interleaves.

Defects fixed

The name filter's definition cache ignored the include state, so an expansion pruned outside a
match was reused inside one and the macro placed volumes it never defined. Pruned expansions are
now cached under their own key, and a dangling placement raises rather than being emitted.

A leaf whose faces enclose no volume was treated as a solid. Such a leaf is now skipped with a
warning naming it.

A PyROOT import failure was swallowed, so --csg required read the whole STEP file before failing
without naming the cause. The import error is now reported, and that mode fails before any file is
read.

A conversion using both the CSG and the exact-surface tier reported the surface count from what
extraction succeeded on rather than from what geom.C carries, overstating it by the parts CSG
took. The README also described the emitted macro as resolving its payloads relative to its own
location, where it names them by absolute path; the sed that rewrites the prefix is given instead.

Testing

O2_CADtoTGeo.py --self-test passes 95 checks, two of them new and comparing a parallel
conversion against a serial one over the file set, the sidecar bytes, the shape file sizes and the
tier assigned to every part. The self-test needs pythonOCC and is not wired into ctest, so it does
not run in CI; it was run by hand, together with full conversions of both models that prompted the
feedback.

Overall, a large conversion now takes half the time for the same output, reports what it is doing
while it runs, and no longer misreports or mis-emits the parts the user session exposed.

🤖 Generated with Claude Code

sawenzel and others added 9 commits September 25, 2026 14:18
This fixes a problem in o2-cad-to-tgeo's --include-name filter and adds a self-test.

- A part shared by an included and an excluded subtree was cached as dropped on
  its first visit and then placed on its second, so geom.C did not compile.
- In the other visit order the part leaked into the excluded subtree.
- An empty leaf placed twice left the same dangling placement.
- The pruned expansion of a definition now has its own key, a cached definition
  that produced nothing is no longer placed, and a dangling placement stops the
  conversion.

Co-Authored-By: Claude Opus 5 <[email protected]>
This fixes a problem in o2-cad-to-tgeo with sheet bodies and adds a self-test.

- A leaf made only of open faces encloses no volume, but was converted as a
  solid; its O2BVHSurfaceSolid then refused to close when geom.C was built.
- Such a leaf is now skipped with a warning.
- Open faces beside a closed body are dropped with a warning.
- Closed shells without a solid around them are kept as volumes.

Co-Authored-By: Claude Opus 5 <[email protected]>
This fixes a problem in o2-cad-to-tgeo's CSG path when PyROOT does not import, and
adds a self-test.

- The import error was discarded, so a broken environment showed only as "ROOT
  unavailable" on every part.
- --csg required then shipped all accepted parts as meshes and exited 0.
- The converter now names the interpreter and the import error up front.
- --csg required stops before reading the STEP file; --csg auto warns and goes on.

Co-Authored-By: Claude Opus 5 <[email protected]>
This makes o2-cad-to-tgeo mesh one volume per process and adds a self-test.

- Meshing was 77% of the conversion time of a large model and ran on one core.
- The volumes are now queued during the tree walk and meshed afterwards, over all
  cores by default; --jobs sets the count and --jobs 1 keeps the serial path.
- A progress line reports how many volumes are done, with an ETA.
- The ALICE 3 outer disc converts in 33 s instead of 3m14s, with byte-identical
  facet files.

Co-Authored-By: Claude Opus 5 <[email protected]>
This adds a progress line to the two remaining silent phases of o2-cad-to-tgeo.

- Exact-surface extraction reports how many leaf solids are done, with an ETA.
- The CSG cascade prefixes each part with its position in the run.
- On the ALICE 3 stave the CSG cascade is now the slowest phase, at about 20 s of
  24 s; it is still serial.

Co-Authored-By: Claude Opus 5 <[email protected]>
This speeds up the CSG cascade of the CAD converter and adds a self-test for it.

- The per-part recognition loop now runs one leaf solid per forked process, under the
  --jobs option the mesher already had.
- The OuterDisc converts in 12.9 s instead of 26.4 s with --csg auto --exact-surfaces
  auto, and the stave in 12.8 s instead of 26.4 s.
- A worker decides acceptance but does not write shape_*.root. A TFile records its
  streamer infos in the order its own process first streamed them, so a pool wrote a
  different byte layout for the same shape. The parent writes those files in part order.
- The shapes were the same either way: identical class and bounding box, and 0 of 64000
  lattice points disagreed on Contains.
- Recognition falls back to serial when this process has already meshed serially, for the
  same OCCT reason the mesher does.
- The new self-test converts the example twice and compares the sidecars, geom.C, the
  shape file sizes and the tier of every part.

Co-Authored-By: Claude Opus 5 <[email protected]>
This records where the time goes when a big geom.C is loaded, so the overlap check is not
mistaken for the load.

- On the 140-part OuterDisc: parse 1.3 s, build 15.7 s, CloseGeometry 0.0 s, Export 11.7 s.
- CheckOverlaps takes 513.8 s on the same model and is off by default.

Co-Authored-By: Claude Opus 5 <[email protected]>
This fixes a misleading line printed when a conversion uses both --csg and --exact-surfaces.

- The count came from every part exact-surface extraction succeeded on, not from the parts
  geom.C carries as surface solids, so it overstated the tier by the parts CSG took.
- On the OTR stave it said 137/137 where the macro holds 63 LoadSurfaces calls and the
  tier table says 63.
- The parts that were extracted and then outranked by CSG are now reported separately.

Co-Authored-By: Claude Opus 5 <[email protected]>
This corrects the README on whether a converted folder can be moved.

- The macro was documented as resolving its payloads relative to its own location.
- It names them by absolute path, so the folder cannot be moved or handed on as it stands.
- The sed that rewrites the prefix is given instead.

Co-Authored-By: Claude Opus 5 <[email protected]>
@sawenzel
sawenzel requested a review from a team as a code owner September 25, 2026 12:19
@sawenzel sawenzel changed the title Mesh and recognise CAD parts in parallel, and fix the defects found at the Upgrade Week CAD simulation: Parallelize meshing and solid recognition; feedback fixes Sep 25, 2026
@alibuild

Copy link
Copy Markdown
Collaborator

Error while checking build/O2/fullCI_slc9 for 143b61d at 2026-09-25 14:39:

No log files found

Full log here.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

2 participants