def backward_step(): ''' Poiseuille flow with a boundary asymmetry ''' m = 22 n = 67 step_height = 12 step_width = 10 obstacle = gds.utils.flatten([[(j, i) for i in range(step_height)] for j in range(step_width)]) G, (l, r, t, b) = gds.triangular_lattice(m, n, with_boundaries=True) for g in [G, l, r, t, b]: g.remove_nodes_from(obstacle) for i in range(step_width + 1): b.add_node((i, step_height)) if i > 0: b.add_edge((i - 1, step_height), (i, step_height)) for j in range(step_height + 1): b.add_node((step_width, j)) if i > 0: b.add_edge((step_width, j - 1), (step_width, j)) 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)]))) weight = 1. nx.set_edge_attributes(G, weight, name='w') inlet_v = 1.0 # outlet_v=2*(m - step_height - 2)*inlet_v / (m - 2) outlet_p = 0.0 # ref_p=0.0 # grad_p=100.0 velocity, pressure = navier_stokes(G, viscosity=100., density=1.0, inlets=l.nodes, outlets=r.nodes, w_key='w') pressure.set_constraints(dirichlet=gds.combine_bcs( # {n: grad_p/2 for n in l.nodes}, # {n: -grad_p/2 for n in r.nodes if n[1] > step_height//2} {(n // 2 + 1, j): outlet_p for j in range(n)} # {(n//2+1,m): ref_p} )) velocity.set_constraints(dirichlet=gds.combine_bcs( {((0, i), (1, i)): inlet_v for i in range(step_height + 1, m)}, # {((n//2, i), (n//2+1, i)): outlet_v for i in range(1, m)}, # {((n//2-1, 2*i+1), (n//2, 2*i+1)): outlet_v for i in range(0, m//2)}, gds.zero_edge_bc(t), gds.zero_edge_bc(b), )) return velocity, pressure
def voronoi_poiseuille(): np.random.seed(401) gradP = 1.0 n_boundary = 10 n_interior = 100 G, (l, r, t, b) = gds.voronoi_lattice(n_boundary, n_interior, with_boundaries=True, eps=0.07) # tb = set(t.nodes()) | set(b.nodes()) v_free_l, v_free_r = set(l.nodes()), set(r.nodes()) v_free = v_free_l | v_free_r v_bd_l = set() # for v in v_free_l: # u = v - 1j # G.add_node(u) # G.add_edge(u, v) # G.nodes[u]['pos'] = (G.nodes[v]['pos'][0] - 0.1, G.nodes[v]['pos'][1]) # v_bd_l.add(u) v_bd_r = set() # for v in v_free_r: # u = v - 1j # G.add_node(u) # G.add_edge(v, u) # G.nodes[u]['pos'] = (G.nodes[v]['pos'][0] + 0.1, G.nodes[v]['pos'][1]) # v_bd_r.add(u) v_bd = v_bd_l | v_bd_r pressure, velocity = navier_stokes(G, viscosity=1., density=1e-2, v_free=v_bd | v_free) pressure.set_constraints(dirichlet=gds.combine_bcs( {n: gradP / 2 for n in v_free_l | v_bd_l}, {n: -gradP / 2 for n in v_free_r | v_bd_r}, )) # e_free_mask = np.array([1 if len(set(velocity.iX[i]) - v_bd)==2 else 0 for i in range(velocity.ndim)]) # 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) # local_state['t'] = t # if e[1] in v_bd_l: # return -np.clip(local_state['div'][pressure.X[e[0]]], 0, None) # elif e[1] in v_bd_r: # return -np.clip(local_state['div'][pressure.X[e[0]]], None, 0) velocity.set_constraints(dirichlet=gds.combine_bcs( # free_boundaries, gds.zero_edge_bc(t), gds.zero_edge_bc(b), )) return pressure, velocity
def lid_driven_cavity(G, dG, v=10, viscosity=10): (l, r, t, b) = dG v_free = (set(l.nodes()) & set(t.nodes())) | (set(r.nodes()) & set(t.nodes())) print('v_free:', v_free) velocity, pressure = navier_stokes(G, viscosity=viscosity, v_free=v_free) velocity.set_constraints(dirichlet=gds.combine_bcs( gds.const_edge_bc(t, v), gds.zero_edge_bc(b), gds.zero_edge_bc(l), gds.zero_edge_bc(r), )) # pressure.set_constraints(dirichlet={(0, 0): 0.}) # Pressure reference return velocity, pressure
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 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 tri_poiseuille(): m = 14 n = 58 gradP = 1.0 G, (l, r, t, b) = gds.triangular_lattice(m, n, with_boundaries=True) # G.remove_edges_from(l.edges()) # G.remove_edges_from(r.edges()) # G.remove_edges_from(G.subgraph([(0, 2*i+1) for i in range(m//2)] + [(1, 2*i) for i in range(m//2+1)]).edges()) # G.remove_edges_from(G.subgraph([(n//2-1, 2*i+1) for i in range(m//2)] + [(n//2, 2*i) for i in range(m//2+1)]).edges()) v_free_l = set(l.nodes()) - (set(t.nodes()) | set(b.nodes())) # v_free_l_int = set((n[0]+1, n[1]) for n in v_free_l) v_free_r = set(r.nodes()) - (set(t.nodes()) | set(b.nodes())) # v_free_r_int = set((n[0]-1, n[1]) for n in v_free_r) 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.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(G, dG, viscosity=50, density=1, gradP=10): (l, r, t, b) = dG 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)) velocity, pressure = navier_stokes(G, viscosity=viscosity, density=density, 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}, )) velocity.set_constraints(dirichlet=gds.combine_bcs( gds.zero_edge_bc(t), gds.zero_edge_bc(b), )) return velocity, pressure
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)
def hex_poiseuille(): m = 14 n = 29 gradP = 1.0 G, (l, r, t, b) = gds.hexagonal_lattice(m, n, with_boundaries=True) v_free_l = set(l.nodes()) - (set(t.nodes()) | set(b.nodes())) # v_free_l.remove(min(v_free_l, key=lambda x: x[1])) # v_free_l.remove(max(v_free_l, key=lambda x: x[1])) v_free_r = set(r.nodes()) - (set(t.nodes()) | set(b.nodes())) # v_free_r.remove(min(v_free_r, key=lambda x: x[1])) # v_free_r.remove(max(v_free_r, key=lambda x: x[1])) v_free = v_free_l | v_free_r v_bd_l = set() for v in v_free_l: u = (-1, v[1]) G.add_node(u) G.add_edge(u, v) G.nodes[u]['pos'] = (G.nodes[v]['pos'][0] - 1.0, G.nodes[v]['pos'][1]) v_bd_l.add(u) v_bd_r = set() for v in v_free_r: u = (n + 1, v[1]) G.add_node(u) G.add_edge(v, u) G.nodes[u]['pos'] = (G.nodes[v]['pos'][0] + 1.0, G.nodes[v]['pos'][1]) v_bd_r.add(u) v_bd = v_bd_l | v_bd_r pressure, velocity = navier_stokes(G, viscosity=1., density=1e-2, v_free=v_bd | v_free) e_free_mask = np.array([ 1 if len(set(velocity.iX[i]) - v_bd) == 2 else 0 for i in range(velocity.ndim) ]) pressure.set_constraints(dirichlet=gds.combine_bcs( {n: gradP / 2 for n in v_free_l | v_bd_l}, {n: -gradP / 2 for n in v_free_r | v_bd_r}, )) 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) local_state['t'] = t if e[1] in v_bd_l: return -local_state['div'][pressure.X[e[0]]] elif e[1] in v_bd_r: return -local_state['div'][pressure.X[e[0]]] # elif (e[0][1] == e[1][1] == 0) and (e[0][0] == e[1][0] - 1): # return 0 # elif (e[0][1] == e[1][1] == n) and (e[0][0] == e[1][0] - 1): # return 0 velocity.set_constraints(dirichlet=gds.combine_bcs( free_boundaries, gds.zero_edge_bc(t), gds.zero_edge_bc(b), )) return pressure, velocity