Example #1
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)
Example #2
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
Example #3
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
Example #4
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)
Example #5
0
def rotmat(angle):
    return fn.asarray([
        [fn.cos(angle), -fn.sin(angle)],
        [fn.sin(angle), fn.cos(angle)],
    ])
Example #6
0
def main(etype: str, btype: str, degree: int, nrefine: int):
    '''
  Adaptively refined Laplace problem on an L-shaped domain.

  .. arguments::

     etype [square]
       Type of elements (square/triangle/mixed).
     btype [h-std]
       Type of basis function (h/th-std/spline), with availability depending on
       the configured element type.
     degree [2]
       Polynomial degree
     nrefine [5]
       Number of refinement steps to perform.
  '''

    domain, geom = mesh.unitsquare(2, etype)

    x, y = geom - .5
    exact = (x**2 + y**2)**(1 / 3) * function.cos(
        function.arctan2(y + x, y - x) * (2 / 3))
    domain = domain.trim(exact - 1e-15, maxrefine=0)
    linreg = util.linear_regressor()

    with treelog.iter.fraction('level', range(nrefine + 1)) as lrange:
        for irefine in lrange:

            if irefine:
                refdom = domain.refined
                ns.refbasis = refdom.basis(btype, degree=degree)
                indicator = refdom.integral(
                    'd(refbasis_n, x_k) d(u, x_k) J(x)' @ ns,
                    degree=degree * 2).eval(lhs=lhs)
                indicator -= refdom.boundary.integral(
                    'refbasis_n d(u, x_k) n(x_k) J(x)' @ ns,
                    degree=degree * 2).eval(lhs=lhs)
                supp = ns.refbasis.get_support(
                    indicator**2 > numpy.mean(indicator**2))
                domain = domain.refined_by(refdom.transforms[supp])

            ns = function.Namespace()
            ns.x = geom
            ns.basis = domain.basis(btype, degree=degree)
            ns.u = 'basis_n ?lhs_n'
            ns.du = ns.u - exact

            sqr = domain.boundary['trimmed'].integral('u^2 J(x)' @ ns,
                                                      degree=degree * 2)
            cons = solver.optimize('lhs', sqr, droptol=1e-15)

            sqr = domain.boundary.integral('du^2 J(x)' @ ns, degree=7)
            cons = solver.optimize('lhs', sqr, droptol=1e-15, constrain=cons)

            res = domain.integral('d(basis_n, x_k) d(u, x_k) J(x)' @ ns,
                                  degree=degree * 2)
            lhs = solver.solve_linear('lhs', res, constrain=cons)

            ndofs = len(ns.basis)
            error = domain.integral('<du^2, sum:k(d(du, x_k)^2)>_i J(x)' @ ns,
                                    degree=7).eval(lhs=lhs)**.5
            rate, offset = linreg.add(numpy.log(len(ns.basis)),
                                      numpy.log(error))
            treelog.user(
                'ndofs: {ndofs}, L2 error: {error[0]:.2e} ({rate[0]:.2f}), H1 error: {error[1]:.2e} ({rate[1]:.2f})'
                .format(ndofs=len(ns.basis), error=error, rate=rate))

            bezier = domain.sample('bezier', 9)
            x, u, du = bezier.eval(['x', 'u', 'du'] @ ns, lhs=lhs)
            export.triplot('sol.png', x, u, tri=bezier.tri, hull=bezier.hull)
            export.triplot('err.png', x, du, tri=bezier.tri, hull=bezier.hull)

    return ndofs, error, lhs
Example #7
0
def main(nelems: int, etype: str, btype: str, degree: int,
         epsilon: typing.Optional[float], contactangle: float, timestep: float,
         mtol: float, seed: int, circle: bool, stab: stab):
    '''
  Cahn-Hilliard equation on a unit square/circle.

  .. arguments::

     nelems [20]
       Number of elements along domain edge.
     etype [square]
       Type of elements (square/triangle/mixed).
     btype [std]
       Type of basis function (std/spline), with availability depending on the
       configured element type.
     degree [2]
       Polynomial degree.
     epsilon []
       Interface thickness; defaults to an automatic value based on the
       configured mesh density if left unspecified.
     contactangle [90]
       Wall contact angle in degrees.
     timestep [.01]
       Time step.
     mtol [.01]
       Threshold value for chemical potential peak to peak difference, used as
       a stop criterion.
     seed [0]
       Random seed for the initial condition.
     circle [no]
       Select circular domain as opposed to a unit square.
     stab [linear]
       Stabilization method (linear/optimal/none).
  '''

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

    domain, geom = mesh.unitsquare(nelems, etype)
    bezier = domain.sample('bezier', 5)  # sample for plotting

    ns = function.Namespace()
    if not circle:
        ns.x = geom
    else:
        angle = (geom - .5) * (numpy.pi / 2)
        ns.x = function.sin(angle) * function.cos(angle)[[1, 0
                                                          ]] / numpy.sqrt(2)
    ns.epsilon = epsilon
    ns.ewall = .5 * numpy.cos(contactangle * numpy.pi / 180)
    ns.cbasis = ns.mbasis = domain.basis('std', degree=degree)
    ns.c = 'cbasis_n ?c_n'
    ns.dc = 'cbasis_n (?c_n - ?c0_n)'
    ns.m = 'mbasis_n ?m_n'
    ns.F = '.5 (c^2 - 1)^2 / epsilon^2'
    ns.dF = stab.value
    ns.dt = timestep

    nrg_mix = domain.integral('F J(x)' @ ns, degree=7)
    nrg_iface = domain.integral('.5 sum:k(d(c, x_k)^2) J(x)' @ ns, degree=7)
    nrg_wall = domain.boundary.integral('(abs(ewall) + c ewall) J(x)' @ ns,
                                        degree=7)
    nrg = nrg_mix + nrg_iface + nrg_wall + domain.integral(
        '(dF - m dc - .5 dt epsilon^2 sum:k(d(m, x_k)^2)) J(x)' @ ns, degree=7)

    numpy.random.seed(seed)
    state = dict(c=numpy.random.normal(0, .5, ns.cbasis.shape),
                 m=numpy.random.normal(0, .5,
                                       ns.mbasis.shape))  # initial condition

    with treelog.iter.plain('timestep', itertools.count()) as steps:
        for istep in steps:

            E = sample.eval_integrals(nrg_mix, nrg_iface, nrg_wall, **state)
            treelog.user(
                'energy: {0:.3f} ({1[0]:.0f}% mixture, {1[1]:.0f}% interface, {1[2]:.0f}% wall)'
                .format(sum(E), 100 * numpy.array(E) / sum(E)))

            x, c, m = bezier.eval(['x', 'c', 'm'] @ ns, **state)
            export.triplot('phase.png', x, c, tri=bezier.tri, clim=(-1, 1))
            export.triplot('chempot.png', x, m, tri=bezier.tri)

            if numpy.ptp(m) < mtol:
                break

            state['c0'] = state['c']
            state = solver.optimize(['c', 'm'],
                                    nrg,
                                    arguments=state,
                                    tol=1e-10)

    return state