Function

The function module defines the Evaluable class and derived objects, commonly referred to as nutils functions. They represent mappings from a nutils.topology onto Python space. The notabe class of Array objects map onto the space of Numpy arrays of predefined dimension and shape. Most functions used in nutils applicatons are of this latter type, including the geometry and function bases for analysis.

Nutils functions are essentially postponed python functions, stored in a tree structure of input/output dependencies. Many Array objects have directly recognizable numpy equivalents, such as Sin or Inverse. By not evaluating directly but merely stacking operations, complex operations can be defined prior to entering a quadrature loop, allowing for a higher level style programming. It also allows for automatic differentiation and code optimization.

It is important to realize that nutils functions do not map for a physical xy-domain but from a topology, where a point is characterized by the combination of an element and its local coordinate. This is a natural fit for typical finite element operations such as quadrature. Evaluation from physical coordinates is possible only via inverting of the geometry function, which is a fundamentally expensive and currently unsupported operation.

class nutils.function.Evaluable(args: tuple)[source]

Base class

asciitree(seen=None)[source]

string representation

graphviz()[source]

create function graph

stackstr(nlines=-1)[source]

print stack

exception nutils.function.EvaluationError(etype, evalue, evaluable, values)[source]

evaluation error

class nutils.function.Array(args: tuple, shape: tuple, dtype: <function <lambda> at 0x7fa7565db950>)[source]

array function

class nutils.function.Normal(lgrad: <function <lambda> at 0x7fa7565db9d8>)[source]

normal

class nutils.function.ArrayFunc(args: tuple, shape: tuple)[source]

deprecated ArrayFunc alias

class nutils.function.Interpolate(x: <function <lambda> at 0x7fa7565db9d8>, xp: nutils.numeric.const, fp: nutils.numeric.const, left=None, right=None)[source]

interpolate uniformly spaced data; stepwise for now

class nutils.function.BlockAdd(funcs: nutils.util.frozenmultiset)[source]

block addition (used for DG)

class nutils.function.Sampled(data: nutils.util.frozendict, trans=<nutils.function.SelectChain object>)[source]

sampled

class nutils.function.Zeros(shape: tuple, dtype: <function <lambda> at 0x7fa7565db950>)[source]

zero

class nutils.function.Guard(fun: <function <lambda> at 0x7fa7565db9d8>)[source]

bar all simplifications

class nutils.function.TrigNormal(angle: <function <lambda> at 0x7fa7565db9d8>)[source]

cos, sin

class nutils.function.TrigTangent(angle: <function <lambda> at 0x7fa7565db9d8>)[source]

-sin, cos

class nutils.function.Find(where: <function <lambda> at 0x7fa7565db9d8>)[source]

indices of boolean index vector

class nutils.function.DerivativeTargetBase(args: tuple, shape: tuple, dtype: <function <lambda> at 0x7fa7565db950>)[source]

base class for derivative targets

class nutils.function.Argument(name, shape: tuple, nderiv: int = 0)[source]

Array argument, to be substituted before evaluation.

The Argument is an Array with a known shape, but whose values are to be defined later, before evaluation, e.g. using replace_arguments().

It is possible to take the derivative of an Array to an Argument:

>>> from nutils import function
>>> a = function.Argument('x', [])
>>> b = function.Argument('y', [])
>>> f = a**3 + b**2
>>> function.derivative(f, a).simplified == (3.*a**2).simplified
True

Furthermore, derivatives to the local cooardinates are remembered and applied to the replacement when using replace_arguments():

>>> from nutils import mesh
>>> domain, x = mesh.rectilinear([2,2])
>>> basis = domain.basis('spline', degree=2)
>>> c = function.Argument('c', basis.shape)
>>> replace_arguments(c.grad(x), dict(c=basis)) == basis.grad(x)
True
Parameters:
  • name (str) – The Identifier of this argument.
  • shape (tuple of ints) – The shape of this argument.
  • nderiv (int, non-negative) – Number of times a derivative to the local coordinates is taken. Default: 0.
class nutils.function.LocalCoords(ndims: int)[source]

local coords derivative target

class nutils.function.Polyval(coeffs: <function <lambda> at 0x7fa7565db9d8>, points: <function <lambda> at 0x7fa7565db9d8>, ngrad: int = 0)[source]

Computes the \(k\)-dimensional array

\[\begin{split}j_0,\dots,j_{k-1} \mapsto \sum_{\substack{i_0,\dots,i_{n-1}\in\mathbb{N}\\i_0+\cdots+i_{n-1}\le d}} p_0^{i_0} \cdots p_{n-1}^{i_{n-1}} c_{j_0,\dots,j_{k-1},i_0,\dots,i_{n-1}},\end{split}\]

where \(p\) are the \(n\)-dimensional local coordinates and \(c\) is the argument coeffs and \(d\) is the degree of the polynomial, where \(d\) is the length of the last \(n\) axes of coeffs.

Warning

All coefficients with a (combined) degree larger than \(d\) should be zero. Failing to do so won’t raise an Exception, but might give incorrect results.

nutils.function.chain(funcs)[source]
nutils.function.bringforward(arg, axis)[source]

bring axis forward

nutils.function.matmat(arg0, *args)[source]

helper function, contracts last axis of arg0 with first axis of arg1, etc

nutils.function.derivative(func, var, seen=None)[source]
nutils.function.localgradient(arg, ndims)[source]

local derivative

nutils.function.outer(arg1, arg2=None, axis=0)[source]

outer product

nutils.function.polyfunc(coeffs, dofs, ndofs, transforms, *, issorted=True)[source]

Create an inflated Polyval with coefficients coeffs and corresponding dofs dofs. The arguments coeffs, dofs and transforms are assumed to have matching order. In addition, if issorted is true, the transforms argument is assumed to be sorted.

nutils.function.find(arg)[source]
nutils.function.replace_arguments(value, arguments)[source]

Replace Argument objects in value.

Replace Argument objects in value according to the arguments map, taking into account derivatives to the local coordinates.

Parameters:
Returns:

The edited value.

Return type:

Array

class nutils.function.Namespace(*, default_geometry_name='x')[source]

Namespace for Array objects supporting assignments with tensor expressions.

The Namespace object is used to store Array objects.

>>> from nutils import function
>>> ns = function.Namespace()
>>> ns.A = function.zeros([3, 3])
>>> ns.x = function.zeros([3])
>>> ns.c = 2

In addition to the assignment of Array objects, it is also possible to specify an array using a tensor expression string — see nutils.expression.parse() for the syntax. All attributes defined in this namespace are available as variables in the expression. If the array defined by the expression has one or more dimensions the indices of the axes should be appended to the attribute name. Examples:

>>> ns.cAx_i = 'c A_ij x_j'
>>> ns.xAx = 'x_i A_ij x_j'

It is also possible to simply evaluate an expression without storing its value in the namespace by passing the expression to the method eval_ suffixed with appropriate indices:

>>> ns.eval_('2 c')
Array<>
>>> ns.eval_i('c A_ij x_j')
Array<3>
>>> ns.eval_ij('A_ij + A_ji')
Array<3,3>

For zero and one dimensional expressions the following shorthand can be used:

>>> '2 c' @ ns
Array<>
>>> 'A_ij x_j' @ ns
Array<3>

When evaluating an expression through this namespace the following functions are available: opposite, sin, cos, tan, sinh, cosh, tanh, arcsin, arccos, arctan2, arctanh, exp, abs, ln, log, log2, log10, sqrt and sign.

Parameters:default_geometry_name (str) – The name of the default geometry. This argument is passed to nutils.expression.parse(). Default: 'x'.
arg_shapes

types.MappingProxyType – A readonly map of argument names and shapes.

default_geometry_name

str – The name of the default geometry. See argument with the same name.

default_geometry

nutils.function.Array – The default geometry, shorthand for getattr(ns, ns.default_geometry_name).

copy_(*, default_geometry_name=None)[source]

Return a copy of this namespace.