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 square_edge_diffusion(): m, n = 10, 10 G, (l, r, t, b) = gds.square_lattice(n, m, with_boundaries=True) faces, outer_face = gds.embedded_faces(G) for j in range(m): G.add_edge((n - 1, j), (0, j)) aux_faces = [((n - 1, j), (0, j), (0, j + 1), (n - 1, j + 1)) for j in range(m - 1)] G.faces = faces + aux_faces # Hacky G.rendered_faces = np.array(range(len(faces)), dtype=np.intp) # Hacky v = gds.edge_gds(G) v.set_evolution(dydt=lambda t, y: v.laplacian(y)) velocity = 1.0 def boundary(e): if e in b.edges: return velocity elif e == ((0, 0), (m - 1, 0)): return -velocity elif e in t.edges or e == ((0, n - 1), (m - 1, n - 1)): return 0.0 return None v.set_constraints(dirichlet=boundary) return v
def grid_tv_boundary(): G = gds.square_lattice(10, 10) temperature = gds.node_gds(G) temperature.set_evolution(dydt=lambda t, y: temperature.laplacian()) temperature.set_constraints(dirichlet=gds.combine_bcs( lambda x: 0 if x[0] == 9 else None, lambda t, x: np.sin(t + x[1] / 4)**2 if x[0] == 0 else None)) gds.render(temperature, title='Heat equation with time-varying boundary')
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 fluid_on_grid(): G = gds.square_lattice(10, 10) i, o = (3, 3), (6, 6) dG = nx.Graph() dG.add_nodes_from([i, o]) velocity, pressure = navier_stokes(G, dG) pressure.set_constraints(dirichlet={i: 10.0, o: -10.0}) tracer = lagrangian_tracer(velocity, [i]) return velocity, pressure, tracer
def heat_grid(n=10, steady_state=False) -> gds.node_gds: G = gds.square_lattice(n, n) temp = gds.node_gds(G) if steady_state: ''' Steady-state version (for comparison) ''' temp.set_evolution(cost=lambda t, y: temp.laplacian(y)) else: temp.set_evolution(dydt=lambda t, y: temp.laplacian(y)) return temp
def advection_on_grid(): n = 5 G = gds.square_lattice(n, n) def v_field(e): if e[1][0] >= e[0][0] and e[1][1] >= e[0][1]: return 1 else: return -1 conc, flow = advection(G, v_field) conc.set_initial(y0 = lambda x: 1.0 if x == (0, 0) else 0.) # delta initial condition return conc, flow
def sq_poiseuille(): m = 14 n = 28 gradP = 6.0 G, (l, r, t, b) = gds.square_lattice(m, n, with_boundaries=True) v_free_l = set(l.nodes()) - (set(t.nodes()) | set(b.nodes())) v_free_r = set(r.nodes()) - (set(t.nodes()) | set(b.nodes())) v_free = v_free_l | v_free_r pressure, velocity = navier_stokes(G, viscosity=1., density=1e-2, v_free=v_free) e_free = np.array([velocity.X[(n, (n[0] + 1, n[1]))] for n in v_free_l] + [velocity.X[((n[0] - 1, n[1]), n)] for n in v_free_r], dtype=np.intp) e_free_mask = np.ones(velocity.ndim) e_free_mask[e_free] = 0 pressure, velocity = navier_stokes(G, viscosity=1., density=1e-2, v_free=v_free) pressure.set_constraints(dirichlet=gds.combine_bcs( {n: gradP / 2 for n in l.nodes}, {(n[0] + 1, n[1]): gradP / 2 for n in l.nodes}, {n: -gradP / 2 for n in r.nodes}, {(n[0] - 1, n[1]): -gradP / 2 for n in r.nodes}, )) local_state = {'t': None, 'div': None} def free_boundaries(t, e): if local_state['t'] != t: local_state['div'] = velocity.div(velocity.y * e_free_mask) if e[0][1] == e[1][1] and e[0][0] + 1 == e[1][0]: if e[0] in v_free: return local_state['div'][pressure.X[e[1]]] elif e[1] in v_free: return -local_state['div'][pressure.X[e[0]]] velocity.set_constraints(dirichlet=gds.combine_bcs(gds.zero_edge_bc( t), gds.zero_edge_bc(b), free_boundaries)) return pressure, velocity
def poiseuille(): m, n = 8, 10 G = gds.square_lattice(n, m) velocity, pressure = fluid_projected.navier_stokes(G) def pressure_values(x): if x[0] == 0: return 0.2 if x[0] == n-1: return -0.2 return None pressure.set_constraints(dirichlet=pressure_values) def no_slip(x): if x[0][1] == x[1][1] == 0 or x[0][1] == x[1][1] == m-1: return 0. return None velocity.set_constraints(dirichlet=no_slip) return velocity, pressure
def sq_poiseuille_projected(viscosity, density): m=14 n=28 gradP=6.0 G, (l, r, t, b) = gds.square_lattice(m, n, with_boundaries=True) v_free_l = set(l.nodes()) - (set(t.nodes()) | set(b.nodes())) v_free_r = set(r.nodes()) - (set(t.nodes()) | set(b.nodes())) v_free = v_free_l | v_free_r velocity = navier_stokes_projected(G, viscosity=viscosity, density=density, body_force=lambda t, y: gradP*np.ones_like(y), v_free=v_free) velocity.set_constraints(dirichlet=gds.combine_bcs( gds.zero_edge_bc(t), gds.zero_edge_bc(b), )) return velocity
def sq_lid_driven_cavity_ivp(): m = 18 n = 21 v = 1.0 G, (l, r, t, b) = gds.square_lattice(m, n, with_boundaries=True) velocity, pressure = navier_stokes(G, viscosity=200., density=0.1) def walls(e): if e in t.edges(): return v elif e in b.edges(): return -v elif e in r.edges(): return -v elif (e[1], e[0]) in r.edges(): return v elif e in l.edges(): return v elif (e[1], e[0]) in l.edges(): return -v return 0 velocity.set_initial(y0=walls) pressure.set_constraints(dirichlet={(0, 0): 0.}) # Pressure reference return velocity, pressure
def poiseuille_flow(): ''' API example ''' G, (G_L, G_R, G_T, G_B) = gds.square_lattice(m, n, with_boundaries=True) velocity = Field(GraphDomain.Edges, G) velocity.set_dirichlet_boundary(set(G_T.edges()) | set(G_B.edges()), 0.) velocity.set_free_boundary(set(G_L.edges()) | set(G_R.edges())) pressure = Field(GraphDomain.Nodes, G) pressure.set_dirichlet_boundary(set(G_L.edges()), 1.) pressure.set_dirichlet_boundary(set(G_R.edges()), -1.) pressure.set_free_boundary(set(G_T.edges()) | set(G_B.edges())) dt = 1e-3 velocity.set_evolution(dydt=-advect(velocity, velocity) - grad(pressure) / density + laplacian(velocity) * viscosity / density) pressure.set_evolution( lhs=div(velocity / dt - advect(velocity, velocity)) - laplacian(pressure) / density + laplacian(div(velocity)) * viscosity / density)
def sq_couette(): m, n = 11, 10 G, (l, r, t, b) = gds.square_lattice(m, n, with_boundaries=True) faces, outer_face = gds.embedded_faces(G) for j in range(m): G.add_edge((n-1, j), (0, j)) aux_faces = [((n-1, j), (0, j), (0, j+1), (n-1, j+1)) for j in range(m-1)] G.faces = faces + aux_faces # Hacky G.rendered_faces = np.array(range(len(faces)), dtype=np.intp) # Hacky pressure, velocity = navier_stokes(G, viscosity=1., density=1e-2) vel = 1.0 def walls(e): if e in t.edges or e == ((0, m-1), (n-1, m-1)): return 0 elif e in b.edges: return vel elif e == ((0, 0), (n-1, 0)): return -vel return None velocity.set_constraints(dirichlet=walls) return pressure, velocity
def sq_couette_ivp(viscosity, density): m, n = 11, 10 G, (l, r, t, b) = gds.square_lattice(m, n, with_boundaries=True, with_lattice_components=True) faces, outer_face = gds.embedded_faces(G) for j in range(m): G.add_edge((n-1, j), (0, j)) # for i in range(n): # G.add_edge((i, 0), (i, m-1)) aux_faces = [((n-1, j), (0, j), (0, j+1), (n-1, j+1)) for j in range(m-1)] # aux_faces += [((i, 0), (i, m-1), (i+1, m-1), (i+1, 0)) for i in range(n-1)] G.faces = faces + aux_faces # Hacky G.rendered_faces = np.array(range(len(faces)), dtype=np.intp) # Hacky pressure, velocity = navier_stokes(G, viscosity=viscosity, density=density) vel = 1.0 def walls(e): if e[0][1] == e[1][1] == m//2: if e[0][0] == 0 and e[1][0] == n-1: return -vel return vel return 0 velocity.set_initial(y0=walls) return pressure, velocity
'diffusion_tri': v2.project(gds.GraphDomain.edges, lambda v: v.laplacian()), 'diffusion_hex': v3.project(gds.GraphDomain.edges, lambda v: v.laplacian()), 'advection_square': v1.project(gds.GraphDomain.edges, lambda v: -v.advect()), 'advection_tri': v2.project(gds.GraphDomain.edges, lambda v: -v.advect()), 'advection_hex': v3.project(gds.GraphDomain.edges, lambda v: -v.advect()), 'divergence_square': v1.project(gds.GraphDomain.nodes, lambda v: v.div()), 'divergence_tri': v2.project(gds.GraphDomain.nodes, lambda v: v.div()), 'divergence_hex': v3.project(gds.GraphDomain.nodes, lambda v: v.div()), }) sys.solve_to_disk(5.0, 0.01, 'lid_driven_cavity') if __name__ == '__main__': # render() # G, dG = gds.triangular_lattice(18, 42, with_boundaries=True) G, dG = gds.square_lattice(16, 30, with_boundaries=True) # G, dG = gds.hexagonal_lattice(18, 21, with_boundaries=True) v, p = lid_driven_cavity(G, dG, viscosity=200) fluid_test(v, p, columns=3, edge_palette=cc.bgy)