Example #1
0
    def __init__(self, fn=None, *args, **kwargs):

        self._fn = _Function.convert(fn)

        fncself = None
        if self._fn:
            fncself = self._fn._fncself

        # create instance
        self._fncself = _cfn.MathUnary_erf(fncself)

        # build parent
        super(erf, self).__init__(argument_fns=[
            fn,
        ], **kwargs)
Example #2
0
    def __init__(self, fn, *args, **kwargs):

        _fn = _Function.convert(fn)
        if _fn == None:
            raise ValueError("provided 'fn' must a 'Function' or convertible.")
        self._fn = _fn

        # create instance
        self._fncself = _cfn.TensorFunc(self._fn._fncself,
                                        _cfn.TensorFunc.get_antisymmetric)

        # build parent
        super(antisymmetric, self).__init__(argument_fns=[
            fn,
        ], **kwargs)
Example #3
0
    def __init__(self, fn1, fn2, **kwargs):
        fn1fn = Function.convert(fn1)
        if not isinstance(fn1fn, Function):
            raise TypeError(
                "Functions must be of type (or convertible to) 'Function'.")
        fn2fn = Function.convert(fn2)
        if not isinstance(fn2fn, Function):
            raise TypeError(
                "Functions must be of type (or convertible to) 'Function'.")

        self._fn1 = fn1fn
        self._fn2 = fn2fn
        # ok finally lets create the fn
        self._fncself = _cfn.Divide(self._fn1._fncself, self._fn2._fncself)
        # build parent
        super(divide, self).__init__(argument_fns=[fn1fn, fn2fn], **kwargs)
Example #4
0
    def __init__(self, fn1, fn2, **kwargs):
        fn1fn = _Function._CheckIsFnOrConvertOrThrow(fn1)
        if not isinstance(fn1fn, _Function):
            raise TypeError(
                "Functions must be of type (or convertible to) 'Function'.")
        fn2fn = _Function._CheckIsFnOrConvertOrThrow(fn2)
        if not isinstance(fn2fn, _Function):
            raise TypeError(
                "Functions must be of type (or convertible to) 'Function'.")

        self._fn1 = fn1fn
        self._fn2 = fn2fn
        # ok finally lets create the fn
        self._fncself = _cfn.Dot(self._fn1._fncself, self._fn2._fncself)
        # build parent
        super(dot, self).__init__(argument_fns=[fn1fn, fn2fn], **kwargs)
Example #5
0
 def _GetIOForPyInput(self, value):
     if isinstance(value, (int, float, bool)):
         if isinstance(value, bool):
             ioguy = _cfn.IO_bool(1, 0)
         elif isinstance(value, int):
             ioguy = _cfn.IO_int(1, 0)
         elif isinstance(value, float):
             ioguy = _cfn.IO_double(1, 0)
         else:
             raise RuntimeError(
                 "Failure during object creation. Please contact developers."
             )
         # now set val
         ioguy.value(value, 0)
     else:
         try:
             iterator = iter(value)
         except TypeError:
             raise ValueError(
                 "'value' object provided to Constant Function constructor does not appear to be valid. "
                 +
                 "Only python types 'int', 'float' and 'bool' are acceptable, or iterable objects "
                 + "homogeneous in these types.")
         else:
             # iterable
             tupleGuy = tuple(iterator)
             lenTupleGuy = len(tupleGuy)
             firstFella = tupleGuy[0]
             if isinstance(firstFella, bool):
                 ioguy = _cfn.IO_bool(lenTupleGuy, 3)
             elif isinstance(firstFella, int):
                 ioguy = _cfn.IO_int(lenTupleGuy, 3)
             elif isinstance(firstFella, float):
                 ioguy = _cfn.IO_double(lenTupleGuy, 3)
             else:
                 raise ValueError(
                     "'value' object provided to Constant Function appears to be an iterable, but "
                     +
                     "does not appear to contain objects of python type 'int', 'float' or 'bool'."
                 )
             # right, now load in ze data
             ii = 0
             for val in tupleGuy:
                 if not isinstance(val, type(firstFella)):
                     raise ValueError(
                         "'value' object provided to Constant Function appears to be an iterable, but "
                         +
                         "does not appear to be homogeneous in type. Objects in iterable must all be "
                         +
                         "of python type 'int', all of type 'float', or all of type 'bool'."
                     )
                 ioguy.value(val, ii)
                 ii += 1
     return ioguy
Example #6
0
    def __init__(self, x_Fn, y_Fn, **kwargs):
        fn1fn = Function._CheckIsFnOrConvertOrThrow(x_Fn)
        if not isinstance(fn1fn, Function):
            raise TypeError(
                "Functions must be of type (or convertible to) 'Function'.")
        fn2fn = Function._CheckIsFnOrConvertOrThrow(y_Fn)
        if not isinstance(fn2fn, Function):
            raise TypeError(
                "Functions must be of type (or convertible to) 'Function'.")

        self._fn1 = fn1fn
        self._fn2 = fn2fn
        # ok finally lets create the fn
        self._fncself = _cfn.MathBinary(self._fn1._fncself, self._fn2._fncself,
                                        _cfn.MathBinary.subtract)
        # build parent
        super(subtract, self).__init__(argument_fns=[fn1fn, fn2fn], **kwargs)
Example #7
0
    def __init__(self, fn1, fn2, **kwargs):
        # lets convert integer powers to floats
        if isinstance(fn2, int):
            fn2 = float(fn2)
        fn1fn = _Function.convert( fn1 )
        if not isinstance( fn1fn, _Function ):
            raise TypeError("Functions must be of type (or convertible to) 'Function'.")
        fn2fn = _Function.convert( fn2 )
        if not isinstance( fn2fn, _Function ):
            raise TypeError("Functions must be of type (or convertible to) 'Function'.")

        self._fn1 = fn1fn
        self._fn2 = fn2fn
        # ok finally lets create the fn
        self._fncself = _cfn.Pow(self._fn1._fncself, self._fn2._fncself )
        # build parent
        super(pow,self).__init__(argument_fns=[fn1fn,fn2fn],**kwargs)
Example #8
0
    def _GetIOForPyInput(self, value):
        if isinstance(value, (int,float,bool) ):
            if isinstance(value,bool):
                ioguy = _cfn.IO_bool(1,_cfn.FunctionIO.Scalar)
            elif isinstance(value, int):
                ioguy = _cfn.IO_int(1,_cfn.FunctionIO.Scalar)
            elif isinstance(value,float):
                ioguy = _cfn.IO_double(1,_cfn.FunctionIO.Scalar)
            else:
                raise RuntimeError("Failure during object creation. Please contact developers.")
            # now set val
            ioguy.value(value,0)
        else:
            try:
                iterator = iter(value)
            except TypeError:
                raise ValueError("'value' object provided to Constant Function constructor does not appear to be valid. "
                                +"Only python types 'int', 'float' and 'bool' are acceptable, or iterable objects "
                                +"homogeneous in these types. Provided object was of type '{}'.".format(value.__class__.__name__) )
            else:
                # iterable
                tupleGuy = tuple(iterator)
                try:
                    lenTupleGuy = len(tupleGuy)
                except:
                    raise ValueError("'value' object provided to Constant function appears to be an iterable, but "
                                    +"does not appear to have a known length.")

                if lenTupleGuy == 0:
                    raise ValueError("'value' object provided to Constant function appears to be an iterable, but "
                                    +"seems to be of zero size. Iterable values must be of non-zero size.")
                firstFella = tupleGuy[0]
                if isinstance(firstFella,bool):
                    ioguy = _cfn.IO_bool(lenTupleGuy,_cfn.FunctionIO.Array)
                elif isinstance(firstFella, int):
                    ioguy = _cfn.IO_int(lenTupleGuy,_cfn.FunctionIO.Array)
                elif isinstance(firstFella,float):
                    ioguy = _cfn.IO_double(lenTupleGuy,_cfn.FunctionIO.Array)
                else:
                    raise ValueError("'value' object provided to Constant function appears to be an iterable, but "
                                    +"does not appear to contain objects of python type 'int', 'float' or 'bool'.")
                # right, now load in ze data
                ii = 0
                for val in tupleGuy:
                    if not isinstance(val,type(firstFella)):
                        raise ValueError("'value' object provided to Constant function appears to be an iterable, but "
                                        +"does not appear to be homogeneous in type. Objects in iterable must all be "
                                        +"of python type 'int', 'float' or 'bool'.")
                    ioguy.value(val,ii)
                    ii+=1;
        return ioguy
Example #9
0
    def __init__(self, fn, n, *args, **kwargs):

        _fn = Function.convert(fn)
        if _fn == None:
            raise ValueError("provided 'fn' must a 'Function' or convertible.")
        self._fn = _fn

        if not isinstance(n, int):
            raise TypeError("'n' argument is expected to be of type 'int'.")
        if n < 0:
            raise TypeError("'n' argument must be a non-negative integer.")

        # create instance
        self._fncself = _cfn.At(self._fn._fncself, n)

        # build parent
        super(at, self).__init__(argument_fns=[
            fn,
        ], *args, **kwargs)
Example #10
0
 def _GetIOForPyInput(self, value):
     if isinstance(value, (int, float, bool)):
         if isinstance(value, bool):
             ioguy = _cfn.IO_bool(1, 0)
         elif isinstance(value, int):
             ioguy = _cfn.IO_int(1, 0)
         elif isinstance(value, float):
             ioguy = _cfn.IO_double(1, 0)
         else:
             raise RuntimeError(
                 "Failure during object creation. Please contact developers."
             )
         # now set val
         ioguy.value(value, 0)
     else:
         try:
             iterator = iter(value)
         except TypeError:
             raise ValueError(
                 "'value' object provided to Constant Function constructor does not appear to be valid."
             )
         else:
             # iterable
             tupleGuy = tuple(iterator)
             lenTupleGuy = len(tupleGuy)
             firstFella = tupleGuy[0]
             if isinstance(firstFella, bool):
                 ioguy = _cfn.IO_bool(lenTupleGuy, 3)
             elif isinstance(firstFella, int):
                 ioguy = _cfn.IO_int(lenTupleGuy, 3)
             elif isinstance(firstFella, float):
                 ioguy = _cfn.IO_double(lenTupleGuy, 3)
             else:
                 raise ValueError(
                     "'value' object provided to Constant Function constructor does not appear to be valid."
                 )
             # right, now load in ze data
             ii = 0
             for val in tupleGuy:
                 if not isinstance(val, type(firstFella)):
                     raise ValueError(
                         "Your array (or similar) must be homogeneous of type."
                     )
                 ioguy.value(val, ii)
                 ii += 1
     return ioguy
Example #11
0
    def __init__(self, fn_key=None, mapping=None, fn_default=None, *args, **kwargs):
                    
        if not mapping:
            raise ValueError("You must specify a mapping via the 'mapping' parameter.")
        if not isinstance(mapping, dict):
            raise TypeError("'mapping' object passed in must be of python type 'dict'")

        if not fn_key:
            raise ValueError("You must specify a key function via the 'fn_key' parameter.")
        fn_key = _Function.convert(fn_key)

        self.fn_default = _Function.convert(fn_default)
        if self.fn_default == None:
            fn_defaultCself = None
        else:
            fn_defaultCself = self.fn_default._fncself
        # create instance
        self._fncself = _cfn.Map( fn_key._fncself, fn_defaultCself )

        self._fn_key  = fn_key
        self._mapping = mapping

        # build parent
        super(map,self).__init__(argument_fns=[fn_key,self.fn_default],**kwargs)
        
        self._map = {}

        for key, value in mapping.items():
            if not isinstance(key, int) or key < 0:
                raise ValueError("Key '{}' not valid. Mapping keys must be unsigned integers.".format(key))
            funcVal = _Function.convert(value)
            if funcVal == None:
                raise ValueError("'None' is not valid for mapped functions.")
            
            self._underlyingDataItems.update(funcVal._underlyingDataItems) # update dictionary
            # insert mapping and keep handles in py dict
            self._map[key] = funcVal
            self._fncself.insert( key, funcVal._fncself )
Example #12
0
    def __init__(self, vertices, fn=None, *args, **kwargs):

        if fn:
            self._fn = _Function._CheckIsFnOrConvertOrThrow(fn)
        else:
            self._fn = input()

        if not isinstance(vertices, np.ndarray):
            raise TypeError("Provided 'vertices' must be a numpy array.")
        if len(vertices.shape) != 2:
            raise TypeError("Provided 'vertices' array must be 2 dimensional.")
        if vertices.shape[0] < 3:
            raise TypeError(
                "Provided 'vertices' array must contain at least 3 vertices.")
        if vertices.shape[1] != 2:
            raise TypeError(
                "Provided 'vertices' array must contain 2d vectors.")

        # ok, need to create a 3d array from the 2d array.. create array of required size
        threedeearray = np.zeros((vertices.shape[0], 3))
        # now copy
        threedeearray[:, 0:2] = vertices[:, 0:2]

        # create instance
        import random
        import string
        self._id = "".join(
            random.choice(string.ascii_uppercase + string.digits)
            for _ in range(8))
        self._fncself = _cfn.Polygon(self._fn._fncself, threedeearray,
                                     self._id)

        # build parent
        super(Polygon, self).__init__(argument_fns=[
            fn,
        ], *args, **kwargs)
Example #13
0
    def evaluate(self, inputData=None, inputType=None):
        """
        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: array of results

        Examples
        --------
        >>> import math as sysmath
        >>> import underworld.function.math as fnmath
        >>> sinfn = fnmath.sin()
        
        Single evaluation:
        
        >>> np.allclose( sinfn.evaluate(sysmath.pi/4.), [[ 0.5*sysmath.sqrt(2.)]]  )
        True
        
        Multiple evaluations
        
        >>> input = (0.,sysmath.pi/4.,2.*sysmath.pi)
        >>> np.allclose( sinfn.evaluate(input), [[ 0., 0.5*sysmath.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

        Also note that if evaluating across an empty input, an empty output
        is returned. Note that the shape and type of the output is always fixed
        and may differ from the shape/type returned for an actual (non-empty)
        evaluation. Usually this should not be an issue.
        >>> var.evaluate(np.zeros((0,2)))
        array([], shape=(0, 1), dtype=float64)
        >>> var.evaluate(mesh.specialSets["Empty"])
        array([], shape=(0, 1), dtype=float64)

        """
        if inputData is None:
            inputData = 0.
        if inputType != None and inputType not in types.keys():
            raise ValueError(
                "Provided input type does not appear to be valid.")
        if isinstance(inputData, FunctionInput):
            if inputType != None:
                raise ValueError(
                    "'inputType' specification not supported for this input class."
                )
            return _cfn.Query(self._fncself).query(inputData._get_iterator())
        elif isinstance(inputData, np.ndarray):
            if inputType != None:
                if inputType == ScalarType:
                    if inputData.shape[1] != 1:
                        raise ValueError("You have specified ScalarType input, but your input size is {}.\n".format(inputData.shape[1]) \
                                        +"ScalarType inputs must be of size 1.")
                if inputType == VectorType:
                    if inputData.shape[1] not in (2, 3):
                        raise ValueError("You have specified VectorType input, but your input size is {}.\n".format(inputData.shape[1]) \
                                        +"VectorType inputs must be of size 2 or 3 (for 2d or 3d).")
                if inputType == SymmetricTensorType:
                    if inputData.shape[1] not in (3, 6):
                        raise ValueError("You have specified SymmetricTensorType input, but your input size is {}.\n".format(inputData.shape[1]) \
                                        +"SymmetricTensorType inputs must be of size 3 or 6 (for 2d or 3d).")
                if inputType == TensorType:
                    if inputData.shape[1] not in (4, 9):
                        raise ValueError("You have specified TensorType input, but your input size is {}.\n".format(inputData.shape[1]) \
                                        +"TensorType inputs must be of size 4 or 9 (for 2d or 3d).")
            else:
                inputType = ArrayType
            # lets check if this array owns its data.. process directly if it does, otherwise take a copy..
            # this is to avoid a bug in the way we parse non-trivial numpy arrays.  will fix in future.  #152
            # Note, we also added the check for 'F_CONTIGUOUS' as we also don't handle this correctly it seems.
            if (not (inputData.base is None)
                ) or inputData.flags['F_CONTIGUOUS']:
                inputData = inputData.copy()
            return _cfn.Query(self._fncself).query(
                _cfn.NumpyInput(inputData, inputType))
        else:
            # try convert and recurse
            return self.evaluate(
                self._evaluate_data_convert_to_ndarray(inputData), inputType)
Example #14
0
    def _setup(self):
        # now actually setup function guy
        self._fncself = _cfn.FeVariableFn(self._cself)

        self._underlyingDataItems.add(self)
Example #15
0
    def __init__(self, swarm, dataType, count, writeable=True, **kwargs):

        if not isinstance(swarm, sab.SwarmAbstract):
            raise TypeError("'swarm' object passed in must be of type 'Swarm'")
        self._swarm = weakref.ref(swarm)

        self._arr = None
        self._arrshadow = None
        self._writeable = writeable

        # clear the reference to numpy arrays, as memory layout *will* change.
        swarm._clear_variable_arrays()

        if len(swarm._livingArrays) != 0:
            raise RuntimeError("""
            There appears to be {} swarm variable numpy array objects still in
            existance. When a new swarm variable is added, it results in the modification
            of existing swarm variable memory layouts and locations, and therefore
            existing numpy array views of swarm variables will cease to be valid. Potential
            modification of these invalid numpy arrays is dangerous, and therefore they must
            be removed before a new variable can be added.  The python 'del' command may be useful,
            though be aware that an object cannot be destroyed while another object retains a
            reference to it. Once you have added the required swarm variables, you can easily
            regenerate the numpy views of other variables again using the 'data' property."""
                               .format(len(swarm._livingArrays)))

        if not isinstance(dataType, str):
            raise TypeError(
                "'dataType' object passed in must be of type 'str'")
        if dataType.lower() not in self._supportedDataTypes:
            raise ValueError(
                "'dataType' provided ({}) does not appear to be supported. \nSupported types are {}."
                .format(dataType.lower(), self._supportedDataTypes))
        self._dataType = dataType.lower()

        if not isinstance(count, int) or (count < 1):
            raise TypeError("Provided 'count' must be a positive integer.")
        self._count = count

        if self._dataType == "double":
            dtype = libUnderworld.StGermain.StgVariable_DataType_Double
        elif self._dataType == "float":
            dtype = libUnderworld.StGermain.StgVariable_DataType_Float
        elif self._dataType == "int":
            dtype = libUnderworld.StGermain.StgVariable_DataType_Int
        elif self._dataType == "long":
            dtype = libUnderworld.StGermain.StgVariable_DataType_Long
        elif self._dataType == "char":
            dtype = libUnderworld.StGermain.StgVariable_DataType_Char
        elif self._dataType == "short":
            dtype = libUnderworld.StGermain.StgVariable_DataType_Short

        # first, check if we were passed in a cself pointer, in which case we are purely wrapping a pre-exisiting swarmvar
        if "_cself" in kwargs:
            self._cself = kwargs["_cself"]
            if self._cself.swarm.name != swarm._cself.name:
                raise ValueError(
                    "Passed in cself object's swarm must be same as that provided in arguments"
                )
            if self._cself.dofCount != self.count:
                raise ValueError(
                    "Passed in cself object's dofcount must be same as that provided in arguments"
                )
            # note that we aren't checking the datatype
        else:
            varname = self.swarm._cself.name + "_" + str(
                len(self.swarm.variables))
            self._cself = libUnderworld.StgDomain.Swarm_NewVectorVariable(
                self.swarm._cself, varname, -1, dtype, count)
            libUnderworld.StGermain.Stg_Component_Build(
                self._cself, None, False)
            libUnderworld.StGermain.Stg_Component_Initialise(
                self._cself, None, False)

        self.swarm.variables.append(self)

        # lets realloc swarm now
        libUnderworld.StgDomain.Swarm_Realloc(self.swarm._cself)

        # create function guy
        self._fncself = _cfn.SwarmVariableFn(self._cself)

        # build parent
        super(SwarmVariable, self).__init__(argument_fns=None, **kwargs)

        self._underlyingDataItems.add(
            self
        )  # add weakref to self in here.. note this must occur after call to super.
Example #16
0
 def __init__(self, Beta=4., *args, **kwargs):
     self._ckeep = _cfn.SolDB3d(Beta)
     super(SolDB3d, self).__init__(_cfn.SolDB3dCRTP(self._ckeep, 3),
                                   **kwargs)
Example #17
0
 def __init__(self, *args, **kwargs):
     self._ckeep = _cfn.SolDB2d()
     super(SolDB2d, self).__init__(_cfn.SolDB2dCRTP(self._ckeep, 2),
                                   **kwargs)
Example #18
0
    def evaluate(self, inputData, inputType=None):
        """
        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.

        Results are returned as numpy array.

        Parameters
        ----------
        inputData: float, list, tuple, ndarray, 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.

        Returns
        -------
        ndarray: array of results

        Examples
        --------
        >>> import math
        >>> import _math as fnmath
        >>> sinfn = fnmath.sin()
        >>> np.isclose( sinfn.evaluate(math.pi/4.), [[ 0.5*math.sqrt(2.)]]  )
        array([[ True]], dtype=bool)
        >>> intup = (0.,math.pi/4.,2.*math.pi)
        >>> np.isclose( sinfn.evaluate(intup), [[ 0., 0.5*math.sqrt(2.), 0.]]  )
        array([[ True,  True,  True]], dtype=bool)

        """
        if inputType != None and inputType not in (ScalarType, VectorType,
                                                   SymmetricTensorType,
                                                   TensorType, ArrayType):
            raise ValueError(
                "Provided input type does not appear to be valid.")
        if isinstance(inputData, FunctionInput):
            if inputType != None:
                raise ValueError(
                    "'inputType' specification not supported for this input class."
                )
            return _cfn.Query(self._fncself).query(inputData._get_iterator())
        elif isinstance(inputData, np.ndarray):
            if inputType != None:
                if inputType == ScalarType:
                    if inputData.shape[1] != 1:
                        raise ValueError("You have specified ScalarType input, but your input size is {}.\n".format(inputData.shape[1]) \
                                        +"ScalarType inputs must be of size 1.")
                if inputType == VectorType:
                    if inputData.shape[1] not in (2, 3):
                        raise ValueError("You have specified VectorType input, but your input size is {}.\n".format(inputData.shape[1]) \
                                        +"VectorType inputs must be of size 2 or 3 (for 2d or 3d).")
                if inputType == SymmetricTensorType:
                    if inputData.shape[1] not in (3, 6):
                        raise ValueError("You have specified SymmetricTensorType input, but your input size is {}.\n".format(inputData.shape[1]) \
                                        +"SymmetricTensorType inputs must be of size 3 or 6 (for 2d or 3d).")
                if inputType == TensorType:
                    if inputData.shape[1] not in (4, 9):
                        raise ValueError("You have specified TensorType input, but your input size is {}.\n".format(inputData.shape[1]) \
                                        +"TensorType inputs must be of size 4 or 9 (for 2d or 3d).")
            else:
                inputType = ArrayType
            return _cfn.Query(self._fncself).query(
                _cfn.NumpyInput(inputData, inputType))
        elif isinstance(inputData, float):
            tupleInput = (inputData, )
            # recurse
            return self.evaluate(tupleInput, inputType)
        elif isinstance(inputData, (list, tuple)):
            arr = np.empty([1, len(inputData)])
            ii = 0
            for guy in inputData:
                if not isinstance(guy, float):
                    raise TypeError(
                        "Iterable inputs must only contain python 'float' objects."
                    )
                arr[0, ii] = guy
                ii += 1
            # recurse
            return self.evaluate(arr, inputType)
        else:
            raise TypeError(
                "Input provided for function evaluation does not appear to be supported."
            )