def _verify_params(self, where, node_type): """Verifies that the node parameters are set correctly.""" for name, param in node_type.params.iteritems(): # Single number. if util.is_number(param): continue # Single vector. elif type(param) is tuple: for el in param: if not util.is_number(el): raise ValueError("Tuple elements have to be numbers.") # Field. If more than a single number is needed per node, this # needs to be a numpy record array. Use node_util.multifield() # to create this array easily. elif isinstance(param, np.ndarray): assert param.size == np.sum(where), ("Your array needs to " "have exactly as many nodes as there are True values " "in the 'where' array. Use node_util.multifield() to " "generate the array in an easy way.") elif isinstance(param, nt.DynamicValue): if param.has_symbols(sym.S.time): self.config.time_dependence = True if param.has_symbols(sym.S.gx, sym.S.gy, sym.S.gz): self.config.space_dependence = True continue else: raise ValueError("Unrecognized node param: {0} (type {1})". format(name, type(param)))
def _verify_params(self, where, node_type): """Verifies that the node parameters are set correctly.""" for name, param in node_type.params.items(): # Single number. if util.is_number(param): continue # Single vector. elif type(param) is tuple: for el in param: if not util.is_number(el): raise ValueError("Tuple elements have to be numbers.") # Field. If more than a single number is needed per node, this # needs to be a numpy record array. Use node_util.multifield() # to create this array easily. elif isinstance(param, np.ndarray): assert param.size == np.sum(where), ( "Your array needs to " "have exactly as many nodes as there are True values " "in the 'where' array. Use node_util.multifield() to " "generate the array in an easy way.") elif isinstance(param, nt.DynamicValue): if param.has_symbols(sym.S.time) or list( zip(param.get_timeseries())): self.config.time_dependence = True if param.has_symbols(sym.S.gx, sym.S.gy, sym.S.gz): self.config.space_dependence = True continue elif isinstance(param, ImmutableDenseMatrix): continue else: raise ValueError( "Unrecognized node param: {0} (type {1})".format( name, type(param)))
def _get_structured_array(self, params): """Returns a structured numpy array with spatial data""" data = () where = [] for param in params: if isinstance(param, SpatialArray): data += (param._data, ) if where != [] and where is not None: assert where == param._where else: where = param._where.copy() continue elif is_number(param): data += (param, ) continue elif not isinstance(param, expr.Expr): continue for arg in param.args: if isinstance(arg, SpatialArray): data += (arg._data, ) if where != [] and where is not None: assert where == arg._where else: where = arg._where.copy() break else: data += (1.0, ) return multifield(data, where)
def prepare_encode(self, type_map, param_map, param_dict): """ :param type_map: uint32 array of NodeType.ids :param param_map: array whose entries are keys in param_dict :param param_dict: maps entries from param_map to LBNodeType objects """ uniq_types = list(np.unique(type_map)) for nt_id in uniq_types: self._node_types.add(nt._NODE_TYPES[nt_id]) # Initialize the node ID map used for remapping. for i, node_type in enumerate(uniq_types): self._type_id_remap[node_type] = i + 1 self._bits_type = bit_len(len(uniq_types)) self._type_map = type_map self._param_map = param_map self._param_dict = param_dict self._encoded_param_map = np.zeros_like(self._type_map) self._scratch_map = np.zeros_like(self._type_map) param_to_idx = dict() # Maps entries in seen_params to ids. seen_params = set() param_items = 0 self._symbol_map = {} # Maps param indices to sympy expressions. # Refer to subdomain.Subdomain._verify_params for a list of allowed # ways of encoding nodes. for node_key, node_type in param_dict.iteritems(): for param in node_type.params.itervalues(): if util.is_number(param): if param in seen_params: idx = param_to_idx[param] else: seen_params.add(param) self._geo_params.append(param) idx = param_items param_to_idx[param] = idx param_items += 1 self._encoded_param_map[param_map == node_key] = idx elif type(param) is tuple: if param in seen_params: idx = param_to_idx[param] else: seen_params.add(param) self._geo_params.extend(param) idx = param_items param_to_idx[param] = idx param_items += len(param) self._encoded_param_map[param_map == node_key] = idx # Param is a structured numpy array. elif isinstance(param, np.ndarray): nodes_idx = np.argwhere(param_map == node_key) uniques = np.unique(param) uniques.flags.writeable = False for value in uniques: if value in seen_params: idx = param_to_idx[value] else: seen_params.add(value) self._geo_params.extend(value) idx = param_items param_to_idx[value] = idx param_items += len(value) idxs = nodes_idx[param == value] if idxs.shape[1] == 3: self._encoded_param_map[idxs[:,0], idxs[:,1], idxs[:,2]] = idx elif idxs.shape[1] == 2: self._encoded_param_map[idxs[:,0], idxs[:,1]] = idx else: assert False, 'Unsupported dimension: {0}'.format( idxs.shape[1]) self._non_symbolic_idxs = param_items # Second pass: only process symbolic expressions here. for node_key, node_type in param_dict.iteritems(): for param in node_type.params.itervalues(): if isinstance(param, nt.DynamicValue): if param in seen_params: idx = param_to_idx[value] else: seen_params.add(param) idx = param_items self._symbol_map[idx] = param param_to_idx[param] = idx param_items += 1 self._encoded_param_map[param_map == node_key] = idx self._bits_param = bit_len(param_items) # Maps node type ID to base offset within the scratch space array. self._scratch_space_base = {} type_to_node_count = {} # Generate unique (within node type) scratch space ids. for node_type in self._node_types: if node_type.scratch_space_size(self.dim) <= 0: continue def _selector(idx_list): return [slice(i, i+1) for i in idx_list] idx = np.argwhere(self._type_map == node_type.id) num_nodes = idx.shape[0] type_to_node_count[node_type.id] = num_nodes for i in xrange(num_nodes): self._scratch_map[_selector(idx[i,:])] = i self._scratch_space_base[node_type.id] = self.scratch_space_size # Accumulate size requirements of specific types into a global # size value for the whole scratch buffer. self.scratch_space_size += num_nodes * node_type.scratch_space_size(self.dim) if type_to_node_count: self._bits_scratch = bit_len(max(type_to_node_count.itervalues())) else: self._bits_scratch = 0
def prepare_encode(self, type_map, param_map, param_dict, orientation, have_link_tags): """ :param type_map: uint32 array of NodeType.ids :param param_map: array whose entries are keys in param_dict :param param_dict: maps entries from param_map to LBNodeType objects """ uniq_types = list(np.unique(type_map)) for nt_id in uniq_types: self._node_types.add(nt._NODE_TYPES[nt_id]) # Initialize the node ID map used for remapping. for i, node_type in enumerate(uniq_types): self._type_id_remap[node_type] = i + 1 self._bits_type = bit_len(len(uniq_types)) self._type_map = type_map self._param_map = param_map self._param_dict = param_dict self._encoded_param_map = np.zeros_like(self._type_map) self._scratch_map = np.zeros_like(self._type_map) param_to_idx = dict() # Maps entries in seen_params to ids. seen_params = set() param_items = 0 # Refer to subdomain.Subdomain._verify_params for a list of allowed # ways of encoding nodes. for node_key, node_type in param_dict.iteritems(): for param in node_type.params.itervalues(): if util.is_number(param): if param in seen_params: idx = param_to_idx[param] else: seen_params.add(param) self._geo_params.append(param) idx = param_items param_to_idx[param] = idx param_items += 1 self._encoded_param_map[param_map == node_key] = idx elif type(param) is tuple: if param in seen_params: idx = param_to_idx[param] else: seen_params.add(param) self._geo_params.extend(param) idx = param_items param_to_idx[param] = idx param_items += len(param) self._encoded_param_map[param_map == node_key] = idx # Param is a structured numpy array. elif isinstance(param, np.ndarray): nodes_idx = np.argwhere(param_map == node_key) uniques = np.unique(param) uniques.flags.writeable = False for value in uniques: if value in seen_params: idx = param_to_idx[value] else: seen_params.add(value) self._geo_params.extend(value) idx = param_items param_to_idx[value] = idx param_items += len(value) idxs = nodes_idx[param == value] if idxs.shape[1] == 3: self._encoded_param_map[idxs[:,0], idxs[:,1], idxs[:,2]] = idx elif idxs.shape[1] == 2: self._encoded_param_map[idxs[:,0], idxs[:,1]] = idx else: assert False, 'Unsupported dimension: {0}'.format( idxs.shape[1]) self._non_symbolic_idxs = param_items self._symbol_map = {} # Maps param indices to sympy expressions. # Maps timeseries data ID to offset in self._timeseries_data. timeseries_offset_map = {} timeseries_offset = 0 # TODO(michalj): Verify that the type of the symbolic expression matches # that of the boundary condition (vector vs scalar, etc). # Second pass: only process symbolic expressions here. for node_key, node_type in param_dict.iteritems(): for param in node_type.params.itervalues(): if isinstance(param, nt.DynamicValue): if param in seen_params: idx = param_to_idx[value] else: seen_params.add(param) idx = param_items self._symbol_map[idx] = param param_to_idx[param] = idx param_items += 1 for ts in param.get_timeseries(): dh = ts.data_hash() if dh in timeseries_offset_map: ts._offset = timeseries_offset_map[dh] else: ts._offset = timeseries_offset timeseries_offset_map[dh] = ts._offset timeseries_offset += ts._data.size self._timeseries_data.extend(ts._data) self._encoded_param_map[param_map == node_key] = idx self._bits_param = bit_len(param_items) # Maps node type ID to base offset within the scratch space array. self._scratch_space_base = {} type_to_node_count = {} # Generate unique (within node type) scratch space ids. for node_type in self._node_types: if node_type.scratch_space_size(self.dim) <= 0: continue def _selector(idx_list): return [slice(i, i+1) for i in idx_list] idx = np.argwhere(self._type_map == node_type.id) num_nodes = idx.shape[0] type_to_node_count[node_type.id] = num_nodes for i in xrange(num_nodes): self._scratch_map[_selector(idx[i,:])] = i self._scratch_space_base[node_type.id] = self.scratch_space_size # Accumulate size requirements of specific types into a global # size value for the whole scratch buffer. self.scratch_space_size += num_nodes * node_type.scratch_space_size(self.dim) if type_to_node_count: self._bits_scratch = bit_len(max(type_to_node_count.itervalues())) else: self._bits_scratch = 0 self._have_link_tags = have_link_tags if have_link_tags: # TODO: Actually drop these bits to save space in the node code. # It would be nice to use reduce here instead, but # bitwise_and.identity = 1 makes it impossible to use it. self._unused_tag_bits = int(np.bitwise_and.accumulate( orientation[orientation > 0])[-1])
def prepare_encode(self, type_map, param_map, param_dict, orientation, have_link_tags): """ :param type_map: uint32 array of NodeType.ids :param param_map: array whose entries are keys in param_dict :param param_dict: maps entries from param_map to LBNodeType objects """ uniq_types = list(np.unique(type_map)) for nt_id in uniq_types: self._node_types.add(nt._NODE_TYPES[nt_id]) # Initialize the node ID map used for remapping. for i, node_type in enumerate(uniq_types): self._type_id_remap[node_type] = i + 1 self._bits_type = bit_len(len(uniq_types)) self._type_map = type_map self._param_map = param_map self._param_dict = param_dict self._encoded_param_map = np.zeros_like(self._type_map) self._scratch_map = np.zeros_like(self._type_map) param_to_idx = dict() # Maps entries in seen_params to ids. seen_params = set() param_items = 0 # Refer to subdomain.Subdomain._verify_params for a list of allowed # ways of encoding nodes. for node_key, node_type in param_dict.items(): for param in node_type.params.values(): if util.is_number(param): if param in seen_params: idx = param_to_idx[param] else: seen_params.add(param) self._geo_params.append(param) idx = param_items param_to_idx[param] = idx param_items += 1 self._encoded_param_map[param_map == node_key] = idx elif type(param) is tuple: if param in seen_params: idx = param_to_idx[param] else: seen_params.add(param) self._geo_params.extend(param) idx = param_items param_to_idx[param] = idx param_items += len(param) self._encoded_param_map[param_map == node_key] = idx # Param is a structured numpy array. elif isinstance(param, np.ndarray): nodes_idx = np.argwhere(param_map == node_key) uniques = np.unique(param) uniques.flags.writeable = False for value in uniques: if value in seen_params: idx = param_to_idx[value] else: seen_params.add(value) self._geo_params.extend(value) idx = param_items param_to_idx[value] = idx param_items += len(value) idxs = nodes_idx[param == value] if idxs.shape[1] == 3: self._encoded_param_map[idxs[:,0], idxs[:,1], idxs[:,2]] = idx elif idxs.shape[1] == 2: self._encoded_param_map[idxs[:,0], idxs[:,1]] = idx else: assert False, 'Unsupported dimension: {0}'.format( idxs.shape[1]) self._non_symbolic_idxs = param_items self._symbol_map = {} # Maps param indices to sympy expressions. self._symbol_to_geo_map = {} #Maps array indices #to one sympy expression self._non_sa_symbolic_map = {} self._extended_copy_map = {} # Maps timeseries data ID to offset in self._timeseries_data. timeseries_offset_map = {} timeseries_offset = 0 for node_key, node_type in param_dict.items(): for param in node_type.params.values(): if isinstance(param, nt.DynamicValue) and param.need_mf: param_data = param.data nodes_idx = np.argwhere(param_map == node_key) symbol_idx = param_items self._symbol_map[symbol_idx] = param uniques = np.unique(param_data) uniques.flags.writeable = False sym_indexes=() for value in uniques: if (value, param) in seen_params: idx = param_to_idx[(value, param)] else: seen_params.add((value, param)) for v in value: self._geo_params.append((v, param)) idx = param_items sym_indexes+=(idx,) param_to_idx[(value, param)] = idx param_items += len(value) for ts in param.get_timeseries(): dh = ts.data_hash() if dh in timeseries_offset_map: ts._offset = timeseries_offset_map[dh] else: ts._offset = timeseries_offset timeseries_offset_map[dh] = ts._offset timeseries_offset += ts._data.size self._timeseries_data.extend(ts._data) idxs = nodes_idx[param_data == value] if idxs.shape[1] == 3: self._encoded_param_map[idxs[:,0], idxs[:,1], idxs[:,2]] = idx elif idxs.shape[1] == 2: self._encoded_param_map[idxs[:,0], idxs[:,1]] = idx else: assert False, 'Unsupported dimension: {0}'.format( idxs.shape[1]) self._symbol_to_geo_map[symbol_idx]=sym_indexes # TODO(michalj): Verify that the type of the symbolic expression matches # that of the boundary condition (vector vs scalar, etc). # Second pass: only process symbolic expressions here. for node_key, node_type in param_dict.items(): for param in node_type.params.values(): if isinstance(param, nt.DynamicValue) and not param.need_mf: if param in seen_params: idx = param_to_idx[param] else: seen_params.add(param) idx = param_items self._symbol_map[idx] = param self._non_sa_symbolic_map[idx] = param param_to_idx[param] = idx param_items += 1 for ts in param.get_timeseries(): dh = ts.data_hash() if dh in timeseries_offset_map: ts._offset = timeseries_offset_map[dh] else: ts._offset = timeseries_offset timeseries_offset_map[dh] = ts._offset timeseries_offset += ts._data.size self._timeseries_data.extend(ts._data) self._encoded_param_map[param_map == node_key] = idx elif isinstance(param, ImmutableDenseMatrix): if param in seen_params: idx = param_to_idx[param] else: seen_params.add(param) idx = param_items self._extended_copy_map[idx] = param param_to_idx[param] = idx param_items += 1 self._encoded_param_map[param_map == node_key] = idx self._bits_param = bit_len(param_items) # Maps node type ID to base offset within the scratch space array. self._scratch_space_base = {} type_to_node_count = {} # Generate unique (within node type) scratch space ids. for node_type in self._node_types: if node_type.scratch_space_size(self.dim) <= 0: continue def _selector(idx_list): return tuple([slice(i, i+1) for i in idx_list]) idx = np.argwhere(self._type_map == node_type.id) num_nodes = idx.shape[0] type_to_node_count[node_type.id] = num_nodes for i in range(num_nodes): self._scratch_map[_selector(idx[i,:])] = i self._scratch_space_base[node_type.id] = self.scratch_space_size # Accumulate size requirements of specific types into a global # size value for the whole scratch buffer. self.scratch_space_size += num_nodes * node_type.scratch_space_size(self.dim) if type_to_node_count: self._bits_scratch = bit_len(max(type_to_node_count.values())) else: self._bits_scratch = 0 self._have_link_tags = have_link_tags if have_link_tags: # TODO: Actually drop these bits to save space in the node code. # It would be nice to use reduce here instead, but # bitwise_and.identity = 1 makes it impossible to use it. self._unused_tag_bits = int(np.bitwise_and.accumulate( orientation[orientation > 0])[-1])
def prepare_encode(self, type_map, param_map, param_dict): """ :param type_map: uint32 array of NodeType.ids :param param_map: array whose entries are keys in param_dict :param param_dict: maps entries from param_map to LBNodeType objects """ uniq_types = list(np.unique(type_map)) for nt_id in uniq_types: self._node_types.add(nt._NODE_TYPES[nt_id]) # Initialize the node ID map used for remapping. for i, node_type in enumerate(uniq_types): self._type_id_remap[node_type] = i + 1 self._bits_type = bit_len(len(uniq_types)) self._type_map = type_map self._param_map = param_map self._param_dict = param_dict self._encoded_param_map = np.zeros_like(self._type_map) self._scratch_map = np.zeros_like(self._type_map) param_to_idx = dict() # Maps entries in seen_params to ids. seen_params = set() param_items = 0 self._symbol_map = {} # Maps param indices to sympy expressions. # Refer to subdomain.Subdomain._verify_params for a list of allowed # ways of encoding nodes. for node_key, node_type in param_dict.iteritems(): for param in node_type.params.itervalues(): if util.is_number(param): if param in seen_params: idx = param_to_idx[param] else: seen_params.add(param) self._geo_params.append(param) idx = param_items param_to_idx[param] = idx param_items += 1 self._encoded_param_map[param_map == node_key] = idx elif type(param) is tuple: if param in seen_params: idx = param_to_idx[param] else: seen_params.add(param) self._geo_params.extend(param) idx = param_items param_to_idx[param] = idx param_items += len(param) self._encoded_param_map[param_map == node_key] = idx # Param is a structured numpy array. elif isinstance(param, np.ndarray): nodes_idx = np.argwhere(param_map == node_key) uniques = np.unique(param) uniques.flags.writeable = False for value in uniques: if value in seen_params: idx = param_to_idx[value] else: seen_params.add(value) self._geo_params.extend(value) idx = param_items param_to_idx[value] = idx param_items += len(value) idxs = nodes_idx[param == value] if idxs.shape[1] == 3: self._encoded_param_map[idxs[:, 0], idxs[:, 1], idxs[:, 2]] = idx elif idxs.shape[1] == 2: self._encoded_param_map[idxs[:, 0], idxs[:, 1]] = idx else: assert False, 'Unsupported dimension: {0}'.format( idxs.shape[1]) self._non_symbolic_idxs = param_items # Second pass: only process symbolic expressions here. for node_key, node_type in param_dict.iteritems(): for param in node_type.params.itervalues(): if isinstance(param, nt.DynamicValue): if param in seen_params: idx = param_to_idx[value] else: seen_params.add(param) idx = param_items self._symbol_map[idx] = param param_to_idx[param] = idx param_items += 1 self._encoded_param_map[param_map == node_key] = idx self._bits_param = bit_len(param_items) # Maps node type ID to base offset within the scratch space array. self._scratch_space_base = {} type_to_node_count = {} # Generate unique (within node type) scratch space ids. for node_type in self._node_types: if node_type.scratch_space_size(self.dim) <= 0: continue def _selector(idx_list): return [slice(i, i + 1) for i in idx_list] idx = np.argwhere(self._type_map == node_type.id) num_nodes = idx.shape[0] type_to_node_count[node_type.id] = num_nodes for i in xrange(num_nodes): self._scratch_map[_selector(idx[i, :])] = i self._scratch_space_base[node_type.id] = self.scratch_space_size # Accumulate size requirements of specific types into a global # size value for the whole scratch buffer. self.scratch_space_size += num_nodes * node_type.scratch_space_size( self.dim) if type_to_node_count: self._bits_scratch = bit_len(max(type_to_node_count.itervalues())) else: self._bits_scratch = 0