Exemplo 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()
Exemplo n.º 2
0
def convergence(nrefine=5):
  err, h = numpy.array([main(nr=irefine) for irefine in log.range('refine', nrefine)]).T
  with plot.PyPlot( 'convergence' ) as plt:
    plt.loglog(h, err, 'k*--')
    plt.slope_triangle(h, err)
    plt.ylabel('L2 error of stress')
    plt.grid(True)
Exemplo n.º 3
0
 def qgplot(self, **plotkwargs):
     assert len(self) == 2, NotImplementedError
     plt = plot.PyPlot('I am a dummy', **plotkwargs)
     domain = self.domain
     points = domain.elem_eval(self.geom, ischeme='bezier5', separate=True)
     plt.mesh(points)
     plt.show()
Exemplo n.º 4
0
    def plot_function(self,
                      func=[],
                      ischeme='bezier5',
                      ref=0,
                      boundary=False,
                      show=True,
                      **plotkwargs):
        assert self.targetspace == 2, NotImplementedError
        plt = plot.PyPlot('I am a dummy', **plotkwargs)
        domain = self.domain if not boundary else self.domain.boundary
        func = [self.mapping] + func
        points = domain.refine(ref).elem_eval(func,
                                              ischeme=ischeme,
                                              separate=True)

        if domain.ndims == 2:
            plt.mesh(*points)
        elif domain.ndims == 1:
            assert len(func) == 1
            plt.segments(np.asarray(*points))
            plt.aspect('equal')
            plt.autoscale(enable=True, axis='both', tight=True)
        else:
            raise NotImplementedError

        if show:
            plt.show()
Exemplo n.º 5
0
 def __call__(self, lhs):
     ns = self.namespace(lhs=lhs)
     self.energies[self.index, :2] = self.domain.integrate(
         ['(c^2 - 1)^2 / 2 epsilon^2' @ ns, '.5 c_,k c_,k' @ ns],
         geometry=ns.x,
         degree=4)
     self.energies[self.index, 2] = self.domain.boundary.integrate(
         'abs(ewall) + ewall c' @ ns, geometry=ns.x, degree=4)
     self.energies[self.index, 3] = self.energies[self.index, :3].sum()
     x, c = self.domain.elem_eval([ns.x, ns.c],
                                  ischeme='bezier4',
                                  separate=True)
     with plot.PyPlot('flow', index=self.index) as plt:
         plt.axes(yticks=[], xticks=[])
         plt.mesh(x, c)
         plt.colorbar()
         plt.clim(-1, 1)
         plt.axes([.07, .05, .35, .25], yticks=[], xticks=[],
                  axisbg='w').patch.set_alpha(.8)
         for energy, name in zip(self.energies[:self.index + 1].T,
                                 ['mixture', 'interface', 'wall', 'total']):
             plt.plot(numpy.arange(len(energy))[::-1],
                      energy[::-1],
                      '-o',
                      markevery=self.index + 1,
                      label=name)
         plt.legend(numpoints=1, frameon=False, fontsize=8)
         plt.xlim(0, len(self.energies))
         plt.ylim(0, self.energies[0, 3])
         plt.xlabel('time')
         plt.ylabel('energy')
     self.index += 1
Exemplo n.º 6
0
 def __call__(self, lhs):
     angle = self.index * self.timestep * self.rotation
     ns = self.ns(lhs=lhs)
     x, u, normu, p = self.plotdomain.elem_eval(
         [ns.x, ns.u, function.norm2(ns.u), ns.p],
         ischeme='bezier9',
         separate=True)
     with plot.PyPlot('flow', index=self.index) as plt:
         plt.axes([0, 0, 1, 1], yticks=[], xticks=[], frame_on=False)
         tri = plt.mesh(x, normu, mergetol=1e-5, cmap='jet')
         plt.clim(0, 1.5)
         plt.tricontour(tri,
                        p,
                        every=self.every,
                        cmap='gray',
                        linestyles='solid',
                        alpha=.8)
         uv = plot.interpolate(tri, self.xy, u)
         plt.vectors(self.xy, uv, zorder=9, pivot='mid', stems=False)
         plt.plot(0,
                  0,
                  'k',
                  marker=(3, 2, angle * 180 / numpy.pi - 90),
                  markersize=20)
         plt.xlim(self.bbox[0])
         plt.ylim(self.bbox[1])
     self.xy = util.regularize(self.bbox, self.spacing,
                               self.xy + uv * self.timestep)
     self.index += 1
Exemplo n.º 7
0
 def __call__(self, c, mu, *energies):
     self.energies[self.index] = energies
     self.index += 1
     xpnt, cpnt = self.domain.elem_eval([self.geom, c],
                                        ischeme='bezier4',
                                        separate=True)
     I = numpy.arange(self.index - 1, -1, -1)
     E = self.energies[self.index - 1::-1].T
     with self.plt if self.plt else plot.PyPlot('flow',
                                                index=self.index) as plt:
         plt.axes(yticks=[], xticks=[])
         plt.mesh(xpnt, cpnt)
         plt.colorbar()
         plt.clim(-1, 1)
         plt.axes([.07, .05, .35, .25], yticks=[], xticks=[],
                  axisbg='w').patch.set_alpha(.8)
         for i, name in enumerate(['mixture', 'interface', 'wall',
                                   'total']):
             plt.plot(I,
                      E[i] if i < len(E) else E.sum(0),
                      '-o',
                      markevery=self.index,
                      label=name)
         plt.legend(numpoints=1, frameon=False, fontsize=8)
         plt.xlim(0, len(self.energies))
         plt.ylim(0, self.energies[0].sum())
         plt.xlabel('time')
         plt.ylabel('energy')
Exemplo n.º 8
0
def makeplots(domain, geom, stress):

    points, colors = domain.elem_eval([geom, stress[0, 1]],
                                      ischeme='bezier3',
                                      separate=True)
    with plot.PyPlot('stress', ndigits=0) as plt:
        plt.mesh(points, colors, tight=False)
        plt.colorbar()
Exemplo n.º 9
0
 def __call__( self, velo, pres ):
   self.index += 1
   points, velo, pres = self.domain.elem_eval( [ self.geom, velo, pres ], ischeme='bezier9', separate=True )
   with plot.PyPlot( 'flow', index=self.index, ndigits=4 ) as plt:
     tri = plt.mesh( points, mergetol=1e-5 )
     plt.tricontour( tri, pres, every=self.dpres, linestyles='solid', alpha=.333 )
     plt.colorbar()
     plt.streamplot( tri, velo, spacing=.01, linewidth=-10, color='k', zorder=9 )
Exemplo n.º 10
0
 def __call__(self, ns):
     self.index += 1
     xp, up = self.domain.elem_eval([ns.x, ns.u],
                                    ischeme='bezier7',
                                    separate=True)
     with plot.PyPlot('solution', index=self.index) as plt:
         plt.mesh(xp, up)
         plt.clim(0, 1)
         plt.colorbar()
Exemplo n.º 11
0
 def plotpng(self,k,i):
     with plot.PyPlot(self.name[k] + '{}'.format("%04d", self.ii) + '{}'.format("%04d", i)) as plt:
         plt.title(self.name[k] + ' at t={:5.1f}'.format(i*self.prop.timestep))
         plt.mesh(self.Total_eval[0], self.Total_eval[i+1+k*self.leni])
         plt.colorbar(orientation = 'horizontal')
         plt.clim(self.clim[k][0],self.clim[k][1])
         plt.ylabel('Height in [m]')
         plt.xlabel('Width in [m]')
         plt.savefig(self.prop.dir + '2. Figures/' + self.name[k] + str(self.ii) + ' {}'.format(i),bbox_inches='tight', dpi = self.prop.dpi)
Exemplo n.º 12
0
 def __call__(self, u):
     self.index += 1
     xp, up = self.domain.elem_eval([self.geom, u],
                                    ischeme='bezier7',
                                    separate=True)
     with self.plt if self.plt else plot.PyPlot('solution',
                                                index=self.index) as plt:
         plt.mesh(xp, up)
         plt.clim(0, 1)
         plt.colorbar()
Exemplo n.º 13
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)
Exemplo n.º 14
0
def convergence(
    degree    = 2 ,
    nrefine   = 6,
    maxrefine = 7
    ):
  """Performs convergence study for the example
  Parameters
  ----------
  degree    : int
      b-spline degree
  nrefine   : int
      level of h-refinement
  maxrefine : int
      bisectioning steps
  """
  l2err, h1err, errh = numpy.array([main(nelems=2**(1+irefine), maxrefine = nmaxrefine, degree=degree)[1] for nmaxrefine in range(1,maxrefine+1) for irefine in log.range('refine', nrefine)]).T
  h = .5**numpy.arange(nrefine)
  clrstr = ['k*--','ks--','k^--','ko--','k--','k+--','kv--','k<--','kX--','k>--']
  # ploting errors
  with plot.PyPlot('L2error',ndigits=0) as plt:
    for m in range(0,maxrefine):
      plt.loglog(h, l2err[nrefine*m:nrefine*(m+1)], clrstr[m],label='maxrefine ={}'.format(m))
      plt.slope_triangle(h, l2err[nrefine*m:nrefine*(m+1)])
      plt.legend()
    plt.ylabel('L2 error')
    plt.grid(True)
  with plot.PyPlot('H1error',ndigits=0) as plt:
    for m in range(0,maxrefine):
      plt.loglog(h, h1err[nrefine*m:nrefine*(m+1)], clrstr[m],label='maxrefine ={}'.format(m))
      plt.slope_triangle(h, h1err[nrefine*m:nrefine*(m+1)])
      plt.legend()
    plt.ylabel('H1 error')
    plt.grid(True) 
  
  with plot.PyPlot('Energy_error',ndigits=0) as plt:
    for m in range(0,maxrefine):
      plt.loglog(h, errh[nrefine*m:nrefine*(m+1)], clrstr[m],label='maxrefine ={}'.format(m))
      plt.slope_triangle(h, errh[nrefine*m:nrefine*(m+1)])
      plt.legend()
    plt.ylabel('Energy error')
    plt.grid(True) 
Exemplo n.º 15
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
Exemplo n.º 16
0
 def __call__( self, velo, pres, angle ):
   self.index += 1
   points, velo, flow, pres = self.plotdomain.elem_eval( [ self.geom, velo, function.norm2(velo), pres ], ischeme='bezier9', separate=True )
   with self.plt if self.plt else plot.PyPlot( 'flow', index=self.index ) as plt:
     plt.axes( [0,0,1,1], yticks=[], xticks=[], frame_on=False )
     tri = plt.mesh( points, flow, mergetol=1e-5 )
     plt.clim( 0, 1.5 )
     plt.tricontour( tri, pres, every=self.every, cmap='gray', linestyles='solid', alpha=.8 )
     uv = plot.interpolate( tri, self.xy, velo )
     plt.vectors( self.xy, uv, zorder=9, pivot='mid', stems=False )
     plt.plot( 0, 0, 'k', marker=(3,2,angle*180/numpy.pi-90), markersize=20 )
     plt.xlim( self.bbox[0] )
     plt.ylim( self.bbox[1] )
   self.xy = util.regularize( self.bbox, self.spacing, self.xy + uv * self.timestep )
Exemplo n.º 17
0
def postprocess(domain, ns):

    # confirm that velocity is pointwise divergence-free
    div = domain.integrate('(u_k,k)^2' @ ns, geometry=ns.x, degree=9)**.5
    log.info('velocity divergence: {:.2e}'.format(div))

    # plot velocity field as streamlines, pressure field as contours
    x, u, p = domain.elem_eval([ns.x, ns.u, ns.p],
                               ischeme='bezier9',
                               separate=True)
    with plot.PyPlot('flow') as plt:
        tri = plt.mesh(x, mergetol=1e-5)
        plt.tricontour(tri, p, every=.01, linestyles='solid', alpha=.333)
        plt.colorbar()
        plt.streamplot(tri, u, spacing=.01, linewidth=-10, color='k', zorder=9)
Exemplo n.º 18
0
def convergence(nrefine=5):

    err = []
    h = []

    for irefine in log.range('refine', nrefine):
        serr, hmax = main(nr=irefine)
        err.append(serr)
        h.append(hmax)

    with plot.PyPlot('convergence') as plt:
        plt.loglog(h, err, 'k*--')
        plt.slope_triangle(h, err)
        plt.ylabel('L2 error of stress')
        plt.grid(True)
Exemplo n.º 19
0
def makeplots(domain, ns):
  
  # velocity field evaluation
  points, vals = domain.simplex.elem_eval([ns.x, ns.u], ischeme='bezier5', separate=True)
  # trimming curve evaluation
  tpoints = domain.boundary['trimmed'].elem_eval(ns.x, ischeme='bezier5', separate=True)
  # background domain evaluation
  background_domain = topology.UnstructuredTopology(ndims=2, elements=[element.Element(element.LineReference()**2,elem.transform) for elem in domain])
  bpoints = background_domain.simplex.elem_eval(ns.x, ischeme='bezier2', separate=True)
  with plot.PyPlot('cylinder', ndigits=1) as plt:
    plt.mesh(points , vals, edgecolors='none')
    plt.mesh(bpoints, edgecolors='r', edgewidth=1.5, mergetol=1e-6)
    plt.segments( tpoints , color='g', lw=2 )
    plt.gca().axis('off')
    plt.axis('equal') 
Exemplo n.º 20
0
 def __init__(self, domain, ns, timestep, rotation, bbox=((-2,6),(-3,3))):
   self.bbox = numpy.asarray(bbox)
   self.plotdomain = domain.select(function.min(*(ns.x-self.bbox[:,0])*(self.bbox[:,1]-ns.x)), 'bezier3')
   self.ns = ns
   self.every = .01
   self.index = 0
   self.timestep = timestep
   self.rotation = rotation
   self.spacing = .075
   self.xy = util.regularize(self.bbox, self.spacing)
   x = domain.elem_eval(ns.x, ischeme='bezier5', separate=True)
   inflow = domain.boundary['inflow'].elem_eval(ns.x, ischeme='bezier5', separate=True)
   with plot.PyPlot('mesh', ndigits=0) as plt:
     plt.mesh(x)
     plt.rectangle(self.bbox[:,0], *(self.bbox[:,1] - self.bbox[:,0]), ec='green')
     plt.segments(inflow, colors='red')
def main(nelems=8, degree=2, diffusion_over_h=0.5):

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

    # common integration arguments
    int_kwargs = dict(geometry=geom, ischeme='gauss{}'.format(degree * 2 + 1))

    for i in log.range('refinement', 4):

        # create domain and basis for global refinement step `i`
        if i > 0:
            domain = domain.refined
        φ = domain.basis('spline', degree=degree)

        # compute an initial guess based on the previous iteration, if any
        if i > 0:
            u_hat = domain.project(u, onto=φ, **int_kwargs)
        else:
            u_hat = numpy.zeros(φ.shape)

        # solve
        R = functools.partial(residual,
                              diffusion=diffusion_over_h / (nelems * 2**i),
                              geom=geom,
                              domain=domain,
                              φ=φ,
                              **int_kwargs)
        u_hat = newton(R, x0=u_hat, maxiter=20, restol=1e-8, lintol=0)

        # expand solution
        u = φ.dot(u_hat)

        # plot
        points, colors = domain.elem_eval([geom, u],
                                          ischeme='bezier3',
                                          separate=True)
        with plot.PyPlot('solution') as plt:
            plt.title('nelems={}'.format(nelems * 2**i))
            plt.mesh(points, colors)
            plt.colorbar()
            plt.clim(0, 1)
            plt.xlabel('t')
            plt.ylabel('x')
Exemplo n.º 22
0
def main(
    nelems: 'number of elements' = 10,
    degree: 'polynomial degree' = 1,
    basistype: 'basis function' = 'spline',
    solvetol: 'solver tolerance' = 1e-10,
    figures: 'create figures' = True,
  ):

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

  # create namespace
  ns = function.Namespace()
  ns.x = geom
  ns.basis = domain.basis(basistype, degree=degree)
  ns.u = 'basis_n ?lhs_n'
  ns.fx = 'sin(x_0)'
  ns.fy = 'exp(x_1)'

  # construct residual
  res = domain.integral('-basis_n,i u_,i' @ ns, geometry=ns.x, degree=degree*2)
  res += domain.boundary['top'].integral('basis_n fx fy' @ ns, geometry=ns.x, degree=degree*2)

  # construct dirichlet constraints
  sqr = domain.boundary['left'].integral('u^2' @ ns, geometry=ns.x, degree=degree*2)
  sqr += domain.boundary['bottom'].integral('(u - fx)^2' @ ns, geometry=ns.x, degree=degree*2)
  cons = solver.optimize('lhs', sqr, droptol=1e-15)

  # find lhs such that res == 0 and substitute this lhs in the namespace
  lhs = solver.solve_linear('lhs', res, constrain=cons)
  ns = ns(lhs=lhs)

  # plot solution
  if figures:
    points, colors = domain.elem_eval([ns.x, ns.u], ischeme='bezier9', separate=True)
    with plot.PyPlot('solution', index=nelems) as plt:
      plt.mesh(points, colors, cmap='jet')
      plt.colorbar()

  # evaluate error against exact solution fx fy
  err = domain.integrate('(u - fx fy)^2' @ ns, geometry=ns.x, degree=degree*2)**.5
  log.user('L2 error: {:.2e}'.format(err))

  return cons, lhs, err
Exemplo n.º 23
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,
    withplots: 'create plots' = 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 |= dict(lhs=lhs)

    # post-processing
    if withplots:
        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
Exemplo n.º 24
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,
    withplots: 'create plots' = True,
):

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

    #Define the control points and control point weights
    controlpoints = numpy.array([[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]])
    weights = numpy.array(
        [1, .5 + .5 / 2**.5, .5 + .5 / 2**.5, 1, 1, 1, 1, 1, 1, 1, 1, 1])

    #Create the second-order B-spline basis over the coarsest domain
    bsplinebasis = domain.basis('spline', degree=2)

    #Create the NURBS basis
    weightfunc = bsplinebasis.dot(weights)
    nurbsbasis = (bsplinebasis * weights) / weightfunc

    #Create the isogeometric map
    geometry = (nurbsbasis[:, _] * controlpoints).sum(0)

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

    #Create the B-spline basis
    bsplinebasis = domain.basis('spline', degree=2)

    #Create the NURBS basis
    weights = domain.project(weightfunc,
                             onto=bsplinebasis,
                             geometry=geometry,
                             ischeme='gauss9')
    nurbsbasis = (bsplinebasis * weights) / weightfunc

    #Create the displacement field basis
    ubasis = nurbsbasis.vector(2)

    #Define the plane stress function
    stress = library.Hooke(lmbda=E * nu / (1 - nu**2), mu=.5 * E / (1 + nu))

    #Get the exact solution
    uexact = exact_solution(geometry, T, R, E, nu)
    sigmaexact = stress(uexact.symgrad(geometry))

    #Define the linear and bilinear forms
    mat_func = function.outer(ubasis.symgrad(geometry),
                              stress(ubasis.symgrad(geometry))).sum([2, 3])
    rhs_func = (ubasis * sigmaexact.dotnorm(geometry)).sum(-1)

    #Compute the matrix and rhs
    mat = domain.integrate(mat_func, geometry=geometry, ischeme='gauss9')
    rhs = domain.boundary['right'].integrate(rhs_func,
                                             geometry=geometry,
                                             ischeme='gauss9')

    #Compute the constraints vector for the symmetry conditions
    cons = domain.boundary['top,bottom'].project(0,
                                                 onto=ubasis.dotnorm(geometry),
                                                 geometry=geometry,
                                                 ischeme='gauss9')

    #Solve the system of equations
    sol = mat.solve(rhs=rhs, constrain=cons)

    #Compute the approximate displacement and stress functions
    u = ubasis.dot(sol)
    sigma = stress(u.symgrad(geometry))

    #Post-processing
    if withplots:
        points, colors = domain.simplex.elem_eval([geometry, sigma[0, 0]],
                                                  ischeme='bezier8',
                                                  separate=True)
        with plot.PyPlot('solution', index=nr) as plt:
            plt.mesh(points, colors)
            plt.colorbar()

    #Compute the L2-norm of the error in the stress
    err = numpy.sqrt(
        domain.integrate(
            ((sigma - sigmaexact) * (sigma - sigmaexact)).sum([0, 1]),
            geometry=geometry,
            ischeme='gauss9'))

    #Compute the mesh parameter (maximum physical distance between diagonally opposite knot locations)
    hmax = numpy.max([
        max(numpy.linalg.norm(verts[0] - verts[3]),
            numpy.linalg.norm(verts[1] - verts[2])) for verts in
        domain.elem_eval(geometry, ischeme='bezier2', separate=True)
    ])

    return err, hmax
Exemplo n.º 25
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,
    withplots: 'create plots' = True,
  ):

  uinf = numpy.array([ 1, 0 ])
  log.user( 'reynolds number:', density/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, gridgeom = mesh.rectilinear( [range(melems+1),numpy.linspace(0,2*numpy.pi,2*nelems+1)], periodic=(1,) )
  rho, phi = gridgeom
  phi += 1e-3 # tiny nudge (0.057 deg) to break element symmetry
  cylvelo = -.5 * rotation * function.trignormal(phi)
  radius = .5 * function.exp( rscale * rho )
  geom = radius * function.trigtangent(phi)

  # prepare bases
  J = geom.grad( gridgeom )
  detJ = function.determinant( J )
  vnbasis, vtbasis, pbasis = function.chain([ # compatible spaces using piola transformation
    domain.basis( 'spline', degree=(3,2), removedofs=((0,),None) )[:,_] * J[:,0] / detJ,
    domain.basis( 'spline', degree=(2,3) )[:,_] * J[:,1] / detJ,
    domain.basis( 'spline', degree=2 ) / detJ,
  ])
  vbasis = vnbasis + vtbasis
  stressbasis = (2*viscosity) * vbasis.symgrad(geom) - pbasis[:,_,_] * function.eye( domain.ndims )

  # prepare matrices
  A = function.outer( vbasis.grad(geom), stressbasis ).sum([2,3]) + function.outer( pbasis, vbasis.div(geom) )
  Ao = function.outer( vbasis, density * ( vbasis.grad(geom) * uinf ).sum(-1) ).sum(-1)
  At = (density/timestep) * function.outer( vbasis ).sum(-1)
  Ad = function.outer( vbasis.div(geom) )
  stokesmat, uniconvec, inertmat, divmat = domain.integrate( [ A, Ao, At, Ad ], geometry=geom, ischeme='gauss9' )

  # interior boundary condition (weak imposition of shear verlocity component)
  inner = domain.boundary['left']
  h = inner.elem_eval( 1, geometry=geom, ischeme='gauss9', asfunction=True )
  nietzsche = (2*viscosity) * ( (7.5/h) * vbasis - vbasis.symgrad(geom).dotnorm(geom) )
  B = function.outer( nietzsche, vbasis ).sum(-1)
  b = ( nietzsche * cylvelo ).sum(-1)
  bcondmat, rhs = inner.integrate( [ B, b ], geometry=geom, ischeme='gauss9' )
  stokesmat += bcondmat

  # exterior boundary condition (full velocity vector imposed at inflow)
  inflow = domain.boundary['right'].select( -( uinf * geom.normal() ).sum(-1), ischeme='gauss1' )
  cons = inflow.project( uinf, onto=vbasis, geometry=geom, ischeme='gauss9', tol=1e-12 )

  # initial condition (stationary oseen flow)
  lhs = (stokesmat+uniconvec).solve( rhs, constrain=cons, tol=0 )

  # prepare plotting
  if not withplots:
    makeplots = lambda *args: None
  else:
    makeplots = MakePlots( domain, geom, video=withplots=='video', timestep=timestep )
    mesh_ = domain.elem_eval( geom, ischeme='bezier5', separate=True )
    inflow_ = inflow.elem_eval( geom, ischeme='bezier5', separate=True )
    with plot.PyPlot( 'mesh', ndigits=0 ) as plt:
      plt.mesh( mesh_ )
      plt.rectangle( makeplots.bbox[:,0], *( makeplots.bbox[:,1] - makeplots.bbox[:,0] ), ec='green' )
      plt.segments( inflow_, colors='red' )

  # start time stepping
  stokesmat += inertmat
  precon = (stokesmat+uniconvec).getprecon( 'splu', constrain=cons )
  for istep in log.count( 'timestep', start=1 ):
    log.info( 'velocity divergence:', divmat.matvec(lhs).dot(lhs) )
    convection = density * ( vbasis.grad(geom) * vbasis.dot(lhs) ).sum(-1)
    matrix = stokesmat + domain.integrate( function.outer( vbasis, convection ).sum(-1), ischeme='gauss9', geometry=geom )
    lhs = matrix.solve( rhs + inertmat.matvec(lhs), lhs0=lhs, constrain=cons, tol=tol, restart=9999, precon=precon )
    makeplots( vbasis.dot(lhs), pbasis.dot(lhs), istep*timestep*rotation )
    if istep*timestep > tmax:
      break

  return lhs