def map_for_axes(function, obj, axes, rank): if axes is None: return function(obj) else: return [(function(collapsed_gather_nd(obj, i)) if _contains_axis( axes, i, rank) else collapsed_gather_nd(obj, i)) for i in range(rank)]
def sparse_indices(dimensions, periodic=False): N = int(np.prod(dimensions)) d = len(dimensions) dims = range(d) gridpoints_linear = np.arange(N) gridpoints = np.stack(np.unravel_index( gridpoints_linear, dimensions)) # d * (N^2) array mapping from linear to spatial frames indices_list = [np.stack([gridpoints_linear] * 2, axis=-1)] for dim in dims: dim_direction = math.expand_dims( [1 if i == dim else 0 for i in range(d)], axis=-1) # --- Stencil upper cells --- upper_points, upper_idx = wrap_or_discard(gridpoints + dim_direction, dim, dimensions, periodic=collapsed_gather_nd( periodic, [dim, 1])) indices_list.append( np.stack([gridpoints_linear[upper_idx], upper_points], axis=-1)) # --- Stencil lower cells --- lower_points, lower_idx = wrap_or_discard(gridpoints - dim_direction, dim, dimensions, periodic=collapsed_gather_nd( periodic, [dim, 0])) indices_list.append( np.stack([gridpoints_linear[lower_idx], lower_points], axis=-1)) indices = np.concatenate(indices_list, axis=0) # --- Sort indices --- sorting = np.lexsort(np.transpose(indices)[:, ::-1]) sorted_indices = indices[sorting] return sorted_indices, sorting
def collapsed_gather_nd(self): self.assertEqual('a', collapsed_gather_nd('a', [1, 2, 3, 4, 5])) self.assertEqual('b', collapsed_gather_nd(['a', 'b'], [1, 0])) self.assertEqual( ('b', 'b'), collapsed_gather_nd(['a', ('b', 'b')], [1, 0], leaf_condition=lambda x: isinstance(x, tuple)))
def pad(self, value, pad_width, mode='constant', constant_values=0): dims = range(len(self.staticshape(value))) if isinstance(mode, six.string_types) and len( self.staticshape(constant_values)) == 0: return self._single_mode_single_constant_pad( value, pad_width, mode, constant_values) else: mode = expand(mode, shape=(len(dims), 2)) passes = [('wrap', 0), ('symmetric', 0), ('reflect', 0)] constant_values = expand(constant_values, shape=(len(dims), 2)) constant_value_set = set() for d in dims: for upper in (False, True): constant_value_set.add(constant_values[d][upper]) for const in constant_value_set: passes.append(('constant', const)) for single_mode, constant_value in passes: # order matters! wrap first widths = [[ collapsed_gather_nd(pad_width, [d, upper]) if mode[d][upper] == single_mode and constant_values[d][upper] == constant_value else 0 for upper in (False, True) ] for d in dims] value = self._single_mode_single_constant_pad( value, widths, single_mode, constant_value) return value
def pad(self, value, pad_width, mode='constant', constant_values=0): dims = range(len(self.shape(value))) constant_values = expand(constant_values, shape=(len(dims), 2)) if isinstance(mode, six.string_types): return self._single_mode_pad(value, pad_width, mode, constant_values) else: mode = expand(mode, shape=(len(dims), 2)) for single_mode in ('wrap', 'symmetric', 'reflect', 'constant'): # order matters! wrap first widths = [[collapsed_gather_nd(pad_width, [d, upper]) if mode[d][upper] == single_mode else 0 for upper in (False, True)] for d in dims] value = self._single_mode_pad(value, widths, single_mode, constant_values) return value
def resample_cuda(inputs, sample_coords, boundary): ZERO = 0 REPLICATE = 1 CIRCULAR = 2 SYMMETRIC = 3 REFLECT = 4 shape = inputs.shape dims = len(shape) - 2 boundary_array = np.zeros((dims, 2), np.uint32) for i in range(dims): for j in range(2): current_boundary = collapsed_gather_nd(boundary, [i, j]).lower() if current_boundary == 'zero' or current_boundary == 'constant': boundary_array[i, j] = ZERO elif current_boundary == 'replicate': boundary_array[i, j] = REPLICATE elif current_boundary == 'circular' or current_boundary == 'wrap': boundary_array[i, j] = CIRCULAR elif current_boundary == 'symmetric': boundary_array[i, j] = SYMMETRIC elif current_boundary == 'reflect': boundary_array[i, j] = REFLECT return resample_op.resample(inputs, sample_coords, boundary_array)
def setup(self): header_layout = html.Div([ dcc.Link('Home', href='/'), ' - ', dcc.Link('Side-by-Side', href='/side-by-side'), ' - ', dcc.Link('Quad', href='/quad'), ' - ', dcc.Link('Info', href='/info'), ' - ', dcc.Link('Log', href='/log'), ' - ', dcc.Link(u'Φ Board', href='/board'), # ' - ', # dcc.Link('Scripting', href='/scripting'), ' - ', html. A('Help', href= 'https://github.com/tum-pbs/PhiFlow/blob/master/documentation/Web_Interface.md', target='_blank'), ]) dash_app = self.dash_app = DashApp(self.app, self.config, header_layout) # --- Shared components --- player_controls = build_player_controls(dash_app) status_bar = build_status_bar(dash_app) model_controls = build_model_controls(dash_app) # --- Home --- layout = html.Div([ build_description(dash_app), build_view_selection(dash_app), html.Div(style={ 'width': 1000, 'height': 800, 'margin-left': 'auto', 'margin-right': 'auto' }, children=[ build_viewer(dash_app, id='home', initial_field_name=collapsed_gather_nd( self.config.get('display', None), [0]), config=self.config), ]), status_bar, player_controls, model_controls, ]) dash_app.add_page('/', layout) # --- Side by Side --- if 'display' in self.config: sbs_fieldnames = self.config['display'] if sbs_fieldnames is None: sbs_fieldnames = [None, None] elif isinstance(sbs_fieldnames, six.string_types): sbs_fieldnames = [sbs_fieldnames] * 2 else: sbs_fieldnames = self.app.fieldnames if len(sbs_fieldnames) == 0: sbs_fieldnames = ['None', 'None'] elif len(sbs_fieldnames) < 2: sbs_fieldnames = list(sbs_fieldnames) + ['None'] layout = html.Div([ build_view_selection(dash_app), html.Div(style={ 'width': '50%', 'height': 700, 'display': 'inline-block' }, children=[ build_viewer(dash_app, id='left', initial_field_name=sbs_fieldnames[0], config=self.config), ]), html.Div(style={ 'width': '50%', 'height': 700, 'display': 'inline-block' }, children=[ build_viewer(dash_app, id='right', initial_field_name=sbs_fieldnames[1], config=self.config), ]), status_bar, player_controls, model_controls, ]) dash_app.add_page('/side-by-side', layout) # --- Quad --- layout = html.Div([ build_view_selection(dash_app), html.Div(style={ 'width': '50%', 'height': 700, 'display': 'inline-block' }, children=[ build_viewer(dash_app, id='top-left', initial_field_name=sbs_fieldnames[0], config=self.config), ]), html.Div(style={ 'width': '50%', 'height': 700, 'display': 'inline-block' }, children=[ build_viewer(dash_app, id='top-right', initial_field_name=sbs_fieldnames[1], config=self.config), ]), html.Div(style={ 'width': '50%', 'height': 700, 'display': 'inline-block' }, children=[ build_viewer(dash_app, id='bottom-left', initial_field_name=sbs_fieldnames[0], config=self.config), ]), html.Div(style={ 'width': '50%', 'height': 700, 'display': 'inline-block' }, children=[ build_viewer(dash_app, id='bottom-right', initial_field_name=sbs_fieldnames[1], config=self.config), ]), status_bar, player_controls, model_controls, ]) dash_app.add_page('/quad', layout) # --- Log --- layout = html.Div([ dcc.Markdown('# Log'), status_bar, player_controls, build_log(dash_app) ]) dash_app.add_page('/log', layout) # --- Info --- layout = html.Div([ build_description(dash_app), status_bar, player_controls, build_phiflow_info(dash_app), build_app_details(dash_app), build_app_time(dash_app), ]) dash_app.add_page('/info', layout) # --- Board --- layout = html.Div([ dcc.Markdown(u'# Φ Board'), status_bar, player_controls, ] + ([] if 'tensorflow' not in dash_app.app.traits else [ build_tensorboard_launcher(dash_app), ]) + [ model_controls, build_benchmark(dash_app), ] + ([] if 'tensorflow' not in dash_app.app.traits else [ build_tf_profiler(dash_app), ]) + [ build_system_controls(dash_app), # ToDo: Graphs, Record/Animate ]) dash_app.add_page('/board', layout) # --- Scripting --- layout = html.Div([ dcc.Markdown(u'# Python Scripting'), 'Custom Fields, Execute script, Restart' ]) dash_app.add_page('/scripting', layout) return self.dash_app.dash
def surface_material(self, axis=0, upper_boundary=False): return collapsed_gather_nd(self.boundaries, axis, upper_boundary)
def sparse_values(dimensions, extended_active_mask, extended_fluid_mask, sorting=None, periodic=False): """ Builds a sparse matrix such that when applied to a flattened pressure channel, it calculates the laplace of that channel, taking into account obstacles and empty cells. :param dimensions: valid simulation dimensions. Pressure channel should be of shape (batch size, dimensions..., 1) :param extended_active_mask: Binary tensor with 2 more entries in every dimension than 'dimensions'. :param extended_fluid_mask: Binary tensor with 2 more entries in every dimension than 'dimensions'. :return: SciPy sparse matrix that acts as a laplace on a flattened pressure channel given obstacles and empty cells """ N = int(np.prod(dimensions)) d = len(dimensions) dims = range(d) values_list = [] diagonal_entries = 0 # diagonal matrix entries gridpoints_linear = np.arange(N) gridpoints = np.stack(np.unravel_index(gridpoints_linear, dimensions)) # d * (N^2) array mapping from linear to spatial frames for dim in dims: lower_active, self_active, upper_active = _dim_shifted(extended_active_mask, dim, (-1, 0, 1), diminish_others=(1, 1)) lower_accessible, upper_accessible = _dim_shifted(extended_fluid_mask, dim, (-1, 1), diminish_others=(1, 1)) stencil_upper = upper_active * self_active stencil_lower = lower_active * self_active stencil_center = - lower_accessible - upper_accessible diagonal_entries += math.flatten(stencil_center) dim_direction = math.expand_dims([1 if i == dim else 0 for i in range(d)], axis=-1) # --- Stencil upper cells --- upper_points, upper_idx = wrap_or_discard(gridpoints + dim_direction, dim, dimensions, periodic=collapsed_gather_nd(periodic, [dim, 1])) values_list.append(math.gather(math.flatten(stencil_upper), upper_idx)) # --- Stencil lower cells --- lower_points, lower_idx = wrap_or_discard(gridpoints - dim_direction, dim, dimensions, periodic=collapsed_gather_nd(periodic, [dim, 0])) values_list.append(math.gather(math.flatten(stencil_lower), lower_idx)) values_list.insert(0, math.minimum(diagonal_entries, -1.)) values = math.concat(values_list, axis=0) if sorting is not None: values = math.gather(values, sorting) return values
def sparse_pressure_matrix(dimensions, extended_active_mask, extended_fluid_mask, periodic=False): """ Builds a sparse matrix such that when applied to a flattened pressure channel, it calculates the laplace of that channel, taking into account obstacles and empty cells. :param dimensions: valid simulation dimensions. Pressure channel should be of shape (batch size, dimensions..., 1) :param extended_active_mask: Binary tensor with 2 more entries in every dimension than 'dimensions'. :param extended_fluid_mask: Binary tensor with 2 more entries in every dimension than 'dimensions'. :return: SciPy sparse matrix that acts as a laplace on a flattened pressure channel given obstacles and empty cells """ N = int(np.prod(dimensions)) d = len(dimensions) A = scipy.sparse.lil_matrix((N, N), dtype=np.float32) dims = range(d) diagonal_entries = np.zeros(N, extended_active_mask.dtype) # diagonal matrix entries gridpoints_linear = np.arange(N) gridpoints = np.stack(np.unravel_index(gridpoints_linear, dimensions)) # d * (N^2) array mapping from linear to spatial frames for dim in dims: lower_active, self_active, upper_active = _dim_shifted(extended_active_mask, dim, (-1, 0, 1), diminish_others=(1,1)) lower_accessible, upper_accessible = _dim_shifted(extended_fluid_mask, dim, (-1, 1), diminish_others=(1, 1)) stencil_upper = upper_active * self_active stencil_lower = lower_active * self_active stencil_center = - lower_accessible - upper_accessible diagonal_entries += math.flatten(stencil_center) dim_direction = math.expand_dims([1 if i == dim else 0 for i in range(d)], axis=-1) # --- Stencil upper cells --- upper_points, upper_idx = wrap_or_discard(gridpoints + dim_direction, dim, dimensions, periodic=collapsed_gather_nd(periodic, [dim, 1])) A[gridpoints_linear[upper_idx], upper_points] = stencil_upper.flatten()[upper_idx] # --- Stencil lower cells --- lower_points, lower_idx = wrap_or_discard(gridpoints - dim_direction, dim, dimensions, periodic=collapsed_gather_nd(periodic, [dim, 0])) A[gridpoints_linear[lower_idx], lower_points] = stencil_lower.flatten()[lower_idx] A[gridpoints_linear, gridpoints_linear] = math.minimum(diagonal_entries, -1) # avoid 0, could lead to NaN return scipy.sparse.csc_matrix(A)