def test_HydroUniformIC(self): # declare symbolic variables x, t, alpha = symbols('x t alpha') # create solution for thermodynamic state and flow field rho = sympify('1') u = sympify('1') E = sympify('10') # create solution for radiation field psim = sympify('0') psip = sympify('0') # numeric values alpha_value = 0.01 cv_value = 1.0 gamma_value = 1.4 sig_s = 0.0 sig_a = 0.0 # create MMS source functions rho_src, mom_src, E_src, psim_src, psip_src = createMMSSourceFunctionsHydroOnly( rho=rho, u=u, E=E, gamma_value=gamma_value, cv_value=cv_value, alpha_value=alpha_value, display_equations=False) # create functions for exact solutions substitutions = dict() substitutions['alpha'] = alpha_value rho = rho.subs(substitutions) u = u.subs(substitutions) mom = rho * u E = E.subs(substitutions) rho_f = lambdify((symbols('x'), symbols('t')), rho, "numpy") u_f = lambdify((symbols('x'), symbols('t')), u, "numpy") mom_f = lambdify((symbols('x'), symbols('t')), mom, "numpy") E_f = lambdify((symbols('x'), symbols('t')), E, "numpy") psim_f = lambdify((symbols('x'), symbols('t')), psim, "numpy") psip_f = lambdify((symbols('x'), symbols('t')), psip, "numpy") # spatial and temporal domains width = 1.0 t_start = 0.0 t_end = 0.005 dt_constant = 0.001 # create mesh n_elems = 20 mesh = Mesh(n_elems, width) # compute radiation BC; assumes BC is independent of time psi_left = psip_f(x=0.0, t=0.0) psi_right = psim_f(x=width, t=0.0) rad_BC = RadBC(mesh, "dirichlet", psi_left=psi_left, psi_right=psi_right) # compute radiation IC psi_IC = computeRadiationVector(psim_f, psip_f, mesh, t=0.0) rad_IC = Radiation(psi_IC) # compute hydro IC hydro_IC = computeAnalyticHydroSolution(mesh, t=0.0, rho=rho_f, u=u_f, E=E_f, cv=cv_value, gamma=gamma_value) # create hydro BC hydro_BC = HydroBC(bc_type='dirichlet', mesh=mesh, rho_BC=rho_f, mom_BC=mom_f, erg_BC=E_f) # create cross sections cross_sects = [(ConstantCrossSection(sig_s, sig_s + sig_a), ConstantCrossSection(sig_s, sig_s + sig_a)) for i in xrange(mesh.n_elems)] # slope limiter option slope_limiter = "vanleer" # if run standalone, then be verbose if __name__ == '__main__': verbosity = 2 else: verbosity = 0 # run the rad-hydro transient rad_new, hydro_new = runNonlinearTransient(mesh=mesh, problem_type='rad_hydro', dt_option='constant', dt_constant=dt_constant, slope_limiter=slope_limiter, use_2_cycles=False, t_start=t_start, t_end=t_end, rad_BC=rad_BC, hydro_BC=hydro_BC, cross_sects=cross_sects, rad_IC=rad_IC, hydro_IC=hydro_IC, mom_src=mom_src, E_src=E_src, psim_src=psim_src, psip_src=psip_src, verbosity=verbosity) # number of decimal places to check n_decimal_places = 15 # check that states are all equal to the IC for i in xrange(n_elems): state = hydro_new[i] state_IC = hydro_IC[i] rho, mom, erg = state.getConservativeVariables() rho0, mom0, erg0 = state_IC.getConservativeVariables() self.assertAlmostEqual(rho, rho0, n_decimal_places) self.assertAlmostEqual(mom, mom0, n_decimal_places) self.assertAlmostEqual(erg, erg0, n_decimal_places)
def test_RadHydroShock(self): # test case test_case = "marcho3" # mach1.2 mach2 mach50 # create uniform mesh n_elems = 1000 width = 0.04 x_start = -0.02 mesh_center = x_start + 0.5 * width mesh = Mesh(n_elems, width, x_start=x_start) # slope limiter slope_limiter = "double-minmod" # gamma constant gam = 5.0 / 3.0 # material 1 and 2 properties: Table 6.1 sig_a1 = 390.71164263502122 sig_s1 = 853.14410158161809 - sig_a1 c_v1 = 0.12348 sig_a2 = sig_a1 sig_s2 = sig_s1 c_v2 = c_v1 if not (test_case == "mach2" or test_case == "marcho3"): raise NotImplementedError("All but mach2 and marcho3 shock may have wrong input"\ "values. Need to check Jarrod Ewards thesis, starting with Table 6.1") if test_case == "mach1.2": # Mach 1.2 problem: Table 6.2 # material 1 IC rho1 = 1.0 E1 = 2.2226400000000000e-02 u1 = 1.4055888445772469e-01 e1 = E1 / rho1 - 0.5 * u1 * u1 Erad_left = 1.372E-06 # material 2 IC rho2 = 1.2973213452231311 E2 = 2.6753570531538713e-002 u2 = 1.0834546504247138e-001 e2 = E2 / rho2 - 0.5 * u2 * u2 Erad_right = 2.7955320762182542e-06 # final time t_end = 0.5 # temperature plot filename test_filename = "radshock_mach1.2.pdf" # temperature plot exact solution filename exact_solution_filename = "mach1.2_exact_solution.csv" elif test_case == "mach2": # Mach 2 problem: Table 6.3 # material 1 IC rho1 = 1.0 E1 = 3.9788000000000004e-002 u1 = 2.3426480742954117e-001 e1 = E1 / rho1 - 0.5 * u1 * u1 T1 = e1 / c_v1 Erad_left = 1.372E-06 # material 2 IC rho2 = 2.2860748989303659e+000 E2 = 7.0649692950433357e-002 u2 = 1.0247468599526272e-001 e2 = E2 / rho2 - 0.5 * u2 * u2 T2 = e2 / c_v2 Erad_right = 2.5560936967521927e-005 print "rho", rho1, rho2 print "vel", u1, u2 print "Temperature", T1, T2 print "momentum", rho1 * u1, rho2 * u2 print "E", E1, E2 print "E_r", Erad_left, Erad_right print sig_a1, sig_s1 # final time t_end = 1.0 # temperature plot output filename test_filename = "radshock_mach2.pdf" # temperature plot exact solution filename exact_solution_filename = "marcho2_exact_solution.csv" elif test_case == "mach50": # Mach 50 problem: Table 6.4 raise NotImplementedError("Mach 50 test requires negativity monitoring," \ + "which is not yet implemented.") # material 1 IC rho1 = 1.0 E1 = 1.7162348000000001e+001 u1 = 5.8566201857385289e+000 e1 = E1 / rho1 - 0.5 * u1 * u1 Erad_left = 1.372E-06 # material 2 IC rho2 = 6.5189217901173153e+000 E2 = 9.5144308747326214e+000 u2 = 8.9840319830453630e-001 e2 = E2 / rho2 - 0.5 * u2 * u2 Erad_right = 7.3372623010289956e+001 # final time t_end = 1.5 # temperature plot filename test_filename = "radshock_mach50.pdf" # temperature plot exact solution filename exact_solution_filename = "mach50_exact_solution.csv" elif test_case == "marcho2": # material 1 IC rho1 = 1.0 u1 = 0.23426480742954117 T1 = 1.219999999999999973e-01 e1 = T1 * c_v2 E1 = 0.5 * rho1 * u1 * u1 + e1 * rho1 Erad_left = 3.039477120074432e-06 # material 2 IC rho2 = 2.286074898930029242 u2 = 0.10247468599526272 T2 = 2.534635394302977573e-01 e2 = T2 * c_v2 E2 = 0.5 * rho2 * u2 * u2 + e2 * rho2 Erad_right = 5.662673693907908e-05 print "rho", rho1, rho2 print "vel", u1, u2 print "Temperature", T1, T2 print "momentum", rho1 * u1, rho2 * u2 print "E", E1, E2 print "E_r", Erad_left, Erad_right # final time t_end = 0.10 # temperature plot filename test_filename = "radshock_mach50.pdf" # temperature plot exact solution filename exact_solution_filename = "marcho2_exact_solution.csv" elif test_case == "marcho1.05": # material 1 IC rho1 = 1.0 u1 = 0.1228902 T1 = 0.1 e1 = T1 * c_v2 E1 = 0.5 * rho1 * u1 * u1 + e1 * rho1 Erad_left = 1.372E-06 # material 2 IC rho2 = 1.0749588 u2 = rho1 * u1 / rho2 T2 = 0.1049454 e2 = T2 * c_v2 E2 = 0.5 * rho2 * u2 * u2 + e2 * rho2 Erad_right = 1.664211799256650E-06 print "rho", rho1, rho2 print "vel", u1, u2 print "Temperature", T1, T2 print "momentum", rho1 * u1, rho2 * u2 print "E", E1, E2 print "E_r", Erad_left, Erad_right # final time t_end = 1.0 # temperature plot filename test_filename = "radshock_mach50.pdf" # temperature plot exact solution filename exact_solution_filename = "marcho1.05_exact_solution.csv" exact_solution_filename = None elif test_case == "marcho3": #new c_v and pure absorber cross sections c_v1 = 0.221804 c_v2 = c_v1 sig_a1 = 577.3502692 sig_s1 = 0. sig_a2 = sig_a1 sig_s2 = sig_s1 # material 1 IC rho1 = 1.0 mom1 = 0.5192549757 u1 = mom1 / rho1 T1 = 0.1215601363 e1 = T1 * c_v1 E1 = 0.5 * rho1 * u1 * u1 + e1 * rho1 Erad_left = 2.995841442e-06 # material 2 IC rho2 = 3.002167609 u2 = rho1 * u1 / rho2 T2 = 0.4451426103 e2 = T2 * c_v2 E2 = 0.5 * rho2 * u2 * u2 + e2 * rho2 Erad_right = 0.0005387047241 print "rho", rho1, rho2 print "vel", u1, u2 print "Temperature", T1, T2 print "momentum", rho1 * u1, rho2 * u2 print "E", E1, E2 print "E_r", Erad_left, Erad_right # final time t_end = 1.0 # temperature plot filename test_filename = "radshock_marcho3.pdf" # temperature plot exact solution filename exact_solution_filename = None else: raise NotImplementedError("Invalid test case") # compute radiation BC; assumes BC is independent of time c = GC.SPD_OF_LGT psi_left = 0.5 * c * Erad_left psi_right = 0.5 * c * Erad_right #Create BC object rad_BC = RadBC(mesh, "dirichlet", psi_left=psi_left, psi_right=psi_right) # construct cross sections and hydro IC cross_sects = list() hydro_IC = list() psi_IC = list() for i in range(mesh.n_elems): if mesh.getElement(i).x_cent < mesh_center: # material 1 cross_sects.append( (ConstantCrossSection(sig_s1, sig_s1 + sig_a1), ConstantCrossSection(sig_s1, sig_s1 + sig_a1))) hydro_IC.append( HydroState(u=u1, rho=rho1, e=e1, spec_heat=c_v1, gamma=gam)) psi_IC += [psi_left for dof in range(4)] else: # material 2 cross_sects.append( (ConstantCrossSection(sig_s2, sig_a2 + sig_s2), ConstantCrossSection(sig_s2, sig_a2 + sig_s2))) hydro_IC.append( HydroState(u=u2, rho=rho2, e=e2, spec_heat=c_v2, gamma=gam)) psi_IC += [psi_right for dof in range(4)] #Smooth out the middle solution optionally, shouldnt need this n_smoothed = 0 state_l = hydro_IC[0] state_r = hydro_IC[-1] rho_l = state_l.rho rho_r = state_r.rho drho = rho_r - rho_l u_l = state_l.u u_r = state_r.u du = u_r - u_l e_l = state_l.e e_r = state_r.e de = e_r - e_l print "p", state_l.p, state_r.p print "mach number", state_l.u / state_l.getSoundSpeed( ), state_r.u / state_r.getSoundSpeed() #Scale idx = 0 if n_smoothed > 0: for i in range(mesh.n_elems / 2 - n_smoothed / 2 - 1, mesh.n_elems / 2 + n_smoothed / 2): rho = rho_l + drho * idx / n_smoothed u = rho_l * u_l / rho e = e_l + de * idx / n_smoothed idx += 1 E = 0.5 * rho * u * u + rho * e hydro_IC[i].updateState(rho, rho * u, E) # plot hydro initial conditions plotHydroSolutions(mesh, hydro_IC) rad_IC = Radiation(psi_IC) # create hydro BC hydro_BC = HydroBC(bc_type='fixed', mesh=mesh, state_L=state_l, state_R=state_r) hydro_BC = HydroBC(mesh=mesh, bc_type='reflective') # transient options t_start = 0.0 # if run standalone, then be verbose if __name__ == '__main__': verbosity = 2 else: verbosity = 0 # run the rad-hydro transient rad_new, hydro_new = runNonlinearTransient(mesh=mesh, problem_type='rad_hydro', dt_option='CFL', CFL=0.6, use_2_cycles=True, t_start=t_start, t_end=t_end, rad_BC=rad_BC, cross_sects=cross_sects, rad_IC=rad_IC, hydro_IC=hydro_IC, hydro_BC=hydro_BC, verbosity=verbosity, slope_limiter=slope_limiter, check_balance=False) # plot if __name__ == '__main__': # compute exact hydro solution hydro_exact = None # plot hydro solution plotHydroSolutions(mesh, hydro_new, exact=hydro_exact) # plot material and radiation temperatures plotTemperatures(mesh, rad_new.E, hydro_states=hydro_new, print_values=True, save=True, filename=test_filename, exact_solution_filename=exact_solution_filename) # plot angular fluxes plotS2Erg(mesh, rad_new.psim, rad_new.psip)
def runConvergenceTest(self, time_stepper): # transient options dt_start = 0.01 # time step size t_start = 0.0 # start time t_end = 0.1 # end time # constant cross section values sig_s = 1.0 sig_a = 2.0 # boundary fluxes psi_left = 0.0 psi_right = 0.0 # compute exact scalar flux solution def exactScalarFlux(x): return t_end * sin(pi * x) + 2.0 * t_end * sin(pi * (1.0 - x)) # create symbolic expressions for MMS solution x, t, alpha = sym.symbols('x t alpha') psim = 2 * t * sym.sin(sym.pi * (1 - x)) psip = t * sym.sin(sym.pi * x) # number of elements n_elems = 10 # number of refinement cycles n_cycles = 5 # initialize lists for mesh size and L1 error for each cycle max_dx = list() L1_error = list() # print header if __name__ == '__main__': print('\n%s:' % time_stepper) # loop over refinement cycles for cycle in xrange(n_cycles): if __name__ == '__main__': print("\nCycle %d of %d: n_elems = %d" % (cycle + 1, n_cycles, n_elems)) # create uniform mesh mesh = Mesh(n_elems, 1.0) # append max dx for this cycle to list max_dx.append(mesh.max_dx) # radiation BC rad_BC = RadBC(mesh, "dirichlet", psi_left=psi_left, psi_right=psi_right) # compute uniform cross sections cross_sects = [(ConstantCrossSection(sig_s, sig_s + sig_a), ConstantCrossSection(sig_s, sig_s + sig_a)) for i in xrange(mesh.n_elems)] # create source function handles psim_src, psip_src = createMMSSourceFunctionsRadOnly( psim=psim, psip=psip, sigma_s_value=sig_s, sigma_a_value=sig_a) # IC n_dofs = mesh.n_elems * 4 rad_IC = Radiation(np.zeros(n_dofs)) # if run standalone, then be verbose if __name__ == '__main__': verbosity = 2 else: verbosity = 0 # run transient rad_new = runLinearTransient(mesh=mesh, time_stepper=time_stepper, dt_option='constant', dt_constant=dt_start, t_start=t_start, t_end=t_end, rad_BC=rad_BC, cross_sects=cross_sects, rad_IC=rad_IC, psim_src=psim_src, psip_src=psip_src, verbosity=verbosity) # compute L1 error L1_error.append(\ computeL1ErrorLD(mesh, rad_new.phi, exactScalarFlux)) # double number of elements for next cycle n_elems *= 2 # compute convergence rates rates = computeConvergenceRates(max_dx, L1_error) # print convergence table if not being run in suite if __name__ == '__main__': printConvergenceTable(max_dx, L1_error, rates=rates, dx_desc='dx', err_desc='L1') # check that final rate is approximately 2nd order self.assert_(rates[n_cycles - 2] > 1.95)
def test_RadTransientBDF2(self): # create uniform mesh mesh = Mesh(50, 5.0) # compute uniform cross sections sig_s = 1.0 sig_a = 2.0 cross_sects = [(ConstantCrossSection(sig_s, sig_s + sig_a), ConstantCrossSection(sig_s, sig_s + sig_a)) for i in xrange(mesh.n_elems)] # transient options dt = 0.1 # time step size t_start = 0.0 # start time t_end = 10.0 # end time time_stepper = 'BDF2' # time-stepper # boundary fluxes psi_left = 2.5 psi_right = 2.2 rad_BC = RadBC(mesh, "dirichlet", psi_left=psi_left, psi_right=psi_right) # create source function handles psim_src = lambda x, t: 2.4 psip_src = lambda x, t: 2.4 # IC n_dofs = mesh.n_elems * 4 rad_IC = Radiation(np.zeros(n_dofs)) # if run standalone, then be verbose if __name__ == '__main__': verbosity = 2 else: verbosity = 0 # run transient rad_new = runLinearTransient(mesh=mesh, time_stepper=time_stepper, dt_option='constant', dt_constant=dt, t_start=t_start, t_end=t_end, rad_BC=rad_BC, cross_sects=cross_sects, rad_IC=rad_IC, psim_src=psim_src, psip_src=psip_src, verbosity=verbosity) # compute the steady-state solution Q = computeRadiationExtraneousSource(psim_src, psip_src, mesh, t_start) rad_ss = radiationSolveSS(mesh, cross_sects, Q, rad_BC=rad_BC) # compute difference of transient and steady-state scalar flux phi_diff = [ tuple(map(operator.sub, rad_new.phi[i], rad_ss.phi[i])) for i in xrange(len(rad_new.phi)) ] # compute discrete L1 norm of difference L1_norm_diff = computeDiscreteL1Norm(phi_diff) # assert that solution has converged to steady-state n_decimal_places = 12 self.assertAlmostEqual(L1_norm_diff, 0.0, n_decimal_places) # plot solutions if run standalone if __name__ == "__main__": plotScalarFlux(mesh, rad_new.psim, rad_new.psip, scalar_flux_exact=rad_ss.phi, exact_data_continuous=False)
def test_PureAbsorberProblem(self): # number of elements n_elems = 50 # mesh L = 10.0 # domain length mesh = Mesh(n_elems,L) # physics data sig_t = 0.1 # total cross section sig_s = 0.0 # scattering cross section inc_minus = 10 # isotropic incoming angular flux for minus direction inc_plus = 20 # isotropic incoming angular flux for plus direction rad_BC = RadBC(mesh, "dirichlet", psi_left=inc_plus, psi_right=inc_minus) # cross sections cross_sects = [(ConstantCrossSection(sig_s,sig_t), ConstantCrossSection(sig_s,sig_t)) for i in xrange(n_elems)] # sources Q = [0.0 for i in xrange(mesh.n_elems*4)] # compute LD solution rad = radiationSolveSS(mesh, cross_sects, Q, rad_BC=rad_BC) # get continuous x-points xlist = makeContinuousXPoints(mesh) # exact solution functions def exactPsiMinus(x): return inc_minus*exp(-sig_t/mu["-"]*(x-L)) def exactPsiPlus(x): return inc_plus *exp(-sig_t/mu["+"]*x) def exactScalarFlux(x): return exactPsiMinus(x) + exactPsiPlus(x) # compute exact solutions psim_exact = [exactPsiMinus(x) for x in xlist] psip_exact = [exactPsiPlus(x) for x in xlist] exact_scalar_flux = [psi_m+psi_p for psi_m, psi_p in zip(psim_exact, psip_exact)] # plot solutions if __name__ == '__main__': plotAngularFlux(mesh, rad.psim, rad.psip, psi_minus_exact=psim_exact, psi_plus_exact=psip_exact) # compute L1 error L1_error = computeL1ErrorLD(mesh,rad.phi,exactScalarFlux) # compute L1 norm of exact solution to be used as normalization constant L1_norm_exact = quad(exactScalarFlux, 0.0, L)[0] # compute relative L1 error L1_relative_error = L1_error / L1_norm_exact # check that L1 error is small n_decimal_places = 3 self.assertAlmostEqual(L1_relative_error,0.0,n_decimal_places)
def test_TRTBE(self): # create mesh n_elems = 200 mesh = Mesh(n_elems, 1.) # time step size and transient start and end times dt = 0.001 t_start = 0.0 #t_end = 0.01 t_end = 0.1 # initialize temperature T_init = 0.05 T_l = 0.5 T_r = 0.05 # gamma constant gam = 1.4 # material 1 properties and IC sig_s1 = 0.0 sig_a1 = 0.2 c_v1 = convSpecHeatErgsEvToJksKev(1.E+12) rho1 = 0.01 e1 = T_init * c_v1 # material 2 properties and IC sig_s2 = 0.0 sig_a2 = 2000. c_v2 = c_v1 rho2 = 10. e2 = T_init * c_v2 # construct cross sections and hydro IC cross_sects = list() hydro_IC = list() for i in range(mesh.n_elems): if mesh.getElement(i).x_cent < 0.5: # material 1 cross_sects.append( (ConstantCrossSection(sig_s1, sig_s1 + sig_a1), ConstantCrossSection(sig_s1, sig_s1 + sig_a1))) hydro_IC.append( HydroState(u=0, rho=rho1, e=e1, spec_heat=c_v1, gamma=gam)) else: # material 2 cross_sects.append( (ConstantCrossSection(sig_s2, sig_a2 + sig_s2), ConstantCrossSection(sig_s2, sig_a2 + sig_s2))) hydro_IC.append( HydroState(u=0, rho=rho2, e=e2, spec_heat=c_v2, gamma=gam)) # create hydro BC hydro_BC = HydroBC(bc_type='reflective', mesh=mesh) # initialize radiation to equilibrium solution psi_left = computeEquivIntensity(T_l) psi_right = computeEquivIntensity(T_r) rad_IC = Radiation([psi_right for i in range(n_elems * 4)]) rad_BC = RadBC(mesh, "dirichlet", psi_left=psi_left, psi_right=psi_right) # time-stepper time_stepper = "BDF2" # if run standalone, then be verbose if __name__ == '__main__': verbosity = 2 else: verbosity = 0 # run transient rad_new, hydro_new = runNonlinearTransient(mesh=mesh, time_stepper=time_stepper, problem_type='rad_mat', dt_option='constant', dt_constant=dt, t_start=t_start, t_end=t_end, rad_BC=rad_BC, cross_sects=cross_sects, rad_IC=rad_IC, hydro_IC=hydro_IC, hydro_BC=hydro_BC, verbosity=verbosity, check_balance=True) # plot solutions if run standalone if __name__ == "__main__": plotTemperatures(mesh, rad_new.E, hydro_states=hydro_new, print_values=False)
def test_RadHydroMMS(self): # slope limiter: choices are: # none step minmod double-minmod superbee minbee vanleer slope_limiter = 'none' # number of elements n_elems = 50 # end time t_end = 0.1 # choice of solutions for hydro hydro_case = "linear" # constant linear exponential # choice of solutions for radiation rad_case = "zero" # zero constant sin # declare symbolic variables x, t, alpha, c = symbols('x t alpha c') # create solution for thermodynamic state and flow field if hydro_case == "constant": rho = sympify('4.0') u = sympify('1.2') E = sympify('10.0') elif hydro_case == "linear": rho = 1 + x - t u = sympify('1') E = 5 + 5 * (x - 0.5)**2 elif hydro_case == "exponential": rho = exp(x + t) + 5 u = exp(-x) * sin(t) - 1 E = 10 * exp(x + t) else: raise NotImplementedError("Invalid hydro test case") # create solution for radiation field if rad_case == "zero": psim = sympify('0') psip = sympify('0') elif rad_case == "constant": psim = 50 * c psip = 50 * c elif rad_case == "sin": rad_scale = 50 * c psim = rad_scale * 2 * t * sin(pi * (1 - x)) + 10 * c psip = rad_scale * t * sin(pi * x) + 10 * c else: raise NotImplementedError("Invalid radiation test case") # numeric values alpha_value = 0.01 cv_value = 1.0 gamma_value = 1.4 sig_s = 1.0 sig_a = 1.0 #sig_a = 0.0 # create MMS source functions rho_src, mom_src, E_src, psim_src, psip_src = createMMSSourceFunctionsRadHydro( rho=rho, u=u, E=E, psim=psim, psip=psip, sigma_s_value=sig_s, sigma_a_value=sig_a, gamma_value=gamma_value, cv_value=cv_value, alpha_value=alpha_value, display_equations=False) # create functions for exact solutions substitutions = dict() substitutions['alpha'] = alpha_value substitutions['c'] = GC.SPD_OF_LGT rho = rho.subs(substitutions) u = u.subs(substitutions) mom = rho * u E = E.subs(substitutions) psim = psim.subs(substitutions) psip = psip.subs(substitutions) rho_f = lambdify((symbols('x'), symbols('t')), rho, "numpy") u_f = lambdify((symbols('x'), symbols('t')), u, "numpy") mom_f = lambdify((symbols('x'), symbols('t')), mom, "numpy") E_f = lambdify((symbols('x'), symbols('t')), E, "numpy") psim_f = lambdify((symbols('x'), symbols('t')), psim, "numpy") psip_f = lambdify((symbols('x'), symbols('t')), psip, "numpy") # create uniform mesh width = 1.0 mesh = Mesh(n_elems, width) # compute radiation IC psi_IC = computeRadiationVector(psim_f, psip_f, mesh, t=0.0) rad_IC = Radiation(psi_IC) # compute radiation BC; assumes BC is independent of time psi_left = psip_f(x=0.0, t=0.0) psi_right = psim_f(x=width, t=0.0) #Create Radiation BC object rad_BC = RadBC(mesh, "dirichlet", psi_left=psi_left, psi_right=psi_right) # compute hydro IC hydro_IC = computeAnalyticHydroSolution(mesh, t=0.0, rho=rho_f, u=u_f, E=E_f, cv=cv_value, gamma=gamma_value) # create hydro BC hydro_BC = HydroBC(bc_type='dirichlet', mesh=mesh, rho_BC=rho_f, mom_BC=mom_f, erg_BC=E_f) # create cross sections cross_sects = [(ConstantCrossSection(sig_s, sig_s + sig_a), ConstantCrossSection(sig_s, sig_s + sig_a)) for i in xrange(mesh.n_elems)] # if run standalone, then be verbose if __name__ == '__main__': verbosity = 2 else: verbosity = 0 # run the rad-hydro transient rad_new, hydro_new = runNonlinearTransient( mesh=mesh, problem_type='rad_hydro', dt_option='CFL', #dt_option = 'constant', CFL=0.5, #dt_constant = 0.002, slope_limiter=slope_limiter, time_stepper='BDF2', use_2_cycles=True, t_start=0.0, t_end=t_end, rad_BC=rad_BC, cross_sects=cross_sects, rad_IC=rad_IC, hydro_IC=hydro_IC, hydro_BC=hydro_BC, mom_src=mom_src, E_src=E_src, rho_src=rho_src, psim_src=psim_src, psip_src=psip_src, verbosity=verbosity, check_balance=False) # plot if __name__ == '__main__': # compute exact hydro solution hydro_exact = computeAnalyticHydroSolution(mesh, t=t_end, rho=rho_f, u=u_f, E=E_f, cv=cv_value, gamma=gamma_value) # plot hydro solution plotHydroSolutions(mesh, hydro_new, x_exact=mesh.getCellCenters(), exact=hydro_exact) # compute exact radiation energy Er_exact_fn = 1. / GC.SPD_OF_LGT * (psim + psip) Er_exact = [] x = mesh.getCellCenters() for xi in x: substitutions = {'x': xi, 't': t_end} Er_exact.append(Er_exact_fn.subs(substitutions)) # plot radiation energy plotRadErg(mesh, rad_new.E, exact_Er=Er_exact)
def test_SSConvergence(self): # physics data sig_a = 0.25 # absorption cross section sig_s = 0.75 # scattering cross section sig_t = sig_s + sig_a # total cross section D = 1.0 / (3 * sig_t) # diffusion coefficient L = sqrt(D / sig_a) # diffusion length xL = 0.0 # left boundary of domain xR = 3.0 # right boundary of domain Q = 1.0 # isotropic source A = 2.4084787907 # constant used in exact solution function B = -2.7957606046 # constant used in exact solution function # function for exact scalar flux solution def exactScalarFlux(x): return A * sinh(x / L) + B * cosh(x / L) + Q * L * L / D # number of elements n_elems = 10 # number of refinement cycles n_cycles = 5 # initialize lists for mesh size and L1 error for each cycle max_dx = list() L1_error = list() # loop over refinement cycles for cycle in xrange(n_cycles): if __name__ == '__main__': print("Cycle %d of %d: n_elems = %d" % (cycle + 1, n_cycles, n_elems)) # mesh mesh = Mesh(n_elems, xR) # append max dx for this cycle to list max_dx.append(mesh.max_dx) # radiation BC rad_BC = RadBC(mesh, "dirichlet", psi_left=0.0, psi_right=0.0) # cross sections cross_sects = [(ConstantCrossSection(sig_s, sig_t), ConstantCrossSection(sig_s, sig_t)) for i in xrange(n_elems)] # sources Q_iso = [(0.5 * Q) for i in xrange(mesh.n_elems * 4)] # compute LD solution rad = radiationSolveSS(mesh, cross_sects, Q_iso, rad_BC=rad_BC) # compute L1 error L1_error.append(\ computeL1ErrorLD(mesh, rad.phi, exactScalarFlux)) # double number of elements for next cycle n_elems *= 2 # compute convergence rates rates = computeConvergenceRates(max_dx, L1_error) # print convergence table if not being run in suite if __name__ == '__main__': printConvergenceTable(max_dx, L1_error, rates=rates, dx_desc='dx', err_desc='L1') # check that final rate is approximately 2nd order self.assert_(rates[n_cycles - 2] > 1.95)
def test_PureScatteringProblem(self): # physics data sig_a = 0.0 # absorption cross section sig_s = 1.0 # scattering cross section sig_t = sig_s + sig_a # total cross section xL = 0.0 # left boundary of domain width = 100.0 # domain width xR = xL + width # right boundary of domain inc_j_minus = 1 # incoming minus direction half-range current inc_j_plus = 3 # incoming plus direction half-range current Q = 1.0 # isotropic source D = 1.0 / (3 * sig_t) # diffusion coefficient # number of elements n_elems = 50 # mesh mesh = Mesh(n_elems, width, xL) # radiation BC rad_BC = RadBC(mesh, "dirichlet", psi_left=2 * inc_j_plus, psi_right=2 * inc_j_minus) # cross sections cross_sects = [(ConstantCrossSection(sig_s, sig_t), ConstantCrossSection(sig_s, sig_t)) for i in xrange(n_elems)] # sources Q_src = [0.5 * Q for i in xrange(mesh.n_elems * 4)] # compute LD solution rad = radiationSolveSS(mesh, cross_sects, Q_src, rad_BC=rad_BC) # get continuous x-points xlist = makeContinuousXPoints(mesh) # function for the exact scalar flux solution def exactScalarFlux(x): return Q / (2 * D) * (2 * D * xR + xR * x - x * x) # compute exact scalar flux solution scalar_flux_exact = [exactScalarFlux(x) for x in xlist] # plot solutions if __name__ == '__main__': plotScalarFlux(mesh, rad.psim, rad.psip, scalar_flux_exact=scalar_flux_exact) # compute L1 error L1_error = computeL1ErrorLD(mesh, rad.phi, exactScalarFlux) # compute L1 norm of exact solution to be used as normalization constant L1_norm_exact = quad(exactScalarFlux, xL, xR)[0] # compute relative L1 error L1_relative_error = L1_error / L1_norm_exact # check that L1 error is small n_decimal_places = 2 self.assertAlmostEqual(L1_relative_error, 0.0, n_decimal_places)
def test_RadHydroMMS(self): # declare symbolic variables x, t, A, B, C, c, cv, gamma, mu, alpha = \ symbols('x t A B C c cv gamma mu alpha') #These constants, as well as cross sections and C_v, rho_ref #will set the material #and radiation to be small relative to kinetic energy Ctilde = 100. P = 0.1 #Arbitrary mach number well below the sound speed. The choice of gamma and #the cv value, as well as C and P constrain all other material reference #parameters, but we are free to choose the material velocity below the sound #speed to ensure no shocks are formed M = 0.9 cfl_value = 0.6 #but 2 time steps, so really like a CFL of 0.3 width = 2.0 * math.pi # numeric values gamma_value = 5. / 3. cv_value = 0.14472799784454 # number of refinement cycles n_cycles = 5 # number of elements in first cycle n_elems = 40 # transient options t_start = 0.0 t_end = 2.0 * math.pi / Ctilde # numeric values A_value = 1.0 B_value = 1.0 C_value = 1.0 alpha_value = 0.5 gamma_value = 5.0 / 3.0 sig_s_value = 0.0 sig_a_value = 1.0 # numeric values a_inf = GC.SPD_OF_LGT / Ctilde #T_inf = a_inf**2/(gamma_value*(gamma_value - 1.)*cv_value) #rho_inf = GC.RAD_CONSTANT*T_inf**4/(P*a_inf**2) rho_inf = 1.0 T_inf = pow(rho_inf * P * a_inf**2 / GC.RAD_CONSTANT, 0.25) #to set T_inf based on rho_inf, cv_value = a_inf**2 / (T_inf * gamma_value * (gamma_value - 1.) ) # to set c_v, if rho specified p_inf = rho_inf * a_inf * a_inf Er_inf = GC.RAD_CONSTANT * T_inf**4 # MMS solutions rho = rho_inf * A * (sin(B * x - C * t) + 2.) u = M * a_inf * 1. / (A * (sin(B * x - C * t) + 2.)) p = p_inf * A * alpha * (sin(B * x - C * t) + 2.) Er = alpha * (sin(B * x - Ctilde * C * t) + 2.) * Er_inf Fr = alpha * (sin(B * x - Ctilde * C * t) + 2.) * c * Er_inf #Er = 0.5*(sin(2*pi*x - 10.*t) + 2.)/c #Fr = 0.5*(sin(2*pi*x - 10.*t) + 2.) e = p / (rho * (gamma_value - 1.)) E = 0.5 * rho * u * u + rho * e print "The dimensionalization parameters are: " print " a_inf : ", a_inf print " T_inf : ", T_inf print " rho_inf : ", rho_inf print " p_inf : ", p_inf # derived solutions T = e / cv_value E = rho * (u * u / 2 + e) psip = (Er * c + Fr / mu) / 2 psim = (Er * c - Fr / mu) / 2 # create list of substitutions substitutions = dict() substitutions['A'] = A_value substitutions['B'] = B_value substitutions['C'] = C_value substitutions['c'] = GC.SPD_OF_LGT substitutions['cv'] = cv_value substitutions['gamma'] = gamma_value substitutions['mu'] = RU.mu["+"] substitutions['alpha'] = alpha_value # make substitutions rho = rho.subs(substitutions) u = u.subs(substitutions) mom = rho * u E = E.subs(substitutions) psim = psim.subs(substitutions) psip = psip.subs(substitutions) # create MMS source functions rho_src, mom_src, E_src, psim_src, psip_src = createMMSSourceFunctionsRadHydro( rho=rho, u=u, E=E, psim=psim, psip=psip, sigma_s_value=sig_s_value, sigma_a_value=sig_a_value, gamma_value=gamma_value, cv_value=cv_value, alpha_value=alpha_value, display_equations=True) # create functions for exact solutions rho_f = lambdify((symbols('x'), symbols('t')), rho, "numpy") u_f = lambdify((symbols('x'), symbols('t')), u, "numpy") mom_f = lambdify((symbols('x'), symbols('t')), mom, "numpy") E_f = lambdify((symbols('x'), symbols('t')), E, "numpy") psim_f = lambdify((symbols('x'), symbols('t')), psim, "numpy") psip_f = lambdify((symbols('x'), symbols('t')), psip, "numpy") dt = [] dx = [] err = [] for cycle in range(n_cycles): # create uniform mesh mesh = Mesh(n_elems, width) # compute radiation IC psi_IC = computeRadiationVector(psim_f, psip_f, mesh, t=0.0) rad_IC = Radiation(psi_IC) # create rad BC object rad_BC = RadBC(mesh, 'periodic') # compute hydro IC hydro_IC = computeAnalyticHydroSolution(mesh, t=0.0, rho=rho_f, u=u_f, E=E_f, cv=cv_value, gamma=gamma_value) # create hydro BC hydro_BC = HydroBC(bc_type='periodic', mesh=mesh) # create cross sections cross_sects = [(ConstantCrossSection(sig_s_value, sig_s_value + sig_a_value), ConstantCrossSection(sig_s_value, sig_s_value + sig_a_value)) for i in xrange(mesh.n_elems)] # compute the initial time step size according to CFL conditon (actually # half). We will then decrease this time step by the same factor as DX each # cycle if cycle == 0: sound_speed = [ sqrt(i.p * i.gamma / i.rho) + abs(i.u) for i in hydro_IC ] dt_vals = [ cfl_value * (mesh.elements[i].dx) / sound_speed[i] for i in xrange(len(hydro_IC)) ] dt_value = min(dt_vals) print "dt_value for hydro: ", dt_value #Make sure not taking too large of step for radiation time scale period = 2. * math.pi / Ctilde dt_value = min(dt_value, period / 8.) print "initial dt_value", dt_value #Adjust the end time to be an exact increment of dt_values print "t_end: ", t_end print "This cycle's dt value: ", dt_value dt.append(dt_value) dx.append(mesh.getElement(0).dx) # if run standalone, then be verbose if __name__ == '__main__': verbosity = 2 else: verbosity = 0 #slope limiter limiter = 'double-minmod' # run the rad-hydro transient rad_new, hydro_new = runNonlinearTransient( mesh=mesh, problem_type='rad_hydro', dt_option='constant', dt_constant=dt_value, slope_limiter=limiter, time_stepper='BDF2', use_2_cycles=True, t_start=t_start, t_end=t_end, rad_BC=rad_BC, cross_sects=cross_sects, rad_IC=rad_IC, hydro_IC=hydro_IC, hydro_BC=hydro_BC, mom_src=mom_src, E_src=E_src, rho_src=rho_src, psim_src=psim_src, psip_src=psip_src, verbosity=verbosity, rho_f=rho_f, u_f=u_f, E_f=E_f, gamma_value=gamma_value, cv_value=cv_value, check_balance=False) # compute exact hydro solution hydro_exact = computeAnalyticHydroSolution(mesh, t=t_end, rho=rho_f, u=u_f, E=E_f, cv=cv_value, gamma=gamma_value) rad_exact = computeAnalyticRadSolution(mesh, t_end, psim=psim_f, psip=psip_f) #Compute error err.append( computeHydroL2Error(hydro_new, hydro_exact, rad_new, rad_exact)) n_elems *= 2 dt_value *= 0.5 # compute convergence rates rates_dx = computeHydroConvergenceRates(dx, err) rates_dt = computeHydroConvergenceRates(dt, err) # print convergence table if n_cycles > 1: printHydroConvergenceTable(dx, err, rates=rates_dx, dx_desc='dx', err_desc='$L_2$') printHydroConvergenceTable(dt, err, rates=rates_dt, dx_desc='dt', err_desc='$L_2$') # plot if __name__ == '__main__': # compute exact hydro solution hydro_exact = computeAnalyticHydroSolution(mesh, t=t_end, rho=rho_f, u=u_f, E=E_f, cv=cv_value, gamma=gamma_value) # plot hydro solution plotHydroSolutions(mesh, hydro_new, x_exact=mesh.getCellCenters(), exact=hydro_exact) #plot exact and our E_r Er_exact_fn = 1. / GC.SPD_OF_LGT * (psim + psip) Fr_exact_fn = (psip - psim) * RU.mu["+"] Er_exact = [] Fr_exact = [] psip_exact = [] psim_exact = [] x = mesh.getCellCenters() for xi in x: substitutions = {'x': xi, 't': t_end} Er_exact.append(Er_exact_fn.subs(substitutions)) Fr_exact.append(Fr_exact_fn.subs(substitutions)) psip_exact.append(psip_f(xi, t_end)) psim_exact.append(psim_f(xi, t_end)) plotRadErg(mesh, rad_new.E, Fr_edge=rad_new.F, exact_Er=Er_exact, exact_Fr=Fr_exact) plotS2Erg(mesh, rad_new.psim, rad_new.psip, exact_psim=psim_exact, exact_psip=psip_exact) plotTemperatures(mesh, rad_new.E, hydro_states=hydro_new, print_values=True) #Make a pickle to save the error tables from sys import argv pickname = "results/testRadHydroStreamingMMSC100.pickle" if len(argv) > 2: if argv[1] == "-o": pickname = argv[2].strip() #Create dictionary of all the data big_dic = {"dx": dx} big_dic["dt"] = dt big_dic["Errors"] = err pickle.dump(big_dic, open(pickname, "w"))
def test_TransientSourceCN(self): # number of decimal places to test n_decimal_places = 11 # create mesh n_elems = 5 mesh = Mesh(n_elems, random()) # compute uniform cross sections cross_sects = [(ConstantCrossSection(random(), random()), ConstantCrossSection(random(), random())) for i in xrange(mesh.n_elems)] # time step size and c*dt dt = random() c_dt = GC.SPD_OF_LGT * dt # boundary fluxes psi_left = random() psi_right = random() rad_BC = RadBC(mesh, "dirichlet", psi_left=psi_left, psi_right=psi_right) # create the steady-state source n = 4 * mesh.n_elems Q = np.zeros(n) for i in xrange(mesh.n_elems): Q[getIndex(i, "L", "+")] = random() Q[getIndex(i, "R", "+")] = random() Q[getIndex(i, "L", "-")] = random() Q[getIndex(i, "R", "-")] = random() # compute the steady-state solution rad_ss = radiationSolveSS(mesh, cross_sects, Q, rad_BC=rad_BC) # time-stepper time_stepper = "CN" # compute the transient source Q_tr = computeRadiationSource(mesh=mesh, time_stepper=time_stepper, problem_type='rad_only', dt=dt, rad_BC=rad_BC, cx_old=cross_sects, rad_old=rad_ss, Qpsi_old=Q, Qpsi_new=Q) # loop over elements and test that sources are what they should be for i in xrange(mesh.n_elems): iLm = getIndex(i, "L", "-") iLp = getIndex(i, "L", "+") iRm = getIndex(i, "R", "-") iRp = getIndex(i, "R", "+") QiLm_expected = rad_ss.psim[i][0] / c_dt + 0.5 * Q[iLm] QiLp_expected = rad_ss.psip[i][0] / c_dt + 0.5 * Q[iLp] QiRm_expected = rad_ss.psim[i][1] / c_dt + 0.5 * Q[iRm] QiRp_expected = rad_ss.psip[i][1] / c_dt + 0.5 * Q[iRp] self.assertAlmostEqual(Q_tr[iLm], QiLm_expected, n_decimal_places) self.assertAlmostEqual(Q_tr[iLp], QiLp_expected, n_decimal_places) self.assertAlmostEqual(Q_tr[iRm], QiRm_expected, n_decimal_places) self.assertAlmostEqual(Q_tr[iRp], QiRp_expected, n_decimal_places)
def test_Hydro(self): # create mesh n_elems = 100 width = 1.0 mesh = Mesh(n_elems,width) x_diaphragm = 0.3 # time step size and transient start and end times CFL = 0.5 t_start = 0.0 t_end = 0.2 # slope limiter slope_limiter = "vanleer" # constant properties sig_s = 1.0 # arbitrary sig_a = 0.0 # set to zero to ensure no emission sig_t = sig_s + sig_a c_v = 3.0 # arbitrary gam = 1.4 # hydro IC values for left half of domain rhoL = 1.0 uL = 0.75 pL = 1.0 # hydro IC values for right half of domain rhoR = 0.125 uR = 0.0 pR = 0.1 # compute left and right internal energies eL = pL/(rhoL*(gam - 1.0)) eR = pR/(rhoR*(gam - 1.0)) # construct cross sections and hydro IC cross_sects = list() hydro_IC = list() for i in range(mesh.n_elems): # cross section is constant cross_sects.append( (ConstantCrossSection(sig_s, sig_t), ConstantCrossSection(sig_s, sig_t)) ) # IC for left half of domain if mesh.getElement(i).x_cent < x_diaphragm: hydro_IC.append( HydroState(u=uL,rho=rhoL,e=eL,gamma=gam,spec_heat=c_v) ) # IC for right half of domain else: hydro_IC.append( HydroState(u=uR,rho=rhoR,e=eR,gamma=gam,spec_heat=c_v) ) # create hydro BC hydro_BC = HydroBC(bc_type='reflective', mesh=mesh) # initialize radiation to zero solution to give pure hydrodynamics rad_IC = Radiation([0.0 for i in range(n_elems*4)]) psi_left = 0.0 psi_right = 0.0 rad_BC = RadBC(mesh, "dirichlet", psi_left=psi_left, psi_right=psi_right) # if run standalone, then be verbose if __name__ == '__main__': verbosity = 2 else: verbosity = 0 # run transient rad_new, hydro_new = runNonlinearTransient( mesh = mesh, time_stepper = 'BE', problem_type = 'rad_hydro', dt_option = 'CFL', CFL = 0.5, use_2_cycles = True, t_start = t_start, t_end = t_end, rad_BC = rad_BC, cross_sects = cross_sects, rad_IC = rad_IC, hydro_IC = hydro_IC, hydro_BC = hydro_BC, slope_limiter = slope_limiter, verbosity = verbosity, check_balance= True) # plot solutions if run standalone if __name__ == "__main__": # get exact solutions #get the exact values f = open('exact_testHydro.txt', 'r') x_e = [] u_e = [] p_e = [] rho_e = [] e_e = [] for line in f: if len(line.split())==1: t = line.split() else: data = line.split() x_e.append(float(data[0])) u_e.append(float(data[1])) p_e.append(float(data[2])) rho_e.append(float(data[4])) e_e.append(float(data[3])) hydro_exact = [] for i in range(len(x_e)): hydro_exact.append(HydroState(u=u_e[i],rho=rho_e[i],e=e_e[i],gamma=gam,spec_heat=c_v) ) plotHydroSolutions(mesh, hydro_new,x_exact=x_e,exact=hydro_exact)
def test_RadHydroMMS(self): # declare symbolic variables x, t, alpha, c = symbols('x t alpha c') # numeric values alpha_value = 0.01 cv_value = 1.0 gamma_value = 1.4 sig_s = 1.0 sig_a = 1.0 # create solution for thermodynamic state and flow field # rho = sympify('4.0') # u = sympify('1.0') # E = sympify('10.0') rho = 2. + sin(2 * pi * x + t) u = 2. + cos(2 * pi * x - t) p = 2. + cos(2 * pi * x + t) e = p / (rho * (gamma_value - 1.)) E = 0.5 * rho * u * u + rho * e # create solution for radiation field rad_scale = 50 * c psim = rad_scale * (2 * t * sin(pi * (1 - x)) + 2 + 0.1 * t) psip = rad_scale * (t * sin(pi * x) + 2 + 0.1 * t) # create MMS source functions rho_src, mom_src, E_src, psim_src, psip_src = createMMSSourceFunctionsRadHydro( rho=rho, u=u, E=E, psim=psim, psip=psip, sigma_s_value=sig_s, sigma_a_value=sig_a, gamma_value=gamma_value, cv_value=cv_value, alpha_value=alpha_value, display_equations=True) # create functions for exact solutions substitutions = dict() substitutions['alpha'] = alpha_value substitutions['c'] = GC.SPD_OF_LGT rho = rho.subs(substitutions) u = u.subs(substitutions) mom = rho * u E = E.subs(substitutions) psim = psim.subs(substitutions) psip = psip.subs(substitutions) rho_f = lambdify((symbols('x'), symbols('t')), rho, "numpy") u_f = lambdify((symbols('x'), symbols('t')), u, "numpy") mom_f = lambdify((symbols('x'), symbols('t')), mom, "numpy") E_f = lambdify((symbols('x'), symbols('t')), E, "numpy") psim_f = lambdify((symbols('x'), symbols('t')), psim, "numpy") psip_f = lambdify((symbols('x'), symbols('t')), psip, "numpy") # create uniform mesh n_elems = 50 width = 1.0 mesh = Mesh(n_elems, width) # compute radiation IC psi_IC = computeRadiationVector(psim_f, psip_f, mesh, t=0.0) rad_IC = Radiation(psi_IC) # create rad BC object rad_BC = RadBC(mesh, 'dirichlet', psip_BC=psip_f, psim_BC=psim_f) # compute hydro IC hydro_IC = computeAnalyticHydroSolution(mesh, t=0.0, rho=rho_f, u=u_f, E=E_f, cv=cv_value, gamma=gamma_value) # create hydro BC hydro_BC = HydroBC(bc_type='periodic', mesh=mesh) # create cross sections cross_sects = [(ConstantCrossSection(sig_s, sig_s + sig_a), ConstantCrossSection(sig_s, sig_s + sig_a)) for i in xrange(mesh.n_elems)] # transient options t_start = 0.0 # t_end = 0.005 t_end = 0.02 # if run standalone, then be verbose if __name__ == '__main__': verbosity = 2 else: verbosity = 0 #slope limiter limiter = 'none' # run the rad-hydro transient rad_new, hydro_new = runNonlinearTransient( mesh=mesh, problem_type='rad_hydro', dt_option='CFL', CFL=0.5, # dt_option = 'constant', # dt_constant = 0.0002, slope_limiter=limiter, time_stepper='BDF2', use_2_cycles=True, t_start=t_start, t_end=t_end, rad_BC=rad_BC, cross_sects=cross_sects, rad_IC=rad_IC, hydro_IC=hydro_IC, hydro_BC=hydro_BC, mom_src=mom_src, E_src=E_src, rho_src=rho_src, psim_src=psim_src, psip_src=psip_src, verbosity=verbosity, rho_f=rho_f, u_f=u_f, E_f=E_f, gamma_value=gamma_value, cv_value=cv_value, check_balance=True) # plot if __name__ == '__main__': # plot radiation solution # compute exact hydro solution hydro_exact = computeAnalyticHydroSolution(mesh, t=t_end, rho=rho_f, u=u_f, E=E_f, cv=cv_value, gamma=gamma_value) # plot hydro solution plotHydroSolutions(mesh, hydro_new, x_exact=mesh.getCellCenters(), exact=hydro_exact) #plot exact and our E_r Er_exact_fn = 1. / GC.SPD_OF_LGT * (psim + psip) Er_exact = [] x = mesh.getCellCenters() for xi in x: substitutions = {'x': xi, 't': t_end} Er_exact.append(Er_exact_fn.subs(substitutions)) plotRadErg(mesh, rad_new.E, exact_Er=Er_exact)
def test_RadHydroMMS(self): # declare symbolic variables x, t, alpha, c, a, mu = symbols('x t alpha c a mu') # number of refinement cycles n_cycles = 5 # number of elements in first cycle n_elems = 20 # We will increase sigma and nondimensional C as we decrease the mesh # size to ensure we stay in the diffusion limit # numeric values gamma_value = 5. / 3. cv_value = 0.14472799784454 # run for a fixed amount of time t_end = 2. * pi sig_s = 0.0 #Want material speeed to be a small fraction of speed of light #and radiation to be small relative to kinetic energy P = 0.001 # a_r T_inf^4/(rho_inf*u_inf^2) #Arbitrary ratio of pressure to density alpha_value = 0.5 #Arbitrary mach number well below the sound speed. The choice of gamma and #the cv value, as well as C and P constrain all other material reference #parameters, but we are free to choose the material velocity below the sound #speed to ensure no shocks are formed M = 0.9 cfl_value = 0.6 #but 2 time steps, so really like a CFL of 0.3 dt = [] dx = [] err = [] for cycle in range(n_cycles): #Keep ratio of and sig_a*dx constant, staying in diffusion limit C = sig_a = 100000. / 20 * n_elems # c/a_inf sig_t = sig_s + sig_a a_inf = GC.SPD_OF_LGT / C #These lines of code assume specified C_v T_inf = a_inf**2 / (gamma_value * (gamma_value - 1.) * cv_value) rho_inf = GC.RAD_CONSTANT * T_inf**4 / (P * a_inf**2) #Specify rho_inf and determine T_inf and Cv_value rho_inf = 1.0 #If we don't choose a reference density, then the specific heat values get ridiculous T_inf = pow(rho_inf * P * a_inf**2 / GC.RAD_CONSTANT, 0.25) #to set T_inf based on rho_inf, cv_value = a_inf**2 / (T_inf * gamma_value * (gamma_value - 1.) ) # to set c_v, if rho specified #Specify T_inf and solve for rho_inf and C_v value # T_inf = 1 # rho_inf = GC.RAD_CONSTANT*T_inf**4/(P*a_inf**2) # cv_value = a_inf**2/(T_inf*gamma_value*(gamma_value-1.)) # to set c_v, if rho specified #Same for all approachs p_inf = rho_inf * a_inf * a_inf print "The dimensionalization parameters are: " print " a_inf : ", a_inf print " T_inf : ", T_inf print " rho_inf : ", rho_inf print " p_inf : ", p_inf print " C_v : ", cv_value print " gamma : ", gamma_value # create solution for thermodynamic state and flow field rho = rho_inf * (2. + sin(x - t)) u = a_inf * M * 0.5 * (2. + cos(x - t)) p = alpha_value * p_inf * (2. + cos(x - t)) e = p / (rho * (gamma_value - 1.)) E = 0.5 * rho * u * u + rho * e # create solution for radiation field based on solution for F # that is the leading order diffusion limit solution T = e / cv_value Er = a * T**4 Fr = -1. / (3. * sig_t) * c * diff(Er, x) + sympify('4./3.') * Er * u #Form psi+ and psi- from Fr and Er psip = (Er * c * mu + Fr) / (2. * mu) psim = (Er * c * mu - Fr) / (2. * mu) # create functions for exact solutions substitutions = dict() substitutions['alpha'] = alpha_value substitutions['c'] = GC.SPD_OF_LGT substitutions['a'] = GC.RAD_CONSTANT substitutions['mu'] = RU.mu["+"] rho = rho.subs(substitutions) u = u.subs(substitutions) mom = rho * u E = E.subs(substitutions) psim = psim.subs(substitutions) psip = psip.subs(substitutions) T = T.subs(substitutions) rho_f = lambdify((symbols('x'), symbols('t')), rho, "numpy") u_f = lambdify((symbols('x'), symbols('t')), u, "numpy") mom_f = lambdify((symbols('x'), symbols('t')), mom, "numpy") E_f = lambdify((symbols('x'), symbols('t')), E, "numpy") psim_f = lambdify((symbols('x'), symbols('t')), psim, "numpy") psip_f = lambdify((symbols('x'), symbols('t')), psip, "numpy") T_f = lambdify((symbols('x'), symbols('t')), T, "numpy") Er = Er.subs(substitutions) Er = lambdify((symbols('x'), symbols('t')), Er, "numpy") #For reference create lambda as ratio of aT^4/rho--u^2 to check #P_f = lambda x,t: GC.RAD_CONSTANT*T_f(x,t)**4/(rho_f(x,t)*u_f(x,t)**2) #dx = 1./100. #x = -1.*dx #t=0.2 #for i in range(100): # x += dx # print "ratio:", P_f(x,t) # create MMS source functions rho_src, mom_src, E_src, psim_src, psip_src = createMMSSourceFunctionsRadHydro( rho=rho, u=u, E=E, psim=psim, psip=psip, sigma_s_value=sig_s, sigma_a_value=sig_a, gamma_value=gamma_value, cv_value=cv_value, alpha_value=alpha_value, display_equations=True) # mesh width = 2. * pi mesh = Mesh(n_elems, width) # compute hydro IC for the sake of computing initial time step size hydro_IC = computeAnalyticHydroSolution(mesh, t=0.0, rho=rho_f, u=u_f, E=E_f, cv=cv_value, gamma=gamma_value) # compute the initial time step size according to CFL conditon (actually # half). We will then decrease this time step by the same factor as DX each # cycle if cycle == 0: sound_speed = [ sqrt(i.p * i.gamma / i.rho) + abs(i.u) for i in hydro_IC ] dt_vals = [ cfl_value * (mesh.elements[i].dx) / sound_speed[i] for i in xrange(len(hydro_IC)) ] dt_value = min(min(dt_vals), 0.5) #don't take too big of time step print "initial dt_value", dt_value #Adjust the end time to be an exact increment of dt_values print "old t_end: ", t_end print "new t_end: ", t_end print "This cycle's dt value: ", dt_value # create uniform mesh mesh = Mesh(n_elems, width) dt.append(dt_value) dx.append(mesh.getElement(0).dx) # compute radiation IC psi_IC = computeRadiationVector(psim_f, psip_f, mesh, t=0.0) rad_IC = Radiation(psi_IC) # create rad BC object rad_BC = RadBC(mesh, 'periodic') # compute hydro IC hydro_IC = computeAnalyticHydroSolution(mesh, t=0.0, rho=rho_f, u=u_f, E=E_f, cv=cv_value, gamma=gamma_value) # Dimensionless parameters. These are all evaluated at peaks of trig # functions, very hard coded print "---------------------------------------------" print " Diffusion limit info:" print "---------------------------------------------" print "Size in mfp of cell", mesh.getElement(0).dx * sig_t print "Ratio of radiation energy to kinetic", Er(0.75, 0) / (rho_f( 0.25, 0) * u_f(0.0, 0)**2), GC.RAD_CONSTANT * T_inf**4 / ( rho_inf * a_inf**2) print "Ratio of speed of light to material sound speed", GC.SPD_OF_LGT / u_f( 0.0, 0), GC.SPD_OF_LGT / (a_inf) print "---------------------------------------------" # create hydro BC hydro_BC = HydroBC(bc_type='periodic', mesh=mesh) # create cross sections cross_sects = [(ConstantCrossSection(sig_s, sig_s + sig_a), ConstantCrossSection(sig_s, sig_s + sig_a)) for i in xrange(mesh.n_elems)] # transient options t_start = 0.0 # if run standalone, then be verbose if __name__ == '__main__': verbosity = 2 else: verbosity = 0 #slope limiter limiter = 'double-minmod' # run the rad-hydro transient rad_new, hydro_new = runNonlinearTransient( mesh=mesh, problem_type='rad_hydro', dt_option='constant', dt_constant=dt_value, slope_limiter=limiter, time_stepper='BDF2', use_2_cycles=True, t_start=t_start, t_end=t_end, rad_BC=rad_BC, cross_sects=cross_sects, rad_IC=rad_IC, hydro_IC=hydro_IC, hydro_BC=hydro_BC, mom_src=mom_src, E_src=E_src, rho_src=rho_src, psim_src=psim_src, psip_src=psip_src, verbosity=verbosity, rho_f=rho_f, u_f=u_f, E_f=E_f, gamma_value=gamma_value, cv_value=cv_value, check_balance=True) # compute exact hydro solution hydro_exact = computeAnalyticHydroSolution(mesh, t=t_end, rho=rho_f, u=u_f, E=E_f, cv=cv_value, gamma=gamma_value) rad_exact = computeAnalyticRadSolution(mesh, t_end, psim=psim_f, psip=psip_f) #Compute error err.append( computeHydroL2Error(hydro_new, hydro_exact, rad_new, rad_exact)) n_elems *= 2 dt_value *= 0.5 # compute convergence rates rates_dx = computeHydroConvergenceRates(dx, err) rates_dt = computeHydroConvergenceRates(dt, err) # print convergence table if n_cycles > 1: printHydroConvergenceTable(dx, err, rates=rates_dx, dx_desc='dx', err_desc='$L_2$') printHydroConvergenceTable(dt, err, rates=rates_dt, dx_desc='dt', err_desc='$L_2$') # plot if __name__ == '__main__': # compute exact hydro solution hydro_exact = computeAnalyticHydroSolution(mesh, t=t_end, rho=rho_f, u=u_f, E=E_f, cv=cv_value, gamma=gamma_value) # plot hydro solution plotHydroSolutions(mesh, hydro_new, x_exact=mesh.getCellCenters(), exact=hydro_exact) #plot exact and our E_r Er_exact_fn = 1. / GC.SPD_OF_LGT * (psim + psip) Fr_exact_fn = (psip - psim) * RU.mu["+"] Er_exact = [] Fr_exact = [] psip_exact = [] psim_exact = [] x = mesh.getCellCenters() for xi in x: substitutions = {'x': xi, 't': t_end} Er_exact.append(Er_exact_fn.subs(substitutions)) Fr_exact.append(Fr_exact_fn.subs(substitutions)) psip_exact.append(psip_f(xi, t_end)) psim_exact.append(psim_f(xi, t_end)) plotRadErg(mesh, rad_new.E, Fr_edge=rad_new.F, exact_Er=Er_exact, exact_Fr=Fr_exact) plotS2Erg(mesh, rad_new.psim, rad_new.psip, exact_psim=psim_exact, exact_psip=psip_exact) plotTemperatures(mesh, rad_new.E, hydro_states=hydro_new, print_values=True) #Make a pickle to save the error tables from sys import argv pickname = "results/testRadHydroDiffMMS.pickle" if len(argv) > 2: if argv[1] == "-o": pickname = argv[2].strip() #Create dictionary of all the data big_dic = {"dx": dx} big_dic["dt"] = dt big_dic["Errors"] = err pickle.dump(big_dic, open(pickname, "w"))
def test_HydroMMS(self): # slope limiter: choices are: # none step minmod double-minmod superbee minbee vanleer slope_limiter = 'none' # number of elements in first cycle n_elems = 50 # number of refinement cycles n_cycles = 1 # end time t_end = 0.1 # choice of solutions for hydro hydro_case = "linear" # constant linear exponential # declare symbolic variables x, t, alpha = symbols('x t alpha') # create solution for thermodynamic state and flow field if hydro_case == "constant": rho = sympify('4.0') u = sympify('1.2') E = sympify('10.0') elif hydro_case == "linear": rho = 1 + x - t u = sympify('1') E = 5 + 5 * (x - 0.5)**2 elif hydro_case == "exponential": rho = exp(x + t) + 5 u = exp(-x) * sin(t) - 1 E = 10 * exp(x + t) else: raise NotImplementedError("Invalid hydro test case") # create solution for radiation field psim = sympify('0') psip = sympify('0') # numeric values alpha_value = 0.01 cv_value = 1.0 gamma_value = 1.4 sig_s = 1.0 sig_a = 0.0 # create MMS source functions rho_src, mom_src, E_src, psim_src, psip_src = createMMSSourceFunctionsHydroOnly( rho=rho, u=u, E=E, gamma_value=gamma_value, cv_value=cv_value, alpha_value=alpha_value, display_equations=False) # create functions for exact solutions substitutions = dict() substitutions['alpha'] = alpha_value rho = rho.subs(substitutions) u = u.subs(substitutions) mom = rho * u E = E.subs(substitutions) rho_f = lambdify((symbols('x'), symbols('t')), rho, "numpy") u_f = lambdify((symbols('x'), symbols('t')), u, "numpy") mom_f = lambdify((symbols('x'), symbols('t')), mom, "numpy") E_f = lambdify((symbols('x'), symbols('t')), E, "numpy") psim_f = lambdify((symbols('x'), symbols('t')), psim, "numpy") psip_f = lambdify((symbols('x'), symbols('t')), psip, "numpy") # spatial and temporal domains width = 1.0 # initialize lists for mesh size and L1 error for each cycle max_dx = list() err = list() # loop over refinement cycles for cycle in xrange(n_cycles): if __name__ == '__main__': print("\nCycle %d of %d: n_elems = %d" % (cycle + 1, n_cycles, n_elems)) # create uniform mesh mesh = Mesh(n_elems, width) # append max dx for this cycle to list max_dx.append(mesh.max_dx) # compute radiation IC psi_IC = computeRadiationVector(psim_f, psip_f, mesh, t=0.0) rad_IC = Radiation(psi_IC) #Make rad BC object with vacuum for hydro only rad_BC = RadBC(mesh, "vacuum") # compute hydro IC hydro_IC = computeAnalyticHydroSolution(mesh, t=0.0, rho=rho_f, u=u_f, E=E_f, cv=cv_value, gamma=gamma_value) # create hydro BC hydro_BC = HydroBC(bc_type='dirichlet', mesh=mesh, rho_BC=rho_f, mom_BC=mom_f, erg_BC=E_f) # create cross sections cross_sects = [(ConstantCrossSection(sig_s, sig_s + sig_a), ConstantCrossSection(sig_s, sig_s + sig_a)) for i in xrange(mesh.n_elems)] # if run standalone, then be verbose if __name__ == '__main__': if n_cycles == 1: verbosity = 2 else: verbosity = 1 else: verbosity = 0 # run the rad-hydro transient rad_new, hydro_new = runNonlinearTransient( mesh=mesh, problem_type='rad_hydro', dt_option='CFL', CFL=0.5, slope_limiter=slope_limiter, time_stepper='BDF2', use_2_cycles=True, t_start=0.0, t_end=t_end, rad_BC=rad_BC, hydro_BC=hydro_BC, cross_sects=cross_sects, rad_IC=rad_IC, hydro_IC=hydro_IC, mom_src=mom_src, E_src=E_src, psim_src=psim_src, psip_src=psip_src, rho_src=rho_src, verbosity=verbosity, check_balance=False, rho_f=rho_f, u_f=u_f, E_f=E_f, gamma_value=gamma_value, cv_value=cv_value) # compute exact hydro solution hydro_exact = computeAnalyticHydroSolution(mesh, t=t_end, rho=rho_f, u=u_f, E=E_f, cv=cv_value, gamma=gamma_value) # compute error err.append(computeHydroL2Error(hydro_new, hydro_exact)) # double number of elements for next cycle n_elems *= 2 # compute convergence rates rates = computeHydroConvergenceRates(max_dx, err) # print convergence table and plot if __name__ == '__main__': # print convergence table if n_cycles > 1: printHydroConvergenceTable(max_dx, err, rates=rates, dx_desc='dx', err_desc='L2') # plot hydro solution plotHydroSolutions(mesh, hydro_new, x_exact=mesh.getCellCenters(), exact=hydro_exact)
def test_RadHydroShock(self): # create uniform mesh n_elems = 500 width = 0.04 x_start = -0.02 mesh_center = x_start + 0.5 * width mesh = Mesh(n_elems, width, x_start=x_start) # slope limiter slope_limiter = "double-minmod" # gamma constant gam = 5.0 / 3.0 # material 1 and 2 properties; T_ref = 0.1 #keV reference unshocked, upstream, ambient, equilibrium sig_a1 = 577.35 sig_s1 = 0.0 c_v1 = 0.14472799784454 sig_a2 = sig_a1 sig_s2 = sig_s1 c_v2 = c_v1 #Read in Jim's nondimensional results to set preshock and postshock dimensional mach_number = "1.2" #Choices are 2.0, 1.2, 3.0, 5.0 filename = 'analytic_shock_solutions/data_for_M%s.pickle' % mach_number f = open(filename, 'r') data = pickle.load(f) f.close() #compute scalings based on an assumed density and reference temperature dp = getDimensParams(T_ref=T_ref, rho_ref=1.0, C_v=c_v1, gamma=gam) print data #Scale non-dimensional values into dimensional results rho1 = data['Density'][0] * dp['rho'] u1 = data['Speed'][0] * dp['a'] #velocity times reference sound speed Erad1 = data['Er'][0] * dp['Er'] T1 = data['Tm'][0] * dp["Tm"] e1 = T1 * c_v1 E1 = rho1 * (e1 + 0.5 * u1 * u1) # material 2 IC rho2 = data['Density'][-1] * dp['rho'] u2 = data['Speed'][-1] * dp['a'] #velocity times reference sound speed Erad2 = data['Er'][-1] * dp['Er'] T2 = data['Tm'][-1] * T_ref e2 = T2 * c_v2 E2 = rho2 * (e2 + 0.5 * u2 * u2) print r"$\rho$ & %0.8e & %0.8e & g cm$^{-3}$ \\" % (rho1, rho2) print r"$u$ & %0.8e & %0.8e & cm sh$^{-1}$ \\" % (u1, u2) print r"$T$ & %0.8e & %0.8e & keV \\" % (T1, T2) print r"$E$ & %0.8e & %0.8e & Jks cm$^{-3}$\\" % (E1, E2) print r"$E_r$ & %0.8e & %0.8e & Jks cm$^{-3}$ \\" % (Erad1, Erad2) print r"$F_r$ & %0.8e & %0.8e & Jks cm$^{-2}$ s$^{-1}$ \\" % (0.0, 0.0) print r"vel", u1, "&", u2 print "Temperature", T1, "&", T2 print "momentum", rho1 * u1, "&", rho2 * u2 print "E", E1, "&", E2 print "E_r", Erad1, "&", Erad2 print sig_a1, sig_s1 exit() # material 1 IC # final time t_end = 0.8 # temperature plot filename test_filename = "radshock_mach_" + re.search( "M(\d\.\d)", filename).group(1) + ".pdf" # compute radiation BC; assumes BC is independent of time c = GC.SPD_OF_LGT psi_left = 0.5 * c * Erad1 psi_right = 0.5 * c * Erad2 #Create BC object rad_BC = RadBC(mesh, "dirichlet", psi_left=psi_left, psi_right=psi_right) # construct cross sections and hydro IC cross_sects = list() hydro_IC = list() psi_IC = list() for i in range(mesh.n_elems): if mesh.getElement(i).x_cent < mesh_center: # material 1 cross_sects.append( (ConstantCrossSection(sig_s1, sig_s1 + sig_a1), ConstantCrossSection(sig_s1, sig_s1 + sig_a1))) hydro_IC.append( HydroState(u=u1, rho=rho1, e=e1, spec_heat=c_v1, gamma=gam)) psi_IC += [psi_left for dof in range(4)] else: # material 2 cross_sects.append( (ConstantCrossSection(sig_s2, sig_a2 + sig_s2), ConstantCrossSection(sig_s2, sig_a2 + sig_s2))) hydro_IC.append( HydroState(u=u2, rho=rho2, e=e2, spec_heat=c_v2, gamma=gam)) psi_IC += [psi_right for dof in range(4)] #Convert pickle data to dimensional form data['Density'] *= dp['rho'] data['Speed'] *= dp['a'] data['Er'] *= dp['Er'] data['Tm'] *= dp['Tm'] x_anal = data['x'] #If desired initialize the solutions to analytic result (ish) analytic_IC = False if analytic_IC: hydro_IC = list() psi_IC = list() for i in range(mesh.n_elems): #Determine which analytic x is closest to cell center xcent = mesh.getElement(i).x_cent min_dist = 9001. idx = -1 for j in range(len(x_anal)): if abs(xcent - x_anal[j]) < min_dist: min_dist = abs(xcent - x_anal[j]) idx = j #Create state based on these values, noting that the pickle has already #been dimensionalized rho1 = data['Density'][idx] u1 = data['Speed'][idx] #velocity times reference sound speed Erad1 = data['Er'][idx] T1 = data['Tm'][idx] e1 = T1 * c_v1 E1 = rho1 * (e1 + 0.5 * u1 * u1) psi_left = 0.5 * c * Erad1 hydro_IC.append( HydroState(u=u1, rho=rho1, e=e1, spec_heat=c_v1, gamma=gam)) psi_IC += [psi_left for dof in range(4)] #Smooth out the middle solution optionally, shouldnt need this n_smoothed = 0 state_l = hydro_IC[0] state_r = hydro_IC[-1] rho_l = state_l.rho rho_r = state_r.rho drho = rho_r - rho_l u_l = state_l.u u_r = state_r.u du = u_r - u_l e_l = state_l.e e_r = state_r.e de = e_r - e_l print "p", state_l.p, state_r.p print "mach number", state_l.u / state_l.getSoundSpeed( ), state_r.u / state_r.getSoundSpeed() #Scale idx = 0 if n_smoothed > 0: for i in range(mesh.n_elems / 2 - n_smoothed / 2 - 1, mesh.n_elems / 2 + n_smoothed / 2): rho = rho_l + drho * idx / n_smoothed u = rho_l * u_l / rho e = e_l + de * idx / n_smoothed idx += 1 E = 0.5 * rho * u * u + rho * e hydro_IC[i].updateState(rho, rho * u, E) # plot hydro initial conditions plotHydroSolutions(mesh, hydro_IC) rad_IC = Radiation(psi_IC) # create hydro BC hydro_BC = HydroBC(bc_type='fixed', mesh=mesh, state_L=state_l, state_R=state_r) #Forcing to reflective? Maybe this is the problem hydro_BC = HydroBC(mesh=mesh, bc_type='reflective') # transient options t_start = 0.0 # if run standalone, then be verbose if __name__ == '__main__': verbosity = 2 else: verbosity = 0 # run the rad-hydro transient rad_new, hydro_new = runNonlinearTransient(mesh=mesh, problem_type='rad_hydro', dt_option='CFL', CFL=0.6, use_2_cycles=True, t_start=t_start, t_end=t_end, rad_BC=rad_BC, cross_sects=cross_sects, rad_IC=rad_IC, hydro_IC=hydro_IC, hydro_BC=hydro_BC, verbosity=verbosity, slope_limiter=slope_limiter, check_balance=False) # plot if __name__ == '__main__': # compute exact hydro solution hydro_exact = None # plot hydro solution plotHydroSolutions(mesh, hydro_new, exact=hydro_exact, pickle_dic=data) # plot material and radiation temperatures Tr_exact, Tm_exact = plotTemperatures(mesh, rad_new.E, hydro_states=hydro_new, print_values=True, save=True, filename=test_filename, pickle_dic=data) # plot angular fluxes plotS2Erg(mesh, rad_new.psim, rad_new.psip) #Make a pickle to save the error tables pickname = "results/testJimsShock_M%s_%ielems.pickle" % ( mach_number, n_elems) #Create dictionary of all the data big_dic = {} big_dic["hydro"] = hydro_new big_dic["hydro_exact"] = hydro_exact big_dic["rad"] = rad_new big_dic["Tr_exact"] = Tr_exact big_dic["Tm_exact"] = Tm_exact pickle.dump(big_dic, open(pickname, "w"))
def test_RadHydroMMS(self): # declare symbolic variables x, t, alpha, c = symbols('x t alpha c') #Cycles for time convergence n_cycles = 3 # numeric values alpha_value = 0.01 cv_value = 1.0 gamma_value = 1.4 sig_s = 1.0 sig_a = 1.0 sig_t = sig_s + sig_a # create solution for thermodynamic state and flow field rho = 2. + sin(2 * pi * x - t) u = 2. + cos(2 * pi * x - t) p = 0.5 * (2. + cos(2 * pi * x - t)) e = p / (rho * (gamma_value - 1.)) E = 0.5 * rho * u * u + rho * e rho = sympify('2') * sin(t / 4.) + 2. u = sympify('3') * sin(t / 4.) + 3. E = sympify('10') * sin(t / 4.) + 10. # create solution for radiation field based on solution for F # that is the leading order diffusion limit solution a = GC.RAD_CONSTANT c = GC.SPD_OF_LGT mu = RU.mu["+"] #Equilibrium diffusion solution Er = (2. + cos(2 * pi * x - t)) Fr = (2. + cos(2 * pi * x - t)) * c psip = (Er * c * mu + Fr) / (2. * mu) psim = (Er * c * mu - Fr) / (2. * mu) psip = sympify('10') * c + 1 * sin(t / 4.) psim = sympify('10') * c + 1 * cos(t / 4.) #Form psi+ and psi- from Fr and Er #psip = sympify('5.')*c #psim = sympify('5.')*c # create MMS source functions rho_src, mom_src, E_src, psim_src, psip_src = createMMSSourceFunctionsRadHydro( rho=rho, u=u, E=E, psim=psim, psip=psip, sigma_s_value=sig_s, sigma_a_value=sig_a, gamma_value=gamma_value, cv_value=cv_value, alpha_value=alpha_value, display_equations=True) # create functions for exact solutions substitutions = dict() substitutions['alpha'] = alpha_value substitutions['c'] = GC.SPD_OF_LGT rho = rho.subs(substitutions) u = u.subs(substitutions) mom = rho * u E = E.subs(substitutions) psim = psim.subs(substitutions) psip = psip.subs(substitutions) rho_f = lambdify((symbols('x'), symbols('t')), rho, "numpy") u_f = lambdify((symbols('x'), symbols('t')), u, "numpy") mom_f = lambdify((symbols('x'), symbols('t')), mom, "numpy") E_f = lambdify((symbols('x'), symbols('t')), E, "numpy") psim_f = lambdify((symbols('x'), symbols('t')), psim, "numpy") psip_f = lambdify((symbols('x'), symbols('t')), psip, "numpy") dt_value = 0.0001 dt = [] err = [] #Loop over cycles for time convergence for cycle in range(n_cycles): # create uniform mesh n_elems = 50 width = 1.0 mesh = Mesh(n_elems, width) #Store dt.append(dt_value) # compute radiation IC psi_IC = computeRadiationVector(psim_f, psip_f, mesh, t=0.0) rad_IC = Radiation(psi_IC) # create rad BC object rad_BC = RadBC(mesh, 'periodic') # compute hydro IC hydro_IC = computeAnalyticHydroSolution(mesh, t=0.0, rho=rho_f, u=u_f, E=E_f, cv=cv_value, gamma=gamma_value) # create hydro BC hydro_BC = HydroBC(bc_type='periodic', mesh=mesh) # create cross sections cross_sects = [(ConstantCrossSection(sig_s, sig_s + sig_a), ConstantCrossSection(sig_s, sig_s + sig_a)) for i in xrange(mesh.n_elems)] # transient options t_start = 0.0 t_end = 0.001 # if run standalone, then be verbose if __name__ == '__main__': verbosity = 2 else: verbosity = 0 #slope limiter limiter = 'none' # run the rad-hydro transient rad_new, hydro_new = runNonlinearTransient( mesh=mesh, problem_type='rad_hydro', dt_option='constant', dt_constant=dt_value, slope_limiter=limiter, use_2_cycles=True, t_start=t_start, t_end=t_end, rad_BC=rad_BC, cross_sects=cross_sects, rad_IC=rad_IC, hydro_IC=hydro_IC, hydro_BC=hydro_BC, mom_src=mom_src, E_src=E_src, rho_src=rho_src, psim_src=psim_src, psip_src=psip_src, verbosity=verbosity, rho_f=rho_f, u_f=u_f, E_f=E_f, gamma_value=gamma_value, cv_value=cv_value, check_balance=True) # compute exact hydro solution hydro_exact = computeAnalyticHydroSolution(mesh, t=t_end, rho=rho_f, u=u_f, E=E_f, cv=cv_value, gamma=gamma_value) #Compute error err.append(computeHydroL2Error(hydro_new, hydro_exact)) dt_value /= 2. # compute convergence rates rates = computeHydroConvergenceRates(dt, err) # plot if __name__ == '__main__': # plot radiation solution # compute exact hydro solution hydro_exact = computeAnalyticHydroSolution(mesh, t=t_end, rho=rho_f, u=u_f, E=E_f, cv=cv_value, gamma=gamma_value) # print convergence table if n_cycles > 1: printHydroConvergenceTable(dt, err, rates=rates, dx_desc='dt', err_desc='L2') # plot hydro solution plotHydroSolutions(mesh, hydro_new, x_exact=mesh.getCellCenters(), exact=hydro_exact) #plot exact and our E_r Er_exact_fn = 1. / GC.SPD_OF_LGT * (psim + psip) Fr_exact_fn = (psip - psim) * RU.mu["+"] Er_exact = [] Fr_exact = [] psip_exact = [] psim_exact = [] x = mesh.getCellCenters() for xi in x: substitutions = {'x': xi, 't': t_end} Er_exact.append(Er_exact_fn.subs(substitutions)) Fr_exact.append(Fr_exact_fn.subs(substitutions)) psip_exact.append(psip_f(xi, t_end)) psim_exact.append(psim_f(xi, t_end)) plotRadErg(mesh, rad_new.E, Fr_edge=rad_new.F, exact_Er=Er_exact, exact_Fr=Fr_exact) plotRadErg(mesh, rad_new.psim, rad_new.psip, exact_Er=psip_exact, exact_Fr=psim_exact)