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)
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)
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)
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)
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
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)
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)
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
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)
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
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 )
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)
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)
def _setup(self): # now actually setup function guy self._fncself = _cfn.FeVariableFn(self._cself) self._underlyingDataItems.add(self)
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.
def __init__(self, Beta=4., *args, **kwargs): self._ckeep = _cfn.SolDB3d(Beta) super(SolDB3d, self).__init__(_cfn.SolDB3dCRTP(self._ckeep, 3), **kwargs)
def __init__(self, *args, **kwargs): self._ckeep = _cfn.SolDB2d() super(SolDB2d, self).__init__(_cfn.SolDB2dCRTP(self._ckeep, 2), **kwargs)
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." )