def define_class(class_id): """Define a class based on Cinfo element with Id=class_id.""" class_name = class_id[0].getField('name') if class_name in globals().keys(): return base = class_id[0].getField('baseClass') if base != 'none': try: base_class = globals()[base] except KeyError: define_class(Id('/classes/' + base)) base_class = globals()[base] else: base_class = object class_obj = type(class_name, (base_class, ), {}) update_class(class_obj, class_id) # Add this class to globals dict globals()[class_name] = class_obj array_class_name = class_name + 'Array' if base != 'none': base_class = globals()[base + 'Array'] else: base_class = object array_class_obj = type(array_class_name, (base_class, ), {}) globals()[array_class_name] = array_class_obj
def syncDataHandler(target): """Synchronize data handlers for target. Parameter: target -- target element or path or Id. """ raise NotImplementedError( 'The implementation is not working for IntFire - goes to invalid objects. First fix that issue with SynBase or something in that line.' ) if isinstance(target, str): if not _moose.exists(target): raise ValueError('%s: element does not exist.' % (target)) target = Id(target) _moose.syncDataHandler(target)
def update_class(cls, class_id): class_name = class_id[0].name num_valueFinfo = getField(class_id[0], 'num_valueFinfo', 'unsigned') num_destFinfo = getField(class_id[0], 'num_destFinfo', 'unsigned') num_lookupFinfo = getField(class_id[0], 'num_lookupFinfo', 'unsigned') valueFinfo = Id('/classes/%s/valueFinfo' % (class_name)) destFinfo = Id('/classes/%s/destFinfo' % (class_name)) lookupFinfo = Id('/classes/%s/lookupFinfo' % (class_name)) destFinfoNames = set( [ObjId(destFinfo, 0, ii, 0).name for ii in range(num_destFinfo)]) for ii in range(num_valueFinfo): field = ObjId(valueFinfo, 0, ii, 0) fieldName = field.name fget = partial(ObjId.getField, fieldName) fset = None if 'get_%s' % (fieldName) in destFinfoNames: fset = partial(ObjId.setField, fieldName) doc = None # The following is to avoid duplicating the documentation # in non-interactive mode. __main__.__file__ is not # defined in interactive mode and that is when we create # the documentation. if not hasattr(main, '__file__'): doc = field.docs setattr(cls, fieldName, property(fget=fget, fset=fset, doc=doc)) for ii in range(num_lookupFinfo): field = ObjId(lookupFinfo, 0, ii, 0) fieldName = field.name fget = partial(_LookupField, fieldName) # The following is to avoid duplicating the documentation # in non-interactive mode. __main__.__file__ is not # defined in interactive mode and that is when we create # the documentation. doc = None if not hasattr(main, '__file__'): doc = field.docs setattr(cls, fieldName, property(fget=fget, doc=doc)) # Go through the destFinfos and make them look like methods for ii in range(num_destFinfo): field = ObjId(destFinfo, 0, ii, 0) fieldName = field.name # get_<fieldName> and set_<fieldName> are internal # destFinfos generated for each valueFinfo (the latter # created for writable ones). They are not to be accessed # by users. if fieldName.startswith('get_') or fieldName.startswith('set_'): continue # Can we handle the arguments required for this destFinfo? # Start optimistically. manageable = True # We keep gathering the function signature in fnsig # This will be a lambda function, lambda x, y, ...: expr # where expr is evaluated and the result returned. fnsig = 'lambda self' # We gather the formal arguments in fnargs. field name # must be the first argument passed to the # ObjId.setField function. fnargs = '"%s"' % (fieldName) # 'type' is a string field in Finfos specifying the type # (retrieved from the template parameters specified in the # C++ definition). for DestFinfo with OpFuncN<MooseClass, # type1, type2, ..., typeN> will have a type string: # "type1,type2,...,typeN". We split this string to find # out the formal arguments of the lambda argtypes = field.type.split(',') for index in range(len(argtypes)): # Check if we know how to handle this argument type if argtypes[index] not in known_types: manageable = False break elif argtypes[index] != 'void': # The replacements are for types with space (like # unsigned int) and templated types (like # vector<int>) arg = 'arg_%d_%s' % (index, argtypes[index].replace( ' ', '_').replace('<', '_').replace('>', '_')) fnsig += ', %s' % (arg) fnargs += ', %s' % (arg) if manageable: # The final function will be: # lambda self, arg_1_type1, arg_2_type2, ..., arg_N_typeN: # self.oid_.setField(fieldName, arg_1_type1, arg_2_type2, ..., arg_N_typeN) function_string = '%s: self.oid_.setDestField(%s)' % (fnsig, fnargs) setattr(cls, fieldName, eval(function_string))
def __init__(self, *args, **kwargs): """Initialize a Neutral object. Arguments: arg1 : A path or an existing ObjId or an Id or a NeutralArray or another Neutral object. path -- a string specifying the path for the Neutral object. If there is already a Neutral object with the given path, a reference to that object is created. Otherwise, a new NeutralArray is created with the given path. In the latter case, the path must be valid up to the last '/'. For example, if you specify '/a/b/c', then for correct operation, there must be an element named 'a' at the top level and a child element of 'a' named 'b'. This works like 'mkdir' or 'md' command in some operating systems. ObjId -- if the first argument is an ObjId, then the Neutral object refers to the existing object with the specified ObjId. Id -- if the first argument is an Id then the Neutral object will refer to some entry in the ArrayElement with this Id. The exact index pointed to will be determined by the second argument, or the first entry if no second argument is specified. NeutralArray -- Same as Id (as if the Id of the NeutralArray was passed). Neutral -- create a new reference to the existing Neutral object. arg2 : if there is a second argument, then this is taken as the dataindex into an existing array element. arg3: if there is a third argument, this is taken as the fieldindex into an existing array field. """ id_ = None self.oid_ = None dindex = None findex = None numFieldBits = None if len(args) >= 1: if isinstance(args[0], ObjId): self.oid_ = args[0] elif isinstance(args[0], Id): id_ = args[0].getValue() elif isinstance(args[0], Neutral): self.oid_ = args[0].oid_ elif isinstance(args[0], NeutralArray): id_ = args[0].id_ elif isinstance(args[0], str): try: self.oid_ = _moose.ObjId(args[0]) except ValueError: # A non-existing path has been provided. Try to # construct a singleton array element and create # reference to the first element. self_class = self.__class__ while (self_class.__name__ not in _moose_classes) and ( self_class != object): # Handle class extension in Python. self_class = self_class.__base__ if self_class == object: raise TypeError( 'Class %s does not inherit any MOOSE class.' % (self.__class__.__name__)) id_ = Id(path=args[0], dims=(1, ), type=self_class.__name__) else: raise TypeError( 'First non-keyword argument must be a number or an existing Id/ObjId/Neutral/NeutralArray object or a path.' ) if len(args) >= 2: dindex = args[1] if len(args) >= 3: findex = args[2] if len(args) >= 4: numFieldBits = args[3] if (kwargs): try: id_ = kwargs['id'] except KeyError: pass try: dindex = kwargs['dataIndex'] except KeyError: pass try: findex = kwargs['fieldIndex'] except KeyError: pass try: numFieldBits = kwargs['numFieldBits'] except KeyError: pass if self.oid_ is None: if id_ is not None: if dindex is None: self.oid_ = _moose.ObjId(id_) elif findex is None: self.oid_ = _moose.ObjId(id_, dindex) elif numFieldBits is None: self.oid_ = _moose.ObjId(id_, dindex, findex) else: self.oid_ = _moose.ObjId(id_, dindex, findex, numFieldBits) # Check for conversion from instance of incompatible MOOSE # class. orig_classname = self.oid_.getField('class') if self.__class__.__name__ != orig_classname: orig_class = eval(orig_classname) self_class = self.__class__ while self_class != object and self_class not in orig_class.mro(): self_class = self_class.__base__ if self_class == object: self.oid_ = None raise TypeError('Cannot convert %s to %s' % (orig_class, self.__class__))
def __init__(self, *args, **kwargs): """ A NeutralArray object can be constructed in many ways. The most basic one being: neutral = moose.NeutralArray('my_neutral_object', [3]) This will create a NeutralArray object with name 'my_neutral_object' containing 3 elements. The object will be created as a child of the current working entity. Any class derived from NeutralArray can also be created using the same constructor. Actually it takes keyword parameters to do that: intfire = moose.NeutralArray(path='/my_neutral_object', dims=[3], type='IntFire') will create an IntFire object of size 3 as a child of the root entity. If the above code is already executed, duplicate = moose.NeutralArray(intfire) will create a duplicate reference to the existing intfire object. They will share the same Id and any changes made via the MOOSE API to one will be effective on the other. """ path = None dims = None self.id_ = None try: className = kwargs['type'] self.className = className except KeyError: # This code is messy and depends on the class name. I # could not find a way to pass the element data type to # the class definition dynamically if not hasattr(self, 'className'): self.className = 'Neutral' try: dims = kwargs['dims'] except KeyError: pass try: path = kwargs['path'] except KeyError: pass if len(args) > 0: if isinstance(args[0], str): path = args[0] elif isinstance(args[0], Id): self.id_ = args[0] elif isinstance(args[0], int): self.id_ = Id(args[0]) if len(args) > 1: dims = args[1] if len(args) > 2: self.className = args[2] # No existing Array element ot Id specified, create new # ArrayElement if self.id_ is None: if path is None: raise TypeError( 'A string path or an existing Id or an int value for existing Id must be the first argument to __init__' ) if exists(path): self.id_ = _moose.Id(path=path) # Check if specified dimensions match the existing # object's dimensions if dims is not None: shape = self.id_.getShape() if isinstance(dims, int): if shape[0] != dims: raise ValueError( 'Specified dimensions do not match that of existing array object' ) else: if len(shape) != len(dims): raise ValueError( 'Specified dimensions do not match that of existing array object' ) for ii in range(len(shape)): if shape[ii] != dims[ii]: raise ValueError( 'Specified dimensions do not match that of existing array object' ) else: dims = (1) # Create a new ArrayElement _base_class = self.__class__ _class_name = self.__class__.__name__ if _class_name.endswith('Array'): _class_name = _class_name[:-len('Array')] # For classes extended in Python get to the first MOOSE base class while _class_name not in _moose_classes: _base_class = self.__base__ if _base_class == object: raise TypeError( 'Class %s does not inherit any MOOSE class.' % (self.__class__.__name__)) _class_name = _base_class.__name__ if _class_name.endswith('Array'): _class_name = _class_name[:-len('Array')] self.id_ = _moose.Id(path=path, dims=dims, type=_class_name) # Check for conversion from instance of incompatible MOOSE # class. orig_classname = self.id_[0].getField('class') + 'Array' if self.__class__.__name__ != orig_classname: orig_class = eval(orig_classname) self_class = self.__class__ while self_class != object and self_class not in orig_class.mro(): self_class = self_class.__base__ if self_class == object: self.id_ = None raise TypeError('Cannot convert %s to %s' % (orig_class, self.__class__))
class NeutralArray(object): """ The base class. Each NeutralArray object has an unique Id (field id_) and that is the only data directly visible under Python. All operation are done on the objects by calling functions on the Id. A NeutralArray object is actually an array. The individual elements in a NeutralArray are of class Neutral. To access these individual elements, you can index the NeutralArray object. """ def __init__(self, *args, **kwargs): """ A NeutralArray object can be constructed in many ways. The most basic one being: neutral = moose.NeutralArray('my_neutral_object', [3]) This will create a NeutralArray object with name 'my_neutral_object' containing 3 elements. The object will be created as a child of the current working entity. Any class derived from NeutralArray can also be created using the same constructor. Actually it takes keyword parameters to do that: intfire = moose.NeutralArray(path='/my_neutral_object', dims=[3], type='IntFire') will create an IntFire object of size 3 as a child of the root entity. If the above code is already executed, duplicate = moose.NeutralArray(intfire) will create a duplicate reference to the existing intfire object. They will share the same Id and any changes made via the MOOSE API to one will be effective on the other. """ path = None dims = None self.id_ = None try: className = kwargs['type'] self.className = className except KeyError: # This code is messy and depends on the class name. I # could not find a way to pass the element data type to # the class definition dynamically if not hasattr(self, 'className'): self.className = 'Neutral' try: dims = kwargs['dims'] except KeyError: pass try: path = kwargs['path'] except KeyError: pass if len(args) > 0: if isinstance(args[0], str): path = args[0] elif isinstance(args[0], Id): self.id_ = args[0] elif isinstance(args[0], int): self.id_ = Id(args[0]) if len(args) > 1: dims = args[1] if len(args) > 2: self.className = args[2] # No existing Array element ot Id specified, create new # ArrayElement if self.id_ is None: if path is None: raise TypeError( 'A string path or an existing Id or an int value for existing Id must be the first argument to __init__' ) if exists(path): self.id_ = _moose.Id(path=path) # Check if specified dimensions match the existing # object's dimensions if dims is not None: shape = self.id_.getShape() if isinstance(dims, int): if shape[0] != dims: raise ValueError( 'Specified dimensions do not match that of existing array object' ) else: if len(shape) != len(dims): raise ValueError( 'Specified dimensions do not match that of existing array object' ) for ii in range(len(shape)): if shape[ii] != dims[ii]: raise ValueError( 'Specified dimensions do not match that of existing array object' ) else: dims = (1) # Create a new ArrayElement _base_class = self.__class__ _class_name = self.__class__.__name__ if _class_name.endswith('Array'): _class_name = _class_name[:-len('Array')] # For classes extended in Python get to the first MOOSE base class while _class_name not in _moose_classes: _base_class = self.__base__ if _base_class == object: raise TypeError( 'Class %s does not inherit any MOOSE class.' % (self.__class__.__name__)) _class_name = _base_class.__name__ if _class_name.endswith('Array'): _class_name = _class_name[:-len('Array')] self.id_ = _moose.Id(path=path, dims=dims, type=_class_name) # Check for conversion from instance of incompatible MOOSE # class. orig_classname = self.id_[0].getField('class') + 'Array' if self.__class__.__name__ != orig_classname: orig_class = eval(orig_classname) self_class = self.__class__ while self_class != object and self_class not in orig_class.mro(): self_class = self_class.__base__ if self_class == object: self.id_ = None raise TypeError('Cannot convert %s to %s' % (orig_class, self.__class__)) def getFieldNames(self, ftype=''): """Return a list of fields available in this object. Parameters: str ftype -- (default '') category of field, valid values are: valueFinfo, lookupFinfo, srcFinfo, destFinfo or sharedFinfo. If empty string or not specified, returns names of fields from all categories. """ return self.id_[0].getFieldNames(ftype) def getFieldType(self, field, ftype=''): """Return the data type of the field as a string.""" return self.id_[0].getFieldType(field, ftype) def __getitem__(self, index): objid = self.id_[index] retclass = eval(self.id_[0].getField('class')) ret = retclass(objid) return ret def __len__(self): return len(self.id_) def __contains__(self, other): if isinstance(other, Neutral): return other.oid_ in self.id_ elif isinstance(other, ObjId): return other in self.id_ else: return False def __repr__(self): return self.id_.getPath() path = property(lambda self: self.id_.getPath()) fieldNames = property(lambda self: self.id_[0].getFieldNames('valueFinfo')) name = property(lambda self: self.id_[0].name) shape = property(lambda self: self.id_.getShape())
from _moose import wildcardFind as _wildcardFind # We override the original import __main__ as main sequence_types = [ 'vector<double>', 'vector<int>', 'vector<long>', 'vector<unsigned int>', 'vector<float>', 'vector<unsigned long>', 'vector<short>', 'vector<Id>', 'vector<ObjId>' ] known_types = [ 'void', 'char', 'short', 'int', 'unsigned int', 'double', 'float', 'long', 'unsigned long', 'string', 'Id', 'ObjId' ] + sequence_types # Dict of available MOOSE class names. This is faster for look-up _moose_classes = dict([(child[0].name, True) for child in Id('/classes')[0].getField('children')]) # class _MooseDescriptor(object): # """Descriptor to give access to MOOSE class' ValueFinfo attributes""" # def __init__(self, name): # self.name = name # def __get__(self, obj, objtype=None): # return obj.oid_.getField(self.name) # def __set__(self, obj, value): # obj.oid_.setField(self.name, value) # def __delete__(self, obj): # raise AttributeError('ValueFinfos cannot be deleted.')
def __init__(self, *args, **kwargs): """ A NeutralArray object can be constructed in many ways. The most basic one being: neutral = moose.NeutralArray('my_neutral_object', [3]) This will create a NeutralArray object with name 'my_neutral_object' containing 3 elements. The object will be created as a child of the current working entity. Any class derived from NeutralArray can also be created using the same constructor. Actually it takes keyword parameters to do that: intfire = moose.NeutralArray(path='/my_neutral_object', dims=[3], type='IntFire') will create an IntFire object of size 3 as a child of the root entity. If the above code is already executed, duplicate = moose.NeutralArray(intfire) will create a duplicate reference to the existing intfire object. They will share the same Id and any changes made via the MOOSE API to one will be effective on the other. """ path = None dims = None self.id_ = None try: className = kwargs['type'] self.className = className except KeyError: # This code is messy and depends on the class name. I # could not find a way to pass the element data type to # the class definition dynamically if not hasattr(self, 'className'): self.className = 'Neutral' try: dims = kwargs['dims'] except KeyError: pass try: path = kwargs['path'] except KeyError: pass if len(args) > 0: if isinstance(args[0], str): path = args[0] elif isinstance(args[0], Id): self.id_ = args[0] elif isinstance(args[0], int): self.id_ = Id(args[0]) if len(args) > 1: dims = args[1] if len(args) > 2: self.className = args[2] # No existing Array element ot Id specified, create new # ArrayElement if self.id_ is None: if path is None: raise TypeError('A string path or an existing Id or an int value for existing Id must be the first argument to __init__') if exists(path): self.id_ = _moose.Id(path=path) # Check if specified dimensions match the existing # object's dimensions if dims is not None: shape = self.id_.getShape() if isinstance(dims, int): if shape[0] != dims: raise ValueError('Specified dimensions do not match that of existing array object') else: if len(shape) != len(dims): raise ValueError('Specified dimensions do not match that of existing array object') for ii in range(len(shape)): if shape[ii] != dims[ii]: raise ValueError('Specified dimensions do not match that of existing array object') else: dims = (1) # Create a new ArrayElement _base_class = self.__class__ _class_name = self.__class__.__name__ if _class_name.endswith('Array'): _class_name = _class_name[:-len('Array')] # For classes extended in Python get to the first MOOSE base class while _class_name not in _moose_classes: _base_class = self.__base__ if _base_class == object: raise TypeError('Class %s does not inherit any MOOSE class.' % (self.__class__.__name__)) _class_name = _base_class.__name__ if _class_name.endswith('Array'): _class_name = _class_name[:-len('Array')] self.id_ = _moose.Id(path=path, dims=dims, type=_class_name) # Check for conversion from instance of incompatible MOOSE # class. orig_classname = self.id_[0].getField('class') + 'Array' if self.__class__.__name__ != orig_classname: orig_class = eval(orig_classname) self_class = self.__class__ while self_class != object and self_class not in orig_class.mro(): self_class = self_class.__base__ if self_class == object: self.id_ = None raise TypeError('Cannot convert %s to %s' % (orig_class, self.__class__))
class NeutralArray(object): """ The base class. Each NeutralArray object has an unique Id (field id_) and that is the only data directly visible under Python. All operation are done on the objects by calling functions on the Id. A NeutralArray object is actually an array. The individual elements in a NeutralArray are of class Neutral. To access these individual elements, you can index the NeutralArray object. """ def __init__(self, *args, **kwargs): """ A NeutralArray object can be constructed in many ways. The most basic one being: neutral = moose.NeutralArray('my_neutral_object', [3]) This will create a NeutralArray object with name 'my_neutral_object' containing 3 elements. The object will be created as a child of the current working entity. Any class derived from NeutralArray can also be created using the same constructor. Actually it takes keyword parameters to do that: intfire = moose.NeutralArray(path='/my_neutral_object', dims=[3], type='IntFire') will create an IntFire object of size 3 as a child of the root entity. If the above code is already executed, duplicate = moose.NeutralArray(intfire) will create a duplicate reference to the existing intfire object. They will share the same Id and any changes made via the MOOSE API to one will be effective on the other. """ path = None dims = None self.id_ = None try: className = kwargs['type'] self.className = className except KeyError: # This code is messy and depends on the class name. I # could not find a way to pass the element data type to # the class definition dynamically if not hasattr(self, 'className'): self.className = 'Neutral' try: dims = kwargs['dims'] except KeyError: pass try: path = kwargs['path'] except KeyError: pass if len(args) > 0: if isinstance(args[0], str): path = args[0] elif isinstance(args[0], Id): self.id_ = args[0] elif isinstance(args[0], int): self.id_ = Id(args[0]) if len(args) > 1: dims = args[1] if len(args) > 2: self.className = args[2] # No existing Array element ot Id specified, create new # ArrayElement if self.id_ is None: if path is None: raise TypeError('A string path or an existing Id or an int value for existing Id must be the first argument to __init__') if exists(path): self.id_ = _moose.Id(path=path) # Check if specified dimensions match the existing # object's dimensions if dims is not None: shape = self.id_.getShape() if isinstance(dims, int): if shape[0] != dims: raise ValueError('Specified dimensions do not match that of existing array object') else: if len(shape) != len(dims): raise ValueError('Specified dimensions do not match that of existing array object') for ii in range(len(shape)): if shape[ii] != dims[ii]: raise ValueError('Specified dimensions do not match that of existing array object') else: dims = (1) # Create a new ArrayElement _base_class = self.__class__ _class_name = self.__class__.__name__ if _class_name.endswith('Array'): _class_name = _class_name[:-len('Array')] # For classes extended in Python get to the first MOOSE base class while _class_name not in _moose_classes: _base_class = self.__base__ if _base_class == object: raise TypeError('Class %s does not inherit any MOOSE class.' % (self.__class__.__name__)) _class_name = _base_class.__name__ if _class_name.endswith('Array'): _class_name = _class_name[:-len('Array')] self.id_ = _moose.Id(path=path, dims=dims, type=_class_name) # Check for conversion from instance of incompatible MOOSE # class. orig_classname = self.id_[0].getField('class') + 'Array' if self.__class__.__name__ != orig_classname: orig_class = eval(orig_classname) self_class = self.__class__ while self_class != object and self_class not in orig_class.mro(): self_class = self_class.__base__ if self_class == object: self.id_ = None raise TypeError('Cannot convert %s to %s' % (orig_class, self.__class__)) def getFieldNames(self, ftype=''): """Return a list of fields available in this object. Parameters: str ftype -- (default '') category of field, valid values are: valueFinfo, lookupFinfo, srcFinfo, destFinfo or sharedFinfo. If empty string or not specified, returns names of fields from all categories. """ return self.id_[0].getFieldNames(ftype) def getFieldType(self, field, ftype=''): """Return the data type of the field as a string.""" return self.id_[0].getFieldType(field, ftype) def __getitem__(self, index): objid = self.id_[index] retclass = eval(self.id_[0].getField('class')) ret = retclass(objid) return ret def __len__(self): return len(self.id_) def __contains__(self, other): if isinstance(other, Neutral): return other.oid_ in self.id_ elif isinstance(other, ObjId): return other in self.id_ else: return False def __repr__(self): return self.id_.getPath() path = property(lambda self: self.id_.getPath()) fieldNames = property(lambda self: self.id_[0].getFieldNames('valueFinfo')) name = property(lambda self: self.id_[0].name) shape = property(lambda self: self.id_.getShape())