Ejemplo n.º 1
0
def example():

  verts = 0,1,3,4,10
  domain, geom = mesh.rectilinear( [ verts ] )
  basis = BSpline( degree=2, knotvalues=verts, knotmultiplicities=[1,2,3,1,1] ).build(domain)
  x, y = domain.elem_eval( [ geom[0], basis ], ischeme='bezier9' )
  with plot.PyPlot( '1D' ) as plt:
    plt.plot( x, y, '-' )

  verts = numpy.arange(10)
  domain, geom = mesh.rectilinear( [ verts ] )
  basis = Mod( Mod( Spline( degree=2, rmlast=True ), 2 ), -3 ).build(domain)
  x, y = domain.elem_eval( [ geom[0], basis ], ischeme='bezier9' )
  with plot.PyPlot( '1D' ) as plt:
    plt.plot( x, y, '-' )

  verts = numpy.arange(10)
  domain, geom = mesh.rectilinear( [ verts ] )
  basis = Mod( Mod( Spline( degree=2, periodic=True ), 2 ), 4 ).build(domain)
  x, y = domain.elem_eval( [ geom[0], basis ], ischeme='bezier9' )
  with plot.PyPlot( '1D' ) as plt:
    plt.plot( x, y, '-' )

  domain, geom = mesh.rectilinear( [ numpy.arange(5) ] * 2 )
  basis = ( Spline( degree=1, rmfirst=True ) * Mod( Spline( degree=2, periodic=True ), 2 ) ).build(domain)
  x, y = domain.elem_eval( [ geom, basis ], ischeme='bezier5' )
  with plot.PyPlot( '2D' ) as plt:
    for i, yi in enumerate( y.T ):
      plt.subplot( 4, 4, i+1 )
      plt.mesh( x, yi )
      plt.gca().set_axis_off()
Ejemplo n.º 2
0
 def test_discontinuous(self):
   pdomain, pgeom = mesh.rectilinear([3], periodic=[0])
   rdomain, rgeom = mesh.rectilinear([3])
   pbasis = pdomain.basis('spline', degree=2, knotmultiplicities=[[3,1,2,3]])
   rbasis = rdomain.basis('spline', degree=2, knotmultiplicities=[[1,1,2,1]])
   psampled = pdomain.sample('gauss', 2).eval(pbasis)
   rsampled = rdomain.sample('gauss', 2).eval(rbasis)
   self.assertAllAlmostEqual(psampled, rsampled)
Ejemplo n.º 3
0
 def setUp(self):
   super().setUp()
   if not self.product:
     self.domain, self.geom = mesh.rectilinear([2,3])
   else:
     domain1, geom1 = mesh.rectilinear([2])
     domain2, geom2 = mesh.rectilinear([3])
     self.domain = domain1 * domain2
     self.geom = function.concatenate(function.bifurcate(geom1, geom2), axis=0)
Ejemplo n.º 4
0
 def setUp(self):
     super().setUp()
     domain, geom = mesh.rectilinear([numpy.linspace(0, 1, 9)] * 2)
     ubasis = domain.basis('std', degree=2)
     if self.vector:
         u = ubasis.vector(2).dot(
             function.Argument('dofs', [len(ubasis) * 2]))
     else:
         u = (ubasis[:, numpy.newaxis] *
              function.Argument('dofs', [len(ubasis), 2])).sum(0)
     Geom = geom * [1.1, 1] + u
     self.cons = solver.optimize('dofs',
                                 domain.boundary['left,right'].integral(
                                     (u**2).sum(0), degree=4),
                                 droptol=1e-15)
     self.boolcons = ~numpy.isnan(self.cons)
     strain = .5 * (function.outer(Geom.grad(geom), axis=1).sum(0) -
                    function.eye(2))
     self.energy = domain.integral(
         ((strain**2).sum([0, 1]) + 20 *
          (function.determinant(Geom.grad(geom)) - 1)**2) *
         function.J(geom),
         degree=6)
     self.residual = self.energy.derivative('dofs')
     self.tol = 1e-10
Ejemplo n.º 5
0
 def setUp(self):
     super().setUp()
     verts = numpy.linspace(0, 1, self.nelems + 1)
     self.domain, self.geom = mesh.rectilinear(
         [verts], periodic=(0, ) if self.periodic else ())
     self.basis = self.domain.basis(self.btype, degree=self.degree) if self.btype != 'spline' \
             else self.domain.basis(self.btype, degree=self.degree, continuity=self.continuity)
Ejemplo n.º 6
0
    def test_sparsity(self):
        topo, geom = mesh.rectilinear([6] * self.ndim)
        topo = topo.refined_by(
            set(
                map(
                    topo.transforms.index,
                    itertools.chain(topo[1:3].transforms,
                                    topo[-2:].transforms))))

        ns = function.Namespace()
        ns.x = geom
        ns.tbasis = topo.basis('th-spline',
                               degree=2,
                               truncation_tolerance=1e-14)
        ns.tnotol = topo.basis('th-spline', degree=2, truncation_tolerance=0)
        ns.hbasis = topo.basis('h-spline', degree=2)

        tA, tA_tol, hA = topo.sample('gauss', 5).integrate_sparse([
            ns.eval_ij('tbasis_i,k tbasis_j,k'),
            ns.eval_ij('tnotol_i,k tnotol_j,k'),
            ns.eval_ij('hbasis_i,k hbasis_j,k')
        ])

        tA_nnz, tA_tol_nnz, hA_nnz = self.vals[self.ndim]
        self.assertEqual(len(sparse.prune(sparse.dedup(tA))), tA_nnz)
        self.assertEqual(len(sparse.prune(sparse.dedup(tA_tol))), tA_tol_nnz)
        self.assertEqual(len(sparse.prune(sparse.dedup(hA))), hA_nnz)
Ejemplo n.º 7
0
 def setUp(self):
   super().setUp()
   domain, geom = mesh.rectilinear([numpy.linspace(0,1,9)] * 2)
   gauss = domain.sample('gauss', 5)
   uin = geom[1] * (1-geom[1])
   dx = function.J(geom, 2)
   ubasis = domain.basis('std', degree=2)
   pbasis = domain.basis('std', degree=1)
   if self.single:
     ubasis, pbasis = function.chain([ubasis.vector(2), pbasis])
     dofs = function.Argument('dofs', [len(ubasis)])
     u = ubasis.dot(dofs)
     p = pbasis.dot(dofs)
     dofs = 'dofs'
     ures = gauss.integral((self.viscosity * (ubasis.grad(geom) * (u.grad(geom) + u.grad(geom).T)).sum([-1,-2]) - ubasis.div(geom) * p) * dx)
     dres = gauss.integral((ubasis * (u.grad(geom) * u).sum(-1)).sum(-1) * dx)
   else:
     u = (ubasis[:,numpy.newaxis] * function.Argument('dofs', [len(ubasis), 2])).sum(0)
     p = (pbasis * function.Argument('pdofs', [len(pbasis)])).sum(0)
     dofs = 'dofs', 'pdofs'
     ures = gauss.integral((self.viscosity * (ubasis[:,numpy.newaxis].grad(geom) * (u.grad(geom) + u.grad(geom).T)).sum(-1) - ubasis.grad(geom) * p) * dx)
     dres = gauss.integral(ubasis[:,numpy.newaxis] * (u.grad(geom) * u).sum(-1) * dx)
   pres = gauss.integral((pbasis * u.div(geom)) * dx)
   cons = solver.optimize('dofs', domain.boundary['top,bottom'].integral((u**2).sum(), degree=4), droptol=1e-10)
   cons = solver.optimize('dofs', domain.boundary['left'].integral((u[0]-uin)**2 + u[1]**2, degree=4), droptol=1e-10, constrain=cons)
   self.cons = cons if self.single else {'dofs': cons}
   stokes = solver.solve_linear(dofs, residual=ures + pres if self.single else [ures, pres], constrain=self.cons)
   self.arguments = dict(dofs=stokes) if self.single else stokes
   self.residual = ures + dres + pres if self.single else [ures + dres, pres]
   inertia = gauss.integral(.5 * (u**2).sum(-1) * dx).derivative('dofs')
   self.inertia = inertia if self.single else [inertia, None]
   self.tol = 1e-10
   self.dofs = dofs
   self.frozen = types.frozenarray if self.single else solver.argdict
Ejemplo n.º 8
0
 def setUp(self):
   super().setUp()
   self.ns = function.Namespace()
   self.domain, self.ns.geom = mesh.rectilinear([2,2])
   self.ns.ubasis = self.domain.basis('std', degree=1)
   self.ns.u = 'ubasis_n ?dofs_n'
   self.optimize = solver.optimize if not self.minimize else lambda *args, newtontol=0, **kwargs: solver.minimize(*args, **kwargs).solve(newtontol)
Ejemplo n.º 9
0
 def test_nonlinear_diagonalshift(self):
     nelems = 10
     domain, geom = mesh.rectilinear([nelems, 1])
     geom *= [2 * numpy.pi / nelems, 1]
     ubasis = domain.basis('spline', degree=2).vector(2)
     u = ubasis.dot(function.Argument('dofs', [len(ubasis)]))
     Geom = [.5 * geom[0], geom[1] + function.cos(geom[0])
             ] + u  # compress by 50% and buckle
     cons = solver.minimize('dofs',
                            domain.boundary['left,right'].integral(
                                (u**2).sum(0), degree=4),
                            droptol=1e-15).solve()
     strain = .5 * (function.outer(Geom.grad(geom), axis=1).sum(0) -
                    function.eye(2))
     energy = domain.integral(
         ((strain**2).sum([0, 1]) + 150 *
          (function.determinant(Geom.grad(geom)) - 1)**2) *
         function.J(geom),
         degree=6)
     nshift = 0
     for iiter, (lhs, info) in enumerate(
             solver.minimize('dofs', energy, constrain=cons)):
         self.assertLess(iiter, 38)
         if info.shift:
             nshift += 1
         if info.resnorm < self.tol:
             break
     self.assertEqual(nshift, 9)
Ejemplo n.º 10
0
def navierstokes():
  domain, geom = mesh.rectilinear( [numpy.linspace(0,1,9)] * 2 )
  ubasis, pbasis = function.chain([
    domain.basis( 'std', degree=2 ).vector(2),
    domain.basis( 'std', degree=1 ),
  ])
  dofs = function.DerivativeTarget( [len(ubasis)] )
  u = ubasis.dot( dofs )
  p = pbasis.dot( dofs )
  viscosity = 1
  inertia = model.Integral( (ubasis * u).sum(-1), domain=domain, geometry=geom, degree=5 )
  stokesres = model.Integral( viscosity * ubasis['ni,j'] * (u['i,j']+u['j,i']) - ubasis['nk,k'] * p + pbasis['n'] * u['k,k'], domain=domain, geometry=geom, degree=5 )
  residual = stokesres + model.Integral( ubasis['ni'] * u['i,j'] * u['j'], domain=domain, geometry=geom, degree=5 )
  cons = domain.boundary['top,bottom'].project( [0,0], onto=ubasis, geometry=geom, ischeme='gauss2' ) \
       | domain.boundary['left'].project( [geom[1]*(1-geom[1]),0], onto=ubasis, geometry=geom, ischeme='gauss2' )
  lhs0 = model.solve_linear( dofs, residual=stokesres, constrain=cons )

  for name in 'direct', 'newton', 'pseudotime':
    @unittest( name=name, raises=name=='direct' and model.ModelError)
    def res():
      tol = 1e-10
      if name == 'direct':
        lhs = model.solve_linear( dofs, residual=residual, constrain=cons )
      elif name == 'newton':
        lhs = model.newton( dofs, residual=residual, lhs0=lhs0, freezedofs=cons.where ).solve( tol=tol, maxiter=2 )
      else:
        lhs = model.pseudotime( dofs, residual=residual, lhs0=lhs0, freezedofs=cons.where, inertia=inertia, timestep=1 ).solve( tol=tol, maxiter=3 )
      res = residual.replace( dofs, lhs ).eval()
      resnorm = numpy.linalg.norm( res[~cons.where] )
      assert resnorm < tol
Ejemplo n.º 11
0
def main(viscosity=1.3e-3, density=1e3, pout=223e5, uw=-0.01, nelems=10):
    # viscosity = 1.3e-3
    # density = 1e3
    # pout = 223e5
    # nelems = 10
    # uw = -0.01

    domain, geom = mesh.rectilinear([numpy.linspace(0, 1, nelems), numpy.linspace(1, 2, nelems), [0, 2 * numpy.pi]],
                                periodic=[2])
    domain = domain.withboundary(inner='bottom', outer='top')

    ns = function.Namespace()
    ns.y, ns.r, ns.θ = geom
    ns.x_i = '<r cos(θ), y, r sin(θ)>_i'
    ns.uybasis, ns.urbasis, ns.pbasis = function.chain([
    domain.basis('std', degree=3, removedofs=((0,-1), None, None)),  # remove normal component at y=0 and y=1
    domain.basis('std', degree=3, removedofs=((0,-1), None, None)),  # remove tangential component at y=0 (no slip)
    domain.basis('std', degree=2)])
    ns.ubasis_ni = '<urbasis_n cos(θ), uybasis_n, urbasis_n sin(θ)>_i'
    ns.viscosity = viscosity
    ns.density = density
    ns.u_i = 'ubasis_ni ?lhs_n'
    ns.p = 'pbasis_n ?lhs_n'
    ns.sigma_ij = 'viscosity (u_i,j + u_j,i) - p δ_ij'
    ns.pout = pout
    ns.uw = uw
    ns.uw_i = 'uw <cos(phi), 0, sin(phi)>_i'
    ns.tout_i = '-pout n_i'
    ns.uw_i = 'uw n_i'  # uniform outflow

    res = domain.integral('(viscosity ubasis_ni,j u_i,j - p ubasis_ni,i + pbasis_n u_k,k) d:x' @ ns, degree=6)
    # res -= domain[1].boundary['inner'].integral('ubasis_ni tout_i d:x' @ ns, degree=6)

    sqr = domain.boundary['inner'].integral('(u_i - uw_i) (u_i - uw_i) d:x' @ ns, degree=6)
    # sqr = domain.boundary['outer'].integral('(u_i - uin_i) (u_i - uin_i) d:x' @ ns, degree=6)
    sqr -= domain.boundary['outer'].integral('(p - pout) (p - pout) d:x' @ ns, degree=6)
    cons = solver.optimize('lhs', sqr, droptol=1e-15)

    lhs = solver.solve_linear('lhs', res, constrain=cons)

    plottopo = domain[:, :, 0:].boundary['back']

    bezier = plottopo.sample('bezier', 10)
    r, y, p, u = bezier.eval([ns.r, ns.y, ns.p, function.norm2(ns.u)], lhs=lhs)
    with export.mplfigure('pressure.png', dpi=800) as fig:
        ax = fig.add_subplot(111, title='pressure', aspect=1)
        ax.autoscale(enable=True, axis='both', tight=True)
        im = ax.tripcolor(r, y, bezier.tri, p, shading='gouraud', cmap='jet')
        ax.add_collection(
            collections.LineCollection(numpy.array([y, r]).T[bezier.hull], colors='k', linewidths=0.2, alpha=0.2))
        fig.colorbar(im)

    uniform = plottopo.sample('uniform', 1)
    r_, y_, uv = uniform.eval([ns.r, ns.y, ns.u], lhs=lhs)
    with export.mplfigure('velocity.png', dpi=800) as fig:
        ax = fig.add_subplot(111, title='Velocity', aspect=1)
        ax.autoscale(enable=True, axis='both', tight=True)
        im = ax.tripcolor(r, y, bezier.tri, u, shading='gouraud', cmap='jet')
        ax.quiver(r_, y_, uv[:, 0], uv[:, 1], angles='xy', scale_units='xy')
        fig.colorbar(im)
Ejemplo n.º 12
0
def laplace():
    domain, geom = mesh.rectilinear([8, 8])
    basis = domain.basis('std', degree=1)
    cons = domain.boundary['left'].project(0,
                                           onto=basis,
                                           geometry=geom,
                                           ischeme='gauss2')
    dofs = function.DerivativeTarget([len(basis)])
    u = basis.dot(dofs)
    residual = model.Integral( ( basis.grad(geom) * u.grad(geom) ).sum(-1), domain=domain, geometry=geom, degree=2 ) \
             + model.Integral( basis, domain=domain.boundary['top'], geometry=geom, degree=2 )

    for name in 'direct', 'newton':

        @unittest(name=name)
        def res():
            if name == 'direct':
                lhs = model.solve_linear(dofs,
                                         residual=residual,
                                         constrain=cons)
            else:
                lhs = model.newton(dofs,
                                   residual=residual,
                                   lhs0=cons | 0,
                                   freezedofs=cons.where).solve(tol=1e-10,
                                                                maxiter=0)
            res = residual.replace(dofs, lhs).eval()
            resnorm = numpy.linalg.norm(res[~cons.where])
            assert resnorm < 1e-13
Ejemplo n.º 13
0
 def test(self):
   for knotmultiplicities, ndofs in [([3,1,3], 4), ([3,2,1,3], 6)]:
     domain, geom = mesh.rectilinear([len(knotmultiplicities)-1], periodic=[0])
     basis = domain.basis('spline', degree=3, knotmultiplicities=[knotmultiplicities])
     self.assertEqual(len(basis), ndofs)
     self.assertContinuous(topo=domain, geom=geom, basis=basis, continuity=0)
     self.assertPartitionOfUnity(topo=domain, basis=basis)
Ejemplo n.º 14
0
 def setUp(self):
     super().setUp()
     domain, geom = mesh.rectilinear([numpy.linspace(0, 1, 9)] * 2)
     ubasis, pbasis = function.chain([
         domain.basis('std', degree=2).vector(2),
         domain.basis('std', degree=1),
     ])
     dofs = function.Argument('dofs', [len(ubasis)])
     u = ubasis.dot(dofs)
     p = pbasis.dot(dofs)
     viscosity = 1e-3
     self.inertia = domain.integral((ubasis * u).sum(-1) * function.J(geom),
                                    degree=5)
     stokesres = domain.integral(
         (viscosity * (ubasis.grad(geom) *
                       (u.grad(geom) + u.grad(geom).T)).sum([-1, -2]) -
          ubasis.div(geom) * p + pbasis * u.div(geom)) * function.J(geom),
         degree=5)
     self.residual = stokesres + domain.integral(
         (ubasis *
          (u.grad(geom) * u).sum(-1) * u).sum(-1) * function.J(geom),
         degree=5)
     self.cons = domain.boundary['top,bottom'].project([0,0], onto=ubasis, geometry=geom, ischeme='gauss4') \
               | domain.boundary['left'].project([geom[1]*(1-geom[1]),0], onto=ubasis, geometry=geom, ischeme='gauss4')
     self.lhs0 = solver.solve_linear('dofs',
                                     residual=stokesres,
                                     constrain=self.cons)
     self.tol = 1e-10
Ejemplo n.º 15
0
 def setUp(self):
     super().setUp()
     if self.ndims == 2:
         domain, geom = mesh.unitsquare(4, self.variant)
         nverts = 25
     elif self.variant == 'tensor':
         structured, geom = mesh.rectilinear(
             [numpy.linspace(0, 1, 5 - i) for i in range(self.ndims)])
         domain = topology.ConnectedTopology(structured.references,
                                             structured.transforms,
                                             structured.opposites,
                                             structured.connectivity)
         nverts = numpy.product([5 - i for i in range(self.ndims)])
     elif self.variant == 'simplex':
         numpy.random.seed(0)
         nverts = 20
         simplices = numeric.overlapping(numpy.arange(nverts),
                                         n=self.ndims + 1)
         coords = numpy.random.normal(size=(nverts, self.ndims))
         root = transform.Identifier(self.ndims, 'test')
         transforms = transformseq.PlainTransforms(
             [(root, transform.Square((c[1:] - c[0]).T, c[0]))
              for c in coords[simplices]], self.ndims)
         domain = topology.SimplexTopology(simplices, transforms,
                                           transforms)
         geom = function.rootcoords(self.ndims)
     else:
         raise NotImplementedError
     self.domain = domain
     self.basis = domain.basis(
         self.btype) if self.btype == 'bubble' else domain.basis(
             self.btype, degree=self.degree)
     self.geom = geom
     self.nverts = nverts
Ejemplo n.º 16
0
def poisson_patch(bottom, right, top, left):
    from nutils import version
    if version != '3.0':
        raise ImportError('Outdated nutils version detected, only v3.0 supported. Upgrade by \"pip install --upgrade nutils\"')

    from nutils import mesh, function as fn
    from nutils import _, log

    # error test input
    if left.rational or right.rational or top.rational or bottom.rational:
        raise RuntimeError('poisson_patch not supported for rational splines')

    # these are given as a oriented loop, so make all run in positive parametric direction
    top.reverse()
    left.reverse()

    # in order to add spline surfaces, they need identical parametrization
    Curve.make_splines_identical(top, bottom)
    Curve.make_splines_identical(left, right)

    # create computational (nutils) mesh
    p1 = bottom.order(0)
    p2 = left.order(0)
    n1 = len(bottom)
    n2 = len(left)
    dim= left.dimension
    k1 = bottom.knots(0)
    k2 = left.knots(0)
    m1 = [bottom.order(0) - bottom.continuity(k) - 1 for k in k1]
    m2 = [left.order(0)   - left.continuity(k)   - 1 for k in k2]
    domain, geom = mesh.rectilinear([k1, k2])
    basis = domain.basis('spline', [p1-1, p2-1], knotmultiplicities=[m1,m2])

    # assemble system matrix
    grad      = basis.grad(geom)
    outer     = fn.outer(grad,grad)
    integrand = outer.sum(-1)
    matrix = domain.integrate(integrand, geometry=geom, ischeme='gauss'+str(max(p1,p2)+1))

    # initialize variables
    controlpoints = np.zeros((n1,n2,dim))
    rhs           = np.zeros((n1*n2))
    constraints = np.array([[np.nan]*n2]*n1)

    # treat all dimensions independently
    for d in range(dim):
        # add boundary conditions
        constraints[ 0, :] = left[  :,d]
        constraints[-1, :] = right[ :,d]
        constraints[ :, 0] = bottom[:,d]
        constraints[ :,-1] = top[   :,d]

        # solve system
        lhs = matrix.solve(rhs, constrain=np.ndarray.flatten(constraints), solver='cg', tol=state.controlpoint_absolute_tolerance)

        # wrap results into splipy datastructures
        controlpoints[:,:,d] = np.reshape(lhs, (n1,n2), order='C')

    return Surface(bottom.bases[0], left.bases[0], controlpoints, bottom.rational, raw=True)
Ejemplo n.º 17
0
def main(nelems: int, degree: int, reynolds: float):
    '''
  Driven cavity benchmark problem using compatible spaces.

  .. arguments::

     nelems [12]
       Number of elements along edge.
     degree [2]
       Polynomial degree for velocity; the pressure space is one degree less.
     reynolds [1000]
       Reynolds number, taking the domain size as characteristic length.
  '''

    verts = numpy.linspace(0, 1, nelems + 1)
    domain, geom = mesh.rectilinear([verts, verts])

    ns = function.Namespace()
    ns.x = geom
    ns.Re = reynolds
    ns.ubasis = function.vectorize([
        domain.basis('spline',
                     degree=(degree, degree - 1),
                     removedofs=((0, -1), None)),
        domain.basis('spline',
                     degree=(degree - 1, degree),
                     removedofs=(None, (0, -1)))
    ])
    ns.pbasis = domain.basis('spline', degree=degree - 1)
    ns.u_i = 'ubasis_ni ?u_n'
    ns.p = 'pbasis_n ?p_n'
    ns.stress_ij = '(d(u_i, x_j) + d(u_j, x_i)) / Re - p δ_ij'
    ns.uwall = domain.boundary.indicator('top'), 0
    ns.N = 5 * degree * nelems  # nitsche constant based on element size = 1/nelems
    ns.nitsche_ni = '(N ubasis_ni - (d(ubasis_ni, x_j) + d(ubasis_nj, x_i)) n(x_j)) / Re'

    ures = domain.integral('d(ubasis_ni, x_j) stress_ij d:x' @ ns,
                           degree=2 * degree)
    ures += domain.boundary.integral(
        '(nitsche_ni (u_i - uwall_i) - ubasis_ni stress_ij n(x_j)) d:x' @ ns,
        degree=2 * degree)
    pres = domain.integral('pbasis_n (d(u_k, x_k) + ?lm) d:x' @ ns,
                           degree=2 * degree)
    lres = domain.integral('p d:x' @ ns, degree=2 * degree)

    with treelog.context('stokes'):
        state0 = solver.solve_linear(['u', 'p', 'lm'], [ures, pres, lres])
        postprocess(domain, ns, **state0)

    ures += domain.integral('ubasis_ni d(u_i, x_j) u_j d:x' @ ns,
                            degree=3 * degree)
    with treelog.context('navierstokes'):
        state1 = solver.newton(('u', 'p', 'lm'), (ures, pres, lres),
                               arguments=state0).solve(tol=1e-10)
        postprocess(domain, ns, **state1)

    return state0, state1
Ejemplo n.º 18
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))
Ejemplo n.º 19
0
 def setUp(self):
   super().setUp()
   domain, geom = mesh.rectilinear([8,8])
   basis = domain.basis('std', degree=1)
   self.cons = domain.boundary['left'].project(0, onto=basis, geometry=geom, ischeme='gauss2')
   dofs = function.Argument('dofs', [len(basis)])
   u = basis.dot(dofs)
   self.residual = domain.integral((basis.grad(geom) * u.grad(geom)).sum(-1), geometry=geom, degree=2) \
                 + domain.boundary['top'].integral(basis, geometry=geom, degree=2)
Ejemplo n.º 20
0
 def setUp(self):
   super().setUp()
   self.domain, self.geom = mesh.rectilinear([max(1, self.nelems-n) for n in range(self.ndims)], periodic=[0] if self.periodic else [])
   for iref in range(self.nrefine):
     self.domain = self.domain.refined_by([len(self.domain)-1])
   if self.boundary:
     self.domain = self.domain.boundary[self.boundary]
   self.basis = self.domain.basis(self.btype, degree=self.degree)
   self.gauss = 'gauss{}'.format(2*self.degree)
Ejemplo n.º 21
0
def main(
    nelems: 'number of elements' = 20,
    degree: 'polynomial degree' = 1,
    timescale: 'time scale (timestep=timescale/nelems)' = .5,
    tol: 'solver tolerance' = 1e-5,
    ndims: 'spatial dimension' = 1,
    endtime: 'end time, 0 for no end time' = 0,
    withplots: 'create plots' = True,
):

    # construct mesh
    domain, geom = mesh.rectilinear([numpy.linspace(0, 1, nelems + 1)] * ndims,
                                    periodic=range(ndims))
    basis = domain.basis('discont', degree=degree)

    # construct initial condition (centered gaussian)
    u = function.exp(-(((geom - .5) * 5)**2).sum(-1))
    lhs = domain.project(u, onto=basis, geometry=geom, ischeme='gauss5')

    # prepare matrix
    timestep = timescale / nelems
    At = (1 / timestep) * function.outer(basis)
    matrix0 = domain.integrate(At, geometry=geom, ischeme='gauss5')

    # prepare plotting
    makeplots = MakePlots(domain, geom, video=withplots
                          == 'video') if withplots else lambda *args: None

    # start time stepping
    for itime in log.count('timestep'):
        makeplots(u)
        if endtime and itime * timestep >= endtime:
            break
        rhs = matrix0.matvec(lhs)
        for ipicard in log.count('picard'):
            u = basis.dot(lhs)
            beta = function.repeat(u[_], ndims, axis=0)
            Am = -function.outer((basis[:, _] * beta).div(geom), basis)
            dmatrix = domain.integrate(Am, geometry=geom, ischeme='gauss5')
            alpha = .5 * function.sign(function.mean(beta).dotnorm(geom))
            Ai = function.outer(
                function.jump(basis),
                (alpha * function.jump(basis[:, _] * beta) -
                 function.mean(basis[:, _] * beta)).dotnorm(geom))
            dmatrix += domain.interfaces.integrate(Ai,
                                                   geometry=geom,
                                                   ischeme='gauss5')
            lhs, info = (matrix0 + dmatrix).solve(rhs,
                                                  lhs0=lhs,
                                                  tol=tol,
                                                  restart=999,
                                                  precon='spilu',
                                                  info=True)
            if info.niter == 0:
                break

    return rhs, lhs
Ejemplo n.º 22
0
 def setUp(self):
   super().setUp()
   domain, geom = mesh.rectilinear([8,8])
   basis = domain.basis('std', degree=1)
   self.cons = domain.boundary['left'].project(0, onto=basis, geometry=geom, ischeme='gauss2')
   dofs = function.Argument('dofs', [len(basis)])
   u = basis.dot(dofs)
   self.residual = domain.integral((basis.grad(geom) * u.grad(geom)).sum(-1)*function.J(geom), degree=2) \
                 + domain.boundary['top'].integral(basis*function.J(geom), degree=2)
Ejemplo n.º 23
0
def splipy_to_nutils(spline):
    """ Returns nutils domain and geometry object for spline mapping given by the argument """
    from nutils import mesh, function
    domain, geom = mesh.rectilinear(spline.knots())
    cp    = controlpoints(spline)
    basis = domain.basis('spline', degree=degree(spline), knotmultiplicities=multiplicities(spline))
    geom  = function.matmat(basis, cp)
    #TODO: add correct behaviour for rational and/or periodic geometries
    return domain, geom
Ejemplo n.º 24
0
 def setUp(self):
   ns = function.Namespace()
   domain, ns.x = mesh.rectilinear([10], periodic=(0,))
   ns.basis = domain.basis('discont', degree=1)
   ns.u = 'basis_n ?dofs_n'
   ns.f = '.5 u^2'
   self.residual = domain.integral('-basis_n,0 f d:x' @ ns, degree=2)
   self.residual += domain.interfaces.integral('-[basis_n] n_0 ({f} - .5 [u] n_0) d:x' @ ns, degree=4)
   self.inertia = domain.integral('basis_n u d:x' @ ns, degree=5)
   self.lhs0 = numpy.sin(numpy.arange(len(ns.basis))) # "random" initial vector
Ejemplo n.º 25
0
def main(alpha=0.01, nelems=64, degree=2, dt=0.01, tend=1):

    # construct topology, geometry and basis
    verts = numpy.linspace(0, 1, nelems + 1)
    domain, geom = mesh.rectilinear([verts, verts])
    basis = domain.basis('spline', degree=degree)
    ischeme = 'gauss4'
    print(basis)
    exit()

    # construct matrices
    A = 1 / dt * basis['i'] * basis['j'] + alpha / 2 * basis['i,k'] * basis[
        'j,k']
    B = 1 / dt * basis['i'] * basis['j'] - alpha / 2 * basis['i,k'] * basis[
        'j,k']
    A, B = domain.integrate([A, B], geometry=geom, ischeme=ischeme)

    # construct dirichlet boundary constraints
    cons = domain.boundary.project(0,
                                   onto=basis,
                                   geometry=geom,
                                   ischeme=ischeme)

    # construct initial condition
    x0, x1 = geom
    l = function.max(
        # level set of a square centred at (0.3,0.4)
        0.15 - (abs(0.3 - x0) + abs(0.4 - x1)),
        # level set of a circle centred at (0.7,0.6)
        0.15 - ((0.7 - x0)**2 + (0.6 - x1)**2)**0.5,
    )
    # smooth heaviside of level set
    u0 = 0.5 + 0.5 * function.tanh(nelems / 2 * l)

    for n in log.range('timestep', round(tend / dt) + 1):

        if n == 0:
            # project initial condition on `basis`
            w = domain.project(u0, onto=basis, geometry=geom, ischeme=ischeme)
        else:
            # time step
            w = A.solve(B.matvec(w), constrain=cons)

        # construct solution
        u = basis.dot(w)

        # plot
        points, colors = domain.elem_eval([geom, u],
                                          ischeme='bezier3',
                                          separate=True)
        with plot.PyPlot('temperature') as plt:
            plt.title('t={:5.2f}'.format(n * dt))
            plt.mesh(points, colors)
            plt.colorbar()
            plt.clim(0, 1)
Ejemplo n.º 26
0
def main(nelems: int, degree: int, reynolds: float):
    '''
  Driven cavity benchmark problem using compatible spaces.

  .. arguments::

     nelems [12]
       Number of elements along edge.
     degree [2]
       Polynomial degree for velocity; the pressure space is one degree less.
     reynolds [1000]
       Reynolds number, taking the domain size as characteristic length.
  '''

    verts = numpy.linspace(0, 1, nelems + 1)
    domain, geom = mesh.rectilinear([verts, verts])

    ns = function.Namespace()
    ns.x = geom
    ns.Re = reynolds
    ns.uxbasis, ns.uybasis, ns.pbasis, ns.lbasis = function.chain([
        domain.basis('spline',
                     degree=(degree, degree - 1),
                     removedofs=((0, -1), None)),
        domain.basis('spline',
                     degree=(degree - 1, degree),
                     removedofs=(None, (0, -1))),
        domain.basis('spline', degree=degree - 1),
        [1],  # lagrange multiplier
    ])
    ns.ubasis_ni = '<uxbasis_n, uybasis_n>_i'
    ns.u_i = 'ubasis_ni ?lhs_n'
    ns.p = 'pbasis_n ?lhs_n'
    ns.l = 'lbasis_n ?lhs_n'
    ns.stress_ij = '(u_i,j + u_j,i) / Re - p δ_ij'
    ns.uwall = domain.boundary.indicator('top'), 0
    ns.N = 5 * degree * nelems  # nitsche constant based on element size = 1/nelems
    ns.nitsche_ni = '(N ubasis_ni - (ubasis_ni,j + ubasis_nj,i) n_j) / Re'

    res = domain.integral(
        '(ubasis_ni,j stress_ij + pbasis_n (u_k,k + l) + lbasis_n p) d:x' @ ns,
        degree=2 * degree)
    res += domain.boundary.integral(
        '(nitsche_ni (u_i - uwall_i) - ubasis_ni stress_ij n_j) d:x' @ ns,
        degree=2 * degree)
    with treelog.context('stokes'):
        lhs0 = solver.solve_linear('lhs', res)
        postprocess(domain, ns, lhs=lhs0)

    res += domain.integral('ubasis_ni u_i,j u_j d:x' @ ns, degree=3 * degree)
    with treelog.context('navierstokes'):
        lhs1 = solver.newton('lhs', res, lhs0=lhs0).solve(tol=1e-10)
        postprocess(domain, ns, lhs=lhs1)

    return lhs0, lhs1
Ejemplo n.º 27
0
    def __init__(self, physical, n, p):
        """ __init__(self, physical, n, p)
        Constructor for finite element object
        :param physical : (width, height) of physical domain
        :param n        : (n1,n2), number of elements in computational domain
        :param p        : (p1,p2), polynomial degree of compuational discretization
        """
        # create splipy object
        splinesurf = splines.square() * physical
        splinesurf.reparam((0, physical[0]), (0, physical[1]))
        splinesurf.raise_order(p[0] - 1, p[1] - 1)
        splinesurf.refine(n[0] - 1, n[1] - 1)

        # create nutils mesh
        domain, geom = mesh.rectilinear(splinesurf.knots())
        basis = domain.basis('spline', degree=p)

        # pre-compute all system matrices
        derivs = function.outer(basis.grad(geom), basis.grad(geom))
        laplace = derivs[:, :, 0] + derivs[:, :, 1]
        A = domain.integrate(laplace, geometry=geom, ischeme='gauss3')
        M = domain.integrate(function.outer(basis, basis),
                             geometry=geom,
                             ischeme='gauss3')
        # print(M.toarray())

        # pre-compute evaluation matrices
        self.Nu = splinesurf.bases[0].evaluate(
            np.linspace(splinesurf.start('u'), splinesurf.end('u'),
                        physical[0]))
        self.Nv = splinesurf.bases[1].evaluate(
            np.linspace(splinesurf.start('v'), splinesurf.end('v'),
                        physical[1]))

        # store all nutils object as class variables
        self.splinesurf = splinesurf
        self.domain = domain
        self.geom = geom
        self.basis = basis
        self.A = A.toscipy() * 1e2
        self.M = M.toscipy()
        self.u = np.matrix(np.zeros((A.shape[0], 1)))
        self.b = np.matrix(np.zeros((A.shape[0], 1)))

        self.n = np.array(n)
        self.p = np.array(p)
        self.physical = np.array(physical)
        self.time = {
            'add_smoke': 0,
            'get_img': 0,
            'stop_smoke': 0,
            'diffuse': 0,
            'solve': 0
        }
Ejemplo n.º 28
0
def splipy_to_nutils(spline):
    """ Returns nutils domain and geometry object for spline mapping given by the argument """
    from nutils import mesh, function
    domain, geom = mesh.rectilinear(spline.knots())
    cp = controlpoints(spline)
    basis = domain.basis('spline',
                         degree=degree(spline),
                         knotmultiplicities=multiplicities(spline))
    geom = function.matmat(basis, cp)
    #TODO: add correct behaviour for rational and/or periodic geometries
    return domain, geom
Ejemplo n.º 29
0
def test_nutils_tensor():
    domain, geom = mesh.rectilinear([[0, 1], [0, 1]])
    basis = domain.basis('spline', degree=1)

    itg = basis[:, _, _] * basis[_, :, _] * basis[_, _, :]

    a = AffineIntegral(1, itg)
    a.prop(domain=domain, geometry=geom, ischeme='gauss9')
    a = a.cache_main(force=True)(None, {})
    b = domain.integrate(itg * fn.J(geom), ischeme='gauss9')

    np.testing.assert_almost_equal(a, b)
Ejemplo n.º 30
0
def navierstokes():
    domain, geom = mesh.rectilinear([numpy.linspace(0, 1, 9)] * 2)
    ubasis, pbasis = function.chain([
        domain.basis('std', degree=2).vector(2),
        domain.basis('std', degree=1),
    ])
    dofs = function.DerivativeTarget([len(ubasis)])
    u = ubasis.dot(dofs)
    p = pbasis.dot(dofs)
    viscosity = 1
    inertia = model.Integral((ubasis * u).sum(-1),
                             domain=domain,
                             geometry=geom,
                             degree=5)
    stokesres = model.Integral(viscosity * ubasis['ni,j'] *
                               (u['i,j'] + u['j,i']) - ubasis['nk,k'] * p +
                               pbasis['n'] * u['k,k'],
                               domain=domain,
                               geometry=geom,
                               degree=5)
    residual = stokesres + model.Integral(ubasis['ni'] * u['i,j'] * u['j'],
                                          domain=domain,
                                          geometry=geom,
                                          degree=5)
    cons = domain.boundary['top,bottom'].project( [0,0], onto=ubasis, geometry=geom, ischeme='gauss2' ) \
         | domain.boundary['left'].project( [geom[1]*(1-geom[1]),0], onto=ubasis, geometry=geom, ischeme='gauss2' )
    lhs0 = model.solve_linear(dofs, residual=stokesres, constrain=cons)

    for name in 'direct', 'newton', 'pseudotime':

        @unittest(name=name, raises=name == 'direct' and model.ModelError)
        def res():
            tol = 1e-10
            if name == 'direct':
                lhs = model.solve_linear(dofs,
                                         residual=residual,
                                         constrain=cons)
            elif name == 'newton':
                lhs = model.newton(dofs,
                                   residual=residual,
                                   lhs0=lhs0,
                                   freezedofs=cons.where).solve(tol=tol,
                                                                maxiter=2)
            else:
                lhs = model.pseudotime(dofs,
                                       residual=residual,
                                       lhs0=lhs0,
                                       freezedofs=cons.where,
                                       inertia=inertia,
                                       timestep=1).solve(tol=tol, maxiter=3)
            res = residual.replace(dofs, lhs).eval()
            resnorm = numpy.linalg.norm(res[~cons.where])
            assert resnorm < tol
Ejemplo n.º 31
0
 def setUp(self):
   super().setUp()
   domain, geom = mesh.rectilinear([numpy.linspace(0,1,9)] * 2)
   ubasis = domain.basis('std', degree=2).vector(2)
   u = ubasis.dot(function.Argument('dofs', [len(ubasis)]))
   Geom = geom * [1.1, 1] + u
   self.cons = solver.minimize('dofs', domain.boundary['left,right'].integral((u**2).sum(0), degree=4), droptol=1e-15).solve()
   self.boolcons = ~numpy.isnan(self.cons)
   strain = .5 * (function.outer(Geom.grad(geom), axis=1).sum(0) - function.eye(2))
   self.energy = domain.integral(((strain**2).sum([0,1]) + 20*(function.determinant(Geom.grad(geom))-1)**2)*function.J(geom), degree=6)
   self.residual = self.energy.derivative('dofs')
   self.tol = 1e-10
Ejemplo n.º 32
0
def mk_case(override):
    pspace = np.linspace(0, 2*np.pi, 4)
    rspace = np.linspace(0, 1, 3)
    domain, refgeom = mesh.rectilinear([rspace, pspace], periodic=(1,))
    r, ang = refgeom
    geom = fn.asarray((
        (1 + 10 * r) * fn.cos(ang),
        (1 + 10 * r) * fn.sin(ang),
    ))
    case = cases.airfoil(mesh=(domain, refgeom, geom), lift=False, amax=10, rmax=10, piola=True)
    case.precompute(force=override)
    return case
Ejemplo n.º 33
0
def main(
    nelems: 'number of elements' = 12,
    lmbda: 'first lamé constant' = 1.,
    mu: 'second lamé constant' = 1.,
    degree: 'polynomial degree' = 2,
    withplots: 'create plots' = True,
    solvetol: 'solver tolerance' = 1e-10,
):

    # construct mesh
    verts = numpy.linspace(0, 1, nelems + 1)
    domain, geom = mesh.rectilinear([verts, verts])

    # create namespace
    ns = function.Namespace(default_geometry_name='x0')
    ns.x0 = geom
    ns.basis = domain.basis('spline', degree=degree).vector(2)
    ns.u_i = 'basis_ni ?lhs_n'
    ns.x_i = 'x0_i + u_i'
    ns.lmbda = lmbda
    ns.mu = mu
    ns.strain_ij = '(u_i,j + u_j,i) / 2'
    ns.stress_ij = 'lmbda strain_kk δ_ij + 2 mu strain_ij'

    # construct dirichlet boundary constraints
    sqr = domain.boundary['left'].integral('u_k u_k' @ ns,
                                           geometry=ns.x0,
                                           degree=2)
    sqr += domain.boundary['right'].integral('(u_0 - .5)^2' @ ns,
                                             geometry=ns.x0,
                                             degree=2)
    cons = solver.optimize('lhs', sqr, droptol=1e-15)

    # construct residual
    res = domain.integral('basis_ni,j stress_ij' @ ns,
                          geometry=ns.x0,
                          degree=2)

    # solve system and substitute the solution in the namespace
    lhs = solver.solve_linear('lhs', res, constrain=cons)
    ns |= dict(lhs=lhs)

    # plot solution
    if withplots:
        points, colors = domain.elem_eval([ns.x, ns.stress[0, 1]],
                                          ischeme='bezier3',
                                          separate=True)
        with plot.PyPlot('stress', ndigits=0) as plt:
            plt.mesh(points, colors, tight=False)
            plt.colorbar()

    return lhs, cons
Ejemplo n.º 34
0
def mk_mesh(nang, nrad, rmin, rmax):
    aspace = np.linspace(0, 2 * np.pi, nang + 1)
    rspace = np.linspace(0, 1, nrad + 1)
    domain, refgeom = mesh.rectilinear([rspace, aspace], periodic=(1, ))

    rad, theta = refgeom
    K = 5
    rad = (fn.exp(K * rad) - 1) / (np.exp(K) - 1)
    x = (rad * (rmax - rmin) + rmin) * fn.cos(theta)
    y = (rad * (rmax - rmin) + rmin) * fn.sin(theta)
    geom = fn.asarray([x, y])

    return domain, refgeom, geom
Ejemplo n.º 35
0
 def test_nonlinear_diagonalshift(self):
   nelems = 10
   domain, geom = mesh.rectilinear([nelems,1])
   geom *= [2*numpy.pi/nelems, 1]
   ubasis = domain.basis('spline', degree=2).vector(2)
   u = ubasis.dot(function.Argument('dofs', [len(ubasis)]))
   Geom = [.5 * geom[0], geom[1] + function.cos(geom[0])] + u # compress by 50% and buckle
   cons = solver.minimize('dofs', domain.boundary['left,right'].integral((u**2).sum(0), degree=4), droptol=1e-15).solve()
   strain = .5 * (function.outer(Geom.grad(geom), axis=1).sum(0) - function.eye(2))
   energy = domain.integral(((strain**2).sum([0,1]) + 150*(function.determinant(Geom.grad(geom))-1)**2)*function.J(geom), degree=6)
   nshift = 0
   for iiter, (lhs, info) in enumerate(solver.minimize('dofs', energy, constrain=cons)):
     self.assertLess(iiter, 90)
     if info.shift:
       nshift += 1
     if info.resnorm < self.tol:
       break
   self.assertEqual(nshift, 60)
Ejemplo n.º 36
0
 def setUp(self):
   super().setUp()
   domain, geom = mesh.rectilinear([numpy.linspace(0,1,9)] * 2)
   ubasis, pbasis = function.chain([
     domain.basis('std', degree=2).vector(2),
     domain.basis('std', degree=1),
   ])
   dofs = function.Argument('dofs', [len(ubasis)])
   u = ubasis.dot(dofs)
   p = pbasis.dot(dofs)
   viscosity = 1
   self.inertia = domain.integral((ubasis * u).sum(-1), geometry=geom, degree=5)
   stokesres = domain.integral(viscosity * (ubasis.grad(geom) * (u.grad(geom)+u.grad(geom).T)).sum([-1,-2]) - ubasis.div(geom) * p + pbasis * u.div(geom), geometry=geom, degree=5)
   self.residual = stokesres + domain.integral((ubasis * (u.grad(geom) * u).sum(-1) * u).sum(-1), geometry=geom, degree=5)
   self.cons = domain.boundary['top,bottom'].project([0,0], onto=ubasis, geometry=geom, ischeme='gauss2') \
             | domain.boundary['left'].project([geom[1]*(1-geom[1]),0], onto=ubasis, geometry=geom, ischeme='gauss2')
   self.lhs0 = solver.solve_linear('dofs', residual=stokesres, constrain=self.cons)
   self.tol = 1e-10
Ejemplo n.º 37
0
def main(
    nelems: 'number of elements' = 12,
    lmbda: 'first lamé constant' = 1.,
    mu: 'second lamé constant' = 1.,
    degree: 'polynomial degree' = 2,
    withplots: 'create plots' = True,
    solvetol: 'solver tolerance' = 1e-10,
 ):

  # construct mesh
  verts = numpy.linspace(0, 1, nelems+1)
  domain, geom = mesh.rectilinear([verts,verts])

  # create namespace
  ns = function.Namespace(default_geometry_name='x0')
  ns.x0 = geom
  ns.basis = domain.basis('spline', degree=degree).vector(2)
  ns.u_i = 'basis_ni ?lhs_n'
  ns.x_i = 'x0_i + u_i'
  ns.lmbda = lmbda
  ns.mu = mu
  ns.strain_ij = '(u_i,j + u_j,i) / 2'
  ns.stress_ij = 'lmbda strain_kk δ_ij + 2 mu strain_ij'

  # construct dirichlet boundary constraints
  sqr = domain.boundary['left'].integral('u_k u_k' @ ns, geometry=ns.x0, degree=2)
  sqr += domain.boundary['right'].integral('(u_0 - .5)^2' @ ns, geometry=ns.x0, degree=2)
  cons = solver.optimize('lhs', sqr, droptol=1e-15)

  # construct residual
  res = domain.integral('basis_ni,j stress_ij' @ ns, geometry=ns.x0, degree=2)

  # solve system and substitute the solution in the namespace
  lhs = solver.solve_linear('lhs', res, constrain=cons)
  ns |= dict(lhs=lhs)

  # plot solution
  if withplots:
    points, colors = domain.elem_eval([ns.x, ns.stress[0,1]], ischeme='bezier3', separate=True)
    with plot.PyPlot('stress', ndigits=0) as plt:
      plt.mesh(points, colors, tight=False)
      plt.colorbar()

  return lhs, cons
Ejemplo n.º 38
0
def laplace():
  domain, geom = mesh.rectilinear( [8,8] )
  basis = domain.basis( 'std', degree=1 )
  cons = domain.boundary['left'].project( 0, onto=basis, geometry=geom, ischeme='gauss2' )
  dofs = function.DerivativeTarget( [len(basis)] )
  u = basis.dot( dofs )
  residual = model.Integral( ( basis.grad(geom) * u.grad(geom) ).sum(-1), domain=domain, geometry=geom, degree=2 ) \
           + model.Integral( basis, domain=domain.boundary['top'], geometry=geom, degree=2 )

  for name in 'direct', 'newton':
    @unittest( name=name )
    def res():
      if name == 'direct':
        lhs = model.solve_linear( dofs, residual=residual, constrain=cons )
      else:
        lhs = model.newton( dofs, residual=residual, lhs0=cons|0, freezedofs=cons.where ).solve( tol=1e-10, maxiter=0 )
      res = residual.replace( dofs, lhs ).eval()
      resnorm = numpy.linalg.norm( res[~cons.where] )
      assert resnorm < 1e-13
Ejemplo n.º 39
0
def main(
    nelems: 'number of elements' = 20,
    degree: 'polynomial degree' = 1,
    timescale: 'time scale (timestep=timescale/nelems)' = .5,
    tol: 'solver tolerance' = 1e-5,
    ndims: 'spatial dimension' = 1,
    endtime: 'end time, 0 for no end time' = 0,
    withplots: 'create plots' = True,
 ):

  # construct mesh, basis
  ns = function.Namespace()
  domain, ns.x = mesh.rectilinear([numpy.linspace(0,1,nelems+1)]*ndims, periodic=range(ndims))
  ns.basis = domain.basis('discont', degree=degree)
  ns.u = 'basis_n ?lhs_n'

  # construct initial condition (centered gaussian)
  lhs0 = domain.project('exp(-?y_i ?y_i) | ?y_i = 5 (x_i - 0.5_i)' @ ns, onto=ns.basis, geometry=ns.x, degree=5)

  # prepare residual
  ns.f = '.5 u^2'
  ns.C = 1
  res = domain.integral('-basis_n,0 f' @ ns, geometry=ns.x, degree=5)
  res += domain.interfaces.integral('-[basis_n] n_0 ({f} - .5 C [u] n_0)' @ ns, geometry=ns.x, degree=5)
  inertia = domain.integral('basis_n u' @ ns, geometry=ns.x, degree=5)

  # prepare plotting
  makeplots = MakePlots(domain, video=withplots=='video') if withplots else lambda ns: None

  # start time stepping
  timestep = timescale/nelems
  for itime, lhs in log.enumerate('timestep', solver.impliciteuler('lhs', res, inertia, timestep, lhs0, newtontol=tol)):
    makeplots(ns | dict(lhs=lhs))
    if endtime and itime * timestep >= endtime:
      break

  return res.eval(arguments=dict(lhs=lhs)), lhs
Ejemplo n.º 40
0
def main(
    nelems: 'number of elements' = 20,
    epsilon: 'epsilon, 0 for automatic (based on nelems)' = 0,
    timestep: 'time step' = .01,
    maxtime: 'end time' = 1.,
    theta: 'contact angle (degrees)' = 90,
    init: 'initial condition (random/bubbles)' = 'random',
    withplots: 'create plots' = True,
  ):

  mineps = 1./nelems
  if not epsilon:
    log.info('setting epsilon={}'.format(mineps))
    epsilon = mineps
  elif epsilon < mineps:
    log.warning('epsilon under crititical threshold: {} < {}'.format(epsilon, mineps))

  # create namespace
  ns = function.Namespace()
  ns.epsilon = epsilon
  ns.ewall = .5 * numpy.cos( theta * numpy.pi / 180 )

  # construct mesh
  xnodes = ynodes = numpy.linspace(0,1,nelems+1)
  domain, ns.x = mesh.rectilinear( [ xnodes, ynodes ] )

  # prepare bases
  ns.cbasis, ns.mubasis = function.chain([
    domain.basis('spline', degree=2),
    domain.basis('spline', degree=2)
  ])

  # polulate namespace
  ns.c = 'cbasis_n ?lhs_n'
  ns.c0 = 'cbasis_n ?lhs0_n'
  ns.mu = 'mubasis_n ?lhs_n'
  ns.f = '(6 c0 - 2 c0^3 - 4 c) / epsilon^2'

  # construct initial condition
  if init == 'random':
    numpy.random.seed(0)
    lhs0 = numpy.random.normal(0, .5, ns.cbasis.shape)
  elif init == 'bubbles':
    R1 = .25
    R2 = numpy.sqrt(.5) * R1 # area2 = .5 * area1
    ns.cbubble1 = function.tanh((R1-function.norm2(ns.x-(.5+R2/numpy.sqrt(2)+.8*ns.epsilon)))/ns.epsilon)
    ns.cbubble2 = function.tanh((R2-function.norm2(ns.x-(.5-R1/numpy.sqrt(2)-.8*ns.epsilon)))/ns.epsilon)
    sqr = domain.integral('(c - cbubble1 - cbubble2 - 1)^2 + mu^2' @ ns, geometry=ns.x, degree=4)
    lhs0 = solver.optimize('lhs', sqr)
  else:
    raise Exception( 'unknown init %r' % init )

  # construct residual
  res = domain.integral('epsilon^2 cbasis_n,k mu_,k + mubasis_n (mu + f) - mubasis_n,k c_,k' @ ns, geometry=ns.x, degree=4)
  res -= domain.boundary.integral('mubasis_n ewall' @ ns, geometry=ns.x, degree=4)
  inertia = domain.integral('cbasis_n c' @ ns, geometry=ns.x, degree=4)

  # solve time dependent problem
  nsteps = numeric.round(maxtime/timestep)
  makeplots = MakePlots(domain, nsteps, ns) if withplots else lambda *args: None
  for istep, lhs in log.enumerate('timestep', solver.impliciteuler('lhs', target0='lhs0', residual=res, inertia=inertia, timestep=timestep, lhs0=lhs0)):
    makeplots(lhs)
    if istep == nsteps:
      break

  return lhs0, lhs
Ejemplo n.º 41
0
 def setUp(self):
   super().setUp()
   self.ns = function.Namespace()
   self.domain, self.ns.geom = mesh.rectilinear([2,2])
   self.ns.ubasis = self.domain.basis('std', degree=1)
Ejemplo n.º 42
0
def main(
    nelems: 'number of elements' = 12,
    viscosity: 'fluid viscosity' = 1e-2,
    density: 'fluid density' = 1,
    tol: 'solver tolerance' = 1e-12,
    rotation: 'cylinder rotation speed' = 0,
    timestep: 'time step' = 1/24,
    maxradius: 'approximate domain size' = 25,
    tmax: 'end time' = numpy.inf,
    degree: 'polynomial degree' = 2,
    figures: 'create figures' = True,
  ):

  log.user('reynolds number: {:.1f}'.format(density / viscosity)) # based on unit length and velocity

  # create namespace
  ns = function.Namespace()
  ns.uinf = 1, 0
  ns.density = density
  ns.viscosity = viscosity

  # construct mesh
  rscale = numpy.pi / nelems
  melems = numpy.ceil(numpy.log(2*maxradius) / rscale).astype(int)
  log.info('creating {}x{} mesh, outer radius {:.2f}'.format(melems, 2*nelems, .5*numpy.exp(rscale*melems)))
  domain, x0 = mesh.rectilinear([range(melems+1),numpy.linspace(0,2*numpy.pi,2*nelems+1)], periodic=(1,))
  rho, phi = x0
  phi += 1e-3 # tiny nudge (0.057 deg) to break element symmetry
  radius = .5 * function.exp(rscale * rho)
  ns.x = radius * function.trigtangent(phi)
  domain = domain.withboundary(inner='left', inflow=domain.boundary['right'].select(-ns.uinf.dotnorm(ns.x), ischeme='gauss1'))

  # prepare bases (using piola transformation to maintain u/p compatibility)
  J = ns.x.grad(x0)
  detJ = function.determinant(J)
  ns.unbasis, ns.utbasis, ns.pbasis = function.chain([ # compatible spaces using piola transformation
    domain.basis('spline', degree=(degree+1,degree), removedofs=((0,),None))[:,_] * J[:,0] / detJ,
    domain.basis('spline', degree=(degree,degree+1))[:,_] * J[:,1] / detJ,
    domain.basis('spline', degree=degree) / detJ,
  ])
  ns.ubasis_ni = 'unbasis_ni + utbasis_ni'

  # populate namespace
  ns.u_i = 'ubasis_ni ?lhs_n'
  ns.p = 'pbasis_n ?lhs_n'
  ns.sigma_ij = 'viscosity (u_i,j + u_j,i) - p δ_ij'
  ns.hinner = 2 * numpy.pi / nelems
  ns.c = 5 * (degree+1) / ns.hinner
  ns.nietzsche_ni = 'viscosity (c ubasis_ni - (ubasis_ni,j + ubasis_nj,i) n_j)'
  ns.ucyl = -.5 * rotation * function.trignormal(phi)

  # create residual vector components
  res = domain.integral('ubasis_ni,j sigma_ij + pbasis_n u_k,k' @ ns, geometry=ns.x, degree=2*(degree+1))
  res += domain.boundary['inner'].integral('nietzsche_ni (u_i - ucyl_i)' @ ns, geometry=ns.x, degree=2*(degree+1))
  oseen = domain.integral('density ubasis_ni u_i,j uinf_j' @ ns, geometry=ns.x, degree=2*(degree+1))
  convec = domain.integral('density ubasis_ni u_i,j u_j' @ ns, geometry=ns.x, degree=3*(degree+1))
  inertia = domain.integral('density ubasis_ni u_i' @ ns, geometry=ns.x, degree=2*(degree+1))

  # constrain full velocity vector at inflow
  sqr = domain.boundary['inflow'].integral('(u_i - uinf_i) (u_i - uinf_i)' @ ns, geometry=ns.x, degree=9)
  cons = solver.optimize('lhs', sqr, droptol=1e-15)

  # solve unsteady navier-stokes equations, starting from stationary oseen flow
  lhs0 = solver.solve_linear('lhs', res+oseen, constrain=cons)
  makeplots = MakePlots(domain, ns, timestep=timestep, rotation=rotation) if figures else lambda *args: None
  for istep, lhs in log.enumerate('timestep', solver.impliciteuler('lhs', residual=res+convec, inertia=inertia, lhs0=lhs0, timestep=timestep, constrain=cons, newtontol=1e-10)):
    makeplots(lhs)
    if istep * timestep >= tmax:
      break

  return lhs0, lhs
Ejemplo n.º 43
0
def main(
    L: 'domain size' = 4.,
    R: 'hole radius' = 1.,
    E: "young's modulus" = 1e5,
    nu: "poisson's ratio" = 0.3,
    T: 'far field traction' = 10,
    nr: 'number of h-refinements' = 2,
    figures: 'create figures' = True,
  ):

  ns = function.Namespace()
  ns.lmbda = E*nu/(1-nu**2)
  ns.mu = .5*E/(1+nu)

  # create the coarsest level parameter domain
  domain0, geometry = mesh.rectilinear( [1,2] )

  # create the second-order B-spline basis over the coarsest domain
  ns.bsplinebasis = domain0.basis('spline', degree=2)
  ns.controlweights = 1,.5+.5/2**.5,.5+.5/2**.5,1,1,1,1,1,1,1,1,1
  ns.weightfunc = 'bsplinebasis_n controlweights_n'
  ns.nurbsbasis = ns.bsplinebasis * ns.controlweights / ns.weightfunc

  # create the isogeometric map
  ns.controlpoints = [0,R],[R*(1-2**.5),R],[-R,R*(2**.5-1)],[-R,0],[0,.5*(R+L)],[-.15*(R+L),.5*(R+L)],[-.5*(R+L),.15*(R*L)],[-.5*(R+L),0],[0,L],[-L,L],[-L,L],[-L,0]
  ns.x_i = 'nurbsbasis_n controlpoints_ni'

  # create the computational domain by h-refinement
  domain = domain0.refine(nr)

  # create the second-order B-spline basis over the refined domain
  ns.bsplinebasis = domain.basis('spline', degree=2)
  sqr = domain.integral('(bsplinebasis_n ?lhs_n - weightfunc)^2' @ ns, geometry=ns.x, degree=9)
  ns.controlweights = solver.optimize('lhs', sqr)
  ns.nurbsbasis = ns.bsplinebasis * ns.controlweights / ns.weightfunc

  # prepare the displacement field
  ns.ubasis = ns.nurbsbasis.vector(2)
  ns.u_i = 'ubasis_ni ?lhs_n'
  ns.strain_ij = '(u_i,j + u_j,i) / 2'
  ns.stress_ij = 'lmbda strain_kk δ_ij + 2 mu strain_ij'

  # construct the exact solution
  ns.r2 = 'x_k x_k'
  ns.R2 = R**2
  ns.T = T
  ns.k = (3-nu) / (1+nu) # plane stress parameter
  ns.uexact_i = '''(T / 4 mu) <x_0 ((k + 1) / 2 + (1 + k) R2 / r2 + (1 - R2 / r2) (x_0^2 - 3 x_1^2) R2 / r2^2),
                               x_1 ((k - 3) / 2 + (1 - k) R2 / r2 + (1 - R2 / r2) (3 x_0^2 - x_1^2) R2 / r2^2)>_i'''
  ns.strainexact_ij = '(uexact_i,j + uexact_j,i) / 2'
  ns.stressexact_ij = 'lmbda strainexact_kk δ_ij + 2 mu strainexact_ij'

  # define the linear and bilinear forms
  res = domain.integral('ubasis_ni,j stress_ij' @ ns, geometry=ns.x, degree=9)
  res -= domain.boundary['right'].integral('ubasis_ni stressexact_ij n_j' @ ns, geometry=ns.x, degree=9)

  # compute the constraints vector for the symmetry conditions
  sqr = domain.boundary['top,bottom'].integral('(u_i n_i)^2' @ ns, degree=9)
  cons = solver.optimize('lhs', sqr, droptol=1e-15)

  # solve the system of equations
  lhs = solver.solve_linear('lhs', res, constrain=cons)
  ns = ns(lhs=lhs)

  # post-processing
  if figures:
    geom, stressxx = domain.simplex.elem_eval([ns.x, 'stress_00' @ ns], ischeme='bezier8', separate=True)
    with plot.PyPlot( 'solution', index=nr ) as plt:
      plt.mesh( geom, stressxx )
      plt.colorbar()

  # compute the L2-norm of the error in the stress
  err = domain.integrate('(?dstress_ij ?dstress_ij)(dstress_ij = stress_ij - stressexact_ij)' @ ns, geometry=ns.x, ischeme='gauss9')**.5

  # compute the mesh parameter (maximum physical distance between knots)
  hmax = max(numpy.linalg.norm(v[:,numpy.newaxis]-v, axis=2).max() for v in domain.elem_eval(ns.x, ischeme='bezier2', separate=True))

  return err, hmax