Exemplo n.º 1
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)
Exemplo n.º 2
0
def _plot(suffix,
          name='solution',
          figsize=(10, 10),
          index=None,
          mesh=None,
          xlim=None,
          ylim=None,
          axes=True,
          show=False,
          segments=None,
          ndigits=4,
          **kwargs):
    if ndigits is None:
        ndigits = 0 if index is None else 4
    filename = f'{name}-{suffix}'
    if index:
        filename += f'-{index:0{ndigits}}'
    filename += '.png'
    with export.mplfigure(filename, figsize=figsize) as fig:
        ax = fig.add_subplot(111)
        yield (fig, ax)
        if mesh is not None:
            collection = LineCollection(mesh,
                                        colors='black',
                                        linewidth=0.1,
                                        alpha=1.0)
            ax.add_collection(collection)
        ax.set_aspect('equal')
        ax.autoscale(enable=True, axis='both', tight=True)
        if xlim: ax.set_xlim(*xlim)
        if ylim: ax.set_ylim(*ylim)
        if not axes:
            ax.axis('off')
        if show: plt.show()
def postprocess(domain, ns, every=.05, spacing=.01, **arguments):

  div = domain.integral('d(u_k, x_k)^2 J(x)' @ ns, degree=1).eval(**arguments)**.5
  treelog.info('velocity divergence: {:.2e}'.format(div)) # confirm that velocity is pointwise divergence-free

  ns = ns.copy_() # copy namespace so that we don't modify the calling argument
  ns.streambasis = domain.basis('std', degree=2)[1:] # remove first dof to obtain non-singular system
  ns.stream = 'streambasis_n ?streamdofs_n' # stream function
  ns.ε = function.levicivita(2)
  sqr = domain.integral('sum:i((u_i - ε_ij d(stream, x_j))^2) J(x)' @ ns, degree=4)
  arguments['streamdofs'] = solver.optimize('streamdofs', sqr, arguments=arguments) # compute streamlines

  bezier = domain.sample('bezier', 9)
  x, u, p, stream = bezier.eval(['x', 'norm2(u)', 'p', 'stream'] @ ns, **arguments)
  with export.mplfigure('flow.png') as fig: # plot velocity as field, pressure as contours, streamlines as dashed
    ax = fig.add_axes([.1,.1,.8,.8], yticks=[], aspect='equal')
    import matplotlib.collections
    ax.add_collection(matplotlib.collections.LineCollection(x[bezier.hull], colors='w', linewidths=.5, alpha=.2))
    ax.tricontour(x[:,0], x[:,1], bezier.tri, stream, 16, colors='k', linestyles='dotted', linewidths=.5, zorder=9)
    caxu = fig.add_axes([.1,.1,.03,.8], title='velocity')
    imu = ax.tripcolor(x[:,0], x[:,1], bezier.tri, u, shading='gouraud', cmap='jet')
    fig.colorbar(imu, cax=caxu)
    caxu.yaxis.set_ticks_position('left')
    caxp = fig.add_axes([.87,.1,.03,.8], title='pressure')
    imp = ax.tricontour(x[:,0], x[:,1], bezier.tri, p, 16, cmap='gray', linestyles='solid')
    fig.colorbar(imp, cax=caxp)
Exemplo n.º 4
0
def plotbuildup_1D(ns, bezier, x, p, TT, endtime, t2):
    """ Exports figures to public.html for the pressure and temperature 1D radial profile along the reservoir

    Arguments:
    ns (?):           Namespace
    bezier (?):       Parametric curve
    x (array):        Radial position
    p (array):        Fluid pressure
    T (array):        System (Solid + Fluid) temperature
    endtime (float):  Time that drawdown period ended
    t2 (float):       Time of buildup period

    Returns:
    pressure1d (png):    graph of 1D radial pressure
    temperature1d (png): graph of 1D radial temperature
    """

    with export.mplfigure('pressure1d.png', dpi=800) as plt:
        ax = plt.subplots()
        ax.set(xlabel='Distance [m]', ylabel='Pressure [MPa]')
        ax.plot(nanjoin(x[:, 0], bezier.tri)[::100],
                nanjoin(p, bezier.tri)[::100] / 1e6,
                label="FEM")
        ax.plot(x[:, 0][::100],
                np.array(panalyticalbuildup(ns, endtime, t2,
                                            x[:, 0]))[0][0][0][::100] / 1e6,
                label="analytical")
        ax.legend(loc="center right")

    with export.mplfigure('temperature1d.png', dpi=800) as plt:
        ax = plt.subplots()
        ax.set(xlabel='Distance [m]', ylabel='Temperature [K]')
        # ax.set_ylim([362.85, 363.02])
        ax.plot(nanjoin(x[:, 0], bezier.tri)[0:100000:10],
                nanjoin(TT, bezier.tri)[0:100000:10],
                label="FEM")
        ax.plot(nanjoin(x[:, 0], bezier.tri)[0:100000:10],
                np.array(
                    Tanalyticalbuildup(
                        ns, endtime, t2,
                        nanjoin(x[:, 0], bezier.tri)[0:100000:10]))[0][0][0],
                label="analytical")
        ax.legend(loc="center right")
Exemplo n.º 5
0
def postprocess(domain, ns, every=.05, spacing=.01, **arguments):

    ns = ns.copy_(
    )  # copy namespace so that we don't modify the calling argument
    ns.streambasis = domain.basis(
        'std', degree=2)[1:]  # remove first dof to obtain non-singular system
    ns.stream = 'streambasis_n ?streamdofs_n'  # stream function
    sqr = domain.integral(
        '((u_0 - stream_,1)^2 + (u_1 + stream_,0)^2) d:x' @ ns, degree=4)
    arguments['streamdofs'] = solver.optimize(
        'streamdofs', sqr, arguments=arguments)  # compute streamlines

    bezier = domain.sample('bezier', 9)
    x, u, p, stream = bezier.eval(['x_i', 'sqrt(u_k u_k)', 'p', 'stream'] @ ns,
                                  **arguments)
    with export.mplfigure(
            'flow.png'
    ) as fig:  # plot velocity as field, pressure as contours, streamlines as dashed
        ax = fig.add_axes([.1, .1, .8, .8], yticks=[], aspect='equal')
        import matplotlib.collections
        ax.add_collection(
            matplotlib.collections.LineCollection(x[bezier.hull],
                                                  colors='w',
                                                  linewidths=.5,
                                                  alpha=.2))
        ax.tricontour(x[:, 0],
                      x[:, 1],
                      bezier.tri,
                      stream,
                      16,
                      colors='k',
                      linestyles='dotted',
                      linewidths=.5,
                      zorder=9)
        caxu = fig.add_axes([.1, .1, .03, .8], title='velocity')
        imu = ax.tripcolor(x[:, 0],
                           x[:, 1],
                           bezier.tri,
                           u,
                           shading='gouraud',
                           cmap='jet')
        fig.colorbar(imu, cax=caxu)
        caxu.yaxis.set_ticks_position('left')
        caxp = fig.add_axes([.87, .1, .03, .8], title='pressure')
        imp = ax.tricontour(x[:, 0],
                            x[:, 1],
                            bezier.tri,
                            p,
                            16,
                            cmap='gray',
                            linestyles='solid')
        fig.colorbar(imp, cax=caxp)
Exemplo n.º 6
0
def plotovertime(timeperiod, parraywell, parrayexact, Tarraywell, Tarrayexact,
                 Qarray):
    with export.mplfigure('pressuretime.png', dpi=800) as plt:
        ax1 = plt.subplots()
        ax2 = ax1.twinx()
        ax1.set(xlabel='Time [s]')
        ax1.set_ylabel('Pressure [MPa]', color='b')
        ax2.set_ylabel('Volumetric flow rate [m^3/s]', color='k')
        ax1.plot(timeperiod, parraywell / 1e6, 'bo', label="FEM")
        ax1.plot(timeperiod, parrayexact / 1e6, label="analytical")
        # ax1.plot(timeperiod, parrayexp, label="NLOG")
        ax1.legend(loc="center right")
        ax2.plot(timeperiod, Qarray, 'k')

        # with export.mplfigure('pressuretimeerror.png', dpi=800) as plt:
        #     ax1 = plt.subplots()
        #     ax2 = ax1.twinx()
        #     ax1.set(xlabel='Time [s]')
        #     ax1.set(ylabel=r'$\left(\left|p_{w}-{p}_{w,exact}\right|/\left|p_{w,0}\right|\right)$', yscale="log")
        #     ax2.set_ylabel('Volumetric flow rate [m^3/s]', color='k')
        #     ax1.plot(timeperiod, parrayerror / 225e5, 'bo', label=r'$r_{dr} = 1000m$ refined mesh')
        #     ax1.set_ylim(ymin=0.00005)
        #     ax1.legend(loc="center right")
        #     ax2.plot(timeperiod, Qarray, 'k')

    with export.mplfigure('temperaturetime.png', dpi=800) as plt:
        ax1 = plt.subplots()
        ax2 = ax1.twinx()
        # ax1.set_ylim([362.9, 363.1])
        ax1.set(xlabel='Time [s]')
        ax1.set_ylabel('Temperature [K]', color='b')
        ax2.set_ylabel('Volumetric flow rate [m^3/s]', color='k')
        ax1.plot(timeperiod, Tarraywell, 'ro', label="FEM")
        ax1.plot(timeperiod, Tarrayexact, label="analytical")
        ax1.legend(loc="center right")
        ax2.plot(timeperiod, Qarray, 'k')
Exemplo n.º 7
0
 def test_autodetect_imagetype(self):
     for (imagetype, test) in (
         ('jpg', lambda data: self.assertEqual(data[:3], b'\xFF\xD8\xFF')),
         ('png', lambda data: self.assertEqual(
             data[:8], b'\x89\x50\x4E\x47\x0D\x0A\x1A\x0A')),
         ('pdf',
          lambda data: self.assertEqual(data[:4], b'\x25\x50\x44\x46')),
         ('svg', lambda data: self.assertRegex(data, b'<svg[^<>]*>'))):
         with self.subTest(imagetype=imagetype):
             with export.mplfigure('test.{}'.format(imagetype)) as fig:
                 ax = fig.add_subplot(111)
                 ax.plot([1, 2, 3], [1, 2, 3])
             with (self.outdir /
                   'test.{}'.format(imagetype)).open('rb') as f:
                 test(f.read())
Exemplo n.º 8
0
def main(nelems: int, degree: int, reynolds: float, rotation: float,
         timestep: float, maxradius: float, seed: int, endtime: float):
    '''
  Flow around a cylinder.

  .. arguments::

     nelems [24]
       Element size expressed in number of elements along the cylinder wall.
       All elements have similar shape with approximately unit aspect ratio,
       with elements away from the cylinder wall growing exponentially.
     degree [3]
       Polynomial degree for velocity space; the pressure space is one degree
       less.
     reynolds [1000]
       Reynolds number, taking the cylinder radius as characteristic length.
     rotation [0]
       Cylinder rotation speed.
     timestep [.04]
       Time step
     maxradius [25]
       Target exterior radius; the actual domain size is subject to integer
       multiples of the configured element size.
     seed [0]
       Random seed for small velocity noise in the intial condition.
     endtime [inf]
       Stopping time.
  '''

    elemangle = 2 * numpy.pi / nelems
    melems = int(numpy.log(2 * maxradius) / elemangle + .5)
    treelog.info('creating {}x{} mesh, outer radius {:.2f}'.format(
        melems, nelems, .5 * numpy.exp(elemangle * melems)))
    domain, geom = mesh.rectilinear([melems, nelems], periodic=(1, ))
    domain = domain.withboundary(inner='left', outer='right')

    ns = function.Namespace()
    ns.uinf = 1, 0
    ns.r = .5 * function.exp(elemangle * geom[0])
    ns.Re = reynolds
    ns.phi = geom[1] * elemangle  # add small angle to break element symmetry
    ns.x_i = 'r <cos(phi), sin(phi)>_i'
    ns.J = ns.x.grad(geom)
    ns.unbasis, ns.utbasis, ns.pbasis = function.chain([  # compatible spaces
        domain.basis(
            'spline', degree=(degree, degree - 1), removedofs=((0, ), None)),
        domain.basis('spline', degree=(degree - 1, degree)),
        domain.basis('spline', degree=degree - 1),
    ]) / function.determinant(ns.J)
    ns.ubasis_ni = 'unbasis_n J_i0 + utbasis_n J_i1'  # piola transformation
    ns.u_i = 'ubasis_ni ?lhs_n'
    ns.p = 'pbasis_n ?lhs_n'
    ns.sigma_ij = '(u_i,j + u_j,i) / Re - p δ_ij'
    ns.h = .5 * elemangle
    ns.N = 5 * degree / ns.h
    ns.rotation = rotation
    ns.uwall_i = '0.5 rotation <-sin(phi), cos(phi)>_i'

    inflow = domain.boundary['outer'].select(
        -ns.uinf.dotnorm(ns.x),
        ischeme='gauss1')  # upstream half of the exterior boundary
    sqr = inflow.integral('(u_i - uinf_i) (u_i - uinf_i)' @ ns,
                          degree=degree * 2)
    cons = solver.optimize(
        'lhs', sqr, droptol=1e-15)  # constrain inflow semicircle to uinf

    sqr = domain.integral('(u_i - uinf_i) (u_i - uinf_i) + p^2' @ ns,
                          degree=degree * 2)
    lhs0 = solver.optimize('lhs', sqr)  # set initial condition to u=uinf, p=0

    numpy.random.seed(seed)
    lhs0 *= numpy.random.normal(1, .1, lhs0.shape)  # add small velocity noise

    res = domain.integral(
        '(ubasis_ni u_i,j u_j + ubasis_ni,j sigma_ij + pbasis_n u_k,k) d:x'
        @ ns,
        degree=9)
    res += domain.boundary['inner'].integral(
        '(N ubasis_ni - (ubasis_ni,j + ubasis_nj,i) n_j) (u_i - uwall_i) d:x / Re'
        @ ns,
        degree=9)
    inertia = domain.integral('ubasis_ni u_i d:x' @ ns, degree=9)

    bbox = numpy.array(
        [[-2, 46 / 9],
         [-2, 2]])  # bounding box for figure based on 16x9 aspect ratio
    bezier0 = domain.sample('bezier', 5)
    bezier = bezier0.subset((bezier0.eval(
        (ns.x - bbox[:, 0]) * (bbox[:, 1] - ns.x)) > 0).all(axis=1))
    interpolate = util.tri_interpolator(
        bezier.tri, bezier.eval(ns.x),
        mergetol=1e-5)  # interpolator for quivers
    spacing = .05  # initial quiver spacing
    xgrd = util.regularize(bbox, spacing)

    with treelog.iter.plain(
            'timestep',
            solver.impliciteuler('lhs',
                                 residual=res,
                                 inertia=inertia,
                                 lhs0=lhs0,
                                 timestep=timestep,
                                 constrain=cons,
                                 newtontol=1e-10)) as steps:
        for istep, lhs in enumerate(steps):

            t = istep * timestep
            x, u, normu, p = bezier.eval(
                ['x_i', 'u_i', 'sqrt(u_k u_k)', 'p'] @ ns, lhs=lhs)
            ugrd = interpolate[xgrd](u)

            with export.mplfigure('flow.png', figsize=(12.8, 7.2)) as fig:
                ax = fig.add_axes([0, 0, 1, 1],
                                  yticks=[],
                                  xticks=[],
                                  frame_on=False,
                                  xlim=bbox[0],
                                  ylim=bbox[1])
                im = ax.tripcolor(x[:, 0],
                                  x[:, 1],
                                  bezier.tri,
                                  p,
                                  shading='gouraud',
                                  cmap='jet')
                import matplotlib.collections
                ax.add_collection(
                    matplotlib.collections.LineCollection(x[bezier.hull],
                                                          colors='k',
                                                          linewidths=.1,
                                                          alpha=.5))
                ax.quiver(xgrd[:, 0],
                          xgrd[:, 1],
                          ugrd[:, 0],
                          ugrd[:, 1],
                          angles='xy',
                          width=1e-3,
                          headwidth=3e3,
                          headlength=5e3,
                          headaxislength=2e3,
                          zorder=9,
                          alpha=.5)
                ax.plot(0,
                        0,
                        'k',
                        marker=(3, 2, t * rotation * 180 / numpy.pi - 90),
                        markersize=20)
                cax = fig.add_axes([0.9, 0.1, 0.01, 0.8])
                cax.tick_params(labelsize='large')
                fig.colorbar(im, cax=cax)

            if t >= endtime:
                break

            xgrd = util.regularize(bbox, spacing, xgrd + ugrd * timestep)

    return lhs0, lhs
Exemplo n.º 9
0
def main(fname: str, degree: int, Δuload: unit['mm'], nsteps: int, E: unit['GPa'], nu: float, σyield: unit['MPa'], hardening: unit['GPa'], referencedata: typing.Optional[str], testing: bool):

  '''
  Plastic deformation of a perforated strip.

  .. arguments::

     fname [strip.msh]
       Mesh file with units in [mm]

     degree [1]
       Finite element interpolation order

     Δuload [5μm]
       Load boundary displacement steps

     nsteps [11]
       Number of load steps

     E [70GPa]
       Young's modulus

     nu [0.2]
       Poisson ratio

     σyield [243MPa]
       Yield strength

     hardening [2.25GPa]
       Hardening parameter

     referencedata [zienkiewicz.csv]
       Reference data file name

     testing [False]
       Use a 1 element mesh for testing

  .. presets::

     testing
       nsteps=30
       referencedata=
       testing=True
  '''

  # We commence with reading the mesh from the specified GMSH file, or, alternatively,
  # we continue with a single-element mesh for testing purposes.
  domain, geom = mesh.gmsh(pathlib.Path(__file__).parent/fname)
  Wdomain, Hdomain = domain.boundary['load'].integrate([function.J(geom),geom[1]*function.J(geom)], degree=1)
  Hdomain /= Wdomain

  if testing:
    domain, geom = mesh.rectilinear([numpy.linspace(0,Wdomain/2,2),numpy.linspace(0,Hdomain,2)])
    domain = domain.withboundary(hsymmetry='left', vsymmetry='bottom', load='top')

  # We next initiate the point set in which the constitutive bahvior will be evaluated.
  # Note that this is also the point set in which the history variable will be stored.
  gauss  = domain.sample('gauss', 2)

  # Elasto-plastic formulation
  # ==========================
  # The weak formulation is constructed using a `Namespace`, which is initialized and
  # populated with the necessary problem parameters and coordinate system. Note that the
  # coefficients `mu` and `λ` have been defined such that 'C_{ijkl}' is the fourth-order
  # **plane stress** elasticity tensor.

  ns = function.Namespace(fallback_length=domain.ndims)

  ns.x      = geom
  ns.Δuload = Δuload
  ns.mu     = E/(1-nu**2)*((1-nu)/2)
  ns.λ      = E/(1-nu**2)*nu
  ns.delta  = function.eye(domain.ndims)
  ns.C_ijkl = 'mu ( delta_ik delta_jl + delta_il delta_jk ) + λ delta_ij delta_kl'

  # We make use of a Lagrange finite element basis of arbitrary `degree`. Since we
  # approximate the displacement field, the basis functions are vector-valued. Both
  # the displacement field at the current load step `u` and displacement field of the
  # previous load step `u0` are approximated using this basis:

  ns.basis = domain.basis('std',degree=degree).vector(domain.ndims)

  ns.u0_i = 'basis_ni ?lhs0_n'
  ns.u_i  = 'basis_ni ?lhs_n'

  # This simulation is based on a standard elasto-plasticity model. In this
  # model the *total strain*, ε_kl = ½ (∂u_k/∂x_l + ∂u_l/∂x_k)', is comprised of an
  # elastic and a plastic part:
  #
  #   ε_kl = εe_kl + εp_kl
  #
  # The stress is related to the *elastic strain*, εe_kl, through Hooke's law:
  #
  #   σ_ij = C_ijkl εe_kl = C_ijkl (ε_kl - εp_kl)

  ns.ε_kl   = '(u_k,l + u_l,k) / 2'
  ns.ε0_kl  = '(u0_k,l + u0_l,k) / 2'
  ns.gbasis = gauss.basis()
  ns.εp0_ij = 'gbasis_n ?εp0_nij'
  ns.κ0     = 'gbasis_n ?κ0_n'

  ns.εp    = PlasticStrain(ns.ε, ns.ε0, ns.εp0, ns.κ0, E, nu, σyield, hardening)
  ns.εe_ij = 'ε_ij - εp_ij'
  ns.σ_ij  = 'C_ijkl εe_kl'

  # Note that the plasticity model is implemented through the user-defined function `PlasticStrain`,
  # which implements the actual yielding model including a standard return mapping algorithm. This
  # function is discussed in detail below.
  #
  # The components of the residual vector are then defined as:
  #
  #   r_n = ∫_Ω (∂N_ni/∂x_j) σ_ij dΩ

  res = domain.integral('basis_ni,j σ_ij d:x' @ ns, degree=2)

  # The problem formulation is completed by supplementing prescribed displacement boundary conditions
  # (for a load step), which are computed in the standard manner:

  sqr  = domain.boundary['hsymmetry,vsymmetry'].integral('(u_k n_k)^2 d:x' @ ns, degree=2)
  sqr += domain.boundary['load'].integral('(u_k n_k - Δuload)^2 d:x' @ ns, degree=2)
  cons = solver.optimize('lhs', sqr, droptol=1e-15)

  # Incremental-iterative solution procedure
  # ========================================
  # We initialize the solution vector for the first load step `lhs` and solution vector
  # of the previous load step `lhs0`. Note that, in order to construct a predictor step
  # for the first load step, we define the previous load step state as the solution
  # vector corresponding to a negative elastic loading step.

  lhs0 = -solver.solve_linear('lhs', domain.integral('basis_ni,j C_ijkl ε_kl d:x' @ ns, degree=2), constrain=cons)
  lhs  = numpy.zeros_like(lhs0)
  εp0  = numpy.zeros((gauss.npoints,)+ns.εp0.shape)
  κ0   = numpy.zeros((gauss.npoints,)+ns.κ0.shape)

  # To store the force-dispalcement data we initialize an empty data array with the
  # inital state solution substituted in the first row.
  fddata      = numpy.empty(shape=(nsteps+1,2))
  fddata[:]   = numpy.nan
  fddata[0,:] = 0

  # Load step incrementation
  # ------------------------
  with treelog.iter.fraction('step', range(nsteps)) as counter:
    for step in counter:

      # The solution of the previous load step is set to `lhs0`, and the Newton solution
      # procedure is initialized by extrapolation of the state vector:
      lhs_init = lhs + (lhs-lhs0)
      lhs0     = lhs

      # The non-linear system of equations is solved for `lhs` using Newton iterations,
      # where the `step` variable is used to scale the incremental constraints.
      lhs = solver.newton(target='lhs', residual=res, constrain=cons*step, lhs0=lhs_init, arguments={'lhs0':lhs0,'εp0':εp0,'κ0':κ0}).solve(tol=1e-6)

      # The computed solution is post-processed in the form of a loading curve - which
      # plots the normalized mean stress versus the maximum 'ε_{yy}' strain
      # component - and a contour plot showing the 'σ_{yy}' stress component on a
      # deformed mesh. Note that since the stresses are defined in the integration points
      # only, a post-processing step is involved that transfers the stress information to
      # the nodal points.
      εyymax = gauss.eval(ns.ε[1,1], arguments=dict(lhs=lhs)).max()

      basis = domain.basis('std', degree=1)
      bw, b = domain.integrate([basis * ns.σ[1,1] * function.J(geom), basis * function.J(geom)], degree=2, arguments=dict(lhs=lhs,lhs0=lhs0,εp0=εp0,κ0=κ0))
      σyy = basis.dot(bw / b)

      uyload, σyyload = domain.boundary['load'].integrate(['u_1 d:x'@ns,σyy * function.J(geom)], degree=2, arguments=dict(lhs=lhs,εp0=εp0,κ0=κ0))
      uyload /= Wdomain
      σyyload /= Wdomain
      fddata[step,0] = (E*εyymax)/σyield
      fddata[step,1] = (σyyload*2)/σyield

      with export.mplfigure('forcedisp.png') as fig:
        ax = fig.add_subplot(111, xlabel=r'${E \cdot {\rm max}(\varepsilon_{yy})}/{\sigma_{\rm yield}}$', ylabel=r'${\sigma_{\rm mean}}/{\sigma_{\rm yield}}$')
        if referencedata:
          data = numpy.genfromtxt(pathlib.Path(__file__).parent/referencedata, delimiter=',', skip_header=1)
          ax.plot(data[:,0], data[:,1], 'r:', label='Reference')
          ax.legend()
        ax.plot(fddata[:,0], fddata[:,1], 'o-', label='Nutils')
        ax.grid()

      bezier = domain.sample('bezier', 3)
      points, uvals, σyyvals = bezier.eval(['(x_i + 25 u_i)' @ ns, ns.u, σyy], arguments=dict(lhs=lhs))
      with export.mplfigure('stress.png') as fig:
        ax = fig.add_subplot(111, aspect='equal', xlabel=r'$x$ [mm]', ylabel=r'$y$ [mm]')
        im = ax.tripcolor(points[:,0]/unit('mm'), points[:,1]/unit('mm'), bezier.tri, σyyvals/unit('MPa'), shading='gouraud', cmap='jet')
        ax.add_collection(collections.LineCollection(points.take(bezier.hull, axis=0), colors='k', linewidths=.1))
        ax.autoscale(enable=True, axis='both', tight=True)
        cb = fig.colorbar(im)
        im.set_clim(0, 1.2*σyield)
        cb.set_label(r'$σ_{yy}$ [MPa]')

      # Load step convergence
      # ---------------------
      # At the end of the loading step, the plastic strain state and history parameter are updated,
      # where use if made of the strain hardening relation for the history variable:
      #
      #   Δκ = √(Δεp_ij Δεp_ij)

      Δεp = ns.εp-ns.εp0
      Δκ  = function.sqrt((Δεp*Δεp).sum((0,1)))
      κ0  = gauss.eval(ns.κ0+Δκ, arguments=dict(lhs0=lhs0,lhs=lhs,εp0=εp0,κ0=κ0))
      εp0 = gauss.eval(ns.εp, arguments=dict(lhs0=lhs0,lhs=lhs,εp0=εp0,κ0=κ0))
Exemplo n.º 10
0
def main():

    # length = 1000
    # selems = [length/25,
    #           length/50,
    #           length/100,
    #           length/200,
    #           length/400,
    #           length/1000]
    # nelems = [2.5,
    #           5,
    #           10,
    #           20,
    #           40,
    #           100,
    #           200] #elements per 100m
    # print(selems)
    #
    # #t=600, L=1000
    # pFEA = [22086111.42748884,
    #         21902014.957589053,
    #         21726777.721221756,
    #         21562538.447041728, #dz = 5m
    #         21411662.357217178,
    #         21243415.78431648]
    # pEX = [20700173.2868534,
    #        20700173.2868534,
    #        20700173.2868534,
    #        20700173.2868534, #dz = 5m
    #        20700173.2868534,
    #        20700173.2868534]
    # print(pFEA, pEX)
    #
    # # t=600, L=250
    # pFEA2 = [22145699.217542585,
    #         (21912576.577329777+21891746.037332077)/2,
    #         21726704.23802078,  #dz = 10m
    #         21562470.026213087, #dz = 5m
    #         21411600.745572496, #dz = 2.5m
    #         21243475.78431648]  #dz = 1m
    #
    # pEX2 =  [20700173.2868534,
    #         20700173.2868534,
    #         20700173.2868534,
    #         20700173.2868534,   #dz = 5m
    #         20700173.2868534,   #dz = 2.5m
    #         20700173.2868534]   #dz = 1m
    #
    #
    #
    # pFEA2refined = [21135143.533079684,
    #                 21103572.526394643, #20m (5/100), (12.5 element op 250)
    #                 21068682.36205357, #10m (10/100), (25 elements)
    #                 21055465.52883131] #1m (100/100m), (250elements op L=250)
    # nelemsrefined = [2.5,
    #                  5,
    #                  10,
    #                  100]
    # pEX2refined =  [20700173.2868534,
    #                 20700173.2868534,
    #                 20700173.2868534,
    #                 20700173.2868534]
    #
    # pFEA3refined = [21135143.533079684,
    #                 21103572.526394643,  # 20m (5/100), (12.5 element op 250)
    #                 21068682.36205357,  # 10m (10/100), (25 elements)
    #                 21055465.52883131]  # 1m (100/100m), (250elements op L=250)
    # nelemsrefined = [2.5,
    #                  5,
    #                  10,
    #                  100]
    # pEX3refined = [20700173.2868534,
    #                20700173.2868534,
    #                20700173.2868534,
    #                20700173.2868534]
    #
    # # t=600 L=250
    # dpFEA = [-1305968.4288678593, #dz = 20m
    #          -2921755.772435982,
    #          -5885792.714165609,
    #          -11436990.774427539, #dz = 2.5m
    #          -25816941.087984808,
    #          -44298204.62592584] #dz = 0.5m
    # dpEX = [-35996534.26293199, #dz = 20m
    #         -35996534.26293199,
    #         -35996534.26293199,
    #         -35996534.26293199,
    #         -35996534.26293199,
    #         -35996534.26293199]

    #R=1000m refined
    nelems = [20, 40, 60, 80, 100, 120]
    pFEA = [
        20741097.145456452, 20715231.891588964, 20710359.28744662,
        20708647.638260685, 20721549.490607046, 20707423.04132063
    ]
    pEX = [
        20700173.2868534, 20700173.2868534, 20700173.2868534, 20700173.2868534,
        20713168.98464002, 20700173.2868534
    ]

    dpFEA = [
        -119927562.10910182, -137233382.50286353, -143126609.38124058,
        -146087319.8746748, -147867023.71421945, -149054570.09563407
    ]
    dpEX = [
        -35996534.26293199, -35996534.26293199, -35996534.26293199,
        -35996534.26293199, -35996534.26293199, -35996534.26293199
    ]

    #calculate L2 and H1 error, ns.du_i = 'u_i - uexact_i'
    def calculate_L2(FEA, EX):
        dp = np.subtract(FEA, EX)
        l2error = (dp * np.transpose(dp))**0.5

        return l2error

    def calculate_H1(FEA, EX, gradFEA, gradEX):
        dp = np.subtract(FEA, EX)
        dpdp = np.subtract(gradFEA, gradEX)
        H1error = (dp * np.transpose(dp) + dpdp * np.transpose(dpdp))**0.5

        return H1error

    # with export.mplfigure('elemspressure.png', dpi=800) as plt:
    #     ax1 = plt.subplots()
    #     ax1.set(xlabel='dz [m]')
    #     ax1.invert_xaxis()
    #     ax1.set_ylabel('Pressure [Pa]')
    #     ax1.plot(selems, pFEA, 'b--', label="FEA R=1000m")
    #     ax1.plot(selems, pEX2, label="analytical")
    #     ax1.plot(selems, pFEA2, '--', label="FEA R=250m")
    #     ax1.legend(loc="center right")
    #
    # with export.mplfigure('error.png', dpi=800) as plt:
    #     ax1 = plt.subplots()
    #     ax1.set(xlabel='dz [m]')
    #     ax1.invert_xaxis()
    #     ax1.set_ylabel('Difference [-]')
    #     ax1.plot(selems, dp/225e5, label="error")
    #     ax1.legend(loc="center right")

    #number of elements per 100m
    #log plot
    # with export.mplfigure('relativeerrorL2.png', dpi=800) as plt:
    #     # plt.add_axes([0.6, 0.3, 0.3, 0.3])
    #     ax1 = plt.subplots()
    #     ax1.set(xlabel=r'$N_{e}$ per 100m', xscale="log")  #'r''
    #     ax1.set(ylabel=r'$\left(\left|p_{w}-{p}_{w,exact}\right|/\left|p_{w,0}\right|\right)$', yscale="log")
    #     ax1.plot(nelems, dp2/225e5, 'o--', color='orange', label=r'$r_{dr} = 250m$ uniform mesh')
    #     ax1.plot(nelems, dp/225e5, 'ob--', label=r'$r_{dr} = 1000m$ uniform mesh')
    #     ax1.plot(nelemsrefined, dp3/ 225e5, 'o--', label=r'$r_{dr} = 250m$ refined mesh')
    #     ax1.legend(loc="upper right")
    #     plt.tight_layout()
    #
    with export.mplfigure('errorL2.png', dpi=800) as plt:
        # plt.add_axes([0.6, 0.3, 0.3, 0.3])
        ax1 = plt.subplots()
        ax1.set(xlabel=r'$N_{e}$')
        ax1.set(ylabel=r'$\left|p_{w}-{p}_{w,exact}\right|_{L^{2}-norm}$',
                yscale="log")
        ax1.plot(nelems,
                 calculate_L2(pFEA, pEX),
                 'o--',
                 color='red',
                 label=r'$r_{dr} = 1000m$, refined mesh')
        ax1.legend(loc="upper right")
        plt.tight_layout()

    with export.mplfigure('errorH1.png', dpi=800) as plt:
        # plt.add_axes([0.6, 0.3, 0.3, 0.3])
        ax1 = plt.subplots()
        ax1.set(xlabel=r'$N_{e}$')  # 'r''
        ax1.set(
            ylabel=
            r'$\sqrt{\left|(p_{w}-{p}_{w,exact})^2+(p_{w}^{\prime}-{p}_{w,exact}^{\prime})2\right|}{H^{1}-norm}$',
            yscale="log")
        ax1.plot(nelems,
                 calculate_H1(pFEA, pEX, dpFEA, dpEX),
                 'o--',
                 color='red',
                 label=r'$r_{dr} = 1000m$, refined mesh')
        ax1.legend(loc="upper right")
        plt.tight_layout()