Evaluate Expression on entities. Args: mesh: Mesh to evaluate Expression on. entities: Entities to evaluate the Expression over. For cells, it is a list of cell indices. For facets, it is a 2D array of (cell index, local facet index).
(
self,
mesh: Mesh,
entities: npt.NDArray[np.int32],
values: npt.NDArray[Scalar] | None = None,
)
| 232 | ) |
| 233 | |
| 234 | def eval( |
| 235 | self, |
| 236 | mesh: Mesh, |
| 237 | entities: npt.NDArray[np.int32], |
| 238 | values: npt.NDArray[Scalar] | None = None, |
| 239 | ) -> npt.NDArray[Scalar]: |
| 240 | """Evaluate Expression on entities. |
| 241 | |
| 242 | Args: |
| 243 | mesh: Mesh to evaluate Expression on. |
| 244 | entities: Entities to evaluate the Expression over. For |
| 245 | cells, it is a list of cell indices. For facets, it is a |
| 246 | 2D array of (cell index, local facet index). |
| 247 | values: Array to fill with evaluated values. If ``None``, |
| 248 | storage will be allocated. Otherwise it must have shape |
| 249 | ``(entities.shape[0], num_points, *value_shape)`` if |
| 250 | there is not argument function and shape |
| 251 | ``(entities.shape[0], num_points, *value_shape, |
| 252 | argument_space_dim)`` if the Expression does have an |
| 253 | argument function. |
| 254 | |
| 255 | Returns: |
| 256 | Expression evaluated at points for ``entities``. Shape is |
| 257 | ``(entities.shape[0], num_points, *value_shape)`` if there |
| 258 | is no argument function, or shape is ``(entities.shape[0], |
| 259 | num_points, *value_shape, argument_space_dim)`` if the |
| 260 | Expression does have an argument function. |
| 261 | """ |
| 262 | _entities = np.asarray(entities, dtype=np.int32) |
| 263 | if (tdim := mesh.topology.dim) != (expr_dim := self._cpp_object.X().shape[1]): |
| 264 | assert expr_dim == tdim - 1 |
| 265 | assert entities.ndim == 2, ( |
| 266 | "entities list should have two dimensions for expression evaluation on facets." |
| 267 | ) |
| 268 | |
| 269 | if self.argument_space is None: |
| 270 | values_shape = (_entities.shape[0], self.X().shape[0], *self.value_shape) |
| 271 | else: |
| 272 | values_shape = ( |
| 273 | _entities.shape[0], |
| 274 | self.X().shape[0], |
| 275 | *self.value_shape, |
| 276 | self.argument_space.element.space_dimension, |
| 277 | ) |
| 278 | |
| 279 | # Allocate memory for result if u was not provided |
| 280 | if values is None: |
| 281 | values = np.zeros(values_shape, dtype=self.dtype) |
| 282 | else: |
| 283 | if values.shape != values_shape: |
| 284 | raise TypeError("Passed values array does not have correct shape.") |
| 285 | if values.dtype != self.dtype: |
| 286 | raise TypeError("Passed values array does not have correct dtype.") |
| 287 | |
| 288 | constants = _cpp.fem.pack_constants(self._cpp_object) |
| 289 | coeffs = _cpp.fem.pack_coefficients(self._cpp_object, mesh._cpp_object, _entities) |
| 290 | _cpp.fem.tabulate_expression( |
| 291 | values, self._cpp_object, constants, coeffs, mesh._cpp_object, _entities |