def __init__(self, refine=1, degree=3, nel=None): if nel is None: nel = int(10 * refine) xpts = np.linspace(0, 2, 2 * nel + 1) ypts = np.linspace(0, 1, nel + 1) domain, geom = mesh.rectilinear([xpts, ypts]) NutilsCase.__init__(self, 'Channel flow', domain, geom, geom) bases = [ domain.basis('spline', degree=(degree, degree - 1)), # vx domain.basis('spline', degree=(degree - 1, degree)), # vy domain.basis('spline', degree=degree - 1), # pressure [0] * 2, # stabilization terms ] basis_lens = [len(b) for b in bases] vxbasis, vybasis, pbasis, __ = fn.chain(bases) vbasis = vxbasis[:, _] * (1, 0) + vybasis[:, _] * (0, 1) self.bases.add('v', vbasis, length=sum(basis_lens[:2])) self.bases.add('p', pbasis, length=basis_lens[2]) self.extra_dofs = 2 self.constrain('v', 'left', 'top', 'bottom') x, y = geom profile = (y * (1 - y))[_] * (1, 0) self.integrals['lift'] = Affine(1, self.project_lift(profile, 'v')) self.integrals['geometry'] = Affine(1, geom) self._exact_solutions = {'v': profile, 'p': 4 - 2 * x} self.integrals['divergence'] = AffineIntegral( -1, fn.outer(vbasis.div(geom), pbasis)) self.integrals['laplacian'] = AffineIntegral( 1, fn.outer(vbasis.grad(geom)).sum((-1, -2))) self.integrals['v-h1s'] = AffineIntegral( 1, fn.outer(vbasis.grad(geom)).sum([-1, -2])) self.integrals['p-l2'] = AffineIntegral(1, fn.outer(pbasis)) self.integrals['convection'] = AffineIntegral( 1, NutilsDelayedIntegrand('w_ia u_jb v_ka,b', 'ijk', 'wuv', x=geom, w=vbasis, u=vbasis, v=vbasis)) points = [(0, (0, 0)), (nel - 1, (0, 1))] eqn = (vbasis.laplace(geom) - pbasis.grad(geom))[:, 0, _] self.integrals['stab-lhs'] = AffineIntegral( 1, collocate(domain, eqn, points, self.ndofs - self.extra_dofs, self.ndofs))
def __init__(self, refine=1, degree=3, nel_up=None, nel_length=None, stabilize=True): if nel_up is None: nel_up = int(10 * refine) if nel_length is None: nel_length = int(100 * refine) domain, geom = mesh.multipatch( patches=[[[0, 1], [3, 4]], [[3, 4], [6, 7]], [[2, 3], [5, 6]]], nelems={ (0, 1): nel_up, (3, 4): nel_up, (6, 7): nel_up, (2, 5): nel_length, (3, 6): nel_length, (4, 7): nel_length, (0, 3): nel_up, (1, 4): nel_up, (2, 3): nel_up, (5, 6): nel_up, }, patchverts=[[-1, 0], [-1, 1], [0, -1], [0, 0], [0, 1], [1, -1], [1, 0], [1, 1]], ) NutilsCase.__init__(self, 'Backward-facing step channel', domain, geom, geom) NU = 1 / self.parameters.add('viscosity', 20, 50) L = self.parameters.add('length', 9, 12, 10) H = self.parameters.add('height', 0.3, 2, 1) V = self.parameters.add('velocity', 0.5, 1.2, 1) # Bases bases = [ domain.basis('spline', degree=(degree, degree - 1)), # vx domain.basis('spline', degree=(degree - 1, degree)), # vy domain.basis('spline', degree=degree - 1), # pressure ] if stabilize: bases.append([0] * 4) basis_lens = [len(b) for b in bases] vxbasis, vybasis, pbasis, *__ = fn.chain(bases) vbasis = vxbasis[:, _] * (1, 0) + vybasis[:, _] * (0, 1) self.bases.add('v', vbasis, length=sum(basis_lens[:2])) self.bases.add('p', pbasis, length=basis_lens[2]) self.extra_dofs = 4 if stabilize else 0 x, y = geom hx = fn.piecewise(x, (0, ), 0, x) hy = fn.piecewise(y, (0, ), y, 0) self.integrals['geometry'] = Affine( 1.0, geom, (L - 1), fn.asarray((hx, 0)), (H - 1), fn.asarray((0, hy)), ) self.constrain('v', 'patch0-bottom', 'patch0-top', 'patch0-left', 'patch1-top', 'patch2-bottom', 'patch2-left') vgrad = vbasis.grad(geom) # Lifting function profile = fn.max(0, y * (1 - y) * 4)[_] * (1, 0) self.integrals['lift'] = Affine(V, self.project_lift(profile, 'v')) # Characteristic functions cp0, cp1, cp2 = [characteristic(domain, (i, )) for i in range(3)] cp12 = cp1 + cp2 # Stokes divergence term self.integrals['divergence'] = AffineIntegral( -(H - 1), fn.outer(vgrad[:, 0, 0], pbasis) * cp2, -(L - 1), fn.outer(vgrad[:, 1, 1], pbasis) * cp12, -1, fn.outer(vbasis.div(geom), pbasis), ) # Stokes laplacian term self.integrals['laplacian'] = AffineIntegral( NU, fn.outer(vgrad).sum([-1, -2]) * cp0, NU / L, fn.outer(vgrad[:, :, 0]).sum(-1) * cp1, NU * L, fn.outer(vgrad[:, :, 1]).sum(-1) * cp1, NU * H / L, fn.outer(vgrad[:, :, 0]).sum(-1) * cp2, NU * L / H, fn.outer(vgrad[:, :, 1]).sum(-1) * cp2, ) # Navier-stokes convective term args = ('ijk', 'wuv') kwargs = {'x': geom, 'w': vbasis, 'u': vbasis, 'v': vbasis} self.integrals['convection'] = AffineIntegral( H, NutilsDelayedIntegrand('c w_ia u_j0 v_ka,0', *args, **kwargs, c=cp2), L, NutilsDelayedIntegrand('c w_ia u_j1 v_ka,1', *args, **kwargs, c=cp12), 1, NutilsDelayedIntegrand('c w_ia u_jb v_ka,b', *args, **kwargs, c=cp0), 1, NutilsDelayedIntegrand('c w_ia u_j0 v_ka,0', *args, **kwargs, c=cp1), ) # Norms self.integrals['v-h1s'] = self.integrals['laplacian'] / NU self.integrals['v-l2'] = AffineIntegral( 1, fn.outer(vbasis).sum(-1) * cp0, L, fn.outer(vbasis).sum(-1) * cp1, L * H, fn.outer(vbasis).sum(-1) * cp2, ) self.integrals['p-l2'] = AffineIntegral( 1, fn.outer(pbasis) * cp0, L, fn.outer(pbasis) * cp1, L * H, fn.outer(pbasis) * cp2, ) if not stabilize: self.verify return root = self.ndofs - self.extra_dofs terms = [] points = [(0, (0, 0)), (nel_up - 1, (0, 1))] eqn = vbasis.laplace(geom)[:, 0, _] colloc = collocate(domain, eqn, points, root, self.ndofs) terms.extend([NU, (colloc + colloc.T)]) eqn = -pbasis.grad(geom)[:, 0, _] colloc = collocate(domain, eqn, points, root, self.ndofs) terms.extend([1, colloc + colloc.T]) points = [(nel_up**2 + nel_up * nel_length, (0, 0))] eqn = vbasis[:, 0].grad(geom).grad(geom) colloc = collocate(domain, eqn[:, 0, 0, _], points, root + 2, self.ndofs) terms.extend([NU / L**2, colloc.T]) colloc = collocate(domain, eqn[:, 1, 1, _], points, root + 2, self.ndofs) terms.extend([NU / H**2, colloc]) eqn = -pbasis.grad(geom)[:, 0, _] colloc = collocate(domain, -pbasis.grad(geom)[:, 0, _], points, root + 2, self.ndofs) terms.extend([1 / L, colloc]) points = [(nel_up * (nel_up - 1), (1, 0))] colloc = collocate(domain, vbasis.laplace(geom)[:, 0, _], points, root + 3, self.ndofs) terms.extend([NU, colloc]) colloc = collocate(domain, -pbasis.grad(geom)[:, 0, _], points, root + 3, self.ndofs) terms.extend([1, colloc]) self.integrals['stab-lhs'] = AffineIntegral(*terms) self.verify()
def __init__(self, refine=1, degree=4, nel=None): if nel is None: nel = int(10 * refine) pts = np.linspace(0, 1, nel + 1) domain, geom = mesh.rectilinear([pts, pts]) NutilsCase.__init__(self, 'Cavity flow', domain, geom, geom) bases = [ domain.basis('spline', degree=(degree, degree - 1)), # vx domain.basis('spline', degree=(degree - 1, degree)), # vy domain.basis('spline', degree=degree - 1), # pressure [1], # lagrange multiplier [0] * 4, # stabilization terms ] basis_lens = [len(b) for b in bases] vxbasis, vybasis, pbasis, lbasis, __ = fn.chain(bases) vbasis = vxbasis[:, _] * (1, 0) + vybasis[:, _] * (0, 1) self.bases.add('v', vbasis, length=sum(basis_lens[:2])) self.bases.add('p', pbasis, length=basis_lens[2]) self.extra_dofs = 5 self.constrain('v', 'left', 'top', 'bottom', 'right') self.integrals['lift'] = Affine(1, np.zeros(vbasis.shape[0])) self.integrals['geometry'] = Affine(1, geom) x, y = geom f = 4 * (x - x**2)**2 g = 4 * (y - y**2)**2 d1f = f.grad(geom)[0] d1g = g.grad(geom)[1] velocity = fn.asarray((f * d1g, -d1f * g)) pressure = d1f * d1g total = domain.integrate(pressure * fn.J(geom), ischeme='gauss9') pressure -= total / domain.volume(geometry=geom) force = pressure.grad(geom) - velocity.laplace(geom) self._exact_solutions = {'v': velocity, 'p': pressure} self.integrals['forcing'] = AffineIntegral(1, (vbasis * force[_, :]).sum(-1)) self.integrals['divergence'] = AffineIntegral( -1, fn.outer(vbasis.div(geom), pbasis)) self.integrals['laplacian'] = AffineIntegral( 1, fn.outer(vbasis.grad(geom)).sum((-1, -2))) self.integrals['v-h1s'] = AffineIntegral( 1, fn.outer(vbasis.grad(geom)).sum([-1, -2])) self.integrals['p-l2'] = AffineIntegral(1, fn.outer(pbasis)) root = self.ndofs - self.extra_dofs points = [(0, (0, 0)), (nel - 1, (0, 1)), (nel * (nel - 1), (1, 0)), (nel**2 - 1, (1, 1))] eqn = (pbasis.grad(geom) - vbasis.laplace(geom))[:, 0, _] colloc = collocate(domain, eqn, points, root + 1, self.ndofs) self.integrals['stab-lhs'] = AffineIntegral(1, colloc, 1, fn.outer(lbasis, pbasis)) self.integrals['stab-rhs'] = AffineIntegral( 1, collocate(domain, force[0, _], points, root + 1, self.ndofs))
def __init__(self, refine=1, degree=3, nel_up=None, nel_length=None, nel_up_mid=None, nel_length_out=None, stabilize=True, override=True): if nel_up is None: nel_up = int(50 * refine) if nel_length is None: nel_length = int(50 * refine) if nel_up_mid is None: nel_up_mid = nel_up // 5 if nel_length_out is None: nel_length_out = 2 * nel_length // 5 domain, geom = mesh.multipatch( patches=[[[0,1],[4,5]], [[1,2],[5,6]], [[2,3],[6,7]], [[5,6],[8,9]]], nelems={ (0,1): nel_up, (4,5): nel_up, (2,3): nel_up, (6,7): nel_up, (1,2): nel_up_mid, (5,6): nel_up_mid, (8,9): nel_up_mid, (0,4): nel_length, (1,5): nel_length, (2,6): nel_length, (3,7): nel_length, (5,8): nel_length_out, (6,9): nel_length_out, }, patchverts=[ [-5,0], [-5,1], [-5,2], [-5,3], [0,0], [0,1], [0,2], [0,3], [2,1], [2,2], ] ) NutilsCase.__init__(self, 'T-shape channel', domain, geom, geom) NU = 1 / self.parameters.add('viscosity', 20, 50) H = self.parameters.add('height', 1, 5) V = self.parameters.add('velocity', 1, 5) bases = [ domain.basis('spline', degree=(degree, degree-1)), # vx domain.basis('spline', degree=(degree-1, degree)), # vy domain.basis('spline', degree=degree-1) # pressure ] if stabilize: bases.append([0] * 4) basis_lens = [len(b) for b in bases] vxbasis, vybasis, pbasis, *__ = fn.chain(bases) vbasis = vxbasis[:,_] * (1,0) + vybasis[:,_] * (0,1) self.bases.add('v', vbasis, length=sum(basis_lens[:2])) self.bases.add('p', pbasis, length=basis_lens[2]) self.extra_dofs = 4 if stabilize else 0 x, y = geom hy = fn.piecewise(y, (1,2), y-1, 0, y-2) self.integrals['geometry'] = Affine(1, geom, H - 1, fn.asarray((0, hy))) self.constrain( 'v', 'patch0-bottom', 'patch0-left', 'patch0-right', 'patch1-left', 'patch2-left', 'patch2-top', 'patch2-right', 'patch3-bottom', 'patch3-top', ) vgrad = vbasis.grad(geom) # Lifting function profile = fn.max(0, y/3 * (1-y/3) * (1-x))[_] * (1, 0) self.integrals['lift'] = Affine(V, self.project_lift(profile, 'v')) # Characteristic functions cp0, cp1, cp2, cp3 = [characteristic(domain, (i,)) for i in range(4)] cp02 = cp0 + cp2 cp13 = cp1 + cp3 # Stokes divergence term self.integrals['divergence'] = AffineIntegral( -(H-1), fn.outer(vgrad[:,0,0], pbasis) * cp02, -1, fn.outer(vbasis.div(geom), pbasis), ) # Stokes laplacian term self.integrals['laplacian'] = AffineIntegral( NU, fn.outer(vgrad).sum([-1,-2]) * cp13, NU*H, fn.outer(vgrad[:,:,0]).sum(-1) * cp02, NU/H, fn.outer(vgrad[:,:,1]).sum(-1) * cp02, ) # Navier-Stokes convective term args = ('ijk', 'wuv') kwargs = {'x': geom, 'w': vbasis, 'u': vbasis, 'v': vbasis} self.integrals['convection'] = AffineIntegral( H, NutilsDelayedIntegrand('c w_ia u_j0 v_ka,0', *args, **kwargs, c=cp02), 1, NutilsDelayedIntegrand('c w_ia u_j1 v_ka,1', *args, **kwargs, c=cp02), 1, NutilsDelayedIntegrand('c w_ia u_jb v_ka,b', *args, **kwargs, c=cp13), ) # Norms self.integrals['v-h1s'] = self.integrals['laplacian'] / NU self.integrals['v-l2'] = AffineIntegral( H, fn.outer(vbasis).sum(-1) * cp02, 1, fn.outer(vbasis).sum(-1) * cp13, ) self.integrals['p-l2'] = AffineIntegral( H, fn.outer(pbasis) * cp02, 1, fn.outer(pbasis) * cp13, ) if not stabilize: self.verify() return root = self.ndofs - self.extra_dofs points = [ (0, (0, 0)), (nel_up*(nel_length-1), (1, 0)), (nel_up*nel_length + nel_up_mid*nel_length + nel_up - 1, (0, 1)), (nel_up*nel_length*2 + nel_up_mid*nel_length - 1, (1, 1)) ] terms = [] eqn = vbasis[:,0].grad(geom).grad(geom) colloc = collocate(domain, eqn[:,0,0,_], points, root, self.ndofs) terms.extend([NU, (colloc + colloc.T)]) colloc = collocate(domain, eqn[:,1,1,_], points, root, self.ndofs) terms.extend([NU/H**2, (colloc + colloc.T)]) eqn = -pbasis.grad(geom)[:,0,_] colloc = collocate(domain, eqn, points, root, self.ndofs) terms.extend([1, colloc + colloc.T]) self.integrals['stab-lhs'] = AffineIntegral(*terms) self.verify()
def __init__(self, refine=1, degree=3, nel=None, power=3): if nel is None: nel = int(10 * refine) pts = np.linspace(0, 1, nel + 1) domain, geom = mesh.rectilinear([pts, pts]) x, y = geom NutilsCase.__init__(self, 'Exact divergence-conforming flow', domain, geom, geom) w = self.parameters.add('w', 1, 2) h = self.parameters.add('h', 1, 2) bases = [ domain.basis('spline', degree=(degree, degree-1)), # vx domain.basis('spline', degree=(degree-1, degree)), # vy domain.basis('spline', degree=degree-1), # pressure [1], # lagrange multiplier [0] * 4, # stabilization terms ] basis_lens = [len(b) for b in bases] vxbasis, vybasis, pbasis, lbasis, __ = fn.chain(bases) vbasis = vxbasis[:,_] * (1,0) + vybasis[:,_] * (0,1) self.bases.add('v', vbasis, length=sum(basis_lens[:2])) self.bases.add('p', pbasis, length=basis_lens[2]) self.extra_dofs = 5 self.integrals['geometry'] = Affine( 1, geom, w-1, fn.asarray((x,0)), h-1, fn.asarray((0,y)), ) self.constrain('v', 'left', 'top', 'bottom', 'right') r = power self.power = power # Exact solution f = x**r g = y**r f1 = r * x**(r-1) g1 = r * y**(r-1) g2 = r*(r-1) * y**(r-2) f3 = r*(r-1)*(r-2) * x**(r-3) g3 = r*(r-1)*(r-2) * y**(r-3) self._exact_solutions = {'v': fn.asarray((f*g1, -f1*g)), 'p': f1*g1 - 1} # Awkward way of computing a solenoidal lift mdom, t = mesh.rectilinear([pts]) hbasis = mdom.basis('spline', degree=degree) hcoeffs = mdom.project(t[0]**r, onto=hbasis, geometry=t, ischeme='gauss9') projtderiv = hbasis.dot(hcoeffs).grad(t)[0] zbasis = mdom.basis('spline', degree=degree-1) zcoeffs = mdom.project(projtderiv, onto=zbasis, geometry=t, ischeme='gauss9') q = np.hstack([ np.outer(hcoeffs, zcoeffs).flatten(), - np.outer(zcoeffs, hcoeffs).flatten(), np.zeros((sum(basis_lens) - len(hcoeffs) * len(zcoeffs) * 2)) ]) self.integrals['lift'] = Affine(w**(r-1) * h**(r-1), q) self.integrals['forcing'] = AffineIntegral( w**(r-2) * h**(r+2), vybasis * (f3 * g)[_], w**r * h**r, 2*vybasis * (f1*g2)[_], w**(r+2) * h**(r-2), -vxbasis * (f*g3)[_], ) vx_x = vxbasis.grad(geom)[:,0] vx_xx = vx_x.grad(geom)[:,0] vx_y = vxbasis.grad(geom)[:,1] vx_yy = vx_y.grad(geom)[:,1] vy_x = vybasis.grad(geom)[:,0] vy_y = vybasis.grad(geom)[:,1] p_x = pbasis.grad(geom)[:,0] self.integrals['laplacian'] = AffineIntegral( h * w, fn.outer(vx_x, vx_x), h**3 / w, fn.outer(vy_x, vy_x), w**3 / h, fn.outer(vx_y, vx_y), w * h, fn.outer(vy_y, vy_y), ) self.integrals['divergence'] = AffineIntegral( h * w, (fn.outer(vx_x, pbasis) + fn.outer(vy_y, pbasis)) ) self['v-h1s'] = AffineIntegral(self.integrals['laplacian']) self['p-l2'] = AffineIntegral(h * w, fn.outer(pbasis, pbasis)) root = self.ndofs - self.extra_dofs points = [(0, (0, 0)), (nel-1, (0, 1)), (nel*(nel-1), (1, 0)), (nel**2-1, (1, 1))] ca, cb, cc = [ collocate(domain, eqn[:,_], points, root+1, self.ndofs) for eqn in [p_x, -vx_xx, -vx_yy] ] self.integrals['stab-lhs'] = AffineIntegral( 1/w, ca, 1/w, cb, w/h**2, cc, 1, fn.outer(lbasis, pbasis), w**3 * h**(r-3), collocate(domain, -f*g3[_], points, root+1, self.ndofs), ) self.integrals['v-trf'] = Affine( w, fn.asarray([[1,0], [0,0]]), h, fn.asarray([[0,0], [0,1]]), )