def test_equlibrium_state_vs_chiantipy(natom=8): """ Test equilibrium states saved in EigenData2 and compare them with Outputs from ChiantiPy. Note: This test requires ChiantiPy to be installed (see details in: https://github.com/chianti-atomic/ChiantiPy). """ try: import ChiantiPy.core as ch except ImportError: warnings.warn('ChiantiPy is required in this test.', UserWarning) return temperatures = [1.0e4, 1.0e5, 1.0e6, 1.0e7, 1.0e8] eqi_ch = ch.ioneq(natom) eqi_ch.calculate(temperatures) conce = eqi_ch.Ioneq table_sta = nei.EigenData2(element=natom) for i in range(2): ch_conce = conce[:, i] table_conce = table_sta.equilibrium_state(T_e=temperatures[i]) assert ch_conce.all() == table_conce.all() return
def test_element_range(): """ Function test_element_range: This function is used to test element including Hydrogen to Iron. """ atomic_numb = np.linspace(1, 26, 26, endpoint=True) for i in atomic_numb: element_symbol = atomic.atomic_symbol(int(i)) eigen = nei.EigenData2(element=element_symbol) print(f'Element: ', element_symbol)
def test_reachequlibrium_state_multisteps(natom=8): """ Starting the random initial distribution, the charge states will reach to equilibrium cases after a long time (multiple steps). In this test, we set the ionization and recombination rates at Te0=2.0e6 K and plasma density ne0=1.0e+7. A random charge states distribution will be finally closed to equilibrium distribution at 2.0e6K. """ # # Initial conditions, set plasma temperature, density and dt # element_symbol = atomic.atomic_symbol(int(natom)) te0 = 1.0e+6 # unit: K ne0 = 1.0e+8 # unit: cm^-3 # Start from any ionizaiont states, e.g., Te = 4.0d4 K, time = 0 table = nei.EigenData2(element=natom) f0 = table.equilibrium_state(T_e=4.0e+4) print('START test_reachequlibrium_state_multisteps:') print(f'time_sta = ', time) print(f'INI: ', f0) print(f'Sum(f0) = ', np.sum(f0)) # After time + dt: dt = 100000.0 # unit: second # Enter the time loop: for it in range(100): ft = func_solver_eigenval(natom, te0, ne0, time + dt, f0, table) f0 = np.copy(ft) time = time + dt print(f'time_end = ', time + dt) print(f'NEI:', ft) print(f'Sum(ft) = ', np.sum(ft)) print(f"EI :", table.equilibrium_state(T_e=te0)) print("End Test.\n")
def test_adapt_time_step(natom=26): """ Set a set of Te/ne profiles. Perfrom NEI calculations using adaptive time-step method and compare it with constant dt results. """ # # Set Te and rho profiles # ncase = 1 for icase in range(ncase): data = create_te_ne_profile(icase=icase) time_arr = data["time_arr"] # unit: [s] te_arr = data["te_arr"] # unit: [K] rho_arr = data["ne_arr"] # unit: [cm^-3] # Start from equilibrium ionizaiont(EI) states table = nei.EigenData2(element=natom) f_ini = table.equilibrium_state(T_e=te_arr[0]) # Method 1: Adaptive time-step: newprofile = adaptive_time_step( te_arr, rho_arr, time_arr, table, accuracy_factor=1.0e-3) print(f"Origin sampling points = ", len(te_arr)) dt_min = 10000.0 for i in range(1, newprofile["ntime"]): dt_c = newprofile["time"][i] - newprofile["time"][i - 1] if (dt_c <= dt_min): dt_min = dt_c print(f"Adaptive samplinge points =", newprofile["ntime"]) print( f"Time = {time_arr[-1]}, Te_sta={te_arr[0]}, Te_end={te_arr[-1]}") print(f"EI_start={f_ini}") f0 = np.copy(f_ini) for i in range(1, newprofile["ntime"]): im = i - 1 ic = i time_im = newprofile["time"][im] time_ic = newprofile["time"][ic] # Time step between im and ic dt_mc = math.fabs(time_ic - time_im) # Constant Temperature te_mc = newprofile["te"][im] # Average Densisty ne_mc = newprofile["neavg"][im] # NEI one-step ft = func_solver_eigenval(natom, te_mc, ne_mc, dt_mc, f0, table) f0 = np.copy(ft) f_nei_ada_time = ft print(f"Min_dt= {dt_min}") print(f"NEI(adapt_dt)={f_nei_ada_time}") # Method 2: Constant time-step: f0 = np.copy(f_ini) time_current = 0.0 dt_const = 0.05 while time_current < time_arr[-1]: te_current = np.interp(time_current, time_arr, te_arr) ne_current = 0.5 * ( np.interp(time_current, time_arr, rho_arr) + np.interp( time_current + dt_const, time_arr, rho_arr)) ft = func_solver_eigenval(natom, te_current, ne_current, dt_const, f0, table) f0 = np.copy(ft) time_current = time_current + dt_const stdout.write("\r%f" % time_current) stdout.flush() stdout.write("\n") dt = time_arr[-1] - time_current te_current = np.interp(time_current, time_arr, te_arr) ne_current = np.interp(time_current, time_arr, rho_arr) ft = func_solver_eigenval(natom, te_current, ne_current, dt, f0, table) ft_nei = ft # final results f_ei_end = table.equilibrium_state(T_e=te_arr[-1]) print(f"const_dt = {dt_const}") print(f"NEI(const_dt)={ft_nei}") diff_adp_cdt = (ft_nei - f_nei_ada_time) / np.amax( [ft_nei, f_nei_ada_time]) print(f"Dif_a&c ={diff_adp_cdt}") print(f"EI_end ={f_ei_end}") # # Output results # return 1
def test_nei_multisteps(natom=8): """ Read temprature and density history file and perfrom NEI calculations. Starting the equilibrium states, and set any time-step in here (adaptive time-step is required in practice). """ # # Read Te and rho profiles # file_path = '/Users/chshen/Works/Project/REU/REU_2018/2018_SummerProject/cr1913_traj_180601/' files = sorted(glob.glob(file_path + '*.sav')) for file in files: data = readsav(file, python_dict=True) time = data['time'] # unit: [s] te = data['te'] # unit: [K] rho = data['rho'] # unit: [cm^-3] v = data['v'] # unit: [km/s] r = data['r'] # r position in sphericalcoordinate: [Rolar radio] t = data['t'] # t position in sphericalcoordinate: [0 ~ PI] p = data['p'] # p position in sphericalcoordinate: [0 ~ 2PI] # # NEI calculations parametes: dt and element # dt = 0.1 # 0.1s # Start from equilibrium ionizaiont(EI) states time_current = 0 table = nei.EigenData2(element=natom) f_ini = table.equilibrium_state(T_e=te[0]) print('START:') print(f'time_sta = ', time_current, te[0]) print(f_ini) # Get adaptive time-step newprofile = adaptive_time_step(te, rho, time, table) print(f"Origin points = ", len(te)) dt_min = 10000.0 for i in range(1, newprofile["ntime"]): dt_c = newprofile["time"][i] - newprofile["time"][i - 1] if (dt_c <= dt_min): dt_min = dt_c print(f"Adaptive time-step =", newprofile["ntime"], "min_dt=", dt_min) # Enter the time-advance using the adaptive time-step: f0 = np.copy(f_ini) for i in range(1, newprofile["ntime"]): im = i - 1 ic = i dt_mc = math.fabs(newprofile["time"][ic] - newprofile["time"][im]) te_mc = newprofile["te"][im] ne_mc = 0.5 * (newprofile["ne"][im] + newprofile["ne"][ic]) ft = func_solver_eigenval(natom, te_mc, ne_mc, dt_mc, f0, table) f0 = np.copy(ft) stdout.write("\r%f" % time_current) stdout.flush() stdout.write("\n") f_nei_ada_time = ft print(f"NEI(adt)={f_nei_ada_time}") # Enter the time loop using constant time-step = 0.1s: f0 = np.copy(f_ini) while time_current < time[-1]: # The original time interval is 1.4458s in this test te_current = np.interp(time_current, time, te) ne_current = 0.5 * (np.interp(time_current, time, rho) + np.interp(time_current + dt, time, rho)) ft = func_solver_eigenval(natom, te_current, ne_current, dt, f0, table) f0 = np.copy(ft) time_current = time_current + dt stdout.write("\r%f" % time_current) stdout.flush() stdout.write("\n") # The last step dt = time[-1] - time_current te_current = np.interp(time_current, time, te) ne_current = np.interp(time_current, time, rho) ft = func_solver_eigenval(natom, te_current, ne_current, dt, f0, table) # final results f_ei_end = table.equilibrium_state(T_e=te[-1]) print(f'time_end = ', time_current, te[-1]) print(f"EI :", f_ei_end) print(f"NEI(cdt)={ft}") # # Output results # return 1