def __init__(self, filename): ''' Notes ----- The EXOFile class is an interface to the Exodus II api. Its methods are named after the analogous method from the Exodus II C bindings, minus the prefix 'ex_'. ''' self.fh = NetCDFFile(filename, mode='w') self.jobid = splitext(basename(filename))[0] self.filename = filename self.initialized = False self.viewable = False
def read_exodus_legacy(filename, variables=None, disp=1, blk_num=1, elem_num=1): '''Read the specified variables from the exodus file in filepath ''' if not isfile(filename): raise IOError('{0}: no such file'.format(filename)) fh = NetCDFFile(filename, 'r') # global/element vars and mapping num_glo_var = fh.dimensions.get('num_glo_var', 0) if num_glo_var: name_glo_var = exodus.stringify(fh.variables['name_glo_var'].data) gmap = dict(zip(name_glo_var, range(len(name_glo_var)))) name_elem_var = exodus.stringify(fh.variables['name_elem_var'].data) emap = dict(zip(name_elem_var, range(len(name_elem_var)))) # retrieve the data from the database head = ['TIME'] if num_glo_var: head.extend([H.upper() for H in name_glo_var]) head.extend([H.upper() for H in name_elem_var]) data = [] times = fh.variables['time_whole'].data.flatten() for (i, time) in enumerate(times): row = [time] if num_glo_var: vals_glo_var = fh.variables['vals_glo_var'].data[i] for var in name_glo_var: var_num = gmap[var] try: row.append(vals_glo_var[var_num]) except KeyError: continue for var in name_elem_var: var_num = emap[var]+1 name = 'vals_elem_var{0}eb{1}'.format(var_num, blk_num) row.append(fh.variables[name].data[i, elem_num-1]) data.append(row) fh.close() data = np.asarray(data) if len(head) != data.shape[1]: raise ValueError('inconsistent data') data = np.array(data) if variables is not None: variables = [x.upper() for x in variables] idx = [] for name in variables: try: idx.append(head.index(name)) except IndexError: raise KeyError('{0} not in output database'.format(name)) head = [head[i] for i in idx] data = data[:, idx] if disp: return head, data return data
def read_exodus_legacy(filename, variables=None, disp=1, blk_num=1, elem_num=1): '''Read the specified variables from the exodus file in filepath ''' if not isfile(filename): raise IOError('{0}: no such file'.format(filename)) fh = NetCDFFile(filename, 'r') # global/element vars and mapping num_glo_var = fh.dimensions.get('num_glo_var', 0) if num_glo_var: name_glo_var = exodus.stringify(fh.variables['name_glo_var'].data) gmap = dict(zip(name_glo_var, range(len(name_glo_var)))) name_elem_var = exodus.stringify(fh.variables['name_elem_var'].data) emap = dict(zip(name_elem_var, range(len(name_elem_var)))) # retrieve the data from the database head = ['TIME'] if num_glo_var: head.extend([H.upper() for H in name_glo_var]) head.extend([H.upper() for H in name_elem_var]) data = [] times = fh.variables['time_whole'].data.flatten() for (i, time) in enumerate(times): row = [time] if num_glo_var: vals_glo_var = fh.variables['vals_glo_var'].data[i] for var in name_glo_var: var_num = gmap[var] try: row.append(vals_glo_var[var_num]) except KeyError: continue for var in name_elem_var: var_num = emap[var] + 1 name = 'vals_elem_var{0}eb{1}'.format(var_num, blk_num) row.append(fh.variables[name].data[i, elem_num - 1]) data.append(row) fh.close() data = np.asarray(data) if len(head) != data.shape[1]: raise ValueError('inconsistent data') data = np.array(data) if variables is not None: variables = [x.upper() for x in variables] idx = [] for name in variables: try: idx.append(head.index(name)) except IndexError: raise KeyError('{0} not in output database'.format(name)) head = [head[i] for i in idx] data = data[:, idx] if disp: return head, data return data
def __init__(self, filename): if not isfile(filename): raise IOError('no such file: {0}'.format(repr(filename))) self.filename = filename self.fh = NetCDFFile(filename, mode='r') self.read()
class EXOFileWriter(_EXOFile): mode = 'w' def __init__(self, filename): ''' Notes ----- The EXOFile class is an interface to the Exodus II api. Its methods are named after the analogous method from the Exodus II C bindings, minus the prefix 'ex_'. ''' self.fh = NetCDFFile(filename, mode='w') self.jobid = splitext(basename(filename))[0] self.filename = filename self.initialized = False self.viewable = False def update(self): pass def __lshift__(self, u): if not self.initialized: self.initialize(*u.alpha()) for step in u.steps.values(): self.put_step(step) self.close() def initialize(self, dimension, num_node, nodes, vertices, num_elem, elements, connect, element_blocks, field_outputs, node_sets=None, side_sets=None): '''Writes the initialization parameters to the EXODUS II file''' # ------------------------------------------------------------------- # # -------------------------------- standard ExodusII dimensioning --- # # ------------------------------------------------------------------- # self.fh.floating_point_word_size = 4 self.fh.version = 5.0300002 self.fh.file_size = 1 self.fh.api_version = 5.0300002 self.fh.title = 'finite element simulation' self.fh.filename = basename(self.filename) self.fh.jobid = self.jobid self.fh.createDimension(DIM_LEN_STRING, 33) self.fh.createDimension(DIM_LEN_LINE, 81) self.fh.createDimension(DIM_FOUR, 4) self.fh.createDimension(DIM_NUM_DIM, dimension) self.fh.createDimension(DIM_NUM_NODES, num_node) self.fh.createDimension(DIM_NUM_ELEM, num_elem) # node and element number maps self.fh.createVariable(VAR_NODES, INT, (DIM_NUM_NODES,)) self.fh.variables[VAR_NODES][:] = nodes self.fh.createVariable(VAR_ELEMENTS, INT, (DIM_NUM_ELEM,)) self.fh.variables[VAR_ELEMENTS][:] = elements # ------------------------------------------------------------------- # # ---------------------------------------------------- QA records --- # # ------------------------------------------------------------------- # now = datetime.datetime.now() day = now.strftime("%m/%d/%y") hour = now.strftime("%H:%M:%S") self.fh.createDimension(DIM_NUM_QA, 1) self.fh.createVariable(VAR_QA_RECORDS, CHAR, (DIM_NUM_QA, DIM_FOUR, DIM_LEN_STRING)) self.fh.variables[VAR_QA_RECORDS][0, 0, :] = adjstr('femlib') self.fh.variables[VAR_QA_RECORDS][0, 1, :] = adjstr(self.jobid) self.fh.variables[VAR_QA_RECORDS][0, 2, :] = adjstr(day) self.fh.variables[VAR_QA_RECORDS][0, 3, :] = adjstr(hour) # ------------------------------------------------------------------- # # ------------------------------------------------- record arrays --- # # ------------------------------------------------------------------- # self.fh.createDimension(DIM_TIME_STEP, None) self.fh.createVariable(VAR_TIME_WHOLE, FLOAT, (DIM_TIME_STEP,)) self.fh.createVariable(VAR_STEP_NUM, INT, (DIM_TIME_STEP,)) self.fh.createDimension(DIM_MAX_STEPS, 100) # arbitrary number self.fh.createVariable(VAR_STEP_NAMES, CHAR, (DIM_MAX_STEPS, DIM_LEN_STRING)) self.step_count = 0 # ------------------------------------------------------------------- # # ------------------------------------------------- field outputs --- # # ------------------------------------------------------------------- # fields = field_outputs.values() nev = sum([len(fo.keys) for fo in fields if fo.position==ELEMENT]) self.fh.createDimension(DIM_NUM_ELEM_VAR, nev) self.fh.createVariable(VAR_NAME_ELEM_VAR, CHAR, (DIM_NUM_ELEM_VAR, DIM_LEN_STRING)) self.fh.createVariable(VAR_FIELD_ELEM_VAR, INT, (DIM_NUM_ELEM_VAR,)) nnv = sum([len(fo.keys) for fo in fields if fo.position==NODE]) self.fh.createDimension(DIM_NUM_NOD_VAR, nnv) self.fh.createVariable(VAR_NAME_NOD_VAR, CHAR, (DIM_NUM_NOD_VAR, DIM_LEN_STRING)) self.fh.createVariable(VAR_FIELD_NOD_VAR, INT, (DIM_NUM_NOD_VAR,)) self.fh.createDimension(DIM_NUM_FIELD, len(fields)) self.fh.createVariable(VAR_FO_PROP1, INT, (DIM_NUM_FIELD,)) self.fh.createVariable(VAR_FO_NAMES, CHAR, (DIM_NUM_FIELD, DIM_LEN_STRING)) self.fh.createVariable(VAR_FO_TYPES, INT, (DIM_NUM_FIELD,)) self.fh.createVariable(VAR_FO_VALINV, CHAR, (DIM_NUM_FIELD, DIM_LEN_STRING)) self.fh.variables[VAR_FO_PROP1][:] = np.arange(len(fields)) + 1 i = j = 0 for (n, fo) in enumerate(fields): self.fh.variables[VAR_FO_NAMES][n, :] = adjstr(fo.name) self.fh.variables[VAR_FO_TYPES][n] = fo.type string = adjstr(asstring(fo.valid_invariants, 0)) self.fh.variables[VAR_FO_VALINV][n] = string for key in fo.keys: key = adjstr(key) if fo.position == ELEMENT: self.fh.variables[VAR_NAME_ELEM_VAR][i, :] = key self.fh.variables[VAR_FIELD_ELEM_VAR][i] = n i += 1 elif fo.position == NODE: self.fh.variables[VAR_NAME_NOD_VAR][j, :] = key self.fh.variables[VAR_FIELD_NOD_VAR][j] = n j += 1 else: raise ValueError('unknown field output position') # ------------------------------------------------------------------- # # -------------------------------------------- node set meta data --- # # ------------------------------------------------------------------- # nns = 0 if node_sets is None else len(node_sets) if nns: self.fh.createDimension(DIM_NUM_NODE_SETS, nns) # node set IDs - standard map prop1 = np.arange(nns, dtype=np.int32) + 1 self.fh.createVariable(VAR_NS_PROP1, INT, (DIM_NUM_NODE_SETS,)) self.fh.variables[VAR_NS_PROP1][:] = prop1 self.fh.variables[VAR_NS_PROP1].name = 'ID' self.fh.createVariable(VAR_NS_NAMES, CHAR, (DIM_NUM_NODE_SETS, DIM_LEN_STRING)) for (i, ns) in enumerate(node_sets, start=1): self.fh.variables[VAR_NS_NAMES][i-1][:] = adjstr(ns.name) self.fh.createDimension(DIM_NUM_NOD_NS(i), len(ns.nodes)) self.fh.createVariable(VAR_NODE_NS(i), INT, (DIM_NUM_NOD_NS(i),)) self.fh.variables[VAR_NODE_NS(i)][:] = ns.nodes # ------------------------------------------------------------------- # # -------------------------------------------- side set meta data --- # # ------------------------------------------------------------------- # nss = 0 if side_sets is None else len(side_sets) if nss: self.fh.createDimension(DIM_NUM_SIDE_SETS, nss) # side set IDs - standard map prop1 = np.arange(nss, dtype=np.int32) + 1 self.fh.createVariable(VAR_SS_PROP1, INT, (DIM_NUM_SIDE_SETS,)) self.fh.variables[VAR_SS_PROP1][:] = prop1 self.fh.variables[VAR_SS_PROP1].name = 'ID' self.fh.createVariable(VAR_SS_NAMES, CHAR, (DIM_NUM_SIDE_SETS, DIM_LEN_STRING)) for (i, ss) in enumerate(side_sets, start=1): self.fh.variables[VAR_SS_NAMES][i-1][:] = adjstr(ss.name) self.fh.createDimension(DIM_NUM_SIDE_SS(i), len(ss.sides)) self.fh.createVariable(VAR_SIDE_SS(i), INT, (DIM_NUM_SIDE_SS(i),)) self.fh.variables[VAR_SIDE_SS(i)][:] = ss.sides self.fh.createVariable(VAR_ELEM_SS(i), INT, (DIM_NUM_ELEM_SS(i),)) self.fh.variables[VAR_ELEM_SS(i)][:] = ss.elements # ------------------------------------------------------------------- # # --------------------------------------- element block meta data --- # # ------------------------------------------------------------------- # # block IDs - standard map num_el_blk = len(element_blocks) self.fh.createDimension(DIM_NUM_EL_BLK, num_el_blk) prop1 = np.arange(num_el_blk, dtype=np.int32) + 1 self.fh.createVariable(VAR_EB_PROP1, INT, (DIM_NUM_EL_BLK,)) self.fh.variables[VAR_EB_PROP1][:] = prop1 self.fh.variables[VAR_EB_PROP1].name = 'ID' self.fh.createVariable(VAR_EB_STATUS, INT, (DIM_NUM_EL_BLK,)) self.fh.variables[VAR_EB_STATUS][:] = np.ones(num_el_blk, dtype=int) self.fh.createVariable(VAR_EB_NAMES, CHAR, (DIM_NUM_EL_BLK, DIM_LEN_STRING)) for (i, block) in enumerate(element_blocks, start=1): self.fh.variables[VAR_EB_NAMES][i-1][:] = adjstr(block.name) # block connect ij = [elements.index(e) for e in block.elements] block_conn = np.array([[n for n in c if n >= 0] for c in connect[ij]]) ne, nn = block_conn.shape d1, d2 = DIM_NUM_EL_IN_BLK(i), DIM_NUM_NOD_PER_EL(i) self.fh.createDimension(d1, ne) self.fh.createDimension(d2, nn) # element map elem_map = VAR_ELEM_MAP(i) self.fh.createVariable(elem_map, INT, (d1,)) self.fh.variables[elem_map][:] = block.elements # set up the element block connectivity self.fh.createVariable(VAR_CONNECT(i), INT, (d1, d2)) self.fh.variables[VAR_CONNECT(i)][:] = block_conn # element type if dimension == 1: elem_type = 'TRUSS' elif dimension == 2: if nn == 3: elem_type = 'TRI' elif nn == 4: elem_type = 'QUAD' elif dimension == 3: if nn in (4, 6): elem_type = 'TET' elif nn in (8, 20): elem_type = 'HEX' self.fh.variables[VAR_CONNECT(i)].elem_type = elem_type for j in range(1, nev+1): self.fh.createVariable(VALS_ELEM_VAR(j,i), FLOAT, (DIM_TIME_STEP, d1)) # ------------------------------------------------------------------- # # ------------------------------------------------ node meta data --- # # ------------------------------------------------------------------- # if len(vertices.shape) == 1: vertices = np.reshape(vertices, (num_node, dimension)) self.fh.createVariable(VAR_COOR_NAMES, CHAR, (DIM_NUM_DIM, DIM_LEN_STRING)) for i in range(dimension): self.fh.variables[VAR_COOR_NAMES][i][:] = adjstr(VAR_COOR_NAME(i)) self.fh.createVariable(VAR_COOR_NAME(i), FLOAT, (DIM_NUM_NODES,)) self.fh.variables[VAR_COOR_NAME(i)][:] = vertices[:, i] for j in range(1, nnv+1): self.fh.createVariable(VALS_NOD_VAR(j), FLOAT, (DIM_TIME_STEP, DIM_NUM_NODES)) # ------------------------------------------------------------------- # # ------------------------------------ global variables meta data --- # # ------------------------------------------------------------------- # self.fh.createDimension(DIM_NUM_GLO_VAR, 1) self.fh.createVariable(VALS_GLO_VAR, FLOAT, (DIM_TIME_STEP, )) self.initialized = True return def put_steps(self, steps): for step in steps: self.put_step(step) self.close() def put_step(self, step): assert self.initialized self.fh.variables[VAR_STEP_NAMES][self.step_count] = adjstr(step.name) for frame in step.frames: # write time value count = len(self.fh.variables[VAR_TIME_WHOLE].data) self.fh.variables[VAR_TIME_WHOLE][count] = frame.value self.fh.variables[VAR_STEP_NUM][count] = self.step_count self.fh.variables[VALS_GLO_VAR][count] = 0. # get node and element fields fields = frame.field_outputs.values() fo_n = [fo for fo in fields if fo.position==NODE] fo_e = [fo for fo in fields if fo.position==ELEMENT] # write out node fields a = stringify(self.fh.variables[VAR_NAME_NOD_VAR]) for fo in fo_n: data = fo.get_data() if len(data.shape) == 1: data = data.reshape(-1, 1) for (k, key) in enumerate(fo.keys): i = a.index(key) + 1 self.fh.variables[VALS_NOD_VAR(i)][count] = data[:, k] # write element data to the appropriate element block a = stringify(self.fh.variables[VAR_NAME_ELEM_VAR]) ebs = stringify(self.fh.variables[VAR_EB_NAMES]) for fo in fo_e: for (j, eb) in enumerate(ebs, start=1): bd = fo.get_data(block=eb) if len(bd.shape) == 1: bd = bd.reshape(-1, 1) for (k, key) in enumerate(fo.keys): i = a.index(key) + 1 self.fh.variables[VALS_ELEM_VAR(i,j)][count] = bd[:, k] self.step_count += 1 return