Exemplo n.º 1
0
def main(mech_filename: str = "data/mechanisms/HeliumArgon.xml",
         show_results: bool = True,
         results_location: Optional[str] = None) -> None:
    #parameters
    fontsize = 12
    tFinal = 7.5e-3
    p5, p1 = 18 * ct.one_atm, 0.48e5
    T5 = 1698.0
    g4 = g1 = 5.0 / 3.0  #monatomic gas in driver and driven sections
    W4, W1 = 4.002602, 39.948  #Helium and argon
    MachReduction = 0.985  #account for shock wave attenuation
    nXCoarse, nXFine = 200, 1000  #mesh resolution
    LDriver, LDriven = 3.0, 5.0
    DDriver, DDriven = 7.5e-2, 5.0e-2
    plt.close("all")
    mpl.rcParams['font.size'] = fontsize
    plt.rc('text', usetex=True)

    #set up geometry
    xLower = -LDriver
    xUpper = LDriven
    xShock = 0.0
    Delta = 10 * (xUpper - xLower) / float(nXFine)
    geometry = (nXCoarse, xLower, xUpper, xShock)
    DInner = lambda x: np.zeros_like(x)
    dDInnerdx = lambda x: np.zeros_like(x)

    def DOuter(x):
        return smoothingFunction(x, xShock, Delta, DDriver, DDriven)

    def dDOuterdx(x):
        return dSFdx(x, xShock, Delta, DDriver, DDriven)

    A = lambda x: np.pi / 4.0 * (DOuter(x)**2.0 - DInner(x)**2.0)
    dAdx = lambda x: np.pi / 2.0 * (DOuter(x) * dDOuterdx(x) - DInner(x) *
                                    dDInnerdx(x))
    dlnAdx = lambda x, t: dAdx(x) / A(x)

    #compute the gas dynamics
    def res(Ms1):
        return p5/p1-((2.0*g1*Ms1**2.0-(g1-1.0))/(g1+1.0)) \
               *((-2.0*(g1-1.0)+Ms1**2.0*(3.0*g1-1.0))/(2.0+Ms1**2.0*(g1-1.0)))

    Ms1 = newton(res, 2.0)
    Ms1 *= MachReduction
    T5oT1 = (2.0*(g1-1.0)*Ms1**2.0+3.0-g1) \
            *((3.0*g1-1.0)*Ms1**2.0-2.0*(g1-1.0)) \
            /((g1+1.0)**2.0*Ms1**2.0)
    T1 = T5 / T5oT1
    a1oa4 = np.sqrt(W4 / W1)
    p4op1 = (1.0+2.0*g1/(g1+1.0)*(Ms1**2.0-1.0)) \
            *(1.0-(g4-1.0)/(g4+1.0)*a1oa4*(Ms1-1.0/Ms1))**(-2.0*g4/(g4-1.0))
    p4 = p1 * p4op1

    #set up the gasses
    u1 = 0.0
    u4 = 0.0
    #initially 0 velocity
    gas1 = ct.Solution(mech_filename)
    gas4 = ct.Solution(mech_filename)
    T4 = T1
    #assumed
    gas1.TPX = T1, p1, "AR:1"
    gas4.TPX = T4, p4, "HE:1"

    #set up solver parameters
    boundaryConditions = ['reflecting', 'reflecting']
    state1 = (gas1, u1)
    state4 = (gas4, u4)
    ss = stanShock(
        gas1,
        initializeRiemannProblem=(state4, state1, geometry),
        boundaryConditions=boundaryConditions,
        cfl=.9,
        outputEvery=100,
        includeBoundaryLayerTerms=True,
        Tw=T1,  #assume wall temperature is in thermal eq. with gas
        DOuter=DOuter,
        dlnAdx=dlnAdx)

    #Solve
    t0 = time.perf_counter()
    tTest = 2e-3
    tradeoffParam = 1.0
    eps = 0.01**2.0 + tradeoffParam * 0.01**2.0
    ss.optimizeDriverInsert(tFinal,
                            p5=p5,
                            tTest=tTest,
                            tradeoffParam=tradeoffParam,
                            eps=eps)
    t1 = time.perf_counter()
    print("The process took ", t1 - t0)

    #recalculate at higher resolution with the insert
    geometry = (nXFine, xLower, xUpper, xShock)
    gas1.TPX = T1, p1, "AR:1"
    gas4.TPX = T4, p4, "HE:1"
    ss = stanShock(
        gas1,
        initializeRiemannProblem=(state4, state1, geometry),
        boundaryConditions=boundaryConditions,
        cfl=.9,
        outputEvery=100,
        includeBoundaryLayerTerms=True,
        Tw=T1,  #assume wall temperature is in thermal eq. with gas
        DOuter=DOuter,
        DInner=ss.DInner,
        dlnAdx=ss.dlnAdx)
    ss.addXTDiagram("p")
    ss.addXTDiagram("T")
    ss.addProbe(max(ss.x))  #end wall probe
    t0 = time.perf_counter()
    ss.advanceSimulation(tFinal)
    t1 = time.perf_counter()
    print("The process took ", t1 - t0)
    pInsert = np.array(ss.probes[0].p)
    tInsert = np.array(ss.probes[0].t)
    ss.plotXTDiagram(ss.XTDiagrams["t"], limits=[200.0, 1800.0])
    ss.plotXTDiagram(ss.XTDiagrams["p"], limits=[0.5, 25])
    xInsert = ss.x
    DOuterInsert = ss.DOuter(ss.x)
    DInnerInsert = ss.DInner(ss.x)

    #recalculate at higher resolution without the insert
    gas1.TPX = T1, p1, "AR:1"
    gas4.TPX = T4, p4, "HE:1"
    ss = stanShock(
        gas1,
        initializeRiemannProblem=(state4, state1, geometry),
        boundaryConditions=boundaryConditions,
        cfl=.9,
        outputEvery=100,
        includeBoundaryLayerTerms=True,
        Tw=T1,  #assume wall temperature is in thermal eq. with gas
        DOuter=DOuter,
        dlnAdx=dlnAdx)
    ss.addXTDiagram("p")
    ss.addXTDiagram("T")
    ss.addProbe(max(ss.x))  #end wall probe
    t0 = time.perf_counter()
    ss.advanceSimulation(tFinal)
    t1 = time.perf_counter()
    print("The process took ", t1 - t0)
    pNoInsert = np.array(ss.probes[0].p)
    tNoInsert = np.array(ss.probes[0].t)
    ss.plotXTDiagram(ss.XTDiagrams["t"], limits=[200.0, 1800.0])
    ss.plotXTDiagram(ss.XTDiagrams["p"], limits=[0.5, 25])

    #plot
    plt.figure()
    plt.plot(tNoInsert / 1e-3,
             pNoInsert / 1e5,
             'k',
             label="$\mathrm{No\ Insert}$")
    plt.plot(tInsert / 1e-3,
             pInsert / 1e5,
             'r',
             label="$\mathrm{Optimized\ Insert}$")
    plt.xlabel("$t\ [\mathrm{ms}]$")
    plt.ylabel("$p\ [\mathrm{bar}]$")
    plt.legend(loc="best")
    plt.tight_layout()

    plt.figure()
    plt.plot(xInsert, DOuterInsert, 'k', label="$D_\mathrm{o}$")
    plt.plot(xInsert, DInnerInsert, 'r', label="$D_\mathrm{i}$")
    plt.xlabel("$x\ [\mathrm{m}]$")
    plt.ylabel("$D\ [\mathrm{m}]$")
    plt.legend(loc="best")
    plt.tight_layout()
    if show_results:
        plt.show()

    if results_location is not None:
        np.savez(os.path.join(results_location, "optimization.npz"),
                 pressure_with_insert=pInsert,
                 pressure_without_insert=pNoInsert,
                 insert_diameter=DInnerInsert,
                 shock_tube_diameter=DOuterInsert,
                 position=xInsert,
                 time_with_insert=tInsert,
                 time_without_insert=tNoInsert)
        plt.savefig(os.path.join(results_location, "optimization.png"))
Exemplo n.º 2
0
def main(data_filename: str = "data/validation/case2.csv",
         mech_filename: str = "data/mechanisms/Nitrogen.xml",
         show_results: bool = True,
         results_location: Optional[str] = None) -> None:
    #=============================================================================
    #provided condtions for Case 2
    Ms = 2.518914
    T1 = 291.75
    p1 = 2026.499994
    p2 = 14730.642333
    tFinal = 60e-3

    #plotting parameters
    fontsize = 12

    #provided geometry
    DDriven = 4.5 * 0.0254
    DDriver = 7.0 * 0.0254
    LDriver = 142.0 * 0.0254
    LDriven = 9.73

    #Set up gasses and determine the initial pressures
    u1 = 0.0
    u4 = 0.0
    #initially 0 velocity
    gas1 = ct.Solution(mech_filename)
    gas4 = ct.Solution(mech_filename)
    T4 = T1
    #assumed
    gas1.TP = T1, p1
    gas4.TP = T4, p1  #use p1 as a place holder
    g1 = gas1.cp / gas1.cv
    g4 = gas4.cp / gas4.cv
    a4oa1 = np.sqrt(g4 / g1 * T4 / T1 * gas1.mean_molecular_weight /
                    gas4.mean_molecular_weight)
    p4 = p2 * (1.0 - (g4 - 1.0) / (g1 + 1.0) / a4oa1 *
               (Ms - 1.0 / Ms))**(-2.0 * g4 /
                                  (g4 - 1.0))  #from handbook of shock waves
    p4 *= DDriven / DDriver  #just made this up
    p4 *= 1.05
    gas4.TP = T4, p4

    #set up geometry
    nX = 1000  #mesh resolution
    xLower = -LDriver
    xUpper = LDriven
    xShock = 0.0
    geometry = (nX, xLower, xUpper, xShock)
    DeltaD = DDriven - DDriver
    DeltaX = (xUpper - xLower
              ) / float(nX) * 10  #diffuse area change for numerical stability

    #DeltaX = 0.75 #from Eduardo's case
    def D(x):
        diameter = DDriven + (DeltaD / DeltaX) * (x - xShock)
        diameter[x < (xShock - DeltaX)] = DDriver
        diameter[x > xShock] = DDriven
        return diameter

    def dDdx(x):
        dDiameterdx = np.ones(len(x)) * (DeltaD / DeltaX)
        dDiameterdx[x < (xShock - DeltaX)] = 0.0
        dDiameterdx[x > xShock] = 0.0
        return dDiameterdx

    A = lambda x: np.pi / 4.0 * D(x)**2.0
    dAdx = lambda x: np.pi / 2.0 * D(x) * dDdx(x)
    dlnAdx = lambda x, t: dAdx(x) / A(x)

    #set up solver parameters
    print("Solving with boundary layer terms")
    boundaryConditions = ['reflecting', 'reflecting']
    state1 = (gas1, u1)
    state4 = (gas4, u4)
    ssbl = stanShock(
        gas1,
        initializeRiemannProblem=(state4, state1, geometry),
        boundaryConditions=boundaryConditions,
        cfl=.9,
        outputEvery=100,
        includeBoundaryLayerTerms=True,
        Tw=T1,  #assume wall temperature is in thermal eq. with gas
        DOuter=D,
        dlnAdx=dlnAdx)
    ssbl.addProbe(max(ssbl.x))  #end wall probe

    #Solve
    t0 = time.perf_counter()
    ssbl.advanceSimulation(tFinal)
    t1 = time.perf_counter()
    print("The process took ", t1 - t0)

    #without  boundary layer model
    print("Solving without boundary layer model")
    boundaryConditions = ['reflecting', 'reflecting']
    gas1.TP = T1, p1
    gas4.TP = T4, p4
    ssnbl = stanShock(gas1,
                      initializeRiemannProblem=(state4, state1, geometry),
                      boundaryConditions=boundaryConditions,
                      cfl=.9,
                      outputEvery=100,
                      includeBoundaryLayerTerms=False,
                      DOuter=D,
                      dlnAdx=dlnAdx)
    ssnbl.addProbe(max(ssnbl.x))  #end wall probe

    #Solve
    t0 = time.perf_counter()
    ssnbl.advanceSimulation(tFinal)
    t1 = time.perf_counter()
    print("The process took ", t1 - t0)

    #import shock tube data
    tExp, pExp = getPressureData(data_filename)
    timeDifference = (
        12.211 -
        8.10) / 1000.0  #difference between the test data and simulation times
    tExp += timeDifference

    #make plots of probe and XT diagrams
    plt.close("all")
    mpl.rcParams['font.size'] = fontsize
    plt.rc('text', usetex=True)
    plt.figure(figsize=(4, 4))
    plt.plot(np.array(ssnbl.probes[0].t) * 1000.0,
             np.array(ssnbl.probes[0].p) / 1.0e5,
             'k',
             label="$\mathrm{Without\ BL\ Model}$",
             linewidth=2.0)
    plt.plot(np.array(ssbl.probes[0].t) * 1000.0,
             np.array(ssbl.probes[0].p) / 1.0e5,
             'r',
             label="$\mathrm{With\ BL\ Model}$",
             linewidth=2.0)
    plt.plot(tExp * 1000.0,
             pExp / 1.0e5,
             label="$\mathrm{Experiment}$",
             alpha=0.7)
    plt.axis([0, 60, -.25, 2.75])
    plt.xlabel("$t\ [\mathrm{ms}]$")
    plt.ylabel("$p\ [\mathrm{bar}]$")
    plt.legend(loc="lower right")
    plt.tight_layout()
    if show_results:
        plt.show()

    if results_location is not None:
        np.savez(os.path.join(results_location, "case2.npz"),
                 pressure_with_boundary_layer=ssbl.probes[0].p,
                 pressure_without_boundary_layer=ssnbl.probes[0].p,
                 time_with_boundary_layer=ssbl.probes[0].t,
                 time_without_boundary_layer=ssnbl.probes[0].t)
        plt.savefig(os.path.join(results_location, "case2.png"))
Exemplo n.º 3
0
def main(data_filename: str = "data/validation/case4.png",
         mech_filename: str = "data/mechanisms/N2O2HeAr.xml",
         show_results: bool = True,
         results_location: Optional[str] = None) -> None:
    #=============================================================================
    #provided condtions for Case4
    T1 = T4 = 292.05
    p1 = 390.0 * 133.322
    p4 = 82.0 * 6894.76 * 0.9
    tFinal = 60e-3

    #plotting parameters
    fontsize = 12

    #provided geometry
    DDriven = 4.5 * 0.0254
    DDriver = DDriven
    LDriver = 142.0 * 0.0254
    LDriven = 9.73

    #Set up gasses and determine the initial pressures
    u1 = 0.0
    u4 = 0.0
    #initially 0 velocity
    gas1 = ct.Solution(mech_filename)
    gas4 = ct.Solution(mech_filename)
    T4 = T1
    #assumed
    gas1.TPX = T1, p1, "O2:0.21,AR:0.79"
    gas4.TPX = T4, p4, "HE:0.25,N2:0.75"

    #set up geometry
    nX = 1000  #mesh resolution
    xLower = -LDriver
    xUpper = LDriven
    xShock = 0.0
    geometry = (nX, xLower, xUpper, xShock)
    #arrays from HTGL
    xInterp = -0.0254 * np.array([
        142, 140, 130, 120, 110, 100, 90, 80, 70, 60, 50, 40, 36, 37, 30, 20,
        10, 0
    ])
    dInterp = 0.0254 * np.array([
        3.25, 3.21, 3.01, 2.81, 2.61, 2.41, 2.21, 2.01, 1.81, 1.61, 1.41, 1.21,
        1.13, 0.00, 0.00, 0.00, 0.00, 0.00
    ])
    dDInterpdxInterp = (dInterp[1:] - dInterp[:-1]) / (xInterp[1:] -
                                                       xInterp[:-1])

    def DOuter(x):
        nX = x.shape[0]
        return DDriven * np.ones(nX)

    def DInner(x):
        diameter = np.interp(x, xInterp, dInterp)
        return diameter

    def dDOuterdx(x):
        return np.zeros(nX)

    def dDInnerdx(x):
        dDiameterdx = np.interp(x, xInterp[:-1], dDInterpdxInterp)
        return dDiameterdx

    A = lambda x: np.pi / 4.0 * (DOuter(x)**2.0 - DInner(x)**2.0)
    dAdx = lambda x: np.pi / 2.0 * (DOuter(x) * dDOuterdx(x) - DInner(x) *
                                    dDInnerdx(x))
    dlnAdx = lambda x, t: dAdx(x) / A(x)

    #solve with boundary layer model
    boundaryConditions = ['reflecting', 'reflecting']
    state1 = (gas1, u1)
    state4 = (gas4, u4)
    ssbl = stanShock(
        gas1,
        initializeRiemannProblem=(state4, state1, geometry),
        boundaryConditions=boundaryConditions,
        cfl=.9,
        outputEvery=100,
        includeBoundaryLayerTerms=True,
        Tw=T1,  #assume wall temperature is in thermal eq. with gas
        DInner=DInner,
        DOuter=DOuter,
        dlnAdx=dlnAdx)
    ssbl.addProbe(max(ssbl.x))  #end wall probe
    ssbl.addXTDiagram("p")
    ssbl.addXTDiagram("T")

    #adjust for partial filling strategy
    XN2Lower = 0.80  #assume smearing during fill
    XN2Upper = 1.5 - XN2Lower
    dx = ssbl.x[1] - ssbl.x[0]
    dV = A(ssbl.x) * dx
    VDriver = np.sum(dV[ssbl.x < xShock])
    V = np.cumsum(dV)
    V -= V[0] / 2.0  #center
    VNorms = V / VDriver
    #get gas properties
    iHE, iN2 = gas4.species_index("HE"), gas4.species_index("N2")
    for iX, VNorm in enumerate(VNorms):
        if VNorm <= 1.0:
            #nitrogen and helium
            X = np.zeros(gas4.n_species)
            XN2 = XN2Lower + (XN2Upper - XN2Lower) * VNorm
            XHE = 1.0 - XN2
            X[[iHE, iN2]] = XHE, XN2
            gas4.TPX = T4, p4, X
            ssbl.r[iX] = gas4.density
            ssbl.Y[iX, :] = gas4.Y
            ssbl.gamma[iX] = gas4.cp / gas4.cv

    #Solve
    t0 = time.perf_counter()
    ssbl.advanceSimulation(tFinal)
    t1 = time.perf_counter()
    print("The process took ", t1 - t0)

    #Solve without boundayr layer model
    boundaryConditions = ['reflecting', 'reflecting']
    gas1.TP = T1, p1
    gas4.TP = T4, p4
    ssnbl = stanShock(
        gas1,
        initializeRiemannProblem=(state4, state1, geometry),
        boundaryConditions=boundaryConditions,
        cfl=.9,
        outputEvery=100,
        includeBoundaryLayerTerms=False,
        Tw=T1,  #assume wall temperature is in thermal eq. with gas
        DInner=DInner,
        DOuter=DOuter,
        dlnAdx=dlnAdx)
    ssnbl.addProbe(max(ssnbl.x))  #end wall probe
    ssnbl.addXTDiagram("p")
    ssnbl.addXTDiagram("T")

    #adjust for partial filling strategy
    XN2Lower = 0.80  #assume smearing during fill
    XN2Upper = 1.5 - XN2Lower
    dx = ssnbl.x[1] - ssnbl.x[0]
    dV = A(ssnbl.x) * dx
    VDriver = np.sum(dV[ssnbl.x < xShock])
    V = np.cumsum(dV)
    V -= V[0] / 2.0  #center
    VNorms = V / VDriver
    #get gas properties
    iHE, iN2 = gas4.species_index("HE"), gas4.species_index("N2")
    for iX, VNorm in enumerate(VNorms):
        if VNorm <= 1.0:
            #nitrogen and helium
            X = np.zeros(gas4.n_species)
            XN2 = XN2Lower + (XN2Upper - XN2Lower) * VNorm
            XHE = 1.0 - XN2
            X[[iHE, iN2]] = XHE, XN2
            gas4.TPX = T4, p4, X
            ssnbl.r[iX] = gas4.density
            ssnbl.Y[iX, :] = gas4.Y
            ssnbl.gamma[iX] = gas4.cp / gas4.cv

    #Solve
    t0 = time.perf_counter()
    ssnbl.advanceSimulation(tFinal)
    t1 = time.perf_counter()
    print("The process took ", t1 - t0)

    #import shock tube data
    tExp, pExp = getPressureData(data_filename)
    timeDifference = (
        18.6 -
        6.40) / 1000.0  #difference between the test data and simulation times
    tExp += timeDifference

    #make plots of probe and XT diagrams
    plt.close("all")
    mpl.rcParams['font.size'] = fontsize
    plt.rc('text', usetex=True)
    plt.figure(figsize=(4, 4))
    plt.plot(np.array(ssnbl.probes[0].t) * 1000.0,
             np.array(ssnbl.probes[0].p) / 1.0e5,
             'k',
             label="$\mathrm{Without\ BL\ Model}$",
             linewidth=2.0)
    plt.plot(np.array(ssbl.probes[0].t) * 1000.0,
             np.array(ssbl.probes[0].p) / 1.0e5,
             'r',
             label="$\mathrm{With\ BL\ Model}$",
             linewidth=2.0)
    plt.plot(tExp * 1000.0,
             pExp / 1.0e5,
             label="$\mathrm{Experiment}$",
             alpha=0.7)
    plt.axis([0, 60, 0, 5])
    plt.xlabel("$t\ [\mathrm{ms}]$")
    plt.ylabel("$p\ [\mathrm{bar}]$")
    plt.legend(loc="lower right")
    plt.tight_layout()
    if show_results:
        plt.show()

    if results_location is not None:
        np.savez(os.path.join(results_location, "case4.npz"),
                 pressure_with_boundary_layer=ssbl.probes[0].p,
                 pressure_without_boundary_layer=ssnbl.probes[0].p,
                 time_with_boundary_layer=ssbl.probes[0].t,
                 time_without_boundary_layer=ssnbl.probes[0].t)
        plt.savefig(os.path.join(results_location, "case4.png"))
Exemplo n.º 4
0
def main(mech_filename: str = "data/mechanisms/Hong.xml",
         show_results: bool = True,
         results_location: Optional[str] = None) -> None:
    #user parameters
    TU=300.0
    p = 1e5
    estFlameThickness=1e-2
    ntFlowThrough=.1
    fontsize=12
    f = 0.1 #factor to reduce Cantera domain


    #find the initial state of the fluids
    gas = ct.Solution(mech_filename)
    unburnedState = TU,p,"H2:2,O2:1,N2:3.76"
    gas.TPX = unburnedState

    #get the flame thickness
    _, flame = flameSpeed(gas,estFlameThickness,returnFlame=True)
    TU, TB = flame.T[0] ,flame.T[-1]
    flameThickness=(TB-TU)/max(np.gradient(flame.T,flame.grid))

    #get flame parameters
    gasUnburned = ct.Solution(mech_filename)
    gasUnburned.TPY = flame.T[0], flame.P, flame.Y[:,0]
    uUnburned = flame.velocity[0]
    unburnedState = gasUnburned, uUnburned
    gasBurned = ct.Solution(mech_filename)
    gasBurned.TPY = flame.T[-1], flame.P, flame.Y[:,-1]
    uBurned = flame.velocity[-1]
    burnedState = gasBurned, uBurned


    #set up grid
    nX = flame.grid.shape[0]
    xCenter = flame.grid[np.argmax(np.gradient(flame.T,flame.grid))]
    L = flame.grid[-1] - flame.grid[0]
    xUpper, xLower = xCenter +L*f, xCenter-L*f

    geometry=(nX,xLower,xUpper,(xUpper+xLower)/2.0)
    boundaryConditions = (gasUnburned.density,uUnburned,None,gasUnburned.Y),(None,None,gasBurned.P,None)
    ss = stanShock(gas,initializeRiemannProblem=(unburnedState,burnedState,geometry),
                   boundaryConditions=boundaryConditions,
                   cfl=.9,
                   reacting=True,
                   includeDiffusion=True,
                   outputEvery=10)

    #interpolate flame solution
    ss.r = np.interp(ss.x,flame.grid,flame.density)
    ss.u = np.interp(ss.x,flame.grid,flame.velocity)
    ss.p[:] = flame.P
    for iSp in range(gas.n_species):
        ss.Y[:,iSp] = np.interp(ss.x,flame.grid,flame.Y[iSp,:])
    T = ss.thermoTable.getTemperature(ss.r,ss.p,ss.Y)
    ss.gamma = ss.thermoTable.getGamma(T,ss.Y)
    #calculate the final time
    tFinal = ntFlowThrough*(xUpper-xLower)/(uUnburned+uBurned)*2.0

    #Solve
    t0 = time.perf_counter()
    ss.advanceSimulation(tFinal)
    t1 = time.perf_counter()
    print("The process took ", t1-t0)

    #plot setup
    plt.close("all")
    font = {'family':'serif', 'serif': ['computer modern roman']}
    plt.rc('font',**font)
    mpl.rcParams['font.size']=fontsize
    plt.rc('text',usetex=True)
    #plot
    plt.plot((flame.grid-xCenter)/flameThickness,flame.T/flame.T[-1],'r',label="$T/T_\mathrm{F}$")
    T = ss.thermoTable.getTemperature(ss.r,ss.p,ss.Y)
    plt.plot((ss.x-xCenter)/flameThickness,T/flame.T[-1],'r--s')
    iOH = gas.species_index("OH")
    plt.plot((flame.grid-xCenter)/flameThickness,flame.Y[iOH,:]*10,'k',label="$Y_\mathrm{OH}\\times 10$")
    plt.plot((ss.x-xCenter)/flameThickness,ss.Y[:,iOH]*10,'k--s')
    iO2 = gas.species_index("O2")
    plt.plot((flame.grid-xCenter)/flameThickness,flame.Y[iO2,:],'g',label="$Y_\mathrm{O_2}$")
    plt.plot((ss.x-xCenter)/flameThickness,ss.Y[:,iO2],'g--s')
    iH2 = gas.species_index("H2")
    plt.plot((flame.grid-xCenter)/flameThickness,flame.Y[iH2,:],'b',label="$Y_\mathrm{H_2}$")
    plt.plot((ss.x-xCenter)/flameThickness,ss.Y[:,iH2],'b--s')
    plt.xlabel("$x/\delta_\mathrm{F}$")
    plt.legend(loc="best")
    if show_results:
        plt.show()

    if results_location is not None:
        np.savez(
            os.path.join(results_location, "laminarFlame.npz"),
            position=ss.x,
            temperature=ss.thermoTable.getTemperature(ss.r,ss.p,ss.Y),
        )
        plt.savefig(os.path.join(results_location, "laminarFlame.png"))
Exemplo n.º 5
0
def main(data_filename: str = "data/validation/case3.csv",
         mech_filename: str = "data/mechanisms/Nitrogen.xml",
         show_results: bool = True,
         results_location: Optional[str] = None) -> None:
    #=============================================================================
    #provided condtions for case 3
    Ms = 2.409616
    T1 = 292.25
    p1 = 1999.83552
    p2 = 13267.880629
    tFinal = 60e-3

    #plotting parameters
    fontsize = 12

    #provided geometry
    DDriven = 4.5 * 0.0254
    DDriver = 4.5 * 0.0254
    LDriver = 142.0 * 0.0254
    LDriven = 9.73
    DOuterInsertBack = 3.375 * 0.0254
    DOuterInsertFront = 1.25 * 0.0254
    LOuterInsert = 102.0 * 0.0254
    DInnerInsert = 0.625 * 0.0254
    LInnerInsert = 117.0 * 0.0254

    #Set up gasses and determine the initial pressures
    u1 = 0.0
    u4 = 0.0
    #initially 0 velocity
    gas1 = ct.Solution(mech_filename)
    gas4 = ct.Solution(mech_filename)
    T4 = T1
    #assumed
    gas1.TP = T1, p1
    gas4.TP = T4, p1  #use p1 as a place holder
    g1 = gas1.cp / gas1.cv
    g4 = gas4.cp / gas4.cv
    a4oa1 = np.sqrt(g4 / g1 * T4 / T1 * gas1.mean_molecular_weight /
                    gas4.mean_molecular_weight)
    p4 = p2 * (1.0 - (g4 - 1.0) / (g1 + 1.0) / a4oa1 *
               (Ms - 1.0 / Ms))**(-2.0 * g4 /
                                  (g4 - 1.0))  #from handbook of shock waves
    p4 *= 1.04
    gas4.TP = T4, p4

    #set up geometry
    nX = 1000  #mesh resolution
    xLower = -LDriver
    xUpper = LDriven
    xShock = 0.0
    geometry = (nX, xLower, xUpper, xShock)
    DeltaD = DDriven - DDriver
    dDOuterInsertdx = (DOuterInsertFront - DOuterInsertBack) / LOuterInsert
    DeltaSmoothingFunction = (xUpper - xLower) / float(nX) * 10.0

    def DOuter(x):
        return DDriven * np.ones(nX)

    def DInner(x):
        diameter = np.zeros(nX)
        diameter += smoothingFunction(x, xLower + LInnerInsert,
                                      DeltaSmoothingFunction, DInnerInsert,
                                      0.0)
        diameter += smoothingFunction(x, xLower + LOuterInsert,
                                      DeltaSmoothingFunction,
                                      DOuterInsertFront - DInnerInsert, 0.0)
        diameter += smoothingFunction(x, xLower + LOuterInsert / 2.0,
                                      LOuterInsert,
                                      DOuterInsertBack - DOuterInsertFront,
                                      0.0)
        return diameter

    def dDOuterdx(x):
        return np.zeros(nX)

    def dDInnerdx(x):
        dDiameterdx = np.zeros(nX)
        dDiameterdx += dSFdx(x, xLower + LInnerInsert, DeltaSmoothingFunction,
                             DInnerInsert, 0.0)
        dDiameterdx += dSFdx(x, xLower + LOuterInsert, DeltaSmoothingFunction,
                             DOuterInsertFront - DInnerInsert, 0.0)
        dDiameterdx += dSFdx(x, xLower + LOuterInsert / 2.0, LOuterInsert,
                             DOuterInsertBack - DOuterInsertFront, 0.0)
        return dDiameterdx

    A = lambda x: np.pi / 4.0 * (DOuter(x)**2.0 - DInner(x)**2.0)
    dAdx = lambda x: np.pi / 2.0 * (DOuter(x) * dDOuterdx(x) - DInner(x) *
                                    dDInnerdx(x))
    dlnAdx = lambda x, t: dAdx(x) / A(x)

    #set up solver parameters
    print("Solving with boundary layer terms")
    boundaryConditions = ['reflecting', 'reflecting']
    state1 = (gas1, u1)
    state4 = (gas4, u4)
    ssbl = stanShock(
        gas1,
        initializeRiemannProblem=(state4, state1, geometry),
        boundaryConditions=boundaryConditions,
        cfl=.9,
        outputEvery=100,
        includeBoundaryLayerTerms=True,
        Tw=T1,  #assume wall temperature is in thermal eq. with gas
        DInner=DInner,
        DOuter=DOuter,
        dlnAdx=dlnAdx)
    ssbl.addProbe(max(ssbl.x))  #end wall probe

    #Solve
    t0 = time.perf_counter()
    ssbl.advanceSimulation(tFinal)
    t1 = time.perf_counter()
    print("The process took ", t1 - t0)

    #without  boundary layer model
    print("Solving without boundary layer model")
    boundaryConditions = ['reflecting', 'reflecting']
    gas1.TP = T1, p1
    gas4.TP = T4, p4
    ssnbl = stanShock(gas1,
                      initializeRiemannProblem=(state4, state1, geometry),
                      boundaryConditions=boundaryConditions,
                      cfl=.9,
                      outputEvery=100,
                      includeBoundaryLayerTerms=False,
                      DInner=DInner,
                      DOuter=DOuter,
                      dlnAdx=dlnAdx)
    ssnbl.addProbe(max(ssnbl.x))  #end wall probe

    #Solve
    t0 = time.perf_counter()
    ssnbl.advanceSimulation(tFinal)
    t1 = time.perf_counter()
    print("The process took ", t1 - t0)

    #import shock tube data
    tExp, pExp = getPressureData(data_filename)
    timeDifference = (
        12.211 -
        8.10) / 1000.0  #difference between the test data and simulation times
    tExp += timeDifference

    #make plots of probe and XT diagrams
    plt.close("all")
    mpl.rcParams['font.size'] = fontsize
    plt.rc('text', usetex=True)
    plt.figure(figsize=(4, 4))
    plt.plot(np.array(ssnbl.probes[0].t) * 1000.0,
             np.array(ssnbl.probes[0].p) / 1.0e5,
             'k',
             label="$\mathrm{Without\ BL\ Model}$",
             linewidth=2.0)
    plt.plot(np.array(ssbl.probes[0].t) * 1000.0,
             np.array(ssbl.probes[0].p) / 1.0e5,
             'r',
             label="$\mathrm{With\ BL\ Model}$",
             linewidth=2.0)
    plt.plot(tExp * 1000.0,
             pExp / 1.0e5,
             label="$\mathrm{Experiment}$",
             alpha=0.7)
    plt.axis([0, 60, -.5, 2])
    plt.xlabel("$t\ [\mathrm{ms}]$")
    plt.ylabel("$p\ [\mathrm{bar}]$")
    plt.legend(loc="lower right")
    plt.tight_layout()
    if show_results:
        plt.show()

    if results_location is not None:
        np.savez(os.path.join(results_location, "case3.npz"),
                 pressure_with_boundary_layer=ssbl.probes[0].p,
                 pressure_without_boundary_layer=ssnbl.probes[0].p,
                 time_with_boundary_layer=ssbl.probes[0].t,
                 time_without_boundary_layer=ssnbl.probes[0].t)
        plt.savefig(os.path.join(results_location, "case3.png"))