underworld.function module

The function module contains the Function class, and related classes.

Function objects are constructed in python, but evaluated in C for efficiency. They provide a high level interface for users to compose model behaviour (such as viscosity), as well as a natural interface by which discrete data (such as meshvariables) may be utilised.

Module Summary

classes:

underworld.function.Function Objects which inherit from this class provide user definable functions within Underworld.
underworld.function.FunctionInput Objects that inherit from this class are able to act as inputs to function evaluation from python.
underworld.function.coord alias of underworld.function._function.input
underworld.function.input This class generates a function which simply passes through its input.

Module Details

classes:

class underworld.function.Function(argument_fns, **kwargs)[source]

Bases: underworld._stgermain.LeftOverParamsChecker

Objects which inherit from this class provide user definable functions within Underworld.

Functions aim to achieve a number of goals: * Provide a natural interface for mathematical behaviour description within python. * Provide a high level interface to Underworld discrete objects. * Allow discrete objects to be used in combination with continuous objects. * Handle the evaluation of discrete objects in the most efficient manner. * Perform all heavy calculations at the C-level for efficiency. * Provide an interface for users to evaluate functions directly within python, utilising numpy arrays for input/output.

__add__(other)[source]

Operator overloading for ‘+’ operation:

Fn3 = Fn1 + Fn2

Creates a new function Fn3 which performs additions of Fn1 and Fn2.

Returns:fn.add
Return type:Add function

Examples

>>> import misc
>>> import numpy as np
>>> three = misc.constant(3.)
>>> four  = misc.constant(4.)
>>> np.allclose( (three + four).evaluate(0.), [[ 7.]]  )  # note we can evaluate anywhere because it's a constant
True
__and__(other)[source]

Operator overloading for ‘&’ operation:

Fn3 = Fn1 & Fn2

Creates a new function Fn3 which returns a bool result for the operation.

Returns:fn.logical_and
Return type:AND function

Examples

>>> import misc
>>> trueFn  = misc.constant(True)
>>> falseFn = misc.constant(False)
>>> (trueFn & falseFn).evaluate()
array([[False]], dtype=bool)

Notes

The ‘&’ operator in python is usually used for bitwise ‘and’ operations, with the ‘and’ operator used for boolean type operators. It is not possible to overload the ‘and’ operator in python, so instead the bitwise equivalent has been utilised.

__div__(other)[source]

Operator overloading for ‘/’ operation:

Fn3 = Fn1 / Fn2

Creates a new function Fn3 which returns the quotient of Fn1 and Fn2.

Returns:fn.divide
Return type:Divide function

Examples

>>> import misc
>>> import numpy as np
>>> two  = misc.constant(2.)
>>> four = misc.constant(4.)
>>> np.allclose( (four/two).evaluate(0.), [[ 2.]]  )  # note we can evaluate anywhere because it's a constant
True
__ge__(other)[source]

Operator overloading for ‘>=’ operation:

Fn3 = Fn1 >= Fn2

Creates a new function Fn3 which returns a bool result for the relation.

Returns:fn.greater_equal
Return type:Greater than or equal to function

Examples

>>> import misc
>>> import numpy as np
>>> two  = misc.constant(2.)
>>> (two >= two).evaluate()
array([[ True]], dtype=bool)
__getitem__(index)[source]

Operator overloading for ‘[]’ operation:

FnComponent = Fn[0]

Creates a new function FnComponent which returns the required component of Fn.

Returns:fn.at
Return type:component function

Examples

>>> import misc
>>> fn  = misc.constant((2.,3.,4.))
>>> np.allclose( fn[1].evaluate(0.), [[ 3.]]  )  # note we can evaluate anywhere because it's a constant
True
__gt__(other)[source]

Operator overloading for ‘>’ operation:

Fn3 = Fn1 > Fn2

Creates a new function Fn3 which returns a bool result for the relation.

Returns:fn.greater
Return type:Greater than function

Examples

>>> import misc
>>> import numpy as np
>>> two  = misc.constant(2.)
>>> four = misc.constant(4.)
>>> (two > four).evaluate()
array([[False]], dtype=bool)
__le__(other)[source]

Operator overloading for ‘<=’ operation:

Fn3 = Fn1 <= Fn2

Creates a new function Fn3 which returns a bool result for the relation.

Returns:fn.less_equal
Return type:Less than or equal to function

Examples

>>> import misc
>>> import numpy as np
>>> two  = misc.constant(2.)
>>> (two <= two).evaluate()
array([[ True]], dtype=bool)
__lt__(other)[source]

Operator overloading for ‘<’ operation:

Fn3 = Fn1 < Fn2

Creates a new function Fn3 which returns a bool result for the relation.

Returns:fn.less
Return type:Less than function

Examples

>>> import misc
>>> import numpy as np
>>> two  = misc.constant(2.)
>>> four = misc.constant(4.)
>>> (two < four).evaluate()
array([[ True]], dtype=bool)
__mul__(other)[source]

Operator overloading for ‘*’ operation:

Fn3 = Fn1 * Fn2

Creates a new function Fn3 which returns the product of Fn1 and Fn2.

Returns:fn.multiply
Return type:Multiply function

Examples

>>> import misc
>>> import numpy as np
>>> three = misc.constant(3.)
>>> four  = misc.constant(4.)
>>> np.allclose( (three*four).evaluate(0.), [[ 12.]]  )  # note we can evaluate anywhere because it's a constant
True
__neg__()[source]

Operator overloading for unary ‘-‘.

FnNeg = -Fn

Creates a new function FnNeg which is the negative of Fn.

Returns:fn.multiply
Return type:Negative function

Examples

>>> import misc
>>> import numpy as np
>>> four = misc.constant(4.)
>>> np.allclose( (-four).evaluate(0.), [[ -4.]]  )  # note we can evaluate anywhere because it's a constant
True
__or__(other)[source]

Operator overloading for ‘|’ operation:

Fn3 = Fn1 | Fn2

Creates a new function Fn3 which returns a bool result for the operation.

Returns:fn.logical_or
Return type:OR function

Examples

>>> import misc
>>> trueFn  = misc.constant(True)
>>> falseFn = misc.constant(False)
>>> (trueFn | falseFn).evaluate()
array([[ True]], dtype=bool)

Notes

The ‘|’ operator in python is usually used for bitwise ‘or’ operations, with the ‘or’ operator used for boolean type operators. It is not possible to overload the ‘or’ operator in python, so instead the bitwise equivalent has been utilised.

__pow__(other)[source]

Operator overloading for ‘**’ operation:

Fn3 = Fn1 ** Fn2

Creates a new function Fn3 which returns Fn1 to the power of Fn2.

Returns:fn.math.pow
Return type:Power function

Examples

>>> import misc
>>> import numpy as np
>>> two  = misc.constant(2.)
>>> four = misc.constant(4.)
>>> np.allclose( (two**four).evaluate(0.), [[ 16.]]  )  # note we can evaluate anywhere because it's a constant
True
__radd__(other)

Operator overloading for ‘+’ operation:

Fn3 = Fn1 + Fn2

Creates a new function Fn3 which performs additions of Fn1 and Fn2.

Returns:fn.add
Return type:Add function

Examples

>>> import misc
>>> import numpy as np
>>> three = misc.constant(3.)
>>> four  = misc.constant(4.)
>>> np.allclose( (three + four).evaluate(0.), [[ 7.]]  )  # note we can evaluate anywhere because it's a constant
True
__rmul__(other)

Operator overloading for ‘*’ operation:

Fn3 = Fn1 * Fn2

Creates a new function Fn3 which returns the product of Fn1 and Fn2.

Returns:fn.multiply
Return type:Multiply function

Examples

>>> import misc
>>> import numpy as np
>>> three = misc.constant(3.)
>>> four  = misc.constant(4.)
>>> np.allclose( (three*four).evaluate(0.), [[ 12.]]  )  # note we can evaluate anywhere because it's a constant
True
__rsub__(other)[source]

Operator overloading for ‘-‘ operation. Right hand version.

Fn3 = Fn1 - Fn2

Creates a new function Fn3 which performs subtraction of Fn2 from Fn1.

Returns:fn.subtract
Return type:RHS subtract function

Examples

>>> import misc
>>> import numpy as np
>>> four  = misc.constant(4.)
>>> np.allclose( (5. - four).evaluate(0.), [[ 1.]]  )  # note we can evaluate anywhere because it's a constant
True
__sub__(other)[source]

Operator overloading for ‘-‘ operation:

Fn3 = Fn1 - Fn2

Creates a new function Fn3 which performs subtraction of Fn2 from Fn1.

Returns:fn.subtract
Return type:Subtract function

Examples

>>> import misc
>>> import numpy as np
>>> three = misc.constant(3.)
>>> four  = misc.constant(4.)
>>> np.allclose( (three - four).evaluate(0.), [[ -1.]]  )  # note we can evaluate anywhere because it's a constant
True
__xor__(other)[source]

Operator overloading for ‘^’ operation:

Fn3 = Fn1 ^ Fn2

Creates a new function Fn3 which returns a bool result for the operation.

Returns:fn.logical_xor
Return type:XOR function

Examples

>>> import misc
>>> trueFn  = misc.constant(True)
>>> falseFn = misc.constant(False)
>>> (trueFn ^ falseFn).evaluate()
array([[ True]], dtype=bool)
>>> (trueFn ^ trueFn).evaluate()
array([[False]], dtype=bool)
>>> (falseFn ^ falseFn).evaluate()
array([[False]], dtype=bool)

Notes

The ‘^’ operator in python is usually used for bitwise ‘xor’ operations, however here we always use the logical version, with the operation inputs cast to their bool equivalents before the operation.

static convert(obj)[source]

This method will attempt to convert the provided input into an equivalent underworld function. If the provided input is already of Function type, it is immediately returned. Likewise, if the input is of None type, it is also returned.

Parameters:obj (fn_like) – The object to be converted. Note that if obj is of type None or Function, it is simply returned immediately. Where obj is of type int/float/double, a Constant type function is returned which evaluates to the provided object’s value. Where obj is of type list/tuple, a function will be returned which evaluates to a vector of the provided list/tuple’s values (where possible).
Returns:
Return type:Fn.Function or None.

Examples

>>> import underworld as uw
>>> import underworld.function as fn
>>> fn_const = fn.Function.convert( 3 )
>>> fn_const.evaluate(0.) # eval anywhere for constant
array([[3]], dtype=int32)
>>> fn_const == fn.Function.convert( fn_const )
True
>>> fn.Function.convert( None )
>>> fn1 = fn.input()
>>> fn2 = 10.*fn.input()
>>> fn3 = 100.*fn.input()
>>> vec = (fn1,fn2,fn3)
>>> fn_vec = fn.Function.convert(vec)
>>> fn_vec.evaluate([3.])
array([[   3.,   30.,  300.]])
evaluate(inputData=None, inputType=None)[source]

This method performs evaluate of a function at the given input(s).

It accepts floats, lists, tuples, numpy arrays, or any object which is of class FunctionInput. lists/tuples must contain floats only.

FunctionInput class objects are shortcuts to their underlying data, often with performance advantages, and sometimes they are the only valid input type (such as using Swarm objects as an inputs to SwarmVariable evaluation). Objects of class FeMesh, Swarm, FeMesh_IndexSet and VoronoiIntegrationSwarm are also of class FunctionInput. See the Function section of the user guide for more information.

Results are returned as numpy array.

Parameters:
  • inputData (float, list, tuple, ndarray, underworld.function.FunctionInput) – The input to the function. The form of this input must be appropriate for the function being evaluated, or an exception will be thrown. Note that if no input is provided, function will be evaluated at 0.
  • inputType (str) – Specifies the type the provided data represents. Acceptable values are ‘scalar’, ‘vector’, ‘symmetrictensor’, ‘tensor’, ‘array’.
Returns:

ndarray

Return type:

array of results

Examples

>>> from . import _systemmath as math
>>> import underworld.function.math as fnmath
>>> sinfn = fnmath.sin()

Single evaluation:

>>> np.allclose( sinfn.evaluate(math.pi/4.), [[ 0.5*math.sqrt(2.)]]  )
True

Multiple evaluations

>>> input = (0.,math.pi/4.,2.*math.pi)
>>> np.allclose( sinfn.evaluate(input), [[ 0., 0.5*math.sqrt(2.), 0.]]  )
True

Single MeshVariable evaluations

>>> mesh = uw.mesh.FeMesh_Cartesian()
>>> var = uw.mesh.MeshVariable(mesh,1)
>>> import numpy as np
>>> var.data[:,0] = np.linspace(0,1,len(var.data))
>>> result = var.evaluate( (0.2,0.5 ) )
>>> np.allclose( result, np.array([[ 0.45]]) )
True

Numpy input MeshVariable evaluation

>>> # evaluate at a set of locations.. provide these as a numpy array.
>>> count = 10
>>> # create an empty array
>>> locations = np.zeros( (count,2))
>>> # specify evaluation coodinates
>>> locations[:,0] = 0.5
>>> locations[:,1] = np.linspace(0.,1.,count)
>>> # evaluate
>>> result = var.evaluate(locations)
>>> np.allclose( result, np.array([[ 0.08333333],                                           [ 0.17592593],                                           [ 0.26851852],                                           [ 0.36111111],                                           [ 0.4537037 ],                                           [ 0.5462963 ],                                           [ 0.63888889],                                           [ 0.73148148],                                           [ 0.82407407],                                           [ 0.91666667]])  )
True

Using the mesh object as a FunctionInput

>>> np.allclose( var.evaluate(mesh), var.evaluate(mesh.data))
True
evaluate_global(inputData, inputType=None)[source]

This method attempts to evalute inputData across all processes, and then consolide the results on the root processor. This is most useful where you wish to evalute your functions using global coordinates which may span processes in a parallel simulation.

Note that this method does not currently support ‘FunctionInput’ class input data.

Due to the communications required for this method, a significant performance overhead may be encountered. The standard evaluate method should be used instead wherever possible.

Please see evaluate method for parameter details.

Notes

This method must be called collectively by all processes.

Returns:
  • Only the root process gets the final results array. All other processes
  • are returned None.
integrate(mesh)[source]

Perform an integral of this underworld function over the given mesh

Parameters:mesh (uw.mesh.FeMesh_Cartesian) – Domain to perform integral over.

Examples

>>> mesh = uw.mesh.FeMesh_Cartesian(minCoord=(0.0,0.0), maxCoord=(1.0,2.0))
>>> fn_1 = uw.function.misc.constant(2.0)
>>> np.allclose( fn_1.integrate( mesh )[0], 4 )
True
>>> fn_2 = uw.function.misc.constant(2.0) * (0.5, 1.0)
>>> np.allclose( fn_2.integrate( mesh ), [2,4] )
True
class underworld.function.FunctionInput(*args, **kwargs)[source]

Bases: underworld._stgermain.LeftOverParamsChecker

Objects that inherit from this class are able to act as inputs to function evaluation from python.

underworld.function.coord

alias of underworld.function._function.input

class underworld.function.input(*args, **kwargs)[source]

Bases: underworld.function._function.Function

This class generates a function which simply passes through its input. It is the identity function. It is often useful when construct functions where the input itself needs to be accessed, such as to extract a particular component.

For example, you may wish to use this function when you wish to extract a particular coordinate component for manipulation. For this reason, we also provide an alias to this class called ‘coord’.

Returns:fn.input
Return type:the input function

Examples

Here we see the input function simply passing through its input.

>>> infunc = input()
>>> np.allclose( infunc.evaluate( (1.,2.,3.) ), [ 1., 2., 3.] )
True

Often this behaviour is useful when we want to construct a function which operates on only a particular coordinate, such as a depth dependent density. We may wish to extract the z coordinate (in 2d):

>>> zcoord = input()[1]
>>> baseDensity = 1.
>>> density = baseDensity - 0.01*zcoord
>>> testCoord1 = (0.1,0.4)
>>> testCoord2 = (0.9,0.4)
>>> np.allclose( density.evaluate( testCoord1 ), density.evaluate( testCoord2 ) )
True