def end_conv_steady_cond(plotting=False): print('Testing steady conduction with convection on ends...') # Supply file name file_name = os.getcwd() + '/Inputs/simple_conv.yaml' # Run model model = main_fv.lim1tr_model(file_name) eqn_sys, cond_man, mat_man, grid_man, bc_man, reac_man, data_man, time_opts = model.run_model( ) # Analytical soln T_left = model.parser.cap_dict['Boundary']['Left']['T'] T_right = model.parser.cap_dict['Boundary']['Right']['T'] r_tot = (2. / 100.) + np.sum(grid_man.dx_arr) / mat_man.k_arr[0] q_flux = (T_left - T_right) / r_tot T_o = T_left - q_flux / 100. T_l = T_right + q_flux / 100. T_ans = T_o - (q_flux / mat_man.k_arr[0]) * grid_man.x_node err = np.sum((T_ans - eqn_sys.T_lin)**2) / grid_man.n_tot if plotting: quick_plot(grid_man.x_node, T_ans, eqn_sys.T_lin, err, 'end_conv_steady_cond') if err > 1e-16: print('\tFailed with MSE {:0.2e}\n'.format(err)) return 0 else: print('\tPassed\n') return 1
def end_conv_steady_cond_stack(plotting=False): print('Testing steady conduction through a stack of three materials...') # Supply file name file_name = os.getcwd() + '/Inputs/stack_cond.yaml' # Run model model = main_fv.lim1tr_model(file_name) eqn_sys, cond_man, mat_man, grid_man, bc_man, reac_man, data_man, time_opts = model.run_model( ) # Analytical soln h_left = model.parser.cap_dict['Boundary']['Left']['h'] T_left = model.parser.cap_dict['Boundary']['Left']['T'] T_right = model.parser.cap_dict['Boundary']['Right']['T'] r_tot = 2 * (0.1 / 10.) + 0.1 / 2. + 2. / 10000. q_flux = (T_left - T_right) / r_tot T_b = np.zeros(4) T_b[0] = T_left - q_flux / h_left T_b[1] = T_b[0] - q_flux * 0.1 / 10. T_b[2] = T_b[1] - q_flux * 0.1 / 2. T_b[3] = T_b[2] - q_flux * 0.1 / 10. x_b = np.array([0, 0.1, 0.2, 0.3]) T_ans = np.interp(grid_man.x_node, x_b, T_b) err = np.sum((T_ans - eqn_sys.T_lin)**2) / grid_man.n_tot if plotting: quick_plot(grid_man.x_node, T_ans, eqn_sys.T_lin, err, 'end_conv_steady_cond_stack') if err > 1e-16: print('\tFailed with MSE {:0.2e}\n'.format(err)) return 0 else: print('\tPassed\n') return 1
def deactivate_bcs_test(): # Build model file_name = os.getcwd() + '/Inputs/small_cube.yaml' model = main_fv.lim1tr_model(file_name) # Set steady flux on all BCs flux_bnd = {'Type': 'Heat Flux', 'Flux': 10000., 'Deactivation Time': 5} bnd_dict = { 'External': { 'Type': 'Adiabatic' }, 'Left': flux_bnd, 'Right': flux_bnd } model.parser.cap_dict['Boundary'] = bnd_dict eqn_sys, cond_man, mat_man, grid_man, bc_man, reac_man, data_man, time_opts = model.run_model( ) dT_rate = 2 * 10000 / (0.01 * 2000 * 500) T_true = 300 + dT_rate * 5 err = abs(T_true - eqn_sys.T_lin[0]) if err > 1e-13: print('\tFailed with RMSE {:0.2e}\n'.format(err)) return 0 else: print('\tPassed\n') return 1
def simple_steady_cond_one_block(plotting=False): print('Testing steady dirichlet conduction...') # Supply file name file_name = '{}/Inputs/simple_cond.yaml'.format(os.getcwd()) model = main_fv.lim1tr_model(file_name) test_status = simple_steady_cond_base(model, 'simple_steady_cond_one_block', plotting=plotting) return test_status
def contact_resistance(plotting=False): print( 'Testing steady conduction with through a stack of three materials with contact resistances...' ) # Supply file name file_name = os.getcwd() + '/Inputs/stack_contact.yaml' # Run model model = main_fv.lim1tr_model(file_name) eqn_sys, cond_man, mat_man, grid_man, bc_man, reac_man, data_man, time_opts = model.run_model( ) h_left = model.parser.cap_dict['Boundary']['Left']['h'] h_right = model.parser.cap_dict['Boundary']['Right']['h'] T_left = model.parser.cap_dict['Boundary']['Left']['T'] T_right = model.parser.cap_dict['Boundary']['Right']['T'] # Analytical soln R_1 = 1. / 100. R_2 = 2. / 100. mat_nodes = int(grid_man.x_node.shape[0] / 3.) r_tot = 2 * (0.1 / 10.) + 0.1 / 2. + 1. / h_left + 1. / h_right + R_1 + R_2 q_flux = (T_left - T_right) / r_tot T_1 = T_left - q_flux / h_left T_2 = T_1 - q_flux * 0.1 / 10. T_3 = T_2 - q_flux * R_1 T_4 = T_3 - q_flux * 0.1 / 2. T_5 = T_4 - q_flux * R_2 T_6 = T_5 - q_flux * 0.1 / 10. T_ans = np.zeros(grid_man.x_node.shape[0]) T_ans[:mat_nodes] = grid_man.x_node[:mat_nodes] * (T_2 - T_1) / 0.1 + T_1 T_ans[mat_nodes:2 * mat_nodes] = (grid_man.x_node[mat_nodes:2 * mat_nodes] - 0.1) * (T_4 - T_3) / 0.1 + T_3 T_ans[2 * mat_nodes:] = (grid_man.x_node[2 * mat_nodes:] - 0.2) * (T_6 - T_5) / 0.1 + T_5 err = np.sum((T_ans - eqn_sys.T_lin)**2) / grid_man.n_tot if plotting: quick_plot(grid_man.x_node, T_ans, eqn_sys.T_lin, err, 'end_conv_steady_contact_stack', raw_diff=False) if err > 1e-1: print('\tFailed with MSE {:0.2e}\n'.format(err)) return 0 else: print('\tPassed\n') return 1
def trans_end_conv(file_name, plotting=False): # Run model model = main_fv.lim1tr_model(file_name) eqn_sys, cond_man, mat_man, grid_man, bc_man, reac_man, data_man, time_opts = model.run_model( ) # Fourier number L = np.sum(grid_man.dx_arr) * 0.5 my_t = time_opts['Run Time'] my_mat = mat_man.get_material('A') alpha = my_mat.k / (my_mat.rho * my_mat.cp) Fo = alpha * my_t / L**2 # Analytical soln (Incropera 6th edition, p. 273) zeta_n = [1.3138, 4.0336, 6.9096, 9.8928] # First four roots of the transcendental eqn with Bi = 5 half_nodes = int(grid_man.n_tot * 0.5) x_star = (np.arange(half_nodes) + 0.5) / half_nodes T_right = model.parser.cap_dict['Boundary']['Right']['T'] theta = np.zeros(half_nodes) for i in range(4): C_n = 4. * np.sin( zeta_n[i]) / (2. * zeta_n[i] + np.sin(2. * zeta_n[i])) theta += C_n * np.exp(-zeta_n[i]**2 * Fo) * np.cos(zeta_n[i] * x_star) T_ans = T_right + theta * (np.mean(time_opts['T Initial']) - T_right) # Calculate error err = np.sqrt(np.sum((T_ans - eqn_sys.T_lin[half_nodes:])**2) / half_nodes) if plotting: is_split = '' if 'split' in file_name: is_split = '_split' plt.figure() plt.plot(L * (1. + x_star), T_ans, 'o', label='Analytical') plt.plot(grid_man.x_node, eqn_sys.T_lin, '-', label='Numerical') plt.ylim([370, 470]) plt.xlabel(r'Postion ($m$)') plt.ylabel(r'Temperature ($K$)') plt.legend() plt.title('RMSE = {:.2E}'.format(err)) plt.savefig('./Figures/trans_end_conv_order_{}{}.png'.format( time_opts['Order'], is_split), bbox_inches='tight') plt.close() if err > 2e-2: print('\tFailed with RMSE {:0.2e}\n'.format(err)) return 0 else: print('\tPassed\n') return 1
def simple_steady_cond_two_blocks_right_cv(plotting=False): print('Testing steady dirichlet conduction...') # Supply file name file_name = '{}/Inputs/simple_cond.yaml'.format(os.getcwd()) model = main_fv.lim1tr_model(file_name) model.parser.cap_dict['Domain Table'] = { 'Material Name': ['A', 'A'], 'Thickness': [0.099, 0.001], 'dx': [0.001, 0.001] } test_status = simple_steady_cond_base( model, 'simple_steady_cond_two_blocks_right_cv', plotting=plotting) return test_status
def trans_end_flux_cn(plotting=False): print('Testing second-order transient end flux...') # Run model file_name = os.getcwd() + '/Inputs/trans_end_flux_cn.yaml' model = main_fv.lim1tr_model(file_name) eqn_sys, cond_man, mat_man, grid_man, bc_man, reac_man, data_man, time_opts = model.run_model( ) # Save a few numbers L = np.sum(grid_man.dx_arr) * 0.5 my_t = time_opts['Run Time'] my_mat = mat_man.get_material('A') alpha = my_mat.k / (my_mat.rho * my_mat.cp) q_in = model.parser.cap_dict['Boundary']['Left']['Flux'] # Analytical soln (Incropera 6th edition, p. 286) c_one = (2 * q_in / my_mat.k) * np.sqrt(alpha * my_t / np.pi) c_two = np.exp(-1. * grid_man.x_node**2 / (4 * alpha * my_t)) c_three = q_in * grid_man.x_node / my_mat.k c_four = sp.special.erfc(grid_man.x_node * 0.5 / np.sqrt(alpha * my_t)) T_ans = np.mean(time_opts['T Initial']) + c_one * c_two - c_three * c_four # Calculate error err = np.sqrt(np.sum((T_ans - eqn_sys.T_lin)**2) / grid_man.n_tot) if plotting: is_split = '' if 'split' in file_name: is_split = '_split' plt.figure() plt.plot(grid_man.x_node, T_ans, 'o', label='Analytical') plt.plot(grid_man.x_node, eqn_sys.T_lin, '-', label='Numerical') plt.xlabel(r'Postion ($m$)') plt.ylabel(r'Temperature ($K$)') plt.legend() plt.title('RMSE = {:.2E}'.format(err)) plt.savefig('./Figures/trans_end_flux_cn.png', bbox_inches='tight') plt.close() if err > 2e-4: print('\tFailed with RMSE {:0.2e}\n'.format(err)) return 0 else: print('\tPassed\n') return 1
def trans_ext_conv(file_name, e_tol): # Run model model = main_fv.lim1tr_model(file_name) eqn_sys, cond_man, mat_man, grid_man, bc_man, reac_man, data_man, time_opts = model.run_model( ) my_t = time_opts['Run Time'] my_mat = mat_man.get_material('A') h_ext = model.parser.cap_dict['Boundary']['External']['h'] T_ext = model.parser.cap_dict['Boundary']['External']['T'] C_o = h_ext * bc_man.PA_r / (my_mat.rho * my_mat.cp) T_ans = T_ext + (np.mean(time_opts['T Initial']) - T_ext) * np.exp( -1.0 * C_o * my_t) err = np.max(np.abs(eqn_sys.T_lin - T_ans)) if err > e_tol: print('\tFailed with RMSE {:0.2e}\n'.format(err)) return 0 else: print('\tPassed\n') return 1
def exterior_steady_cond(plotting=False): print( 'Testing steady dirichlet conduction with a convection source at each node...' ) # Supply file name file_name = os.getcwd() + '/Inputs/simple_fin.yaml' # Run model model = main_fv.lim1tr_model(file_name) eqn_sys, cond_man, mat_man, grid_man, bc_man, reac_man, data_man, time_opts = model.run_model( ) h_left = model.parser.cap_dict['Boundary']['Left']['h'] T_left = model.parser.cap_dict['Boundary']['Left']['T'] h_ext = model.parser.cap_dict['Boundary']['External']['h'] T_ext = model.parser.cap_dict['Boundary']['External']['T'] # Analytical soln (Incropera 6th edition, p. 144) dy = 0.2 dz = 0.1 P = 2 * (dy + dz) A_c = dy * dz L_x = np.sum(grid_man.dx_arr) C_m = np.sqrt(h_ext * bc_man.PA_r / mat_man.k_arr[0]) s_grid = grid_man.x_node C_1 = 1. / ((1. + np.exp(C_m * L_x)) - (mat_man.k_arr[0] * C_m / h_left) * (1. - np.exp(C_m * L_x))) T_ans = T_ext + (T_left - T_ext) * C_1 * (np.exp(C_m * s_grid) + np.exp(C_m * (L_x - s_grid))) err = np.sum((T_ans - eqn_sys.T_lin)**2) / grid_man.n_tot if plotting: quick_plot(grid_man.x_node, T_ans, eqn_sys.T_lin, err, 'exterior_steady_cond') if err > 2e-5: print('\tFailed with MSE {:0.2e}\n'.format(err)) return 0 else: print('\tPassed\n') return 1
def short_rxn_CoO2(): '''Check the short reaction evaluation at a given state for CoO2 limiting ''' print('Testing short circuit reaction with CoO2 limiting...') # Run Model model = main_fv.lim1tr_model('./Inputs/short_only.yaml') model.parser.cap_dict['Species']['Initial Mass Fraction'][0] = 0.16 model.parser.cap_dict['Species']['Initial Mass Fraction'][1] = 0.13 eqn_sys, cond_man, mat_man, grid_man, bc_man, reac_man, data_man, time_opts = model.run_model() # Compute solution voltage = 4.2 short_resistance = 0.001 volume = 4.8e-5 charge_kmol = 1000*6.022e23*1.6023e-19 kg_reactants = 79.007 + 90.931 Y_o = model.parser.cap_dict['Species']['Initial Mass Fraction'] rho_CoO2_o = 2000*Y_o[1] t_arr = np.linspace(0, 4, 41) dT_dt = voltage**2/(short_resistance*volume*2000*800) rate = voltage*kg_reactants/(short_resistance*charge_kmol*volume) rho_CoO2 = rho_CoO2_o - rate*t_arr*(90.931/(79.007 + 90.931)) T_ans = 298.15 + dT_dt*t_arr t_complete = rho_CoO2_o/(rate*90.931/(79.007 + 90.931)) T_f = 298.15 + dT_dt*t_complete for i in range(t_arr.shape[0]): if rho_CoO2[i] < 0: rho_CoO2[i] = 0 T_ans[i] = T_f err = np.sqrt(np.mean((rho_CoO2 - data_man.data_dict['CoO2'][:,0])**2)) err += np.sqrt(np.mean((T_ans - data_man.data_dict['Temperature'][:,0])**2)) if err > 1e-7: print('\tFailed with RMSE {:0.2e}\n'.format(err)) return 0 else: print('\tPassed\n') return 1
def left_conv_right_flux(plotting=False): print( 'Testing steady conduction with through a stack of three materials with contact resistances...' ) # Supply file name file_name = os.getcwd() + '/Inputs/left_conv_right_flux.yaml' # Run model model = main_fv.lim1tr_model(file_name) eqn_sys, cond_man, mat_man, grid_man, bc_man, reac_man, data_man, time_opts = model.run_model( ) h_left = model.parser.cap_dict['Boundary']['Left']['h'] T_left = model.parser.cap_dict['Boundary']['Left']['T'] flux_right = model.parser.cap_dict['Boundary']['Right']['Flux'] # Analytical soln L_x = np.sum(grid_man.dx_arr) T_l = T_left + flux_right / h_left T_r = T_l + flux_right * L_x / mat_man.k_arr[0] T_ans = T_l + grid_man.x_node * (T_r - T_l) / L_x err = np.sum((T_ans - eqn_sys.T_lin)**2) / grid_man.n_tot if plotting: quick_plot(grid_man.x_node, T_ans, eqn_sys.T_lin, err, 'left_conv_right_flux', raw_diff=False) if err > 1e-12: print('\tFailed with MSE {:0.2e}\n'.format(err)) return 0 else: print('\tPassed\n') return 1