def generate_nodes(alpha, nsample, nodeitr): from rbf.pde.nodes import min_energy_nodes from rbf.pde.geometry import contains N = nsample * 2 # total number of nodes node_count = 0 itr = nodeitr vert = alpha.points smp = np.asarray(alpha.bounds, dtype=np.int64) while node_count < nsample: logger.info("Generating %i nodes (%i iterations)..." % (N, itr)) # create N quasi-uniformly distributed nodes out = min_energy_nodes(N, (vert, smp), iterations=itr) nodes = out[0] # remove nodes outside of the domain in_nodes = nodes[contains(nodes, vert, smp)] node_count = len(in_nodes) N = int(1.5 * N) logger.info("%i interior nodes generated (%i iterations)" % (node_count, itr)) xyz_coords = in_nodes.reshape(-1, 3) return xyz_coords
def test_contains_3d(self): vert, smp = sphere() pnt = np.random.normal(0.0, 2.0, (1000, 3)) out1 = geo.contains(pnt, vert, smp) dom = Domain(vert, smp) out2 = dom.contains(pnt) dom.build_rtree() out3 = dom.contains(pnt) self.assertTrue(np.all(out1 == out2)) self.assertTrue(np.all(out1 == out3))
def test_nodes(): from rbf.pde.nodes import min_energy_nodes from rbf.pde.geometry import contains from dentate.alphavol import alpha_shape from mayavi import mlab obs_u = np.linspace(-0.016 * np.pi, 1.01 * np.pi, 25) obs_v = np.linspace(-0.23 * np.pi, 1.425 * np.pi, 25) obs_l = np.linspace(-1.0, 1., num=10) u, v, l = np.meshgrid(obs_u, obs_v, obs_l, indexing='ij') xyz = DG_volume(u, v, l, rotate=[-35., 0., 0.]) print('Constructing volume...') vol = RBFVolume(obs_u, obs_v, obs_l, xyz, order=2) print('Constructing volume triangulation...') tri = vol.create_triangulation() print('Constructing alpha shape...') alpha = alpha_shape([], 120., tri=tri) # Define the problem domain vert = alpha.points smp = np.asarray(alpha.bounds, dtype=np.int64) N = 10000 # total number of nodes # create N quasi-uniformly distributed nodes print('Generating nodes...') rbf_logger = logging.Logger.manager.loggerDict['rbf.pde.nodes'] rbf_logger.setLevel(logging.DEBUG) out = min_energy_nodes(N, (vert, smp), iterations=10, build_rtree=True) nodes = out[0] # remove nodes outside of the domain in_nodes = nodes[contains(nodes, vert, smp)] print('Generated %d interior nodes' % len(in_nodes)) vol.mplot_surface(color=(0, 1, 0), opacity=0.33, ures=10, vres=10) mlab.points3d(*in_nodes.T, color=(1, 1, 0), scale_factor=15.0) mlab.show() return in_nodes, vol.inverse(in_nodes)
def gen_min_energy_nodes(count, domain, constraint, nodeiter, dispersion_delta, snap_delta): N = int(count * 2) # layer-specific number of nodes node_count = 0 while node_count < count: # create N quasi-uniformly distributed nodes def rho(x): return np.ones(x.shape[0]) #nodes = rejection_sampling(N, rho, (vert, smp), start=0) out = min_energy_nodes(N, domain, iterations=nodeiter, **{ 'dispersion_delta': dispersion_delta, 'snap_delta': snap_delta }) nodes = out[0] # remove nodes with nan nodes1 = nodes[~np.logical_or.reduce( (np.isnan(nodes[:, 0]), np.isnan(nodes[:, 1]), np.isnan(nodes[:, 2])))] # remove nodes outside of the domain vert, smp = domain in_nodes = nodes[contains(nodes1, vert, smp)] valid_idxs = None if constraint is not None: valid_idxs = [] current_xyz = in_nodes.reshape(-1, 3) for i in range(len(current_xyz)): if current_xyz[i][2] >= constraint[0] and current_xyz[i][ 2] <= constraint[1]: valid_idxs.append(i) in_nodes = in_nodes[valid_idxs] node_count = len(in_nodes) N = int(1.5 * N) logger.info("%i interior nodes out of %i nodes generated" % (node_count, len(nodes))) return in_nodes
# create the interpolation points xgrid, ygrid = np.meshgrid(np.linspace(0.0, 2.01, 100), np.linspace(0.0, 2.01, 100)) xy = np.array([xgrid.flatten(), ygrid.flatten()]).T # create an interpolation matrix that maps `u` to the displacements at `xy` I = weight_matrix(x=xy, p=nodes[groups['interior+boundary:all']], n=stencil_size, diffs=(0, 0), phi=phi, order=order) I = expand_cols(I, groups['interior+boundary:all'], n) # create a mask for points in `xy` that are outside of the domain is_outside = ~contains(xy, vert, smp) fig = plt.figure() # create the update function for the animation. this plots the solution at time # `time[index]` def update(index): fig.clear() ax = fig.add_subplot(111) u, v = soln.y[:, index].reshape((2, -1)) u_xy = I.dot(u) u_xy[is_outside] = np.nan u_xy = u_xy.reshape((100, 100))
A[groups['boundary:all']] = mq(nodes[groups['boundary:all']], nodes, eps=eps) # create "right hand side" vector d = np.empty(N) d[groups['interior']] = -1.0 # forcing term d[groups['boundary:all']] = 0.0 # boundary condition # Solve for the RBF coefficients coeff = np.linalg.solve(A, d) # interpolate the solution on a grid xg, yg = np.meshgrid(np.linspace(0.0, 2.02, 100), np.linspace(0.0, 2.02, 100)) points = np.array([xg.flatten(), yg.flatten()]).T u = mq(points, nodes, eps=eps).dot(coeff) # mask points outside of the domain u[~contains(points, vert, smp)] = np.nan # fold the solution into a grid ug = u.reshape((100, 100)) # make a contour plot of the solution fig, ax = plt.subplots() p = ax.contourf(xg, yg, ug, np.linspace(0.0, 0.16, 9), cmap='viridis') ax.plot(nodes[:, 0], nodes[:, 1], 'ko', markersize=4) for s in smp: ax.plot(vert[s, 0], vert[s, 1], 'k-', lw=2) ax.set_aspect('equal') ax.set_xlim(-0.05, 2.05) ax.set_ylim(-0.05, 2.05) fig.colorbar(p, ax=ax) fig.tight_layout() plt.savefig('../figures/basis.a.png')
def main(config, config_prefix, types_path, template_path, geometry_path, output_path, output_namespace, populations, resolution, alpha_radius, nodeiter, optiter, io_size, chunk_size, value_chunk_size, verbose): config_logging(verbose) logger = get_script_logger(script_name) comm = MPI.COMM_WORLD rank = comm.rank size = comm.size if io_size == -1: io_size = comm.size if rank == 0: logger.info('%i ranks have been allocated' % comm.size) if rank == 0: if not os.path.isfile(output_path): input_file = h5py.File(types_path, 'r') output_file = h5py.File(output_path, 'w') input_file.copy('/H5Types', output_file) input_file.close() output_file.close() comm.barrier() env = Env(comm=comm, config_file=config, config_prefix=config_prefix) random_seed = int(env.model_config['Random Seeds']['Soma Locations']) random.seed(random_seed) layer_extents = env.geometry['Parametric Surface']['Layer Extents'] rotate = env.geometry['Parametric Surface']['Rotation'] (extent_u, extent_v, extent_l) = get_total_extents(layer_extents) vol = make_volume(extent_u, extent_v, extent_l, rotate=rotate, resolution=resolution) layer_alpha_shapes = {} layer_alpha_shape_path = 'Layer Alpha Shape/%d/%d/%d' % resolution if rank == 0: for layer, extents in viewitems(layer_extents): gc.collect() has_layer_alpha_shape = False if geometry_path: this_layer_alpha_shape_path = '%s/%s' % ( layer_alpha_shape_path, layer) this_layer_alpha_shape = load_alpha_shape( geometry_path, this_layer_alpha_shape_path) layer_alpha_shapes[layer] = this_layer_alpha_shape if this_layer_alpha_shape is not None: has_layer_alpha_shape = True if not has_layer_alpha_shape: this_layer_alpha_shape = make_alpha_shape( extents[0], extents[1], alpha_radius=alpha_radius, rotate=rotate, resolution=resolution) layer_alpha_shapes[layer] = this_layer_alpha_shape if geometry_path: save_alpha_shape(geometry_path, this_layer_alpha_shape_path, this_layer_alpha_shape) population_ranges = read_population_ranges(output_path, comm)[0] if rank == 0: color = 1 else: color = 0 ## comm0 includes only rank 0 comm0 = comm.Split(color, 0) for population in populations: (population_start, population_count) = population_ranges[population] pop_layers = env.geometry['Cell Distribution'][population] pop_layer_count = 0 for layer, count in viewitems(pop_layers): pop_layer_count += count assert (population_count == pop_layer_count) if rank == 0: logger.info("Population %s: layer distribution is %s" % (population, str(pop_layers))) xyz_coords = None xyz_coords_interp = None uvl_coords_interp = None if rank == 0: xyz_coords_lst = [] xyz_coords_interp_lst = [] uvl_coords_interp_lst = [] for layer, count in viewitems(pop_layers): if count <= 0: continue alpha = layer_alpha_shapes[layer] vert = alpha.points smp = np.asarray(alpha.bounds, dtype=np.int64) N = int(count * 2) # layer-specific number of nodes node_count = 0 logger.info("Generating %i nodes..." % N) if verbose: rbf_logger = logging.Logger.manager.loggerDict[ 'rbf.pde.nodes'] rbf_logger.setLevel(logging.DEBUG) while node_count < count: # create N quasi-uniformly distributed nodes out = min_energy_nodes(N, (vert, smp), iterations=nodeiter) nodes = out[0] # remove nodes outside of the domain in_nodes = nodes[contains(nodes, vert, smp)] node_count = len(in_nodes) N = int(1.5 * N) logger.info("%i interior nodes out of %i nodes generated" % (node_count, len(nodes))) xyz_coords_lst.append(in_nodes.reshape(-1, 3)) xyz_coords = np.concatenate(xyz_coords_lst) logger.info("Inverse interpolation of %i nodes..." % len(xyz_coords)) uvl_coords_interp = vol.inverse(xyz_coords) xyz_coords_interp = vol(uvl_coords_interp[:, 0], uvl_coords_interp[:, 1], uvl_coords_interp[:, 2], mesh=False).reshape(3, -1).T logger.info("Broadcasting generated nodes...") xyz_coords = comm.bcast(xyz_coords, root=0) xyz_coords_interp = comm.bcast(xyz_coords_interp, root=0) uvl_coords_interp = comm.bcast(uvl_coords_interp, root=0) coords = [] coords_dict = {} xyz_error = np.asarray([0.0, 0.0, 0.0]) if rank == 0: logger.info("Computing UVL coordinates...") for i in range(0, xyz_coords.shape[0]): coord_ind = i if i % size == rank: if uvl_in_bounds(uvl_coords_interp[coord_ind, :], layer_extents, pop_layers): uvl_coords = uvl_coords_interp[coord_ind, :].ravel() xyz_coords1 = xyz_coords_interp[coord_ind, :].ravel() else: uvl_coords = None xyz_coords1 = None if uvl_coords is not None: xyz_error = np.add( xyz_error, np.abs( np.subtract(xyz_coords[coord_ind, :], xyz_coords1))) logger.info( 'Rank %i: cell %i: %f %f %f' % (rank, i, uvl_coords[0], uvl_coords[1], uvl_coords[2])) coords.append( (xyz_coords1[0], xyz_coords1[1], xyz_coords1[2], uvl_coords[0], uvl_coords[1], uvl_coords[2])) total_xyz_error = np.zeros((3, )) comm.Allreduce(xyz_error, total_xyz_error, op=MPI.SUM) coords_count = 0 coords_count = np.sum(np.asarray(comm.allgather(len(coords)))) if rank == 0: logger.info('Total %i coordinates generated' % coords_count) mean_xyz_error = np.asarray([(total_xyz_error[0] / coords_count), \ (total_xyz_error[1] / coords_count), \ (total_xyz_error[2] / coords_count)]) if rank == 0: logger.info( "mean XYZ error: %f %f %f " % (mean_xyz_error[0], mean_xyz_error[1], mean_xyz_error[2])) coords_lst = comm.gather(coords, root=0) if rank == 0: all_coords = [] for sublist in coords_lst: for item in sublist: all_coords.append(item) if coords_count < population_count: logger.warning("Generating additional %i coordinates " % (population_count - len(all_coords))) safety = 0.01 delta = population_count - len(all_coords) for i in range(delta): for layer, count in viewitems(pop_layers): if count > 0: min_extent = layer_extents[layer][0] max_extent = layer_extents[layer][1] coord_u = np.random.uniform( min_extent[0] + safety, max_extent[0] - safety) coord_v = np.random.uniform( min_extent[1] + safety, max_extent[1] - safety) coord_l = np.random.uniform( min_extent[2] + safety, max_extent[2] - safety) xyz_coords = DG_volume(coord_u, coord_v, coord_l, rotate=rotate).ravel() all_coords.append((xyz_coords[0],xyz_coords[1],xyz_coords[2],\ coord_u, coord_v, coord_l)) sampled_coords = random_subset(all_coords, int(population_count)) sampled_coords.sort( key=lambda coord: coord[3]) ## sort on U coordinate coords_dict = { population_start + i: { 'X Coordinate': np.asarray([x_coord], dtype=np.float32), 'Y Coordinate': np.asarray([y_coord], dtype=np.float32), 'Z Coordinate': np.asarray([z_coord], dtype=np.float32), 'U Coordinate': np.asarray([u_coord], dtype=np.float32), 'V Coordinate': np.asarray([v_coord], dtype=np.float32), 'L Coordinate': np.asarray([l_coord], dtype=np.float32) } for (i, (x_coord, y_coord, z_coord, u_coord, v_coord, l_coord)) in enumerate(sampled_coords) } append_cell_attributes(output_path, population, coords_dict, namespace=output_namespace, io_size=io_size, chunk_size=chunk_size, value_chunk_size=value_chunk_size, comm=comm0) comm.barrier() comm0.Free()
plt.show() quit() # plot the results fig, axs = plt.subplots(2, 2, figsize=(7, 7)) for i, t in enumerate(times[1:]): ax = axs.ravel()[i] xg, yg = np.mgrid[0.0:2.0:200j, 0:2.0:200j] points = np.array([xg.ravel(), yg.ravel()]).T # interpolate the solution onto a grid u = np.empty(N) u[idx['interior']], u[idx['boundary:all']] = soln[i], u_bnd ug = griddata(nodes, u, (xg, yg), method='linear') # mask the points outside of the domain ug.ravel()[~contains(points, vert, smp)] = np.nan # plot the boudary for s in smp: ax.plot(vert[s, 0], vert[s, 1], 'k-') ax.imshow(ug, extent=(0.0, 2.0, 0.0, 2.0), origin='lower', vmin=-0.2, vmax=0.2, cmap='seismic') ax.set_aspect('equal') ax.text(0.6, 0.85, 'time : %s\nnodes : %s' % (t, N), transform=ax.transAxes, fontsize=10)
fig, ax = plt.subplots() for smp in simplices: ax.plot(vertices[smp, 0], vertices[smp, 1], 'k-') for name, idx in groups.items(): ax.plot(nodes[idx, 0], nodes[idx, 1], '.', label=name) points_grid = np.mgrid[nodes[:, 0].min():nodes[:, 0].max():200j, nodes[:, 1].min():nodes[:, 1].max():200j, ] points_flat = points_grid.reshape(2, -1).T soln_interp_flat = KNearestRBFInterpolant(nodes, soln, phi=radial_basis_function, k=stencil_size, order=polynomial_order)(points_flat) soln_interp_flat[~contains(points_flat, vertices, simplices)] = np.nan soln_interp_grid = soln_interp_flat.reshape(points_grid.shape[1:]) p = ax.contourf(*points_grid, soln_interp_grid, cmap='jet') fig.colorbar(p) ax.legend(loc=2) ax.grid(ls=':') ax.set_xlim(-2.5, 2.5) ax.set_ylim(-2.5, 2.5) ax.set_aspect('equal') ax.set_title('Interpolated solution') fig.tight_layout() plt.savefig('../figures/fd.m.png') plt.show()