def process_one_slice(flow, grd, i): """ Returns ... Use cell-average flow quantities and areas from the EAST boundary faces. This is a little dodgy, in general, but we gat away with it here because the cells have right angles. """ TOL = 5.0e-2 rho_f1_z_dA = 0.0 rho_z_dA = 0.0 m_flux = 0.0 H_flux = 0.0 A_f0 = 0.0 A_f1 = 0.0 A_mix = 0.0 A_tot = 0.0 nj = flow.nj nk = flow.nk for j in range(nj): for k in range(nk): vtx = grd.get_vertex_list_for_cell(i, j, k) # The EAST cell face has 1, 2, 6, 5 as corners (unit normal out). face_centroid = quad_centroid(vtx[1], vtx[2], vtx[6], vtx[5]) face_normal = quad_normal(vtx[1], vtx[2], vtx[6], vtx[5]) face_area = quad_area(vtx[1], vtx[2], vtx[6], vtx[5]) # average conditions in cell z = flow.data['pos.z'][i, j, k] pressure = flow.data['p'][i, j, k] rho = flow.data['rho'][i, j, k] e = flow.data['e[0]'][i, j, k] f0 = flow.data['massf[0]'][i, j, k] f1 = flow.data['massf[1]'][i, j, k] rho_z_dA += rho * face_area * z rho_f1_z_dA += rho * f1 * face_area * z A_tot += face_area if f0 > 1.0 - TOL: A_f0 += face_area elif f0 < TOL: A_f1 += face_area else: A_mix += face_area v_x = flow.data['vel.x'][i, j, k] v_y = flow.data['vel.y'][i, j, k] v_z = flow.data['vel.z'][i, j, k] vel_abs = Vector(v_x, v_y, v_z) df = face_area * pressure * face_normal dm_flux = rho * dot(vel_abs, face_normal) * face_area m_flux += dm_flux H_flux += dm_flux * (e + pressure / rho + 0.5 * (v_x * v_x + v_y * v_y + v_z * v_z)) return m_flux, H_flux, A_f0, A_f1, A_mix, A_tot, rho_z_dA, rho_f1_z_dA
def objective(alpha, x_s=x_s, y_s=y_s): """ Objective function for the optimizer. """ from libprep3 import Bezier, Vector bx, by = define_bezier_points(alpha, x_s, y_s) bpath = Bezier([Vector(bx[0],by[0]),Vector(bx[1],by[1]), Vector(bx[2],by[2]),Vector(bx[3],by[3])]) nbez = 1000 pbez = [] for i in range(nbez): t = 1.0/nbez * i pbez.append(bpath.eval(t)) n = len(x_s) sum_sq_err = 0.0 for j in range(n): min_dist = (x_s[j]-pbez[0].x)**2 + (y_s[j]-pbez[0].y)**2 for i in range(1,nbez): dist = (x_s[j]-pbez[i].x)**2 + (y_s[j]-pbez[i].y)**2 if dist < min_dist: min_dist = dist sum_sq_err += min_dist # print "alpha=", alpha, "sum_sq_err=", sum_sq_err return sum_sq_err
print "Begin: Pick up data for tindx=", tindx from libprep3 import Vector, cross, dot, vabs from e3_flow import read_all_blocks from math import sqrt # nb = 28 pick_list = [0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26] # surface rho_inf = 6.081e-4 # kg/m**3 p_inf = 18.55 # Pa u_inf = 2576.0 # m/s T_inf = 102.2 # K T_wall = 295.8 # K from cfpylib.gasdyn import sutherland mu_inf = sutherland.mu(T_inf, 'N2') mm = 0.001 # metres corner1 = Vector(92.08, 42.94) * mm corner2 = Vector(153.69, 130.925) * mm # grid, flow, dim = read_all_blocks(job, nb, tindx, zipFiles=True) print "Compute properties for cell-centres along the surface" outfile = open("surface.data", "w") outfile.write( "# x(m) s(m) tau_w(Pa) Cf Cf_blasius y_plus p(Pa) Cp q(W/m**2) Ch\n") for ib in pick_list: j = 0 # surface is along the South boundary k = 0 # of a 2D grid print "# start of block" for i in range(flow[ib].ni): # Cell closest to surface x = flow[ib].data['pos.x'][i, j, k] y = flow[ib].data['pos.y'][i, j, k]
from e3_flow import read_all_blocks from math import sqrt # nb = 24 pick_list = [0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22] # blocks against surface rho_inf = 8.81e-4 # kg/m**3 p_inf = 31.88 # Pa u_inf = 2304.0 # m/s T_inf = 120.4 # K T_wall = 295.2 # K from cfpylib.gasdyn import sutherland mu_inf = sutherland.mu(T_inf, 'N2') mm = 0.001 # metres R = 32.5*mm xcorner = 101.7*mm corner = Vector(xcorner,R) # grid, flow, dim = read_all_blocks(job, nb, tindx, zipFiles=True) print "Compute shear stress for cell-centres along the surface" outfile = open("surface.data", "w") outfile.write("# x(m) s(m) tau_w(Pa) Cf Cf_blasius y_plus p(Pa) Cp q(W/m**2) Ch\n") for ib in pick_list: j = 0 # surface is along the South boundary k = 0 # of a 2D grid print "# start of block" for i in range(flow[ib].ni): # Cell closest to surface x = flow[ib].data['pos.x'][i,j,k] y = flow[ib].data['pos.y'][i,j,k] ctr = Vector(x, y) # Get vertices on surface, for this cell.
def print_stats_MoA(sliceFileName,jobName,coreRfraction,weight): """ (MoA = Mass- or Area-weighted) Display either the mass-weighted or area-weighted statistics of flow properties at the nozzle exit. """ print weight.capitalize()+"-Weighted Nozzle-exit statistics:" variable_list, data = get_slice_data(sliceFileName) # # Identify edge of core flow. ys = data['pos.y'] xs = data['pos.x'] y_edge = ys[-1] * coreRfraction # # Compute and print area-weighted-average core flow values. exclude_list = ['pos.x', 'pos.y', 'pos.z', 'volume', 'vel.z', 'S'] # fout = open(jobName+'-exit.stats'+weight.capitalize(),'w') fout.write('CoreRadiusFraction: %10.6f\n' % coreRfraction) fout.write('%15s %12s %10s %10s %10s\n' % ("variable","mean-value","minus","plus","std-dev")) fout.write(65*'-'+'\n') # print "%15s %12s %10s %10s %10s" % \ ("variable", "mean-value", "minus", "plus","std-dev") print 65*'-' u = data['vel.x']; v = data['vel.y']; rho = data['rho'] for var in variable_list: if var in exclude_list: continue MassFlux = 0.0; F = 0.0; for j in range(len(ys)): if ys[j] > y_edge: break y1 = 0.5*(ys[j]+ys[j+1]) x1 = 0.5*(xs[j]+xs[j+1]) if j == 0: y0 = 0.0 dx = xs[j]-x1 x0 = xs[j]+dx else: y0 = 0.5*(ys[j-1]+ys[j]) x0 = 0.5*(xs[j-1]+xs[j]) # Area element... #d_Area = y1**2 - y0**2 d_Area = pi*(y0+y1)*sqrt((y1-y0)**2+(x0-x1)**2) # Unit normal vector... edge = Vector(x0,y0,0.0)-Vector(x1,y1,0.0) nhat = Vector(-edge.y, edge.x, 0.0)/vabs(edge) # Velocity vector... vel = Vector(u[j],v[j],0.0) # Weighting factor... if weight in ['area']: weighting = 1.0 elif weight in ['mass']: weighting = rho[j]*dot(vel,nhat) else: print "Unknown weighting option given" break # Accumulate total... F += data[var][j] * weighting * d_Area MassFlux += weighting * d_Area mean = F/MassFlux # Identify low and high values. diff_minus = 0.0 diff_plus = 0.0 count = 0.0 stddev = 0.0 for j in range(len(ys)): if ys[j] > y_edge: break diff = data[var][j] - mean diff_minus = min(diff, diff_minus) diff_plus = max(diff, diff_plus) count += 1 stddev += diff**2 # Calculate the sample standard deviation stddev = (stddev/(count-1))**0.5 print "%15s %12.5g %10.3g %10.3g %10.3g" % \ (var, mean, diff_minus, diff_plus, stddev) fout.write('%15s %12.5g %10.3g %10.3g %10.3g\n' % \ (var, mean, diff_minus, diff_plus, stddev)) # print 65*'-' fout.write(65*'-'+'\n') fout.close() return
def print_stats_CMME(sliceFileName,jobName,coreRfraction,gmodelFile): """ Display statistics of flow properties at the nozzle exit using conservation of mass, momentum and energy (CMME) method. The implementation is loosely based on the paper: Baurle, R.A. and Gaffney, R.L. (2008) "Extraction of One-Dimensional Flow Properties from Multidimensional Data Sets", Journal of Propulsion and Power, vol. 24, no. 4, pg. 704 Equations numbers given in the comments of the code refer to the paper. PJ, 22-Aug-2012: Use brute-force to get the effective 1D flow properties. Assumptions: Geometry is axisymmetric. The fluxes are calculated normal to the curve (which may not be straight) over which we are integrating. The returned averaged velocity vector is parallel to the averaged unit normal over the curve. """ print "Nozzle-exit statistics (CMME):" variable_list, data = get_slice_data(sliceFileName) # # Identify edge of core flow. ys = data['pos.y'] xs = data['pos.x'] y_edge = ys[-1] * coreRfraction # # Over the core region of interest we now want to calculate: # (1) total area; # (2) the unit normal; # (3) total mass flux for each species; # (4) total momentum flux; and # (5) total energy flux. # # First, we need to do a bit of fiddling with variable names in order # to get the species names. speciesKeys = [k for k in variable_list if k.startswith("mass")] # Get a list of just the species names (without the "massf[i]-" prefix)... speciesNames = [name.split('-')[1] for name in speciesKeys] nsp = len(speciesKeys) # # Initialise the totals across the slice: Area = 0.0 #...area nhatTotal = Vector(0.0) #...unit normal speciesMassFluxes = zeros((nsp,)) massFlux = 0.0 momentumFlux = Vector(0.0) energyFlux = 0.0 # We also need to calculate the mass-weighted Mach number for later use. mach = 0.0 # Mass-weighted turbulent parameters will also be reported in the stats file. tke = 0.0 omega = 0.0 dt_chem = 0.0 # # Define the following for ease of use in the integration process below. rho = data['rho'] u = data['vel.x'] v = data['vel.y'] p = data['p'] h0 = data['total_h'] # this includes tke a = data['a'] M = data['M_local'] # # Integrate the conserved properties across the slice. for j in range(len(ys)): if ys[j] > y_edge: break y1 = 0.5*(ys[j]+ys[j+1]) x1 = 0.5*(xs[j]+xs[j+1]) if j == 0: y0 = 0.0 dx = xs[j]-x1 x0 = xs[j]+dx else: y0 = 0.5*(ys[j-1]+ys[j]) x0 = 0.5*(xs[j-1]+xs[j]) # We assume the data is axi-symmetric but no # assumption is made about the straightness # of the plane over which we are integrating. # Hence we use a truncated cone for the area. d_Area = pi*(y0+y1)*sqrt((y1-y0)**2+(x0-x1)**2) Area += d_Area # Calculate the outward pointing unit # normal vector to the differential area # element... edge = Vector(x0,y0,0)-Vector(x1,y1,0) nhat = Vector(-edge.y, edge.x, 0)/vabs(edge) nhatTotal += nhat*d_Area # Velocity vector and weighting function... vel = Vector(u[j],v[j],0.0) weighting = rho[j]*dot(vel,nhat) # Total mass, momentum and energy fluxes... # Eq'ns (2a), (2b), and (2c) in paper. momentumFlux += (weighting*vel + p[j]*nhat)*d_Area #h0 = e0[j] + p[j]/rho[j] + 0.5*dot(vel,vel) #energyFlux += weighting*h0*d_Area energyFlux += weighting*h0[j]*d_Area speciesFractions = array([data[species][j] for species in speciesKeys]) speciesMassFluxes += weighting*speciesFractions*d_Area massFlux += weighting*d_Area # # Mass-weighted parameters... mach += M[j]*weighting*d_Area if 'tke' in data.keys(): tke += data['tke'][j]*weighting*d_Area if 'omega' in data.keys(): omega += data['omega'][j]*weighting*d_Area if 'dt_chem' in data.keys(): dt_chem += data['dt_chem'][j]*weighting*d_Area # Check the total mass flux...Eq'n (A2) assert abs(massFlux - sum(speciesMassFluxes)) <= 1e-7 # # Now, compute the effective 1D flow properties # to have the same integral properties. # # Calculate the overall unit normal vector using Eq'n (10) g_nhat = nhatTotal/Area # and a scalar momentum flux of the effective 1D flow, Eq'n (A8) momentumFluxScalar = dot(momentumFlux,g_nhat) # 1D species mass fractions...Eq'n (A4) massFrac = speciesMassFluxes/massFlux # Mass-weighted Mach number aveMach = mach/massFlux # and mass-weighted turbulent parameters. ave_tke = tke/massFlux #...Eq'n (20) and (A2) ave_omega = omega/massFlux ave_dt_chem = dt_chem/massFlux # and reconstruct the gas state gmodel = create_gas_model(gmodelFile) gdata = Gas_data(gmodel) massfDict = dict([(k,v) for k,v in zip(speciesNames,massFrac)]) set_massf(gdata,gmodel,massfDict) gdata.rho = data['rho'][0] gdata.T[0] = data['T[0]'][0] gmodel.eval_thermo_state_rhoT(gdata) vx = massFlux/(gdata.rho*Area) #print "Before optimizer, vx=", vx, "p=", gdata.p, "T=", gdata.T[0], "rho=", gdata.rho # #print "fm=",massFlux,"fp=",momentumFluxScalar,"fe=",energyFlux def error_estimate(params, gasData=gdata, gasModel=gmodel, fm=massFlux, fp=momentumFluxScalar, fe=energyFlux, tke=ave_tke, Area=Area, mach=aveMach): """ Estimate the badness the current guess for 1D flow properties. params : [rho, T, v] 1D flow properties to be evaluated """ rho, T, vx = params gasData.T[0] = T gasData.rho = rho gmodel.eval_thermo_state_rhoT(gasData) p = gasData.p h = gasModel.mixture_enthalpy(gasData) #...1D static enthalpy M = vx/gasData.a # Relative errors in each conserved quantity. # The "+1.0" items are to avoid (unlikely) problems with zero values # for the given quantities. fm_err = abs(fm - rho*vx*Area)/(abs(fm)+1.0) fp_err = abs(fp - (rho*vx*vx*Area + p*Area))/(abs(fp)+1.0) fe_err = abs(fe - rho*vx*Area*(h+0.5*vx*vx+tke))/(abs(fe)+1.0) mach_err = abs(M - mach)/(abs(mach)+1.0) # The overall error estimate is a weighted sum. return fm_err + fp_err + fe_err + 0.1*mach_err # print "Optimize estimate of 1D flow properties" flow_params, fx, conv_flag, nfe, nres = minimize(error_estimate, [gdata.rho, gdata.T[0], vx], [0.01, 10.0, 10.0], maxfe=1000) rho, T, vx = flow_params #print "fx=", fx #print "convergence-flag=", conv_flag #print "number-of-fn-evaluations=", nfe #print "number-of-restarts=", nres if conv_flag != 1: print "WARNING! Optimizer did not converge properly." gdata.T[0] = T gdata.rho = rho gmodel.eval_thermo_state_rhoT(gdata) p = gdata.p #print "After optimizer, vx=", vx, "p=", p, "T=", T, "rho=", rho g = gmodel.gamma(gdata) R = gmodel.R(gdata) M = vx/gdata.a total_h = energyFlux/massFlux # gmodel.eval_transport_coefficients(gdata) properties = {} properties['rho'] = rho properties['vel.x'] = vx properties['vel.y'] = 0.0 properties['p'] = p properties['a'] = gdata.a properties['mu'] = gdata.mu properties['k[0]'] = gdata.k[0] properties['e[0]'] = gdata.e[0] properties['T[0]'] = T properties['M_local'] = M properties['total_h'] = total_h properties['gamma'] = g properties['R'] = R for k in range(nsp): properties[speciesKeys[k]] = massFrac[k] # Calculate Pitot pressure using Rayleigh formula... if M > 1.0: t1 = (g+1)*M*M/2 t2 = (g+1)/(2*g*M*M - (g-1)); pitot_p = p * pow(t1,(g/(g-1))) * pow(t2,(1/(g-1))); else: t1 = 1 + 0.5*(g-1)*M*M pitot_p = p * pow(t1,(g/(g-1))) properties['pitot_p'] = pitot_p # Calculate total pressure (as isentropic process)... t1 = 1 + 0.5*(g-1)*M*M total_p = p * pow(t1,(g/(g-1))) properties['total_p'] = total_p # # Calculate the turbulent viscosity and thermal # conductivity using definitions given in: # Chan, W.Y.K., Jacobs, P.A., Nap, J.P., Mee, D.J., # Kirchhartz, R.M. (2011) # "The k-w turbulence model in Eilmer3: User guide # test cases", Research Report Number 2010/11 properties['mu_t'] = properties['rho']*ave_tke/ave_omega Pr_t = 8.0/9.0 #...turbulent Prandtl number. Cp = gmodel.Cp(gdata) properties['k_t'] = Cp*properties['mu_t']/Pr_t # Finally, add the remaining mass-weighted turbulent # and chemistry parameters... properties['tke'] = ave_tke properties['omega'] = ave_omega properties['dt_chem'] = ave_dt_chem # # Now we have all the one-dimensionalised flow properties, # calculate the statistics and write a summary. # fout = open(jobName+'-exit.stats','w') if conv_flag != 1: fout.write('WARNING! Optimizer did not converge properly\n') fout.write('CoreRadiusFraction: %10.6f\n' % coreRfraction) fout.write('%15s %12s %10s %10s %10s\n' % \ ("variable","mean-value","minus","plus","std-dev")) fout.write(65*'-') fout.write('\n') print "%15s %12s %10s %10s %10s" % \ ("variable", "mean-value", "minus", "plus","std-dev") print 65*'-' # exclude_list = ['pos.x', 'pos.y', 'pos.z', 'volume', 'vel.z', 'S'] for var in variable_list: if var in exclude_list: continue # Identify the low and high values diff_minus = 0.0 diff_plus = 0.0 count = 0.0 stddev = 0.0 for j in range(len(ys)): if ys[j] > y_edge: break diff = data[var][j] - properties[var] diff_minus = min(diff, diff_minus) diff_plus = max(diff, diff_plus) count += 1 stddev += diff**2 # Calculate the sample standard deviation stddev = (stddev/(count-1))**0.5 print "%15s %12.5g %10.3g %10.3g %10.3g" % \ (var, properties[var], diff_minus, diff_plus, stddev) fout.write('%15s %12.5g %10.3g %10.3g %10.3g\n' % \ (var, properties[var], diff_minus, diff_plus, stddev)) # print 65*'-' fout.write(65*'-'+'\n') fout.close() return
def process_one_slice(flow, grd, i): """ Returns ... Use cell-average flow quantities and areas from the EAST boundary faces. """ m_flux = 0.0 mf_flux = 0.0 mfR_flux = 0.0 H_flux = 0.0 Circ = 0.0 prec = 0.0 z_pen = 0.0 nj = flow.nj nk = flow.nk f0stoic = 0.02876 f0lim = 0.1 * f0stoic # limiting mass fraction defining edge of jet for j in range(nj): for k in range(nk): vtx = grd.get_vertex_list_for_cell(i, j, k) # The EAST cell face has 1, 2, 6, 5 as corners (unit normal out). face_centroid = quad_centroid(vtx[1], vtx[2], vtx[6], vtx[5]) face_normal = quad_normal(vtx[1], vtx[2], vtx[6], vtx[5]) face_area = quad_area(vtx[1], vtx[2], vtx[6], vtx[5]) # average conditions in cell y = flow.data['pos.y'][i, j, k] z = flow.data['pos.z'][i, j, k] pressure = flow.data['p'][i, j, k] rho = flow.data['rho'][i, j, k] e = flow.data['e[0]'][i, j, k] a = flow.data['a'][i, j, k] v_x = flow.data['vel.x'][i, j, k] v_y = flow.data['vel.y'][i, j, k] v_z = flow.data['vel.z'][i, j, k] if j == 0: if k == 0: yp = flow.data['pos.y'][i, j + 1, k] zp = flow.data['pos.z'][i, j, k + 1] v_yp = flow.data['vel.y'][i, j, k + 1] v_zp = flow.data['vel.z'][i, j + 1, k] vort_x = (v_zp - v_z) / (yp - y) - (v_yp - v_y) / (zp - z) elif k == nk - 1: yp = flow.data['pos.y'][i, j + 1, k] zm = flow.data['pos.z'][i, j, k - 1] v_zp = flow.data['vel.z'][i, j + 1, k] v_ym = flow.data['vel.y'][i, j, k - 1] vort_x = (v_zp - v_z) / (yp - y) - (v_y - v_ym) / (z - zm) else: yp = flow.data['pos.y'][i, j + 1, k] zp = flow.data['pos.z'][i, j, k + 1] zm = flow.data['pos.z'][i, j, k - 1] v_zp = flow.data['vel.z'][i, j + 1, k] v_yp = flow.data['vel.y'][i, j, k + 1] v_ym = flow.data['vel.y'][i, j, k - 1] vort_x = 0.5 * (2.0 * (v_zp - v_z) / (yp - y) - (v_yp - v_y) / (zp - z) - (v_y - v_ym) / (z - zm)) elif j == nj - 1: if k == 0: ym = flow.data['pos.y'][i, j - 1, k] zp = flow.data['pos.z'][i, j, k + 1] v_yp = flow.data['vel.y'][i, j, k + 1] v_zm = flow.data['vel.z'][i, j - 1, k] vort_x = (v_zm - v_z) / (ym - y) - (v_yp - v_y) / (zp - z) elif k == nk - 1: ym = flow.data['pos.y'][i, j - 1, k] zm = flow.data['pos.z'][i, j, k - 1] v_zm = flow.data['vel.z'][i, j - 1, k] v_ym = flow.data['vel.y'][i, j, k - 1] vort_x = (v_zm - v_z) / (ym - y) - (v_y - v_ym) / (z - zm) else: ym = flow.data['pos.y'][i, j - 1, k] zp = flow.data['pos.z'][i, j, k + 1] zm = flow.data['pos.z'][i, j, k - 1] v_zm = flow.data['vel.z'][i, j - 1, k] v_yp = flow.data['vel.y'][i, j, k + 1] v_ym = flow.data['vel.y'][i, j, k - 1] vort_x = 0.5 * (2.0 * (v_zm - v_z) / (ym - y) - (v_yp - v_y) / (zp - z) - (v_y - v_ym) / (z - zm)) elif k == 0: yp = flow.data['pos.y'][i, j + 1, k] zp = flow.data['pos.z'][i, j, k + 1] ym = flow.data['pos.y'][i, j - 1, k] v_yp = flow.data['vel.y'][i, j, k + 1] v_zp = flow.data['vel.z'][i, j + 1, k] v_zm = flow.data['vel.z'][i, j - 1, k] vort_x = 0.5 * ((v_zp - v_z) / (yp - y) + (v_z - v_zm) / (y - ym) - 2.0 * (v_yp - v_y) / (zp - z)) elif k == nk - 1: yp = flow.data['pos.y'][i, j + 1, k] ym = flow.data['pos.y'][i, j - 1, k] zm = flow.data['pos.z'][i, j, k - 1] v_zp = flow.data['vel.z'][i, j + 1, k] v_ym = flow.data['vel.y'][i, j, k - 1] v_zm = flow.data['vel.z'][i, j - 1, k] vort_x = 0.5 * ((v_zp - v_z) / (yp - y) + (v_z - v_zm) / (y - ym) - 2.0 * (v_y - v_ym) / (z - zm)) else: yp = flow.data['pos.y'][i, j + 1, k] zp = flow.data['pos.z'][i, j, k + 1] ym = flow.data['pos.y'][i, j - 1, k] zm = flow.data['pos.z'][i, j, k - 1] v_yp = flow.data['vel.y'][i, j, k + 1] v_zp = flow.data['vel.z'][i, j + 1, k] v_ym = flow.data['vel.y'][i, j, k - 1] v_zm = flow.data['vel.z'][i, j - 1, k] vort_x = 0.5 * ((v_zp - v_z) / (yp - y) + (v_z - v_zm) / (y - ym) - (v_yp - v_y) / (zp - z) - (v_y - v_ym) / (z - zm)) Circ += math.fabs(vort_x) * face_area vel_abs = Vector(v_x, v_y, v_z) M = math.sqrt(v_x * v_x + v_y * v_y + v_z * v_z) / a gam = 1.4 p0 = pressure * math.pow(1.0 + 0.5 * (gam - 1.0) * M * M, gam / (gam - 1.0)) df = face_area * pressure * face_normal dm_flux = rho * dot(vel_abs, face_normal) * face_area m_flux += dm_flux f0 = flow.data['massf[0]-H2'][i, j, k] f1 = flow.data['massf[1]-air'][i, j, k] mf_flux += f0 * dm_flux if f0 < 0.02961 * f1: mfR_flux += f0 * dm_flux else: mfR_flux += 0.02961 * f1 * dm_flux if f0 > f0lim: if z > z_pen: z_pen = z zp = flow.data['pos.z'][i, j, k + 1] f0p = flow.data['massf[0]-H2'][i, j, k + 1] if f0p < f0lim: z_pen = (f0lim - f0) / (f0p - f0) * (zp - z) + z prec += p0 * dm_flux H_flux += dm_flux * (e + pressure / rho + 0.5 * math.sqrt(v_x * v_x + v_y * v_y + v_z * v_z)) return m_flux, H_flux, mf_flux, mfR_flux, prec, Circ, z_pen