Beispiel #1
0
    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))
Beispiel #2
0
    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()
Beispiel #3
0
    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))
Beispiel #4
0
    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()
Beispiel #5
0
    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]]),
        )