@@ -228,6 +228,8 @@ class DOFDesc:
228228 .. automethod:: with_domain_tag
229229 .. automethod:: with_discr_tag
230230 .. automethod:: trace
231+ .. automethod:: untrace
232+ .. automethod:: with_boundary_tag
231233
232234 .. automethod:: __eq__
233235 .. automethod:: __ne__
@@ -317,6 +319,30 @@ def trace(self, btag: BoundaryTag) -> "DOFDesc":
317319 return replace (self ,
318320 domain_tag = BoundaryDomainTag (btag , volume_tag = self .domain_tag .tag ))
319321
322+ def untrace (self ) -> "DOFDesc" :
323+ """Return a :class:`DOFDesc` for the volume associated with the boundary
324+ descriptor *self*.
325+
326+ An error is raised if this method is called on a non-boundary instance of
327+ :class:`DOFDesc`.
328+ """
329+ if not isinstance (self .domain_tag , BoundaryDomainTag ):
330+ raise ValueError (f"must originate on boundary, got '{ self .domain_tag } '" )
331+ return replace (self ,
332+ domain_tag = VolumeDomainTag (self .domain_tag .volume_tag ))
333+
334+ def with_boundary_tag (self , btag : BoundaryTag ) -> "DOFDesc" :
335+ """Return a :class:`DOFDesc` representing a boundary named by *btag*
336+ on the same volume as *self*.
337+
338+ An error is raised if this method is called on a non-boundary instance of
339+ :class:`DOFDesc`.
340+ """
341+ if not isinstance (self .domain_tag , BoundaryDomainTag ):
342+ raise ValueError (f"must originate on boundary, got '{ self .domain_tag } '" )
343+ return replace (self ,
344+ domain_tag = replace (self .domain_tag , tag = btag ))
345+
320346 def as_identifier (self ) -> str :
321347 """Returns a descriptive string for this :class:`DOFDesc` that is usable
322348 in Python identifiers.
0 commit comments