@@ -170,6 +170,83 @@ def groups_by_name(self) -> Dict[str, Group]:
170170 def group_names (self ) -> list [str ]:
171171 return self .groups_by_name .keys ()
172172
173+ @property
174+ def implicit_complement (self ) -> Optional [Volume ]:
175+ """
176+ Returns the implicit complement volume.
177+
178+ The implicit complement volume is identified as the volume
179+ that has the material 'Graveyard'.
180+ """
181+ for volume in self .volumes :
182+ if volume .material == 'Graveyard' :
183+ return volume
184+ return None
185+
186+ @property
187+ def implicit_complement_material (self ) -> Optional [str ]:
188+ """
189+ The material of the implicit complement.
190+ """
191+ # Find group with name like 'mat:*_comp'
192+ for group in self .groups :
193+ if group .name and group .name .startswith ('mat:' ) and group .name .endswith ('_comp' ):
194+ return group .name .removeprefix ('mat:' ).removesuffix ('_comp' )
195+ return None
196+
197+ @implicit_complement_material .setter
198+ def implicit_complement_material (self , material_name : Optional [str ]):
199+ """
200+ Set the material of the implicit complement.
201+ """
202+ # First, find and unset any existing implicit complement material group
203+ for group in self .groups :
204+ if group .name and group .name .startswith ('mat:' ) and group .name .endswith ('_comp' ):
205+ group .name = group .name .removesuffix ('_comp' )
206+ break
207+
208+ if material_name is not None :
209+ # Find the group for the new material
210+ material_group_name = f"mat:{ material_name } "
211+ if material_group_name in self .groups_by_name :
212+ group = self .groups_by_name [material_group_name ]
213+ group .name = f"{ group .name } _comp"
214+ else :
215+ # If the group does not exist, we need to find the graveyard and assign it.
216+ graveyard = self .implicit_complement
217+ if graveyard is None :
218+ raise ValueError ("Could not identify the implicit complement volume." )
219+ graveyard .material = material_name
220+ graveyard .material_group .name = f"{ graveyard .material_group .name } _comp"
221+
222+ @property
223+ def default_material (self ) -> Optional [str ]:
224+ """
225+ The default material for volumes without a material.
226+ """
227+ for group in self .groups :
228+ if group .name and group .name .startswith ('pydagmc:default_material:' ):
229+ return group .name .split (':' )[- 1 ]
230+ return None
231+
232+ @default_material .setter
233+ def default_material (self , material_name : Optional [str ]):
234+ """
235+ Set the default material for volumes without a material.
236+ """
237+ # First, remove any existing default material marker
238+ for group in self .groups :
239+ if group .name and group .name .startswith ('pydagmc:default_material:' ):
240+ group .delete ()
241+ break
242+
243+ if material_name is not None :
244+ # Assign the material to all volumes without one.
245+ for volume in self .volumes_without_material :
246+ volume .material = material_name
247+ # Create a marker group to store the default material name
248+ self .create_group (name = f'pydagmc:default_material:{ material_name } ' )
249+
173250 def __repr__ (self ):
174251 return f'{ type (self ).__name__ } : { len (self .volumes )} Volumes, { len (self .surfaces )} Surfaces, { len (self .groups )} Groups'
175252
@@ -670,11 +747,17 @@ def material_group(self) -> Optional[Group]:
670747 @property
671748 def material (self ) -> Optional [str ]:
672749 """Name of the material assigned to this volume."""
673- return self ._metadata_group_name (self ._material_prefix )
750+ name = self ._metadata_group_name (self ._material_prefix )
751+ if name :
752+ return name .removesuffix ('_comp' )
753+ return None
674754
675755 @material .setter
676756 def material (self , name : str ):
757+ is_comp = self .material_group and self .material_group .name .endswith ('_comp' )
677758 self ._set_metadata_group (self ._material_prefix , name )
759+ if is_comp :
760+ self .material_group .name += '_comp'
678761
679762 @property
680763 def surfaces (self ) -> list [Surface ]:
@@ -732,11 +815,13 @@ def name(self) -> Optional[str]:
732815
733816 @name .setter
734817 def name (self , val : str ):
735- if val .lower () in self .model .group_names :
818+ current_name = self .name
819+ if val .lower () in self .model .group_names and val .lower () != current_name .lower ():
736820 raise ValueError (f'Group { val } already used in model.' )
737821
738822 self .model .mb .tag_set_data (self .model .name_tag , self .handle , val )
739823
824+
740825 def _get_geom_ent_by_id (self , entity_type , id ):
741826 category_ents = self .model .mb .get_entities_by_type_and_tag (self .handle , types .MBENTITYSET , [self .model .category_tag ], [entity_type ])
742827 ids = self .model .mb .tag_get_data (self .model .id_tag , category_ents , flat = True )
0 commit comments