Exemple #1
0
def main(ctx_factory=cl.create_some_context,
         use_profiling=False,
         use_logmgr=False,
         use_leap=False):
    """Drive the example."""
    from mpi4py import MPI
    comm = MPI.COMM_WORLD

    logmgr = initialize_logmgr(use_logmgr,
                               filename="vortex.sqlite",
                               mode="wu",
                               mpi_comm=comm)

    cl_ctx = ctx_factory()
    if use_profiling:
        queue = cl.CommandQueue(
            cl_ctx, properties=cl.command_queue_properties.PROFILING_ENABLE)
        actx = PyOpenCLProfilingArrayContext(
            queue,
            allocator=cl_tools.MemoryPool(cl_tools.ImmediateAllocator(queue)),
            logmgr=logmgr)
    else:
        queue = cl.CommandQueue(cl_ctx)
        actx = PyOpenCLArrayContext(queue,
                                    allocator=cl_tools.MemoryPool(
                                        cl_tools.ImmediateAllocator(queue)))

    dim = 2
    nel_1d = 16
    order = 3
    exittol = .1
    t_final = 0.1
    current_cfl = 1.0
    vel = np.zeros(shape=(dim, ))
    orig = np.zeros(shape=(dim, ))
    vel[:dim] = 1.0
    current_dt = .001
    current_t = 0
    eos = IdealSingleGas()
    initializer = Vortex2D(center=orig, velocity=vel)
    casename = "vortex"
    boundaries = {BTAG_ALL: PrescribedBoundary(initializer)}
    constant_cfl = False
    nstatus = 10
    nviz = 10
    rank = 0
    checkpoint_t = current_t
    current_step = 0
    if use_leap:
        from leap.rk import RK4MethodBuilder
        timestepper = RK4MethodBuilder("state")
    else:
        timestepper = rk4_step
    box_ll = -5.0
    box_ur = 5.0

    rank = comm.Get_rank()

    if dim != 2:
        raise ValueError("This example must be run with dim = 2.")

    from meshmode.mesh.generation import generate_regular_rect_mesh
    generate_mesh = partial(generate_regular_rect_mesh,
                            a=(box_ll, ) * dim,
                            b=(box_ur, ) * dim,
                            nelements_per_axis=(nel_1d, ) * dim)
    local_mesh, global_nelements = generate_and_distribute_mesh(
        comm, generate_mesh)
    local_nelements = local_mesh.nelements

    discr = EagerDGDiscretization(actx,
                                  local_mesh,
                                  order=order,
                                  mpi_communicator=comm)
    nodes = thaw(actx, discr.nodes())
    current_state = initializer(nodes)

    vis_timer = None

    if logmgr:
        logmgr_add_device_name(logmgr, queue)
        logmgr_add_device_memory_usage(logmgr, queue)
        logmgr_add_many_discretization_quantities(logmgr, discr, dim,
                                                  extract_vars_for_logging,
                                                  units_for_logging)

        logmgr.add_watches([
            "step.max", "t_step.max", "t_log.max", "min_temperature",
            "L2_norm_momentum1"
        ])

        try:
            logmgr.add_watches(
                ["memory_usage_python.max", "memory_usage_gpu.max"])
        except KeyError:
            pass

        if use_profiling:
            logmgr.add_watches(["multiply_time.max"])

        vis_timer = IntervalTimer("t_vis", "Time spent visualizing")
        logmgr.add_quantity(vis_timer)

    visualizer = make_visualizer(discr)

    initname = initializer.__class__.__name__
    eosname = eos.__class__.__name__
    init_message = make_init_message(dim=dim,
                                     order=order,
                                     nelements=local_nelements,
                                     global_nelements=global_nelements,
                                     dt=current_dt,
                                     t_final=t_final,
                                     nstatus=nstatus,
                                     nviz=nviz,
                                     cfl=current_cfl,
                                     constant_cfl=constant_cfl,
                                     initname=initname,
                                     eosname=eosname,
                                     casename=casename)
    if rank == 0:
        logger.info(init_message)

    get_timestep = partial(inviscid_sim_timestep,
                           discr=discr,
                           t=current_t,
                           dt=current_dt,
                           cfl=current_cfl,
                           eos=eos,
                           t_final=t_final,
                           constant_cfl=constant_cfl)

    def my_rhs(t, state):
        return euler_operator(discr,
                              cv=state,
                              t=t,
                              boundaries=boundaries,
                              eos=eos)

    def my_checkpoint(step, t, dt, state):
        return sim_checkpoint(discr,
                              visualizer,
                              eos,
                              cv=state,
                              exact_soln=initializer,
                              vizname=casename,
                              step=step,
                              t=t,
                              dt=dt,
                              nstatus=nstatus,
                              nviz=nviz,
                              exittol=exittol,
                              constant_cfl=constant_cfl,
                              comm=comm,
                              vis_timer=vis_timer)

    try:
        (current_step, current_t, current_state) = \
            advance_state(rhs=my_rhs, timestepper=timestepper,
                checkpoint=my_checkpoint,
                get_timestep=get_timestep, state=current_state,
                t=current_t, t_final=t_final, logmgr=logmgr,
                eos=eos, dim=dim)
    except ExactSolutionMismatch as ex:
        current_step = ex.step
        current_t = ex.t
        current_state = ex.state

    #    if current_t != checkpoint_t:
    if rank == 0:
        logger.info("Checkpointing final state ...")
    my_checkpoint(current_step,
                  t=current_t,
                  dt=(current_t - checkpoint_t),
                  state=current_state)

    if current_t - t_final < 0:
        raise ValueError("Simulation exited abnormally")

    if logmgr:
        logmgr.close()
    elif use_profiling:
        print(actx.tabulate_profiling_data())
def main(ctx_factory=cl.create_some_context,
         snapshot_pattern="y0euler-{step:06d}-{rank:04d}.pkl",
         restart_step=None,
         use_profiling=False,
         use_logmgr=False):
    """Drive the Y0 example."""

    from mpi4py import MPI
    comm = MPI.COMM_WORLD
    rank = 0
    rank = comm.Get_rank()
    nparts = comm.Get_size()
    """logging and profiling"""
    logmgr = initialize_logmgr(use_logmgr,
                               use_profiling,
                               filename="y0euler.sqlite",
                               mode="wu",
                               mpi_comm=comm)

    cl_ctx = ctx_factory()
    if use_profiling:
        queue = cl.CommandQueue(
            cl_ctx, properties=cl.command_queue_properties.PROFILING_ENABLE)
        actx = PyOpenCLProfilingArrayContext(
            queue,
            allocator=cl_tools.MemoryPool(cl_tools.ImmediateAllocator(queue)),
            logmgr=logmgr)
    else:
        queue = cl.CommandQueue(cl_ctx)
        actx = PyOpenCLArrayContext(queue,
                                    allocator=cl_tools.MemoryPool(
                                        cl_tools.ImmediateAllocator(queue)))

    #nviz = 500
    #nrestart = 500
    nviz = 50
    nrestart = 10000000
    current_dt = 1.0e-7
    #t_final = 5.e-7
    t_final = 3e-4

    dim = 2
    order = 1
    exittol = 10000000  # do never exit when comparing to exact solution
    #t_final = 0.001
    current_cfl = 1.0
    vel_init = np.zeros(shape=(dim, ))
    vel_inflow = np.zeros(shape=(dim, ))
    vel_outflow = np.zeros(shape=(dim, ))
    orig = np.zeros(shape=(dim, ))
    #vel[0] = 340.0
    #vel_inflow[0] = 100.0  # m/s
    current_t = 0
    casename = "y0euler"
    constant_cfl = False
    # no internal euler status messages
    nstatus = 1000000000
    checkpoint_t = current_t
    current_step = 0

    # working gas: CO2 #
    #   gamma = 1.289
    #   MW=44.009  g/mol
    #   cp = 37.135 J/mol-K,
    #   rho= 1.977 kg/m^3 @298K
    gamma_CO2 = 1.289
    R_CO2 = 8314.59 / 44.009

    # background
    #   100 Pa
    #   298 K
    #   rho = 1.77619667e-3 kg/m^3
    #   velocity = 0,0,0
    rho_bkrnd = 1.77619667e-3
    pres_bkrnd = 100
    temp_bkrnd = 298
    c_bkrnd = math.sqrt(gamma_CO2 * pres_bkrnd / rho_bkrnd)

    # isentropic shock relations #
    # lab frame, moving shock
    # state 1 is behind (downstream) the shock, state 2 is in front (upstream) of the shock

    mach = 2.0
    pressure_ratio = (2. * gamma_CO2 * mach * mach -
                      (gamma_CO2 - 1.)) / (gamma_CO2 + 1.)
    density_ratio = (gamma_CO2 + 1.) * mach * mach / (
        (gamma_CO2 - 1.) * mach * mach + 2.)
    mach2 = math.sqrt(((gamma_CO2 - 1.) * mach * mach + 2.) /
                      (2. * gamma_CO2 * mach * mach - (gamma_CO2 - 1.)))

    rho1 = rho_bkrnd
    pressure1 = pres_bkrnd
    rho2 = rho1 * density_ratio
    pressure2 = pressure1 * pressure_ratio
    velocity1 = 0.
    velocity2 = -mach * c_bkrnd * (1 / density_ratio - 1)
    c_shkd = math.sqrt(gamma_CO2 * pressure2 / rho2)

    vel_inflow[0] = velocity2

    timestepper = rk4_step
    eos = IdealSingleGas(gamma=gamma_CO2, gas_const=R_CO2)
    bulk_init = Discontinuity(dim=dim,
                              x0=.05,
                              sigma=0.01,
                              rhol=rho2,
                              rhor=rho1,
                              pl=pressure2,
                              pr=pressure1,
                              ul=vel_inflow[0],
                              ur=0.)
    inflow_init = Lump(dim=dim,
                       rho0=rho2,
                       p0=pressure2,
                       center=orig,
                       velocity=vel_inflow,
                       rhoamp=0.0)
    outflow_init = Lump(dim=dim,
                        rho0=rho1,
                        p0=pressure1,
                        center=orig,
                        velocity=vel_outflow,
                        rhoamp=0.0)

    inflow = PrescribedBoundary(inflow_init)
    outflow = PrescribedBoundary(outflow_init)
    wall = AdiabaticSlipBoundary()
    dummy = DummyBoundary()

    # shock capturing parameters
    # sonic conditions
    density_ratio = (gamma_CO2 + 1.) * 1.0 / ((gamma_CO2 - 1.) + 2.)

    density_star = rho1 * density_ratio
    shock_thickness = 20 * 0.001  # on the order of 3 elements, should match what is in mesh generator
    # alpha is ~h/p (spacing/order)
    #alpha_sc = shock_thickness*abs(velocity1-velocity2)*density_star
    alpha_sc = 0.1
    # sigma is ~p^-4
    sigma_sc = -11.0
    # kappa is empirical ...
    kappa_sc = 0.5
    print(
        f"Shock capturing parameters: alpha {alpha_sc}, s0 {sigma_sc}, kappa {kappa_sc}"
    )

    # timestep estimate
    wave_speed = max(mach2 * c_bkrnd, c_shkd + velocity2)
    char_len = 0.001
    area = char_len * char_len / 2
    perimeter = 2 * char_len + math.sqrt(2 * char_len * char_len)
    h = 2 * area / perimeter

    dt_est = 1 / (wave_speed * order * order / h)
    print(f"Time step estimate {dt_est}\n")

    dt_est_visc = 1 / (wave_speed * order * order / h +
                       alpha_sc * order * order * order * order / h / h)
    print(f"Viscous timestep estimate {dt_est_visc}\n")

    from grudge import sym
    #    boundaries = {BTAG_ALL: DummyBoundary}
    boundaries = {
        sym.DTAG_BOUNDARY("Inflow"): inflow,
        sym.DTAG_BOUNDARY("Outflow"): outflow,
        sym.DTAG_BOUNDARY("Wall"): wall
    }

    #local_mesh, global_nelements = create_parallel_grid(comm,
    #get_pseudo_y0_mesh)
    #
    #local_nelements = local_mesh.nelements

    if restart_step is None:
        local_mesh, global_nelements = create_parallel_grid(comm, get_mesh)
        local_nelements = local_mesh.nelements

    else:  # Restart
        with open(snapshot_pattern.format(step=restart_step, rank=rank),
                  "rb") as f:
            restart_data = pickle.load(f)

        local_mesh = restart_data["local_mesh"]
        local_nelements = local_mesh.nelements
        global_nelements = restart_data["global_nelements"]

        assert comm.Get_size() == restart_data["num_parts"]

    if rank == 0:
        logging.info("Making discretization")
    discr = EagerDGDiscretization(actx,
                                  local_mesh,
                                  order=order,
                                  mpi_communicator=comm)
    nodes = thaw(actx, discr.nodes())

    if restart_step is None:
        if rank == 0:
            logging.info("Initializing soln.")
        current_state = bulk_init(0, nodes, eos=eos)
    else:
        current_t = restart_data["t"]
        current_step = restart_step

        current_state = unflatten(
            actx, discr.discr_from_dd("vol"),
            obj_array_vectorize(actx.from_numpy, restart_data["state"]))

    vis_timer = None

    if logmgr:
        logmgr_add_device_name(logmgr, queue)
        logmgr_add_discretization_quantities(logmgr, discr, eos, dim)
        #logmgr_add_package_versions(logmgr)

        logmgr.add_watches([
            "step.max", "t_sim.max", "t_step.max", "min_pressure",
            "max_pressure", "min_temperature", "max_temperature"
        ])

        try:
            logmgr.add_watches(["memory_usage.max"])
        except KeyError:
            pass

        if use_profiling:
            logmgr.add_watches(["pyopencl_array_time.max"])

        vis_timer = IntervalTimer("t_vis", "Time spent visualizing")
        logmgr.add_quantity(vis_timer)

    #visualizer = make_visualizer(discr, discr.order + 3
    #if discr.dim == 2 else discr.order)
    visualizer = make_visualizer(discr, discr.order)

    #    initname = initializer.__class__.__name__
    initname = "pseudoY0"
    eosname = eos.__class__.__name__
    init_message = make_init_message(dim=dim,
                                     order=order,
                                     nelements=local_nelements,
                                     global_nelements=global_nelements,
                                     dt=current_dt,
                                     t_final=t_final,
                                     nstatus=nstatus,
                                     nviz=nviz,
                                     cfl=current_cfl,
                                     constant_cfl=constant_cfl,
                                     initname=initname,
                                     eosname=eosname,
                                     casename=casename)
    if rank == 0:
        logger.info(init_message)

    get_timestep = partial(inviscid_sim_timestep,
                           discr=discr,
                           t=current_t,
                           dt=current_dt,
                           cfl=current_cfl,
                           eos=eos,
                           t_final=t_final,
                           constant_cfl=constant_cfl)

    def my_rhs(t, state):
        #return inviscid_operator(discr, eos=eos, boundaries=boundaries, q=state, t=t)
        return (inviscid_operator(
            discr, q=state, t=t, boundaries=boundaries, eos=eos) +
                artificial_viscosity(discr,
                                     t=t,
                                     r=state,
                                     eos=eos,
                                     boundaries=boundaries,
                                     alpha=alpha_sc,
                                     sigma=sigma_sc,
                                     kappa=kappa_sc))

    def my_checkpoint(step, t, dt, state):

        write_restart = (check_step(step, nrestart)
                         if step != restart_step else False)
        if write_restart is True:
            with open(snapshot_pattern.format(step=step, rank=rank),
                      "wb") as f:
                pickle.dump(
                    {
                        "local_mesh": local_mesh,
                        "state": obj_array_vectorize(actx.to_numpy,
                                                     flatten(state)),
                        "t": t,
                        "step": step,
                        "global_nelements": global_nelements,
                        "num_parts": nparts,
                    }, f)

        #x0=f(time)
        exact_soln = Discontinuity(dim=dim,
                                   x0=.05,
                                   sigma=0.00001,
                                   rhol=rho2,
                                   rhor=rho1,
                                   pl=pressure2,
                                   pr=pressure1,
                                   ul=vel_inflow[0],
                                   ur=0.,
                                   uc=mach * c_bkrnd)

        return sim_checkpoint(discr=discr,
                              visualizer=visualizer,
                              eos=eos,
                              q=state,
                              vizname=casename,
                              step=step,
                              t=t,
                              dt=dt,
                              nstatus=nstatus,
                              nviz=nviz,
                              exittol=exittol,
                              constant_cfl=constant_cfl,
                              comm=comm,
                              vis_timer=vis_timer,
                              overwrite=True,
                              exact_soln=exact_soln,
                              sigma=sigma_sc,
                              kappa=kappa_sc)

    if rank == 0:
        logging.info("Stepping.")

    (current_step, current_t, current_state) = \
        advance_state(rhs=my_rhs, timestepper=timestepper,
                      checkpoint=my_checkpoint,
                      get_timestep=get_timestep, state=current_state,
                      t_final=t_final, t=current_t, istep=current_step,
                      logmgr=logmgr,eos=eos,dim=dim)

    if rank == 0:
        logger.info("Checkpointing final state ...")

    my_checkpoint(current_step,
                  t=current_t,
                  dt=(current_t - checkpoint_t),
                  state=current_state)

    if current_t - t_final < 0:
        raise ValueError("Simulation exited abnormally")

    if logmgr:
        logmgr.close()
    elif use_profiling:
        print(actx.tabulate_profiling_data())
Exemple #3
0
def main(ctx_factory=cl.create_some_context,
         snapshot_pattern="flame1d-{step:06d}-{rank:04d}.pkl",
         restart_step=None,
         use_profiling=False,
         use_logmgr=False):
    """Drive the Y0 example."""

    from mpi4py import MPI
    comm = MPI.COMM_WORLD
    rank = 0
    rank = comm.Get_rank()
    nparts = comm.Get_size()
    """logging and profiling"""
    logmgr = initialize_logmgr(use_logmgr,
                               filename="flame1d.sqlite",
                               mode="wo",
                               mpi_comm=comm)

    cl_ctx = ctx_factory()
    if use_profiling:
        queue = cl.CommandQueue(
            cl_ctx, properties=cl.command_queue_properties.PROFILING_ENABLE)
        actx = PyOpenCLProfilingArrayContext(
            queue,
            allocator=cl_tools.MemoryPool(cl_tools.ImmediateAllocator(queue)),
            logmgr=logmgr)
    else:
        queue = cl.CommandQueue(cl_ctx)
        actx = PyOpenCLArrayContext(queue,
                                    allocator=cl_tools.MemoryPool(
                                        cl_tools.ImmediateAllocator(queue)))

    #nviz = 500
    #nrestart = 500
    nviz = 1
    nrestart = 3
    #current_dt = 5.0e-8 # stable with euler
    current_dt = 5.0e-8  # stable with rk4
    #current_dt = 4e-7 # stable with lrsrk144
    t_final = 1.5e-7

    dim = 2
    order = 1
    exittol = 1000000000000
    #t_final = 0.001
    current_cfl = 1.0
    current_t = 0
    constant_cfl = False
    nstatus = 10000000000
    rank = 0
    checkpoint_t = current_t
    current_step = 0
    vel_burned = np.zeros(shape=(dim, ))
    vel_unburned = np.zeros(shape=(dim, ))

    # {{{  Set up initial state using Cantera

    # Use Cantera for initialization
    # -- Pick up a CTI for the thermochemistry config
    # --- Note: Users may add their own CTI file by dropping it into
    # ---       mirgecom/mechanisms alongside the other CTI files.
    from mirgecom.mechanisms import get_mechanism_cti
    # uiuc C2H4
    #mech_cti = get_mechanism_cti("uiuc")
    # sanDiego H2
    mech_cti = get_mechanism_cti("sanDiego")

    cantera_soln = cantera.Solution(phase_id="gas", source=mech_cti)
    nspecies = cantera_soln.n_species

    # Initial temperature, pressure, and mixutre mole fractions are needed to
    # set up the initial state in Cantera.
    temp_unburned = 300.0
    temp_ignition = 1500.0
    # Parameters for calculating the amounts of fuel, oxidizer, and inert species
    equiv_ratio = 1.0
    ox_di_ratio = 0.21
    # H2
    stoich_ratio = 0.5
    #C2H4
    #stoich_ratio = 3.0
    # Grab the array indices for the specific species, ethylene, oxygen, and nitrogen
    # C2H4
    #i_fu = cantera_soln.species_index("C2H4")
    # H2
    i_fu = cantera_soln.species_index("H2")
    i_ox = cantera_soln.species_index("O2")
    i_di = cantera_soln.species_index("N2")
    x = np.zeros(nspecies)
    # Set the species mole fractions according to our desired fuel/air mixture
    x[i_fu] = (ox_di_ratio * equiv_ratio) / (stoich_ratio +
                                             ox_di_ratio * equiv_ratio)
    x[i_ox] = stoich_ratio * x[i_fu] / equiv_ratio
    x[i_di] = (1.0 - ox_di_ratio) * x[i_ox] / ox_di_ratio
    # Uncomment next line to make pylint fail when it can't find cantera.one_atm
    one_atm = cantera.one_atm  # pylint: disable=no-member
    # one_atm = 101325.0
    pres_unburned = one_atm

    # Let the user know about how Cantera is being initilized
    print(f"Input state (T,P,X) = ({temp_unburned}, {pres_unburned}, {x}")
    # Set Cantera internal gas temperature, pressure, and mole fractios
    cantera_soln.TPX = temp_unburned, pres_unburned, x
    # Pull temperature, total density, mass fractions, and pressure from Cantera
    # We need total density, and mass fractions to initialize the fluid/gas state.
    y_unburned = np.zeros(nspecies)
    can_t, rho_unburned, y_unburned = cantera_soln.TDY
    can_p = cantera_soln.P
    # *can_t*, *can_p* should not differ (significantly) from user's initial data,
    # but we want to ensure that we use exactly the same starting point as Cantera,
    # so we use Cantera's version of these data.

    # now find the conditions for the burned gas
    cantera_soln.equilibrate('TP')
    temp_burned, rho_burned, y_burned = cantera_soln.TDY
    pres_burned = cantera_soln.P

    casename = "flame1d"
    pyrometheus_mechanism = pyro.get_thermochem_class(cantera_soln)(actx.np)

    # C2H4
    mu = 1.e-5
    kappa = 1.6e-5  # Pr = mu*rho/alpha = 0.75
    # H2
    mu = 1.e-5
    kappa = mu * 0.08988 / 0.75  # Pr = mu*rho/alpha = 0.75

    species_diffusivity = 1.e-5 * np.ones(nspecies)
    transport_model = SimpleTransport(viscosity=mu,
                                      thermal_conductivity=kappa,
                                      species_diffusivity=species_diffusivity)

    eos = PyrometheusMixture(pyrometheus_mechanism,
                             temperature_guess=temp_unburned,
                             transport_model=transport_model)
    species_names = pyrometheus_mechanism.species_names

    print(f"Pyrometheus mechanism species names {species_names}")
    print(
        f"Unburned state (T,P,Y) = ({temp_unburned}, {pres_unburned}, {y_unburned}"
    )
    print(f"Burned state (T,P,Y) = ({temp_burned}, {pres_burned}, {y_burned}")

    flame_start_loc = 0.05
    flame_speed = 1000

    # use the burned conditions with a lower temperature
    bulk_init = PlanarDiscontinuity(dim=dim,
                                    disc_location=flame_start_loc,
                                    sigma=0.01,
                                    nspecies=nspecies,
                                    temperature_left=temp_ignition,
                                    temperature_right=temp_unburned,
                                    pressure_left=pres_burned,
                                    pressure_right=pres_unburned,
                                    velocity_left=vel_burned,
                                    velocity_right=vel_unburned,
                                    species_mass_left=y_burned,
                                    species_mass_right=y_unburned)

    inflow_init = MixtureInitializer(dim=dim,
                                     nspecies=nspecies,
                                     pressure=pres_burned,
                                     temperature=temp_ignition,
                                     massfractions=y_burned,
                                     velocity=vel_burned)
    outflow_init = MixtureInitializer(dim=dim,
                                      nspecies=nspecies,
                                      pressure=pres_unburned,
                                      temperature=temp_unburned,
                                      massfractions=y_unburned,
                                      velocity=vel_unburned)

    inflow = PrescribedViscousBoundary(q_func=inflow_init)
    outflow = PrescribedViscousBoundary(q_func=outflow_init)
    wall = PrescribedViscousBoundary(
    )  # essentially a "dummy" use the interior solution for the exterior

    from grudge import sym
    boundaries = {
        sym.DTAG_BOUNDARY("Inflow"): inflow,
        sym.DTAG_BOUNDARY("Outflow"): outflow,
        sym.DTAG_BOUNDARY("Wall"): wall
    }

    if restart_step is None:
        char_len = 0.001
        box_ll = (0.0, 0.0)
        box_ur = (0.25, 0.01)
        num_elements = (int((box_ur[0] - box_ll[0]) / char_len),
                        int((box_ur[1] - box_ll[1]) / char_len))

        from meshmode.mesh.generation import generate_regular_rect_mesh
        generate_mesh = partial(generate_regular_rect_mesh,
                                a=box_ll,
                                b=box_ur,
                                n=num_elements,
                                mesh_type="X",
                                boundary_tag_to_face={
                                    "Inflow": ["-x"],
                                    "Outflow": ["+x"],
                                    "Wall": ["+y", "-y"]
                                })
        local_mesh, global_nelements = generate_and_distribute_mesh(
            comm, generate_mesh)
        local_nelements = local_mesh.nelements

    else:  # Restart
        with open(snapshot_pattern.format(step=restart_step, rank=rank),
                  "rb") as f:
            restart_data = pickle.load(f)

        local_mesh = restart_data["local_mesh"]
        local_nelements = local_mesh.nelements
        global_nelements = restart_data["global_nelements"]

        assert comm.Get_size() == restart_data["num_parts"]

    if rank == 0:
        logging.info("Making discretization")
    discr = EagerDGDiscretization(actx,
                                  local_mesh,
                                  order=order,
                                  mpi_communicator=comm)
    nodes = thaw(actx, discr.nodes())

    if restart_step is None:
        if rank == 0:
            logging.info("Initializing soln.")
        # for Discontinuity initial conditions
        current_state = bulk_init(t=0., x_vec=nodes, eos=eos)
        # for uniform background initial condition
        #current_state = bulk_init(nodes, eos=eos)
    else:
        current_t = restart_data["t"]
        current_step = restart_step

        current_state = unflatten(
            actx, discr.discr_from_dd("vol"),
            obj_array_vectorize(actx.from_numpy, restart_data["state"]))

    vis_timer = None

    if logmgr:
        logmgr_add_cl_device_info(logmgr, queue)
        logmgr_add_many_discretization_quantities(logmgr, discr, dim,
                                                  extract_vars_for_logging,
                                                  units_for_logging)
        logmgr.add_watches([
            "step.max", "t_sim.max", "t_step.max", "t_log.max", "min_pressure",
            "max_pressure", "min_temperature", "max_temperature"
        ])

        try:
            logmgr.add_watches(
                ["memory_usage_python.max", "memory_usage_gpu.max"])
        except KeyError:
            pass

        if use_profiling:
            logmgr.add_watches(["pyopencl_array_time.max"])

        vis_timer = IntervalTimer("t_vis", "Time spent visualizing")
        logmgr.add_quantity(vis_timer)

    visualizer = make_visualizer(discr, order)
    #    initname = initializer.__class__.__name__
    initname = "flame1d"
    eosname = eos.__class__.__name__
    init_message = make_init_message(dim=dim,
                                     order=order,
                                     nelements=local_nelements,
                                     global_nelements=global_nelements,
                                     dt=current_dt,
                                     t_final=t_final,
                                     nstatus=nstatus,
                                     nviz=nviz,
                                     cfl=current_cfl,
                                     constant_cfl=constant_cfl,
                                     initname=initname,
                                     eosname=eosname,
                                     casename=casename)
    if rank == 0:
        logger.info(init_message)

    #timestepper = rk4_step
    #timestepper = lsrk54_step
    #timestepper = lsrk144_step
    timestepper = euler_step

    get_timestep = partial(inviscid_sim_timestep,
                           discr=discr,
                           t=current_t,
                           dt=current_dt,
                           cfl=current_cfl,
                           eos=eos,
                           t_final=t_final,
                           constant_cfl=constant_cfl)

    def my_rhs(t, state):
        # check for some troublesome output types
        inf_exists = not np.isfinite(discr.norm(state, np.inf))
        if inf_exists:
            if rank == 0:
                logging.info(
                    "Non-finite values detected in simulation, exiting...")
            # dump right now
            sim_checkpoint(discr=discr,
                           visualizer=visualizer,
                           eos=eos,
                           q=state,
                           vizname=casename,
                           step=999999999,
                           t=t,
                           dt=current_dt,
                           nviz=1,
                           exittol=exittol,
                           constant_cfl=constant_cfl,
                           comm=comm,
                           vis_timer=vis_timer,
                           overwrite=True,
                           s0=s0_sc,
                           kappa=kappa_sc)
            exit()

        cv = split_conserved(dim=dim, q=state)
        return (
            ns_operator(discr, q=state, t=t, boundaries=boundaries, eos=eos) +
            eos.get_species_source_terms(cv))

    def my_checkpoint(step, t, dt, state):

        write_restart = (check_step(step, nrestart)
                         if step != restart_step else False)
        if write_restart is True:
            with open(snapshot_pattern.format(step=step, rank=rank),
                      "wb") as f:
                pickle.dump(
                    {
                        "local_mesh": local_mesh,
                        "state": obj_array_vectorize(actx.to_numpy,
                                                     flatten(state)),
                        "t": t,
                        "step": step,
                        "global_nelements": global_nelements,
                        "num_parts": nparts,
                    }, f)

        def loc_fn(t):
            return flame_start_loc + flame_speed * t

        exact_soln = PlanarDiscontinuity(dim=dim,
                                         disc_location=loc_fn,
                                         sigma=0.0000001,
                                         nspecies=nspecies,
                                         temperature_left=temp_ignition,
                                         temperature_right=temp_unburned,
                                         pressure_left=pres_burned,
                                         pressure_right=pres_unburned,
                                         velocity_left=vel_burned,
                                         velocity_right=vel_unburned,
                                         species_mass_left=y_burned,
                                         species_mass_right=y_unburned)

        cv = split_conserved(dim, state)
        reaction_rates = eos.get_production_rates(cv)
        viz_fields = [("reaction_rates", reaction_rates)]

        return sim_checkpoint(discr=discr,
                              visualizer=visualizer,
                              eos=eos,
                              q=state,
                              vizname=casename,
                              step=step,
                              t=t,
                              dt=dt,
                              nstatus=nstatus,
                              nviz=nviz,
                              exittol=exittol,
                              constant_cfl=constant_cfl,
                              comm=comm,
                              vis_timer=vis_timer,
                              overwrite=True,
                              exact_soln=exact_soln,
                              viz_fields=viz_fields)

    if rank == 0:
        logging.info("Stepping.")

    (current_step, current_t, current_state) = \
        advance_state(rhs=my_rhs, timestepper=timestepper,
                      checkpoint=my_checkpoint,
                      get_timestep=get_timestep, state=current_state,
                      t_final=t_final, t=current_t, istep=current_step,
                      logmgr=logmgr,eos=eos,dim=dim)

    if rank == 0:
        logger.info("Checkpointing final state ...")

    my_checkpoint(current_step,
                  t=current_t,
                  dt=(current_t - checkpoint_t),
                  state=current_state)

    if current_t - t_final < 0:
        raise ValueError("Simulation exited abnormally")

    if logmgr:
        logmgr.close()
    elif use_profiling:
        print(actx.tabulate_profiling_data())

    exit()
Exemple #4
0
def main(ctx_factory=cl.create_some_context,
         casename="flame1d",
         user_input_file=None,
         snapshot_pattern="{casename}-{step:06d}-{rank:04d}.pkl",
         restart_step=None,
         restart_name=None,
         use_profiling=False,
         use_logmgr=False,
         use_lazy_eval=False):
    """Drive the 1D Flame example."""

    from mpi4py import MPI
    comm = MPI.COMM_WORLD
    rank = 0
    rank = comm.Get_rank()
    nparts = comm.Get_size()

    if restart_name is None:
        restart_name = casename
    """logging and profiling"""
    logmgr = initialize_logmgr(use_logmgr,
                               filename=(f"{casename}.sqlite"),
                               mode="wo",
                               mpi_comm=comm)

    cl_ctx = ctx_factory()
    if use_profiling:
        if use_lazy_eval:
            raise RuntimeError("Cannot run lazy with profiling.")
        queue = cl.CommandQueue(
            cl_ctx, properties=cl.command_queue_properties.PROFILING_ENABLE)
        actx = PyOpenCLProfilingArrayContext(
            queue,
            allocator=cl_tools.MemoryPool(cl_tools.ImmediateAllocator(queue)),
            logmgr=logmgr)
    else:
        queue = cl.CommandQueue(cl_ctx)
        if use_lazy_eval:
            actx = PytatoArrayContext(queue)
        else:
            actx = PyOpenCLArrayContext(
                queue,
                allocator=cl_tools.MemoryPool(
                    cl_tools.ImmediateAllocator(queue)))

    # default input values that will be read from input (if they exist)
    nviz = 100
    nrestart = 100
    nhealth = 100
    nstatus = 1
    current_dt = 1e-9
    t_final = 1.e-3
    order = 1
    integrator = "rk4"

    if user_input_file:
        if rank == 0:
            with open(user_input_file) as f:
                input_data = yaml.load(f, Loader=yaml.FullLoader)
        else:
            input_data = None
        input_data = comm.bcast(input_data, root=0)
        #print(input_data)
        try:
            nviz = int(input_data["nviz"])
        except KeyError:
            pass
        try:
            nrestart = int(input_data["nrestart"])
        except KeyError:
            pass
        try:
            nhealth = int(input_data["nhealth"])
        except KeyError:
            pass
        try:
            nstatus = int(input_data["nstatus"])
        except KeyError:
            pass
        try:
            current_dt = float(input_data["current_dt"])
        except KeyError:
            pass
        try:
            t_final = float(input_data["t_final"])
        except KeyError:
            pass
        try:
            order = int(input_data["order"])
        except KeyError:
            pass
        try:
            integrator = input_data["integrator"]
        except KeyError:
            pass

    # param sanity check
    allowed_integrators = ["rk4", "euler", "lsrk54", "lsrk144"]
    if (integrator not in allowed_integrators):
        error_message = "Invalid time integrator: {}".format(integrator)
        raise RuntimeError(error_message)

    timestepper = rk4_step
    if integrator == "euler":
        timestepper = euler_step
    if integrator == "lsrk54":
        timestepper = lsrk54_step
    if integrator == "lsrk144":
        timestepper = lsrk144_step

    if (rank == 0):
        print(f'#### Simluation control data: ####')
        print(f'\tnviz = {nviz}')
        print(f'\tnrestart = {nrestart}')
        print(f'\tnhealth = {nhealth}')
        print(f'\tnstatus = {nstatus}')
        print(f'\tcurrent_dt = {current_dt}')
        print(f'\tt_final = {t_final}')
        print(f'\torder = {order}')
        print(f"\tTime integration {integrator}")
        print(f'#### Simluation control data: ####')

    restart_path = 'restart_data/'
    viz_path = 'viz_data/'
    #if(rank == 0):
    #if not os.path.exists(restart_path):
    #os.makedirs(restart_path)
    #if not os.path.exists(viz_path):
    #os.makedirs(viz_path)

    dim = 2
    exittol = .09
    current_cfl = 1.0
    current_t = 0
    constant_cfl = False
    checkpoint_t = current_t
    current_step = 0

    vel_burned = np.zeros(shape=(dim, ))
    vel_unburned = np.zeros(shape=(dim, ))

    # {{{  Set up initial state using Cantera

    # Use Cantera for initialization
    # -- Pick up a CTI for the thermochemistry config
    # --- Note: Users may add their own CTI file by dropping it into
    # ---       mirgecom/mechanisms alongside the other CTI files.
    fuel = "H2"
    allowed_fuels = ["H2", "C2H4"]
    if (fuel not in allowed_fuels):
        error_message = "Invalid fuel selection: {}".format(fuel)
        raise RuntimeError(error_message)

    if rank == 0:
        print(f"Fuel: {fuel}")

    from mirgecom.mechanisms import get_mechanism_cti
    if fuel == "C2H4":
        mech_cti = get_mechanism_cti("uiuc")
    elif fuel == "H2":
        mech_cti = get_mechanism_cti("sanDiego")

    cantera_soln = cantera.Solution(phase_id="gas", source=mech_cti)
    nspecies = cantera_soln.n_species

    # Initial temperature, pressure, and mixutre mole fractions are needed to
    # set up the initial state in Cantera.
    temp_unburned = 300.0
    temp_ignition = 1500.0
    # Parameters for calculating the amounts of fuel, oxidizer, and inert species
    if fuel == "C2H4":
        stoich_ratio = 3.0
    if fuel == "H2":
        stoich_ratio = 0.5
    equiv_ratio = 1.0
    ox_di_ratio = 0.21
    # Grab the array indices for the specific species, ethylene, oxygen, and nitrogen
    i_fu = cantera_soln.species_index(fuel)
    i_ox = cantera_soln.species_index("O2")
    i_di = cantera_soln.species_index("N2")
    x = np.zeros(nspecies)
    # Set the species mole fractions according to our desired fuel/air mixture
    x[i_fu] = (ox_di_ratio * equiv_ratio) / (stoich_ratio +
                                             ox_di_ratio * equiv_ratio)
    x[i_ox] = stoich_ratio * x[i_fu] / equiv_ratio
    x[i_di] = (1.0 - ox_di_ratio) * x[i_ox] / ox_di_ratio
    # Uncomment next line to make pylint fail when it can't find cantera.one_atm
    one_atm = cantera.one_atm  # pylint: disable=no-member
    # one_atm = 101325.0
    pres_unburned = one_atm

    # Let the user know about how Cantera is being initilized
    print(f"Input state (T,P,X) = ({temp_unburned}, {pres_unburned}, {x}")
    # Set Cantera internal gas temperature, pressure, and mole fractios
    cantera_soln.TPX = temp_unburned, pres_unburned, x
    # Pull temperature, total density, mass fractions, and pressure from Cantera
    # We need total density, and mass fractions to initialize the fluid/gas state.
    y_unburned = np.zeros(nspecies)
    can_t, rho_unburned, y_unburned = cantera_soln.TDY
    can_p = cantera_soln.P
    # *can_t*, *can_p* should not differ (significantly) from user's initial data,
    # but we want to ensure that we use exactly the same starting point as Cantera,
    # so we use Cantera's version of these data.

    # now find the conditions for the burned gas
    cantera_soln.equilibrate('TP')
    temp_burned, rho_burned, y_burned = cantera_soln.TDY
    pres_burned = cantera_soln.P

    pyrometheus_mechanism = pyro.get_thermochem_class(cantera_soln)(actx.np)

    kappa = 1.6e-5  # Pr = mu*rho/alpha = 0.75
    mu = 1.e-5
    species_diffusivity = 1.e-5 * np.ones(nspecies)
    transport_model = SimpleTransport(viscosity=mu,
                                      thermal_conductivity=kappa,
                                      species_diffusivity=species_diffusivity)

    eos = PyrometheusMixture(pyrometheus_mechanism,
                             temperature_guess=temp_unburned,
                             transport_model=transport_model)
    species_names = pyrometheus_mechanism.species_names

    print(f"Pyrometheus mechanism species names {species_names}")
    print(
        f"Unburned state (T,P,Y) = ({temp_unburned}, {pres_unburned}, {y_unburned}"
    )
    print(f"Burned state (T,P,Y) = ({temp_burned}, {pres_burned}, {y_burned}")

    flame_start_loc = 0.10
    flame_speed = 1000

    # use the burned conditions with a lower temperature
    #bulk_init = PlanarDiscontinuity(dim=dim, disc_location=flame_start_loc, sigma=0.01, nspecies=nspecies,
    #temperature_left=temp_ignition, temperature_right=temp_unburned,
    #pressure_left=pres_burned, pressure_right=pres_unburned,
    #velocity_left=vel_burned, velocity_right=vel_unburned,
    #species_mass_left=y_burned, species_mass_right=y_unburned)
    bulk_init = PlanarDiscontinuity(dim=dim,
                                    disc_location=flame_start_loc,
                                    sigma=0.0005,
                                    nspecies=nspecies,
                                    temperature_right=temp_ignition,
                                    temperature_left=temp_unburned,
                                    pressure_right=pres_burned,
                                    pressure_left=pres_unburned,
                                    velocity_right=vel_burned,
                                    velocity_left=vel_unburned,
                                    species_mass_right=y_burned,
                                    species_mass_left=y_unburned)

    inflow_init = MixtureInitializer(dim=dim,
                                     nspecies=nspecies,
                                     pressure=pres_burned,
                                     temperature=temp_ignition,
                                     massfractions=y_burned,
                                     velocity=vel_burned)
    outflow_init = MixtureInitializer(dim=dim,
                                      nspecies=nspecies,
                                      pressure=pres_unburned,
                                      temperature=temp_unburned,
                                      massfractions=y_unburned,
                                      velocity=vel_unburned)

    def symmetry(nodes, eos, cv=None, **kwargs):
        dim = len(nodes)

        if cv is not None:
            #cv = split_conserved(dim, q)
            mass = cv.mass
            momentum = cv.momentum
            momentum[1] = -1.0 * momentum[1]
            ke = .5 * np.dot(cv.momentum, cv.momentum) / cv.mass
            energy = cv.energy
            species_mass = cv.species_mass
            return make_conserved(dim=dim,
                                  mass=mass,
                                  momentum=momentum,
                                  energy=energy,
                                  species_mass=species_mass)

    def dummy(nodes, eos, cv=None, **kwargs):
        dim = len(nodes)

        if cv is not None:
            #cv = split_conserved(dim, q)
            mass = cv.mass
            momentum = cv.momentum
            ke = .5 * np.dot(cv.momentum, cv.momentum) / cv.mass
            energy = cv.energy
            species_mass = cv.species_mass
            return make_conserved(dim=dim,
                                  mass=mass,
                                  momentum=momentum,
                                  energy=energy,
                                  species_mass=species_mass)

    inflow = PrescribedViscousBoundary(q_func=inflow_init)
    outflow = PrescribedViscousBoundary(q_func=outflow_init)
    wall_symmetry = PrescribedViscousBoundary(q_func=symmetry)
    wall_dummy = PrescribedViscousBoundary(q_func=dummy)
    wall = PrescribedViscousBoundary(
    )  # essentially a "dummy" use the interior solution for the exterior

    boundaries = {
        DTAG_BOUNDARY("Inflow"): inflow,
        DTAG_BOUNDARY("Outflow"): outflow,
        #DTAG_BOUNDARY("Wall"): wall_dummy}
        DTAG_BOUNDARY("Wall"): wall_symmetry
    }

    if restart_step is None:
        char_len = 0.0001
        box_ll = (0.0, 0.0)
        box_ur = (0.2, 0.00125)
        num_elements = (int((box_ur[0] - box_ll[0]) / char_len),
                        int((box_ur[1] - box_ll[1]) / char_len))

        from meshmode.mesh.generation import generate_regular_rect_mesh
        generate_mesh = partial(generate_regular_rect_mesh,
                                a=box_ll,
                                b=box_ur,
                                n=num_elements,
                                boundary_tag_to_face={
                                    "Inflow": ["+x"],
                                    "Outflow": ["-x"],
                                    "Wall": ["+y", "-y"]
                                })
        local_mesh, global_nelements = generate_and_distribute_mesh(
            comm, generate_mesh)
        local_nelements = local_mesh.nelements

    else:  # Restart
        from mirgecom.restart import read_restart_data
        restart_file = restart_path + snapshot_pattern.format(
            casename=restart_name, step=restart_step, rank=rank)
        restart_data = read_restart_data(actx, restart_file)

        local_mesh = restart_data["local_mesh"]
        local_nelements = local_mesh.nelements
        global_nelements = restart_data["global_nelements"]

        assert comm.Get_size() == restart_data["num_parts"]

    if rank == 0:
        logging.info("Making discretization")
    discr = EagerDGDiscretization(actx,
                                  local_mesh,
                                  order=order,
                                  mpi_communicator=comm)
    nodes = thaw(actx, discr.nodes())

    if restart_step is None:
        if rank == 0:
            logging.info("Initializing soln.")
        # for Discontinuity initial conditions
        current_state = bulk_init(x_vec=nodes, eos=eos, time=0.)
        # for uniform background initial condition
        #current_state = bulk_init(nodes, eos=eos)
    else:
        current_t = restart_data["t"]
        current_step = restart_step
        #current_state = make_fluid_restart_state(actx, discr.discr_from_dd("vol"), restart_data["state"])
        current_state = restart_data["state"]

    vis_timer = None
    log_cfl = LogUserQuantity(name="cfl", value=current_cfl)

    if logmgr:
        logmgr_add_cl_device_info(logmgr, queue)
        logmgr_add_many_discretization_quantities(logmgr, discr, dim,
                                                  extract_vars_for_logging,
                                                  units_for_logging)
        logmgr_set_time(logmgr, current_step, current_t)
        logmgr.add_quantity(log_cfl, interval=nstatus)
        #logmgr_add_package_versions(logmgr)

        logmgr.add_watches([
            ("step.max", "step = {value}, "),
            ("t_sim.max", "sim time: {value:1.6e} s, "),
            ("cfl.max", "cfl = {value:1.4f}\n"),
            ("min_pressure", "------- P (min, max) (Pa) = ({value:1.9e}, "),
            ("max_pressure", "{value:1.9e})\n"),
            ("min_temperature", "------- T (min, max) (K)  = ({value:7g}, "),
            ("max_temperature", "{value:7g})\n"),
            ("t_step.max", "------- step walltime: {value:6g} s, "),
            ("t_log.max", "log walltime: {value:6g} s")
        ])

        try:
            logmgr.add_watches(["memory_usage.max"])
        except KeyError:
            pass

        if use_profiling:
            logmgr.add_watches(["pyopencl_array_time.max"])

        vis_timer = IntervalTimer("t_vis", "Time spent visualizing")
        logmgr.add_quantity(vis_timer)

    visualizer = make_visualizer(discr)

    initname = "flame1d"
    eosname = eos.__class__.__name__
    init_message = make_init_message(dim=dim,
                                     order=order,
                                     nelements=local_nelements,
                                     global_nelements=global_nelements,
                                     dt=current_dt,
                                     t_final=t_final,
                                     nstatus=nstatus,
                                     nviz=nviz,
                                     cfl=current_cfl,
                                     constant_cfl=constant_cfl,
                                     initname=initname,
                                     eosname=eosname,
                                     casename=casename)
    if rank == 0:
        logger.info(init_message)

    get_timestep = partial(inviscid_sim_timestep,
                           discr=discr,
                           t=current_t,
                           dt=current_dt,
                           cfl=current_cfl,
                           eos=eos,
                           t_final=t_final,
                           constant_cfl=constant_cfl)

    def my_rhs(t, state):
        return (
            ns_operator(discr, cv=state, t=t, boundaries=boundaries, eos=eos) +
            eos.get_species_source_terms(cv=state))

    def my_checkpoint(step, t, dt, state, force=False):
        do_health = force or check_step(step, nhealth) and step > 0
        do_viz = force or check_step(step, nviz)
        do_restart = force or check_step(step, nrestart)
        do_status = force or check_step(step, nstatus)

        if do_viz or do_health:
            dv = eos.dependent_vars(state)

        errors = False
        if do_health:
            health_message = ""
            if check_naninf_local(discr, "vol", dv.pressure):
                errors = True
                health_message += "Invalid pressure data found.\n"
            elif check_range_local(discr,
                                   "vol",
                                   dv.pressure,
                                   min_value=1,
                                   max_value=2.e6):
                errors = True
                health_message += "Pressure data failed health check.\n"

        errors = comm.allreduce(errors, MPI.LOR)
        if errors:
            if rank == 0:
                logger.info("Fluid solution failed health check.")
            if health_message:
                logger.info(f"{rank=}:  {health_message}")

        #if check_step(step, nrestart) and step != restart_step and not errors:
        if do_restart or errors:
            filename = restart_path + snapshot_pattern.format(
                step=step, rank=rank, casename=casename)
            restart_dictionary = {
                "local_mesh": local_mesh,
                "order": order,
                "state": state,
                "t": t,
                "step": step,
                "global_nelements": global_nelements,
                "num_parts": nparts
            }
            write_restart_file(actx, restart_dictionary, filename, comm)

        if do_status or do_viz or errors:
            local_cfl = get_inviscid_cfl(discr, eos=eos, dt=dt, cv=state)
            max_cfl = nodal_max(discr, "vol", local_cfl)
            log_cfl.set_quantity(max_cfl)

        #if ((check_step(step, nviz) and step != restart_step) or errors):
        if do_viz or errors:

            def loc_fn(t):
                return flame_start_loc + flame_speed * t

            #exact_soln =  PlanarDiscontinuity(dim=dim, disc_location=loc_fn,
            #sigma=0.0000001, nspecies=nspecies,
            #temperature_left=temp_ignition, temperature_right=temp_unburned,
            #pressure_left=pres_burned, pressure_right=pres_unburned,
            #velocity_left=vel_burned, velocity_right=vel_unburned,
            #species_mass_left=y_burned, species_mass_right=y_unburned)

            reaction_rates = eos.get_production_rates(cv=state)

            # conserved quantities
            viz_fields = [
                #("cv", state),
                ("CV_rho", state.mass),
                ("CV_rhoU", state.momentum[0]),
                ("CV_rhoV", state.momentum[1]),
                ("CV_rhoE", state.energy)
            ]
            # species mass fractions
            viz_fields.extend(
                ("Y_" + species_names[i], state.species_mass[i] / state.mass)
                for i in range(nspecies))
            # dependent variables
            viz_fields.extend([
                ("DV", eos.dependent_vars(state)),
                #("exact_soln", exact_soln),
                ("reaction_rates", reaction_rates),
                ("cfl", local_cfl)
            ])

            write_visfile(discr,
                          viz_fields,
                          visualizer,
                          vizname=viz_path + casename,
                          step=step,
                          t=t,
                          overwrite=True,
                          vis_timer=vis_timer)

        if errors:
            raise RuntimeError("Error detected by user checkpoint, exiting.")

    if rank == 0:
        logging.info("Stepping.")

    (current_step, current_t, current_state) = \
        advance_state(rhs=my_rhs, timestepper=timestepper,
                      checkpoint=my_checkpoint,
                      get_timestep=get_timestep, state=current_state,
                      t_final=t_final, t=current_t, istep=current_step,
                      logmgr=logmgr,eos=eos,dim=dim)

    if rank == 0:
        logger.info("Checkpointing final state ...")
    my_checkpoint(current_step,
                  t=current_t,
                  dt=(current_t - checkpoint_t),
                  state=current_state,
                  force=True)

    if logmgr:
        logmgr.close()
    elif use_profiling:
        print(actx.tabulate_profiling_data())

    exit()
Exemple #5
0
def main(ctx_factory=cl.create_some_context,
         snapshot_pattern="y0euler-{step:06d}-{rank:04d}.pkl",
         restart_step=None, use_profiling=False, use_logmgr=False):
    """Drive the Y0 example."""

    from mpi4py import MPI
    comm = MPI.COMM_WORLD
    rank = 0
    rank = comm.Get_rank()
    nparts = comm.Get_size()

    """logging and profiling"""
    logmgr = initialize_logmgr(use_logmgr, filename="y0euler.sqlite",
        mode="wo", mpi_comm=comm)

    cl_ctx = ctx_factory()
    if use_profiling:
        queue = cl.CommandQueue(cl_ctx,
            properties=cl.command_queue_properties.PROFILING_ENABLE)
        actx = PyOpenCLProfilingArrayContext(queue,
            allocator=cl_tools.MemoryPool(cl_tools.ImmediateAllocator(queue)),
            logmgr=logmgr)
    else:
        queue = cl.CommandQueue(cl_ctx)
        actx = PyOpenCLArrayContext(queue,
            allocator=cl_tools.MemoryPool(cl_tools.ImmediateAllocator(queue)))

    #nviz = 500
    #nrestart = 500
    nviz = 100
    nrestart = 100
    #current_dt = 2.5e-8 # stable with euler
    current_dt = 4e-7 # stable with lrsrk144
    t_final = 5.e-1

    dim = 3
    order = 1
    exittol = .09
    #t_final = 0.001
    current_cfl = 1.0
    vel_init = np.zeros(shape=(dim,))
    vel_inflow = np.zeros(shape=(dim,))
    vel_outflow = np.zeros(shape=(dim,))
    orig = np.zeros(shape=(dim,))
    orig[0] = 0.83
    orig[2] = 0.001
    #vel[0] = 340.0
    #vel_inflow[0] = 100.0  # m/s
    current_t = 0
    casename = "y0euler"
    constant_cfl = False
    nstatus = 10000000000
    rank = 0
    checkpoint_t = current_t
    current_step = 0

    # working gas: CO2 #
    #   gamma = 1.289
    #   MW=44.009  g/mol
    #   cp = 37.135 J/mol-K,
    #   rho= 1.977 kg/m^3 @298K
    gamma_CO2 = 1.289
    R_CO2 = 8314.59/44.009

    # background
    #   100 Pa
    #   298 K
    #   rho = 1.77619667e-3 kg/m^3
    #   velocity = 0,0,0
    rho_bkrnd=1.77619667e-3
    pres_bkrnd=100
    temp_bkrnd=298
     
    # nozzle inflow #
    # 
    # stagnation tempertuare 298 K
    # stagnation pressure 1.5e Pa
    # 
    # isentropic expansion based on the area ratios between the inlet (r=13e-3m) and the throat (r=6.3e-3)
    #
    #  MJA, this is calculated offline, add some code to do it for us
    # 
    #   Mach number=0.139145
    #   pressure=148142
    #   temperature=297.169
    #   density=2.63872
    #   gamma=1.289

    # calculate the inlet Mach number from the area ratio
    nozzleInletRadius = 13.e-3
    nozzleThroatRadius = 6.3e-3
    nozzleInletArea = math.pi*nozzleInletRadius*nozzleInletRadius
    nozzleThroatArea = math.pi*nozzleThroatRadius*nozzleThroatRadius
    inletAreaRatio = nozzleInletArea/nozzleThroatArea

    def getMachFromAreaRatio(area_ratio, gamma, mach_guess=0.01):
        error=1.e-8
        nextError=1.e8
        g=gamma
        M0=mach_guess
        while nextError > error:
            R = ((2/(g+1)+((g-1)/(g+1)*M0*M0))**(((g+1)/(2*g-2))))/M0-area_ratio
            dRdM = (2*((2/(g+1)+((g-1)/(g+1)*M0*M0))**(((g+1)/(2*g-2))))/
                   (2*g-2)*(g-1)/(2/(g+1)+((g-1)/(g+1)*M0*M0))-
                   ((2/(g+1)+((g-1)/(g+1)*M0*M0))**(((g+1)/(2*g-2))))* M0**(-2))
      
            M1=M0-R/dRdM
            nextError=abs(R)
            M0=M1

        return M1


    def getIsentropicPressure(mach, P0, gamma):
        pressure=(1.+(gamma-1.)*0.5*math.pow(mach,2))
        pressure=P0*math.pow(pressure,(-gamma/(gamma-1.)))
        return pressure

  
    def getIsentropicTemperature(mach, T0, gamma):
      temperature=(1.+(gamma-1.)*0.5*math.pow(mach,2))
      temperature=T0*math.pow(temperature,-1.0)
      return temperature


    inlet_mach = getMachFromAreaRatio(area_ratio = inletAreaRatio, gamma=gamma_CO2, mach_guess = 0.01);
    # ramp the stagnation pressure
    start_ramp_pres = 1000
    ramp_interval = 5.e-3
    t_ramp_start = 1e-5
    pres_inflow = getIsentropicPressure(mach=inlet_mach, P0=start_ramp_pres, gamma=gamma_CO2)
    temp_inflow = getIsentropicTemperature(mach=inlet_mach, T0=298, gamma=gamma_CO2)
    rho_inflow = pres_inflow/temp_inflow/R_CO2

    print(f'inlet Mach number {inlet_mach}')
    print(f'inlet temperature {temp_inflow}')
    print(f'inlet pressure {pres_inflow}')

    end_ramp_pres = 150000
    pres_inflow_final = getIsentropicPressure(mach=inlet_mach, P0=end_ramp_pres, gamma=gamma_CO2)

    print(f'final inlet pressure {pres_inflow_final}')


    #pres_inflow=148142
    #temp_inflow=297.169
    #rho_inflow=2.63872
    #mach_inflow=infloM = 0.139145
    vel_inflow[0] = inlet_mach*math.sqrt(gamma_CO2*pres_inflow/rho_inflow)

    # starting pressure for the inflow ramp

    #timestepper = rk4_step
    #timestepper = lsrk54_step
    timestepper = lsrk144_step
    #timestepper = euler_step
    eos = IdealSingleGas(gamma=gamma_CO2, gas_const=R_CO2)
    bulk_init = Discontinuity(dim=dim, x0=-.30,sigma=0.005,
    #bulk_init = Discontinuity(dim=dim, x0=-.31,sigma=0.04,
                              rhol=rho_inflow, rhor=rho_bkrnd,
                              pl=pres_inflow, pr=pres_bkrnd,
                              ul=vel_inflow, ur=vel_outflow)
    #inflow_init = Lump(dim=dim, rho0=rho_inflow, p0=pres_inflow,
                       #center=orig, velocity=vel_inflow, rhoamp=0.0)
    #outflow_init = Lump(dim=dim, rho0=rho_bkrnd, p0=pres_bkrnd,
                       #center=orig, velocity=vel_outflow, rhoamp=0.0)

    # pressure ramp function
    def inflow_ramp_pressure(t, startP=start_ramp_pres, finalP=end_ramp_pres, 
                             ramp_interval=ramp_interval, t_ramp_start=t_ramp_start):
      if t > t_ramp_start:
          rampPressure = min(finalP, startP+(t-t_ramp_start)/ramp_interval*(finalP-startP))
      else:
          rampPressure = startP
      return rampPressure


    class IsentropicInflow:

        def __init__(self, *, dim=1, direc=0, T0=298, P0=1e5, mach= 0.01, p_fun = None):

            self._P0 = P0
            self._T0 = T0
            self._dim = dim
            self._direc = direc
            self._mach = mach
            if p_fun is not None:
              self._p_fun = p_fun
    
        def __call__(self, x_vec, *, t=0, eos):
    
    
            if self._p_fun is not None:
                P0 = self._p_fun(t)
            else:
                P0 = self._P0
            T0 = self._T0

            gamma = eos.gamma()
            gas_const = eos.gas_const()
            pressure = getIsentropicPressure(mach=self._mach, P0=P0, gamma=gamma)
            temperature = getIsentropicTemperature(mach=self._mach, T0=T0, gamma=gamma)
            rho = pressure/temperature/gas_const

            #print(f'ramp Mach number {self._mach}')
            #print(f'ramp stagnation pressure {P0}')
            #print(f'ramp stagnation temperature {T0}')
            #print(f'ramp pressure {pressure}')
            #print(f'ramp temperature {temperature}')

            velocity = np.zeros(shape=(self._dim,)) 
            velocity[self._direc] = self._mach*math.sqrt(gamma*pressure/rho)
    
            mass = 0.0*x_vec[0] + rho
            mom = velocity*mass
            energy = (pressure/(gamma - 1.0)) + np.dot(mom, mom)/(2.0*mass)
            from mirgecom.euler import join_conserved
            return join_conserved(dim=self._dim, mass=mass, momentum=mom, energy=energy)


    inflow_init = IsentropicInflow(dim=dim, T0=298, P0=start_ramp_pres, 
                                   mach = inlet_mach , p_fun=inflow_ramp_pressure)
    outflow_init = Uniform(dim=dim, rho=rho_bkrnd, p=pres_bkrnd,
                           velocity=vel_outflow)

    inflow = PrescribedBoundary(inflow_init)
    outflow = PrescribedBoundary(outflow_init)
    wall = AdiabaticSlipBoundary()
    dummy = DummyBoundary()

    alpha_sc = 0.5
    # s0 is ~p^-4 
    #s0_sc = -11.0
    s0_sc = -5.0
    # kappa is empirical ...
    kappa_sc = 0.5
    print(f"Shock capturing parameters: alpha {alpha_sc}, s0 {s0_sc}, kappa {kappa_sc}")

    # timestep estimate
    #wave_speed = max(mach2*c_bkrnd,c_shkd+velocity2[0])
    #char_len = 0.001
    #area=char_len*char_len/2
    #perimeter = 2*char_len+math.sqrt(2*char_len*char_len)
    #h = 2*area/perimeter

    #dt_est = 1/(wave_speed*order*order/h)
    #print(f"Time step estimate {dt_est}\n")
#
    #dt_est_visc = 1/(wave_speed*order*order/h+alpha_sc*order*order*order*order/h/h)
    #print(f"Viscous timestep estimate {dt_est_visc}\n")

    from grudge import sym
    boundaries = {sym.DTAG_BOUNDARY("Inflow"): inflow,
                  sym.DTAG_BOUNDARY("Outflow"): outflow,
                  sym.DTAG_BOUNDARY("Wall"): wall}

    if restart_step is None:
        local_mesh, global_nelements = create_parallel_grid(comm, get_pseudo_y0_mesh)
        local_nelements = local_mesh.nelements

    else:  # Restart
        with open(snapshot_pattern.format(step=restart_step, rank=rank), "rb") as f:
            restart_data = pickle.load(f)

        local_mesh = restart_data["local_mesh"]
        local_nelements = local_mesh.nelements
        global_nelements = restart_data["global_nelements"]

        assert comm.Get_size() == restart_data["num_parts"]

    if rank == 0:
        logging.info("Making discretization")
    discr = EagerDGDiscretization(
        actx, local_mesh, order=order, mpi_communicator=comm
    )
    nodes = thaw(actx, discr.nodes())

    if restart_step is None:
        if rank == 0:
            logging.info("Initializing soln.")
        # for Discontinuity initial conditions
        current_state = bulk_init(0, nodes, eos=eos)
        # for uniform background initial condition
        #current_state = bulk_init(nodes, eos=eos)
    else:
        current_t = restart_data["t"]
        current_step = restart_step

        current_state = unflatten(
            actx, discr.discr_from_dd("vol"),
            obj_array_vectorize(actx.from_numpy, restart_data["state"]))

    vis_timer = None

    if logmgr:
        logmgr_add_device_name(logmgr, queue)
        logmgr_add_many_discretization_quantities(logmgr, discr, dim,
            extract_vars_for_logging, units_for_logging)
        #logmgr_add_package_versions(logmgr)

        logmgr.add_watches(["step.max", "t_sim.max", "t_step.max", "t_log.max",
                            "min_pressure", "max_pressure",
                            "min_temperature", "max_temperature"])

        try:
            logmgr.add_watches(["memory_usage.max"])
        except KeyError:
            pass

        if use_profiling:
            logmgr.add_watches(["pyopencl_array_time.max"])

        vis_timer = IntervalTimer("t_vis", "Time spent visualizing")
        logmgr.add_quantity(vis_timer)

    visualizer = make_visualizer(discr, discr.order + 3
                                 if discr.dim == 2 else discr.order)
    #    initname = initializer.__class__.__name__
    initname = "pseudoY0"
    eosname = eos.__class__.__name__
    init_message = make_init_message(dim=dim, order=order,
                                     nelements=local_nelements,
                                     global_nelements=global_nelements,
                                     dt=current_dt, t_final=t_final,
                                     nstatus=nstatus, nviz=nviz,
                                     cfl=current_cfl,
                                     constant_cfl=constant_cfl,
                                     initname=initname,
                                     eosname=eosname, casename=casename)
    if rank == 0:
        logger.info(init_message)

    get_timestep = partial(inviscid_sim_timestep, discr=discr, t=current_t,
                           dt=current_dt, cfl=current_cfl, eos=eos,
                           t_final=t_final, constant_cfl=constant_cfl)

    def my_rhs(t, state):
        #return inviscid_operator(discr, eos=eos, boundaries=boundaries, q=state, t=t)
        return ( inviscid_operator(discr, q=state, t=t,boundaries=boundaries, eos=eos)
               + artificial_viscosity(discr,t=t, r=state, eos=eos, boundaries=boundaries,
               alpha=alpha_sc, s0=s0_sc, kappa=kappa_sc))

    def my_checkpoint(step, t, dt, state):

        write_restart = (check_step(step, nrestart)
                         if step != restart_step else False)
        if write_restart is True:
            with open(snapshot_pattern.format(step=step, rank=rank), "wb") as f:
                pickle.dump({
                    "local_mesh": local_mesh,
                    "state": obj_array_vectorize(actx.to_numpy, flatten(state)),
                    "t": t,
                    "step": step,
                    "global_nelements": global_nelements,
                    "num_parts": nparts,
                    }, f)

        return sim_checkpoint(discr=discr, visualizer=visualizer, eos=eos,
                              q=state, vizname=casename,
                              step=step, t=t, dt=dt, nstatus=nstatus,
                              nviz=nviz, exittol=exittol,
                              constant_cfl=constant_cfl, comm=comm, vis_timer=vis_timer,
                              overwrite=True,s0=s0_sc,kappa=kappa_sc)

    if rank == 0:
        logging.info("Stepping.")

    (current_step, current_t, current_state) = \
        advance_state(rhs=my_rhs, timestepper=timestepper,
                      checkpoint=my_checkpoint,
                      get_timestep=get_timestep, state=current_state,
                      t_final=t_final, t=current_t, istep=current_step,
                      logmgr=logmgr,eos=eos,dim=dim)

    if rank == 0:
        logger.info("Checkpointing final state ...")

    my_checkpoint(current_step, t=current_t,
                  dt=(current_t - checkpoint_t),
                  state=current_state)

    if current_t - t_final < 0:
        raise ValueError("Simulation exited abnormally")

    if logmgr:
        logmgr.close()
    elif use_profiling:
        print(actx.tabulate_profiling_data())
Exemple #6
0
def main(use_profiling=False, use_logmgr=False, lazy_eval: bool = False):
    """Drive the example."""
    cl_ctx = cl.create_some_context()

    logmgr = initialize_logmgr(use_logmgr, filename="wave.sqlite", mode="wu")

    if use_profiling:
        if lazy_eval:
            raise RuntimeError("Cannot run lazy with profiling.")
        queue = cl.CommandQueue(
            cl_ctx, properties=cl.command_queue_properties.PROFILING_ENABLE)
        actx = PyOpenCLProfilingArrayContext(
            queue,
            allocator=cl_tools.MemoryPool(cl_tools.ImmediateAllocator(queue)))
    else:
        queue = cl.CommandQueue(cl_ctx)
        if lazy_eval:
            actx = PytatoPyOpenCLArrayContext(queue)
        else:
            actx = PyOpenCLArrayContext(
                queue,
                allocator=cl_tools.MemoryPool(
                    cl_tools.ImmediateAllocator(queue)))

    dim = 2
    nel_1d = 16
    from meshmode.mesh.generation import generate_regular_rect_mesh

    mesh = generate_regular_rect_mesh(a=(-0.5, ) * dim,
                                      b=(0.5, ) * dim,
                                      nelements_per_axis=(nel_1d, ) * dim)

    order = 3

    discr = EagerDGDiscretization(actx, mesh, order=order)

    current_cfl = 0.485
    wave_speed = 1.0
    from grudge.dt_utils import characteristic_lengthscales
    nodal_dt = characteristic_lengthscales(actx, discr) / wave_speed
    from grudge.op import nodal_min
    dt = actx.to_numpy(current_cfl * nodal_min(discr, "vol", nodal_dt))[()]

    print("%d elements" % mesh.nelements)

    fields = flat_obj_array(bump(actx, discr),
                            [discr.zeros(actx) for i in range(discr.dim)])

    if logmgr:
        logmgr_add_cl_device_info(logmgr, queue)
        logmgr_add_device_memory_usage(logmgr, queue)

        logmgr.add_watches(["step.max", "t_step.max", "t_log.max"])

        try:
            logmgr.add_watches(
                ["memory_usage_python.max", "memory_usage_gpu.max"])
        except KeyError:
            pass

        if use_profiling:
            logmgr.add_watches(["multiply_time.max"])

        vis_timer = IntervalTimer("t_vis", "Time spent visualizing")
        logmgr.add_quantity(vis_timer)

    vis = make_visualizer(discr)

    def rhs(t, w):
        return wave_operator(discr, c=wave_speed, w=w)

    compiled_rhs = actx.compile(rhs)

    t = 0
    t_final = 1
    istep = 0
    while t < t_final:
        if logmgr:
            logmgr.tick_before()

        fields = thaw(freeze(fields, actx), actx)
        fields = rk4_step(fields, t, dt, compiled_rhs)

        if istep % 10 == 0:
            if use_profiling:
                print(actx.tabulate_profiling_data())
            print(istep, t, actx.to_numpy(discr.norm(fields[0], np.inf)))
            vis.write_vtk_file("fld-wave-%04d.vtu" % istep, [
                ("u", fields[0]),
                ("v", fields[1:]),
            ],
                               overwrite=True)

        t += dt
        istep += 1

        if logmgr:
            set_dt(logmgr, dt)
            logmgr.tick_after()
Exemple #7
0
def main(use_profiling=False):
    """Drive the example."""
    cl_ctx = cl.create_some_context()
    if use_profiling:
        queue = cl.CommandQueue(
            cl_ctx, properties=cl.command_queue_properties.PROFILING_ENABLE)
        actx = PyOpenCLProfilingArrayContext(
            queue,
            allocator=cl_tools.MemoryPool(cl_tools.ImmediateAllocator(queue)))
    else:
        queue = cl.CommandQueue(cl_ctx)
        actx = PyOpenCLArrayContext(queue,
                                    allocator=cl_tools.MemoryPool(
                                        cl_tools.ImmediateAllocator(queue)))

    dim = 2
    nel_1d = 16
    from meshmode.mesh.generation import generate_regular_rect_mesh

    mesh = generate_regular_rect_mesh(a=(-0.5, ) * dim,
                                      b=(0.5, ) * dim,
                                      nelements_per_axis=(nel_1d, ) * dim)

    order = 3

    if dim == 2:
        # no deep meaning here, just a fudge factor
        dt = 0.7 / (nel_1d * order**2)
    elif dim == 3:
        # no deep meaning here, just a fudge factor
        dt = 0.4 / (nel_1d * order**2)
    else:
        raise ValueError("don't have a stable time step guesstimate")

    print("%d elements" % mesh.nelements)

    discr = EagerDGDiscretization(actx, mesh, order=order)

    fields = flat_obj_array(bump(actx, discr),
                            [discr.zeros(actx) for i in range(discr.dim)])

    vis = make_visualizer(discr)

    def rhs(t, w):
        return wave_operator(discr, c=1, w=w)

    t = 0
    t_final = 3
    istep = 0
    while t < t_final:
        fields = rk4_step(fields, t, dt, rhs)

        if istep % 10 == 0:
            if use_profiling:
                print(actx.tabulate_profiling_data())
            print(istep, t, discr.norm(fields[0], np.inf))
            vis.write_vtk_file("fld-wave-eager-%04d.vtu" % istep, [
                ("u", fields[0]),
                ("v", fields[1:]),
            ])

        t += dt
        istep += 1