Пример #1
0
 def _functionio_for_numpy(self, function_io_guy):
     """
     This method simply takes a swig proxy to a FunctionIO, 
     and returns the data as a numpy array.
     """
     # create input function just so we can process using query
     inputfn = _function.input()
     # create function_io iterator
     func_io_it = _cfn.FunctionIOIter(function_io_guy)
     # process
     return _cfn.Query(inputfn._fncself).query(func_io_it)
Пример #2
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 )