From ab5c5fa50300906136b3fba175c2febf756ae139 Mon Sep 17 00:00:00 2001 From: Erik B Knudsen Date: Wed, 24 Apr 2024 17:12:55 +0200 Subject: [PATCH 01/20] allow -1 to be a sentinel for sense --- src/CAD_to_OpenMC/assembly.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/CAD_to_OpenMC/assembly.py b/src/CAD_to_OpenMC/assembly.py index c722b4d..0e83e4a 100644 --- a/src/CAD_to_OpenMC/assembly.py +++ b/src/CAD_to_OpenMC/assembly.py @@ -630,7 +630,7 @@ def add_entities_to_moab_core(self, mbcore: core.Core, mbtags: dict, noimplicit= mbcore.tag_set_data(mbtags["category"], fset, "Surface") mbcore.add_parent_child(vsets[i], fset) - if len(sense) == 2: + if len(sense) == 2 and sense[1]!=-1: mbcore.tag_set_data( mbtags["surf_sense"], fset, From e5947e0dc849b97097b8cc0756b40ebfff572e76 Mon Sep 17 00:00:00 2001 From: Erik B Knudsen Date: Wed, 24 Apr 2024 17:13:28 +0200 Subject: [PATCH 02/20] remove threaded file-writing --- src/CAD_to_OpenMC/assemblymesher_cq2.py | 92 +++++++------------------ 1 file changed, 26 insertions(+), 66 deletions(-) diff --git a/src/CAD_to_OpenMC/assemblymesher_cq2.py b/src/CAD_to_OpenMC/assemblymesher_cq2.py index bf84cf9..136421f 100644 --- a/src/CAD_to_OpenMC/assemblymesher_cq2.py +++ b/src/CAD_to_OpenMC/assemblymesher_cq2.py @@ -3,15 +3,7 @@ import pathlib as pl import OCP from .assemblymesher_base import assemblymesher - -single_thread_override = False -try: - import multiprocessing as mp - - manager = mp.Manager() - lock = manager.Lock() -except: - single_thread_override = True +import os from .stl_utils import * from . import meshutils @@ -26,6 +18,10 @@ class MesherCQSTL2(assemblymesher): cq_mesher_faceHash = {} + #writer object from OCP + wr=OCP.StlAPI.StlAPI_Writer() + wr.ASCIIMode=True + def __init__( self, tolerance, @@ -88,11 +84,6 @@ def _mesh_surfaces(self): # loop over all surfaces in all entities # and generate meshes (refined or otherwise) mpargs = [] - if single_thread_override or self.threads == 1: - face_hash_table = {} - else: - # manager=mp.Manager() - face_hash_table = manager.dict() k = 0 for i, e in enumerate(self.cq_mesher_entities): if self.verbosity_level: @@ -100,94 +91,63 @@ def _mesh_surfaces(self): e.solid=self._triangulate_solid(e.solid,self.cq_mesher_tolerance,self.cq_mesher_ang_tolerance) mpargs.extend( [ - (k + j, j, i, self.refine, self.surface_hash(f), face_hash_table) + [k + j, j, i, self.refine, self.surface_hash(f), face_hash_table] for j, f in enumerate(e.solid.Faces()) ] ) # we have a set of mesh jobs - scatter those - if single_thread_override or self.threads == 1: - output = [] - for args in mpargs: - output.append(self._mesh_single_nothread(*args)) - else: - pool = mp.Pool(processes=self.threads) - output = pool.starmap(self._mesh_single, mpargs) + for args in mpargs: + self._mesh_single(*args) # process the list of meshed faces. stls = [] for i, e in enumerate(self.cq_mesher_entities): face_stls = [] for k, v in face_hash_table.items(): - vids = v[1] # the volumes that this face belongs to + vids = v[1:] # the volumes that this face belongs to if i in vids: # this face is part of this volume - face_stls.append(v) + face_stls.append([v[0],v[1:]]) stls.append(face_stls) + print(face_stls) return stls def _triangulate_solid(self, solid, tol: float = 1e-3, atol: float = 1e-1): """ create a mesh by means of the underlying OCCT IncrementalMesh on a single solid. This will later be split into surfaces. This has to be done since otherwise a single solid can get leaky - when surfaces do not connect + when its surfaces do not connect properly """ solid.mesh(tol,atol) return solid @classmethod - def _mesh_single_nothread(cls, global_fid, fid, vid, refine, hh, faceHash): + def _mesh_single(cls, global_fid, fid, vid, refine, hh, faceHash): f = cls.cq_mesher_entities[vid].solid.Faces()[fid] if hh in faceHash.keys(): - # surface is in table - simply add the vid to the hash-table - faceHash[hh][1].append(vid) - if cls.verbosity_level: - print(f"INFO: mesher reusing {hh} ({faceHash[hh][0]},{faceHash[hh][1]})") - return (hh, faceHash[hh]) + done=True + ffn=faceHash[hh][0] + previd=faceHash[hh][1] + faceHash[hh]=[ffn,previd,vid] else: - facefilename = f"vol_{vid+1}_face{global_fid:04}.stl" - wr=OCP.StlAPI.StlAPI_Writer() - wr.ASCIIMode=True - status=False - status=wr.Write(f.wrapped,facefilename) - k=0 - while (not status): - print(f'WARNING: failed to write file {facefilename}, retrying (iter{k})') - status=wr.Write(f.wrapped,facefilename) - k=k+1 - if(k>8): - print(f'ERROR: could not write file {facefilename}, volume {vid+1} will likely be leaking') - return None - faceHash[hh] = [facefilename, manager.list([vid])] - if cls.verbosity_level > 1: - print(f"INFO: cq export to file {facefilename}") - if refine: - cls._refine_stls(facefilename, refine) - return (hh, faceHash[hh]) + done=False - @classmethod - def _mesh_single(cls, global_fid, fid, vid, refine, hh, faceHash): - f = cls.cq_mesher_entities[vid].solid.Faces()[fid] - if hh in faceHash.keys(): - # surface is in table - simply add the vid to the hash-table - with lock: - faceHash[hh][1].append(vid) + # surface is in table - simply add the vid to the hash-table + if done: if cls.verbosity_level: - print(f"INFO: mesher reusing {hh} {faceHash[hh][1]}") - return (hh, faceHash[hh]) + print(f"INFO: mesher reusing {hh} ({faceHash[hh][0]},{faceHash[hh][1:]})") + return else: facefilename = f"vol_{vid+1}_face{global_fid:04}.stl" - with lock: - faceHash[hh] = [facefilename, manager.list([vid])] - wr=OCP.StlAPI.StlAPI_Writer() - wr.ASCIIMode=True - wr.Write(f.wrapped,facefilename) + faceHash[hh] = [facefilename, vid, -1] + status=cls.wr.Write(f.wrapped,facefilename) + print(status, f.wrapped,f) if cls.verbosity_level > 1: print(f"INFO: cq export to file {facefilename}") if refine: cls._refine_stls(facefilename, refine) - return (hh, faceHash[hh]) - + return class MesherCQSTL2Builder: def __init__(self): From 1a4352608113880711fbc1770e1a90d930c36b85 Mon Sep 17 00:00:00 2001 From: Erik B Knudsen Date: Wed, 24 Apr 2024 17:36:28 +0200 Subject: [PATCH 03/20] fix forgotten variable decl --- src/CAD_to_OpenMC/assemblymesher_cq2.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/CAD_to_OpenMC/assemblymesher_cq2.py b/src/CAD_to_OpenMC/assemblymesher_cq2.py index 136421f..dbe984e 100644 --- a/src/CAD_to_OpenMC/assemblymesher_cq2.py +++ b/src/CAD_to_OpenMC/assemblymesher_cq2.py @@ -84,6 +84,8 @@ def _mesh_surfaces(self): # loop over all surfaces in all entities # and generate meshes (refined or otherwise) mpargs = [] + face_hash_table={} + k = 0 for i, e in enumerate(self.cq_mesher_entities): if self.verbosity_level: From 156c229ca76f3f36c2c56af8b4315dc88fdbd446 Mon Sep 17 00:00:00 2001 From: Erik B Knudsen Date: Wed, 24 Apr 2024 17:37:12 +0200 Subject: [PATCH 04/20] cleanup --- src/CAD_to_OpenMC/assemblymesher_cq2.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/CAD_to_OpenMC/assemblymesher_cq2.py b/src/CAD_to_OpenMC/assemblymesher_cq2.py index dbe984e..0a63cb8 100644 --- a/src/CAD_to_OpenMC/assemblymesher_cq2.py +++ b/src/CAD_to_OpenMC/assemblymesher_cq2.py @@ -112,7 +112,6 @@ def _mesh_surfaces(self): # this face is part of this volume face_stls.append([v[0],v[1:]]) stls.append(face_stls) - print(face_stls) return stls def _triangulate_solid(self, solid, tol: float = 1e-3, atol: float = 1e-1): @@ -128,6 +127,7 @@ def _triangulate_solid(self, solid, tol: float = 1e-3, atol: float = 1e-1): def _mesh_single(cls, global_fid, fid, vid, refine, hh, faceHash): f = cls.cq_mesher_entities[vid].solid.Faces()[fid] if hh in faceHash.keys(): + # surface is in table - simply add the vid to the hash-table done=True ffn=faceHash[hh][0] previd=faceHash[hh][1] @@ -135,7 +135,6 @@ def _mesh_single(cls, global_fid, fid, vid, refine, hh, faceHash): else: done=False - # surface is in table - simply add the vid to the hash-table if done: if cls.verbosity_level: print(f"INFO: mesher reusing {hh} ({faceHash[hh][0]},{faceHash[hh][1:]})") @@ -144,7 +143,6 @@ def _mesh_single(cls, global_fid, fid, vid, refine, hh, faceHash): facefilename = f"vol_{vid+1}_face{global_fid:04}.stl" faceHash[hh] = [facefilename, vid, -1] status=cls.wr.Write(f.wrapped,facefilename) - print(status, f.wrapped,f) if cls.verbosity_level > 1: print(f"INFO: cq export to file {facefilename}") if refine: From 329694449aa829b10f6da52d3e5b1d4c8de3e291 Mon Sep 17 00:00:00 2001 From: Erik B Knudsen Date: Wed, 1 May 2024 09:31:12 +0200 Subject: [PATCH 05/20] fix tagging logging --- src/CAD_to_OpenMC/assembly.py | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/src/CAD_to_OpenMC/assembly.py b/src/CAD_to_OpenMC/assembly.py index 0e83e4a..a581d5a 100644 --- a/src/CAD_to_OpenMC/assembly.py +++ b/src/CAD_to_OpenMC/assembly.py @@ -207,6 +207,7 @@ def __init__( self.tags = None self.sequential_tags = None self.implicit_complement = implicit_complement + self.noextract_tags = True @classmethod def hdf5_in_moab(cls): @@ -271,6 +272,7 @@ def import_stp_files( scale: overall scaling factor applied to all parts translate: Translation vector to apply to all parts in the step-file. rotate: Rotation angles to apply to the parts in the step-file. + vol_skip: list of volumes to skip meshing. """ for stp in self.stp_files: warn, ct = has_degenerate_toroids(stp,True) @@ -324,8 +326,7 @@ def import_stp_files( e.tag = tag tags_set = tags_set + 1 gmsh.finalize() - - if tags: + elif tags: # tag objects according to the tags dictionary. gmsh.initialize() vols = gmsh.model.occ.importShapes(stp) @@ -342,11 +343,17 @@ def import_stp_files( g = re.match(k, part) if g is not None: tag = tags[k] + tags_set = tags_set + 1 break #if tag is still not set at this point we will either leave it or set it to the default. if tag is None: if e.tag is None or self.noextract_tags: tag = self.default_tag + else: + #use tag from stepfile + g = re.match(r"^([^\s_@]+)", part) + tags_set = tags_set + 1 + tag=g[0] else: tag = tag if self.verbose > 1: From 605c5b684073eb070828a8fb3e242e8cc7321a78 Mon Sep 17 00:00:00 2001 From: Erik B Knudsen Date: Wed, 1 May 2024 09:34:09 +0200 Subject: [PATCH 06/20] add a changelog --- CHANGELOG.md | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 CHANGELOG.md diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..0dbf4fc --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,6 @@ +# changes from 0.13.3 to x.y.z +- fixing the logic of tagging. If a tag ditionary is supplied this will +take precedence over extracted tags, but defaults to the extracted tag if +no match is found in the dictionary +- improvements to the imprinting logic, following the logic in the inbound +in cadquery From 5db0863075a2fda302f71265a1037a6c35ce063b Mon Sep 17 00:00:00 2001 From: Erik B Knudsen Date: Thu, 16 May 2024 10:53:12 +0200 Subject: [PATCH 07/20] add unidecode as dep --- pyproject.toml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/pyproject.toml b/pyproject.toml index 30ce093..bc50e52 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -22,8 +22,10 @@ dependencies=[ 'numpy', 'networkx', 'trimesh', + 'unidecode', ] + [project.urls] "Homepage" = "https://github.com/openmsr/CAD_to_OpenMC" "Bug Tracker" = "https://github.com/openmsr/CAD_to_OpenMC/issues" From 5c5238bea80a1c10186cd1815cff11a31100c5a4 Mon Sep 17 00:00:00 2001 From: Erik B Knudsen Date: Thu, 16 May 2024 10:53:56 +0200 Subject: [PATCH 08/20] Revert "add unidecode as dep" This reverts commit 5db0863075a2fda302f71265a1037a6c35ce063b. --- pyproject.toml | 2 -- 1 file changed, 2 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index bc50e52..30ce093 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -22,10 +22,8 @@ dependencies=[ 'numpy', 'networkx', 'trimesh', - 'unidecode', ] - [project.urls] "Homepage" = "https://github.com/openmsr/CAD_to_OpenMC" "Bug Tracker" = "https://github.com/openmsr/CAD_to_OpenMC/issues" From 77569fcc1d0f22596a311d1f6f1d7ef926d9fec4 Mon Sep 17 00:00:00 2001 From: Erik B Knudsen Date: Thu, 16 May 2024 11:15:04 +0200 Subject: [PATCH 09/20] init work on dellabella algorithm --- src/CAD_to_OpenMC/assemblymesher_db.py | 209 +++++++++++++++++++++++++ 1 file changed, 209 insertions(+) create mode 100644 src/CAD_to_OpenMC/assemblymesher_db.py diff --git a/src/CAD_to_OpenMC/assemblymesher_db.py b/src/CAD_to_OpenMC/assemblymesher_db.py new file mode 100644 index 0000000..894052a --- /dev/null +++ b/src/CAD_to_OpenMC/assemblymesher_db.py @@ -0,0 +1,209 @@ +import cadquery as cq +import subprocess as sp +import pathlib as pl + +from OCC.Core.IMeshTools import ( + IMeshTools_Parameters, + IMeshTools_MeshAlgoType_Watson, + IMeshTools_MeshAlgoType_Delabella, +) +from OCC.Core.TopoDS import TopoDS_Shape +from OCC.Core.BRep import BRep_Builder +from OCC.Core.BRepMesh import BRepMesh_IncrementalMesh +from OCC.Core.BRepTools import breptools +from OCC.Core.StlAPI import StlAPI_Writer + +from .assemblymesher_base import assemblymesher +import os + +from .stl_utils import * +from . import meshutils + +class MesherDB(assemblymesher): + # these need to be class attributes to avoid pickling when spawning a multiprocessing-pool + # this is no longer necessary in fact + db_mmesher_params=None + + db_mesher_faceHash = {} + + #writer object from OCP + wr=StlAPI_Writer() + wr.ASCIIMode=True + + def __init__( + self, + tolerance, + angular_tolerance, + min_mesh_size, + max_mesh_size, + default, + refine, + threads, + entities, + ): + self._set_meshpars(tolerance, angular_tolerance, min_mesh_size, max_mesh_size) + self._clear_face_hashtable() + self.refine = refine + self._set_entities(entities) + self.default = default + self.min_mesh_size = min_mesh_size + self.max_mesh_size = max_mesh_size + if len(entities) <= threads: + self.threads = len(entities) + else: + self.threads = threads + + @property + def refine(self): + return self._refine + + @refine.setter + def refine(self, ref): + if ref == True or ref != 0: + self._refine = True + else: + self._refine = False + + @classmethod + def _set_meshpars(cls, tol, ang_tol, min_sz, max_sz): + cls.params = IMeshTools_Parameters() + # Basic settings, CQ defaults + cls.params.Angle = 1e-3 + cls.params.Deflection = 0.1 + cls.params.InParallel = True + cls.params.Relative = True + # Advanced settings. + cls.params.MeshAlgo = IMeshTools_MeshAlgoType_Delabella + # params.AngleInterior = + # params.DeflectionInterior = + # params.MinSize = + # params.InternalVerticesMode = + # params.ControlSurfaceDeflection = + # params.EnableControlSurfaceDeflectionAllSurfaces = + # params.CleanModel = + # params.AdjustMinSize = + # params.ForceFaceDeflection = + # params.AllowQualityDecrease = + # exportStl(s, 'with-occ.stl', 1e-3, 0.1, True, True) + + @classmethod + def _clear_face_hashtable(cls): + cls.cq_mesher_faceHash = {} + + @classmethod + def _set_entities(cls, entities): + cls.cq_mesher_entities = entities + + def generate_stls(self): + return self._mesh_surfaces() + + @classmethod + def surface_hash(self,surface): + part1=surface + part2=surface.Center().toTuple() + return hash( (part1,part2) ) + + def _mesh_surfaces(self): + # loop over all surfaces in all entities + # and generate meshes (refined or otherwise) + mpargs = [] + face_hash_table={} + + k = 0 + for i, e in enumerate(self.cq_mesher_entities): + if self.verbosity_level: + print(f"INFO: triangulating solid {i}") + e.solid=self._triangulate_solid(e.solid,self.cq_mesher_tolerance,self.cq_mesher_ang_tolerance) + mpargs.extend( + [ + [k + j, j, i, self.refine, self.surface_hash(f), face_hash_table] + for j, f in enumerate(e.solid.Faces()) + ] + ) + + # we have a set of mesh jobs - scatter those + for args in mpargs: + self._mesh_single(*args) + + # process the list of meshed faces. + stls = [] + for i, e in enumerate(self.cq_mesher_entities): + face_stls = [] + for k, v in face_hash_table.items(): + vids = v[1:] # the volumes that this face belongs to + if i in vids: + # this face is part of this volume + face_stls.append([v[0],v[1:]]) + stls.append(face_stls) + return stls + + def _triangulate_solid(self, solid, tol: float = 1e-3, atol: float = 1e-1): + """ create a mesh by means of the underlying OCCT IncrementalMesh + on a single solid. This will later be split into surfaces. + This has to be done since otherwise a single solid can get leaky + when its surfaces do not connect properly + """ + BrepMesh_IncrementalMesh(solid,*self.params) + return solid + + @classmethod + def _mesh_single(cls, global_fid, fid, vid, refine, hh, faceHash): + f = cls.cq_mesher_entities[vid].solid.Faces()[fid] + if hh in faceHash.keys(): + # surface is in table - simply add the vid to the hash-table + done=True + ffn=faceHash[hh][0] + previd=faceHash[hh][1] + faceHash[hh]=[ffn,previd,vid] + else: + done=False + + if done: + if cls.verbosity_level: + print(f"INFO: mesher reusing {hh} ({faceHash[hh][0]},{faceHash[hh][1:]})") + return + else: + facefilename = f"vol_{vid+1}_face{global_fid:04}.stl" + faceHash[hh] = [facefilename, vid, -1] + status=cls.wr.Write(f.wrapped,facefilename) + if cls.verbosity_level > 1: + print(f"INFO: cq export to file {facefilename}") + if refine: + cls._refine_stls(facefilename, refine) + return + +class MesherDBBuilder: + def __init__(self): + self._instance = None + + def __call__( + self, + tolerance, + angular_tolerance, + min_mesh_size, + max_mesh_size, + default, + refine, + threads, + entities, + **_ignored, + ): + if not self._instance: + self._instance = MesherDB( + tolerance, + angular_tolerance, + min_mesh_size, + max_mesh_size, + default, + refine, + threads, + entities, + ) + else: + # We are reusing a mesher instance. Hence reset the parameters and clear the hashtable + self._instance._set_entities(entities) + self._instance._set_meshpars( + tolerance, angular_tolerance, min_mesh_size, max_mesh_size + ) + self._instance._clear_face_hashtable() + return self._instance From 1692ffa069beea5db1b2d62d14af630ff992ef8b Mon Sep 17 00:00:00 2001 From: Erik B Knudsen Date: Thu, 16 May 2024 11:18:35 +0200 Subject: [PATCH 10/20] add the db-mesher to the factory class --- src/CAD_to_OpenMC/assemblymesher.py | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/CAD_to_OpenMC/assemblymesher.py b/src/CAD_to_OpenMC/assemblymesher.py index 37431fd..49b56b9 100644 --- a/src/CAD_to_OpenMC/assemblymesher.py +++ b/src/CAD_to_OpenMC/assemblymesher.py @@ -20,7 +20,13 @@ except (ImportError,OSError) as e: npcq2=e -if (nogmsh and nocq and nocq2): +nodb=False +try: + from .assemblymesher_db import MesherDBBuilder +except (ImportError,OSError) as e: + nodb=e + +if (nogmsh and nocq and nocq2 and nodb): raise ImportError("Could not import any of the mesher backends") class MesherFactory(ObjectFactory): @@ -34,3 +40,5 @@ def get(self,mesher_id,**kwargs): meshers.register_builder('stl',MesherCQSTLBuilder()) if(not nocq2): meshers.register_builder('stl2',MesherCQSTL2Builder()) +if(not nodb): + meshers.register_builder('db',MesherDBBuilder()) From 159c0b0da9498041afaabdeb943fc76674fde0a8 Mon Sep 17 00:00:00 2001 From: Erik B Knudsen Date: Thu, 16 May 2024 11:25:36 +0200 Subject: [PATCH 11/20] testing also the DB-mesher --- tests/test_db.py | 37 +++++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) create mode 100644 tests/test_db.py diff --git a/tests/test_db.py b/tests/test_db.py new file mode 100644 index 0000000..4731a5b --- /dev/null +++ b/tests/test_db.py @@ -0,0 +1,37 @@ +import pytest +import CAD_to_OpenMC.assembly as ab +from tests.harnessRun import HarnessRun +import pathlib as pl +import sys + +class HarnessDB(HarnessRun): + def __init__(self): + super().__init__() + + def run(self,merge=False): + if merge: + self.merge() + + h5p = pl.Path('out_db.h5m') + self.a.solids_to_h5m(backend='db',h5m_filename=str(h5p)) + assert h5p.exists() + assert self.is_validh5m(h5p) + self.cleanup() + + def cleanup(self): + super().cleanup() + pwd=pl.Path('.') + for v in pwd.glob("vol*_face*"): + v.unlink() + +def testcq(): + t = HarnessDB() + t.run() + +def testcq_wmerge(): + t = HarnessDB() + t.run(merge=True) + +if __name__=='__main__': + testdb() + testdb_wmerge() From 2a63c9ca18838d4a9644187f2ee2a9a023983b5a Mon Sep 17 00:00:00 2001 From: Erik B Knudsen Date: Fri, 21 Jun 2024 09:32:37 +0200 Subject: [PATCH 12/20] fix function calls such that db is now functional --- src/CAD_to_OpenMC/assemblymesher_db.py | 40 +++++++++++++------------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/src/CAD_to_OpenMC/assemblymesher_db.py b/src/CAD_to_OpenMC/assemblymesher_db.py index 894052a..f2109f8 100644 --- a/src/CAD_to_OpenMC/assemblymesher_db.py +++ b/src/CAD_to_OpenMC/assemblymesher_db.py @@ -2,16 +2,16 @@ import subprocess as sp import pathlib as pl -from OCC.Core.IMeshTools import ( +from OCP.IMeshTools import ( IMeshTools_Parameters, IMeshTools_MeshAlgoType_Watson, IMeshTools_MeshAlgoType_Delabella, ) -from OCC.Core.TopoDS import TopoDS_Shape -from OCC.Core.BRep import BRep_Builder -from OCC.Core.BRepMesh import BRepMesh_IncrementalMesh -from OCC.Core.BRepTools import breptools -from OCC.Core.StlAPI import StlAPI_Writer +from OCP.TopoDS import TopoDS_Shape +from OCP.BRep import BRep_Builder +from OCP.BRepMesh import BRepMesh_IncrementalMesh +from OCP.BRepTools import BRepTools +from OCP.StlAPI import StlAPI_Writer from .assemblymesher_base import assemblymesher import os @@ -22,7 +22,7 @@ class MesherDB(assemblymesher): # these need to be class attributes to avoid pickling when spawning a multiprocessing-pool # this is no longer necessary in fact - db_mmesher_params=None + db_mesher_params=None db_mesher_faceHash = {} @@ -41,7 +41,7 @@ def __init__( threads, entities, ): - self._set_meshpars(tolerance, angular_tolerance, min_mesh_size, max_mesh_size) + self._set_meshpars(tolerance, angular_tolerance) self._clear_face_hashtable() self.refine = refine self._set_entities(entities) @@ -65,13 +65,13 @@ def refine(self, ref): self._refine = False @classmethod - def _set_meshpars(cls, tol, ang_tol, min_sz, max_sz): + def _set_meshpars(cls, tolerance, angular_tolerance): cls.params = IMeshTools_Parameters() # Basic settings, CQ defaults - cls.params.Angle = 1e-3 - cls.params.Deflection = 0.1 - cls.params.InParallel = True - cls.params.Relative = True + cls.params.Angle = angular_tolerance + cls.params.Deflection = tolerance + cls.params.InParallel = False + cls.params.Relative = False # Advanced settings. cls.params.MeshAlgo = IMeshTools_MeshAlgoType_Delabella # params.AngleInterior = @@ -110,10 +110,12 @@ def _mesh_surfaces(self): face_hash_table={} k = 0 + #compo = cq.Compound.makeCompound([e.solid for e in self.cq_mesher_entities]) + #BRepMesh_IncrementalMesh(compo.wrapped,self.params) for i, e in enumerate(self.cq_mesher_entities): if self.verbosity_level: - print(f"INFO: triangulating solid {i}") - e.solid=self._triangulate_solid(e.solid,self.cq_mesher_tolerance,self.cq_mesher_ang_tolerance) + print(f"INFO: triangulating solid {i} using backend db") + e.solid=self._triangulate_solid(e.solid) mpargs.extend( [ [k + j, j, i, self.refine, self.surface_hash(f), face_hash_table] @@ -137,13 +139,13 @@ def _mesh_surfaces(self): stls.append(face_stls) return stls - def _triangulate_solid(self, solid, tol: float = 1e-3, atol: float = 1e-1): + def _triangulate_solid(self, solid): """ create a mesh by means of the underlying OCCT IncrementalMesh on a single solid. This will later be split into surfaces. This has to be done since otherwise a single solid can get leaky when its surfaces do not connect properly """ - BrepMesh_IncrementalMesh(solid,*self.params) + BRepMesh_IncrementalMesh(solid.wrapped,self.params) return solid @classmethod @@ -202,8 +204,6 @@ def __call__( else: # We are reusing a mesher instance. Hence reset the parameters and clear the hashtable self._instance._set_entities(entities) - self._instance._set_meshpars( - tolerance, angular_tolerance, min_mesh_size, max_mesh_size - ) + self._instance._set_meshpars(tolerance,angular_tolerance) self._instance._clear_face_hashtable() return self._instance From 45beeae7bf3f0d915b745b2a05f663f4967cfc4f Mon Sep 17 00:00:00 2001 From: Erik B Knudsen Date: Fri, 21 Jun 2024 09:33:41 +0200 Subject: [PATCH 13/20] enable db -backend --- src/CAD_to_OpenMC/assembly.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/CAD_to_OpenMC/assembly.py b/src/CAD_to_OpenMC/assembly.py index a581d5a..8c39b9b 100644 --- a/src/CAD_to_OpenMC/assembly.py +++ b/src/CAD_to_OpenMC/assembly.py @@ -180,7 +180,6 @@ def similar_solids(solid1_vol, solid1_bb, solid1_c, solid2_vol, solid2_bb, solid ) return dV + dBB + dCntr - class Assembly: """This class encapsulates a set of geometries defined by step-files addtionally it provides access to meshing-utilities, and export to a DAGMC-enabled @@ -516,7 +515,7 @@ def solids_to_h5m( e.stl = s if self.verbose: self.print_summary() - if backend == "stl2": + if backend in [ "stl2", "db" ] : self.stl2h5m_byface(h5m_path.name, True) else: if heal: From f5387c175352afd3ba40566095c8acb3de267d11 Mon Sep 17 00:00:00 2001 From: Erik B Knudsen Date: Fri, 21 Jun 2024 10:06:21 +0200 Subject: [PATCH 14/20] remove dead code --- src/CAD_to_OpenMC/assemblymesher_db.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/CAD_to_OpenMC/assemblymesher_db.py b/src/CAD_to_OpenMC/assemblymesher_db.py index f2109f8..b3a00b4 100644 --- a/src/CAD_to_OpenMC/assemblymesher_db.py +++ b/src/CAD_to_OpenMC/assemblymesher_db.py @@ -110,8 +110,6 @@ def _mesh_surfaces(self): face_hash_table={} k = 0 - #compo = cq.Compound.makeCompound([e.solid for e in self.cq_mesher_entities]) - #BRepMesh_IncrementalMesh(compo.wrapped,self.params) for i, e in enumerate(self.cq_mesher_entities): if self.verbosity_level: print(f"INFO: triangulating solid {i} using backend db") From 1011fc8ae1faa5f285b3a2cf91859207bc3ed189 Mon Sep 17 00:00:00 2001 From: Erik B Knudsen Date: Mon, 24 Jun 2024 13:12:44 +0200 Subject: [PATCH 15/20] fix typo --- src/CAD_to_OpenMC/assemblymesher.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/CAD_to_OpenMC/assemblymesher.py b/src/CAD_to_OpenMC/assemblymesher.py index 49b56b9..e2bdbc1 100644 --- a/src/CAD_to_OpenMC/assemblymesher.py +++ b/src/CAD_to_OpenMC/assemblymesher.py @@ -18,7 +18,7 @@ try: from .assemblymesher_cq2 import MesherCQSTL2Builder except (ImportError,OSError) as e: - npcq2=e + nocq2=e nodb=False try: From 1c93d84fb32cf671ee52e4aa302c3430696207ac Mon Sep 17 00:00:00 2001 From: Erik B Knudsen Date: Mon, 24 Jun 2024 13:13:10 +0200 Subject: [PATCH 16/20] ocp needs to be 7.7.2.1 to allow dellabella --- .github/workflows/python-app.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/python-app.yml b/.github/workflows/python-app.yml index c0ccf46..44eb20c 100644 --- a/.github/workflows/python-app.yml +++ b/.github/workflows/python-app.yml @@ -45,6 +45,8 @@ jobs: create-args: >- python=${{matrix.pyv}} openmc=0.13.3=dagmc_mpi_openmpi* + ocp=7.7.2.1 + cadquery=2.4.0 init-shell: bash - name: Test OpenMC run: openmc --version From 37e8e1a366252a57b4707ac8ec4b931e7abc855e Mon Sep 17 00:00:00 2001 From: Erik B Knudsen Date: Mon, 24 Jun 2024 13:21:58 +0200 Subject: [PATCH 17/20] bump openmc version --- .github/workflows/python-app.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/python-app.yml b/.github/workflows/python-app.yml index 44eb20c..336821f 100644 --- a/.github/workflows/python-app.yml +++ b/.github/workflows/python-app.yml @@ -44,7 +44,7 @@ jobs: environment-name: cad_to_openmc_Testing create-args: >- python=${{matrix.pyv}} - openmc=0.13.3=dagmc_mpi_openmpi* + openmc=0.14.0=dagmc_mpi_openmpi* ocp=7.7.2.1 cadquery=2.4.0 init-shell: bash From 199b92d5e1acd96333bf383bccb5820beb602cbb Mon Sep 17 00:00:00 2001 From: Erik B Knudsen Date: Mon, 24 Jun 2024 14:12:04 +0200 Subject: [PATCH 18/20] attempt to not pip install cadquery --- .github/workflows/python-app.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/python-app.yml b/.github/workflows/python-app.yml index 336821f..c19794a 100644 --- a/.github/workflows/python-app.yml +++ b/.github/workflows/python-app.yml @@ -55,7 +55,7 @@ jobs: run: | python -m pip install --upgrade pip pip install flake8 build pytest - if [ -f requirements.txt ]; then pip install -r requirements.txt; fi + if [ -f requirements.txt ]; then pip install -r `grep -v cadq requirements.txt`; fi micromamba list python -c "import gmsh" shell: micromamba-shell {0} From 4885b8cbcc116a229cba70d3caeb1761485997fb Mon Sep 17 00:00:00 2001 From: Erik B Knudsen Date: Mon, 24 Jun 2024 14:26:22 +0200 Subject: [PATCH 19/20] avoid reinstalling cadquery-ocp --- .github/workflows/python-app.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/python-app.yml b/.github/workflows/python-app.yml index c19794a..beb8926 100644 --- a/.github/workflows/python-app.yml +++ b/.github/workflows/python-app.yml @@ -55,7 +55,8 @@ jobs: run: | python -m pip install --upgrade pip pip install flake8 build pytest - if [ -f requirements.txt ]; then pip install -r `grep -v cadq requirements.txt`; fi + grep -v cadq requirements.txt > reqs_cleaned.txt + pip install -r reqs_cleaned.txt micromamba list python -c "import gmsh" shell: micromamba-shell {0} From 061239f62ac3058c2e06872d5edccff3aca85a44 Mon Sep 17 00:00:00 2001 From: Erik B Knudsen Date: Mon, 24 Jun 2024 14:30:11 +0200 Subject: [PATCH 20/20] deps should already be handled --- .github/workflows/python-app.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/python-app.yml b/.github/workflows/python-app.yml index beb8926..a381853 100644 --- a/.github/workflows/python-app.yml +++ b/.github/workflows/python-app.yml @@ -70,7 +70,7 @@ jobs: - name: Build, pip-install, and test-import CAD_to_OpenMC with dependencies. run: | python -m build --sdist . - pip install dist/cad_to_openmc*.tar.gz + pip install --no-deps dist/cad_to_openmc*.tar.gz python -c 'import CAD_to_OpenMC.assembly' shell: micromamba-shell {0} - name: Run Tests