Example #1
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)
def newton(f, x0, maxiter, restol, lintol):
    '''find x such that f(x) = 0, starting at x0'''

    for i in log.range('newton', maxiter + 1):
        if i > 0:
            # solve system linearised around `x`, solution in `direction`
            J = f(x, jacobian=True)
            direction = -J.solve(residual, tol=lintol)
            xprev = x
            residual_norm_prev = residual_norm
            # line search, stop if there is convergence w.r.t. iteration `i-1`
            for j in range(4):
                x = xprev + (0.5)**j * direction
                residual = f(x)
                residual_norm = numpy.linalg.norm(residual, 2)
                if residual_norm < residual_norm_prev:
                    break
                # else: no convergence, repeat and reduce step size by one half
            else:
                log.warning('divergence')
        else:
            # before first iteration, compute initial residual
            x = x0
            residual = f(x)
            residual_norm = numpy.linalg.norm(residual, 2)
        log.info('residual norm: {:.5e}'.format(residual_norm))
        if residual_norm < restol:
            break
    else:
        raise ValueError(
            'newton did not converge in {} iterations'.format(maxiter))
    return x
Example #3
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)
Example #4
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)
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')
Example #6
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) 
Example #7
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=%f' % mineps)
        epsilon = mineps
    elif epsilon < mineps:
        log.warning('epsilon under crititical threshold: %f < %f' %
                    (epsilon, mineps))

    ewall = .5 * numpy.cos(theta * numpy.pi / 180)

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

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

    # define mixing energy and splitting: F' = f_p - f_n
    F = lambda c_: (.5 / epsilon**2) * (c_**2 - 1)**2
    f_p = lambda c_: (1. / epsilon**2) * 4 * c_
    f_n = lambda c_: (1. / epsilon**2) * (6 * c_ - 2 * c_**3)

    # prepare matrix
    A = function.outer( cbasis ) \
      + (timestep*epsilon**2) * function.outer( cbasis.grad(geom), mubasis.grad(geom) ).sum(-1) \
      + function.outer( mubasis, mubasis - f_p(cbasis) ) \
      - function.outer( mubasis.grad(geom), cbasis.grad(geom) ).sum(-1)
    matrix = domain.integrate(A, geometry=geom, ischeme='gauss4')

    # prepare wall energy right hand side
    rhs0 = domain.boundary.integrate(mubasis * ewall,
                                     geometry=geom,
                                     ischeme='gauss4')

    # construct initial condition
    if init == 'random':
        numpy.random.seed(0)
        c = cbasis.dot(numpy.random.normal(0, .5, cbasis.shape))
    elif init == 'bubbles':
        R1 = .25
        R2 = numpy.sqrt(.5) * R1  # area2 = .5 * area1
        c = 1 + function.tanh( (R1-function.norm2(geom-(.5+R2/numpy.sqrt(2)+.8*epsilon)))/epsilon ) \
              + function.tanh( (R2-function.norm2(geom-(.5-R1/numpy.sqrt(2)-.8*epsilon)))/epsilon )
    else:
        raise Exception('unknown init %r' % init)

    # prepare plotting
    nsteps = numeric.round(maxtime / timestep)
    makeplots = MakePlots(domain, geom, nsteps, video=withplots
                          == 'video') if withplots else lambda *args: None

    # start time stepping
    for istep in log.range('timestep', nsteps):

        Emix = F(c)
        Eiface = .5 * (c.grad(geom)**2).sum(-1)
        Ewall = (abs(ewall) + ewall * c)

        b = cbasis * c - mubasis * f_n(c)
        rhs, total, energy_mix, energy_iface = domain.integrate(
            [b, c, Emix, Eiface], geometry=geom, ischeme='gauss4')
        energy_wall = domain.boundary.integrate(Ewall,
                                                geometry=geom,
                                                ischeme='gauss4')
        log.user('concentration {}, energy {}'.format(
            total, energy_mix + energy_iface + energy_wall))

        lhs = matrix.solve(rhs0 + rhs, tol=1e-12, restart=999)
        c = cbasis.dot(lhs)
        mu = mubasis.dot(lhs)

        makeplots(c, mu, energy_mix, energy_iface, energy_wall)

    return lhs, energy_mix, energy_iface, energy_wall