import numpy as np from MatlabArray import * from MatlabFuncs import * from fielddisplay import fielddisplay from pairoptions import pairoptions from partition_npart import * from qmupart2npart import qmupart2npart class uniform_uncertain(object): ''' UNIFORM_UNCERTAIN class definition Usage: [uuv] = uniform_uncertain( 'descriptor', descriptor, 'lower', lower, 'upper', upper, 'partition', partition ) where uuv is the uniform_uncertain object returned by the constructor, lower and upper are the pdf distribution bounds, and partition is the partition vector for distributed variables. Can be a partition vector over elements or vertices. Example: md.qmu.variables.rheology = uniform_uncertain( 'descriptor', 'RheologyBBar', 'lower', 1e8, 'upper', 1e9 ) md.qmu.variables.rheology = uniform_uncertain( 'descriptor', 'RheologyBBar', 'lower', 1e8, 'upper', 1e9, 'partition', vpartition ) ''' def __init__(self): # {{{ self.descriptor = '' self.lower = -np.inf self.upper = np.inf self.partition = [] self.nsteps = 0 # }}} @staticmethod def uniform_uncertain(*args): # {{{ nargin = len(args) # create a default object if nargin == 0: return uniform_uncertain() # copy the object elif nargin == 1: if isinstance(args[0], uniform_uncertain): uuv = args[0] else: raise Exception('Object ' + str(args[0]) + ' is a ' + str(type(args[0])) + ' class object, not "uniform_uncertain".') # create the object from the input else: uuv = uniform_uncertain() #recover options: options = pairoptions(*args) #initialize fields: uuv.descriptor = options.getfieldvalue('descriptor') uuv.lower = options.getfieldvalue('lower') uuv.upper = options.getfieldvalue('upper') #if the variable is scaled, a partition vector should have been #supplied, and that partition vector should have as many #partitions as the lower and upper vectors: if uuv.isscaled(): uuv.partition = options.getfieldvalue('partition') uuv.nsteps = options.getfieldvalue('nsteps', 1) npart = qmupart2npart(uuv.partition) if npart != uuv.upper.shape[0]: raise Exception("uniform_uncertain constructor: for the scaled variable %s the upper field is not currently a vector of values for all the partitions described in the partition vector" % uuv.descriptor) if npart != uuv.lower.shape[0]: raise Exception("uniform_uncertain constructor: for the scaled variable %s the lower field is not currently a vector of values for all the partitions described in the partition vector" % uuv.descriptor) if uuv.nsteps != uuv.upper.shape[1]: raise Exception("uniform_uncertain constructor: for the scaled variable %s the col size of the upper field should be identical to the number of time steps" % uuv.descriptor) if uuv.nsteps != uuv.lower.shape[1]: raise Exception("uniform_uncertain constructor: for the scaled variable %s the col size of the lower field should be identical to the number of time steps" % uuv.descriptor) return [uuv] # Always return a list, so we have something akin to a MATLAB single row matrix # }}} def __repr__(self): # {{{ string = ' uniform uncertain variable: ' string = "%s\n%s" % (string, fielddisplay(self, 'descriptor', 'name tag')) string = "%s\n%s" % (string, fielddisplay(self, 'lower', 'pdf lower bound')) string = "%s\n%s" % (string, fielddisplay(self, 'upper', 'pdf upper bound')) if self.partition != []: string = "%s\n%s" % (string, fielddisplay(self, 'partition', 'partition vector defining where sampling will occur')) string = "%s\n%s" % (string, fielddisplay(self, 'nsteps', 'number of time steps')) return string # }}} def __len__(self): # {{{ if type(self.lower) in [list, np.ndarray]: return len(self.lower) else: return 1 # }}} def checkconsistency(self, md, solution, analyses): # {{{ md = checkfield(md, 'field', self.upper, 'fieldname', 'uniform_uncertain.upper', 'NaN', 1, 'Inf', 1, '>', self.lower, 'numel', len(self.lower)) md = checkfield(md, 'field', self.lower, 'fieldname', 'uniform_uncertain.upper', 'NaN', 1, 'Inf', 1, '<', self.upper, 'numel', len(self.upper)) if self.isscaled(): if self.partition == []: raise Exception("uniform_uncertain is a scaled variable, but it's missing a partition vector") #better have a partition vector that has as many partitions as #upper and lower's size: if self.upper.shape[0] != partition_npart(self.partititon): raise Exception("uniform_uncertain error message: row size of upper and partition size should be identical") if self.lower.shape[0] != partition_npart(self.partition): raise Exception("uniform_uncertain error message: row size of lower and partition size should be identical") #we need as steps in upper and lower as there are time steps if self.stddev.shape[1] != self.nsteps: raise Exception("uniform_uncertain error message: col size of upper and partition size should be identical") if self.mean.shape[1] != self.nsteps: raise Exception("uniform_uncertain error message: col size of lower and partition size should be identical") md = checkfield(md, 'field', self.partition, 'fieldname', 'uniform_uncertain.partition', 'NaN', 1, 'Inf', 1, '>=', -1, 'numel', [md.mesh.numberofvertices, md.mesh.numberofvertices]) if self.partition.shape[1] > 1: raise Exception("uniform_uncertain error message: partition should be a column vector") partcheck = np.unique(self.partition) partmin = min(partcheck) partmax = max(partcheck) if partmax < -1: raise Exception("uniform_uncertain error message: partition vector's min value should be -1 (for no partition), or start at 0") nmax = max(md.mesh.numberofelements, md.mesh.numberofvertices) if partmax > nmax: raise Exception("uniform_uncertain error message: partition vector's values cannot go over the number of vertices or elements") # }}} #virtual functions needed by qmu processing algorithms: #implemented: @staticmethod def prop_desc(uuv, dstr): # {{{ desc = ['' for i in range(np.size(uuv))] for i in range(np.size(uuv)): if uuv[i].descriptor != '' or type(uuv[i].descriptor) != str: desc[i] = str(uuv[i].descriptor) elif dstr != '': desc[i] = str(dstr) + str(string_dim(uuv, i, 'vector')) else: desc[i] = 'uuv' + str(string_dim(uuv, i, 'vector')) desc = allempty(desc) return desc # }}} @staticmethod def prop_stddev(uuv): # {{{ stddev = [] return stddev # }}} @staticmethod def prop_mean(uuv): # {{{ mean = [] return mean # }}} @staticmethod def prop_lower(uuv): # {{{ lower = np.zeros(np.size(uuv)) for i in range(np.size(uuv)): lower[i] = uuv[i].lower lower = allequal(lower, -np.inf) return lower # }}} @staticmethod def prop_upper(uuv): # {{{ upper = np.zeros(np.size(uuv)) for i in range(np.size(uuv)): upper[i] = uuv[i].upper #upper = allequal(upper, np.inf) return upper # }}} @staticmethod def prop_abscissas(hbu): # {{{ abscissas = [] return abscissas # }}} @staticmethod def prop_pairs_per_variable(hbu): # {{{ pairs_per_variable = [] return pairs_per_variable # }}} @staticmethod def prop_counts(hbu): # {{{ counts = [] return counts # }}} @staticmethod def prop_initpt(uuv): # {{{ initpt = [] return initpt # }}} @staticmethod def prop_initst(uuv): # {{{ initst = [] return initst # }}} @staticmethod def prop_stype(uuv): # {{{ stype = [] return stype # }}} @staticmethod def prop_scale(uuv): # {{{ scale = [] return scale # }}} #new methods: def isscaled(self): # {{{ if strncmp(self.descriptor, 'scaled_', 7): return True else: return False # }}} @staticmethod def dakota_write(fidi, dvar): # {{{ # possible namespace pollution, the above import seems not to work from vlist_write import vlist_write # collect only the variables of the appropriate class uuv = deepcopy(dvar) fields = fieldnames(uuv) for field in fields: if getattr(uuv, field)[0].__class__.__name__ != 'uniform_uncertain': delattr(uuv, field) if len(uuv) > 0: vlist_write(fidi, 'uniform_uncertain', 'uuv', uuv) # }}}