diff --git a/dagmc/dagnav.py b/dagmc/dagnav.py index 5d3a3ce..8327600 100644 --- a/dagmc/dagnav.py +++ b/dagmc/dagnav.py @@ -90,6 +90,17 @@ def geom_dimension_tag(self): create_if_missing=True, ) + @cached_property + def surf_sense_tag(self): + """Surface sense tag.""" + return self.mb.tag_get_handle( + "GEOM_SENSE_2", + 2, + types.MB_TYPE_HANDLE, + types.MB_TAG_SPARSE, + create_if_missing=True, + ) + def write_file(self, filename): """Write the model to a file. @@ -100,6 +111,7 @@ def write_file(self, filename): """ self.mb.write_file(filename) + class DAGSet: """ Generic functionality for a DAGMC EntitySet. @@ -303,10 +315,53 @@ def __init__(self, model: DAGModel, handle: np.uint64): super().__init__(model, handle) self._check_category_and_dimension() - def get_volumes(self): + @property + def surf_sense(self) -> list[Optional[Volume]]: + """Surface sense data.""" + try: + handles = self.model.mb.tag_get_data( + self.model.surf_sense_tag, self.handle, flat=True + ) + except RuntimeError: + return [None, None] + return [Volume(self.model, handle) if handle != 0 else None + for handle in handles] + + @surf_sense.setter + def surf_sense(self, volumes: list[Optional[Volume]]): + if len(volumes) != 2: + raise ValueError("surf_sense should be a list of two volumes.") + sense_data = [vol.handle if vol is not None else np.uint64(0) + for vol in volumes] + self._tag_set_data(self.model.surf_sense_tag, sense_data) + + # Establish parent-child relationships + for vol in volumes: + if vol is not None: + self.model.mb.add_parent_child(vol.handle, self.handle) + + @property + def forward_volume(self) -> Optional[Volume]: + """Volume with forward sense with respect to the surface.""" + return self.surf_sense[0] + + @forward_volume.setter + def forward_volume(self, volume: Volume): + self.surf_sense = [volume, self.reverse_volume] + + @property + def reverse_volume(self) -> Optional[Volume]: + """Volume with reverse sense with respect to the surface.""" + return self.surf_sense[1] + + @reverse_volume.setter + def reverse_volume(self, volume: Volume): + self.surf_sense = [self.forward_volume, volume] + + def get_volumes(self) -> list[Volume]: """Get the parent volumes of this surface. """ - return [Volume(self.model.mb, h) for h in self.model.mb.get_parent_meshsets(self.handle)] + return [Volume(self.model, h) for h in self.model.mb.get_parent_meshsets(self.handle)] def num_triangles(self): """Returns the number of triangles in this surface""" diff --git a/test/test_basic.py b/test/test_basic.py index 71bdc35..be68861 100644 --- a/test/test_basic.py +++ b/test/test_basic.py @@ -126,6 +126,24 @@ def test_volume(request): assert v1 not in model.groups['mat:fuel'] +def test_surface(request): + test_file = str(request.path.parent / 'fuel_pin.h5m') + model = dagmc.DAGModel(test_file) + + s1 = model.surfaces[1] + assert s1.get_volumes() == [model.volumes[1], model.volumes[2]] + assert s1.forward_volume == model.volumes[1] + assert s1.reverse_volume == model.volumes[2] + + s1.forward_volume = model.volumes[3] + assert s1.forward_volume == model.volumes[3] + assert s1.surf_sense == [model.volumes[3], model.volumes[2]] + + s1.reverse_volume = model.volumes[1] + assert s1.reverse_volume == model.volumes[1] + assert s1.surf_sense == [model.volumes[3], model.volumes[1]] + + def test_hash(request): test_file = str(request.path.parent / 'fuel_pin.h5m') model = dagmc.DAGModel(test_file)