def von_karman_projected(): m = 20 n = 40 gradP = 100.0 inlet_v = 5.0 outlet_p = 0.0 G, (l, r, t, b) = gds.triangular_lattice(m, n, with_boundaries=True) # G, (l, r, t, b) = gds.square_lattice(m, n, with_boundaries=True) # G, (l, r, t, b) = gds.hexagonal_lattice(m, n, with_boundaries=True) # G = gds.triangular_cylinder(m, n) # G = gds.square_cylinder(m, n) # l, r = G.l_boundary, G.r_boundary j, k = 3, m // 2 # Introduce occlusion obstacle = [ (j, k), # (j+1, k), # (j+1, k+1), # (j+1, k-1), # (j-1, k+1), # (j, k+2), ] G.remove_nodes_from(obstacle) velocity, pressure = fluid_projected.navier_stokes(G, viscosity=0.0001) pressure.set_constraints(dirichlet=gds.combine_bcs( {n: gradP / 2 for n in l.nodes}, {n: -gradP / 2 for n in r.nodes})) # velocity.set_constraints(dirichlet=gds.combine_bcs( # {((0, i), (1, i)): inlet_v for i in range(1, m)}, # {((n//2, i), (n//2+1, i)): inlet_v for i in range(1, m)}, # {((n//2-1, 2*i+1), (n//2, 2*i+1)): inlet_v for i in range(0, m//2)}, # # gds.utils.bidict({e: 0 for e in obstacle_boundary}), # gds.utils.bidict({e: 0 for e in t.edges}), # gds.utils.bidict({e: 0 for e in b.edges}) # )) sys = gds.couple({ 'velocity': velocity, # 'divergence': velocity.project(gds.GraphDomain.nodes, lambda v: v.div()), 'vorticity': velocity.project(gds.GraphDomain.faces, lambda v: v.curl()), 'pressure': pressure, # 'tracer': lagrangian_tracer(velocity), # 'advective': velocity.project(gds.GraphDomain.edges, lambda v: -advector(v)), # 'L2': velocity.project(PointObservable, lambda v: np.sqrt(np.dot(v.y, v.y))), # 'dK/dt': velocity.project(PointObservable, lambda v: np.dot(v.y, v.leray_project(-advector(v)))), }) gds.render(sys, canvas=gds.grid_canvas(sys.observables.values(), 3), edge_max=0.6, dynamic_ranges=True, edge_colors=True, edge_palette=cc.bgy)
def render(): p1, v1 = sq_couette_ivp() # p1, v1 = tri_couette_ivp() # p1, v1 = hex_couette_ivp() # p1, v1 = sq_couette() # p2, v2 = tri_couette() # p3, v3 = hex_couette() sys = gds.couple({ 'velocity': v1, # 'velocity_tri': v2, # 'velocity_hex': v3, 'pressure': p1, # 'pressure_tri': p2, # 'pressure_hex': p3, 'vorticity': v1.project(gds.GraphDomain.faces, lambda v: v.curl()), # 'vorticity_tri': v2.project(gds.GraphDomain.faces, lambda v: v.curl()), # 'vorticity_hex': v3.project(gds.GraphDomain.faces, lambda v: v.curl()), # 'divergence_square': v1.project(gds.GraphDomain.nodes, lambda v: v.div()), 'kinetic energy': v1.project(PointObservable, lambda v: (v1.y ** 2).sum(), min_rng=0.1), 'momentum': v1.project(PointObservable, lambda v: np.abs(v1.y).sum(), min_rng=0.1), 'rotational energy': v1.project(PointObservable, lambda v: (v1.curl() ** 2).sum(), min_rng=0.1), 'angular momentum': v1.project(PointObservable, lambda v: np.abs(v1.curl()).sum(), min_rng=0.1), }) gds.render(sys, canvas=gds.grid_canvas(sys.observables.values(), 3), edge_max=0.6, dynamic_ranges=True, min_rng_size=1e-2)
def render_all(): G, dG = gds.square_lattice(14, 28, with_boundaries=True) v1, p1 = poiseuille(G, dG) G, dG = gds.triangular_lattice(14, 58, with_boundaries=True) v2, p2 = poiseuille(G, dG) G, dG = gds.hexagonal_lattice(14, 29, with_boundaries=True) v3, p3 = poiseuille(G, dG) G, dG = gds.voronoi_lattice(10, 100, with_boundaries=True, eps=0.07) v4, p4 = poiseuille(G, dG) sys = gds.couple({ 'velocity (sq)': v1, 'velocity (tri)': v2, 'velocity (hex)': v3, 'velocity (voronoi)': v4, 'pressure (sq)': p1, 'pressure (tri)': p2, 'pressure (hex)': p3, 'pressure (voronoi)': p4, 'vorticity (sq)': v1.project(gds.GraphDomain.faces, lambda v: v.curl()), 'vorticity (tri)': v2.project(gds.GraphDomain.faces, lambda v: v.curl()), 'vorticity (hex)': v3.project(gds.GraphDomain.faces, lambda v: v.curl()), 'vorticity (voronoi)': v4.project(gds.GraphDomain.faces, lambda v: v.curl()), }) gds.render(sys, canvas=gds.grid_canvas(sys.observables.values(), 4), edge_max=0.6, dynamic_ranges=True, plot_width=900, node_size=0.04)
def test_curl(): G1 = nx.Graph() G1.add_nodes_from([1, 2, 3, 4]) G1.add_edges_from([(1, 2), (2, 3), (3, 4), (4, 1)]) v1 = gds.edge_gds(G1) v1.set_evolution(nil=True) v1.set_initial(y0=lambda e: 1 if e == (1, 2) else 0) G2 = nx.Graph() G2.add_nodes_from([1, 2, 3, 4, 5, 6]) G2.add_edges_from([(1, 2), (2, 3), (3, 4), (4, 1), (1, 5), (5, 6), (6, 2)]) v2 = gds.edge_gds(G2) v2.set_evolution(nil=True) v2.set_initial(y0=lambda e: 1 if e == (1, 2) else 0) sys = gds.couple({ 'velocity1': v1, 'curl1': v1.project(gds.GraphDomain.faces, lambda v: v.curl()), 'curl*curl1': v1.project(gds.GraphDomain.edges, lambda v: v.curl_face.T @ v.curl_face @ v.y), 'velocity2': v2, 'curl2': v2.project(gds.GraphDomain.faces, lambda v: v.curl()), 'curl*curl2': v2.project(gds.GraphDomain.edges, lambda v: v.curl_face.T @ v.curl_face @ v.y) }) gds.render(sys, edge_max=0.5, canvas=gds.grid_canvas(sys.observables.values(), 3), dynamic_ranges=True)
def euler_vortex_street(): ''' Vortex street translation in the inviscid model. x-periodic hexagonal lattice. ''' # m, n = 4, 20 # G = gds.hexagonal_lattice(m, n) # speed = 1 # # G = gds.contract_pairs(G, [((0, j), (n, j)) for j in range(1, 2*m)]) # # G = gds.remove_pos(G) # velocity, pressure = fluid_projected.euler(G) # y0 = np.zeros(velocity.ndim) # for j in range(n-1): # if j == 5: # e = ((j, m), (j, m+1)) # y_e = np.zeros(velocity.ndim) # y_e[velocity.X[e]] = 1 # y_f = speed * velocity.curl_face@y_e # y_e = velocity.curl_face.T@y_f # y0 += y_e m, n = 3, 20 G = gds.square_lattice(m, n) speed = 1 velocity, pressure = fluid_projected.euler(G) y0 = np.zeros(velocity.ndim) for j in [m // 2]: i = 5 e = ((i, j), (i + 1, j)) y_e = np.zeros(velocity.ndim) y_e[velocity.X[e]] = 1 y_f = speed * velocity.curl_face @ y_e y0 += velocity.curl_face.T @ y_f velocity.set_initial(y0=lambda x: y0[velocity.X[x]]) velocity.advect() sys = gds.couple({ 'velocity': velocity, 'vorticity': velocity.project(gds.GraphDomain.faces, lambda v: v.curl()), 'advective': velocity.project(gds.GraphDomain.edges, lambda v: -v.advect()), 'pressure': pressure, # 'divergence': velocity.project(gds.GraphDomain.nodes, lambda v: v.div()), }) gds.render(sys, canvas=gds.grid_canvas(sys.observables.values(), 3), edge_max=0.6, dynamic_ranges=True, edge_colors=True, edge_palette=cc.bgy, n_spring_iters=2000)
def scalar_advection_kinds_test(): conc1, flow1 = advection_on_triangles(periodic=True) # conc1, flow1 = advection_on_circle() conc2, flow2 = advection_on_triangles(periodic=True, kind='lie') # conc2, flow2 = advection_on_circle() sys = gds.couple({ 'conc1': conc1, 'flow1': flow1, 'div1': flow1.project(GraphDomain.nodes, lambda v: v.div()), 'conc2': conc2, 'flow2': flow2, 'div2': flow2.project(GraphDomain.nodes, lambda v: v.div()), }) gds.render(sys, canvas=gds.grid_canvas(sys.observables.values(), 3), dynamic_ranges=True, node_size=.05, title='Advection of a Gaussian concentration')
def ns_cycle_test(): n = 30 G = gds.directed_cycle_graph(n) velocity = gds.edge_gds(G) mu = 0 # viscosity print(velocity.X.keys()) D = np.zeros((velocity.ndim, velocity.ndim)) L = -D.T @ D IV = np.zeros((velocity.ndim, velocity.ndim)) edge_pairs = zip( zip(chain([n - 2, n - 1], range(n - 2)), chain([n - 1], range(n - 1))), zip(chain([n - 1], range(n - 1)), range(n))) for idx, (e_i, e_j) in enumerate(edge_pairs): print(e_i, e_j) i, j = velocity.X[e_i], velocity.X[e_j] D[i, i] = -1 D[i, j] = 1 IV[j, idx] = 1 # print(D) # D = -velocity.incidence # Either incidence or dual derivative seems to work Dm = relu(-D) Dp = relu(D) F = Dm.T @ Dp - Dp.T @ Dm # pdb.set_trace() def dvdt(t, v): A = np.multiply(F.T, v).T + np.multiply(F, v) return -A @ v + mu * L @ v velocity.set_evolution(dydt=dvdt) bump = 2 * stats.norm().pdf(np.linspace(-4, 4, n)) # v0 = -IV @ bump # v0 = IV @ rotate(bump, 10) v0 = IV @ (bump - rotate(bump, n // 2)) velocity.set_initial(y0=lambda e: v0[velocity.X[e]]) sys = gds.couple({ 'velocity': velocity, # 'gradient': velocity.project(gds.GraphDomain.edges, lambda v: D @ v.y), # 'laplacian': velocity.project(gds.GraphDomain.edges, lambda v: -D.T @ D @ v.y), # 'dual': velocity.project(gds.GraphDomain.nodes, lambda v: v.y), # 'L1': velocity.project(PointObservable, lambda v: np.abs(v.y).sum()), # 'L2': velocity.project(PointObservable, lambda v: np.linalg.norm(v.y)), # 'min': velocity.project(PointObservable, lambda v: v.y.min()), }) gds.render(sys, canvas=gds.grid_canvas(sys.observables.values(), 3), edge_max=3, dynamic_ranges=False)
def render2(): viscosity, density = 1., 1e-2 p1, v1 = sq_couette_ivp(viscosity, density) p2, v2 = tri_couette_ivp(viscosity, density) p3, v3 = hex_couette_ivp(viscosity, density) sys = gds.couple({ 'velocity_sq': v1, 'velocity_tri': v2, 'velocity_hex': v3, 'flow_material_derivative_sq': v1.project(PointObservable, lambda v: np.abs(viscosity * v.laplacian() - p1.grad()).sum()), 'flow_material_derivative_tri': v2.project(PointObservable, lambda v: np.abs(viscosity * v.laplacian() - p2.grad()).sum()), 'flow_material_derivative_hex': v3.project(PointObservable, lambda v: np.abs(viscosity * v.laplacian() - p3.grad()).sum()), }) gds.render(sys, canvas=gds.grid_canvas(sys.observables.values(), 3), edge_max=0.6, dynamic_ranges=True, min_rng_size=1e-2)
def render(): # p, v = voronoi_poiseuille() p, v = sq_poiseuille() # p1, v1 = sq_poiseuille() # p2, v2 = tri_poiseuille() # p3, v3 = hex_poiseuille() # v = v3 sys = gds.couple({ 'velocity': v, # 'velocity_square': v1, # 'velocity_tri': v2, # 'velocity_hex': v3, 'pressure': p, # 'pressure_square': p1, # 'pressure_tri': p2, # 'pressure_hex': p3, 'vorticity': v.project(gds.GraphDomain.faces, lambda v: v.curl()), # 'vorticity_square': v1.project(gds.GraphDomain.faces, lambda v: v.curl()), # 'vorticity_tri': v2.project(gds.GraphDomain.faces, lambda v: v.curl()), # 'vorticity_hex': v3.project(gds.GraphDomain.faces, lambda v: v.curl()), # 'div_square': v1.project(gds.GraphDomain.nodes, lambda v: v.div()), # 'div_tri': v2.project(gds.GraphDomain.nodes, lambda v: v.div()), # 'div_hex': v3.project(gds.GraphDomain.nodes, lambda v: v.div()), # 'divergence': v.project(gds.GraphDomain.nodes, lambda v: v.div()), # 'laplacian_square': v1.project(gds.GraphDomain.edges, lambda v: v.laplacian()), # 'laplacian_tri': v2.project(gds.GraphDomain.edges, lambda v: v.laplacian()), # 'laplacian_hex': v3.project(gds.GraphDomain.edges, lambda v: v.laplacian()), # 'dd*': v.project(gds.GraphDomain.edges, lambda v: v.dd_()), # 'd*d': v.project(gds.GraphDomain.edges, lambda v: v.d_d()), 'energy': v.project(PointObservable, lambda v: (v.y**2).sum()), 'momentum': v.project(PointObservable, lambda v: np.abs(v.y).sum()), }) gds.render(sys, canvas=gds.grid_canvas(sys.observables.values(), 3), edge_max=0.6, dynamic_ranges=True, plot_width=900, node_size=0.04)
def show_leray(G, v: Callable = None, **kwargs): ''' Show Leray decomposition of a vector field. ''' if v is None: v = lambda x: np.random.uniform(1, 2) orig = gds.edge_gds(G) orig.set_evolution(nil=True) orig.set_initial(y0=v) div_free = orig.project(GraphDomain.edges, lambda u: u.leray_project()) curl_free = orig.project(GraphDomain.edges, lambda u: u.y - u.leray_project()) sys = gds.couple({ 'original': orig, 'original (div)': orig.project(GraphDomain.nodes, lambda u: u.div()), 'original (curl)': orig.project(GraphDomain.faces, lambda u: u.curl()), 'div-free': div_free, 'div-free (div)': div_free.project( GraphDomain.nodes, lambda u: orig.div(u.y)), # TODO: chaining projections? 'div-free (curl)': div_free.project(GraphDomain.faces, lambda u: orig.curl(u.y)), 'curl-free': curl_free, 'curl-free (div)': curl_free.project(GraphDomain.nodes, lambda u: orig.div(u.y)), 'curl-free (curl)': curl_free.project(GraphDomain.faces, lambda u: orig.curl(u.y)), }) gds.render(sys, n_spring_iters=1000, canvas=gds.grid_canvas(sys.observables.values(), 3), title='Leray decomposition', min_rng_size=1e-3, **kwargs)
def plot_beltrami(): if not os.path.exists(save_path): raise Exception('no data') sys = dict() fig_N, fig_M = 0, 0 with open(save_path, 'rb') as f: data = cloudpickle.load(f) fig_N, fig_M = len(data), len(data[next(iter(data))]) for N, subdata in sorted(data.items(), key=lambda x: x[0]): for i in subdata: print((N, i)) u = subdata[i] G = gds.triangular_lattice(m=1, n=N) flow = gds.edge_gds(G) flow.set_evolution(nil=True) flow.set_initial(y0=lambda x: u[flow.X[x]]) sys[f'{N}_{i}'] = flow sys = gds.couple(sys) canvas = gds.grid_canvas(sys.observables.values(), fig_M) gds.render(sys, canvas=canvas, edge_max=0.6, dynamic_ranges=True)
def render_edge_diffusion(v): sys = gds.couple({ 'velocity': v, 'divergence': v.project(gds.GraphDomain.nodes, lambda v: v.div()), 'curl': v.project(gds.GraphDomain.faces, lambda v: v.curl()), 'd*d': v.project(gds.GraphDomain.edges, lambda v: -v.curl_face.T @ v.curl_face @ v.y), 'dd*': v.project(gds.GraphDomain.edges, lambda v: v.dirichlet_laplacian @ v.y), 'L1': v.project(gds.GraphDomain.edges, lambda v: v.laplacian()), }) gds.render(sys, edge_max=0.6, dynamic_ranges=True, canvas=gds.grid_canvas(sys.observables.values(), 3))
def render1(): viscosity, density = 1., 1e-2 p, v = sq_couette_ivp(viscosity, density) # p, v = tri_couette_ivp(viscosity, density) # p, v = hex_couette_ivp(viscosity, density) # components = dict() # for (name, G) in p.G.lattice_components.items(): # components[name] = v.project(G, lambda v: v) # components[f'{name}_energy'] = components[name].project(PointObservable, lambda v: (v.y ** 2).sum(), min_rng=0.1) # components[f'{name}_momentum'] = components[name].project(PointObservable, lambda v: v.y.sum(), min_rng=0.1) sys = gds.couple({ 'velocity': v, 'pressure': p, 'vorticity': v.project(GraphDomain.faces, lambda v: v.curl()), 'mass flux': v.project(GraphDomain.edges, lambda v: viscosity * v.laplacian() - p.grad()), 'total mass flux': v.project(PointObservable, lambda v: np.abs(viscosity * v.laplacian() - p.grad()).sum()), 'divergence': v.project(GraphDomain.nodes, lambda v: v.div()), }) gds.render(sys, canvas=gds.grid_canvas(sys.observables.values(), 3), edge_max=0.6, dynamic_ranges=True, min_rng_size=1e-2)
def edge_diffusion_comp(): v1 = square_edge_diffusion() v2 = tri_edge_diffusion() v3 = hex_edge_diffusion() sys = gds.couple({ 'flow_square': v1, 'flow_tri': v2, 'flow_hex': v3, 'curl_square': v1.project(gds.GraphDomain.faces, lambda v: v.curl()), 'curl_tri': v2.project(gds.GraphDomain.faces, lambda v: v.curl()), 'curl_hex': v3.project(gds.GraphDomain.faces, lambda v: v.curl()), }) gds.render(sys, canvas=gds.grid_canvas(sys.observables.values(), 3), edge_max=0.6, dynamic_ranges=True)
def fluid_test(velocity, pressure=None, columns=3, **kwargs): if hasattr(velocity, 'advector'): advector = velocity.advector # TODO: hacky else: advector = lambda v: v.advect() freqs, spec_fun = edge_power_spectrum(velocity.G) obs = { 'velocity': velocity, 'divergence': velocity.project(gds.GraphDomain.nodes, lambda v: v.div()), # 'vorticity': velocity.project(gds.GraphDomain.faces, lambda v: v.curl()), # 'diffusion': velocity.project(gds.GraphDomain.edges, lambda v: v.laplacian()), # 'tracer': lagrangian_tracer(velocity), # 'advective': velocity.project(gds.GraphDomain.edges, lambda v: -advector(v)), # 'leray projection': velocity.project(gds.GraphDomain.edges, lambda v: v.leray_project()), 'L1': velocity.project(PointObservable, lambda v: np.abs(v.y).sum()), 'power spectrum': velocity.project(VectorObservable, lambda v: spec_fun(v.y), freqs.tolist()), # 'power L2': velocity.project(PointObservable, lambda v: np.sqrt(spec_fun(v.y).sum())), 'L2': velocity.project(PointObservable, lambda v: np.sqrt(np.dot(v.y, v.y))), # 'dK/dt': velocity.project(PointObservable, lambda v: np.dot(v.y, -advector(v))), # 'dK/dt': velocity.project(PointObservable, lambda v: np.dot(v.y, -advector(velocity) - pressure.grad())), } if pressure != None: obs['pressure'] = pressure # obs['pressure_grad'] = pressure.project(gds.GraphDomain.edges, lambda p: -p.grad()) sys = gds.couple(obs) gds.render(sys, canvas=gds.grid_canvas(sys.observables.values(), columns), edge_max=0.6, dynamic_ranges=True, **kwargs)
def von_karman(): m = 20 n = 50 gradP = 80.0 inlet_v = 20.0 outlet_p = 0.0 G, (l, r, t, b) = gds.triangular_lattice(m, n, with_boundaries=True) tb = set(t.nodes()) | set(b.nodes()) lr = set(l.nodes()) | set(r.nodes()) v_free = lr - tb e_free = set(gds.edge_domain(G, lr)) e_normal = set(nx.edge_boundary(G, lr)) j, k = 8, m // 2 # Introduce occlusion obstacle = [ (j, k), (j + 1, k), (j + 2, k), # (j, k+1), # (j, k-1), # (j-1, k), # (j+1, k+1), # (j+1, k-1), # (j, k+2), # (j, k-2), ] obstacle_boundary = gds.utils.flatten([G.neighbors(n) for n in obstacle]) obstacle_boundary = gds.edge_domain(G, obstacle_boundary) G.remove_nodes_from(obstacle) # G.remove_edges_from(list(nx.edge_boundary(G, l, l))) # G.remove_edges_from(list(nx.edge_boundary(G, [(0, 2*i+1) for i in range(m//2)], [(1, 2*i) for i in range(m//2+1)]))) # G.remove_edges_from(list(nx.edge_boundary(G, r, r))) # G.remove_edges_from(list(nx.edge_boundary(G, [(n//2, 2*i+1) for i in range(m//2)], [(n//2, 2*i) for i in range(m//2+1)]))) velocity, pressure = fluid.navier_stokes(G, viscosity=10, v_free=v_free, e_free=e_free, e_normal=e_normal) pressure.set_constraints(dirichlet=gds.combine_bcs( {n: gradP / 2 for n in l.nodes}, {n: -gradP / 2 for n in r.nodes} # {n: 0 for n in l.nodes} # {(n//2+1, j): outlet_p for j in range(n)} )) gradation = np.linspace(-0.1, 0.1, m + 1) velocity.set_constraints(dirichlet=gds.combine_bcs( # {((0, i), (1, i)): inlet_v + gradation[i] for i in range(1, m)}, # {((n//2, i), (n//2+1, i)): inlet_v - gradation[i] for i in range(1, m)}, # {((n//2-1, 2*i+1), (n//2, 2*i+1)): inlet_v - gradation[2*i+1] for i in range(0, m//2)}, {e: 0 for e in obstacle_boundary}, gds.zero_edge_bc(t), gds.zero_edge_bc(b), )) sys = gds.couple({ 'velocity': velocity, # 'divergence': velocity.project(gds.GraphDomain.nodes, lambda v: v.div()), # 'vorticity': velocity.project(gds.GraphDomain.faces, lambda v: v.curl()), 'pressure': pressure, }) gds.render(sys, canvas=gds.grid_canvas(sys.observables.values(), 3), edge_max=0.6, dynamic_ranges=True, edge_palette=cc.bgy)