@@ -155,36 +155,33 @@ def config(self):
155155 config ["interface" ] = self .interface
156156 return config
157157
158- def cell_size (self ):
159- return self .interface .cell_size (self .mt .restriction )
160-
161- def jacobian_at (self , point ):
162- ps = PointSingleton (point )
163- expr = Jacobian (extract_unique_domain (self .mt .terminal ))
164- assert ps .expression .shape == (extract_unique_domain (expr ).topological_dimension (), )
158+ def translate_point_expression (self , expr , point = None ):
165159 if self .mt .restriction == '+' :
166160 expr = PositiveRestricted (expr )
167161 elif self .mt .restriction == '-' :
168162 expr = NegativeRestricted (expr )
163+
164+ cell = self .interface .fiat_cell
165+ sd = cell .get_spatial_dimension ()
166+ if point is None :
167+ point , = cell .make_points (sd , 0 , sd + 1 )
169168 config = {"point_set" : PointSingleton (point )}
170169 config .update (self .config )
171170 config .update (use_canonical_quadrature_point_ordering = False ) # quad point ordering not relevant.
172171 context = PointSetContext (** config )
173172 expr = self .preprocess (expr , context )
174173 return map_expr_dag (context .translator , expr )
175174
175+ def cell_size (self ):
176+ return self .interface .cell_size (self .mt .restriction )
177+
178+ def jacobian_at (self , point ):
179+ expr = Jacobian (extract_unique_domain (self .mt .terminal ))
180+ return self .translate_point_expression (expr , point = point )
181+
176182 def detJ_at (self , point ):
177183 expr = JacobianDeterminant (extract_unique_domain (self .mt .terminal ))
178- if self .mt .restriction == '+' :
179- expr = PositiveRestricted (expr )
180- elif self .mt .restriction == '-' :
181- expr = NegativeRestricted (expr )
182- config = {"point_set" : PointSingleton (point )}
183- config .update (self .config )
184- config .update (use_canonical_quadrature_point_ordering = False ) # quad point ordering not relevant.
185- context = PointSetContext (** config )
186- expr = self .preprocess (expr , context )
187- return map_expr_dag (context .translator , expr )
184+ return self .translate_point_expression (expr , point = point )
188185
189186 def reference_normals (self ):
190187 cell = self .interface .fiat_cell
@@ -210,30 +207,25 @@ def physical_tangents(self):
210207
211208 def physical_normals (self ):
212209 cell = self .interface .fiat_cell
213- if not (isinstance (cell , UFCSimplex ) and cell .get_dimension () == 2 ):
210+ sd = cell .get_spatial_dimension ()
211+ num_faces = len (cell .get_topology ()[sd - 1 ])
212+ if isinstance (cell , UFCSimplex ) and sd == 2 :
213+ pts = self .physical_tangents ()
214+ return gem .ListTensor ([[pts [i , 1 ], - 1 * pts [i , 0 ]] for i in range (num_faces )])
215+ elif isinstance (cell , UFCSimplex ) and sd == 3 :
216+ t = ufl .classes .CellEdgeVectors (extract_unique_domain (self .mt .terminal ))
217+ edges = cell .get_connectivity ()[(sd - 1 , 1 )]
218+ normalize = lambda x : x / ufl .sqrt (ufl .dot (x , x ))
219+ expr = ufl .as_tensor ([- 2.0 * normalize (ufl .cross (t [edges [i ][0 ], :], t [edges [i ][1 ], :]))
220+ for i in range (num_faces )])
221+ return self .translate_point_expression (expr )
222+ else :
214223 raise NotImplementedError ("Can't do physical normals on that cell yet" )
215224
216- num_edges = len (cell .get_topology ()[1 ])
217- pts = self .physical_tangents ()
218- return gem .ListTensor ([[pts [i , 1 ], - 1 * pts [i , 0 ]] for i in range (num_edges )])
219-
220225 def physical_edge_lengths (self ):
221226 expr = ufl .classes .CellEdgeVectors (extract_unique_domain (self .mt .terminal ))
222- if self .mt .restriction == '+' :
223- expr = PositiveRestricted (expr )
224- elif self .mt .restriction == '-' :
225- expr = NegativeRestricted (expr )
226-
227- cell = self .interface .fiat_cell
228- sd = cell .get_spatial_dimension ()
229- num_edges = len (cell .get_topology ()[1 ])
230- expr = ufl .as_vector ([ufl .sqrt (ufl .dot (expr [i , :], expr [i , :])) for i in range (num_edges )])
231- config = {"point_set" : PointSingleton (cell .make_points (sd , 0 , sd + 1 )[0 ])}
232- config .update (self .config )
233- config .update (use_canonical_quadrature_point_ordering = False ) # quad point ordering not relevant.
234- context = PointSetContext (** config )
235- expr = self .preprocess (expr , context )
236- return map_expr_dag (context .translator , expr )
227+ expr = ufl .as_vector ([ufl .sqrt (ufl .dot (expr [i , :], expr [i , :])) for i in range (expr .ufl_shape [0 ])])
228+ return self .translate_point_expression (expr )
237229
238230 def physical_points (self , point_set , entity = None ):
239231 """Converts point_set from reference to physical space"""
0 commit comments