diff --git a/HW1/Images/Case 1.PNG b/HW1/Images/Case 1.PNG new file mode 100644 index 0000000..55b6de9 Binary files /dev/null and b/HW1/Images/Case 1.PNG differ diff --git a/HW1/Images/Case 2.PNG b/HW1/Images/Case 2.PNG new file mode 100644 index 0000000..b27e950 Binary files /dev/null and b/HW1/Images/Case 2.PNG differ diff --git a/HW1/Images/prob1_case1_analytical_temperature_vs_position.png b/HW1/Images/prob1_case1_analytical_temperature_vs_position.png new file mode 100644 index 0000000..3b6dc63 Binary files /dev/null and b/HW1/Images/prob1_case1_analytical_temperature_vs_position.png differ diff --git a/HW1/Images/prob1_case2_analytical_temperature_vs_position.png b/HW1/Images/prob1_case2_analytical_temperature_vs_position.png new file mode 100644 index 0000000..1c310a3 Binary files /dev/null and b/HW1/Images/prob1_case2_analytical_temperature_vs_position.png differ diff --git a/HW1/Images/prob1_comparison_cases.png b/HW1/Images/prob1_comparison_cases.png new file mode 100644 index 0000000..8c805d3 Binary files /dev/null and b/HW1/Images/prob1_comparison_cases.png differ diff --git a/HW1/Images/prob1_heat_flux_comparison.png b/HW1/Images/prob1_heat_flux_comparison.png new file mode 100644 index 0000000..1290cd0 Binary files /dev/null and b/HW1/Images/prob1_heat_flux_comparison.png differ diff --git a/HW1/Images/prob2_case1_fdm_temperature_vs_position.png b/HW1/Images/prob2_case1_fdm_temperature_vs_position.png new file mode 100644 index 0000000..2e63500 Binary files /dev/null and b/HW1/Images/prob2_case1_fdm_temperature_vs_position.png differ diff --git a/HW1/Images/prob2_case1_heat_flux.png b/HW1/Images/prob2_case1_heat_flux.png new file mode 100644 index 0000000..7513547 Binary files /dev/null and b/HW1/Images/prob2_case1_heat_flux.png differ diff --git a/HW1/Images/prob2_case2_fdm_temperature_vs_position.png b/HW1/Images/prob2_case2_fdm_temperature_vs_position.png new file mode 100644 index 0000000..ba807f6 Binary files /dev/null and b/HW1/Images/prob2_case2_fdm_temperature_vs_position.png differ diff --git a/HW1/Images/prob2_case2_heat_flux.png b/HW1/Images/prob2_case2_heat_flux.png new file mode 100644 index 0000000..d666fee Binary files /dev/null and b/HW1/Images/prob2_case2_heat_flux.png differ diff --git a/HW1/Images/prob2_comparison_cases.png b/HW1/Images/prob2_comparison_cases.png new file mode 100644 index 0000000..811ac16 Binary files /dev/null and b/HW1/Images/prob2_comparison_cases.png differ diff --git a/HW1/Images/prob3_case1_convergence.png b/HW1/Images/prob3_case1_convergence.png new file mode 100644 index 0000000..0efeacc Binary files /dev/null and b/HW1/Images/prob3_case1_convergence.png differ diff --git a/HW1/Images/prob3_case2_convergence.png b/HW1/Images/prob3_case2_convergence.png new file mode 100644 index 0000000..48bd9f9 Binary files /dev/null and b/HW1/Images/prob3_case2_convergence.png differ diff --git a/HW1/Judson_Upchurch_HW1.pdf b/HW1/Judson_Upchurch_HW1.pdf new file mode 100644 index 0000000..249ea2b Binary files /dev/null and b/HW1/Judson_Upchurch_HW1.pdf differ diff --git a/HW1/__pycache__/case1.cpython-312.pyc b/HW1/__pycache__/case1.cpython-312.pyc new file mode 100644 index 0000000..6e5b3e5 Binary files /dev/null and b/HW1/__pycache__/case1.cpython-312.pyc differ diff --git a/HW1/__pycache__/case2.cpython-312.pyc b/HW1/__pycache__/case2.cpython-312.pyc new file mode 100644 index 0000000..a57db07 Binary files /dev/null and b/HW1/__pycache__/case2.cpython-312.pyc differ diff --git a/HW1/__pycache__/common.cpython-312.pyc b/HW1/__pycache__/common.cpython-312.pyc new file mode 100644 index 0000000..f6cd51a Binary files /dev/null and b/HW1/__pycache__/common.cpython-312.pyc differ diff --git a/HW1/case1.py b/HW1/case1.py new file mode 100644 index 0000000..f44523d --- /dev/null +++ b/HW1/case1.py @@ -0,0 +1,32 @@ +# case1.py + +import numpy as np + +k = 0.5 # W / (cm K) +area = np.pi / 100 # cm^2 + +def analytical(a, x): + return 100 * np.sinh(a*x) / np.sinh(a) + +def analytical_heat_loss(a): + return -100*k*area*a/np.tanh(a) + +def fdm_array(n, a = 2.75): + dx = 1 / n + kap = 2 + ((a**2)*(dx**2)) + + left_FDM_array = np.zeros((n-1, n-1)) + left_FDM_array[0][0:2] = [kap, -1] + row_FDM = [-1, kap, -1] + + for i in range(1, n-2): + left_FDM_array[i][i-1:i+2] = row_FDM + + left_FDM_array[n-2][n-3:n-1] = [-1, kap] + + return left_FDM_array + +def right_array(n): + array = [0 for _ in range(n-2)] + array.append(100) + return array \ No newline at end of file diff --git a/HW1/case2.py b/HW1/case2.py new file mode 100644 index 0000000..2ed2bde --- /dev/null +++ b/HW1/case2.py @@ -0,0 +1,33 @@ +# case2.py + +import numpy as np + +k = 0.5 # W / (cm K) +area = np.pi / 100 # cm^2 + +def analytical(a, x): + return 100 * np.cosh(a*x) / np.cosh(a) + +def analytical_heat_loss(a): + return -100*k*area*a*np.tanh(a) + +def fdm_array(n, a = 2.75): + dx = 1/ n + kap = 2 + ((a**2)*(dx**2)) + kap_prime = (kap/2) + + left_FDM_array = np.zeros((n, n)) + left_FDM_array[0][0:2] = [kap_prime, -1] + row_FDM = [-1, kap, -1] + + for i in range(1, n-1): + left_FDM_array[i][i-1:i+2] = row_FDM + + left_FDM_array[n-1][n-2:n] = [-1, kap] + + return left_FDM_array + +def right_array(n): + array = [0 for _ in range(n-1)] + array.append(100) + return array \ No newline at end of file diff --git a/HW1/common.py b/HW1/common.py new file mode 100644 index 0000000..9f0ac41 --- /dev/null +++ b/HW1/common.py @@ -0,0 +1,20 @@ +# common.py + +import numpy as np + + +k = 0.5 # W / (cm K) +area = np.pi / 100 # cm^2 + + +def taylor_extraction(t_0, t_1, dx, a=0, order=1): + if order == 1: + return -1 * k * area * (t_1 - t_0) / dx + elif order == 2: + return -1 * k * area * (((t_1 - t_0) / dx) + (a**2 * dx * t_1 / 2)) + +def calc_error(q_exact, q_1): + return np.abs((q_exact - q_1) / q_exact) + +def calc_beta(q_exact, q_1, q_2, dx_1, dx_2): + return np.log(np.abs((q_exact - q_1)/(q_exact - q_2))) / np.log(dx_1 / dx_2) \ No newline at end of file diff --git a/HW1/main.py b/HW1/main.py new file mode 100644 index 0000000..6742f58 --- /dev/null +++ b/HW1/main.py @@ -0,0 +1,535 @@ +# main.py + +import numpy as np +import pandas as pd +import matplotlib.pyplot as plt + +import case1 +import case2 +import common + +data_dict = {} +data_dict["a_values"] = np.array([0.29, 0.5, 1.35, 2.75, 4.75, 9.15]) + +def prob1(): + '''Analytical solutions''' + print("Problem 1") + # Problem 1 - Analytical solution + data_dict["prob1"] = {} + data_dict["prob1"]["x_values"] = np.array([0, 0.125, 0.25, 0.375, 0.5, 0.625, 0.75, 0.875, 1.0]) + data_dict["prob1"]["x_values_fine"] = np.linspace(0, 1) + + # Case 1 temperature calculations + results = [] + results_fine = [] + for a_value in data_dict["a_values"]: + result = case1.analytical(a=a_value, x=data_dict["prob1"]["x_values"]) + result_fine = case1.analytical(a=a_value, x=data_dict["prob1"]["x_values_fine"]) + results.append(result) + results_fine.append(result_fine) + + data_dict["prob1"]["case1_temp_results"] = np.array(results_fine) + + df_case1 = pd.DataFrame(results, index=[f'a = {a}' for a in data_dict["a_values"]], columns=[f'x = {x:.3f}' for x in data_dict["prob1"]["x_values"]]) + + # Pretty print DataFrame for Case 1 temperature + print("Analytical Case 1 Temperature Results:") + print(df_case1) + print("\n" * 2) + + # Plotting Case 1 temperature + plt.figure(figsize=(10, 6)) + for idx, a_value in enumerate(data_dict["a_values"]): + plt.plot(data_dict["prob1"]["x_values_fine"], data_dict["prob1"]["case1_temp_results"][idx], label=f'α = {a_value}') + plt.xlabel('Position (cm)') + plt.ylabel('Temperature (°C)') + plt.legend() + plt.grid(True) + plt.savefig('prob1_case1_analytical_temperature_vs_position.png', dpi=300) + #plt.show() + plt.close() + + # Case 2 temperature calculations + results = [] + results_fine = [] + for a_value in data_dict["a_values"]: + result = case2.analytical(a=a_value, x=data_dict["prob1"]["x_values"]) + result_fine = case2.analytical(a=a_value, x=data_dict["prob1"]["x_values_fine"]) + results.append(result) + results_fine.append(result_fine) + + data_dict["prob1"]["case2_temp_results"] = np.array(results_fine) + + df_case2 = pd.DataFrame(results, index=[f'a = {a}' for a in data_dict["a_values"]], columns=[f'x = {x:.3f}' for x in data_dict["prob1"]["x_values"]]) + + # Pretty print DataFrame for Case 2 + print("Analytical Case 2 Temperature Results:") + print(df_case2) + print("\n" * 2) + + # Plotting Case 2 + plt.figure(figsize=(10, 6)) + for idx, a_value in enumerate(data_dict["a_values"]): + plt.plot(data_dict["prob1"]["x_values_fine"], data_dict["prob1"]["case2_temp_results"][idx], label=f'α = {a_value}') + plt.xlabel('Position (cm)') + plt.ylabel('Temperature (°C)') + plt.legend() + plt.grid(True) + plt.savefig('prob1_case2_analytical_temperature_vs_position.png', dpi=300) + #plt.show() + plt.close() + + # Comparison plots between cases for temperature distribution + fig, axes = plt.subplots(3, 2, figsize=(12, 12), sharex=True, sharey=True) + + for idx, a_value in enumerate(data_dict["a_values"]): + ax = axes[idx // 2, idx % 2] + ax.plot(data_dict["prob1"]["x_values_fine"], data_dict["prob1"]["case1_temp_results"][idx], label='Case 1') + ax.plot(data_dict["prob1"]["x_values_fine"], data_dict["prob1"]["case2_temp_results"][idx], label='Case 2') + ax.set_title(f'α = {a_value}') + ax.set_xlabel('Position (cm)') + ax.set_ylabel('Temperature (°C)') + ax.legend() + ax.grid(True) + + plt.tight_layout(rect=[0, 0, 1, 0.95]) # Adjust layout to make room for the main title + plt.savefig('prob1_comparison_cases.png', dpi=300) + #plt.show() + plt.close() + + # Case 1 heat flux calculations + results = [] + for a_value in data_dict["a_values"]: + result = case1.analytical_heat_loss(a=a_value) + results.append(result) + + data_dict["prob1"]["case1_heat_flux_results"] = np.array(results) + + # Create a DataFrame with alpha as the index and heat flux as the data + df_case1_heat_flux = pd.DataFrame(results, index=[f'a = {a}' for a in data_dict["a_values"]], columns=['Heat Flux']) + + # Pretty print DataFrame for Case 1 heat flux + print("Analytical Case 1 Heat Flux Results:") + print(df_case1_heat_flux) + print("\n" * 2) + + # Case 2 heat flux calculations + results = [] + for a_value in data_dict["a_values"]: + result = case2.analytical_heat_loss(a=a_value) + results.append(result) + + data_dict["prob1"]["case2_heat_flux_results"] = np.array(results) + + # Create a DataFrame with alpha as the index and heat flux as the data + df_case2_heat_flux = pd.DataFrame(results, index=[f'a = {a}' for a in data_dict["a_values"]], columns=['Heat Flux']) + + # Pretty print DataFrame for Case 2 heat flux + print("Analytical Case 2 Heat Flux Results:") + print(df_case2_heat_flux) + print("\n" * 2) + + # Plotting heat flux vs alpha for both cases + plt.figure(figsize=(10, 6)) + plt.plot(data_dict["a_values"], data_dict["prob1"]["case1_heat_flux_results"], label='Case 1') + plt.plot(data_dict["a_values"], data_dict["prob1"]["case2_heat_flux_results"], label='Case 2') + plt.xlabel('Alpha ($cm^{-1}$)') + plt.ylabel('Heat Flux (W)') + plt.legend() + plt.grid(True) + plt.savefig('prob1_heat_flux_comparison.png', dpi=300) + #plt.show() + plt.close() + +def prob2(): + '''FDM with dx = 0.125 and alpha varying''' + print("Problem 2") + data_dict["prob2"] = {} + data_dict["prob2"]["num_point"] = 8 # This does not consider the final T(L) point. So actually we have 9 points + data_dict["prob2"]["dx"] = 0.125 + + # Case 1 + results = [] + # num_point does not consider T(L). So "4" points is T0, T1, T2, T3, and then we add back T(L) + for a_value in data_dict["a_values"]: + fdm_array = case1.fdm_array(data_dict["prob2"]["num_point"], a = a_value) + fdm_array_inverse = np.linalg.inv(fdm_array) + + right_array = case1.right_array(data_dict["prob2"]["num_point"]) + + unkown_temps_array = fdm_array_inverse @ right_array + solution = [0] # First point is 0 from BC + solution[1:] = unkown_temps_array + solution.append(100) # T(L) BC + + results.append(solution) + + data_dict["prob2"]["case1"] = {} + data_dict["prob2"]["case1"]["temp_results"] = np.array(results) + + data_dict["prob2"]["x_values"] = np.array([0, 0.125, 0.25, 0.375, 0.5, 0.625, 0.75, 0.875, 1.0]) + df_case1 = pd.DataFrame(results, index=[f'a = {a}' for a in data_dict["a_values"]], columns=[f'x = {x:.3f}' for x in data_dict["prob2"]["x_values"]]) + + # Pretty print DataFrame for Case 1 temperature + print("FDM Case 1 Temperature Results:") + print(df_case1) + print("\n" * 2) + + # Plotting Case 1 temperature + plt.figure(figsize=(10, 6)) + for idx, a_value in enumerate(data_dict["a_values"]): + plt.plot(data_dict["prob2"]["x_values"], data_dict["prob2"]["case1"]["temp_results"][idx], label=f'α = {a_value}') + plt.xlabel('Position (cm)') + plt.ylabel('Temperature (°C)') + plt.legend() + plt.grid(True) + plt.savefig('prob2_case1_fdm_temperature_vs_position.png', dpi=300) + #plt.show() + plt.close() + + # Case 2 + results = [] + # num_point does not consider T(L). So "4" points is T0, T1, T2, T3, and then we add back T(L) + for a_value in data_dict["a_values"]: + fdm_array = case2.fdm_array(data_dict["prob2"]["num_point"], a = a_value) + fdm_array_inverse = np.linalg.inv(fdm_array) + + right_array = case2.right_array(data_dict["prob2"]["num_point"]) + + unkown_temps_array = fdm_array_inverse @ right_array + + solution = unkown_temps_array.tolist() + solution.append(100) # T(L) BC + + results.append(solution) + + data_dict["prob2"]["case2"] = {} + data_dict["prob2"]["case2"]["temp_results"] = np.array(results) + + data_dict["prob2"]["x_values"] = np.array([0, 0.125, 0.25, 0.375, 0.5, 0.625, 0.75, 0.875, 1.0]) + df_case2 = pd.DataFrame(results, index=[f'a = {a}' for a in data_dict["a_values"]], columns=[f'x = {x:.3f}' for x in data_dict["prob2"]["x_values"]]) + + # Pretty print DataFrame for Case 2 temperature + print("FDM Case 2 Temperature Results:") + print(df_case2) + print("\n" * 2) + + # Plotting Case 2 temperature + plt.figure(figsize=(10, 6)) + for idx, a_value in enumerate(data_dict["a_values"]): + plt.plot(data_dict["prob2"]["x_values"], data_dict["prob2"]["case2"]["temp_results"][idx], label=f'α = {a_value}') + plt.xlabel('Position (cm)') + plt.ylabel('Temperature (°C)') + plt.legend() + plt.grid(True) + plt.savefig('prob2_case2_fdm_temperature_vs_position.png', dpi=300) + #plt.show() + plt.close() + + + # Plot the comparisons similar to problem 1 + # Comparison plots between cases for temperature distribution + fig, axes = plt.subplots(3, 2, figsize=(12, 12), sharex=True, sharey=True) + + for idx, a_value in enumerate(data_dict["a_values"]): + ax = axes[idx // 2, idx % 2] + ax.plot(data_dict["prob2"]["x_values"], data_dict["prob2"]["case1"]["temp_results"][idx], label='Case 1') + ax.plot(data_dict["prob2"]["x_values"], data_dict["prob2"]["case2"]["temp_results"][idx], label='Case 2') + ax.set_title(f'α = {a_value}') + ax.set_xlabel('Position (cm)') + ax.set_ylabel('Temperature (°C)') + ax.legend() + ax.grid(True) + + plt.tight_layout(rect=[0, 0, 1, 0.95]) # Adjust layout to make room for the main title + plt.savefig('prob2_comparison_cases.png', dpi=300) + #plt.show() + plt.close() + + + + # Heat flux extraction + # Case 1 + results = [] + for i in range(len(data_dict["a_values"])): + a = data_dict["a_values"][i] + (t_0, t_1) = data_dict["prob2"]["case1"]["temp_results"][i][-2:] + dx = data_dict["prob2"]["dx"] + first_order = common.taylor_extraction(t_0, t_1, dx, a, 1) + second_order = common.taylor_extraction(t_0, t_1, dx, a, 2) + results.append([first_order, second_order]) + + data_dict["prob2"]["case1"]["heat_results"] = np.array(results) + + # Create a DataFrame with alpha as the index and heat flux as the data + df_case1_heat_flux = pd.DataFrame(results, index=[f'a = {a}' for a in data_dict["a_values"]], columns=['1st Order', '2nd Order']) + + # Pretty print DataFrame for Case 1 heat flux + print("FDM Case 1 Heat Flux Results:") + print(df_case1_heat_flux) + print("\n" * 2) + + # Plotting heat flux vs alpha for both extractions + plt.figure(figsize=(10, 6)) + plt.plot(data_dict["a_values"], [i[0] for i in data_dict["prob2"]["case1"]["heat_results"]], label='1st Order Extraction') + plt.plot(data_dict["a_values"], [i[1] for i in data_dict["prob2"]["case1"]["heat_results"]], label='2nd Order Extraction') + plt.xlabel('Alpha ($cm^{-1}$)') + plt.ylabel('Heat Flux (W)') + plt.legend() + plt.grid(True) + plt.savefig('prob2_case1_heat_flux.png', dpi=300) + #plt.show() + plt.close() + + + + # Case 2 + results = [] + for i in range(len(data_dict["a_values"])): + a = data_dict["a_values"][i] + (t_0, t_1) = data_dict["prob2"]["case2"]["temp_results"][i][-2:] + dx = data_dict["prob2"]["dx"] + first_order = common.taylor_extraction(t_0, t_1, dx, a, 1) + second_order = common.taylor_extraction(t_0, t_1, dx, a, 2) + results.append([first_order, second_order]) + + data_dict["prob2"]["case2"]["heat_results"] = np.array(results) + + # Create a DataFrame with alpha as the index and heat flux as the data + df_case2_heat_flux = pd.DataFrame(results, index=[f'a = {a}' for a in data_dict["a_values"]], columns=['1st Order', '2nd Order']) + + # Pretty print DataFrame for Case 1 heat flux + print("FDM Case 2 Heat Flux Results:") + print(df_case2_heat_flux) + print("\n" * 2) + + # Plotting heat flux vs alpha for both extractions + plt.figure(figsize=(10, 6)) + plt.plot(data_dict["a_values"], [i[0] for i in data_dict["prob2"]["case2"]["heat_results"]], label='1st Order Extraction') + plt.plot(data_dict["a_values"], [i[1] for i in data_dict["prob2"]["case2"]["heat_results"]], label='2nd Order Extraction') + plt.xlabel('Alpha ($cm^{-1}$)') + plt.ylabel('Heat Flux (W)') + plt.legend() + plt.grid(True) + plt.savefig('prob2_case2_heat_flux.png', dpi=300) + #plt.show() + plt.close() + +def prob3(): + '''Convergence analysis of the cases''' + print("Problem 3") + data_dict["prob3"] = {} + data_dict["prob3"]["num_points"] = [2**i for i in range(2, 8)] # This does not consider the final T(L) point. So actually we have n + 1 points + data_dict["prob3"]["dx_values"] = [1 / i for i in data_dict["prob3"]["num_points"]] + + # Case 1 + data_dict["prob3"]["case1"] = {} + data_dict["prob3"]["case1"]["temp_results"] = [] + # num_point does not consider T(L). So "4" points is T0, T1, T2, T3, and then we add back T(L) + for num_point in data_dict["prob3"]["num_points"]: + fdm_array = case1.fdm_array(num_point) + fdm_array_inverse = np.linalg.inv(fdm_array) + + right_array = case1.right_array(num_point) + + unkown_temps_array = fdm_array_inverse @ right_array + solution = [0] # First point is 0 from BC + solution[1:] = unkown_temps_array + solution.append(100) # T(L) BC + + data_dict["prob3"]["case1"]["temp_results"].append(solution) + + #data_dict["prob3"]["x_values_fine"] = np.linspace(0, 1) + #data_dict["prob3"]["case1"]["true_temp_results"] = case1.analytical(a=2.75, x=data_dict["prob3"]["x_values_fine"]) + + # We have all of the temperature results for varying dx + # For each dx, calculate the 1st and 2nd order heat flux + results = [] + for i in range(len(data_dict["prob3"]["dx_values"])): + a = 2.75 + dx = data_dict["prob3"]["dx_values"][i] + (t_0, t_1) = data_dict["prob3"]["case1"]["temp_results"][i][-2:] + + first_order = common.taylor_extraction(t_0, t_1, dx, a, 1) + second_order = common.taylor_extraction(t_0, t_1, dx, a, 2) + results.append([first_order, second_order]) + + data_dict["prob3"]["case1"]["heat_results"] = np.array(results) + + data_dict["prob3"]["case1"]["heat_results_true"] = case1.analytical_heat_loss(a=2.75) + + # Calculate % error and beta values + errors = [] + betas = [] + q_exact = data_dict["prob3"]["case1"]["heat_results_true"] + for i in range(0, len(results)): + + # % Error calculation + q_1_curr, q_2_curr = results[i] + first_order_error = common.calc_error(q_exact, q_1_curr) + second_order_error = common.calc_error(q_exact, q_2_curr) + + # Beta (convergence rate) calculation + if i != 0: + q_1_prev, q_2_prev = results[i-1] + dx_1 = data_dict["prob3"]["dx_values"][i-1] + dx_2 = data_dict["prob3"]["dx_values"][i] + first_order_beta = common.calc_beta(q_exact, q_1_curr, q_1_prev, dx_2, dx_1) + second_order_beta = common.calc_beta(q_exact, q_2_curr, q_2_prev, dx_2, dx_1) + else: + first_order_beta = 0 + second_order_beta = 0 + + errors.append([first_order_error, second_order_error]) + betas.append([first_order_beta, second_order_beta]) + + data_dict["prob3"]["case1"]["errors"] = errors + data_dict["prob3"]["case1"]["betas"] = betas + + # Combine dx values, results, errors, and betas into a DataFrame for display + table_data = [] + + for i in range(len(data_dict["prob3"]["dx_values"])): + table_data.append([ + results[i][0], # 1st order result + results[i][1], # 2nd order result + data_dict["prob3"]["case1"]["heat_results_true"], # True Q + errors[i][0], # 1st order % error + errors[i][1], # 2nd order % error + betas[i][0], # 1st order beta + betas[i][1] # 2nd order beta + ]) + + columns = ['1st Q', '2nd Q', 'True Q', '1st % Error', '2nd % Error', '1st β', '2nd β'] + df_case1 = pd.DataFrame(table_data, index=[f'dx = {i}' for i in data_dict["prob3"]["dx_values"]], columns=columns) + + print("FDM Case 1 Heat Flux Convergence Results:") + print(df_case1) + print("\n" * 2) + + # Plotting + plt.figure(figsize=(8, 6)) + plt.plot(data_dict["prob3"]["dx_values"], [err[0] for err in data_dict["prob3"]["case1"]["errors"]], label='1st Order Error') + plt.plot(data_dict["prob3"]["dx_values"], [err[1] for err in data_dict["prob3"]["case1"]["errors"]], label='2nd Order Error') + plt.xscale('log') + plt.yscale('log') + plt.xlabel('Δx') + plt.ylabel('% Error') + plt.legend() + plt.grid(True) + plt.savefig("prob3_case1_convergence.png", dpi=300) + #plt.show() + plt.close() + + + + + # Case 2 + data_dict["prob3"]["case2"] = {} + data_dict["prob3"]["case2"]["temp_results"] = [] + # num_point does not consider T(L). So "4" points is T0, T1, T2, T3, and then we add back T(L) + for num_point in data_dict["prob3"]["num_points"]: + fdm_array = case2.fdm_array(num_point) + fdm_array_inverse = np.linalg.inv(fdm_array) + + right_array = case2.right_array(num_point) + + unkown_temps_array = fdm_array_inverse @ right_array + solution = [] + solution[0:] = unkown_temps_array + solution.append(100) # T(L) BC + + data_dict["prob3"]["case2"]["temp_results"].append(solution) + + # We have all of the temperature results for varying dx + # For each dx, calculate the 1st and 2nd order heat flux + results = [] + for i in range(len(data_dict["prob3"]["dx_values"])): + a = 2.75 + dx = data_dict["prob3"]["dx_values"][i] + (t_0, t_1) = data_dict["prob3"]["case2"]["temp_results"][i][-2:] + + first_order = common.taylor_extraction(t_0, t_1, dx, a, 1) + second_order = common.taylor_extraction(t_0, t_1, dx, a, 2) + results.append([first_order, second_order]) + + data_dict["prob3"]["case2"]["heat_results"] = np.array(results) + + data_dict["prob3"]["case2"]["heat_results_true"] = case2.analytical_heat_loss(a=2.75) + + # Calculate % error and beta values + errors = [] + betas = [] + q_exact = data_dict["prob3"]["case2"]["heat_results_true"] + for i in range(0, len(results)): + + # % Error calculation + q_1_curr, q_2_curr = results[i] + first_order_error = common.calc_error(q_exact, q_1_curr) + second_order_error = common.calc_error(q_exact, q_2_curr) + + # Beta (convergence rate) calculation + if i != 0: + q_1_prev, q_2_prev = results[i-1] + dx_1 = data_dict["prob3"]["dx_values"][i-1] + dx_2 = data_dict["prob3"]["dx_values"][i] + first_order_beta = common.calc_beta(q_exact, q_1_curr, q_1_prev, dx_2, dx_1) + second_order_beta = common.calc_beta(q_exact, q_2_curr, q_2_prev, dx_2, dx_1) + else: + first_order_beta = 0 + second_order_beta = 0 + + errors.append([first_order_error, second_order_error]) + betas.append([first_order_beta, second_order_beta]) + + data_dict["prob3"]["case2"]["errors"] = errors + data_dict["prob3"]["case2"]["betas"] = betas + + # Combine dx values, results, errors, and betas into a DataFrame for display + table_data = [] + + for i in range(len(data_dict["prob3"]["dx_values"])): + table_data.append([ + results[i][0], # 1st order result + results[i][1], # 2nd order result + data_dict["prob3"]["case2"]["heat_results_true"], # True Q + errors[i][0], # 1st order % error + errors[i][1], # 2nd order % error + betas[i][0], # 1st order beta + betas[i][1] # 2nd order beta + ]) + + columns = ['1st Q', '2nd Q', 'True Q', '1st % Error', '2nd % Error', '1st β', '2nd β'] + df_case2 = pd.DataFrame(table_data, index=[f'dx = {i}' for i in data_dict["prob3"]["dx_values"]], columns=columns) + + print("FDM Case 2 Heat Flux Convergence Results:") + print(df_case2) + print("\n" * 2) + + # Plotting + plt.figure(figsize=(8, 6)) + plt.plot(data_dict["prob3"]["dx_values"], [err[0] for err in data_dict["prob3"]["case2"]["errors"]], label='1st Order Error') + plt.plot(data_dict["prob3"]["dx_values"], [err[1] for err in data_dict["prob3"]["case2"]["errors"]], label='2nd Order Error') + plt.xscale('log') + plt.yscale('log') + plt.xlabel('Δx') + plt.ylabel('% Error') + plt.legend() + plt.grid(True) + plt.savefig("prob3_case2_convergence.png", dpi=300) + #plt.show() + plt.close() + + + + +if __name__ == "__main__": + print("Homework 1 by Judson Upchurch") + print("Please note that some of the tables are transposed compared to the LaTeX equivalent") + print("") + + prob1() # Analyitical temperature distribution + + prob2() # FDM with dx = 0.125 and varying alpha + + prob3() # Convergence analysis \ No newline at end of file diff --git a/HW2/Images/Case 1.PNG b/HW2/Images/Case 1.PNG new file mode 100644 index 0000000..55b6de9 Binary files /dev/null and b/HW2/Images/Case 1.PNG differ diff --git a/HW2/Images/Case 2.PNG b/HW2/Images/Case 2.PNG new file mode 100644 index 0000000..b27e950 Binary files /dev/null and b/HW2/Images/Case 2.PNG differ diff --git a/HW2/Images/prob1_case1_analytical_temperature_vs_position.png b/HW2/Images/prob1_case1_analytical_temperature_vs_position.png new file mode 100644 index 0000000..3b6dc63 Binary files /dev/null and b/HW2/Images/prob1_case1_analytical_temperature_vs_position.png differ diff --git a/HW2/Images/prob1_case2_analytical_temperature_vs_position.png b/HW2/Images/prob1_case2_analytical_temperature_vs_position.png new file mode 100644 index 0000000..1c310a3 Binary files /dev/null and b/HW2/Images/prob1_case2_analytical_temperature_vs_position.png differ diff --git a/HW2/Images/prob1_comparison_cases.png b/HW2/Images/prob1_comparison_cases.png new file mode 100644 index 0000000..8c805d3 Binary files /dev/null and b/HW2/Images/prob1_comparison_cases.png differ diff --git a/HW2/Images/prob1_heat_flux_comparison.png b/HW2/Images/prob1_heat_flux_comparison.png new file mode 100644 index 0000000..1290cd0 Binary files /dev/null and b/HW2/Images/prob1_heat_flux_comparison.png differ diff --git a/HW2/Images/prob2_case1_fdm_temperature_vs_position.png b/HW2/Images/prob2_case1_fdm_temperature_vs_position.png new file mode 100644 index 0000000..2e63500 Binary files /dev/null and b/HW2/Images/prob2_case1_fdm_temperature_vs_position.png differ diff --git a/HW2/Images/prob2_case1_heat_flux.png b/HW2/Images/prob2_case1_heat_flux.png new file mode 100644 index 0000000..7513547 Binary files /dev/null and b/HW2/Images/prob2_case1_heat_flux.png differ diff --git a/HW2/Images/prob2_case2_fdm_temperature_vs_position.png b/HW2/Images/prob2_case2_fdm_temperature_vs_position.png new file mode 100644 index 0000000..ba807f6 Binary files /dev/null and b/HW2/Images/prob2_case2_fdm_temperature_vs_position.png differ diff --git a/HW2/Images/prob2_case2_heat_flux.png b/HW2/Images/prob2_case2_heat_flux.png new file mode 100644 index 0000000..d666fee Binary files /dev/null and b/HW2/Images/prob2_case2_heat_flux.png differ diff --git a/HW2/Images/prob2_comparison_cases.png b/HW2/Images/prob2_comparison_cases.png new file mode 100644 index 0000000..811ac16 Binary files /dev/null and b/HW2/Images/prob2_comparison_cases.png differ diff --git a/HW2/Images/prob3_case1_fem_temperature_vs_position.png b/HW2/Images/prob3_case1_fem_temperature_vs_position.png new file mode 100644 index 0000000..4a4b19a Binary files /dev/null and b/HW2/Images/prob3_case1_fem_temperature_vs_position.png differ diff --git a/HW2/Images/prob3_case1_heat_flux.png b/HW2/Images/prob3_case1_heat_flux.png new file mode 100644 index 0000000..c9f7766 Binary files /dev/null and b/HW2/Images/prob3_case1_heat_flux.png differ diff --git a/HW2/Images/prob3_case2_fem_temperature_vs_position.png b/HW2/Images/prob3_case2_fem_temperature_vs_position.png new file mode 100644 index 0000000..0421410 Binary files /dev/null and b/HW2/Images/prob3_case2_fem_temperature_vs_position.png differ diff --git a/HW2/Images/prob3_case2_heat_flux.png b/HW2/Images/prob3_case2_heat_flux.png new file mode 100644 index 0000000..c4957a6 Binary files /dev/null and b/HW2/Images/prob3_case2_heat_flux.png differ diff --git a/HW2/Images/prob3_comparison_cases.png b/HW2/Images/prob3_comparison_cases.png new file mode 100644 index 0000000..abe215a Binary files /dev/null and b/HW2/Images/prob3_comparison_cases.png differ diff --git a/HW2/Images/prob4_case1_heat_convergence.png b/HW2/Images/prob4_case1_heat_convergence.png new file mode 100644 index 0000000..ea11e63 Binary files /dev/null and b/HW2/Images/prob4_case1_heat_convergence.png differ diff --git a/HW2/Images/prob4_case1_temp_convergence.png b/HW2/Images/prob4_case1_temp_convergence.png new file mode 100644 index 0000000..2fbaa9d Binary files /dev/null and b/HW2/Images/prob4_case1_temp_convergence.png differ diff --git a/HW2/Images/prob4_case2_heat_convergence.png b/HW2/Images/prob4_case2_heat_convergence.png new file mode 100644 index 0000000..1dded13 Binary files /dev/null and b/HW2/Images/prob4_case2_heat_convergence.png differ diff --git a/HW2/Images/prob4_case2_temp_convergence.png b/HW2/Images/prob4_case2_temp_convergence.png new file mode 100644 index 0000000..08a9b84 Binary files /dev/null and b/HW2/Images/prob4_case2_temp_convergence.png differ diff --git a/HW2/Judson_Upchurch_HW2.pdf b/HW2/Judson_Upchurch_HW2.pdf new file mode 100644 index 0000000..b06bcf2 Binary files /dev/null and b/HW2/Judson_Upchurch_HW2.pdf differ diff --git a/HW2/__pycache__/case1.cpython-312.pyc b/HW2/__pycache__/case1.cpython-312.pyc new file mode 100644 index 0000000..89d144d Binary files /dev/null and b/HW2/__pycache__/case1.cpython-312.pyc differ diff --git a/HW2/__pycache__/case2.cpython-312.pyc b/HW2/__pycache__/case2.cpython-312.pyc new file mode 100644 index 0000000..0d06ada Binary files /dev/null and b/HW2/__pycache__/case2.cpython-312.pyc differ diff --git a/HW2/__pycache__/common.cpython-312.pyc b/HW2/__pycache__/common.cpython-312.pyc new file mode 100644 index 0000000..2985a71 Binary files /dev/null and b/HW2/__pycache__/common.cpython-312.pyc differ diff --git a/HW2/case1.py b/HW2/case1.py new file mode 100644 index 0000000..b7228c8 --- /dev/null +++ b/HW2/case1.py @@ -0,0 +1,47 @@ +# case1.py + +import numpy as np + +k = 0.5 # W / (cm K) +area = np.pi / 100 # cm^2 + +def analytical(a, x): + return 100 * np.sinh(a*x) / np.sinh(a) + +def analytical_heat_loss(a): + return -100*k*area*a/np.tanh(a) + +def fdm_array(n, a = 2.75): + dx = 1 / n + kap = 2 + ((a**2)*(dx**2)) + + left_FDM_array = np.zeros((n-1, n-1)) + left_FDM_array[0][0:2] = [kap, -1] + row_FDM = [-1, kap, -1] + + for i in range(1, n-2): + left_FDM_array[i][i-1:i+2] = row_FDM + + left_FDM_array[n-2][n-3:n-1] = [-1, kap] + + return left_FDM_array + +def fem_array(n, a = 2.75): + dx = 1 / n + kap = (2/dx + 4*a**2*dx/6) / (1/dx - a**2*dx/6) + + left_FDM_array = np.zeros((n-1, n-1)) + left_FDM_array[0][0:2] = [kap, -1] + row_FDM = [-1, kap, -1] + + for i in range(1, n-2): + left_FDM_array[i][i-1:i+2] = row_FDM + + left_FDM_array[n-2][n-3:n-1] = [-1, kap] + + return left_FDM_array + +def right_array(n): + array = [0 for _ in range(n-2)] + array.append(100) + return array \ No newline at end of file diff --git a/HW2/case2.py b/HW2/case2.py new file mode 100644 index 0000000..e8d20c1 --- /dev/null +++ b/HW2/case2.py @@ -0,0 +1,49 @@ +# case2.py + +import numpy as np + +k = 0.5 # W / (cm K) +area = np.pi / 100 # cm^2 + +def analytical(a, x): + return 100 * np.cosh(a*x) / np.cosh(a) + +def analytical_heat_loss(a): + return -100*k*area*a*np.tanh(a) + +def fdm_array(n, a = 2.75): + dx = 1 / n + kap = 2 + ((a**2)*(dx**2)) + kap_prime = (kap/2) + + left_FDM_array = np.zeros((n, n)) + left_FDM_array[0][0:2] = [kap_prime, -1] + row_FDM = [-1, kap, -1] + + for i in range(1, n-1): + left_FDM_array[i][i-1:i+2] = row_FDM + + left_FDM_array[n-1][n-2:n] = [-1, kap] + + return left_FDM_array + +def fem_array(n, a = 2.75): + dx = 1 / n + kap = (2/dx + 4*a**2*dx/6) / (1/dx - a**2*dx/6) + kap_prime = (kap/2) + + left_FDM_array = np.zeros((n, n)) + left_FDM_array[0][0:2] = [kap_prime, -1] + row_FDM = [-1, kap, -1] + + for i in range(1, n-1): + left_FDM_array[i][i-1:i+2] = row_FDM + + left_FDM_array[n-1][n-2:n] = [-1, kap] + + return left_FDM_array + +def right_array(n): + array = [0 for _ in range(n-1)] + array.append(100) + return array \ No newline at end of file diff --git a/HW2/common.py b/HW2/common.py new file mode 100644 index 0000000..ecab3b0 --- /dev/null +++ b/HW2/common.py @@ -0,0 +1,25 @@ +# common.py + +import numpy as np + + +k = 0.5 # W / (cm K) +area = np.pi / 100 # cm^2 + + +def taylor_extraction(t_0, t_1, dx, a=0, order=1): + if order == 1: + return -1 * k * area * (t_1 - t_0) / dx + elif order == 2: + return -1 * k * area * (((t_1 - t_0) / dx) + (a**2 * dx * t_1 / 2)) + +def calc_error(q_exact, q_1): + return np.abs((q_exact - q_1) / q_exact) + +def calc_beta(q_exact, q_1, q_2, dx_1, dx_2): + return np.log(np.abs((q_exact - q_1)/(q_exact - q_2))) / np.log(dx_1 / dx_2) + +def fem_heat_extraction(t_1, t_2, dx, a = 2.75): + term_1 = (-1/dx + a**2*dx/6) * t_1 + term_2 = (1/dx + 2*a**2*dx/6) * t_2 + return -1 * k * area * (term_1 + term_2) \ No newline at end of file diff --git a/HW2/main.py b/HW2/main.py new file mode 100644 index 0000000..c9a4e86 --- /dev/null +++ b/HW2/main.py @@ -0,0 +1,897 @@ +# main.py + +import numpy as np +import pandas as pd +import matplotlib.pyplot as plt + +import case1 +import case2 +import common + +data_dict = {} +data_dict["a_values"] = np.array([0.29, 0.5, 1.35, 2.75, 4.75, 9.15]) + +def prob1(): + '''Analytical solutions''' + print("Problem 1") + # Problem 1 - Analytical solution + data_dict["prob1"] = {} + data_dict["prob1"]["x_values"] = np.array([0, 0.125, 0.25, 0.375, 0.5, 0.625, 0.75, 0.875, 1.0]) + data_dict["prob1"]["x_values_fine"] = np.linspace(0, 1) + + # Case 1 temperature calculations + results = [] + results_fine = [] + for a_value in data_dict["a_values"]: + result = case1.analytical(a=a_value, x=data_dict["prob1"]["x_values"]) + result_fine = case1.analytical(a=a_value, x=data_dict["prob1"]["x_values_fine"]) + results.append(result) + results_fine.append(result_fine) + + data_dict["prob1"]["case1_temp_results"] = np.array(results_fine) + + df_case1 = pd.DataFrame(results, index=[f'a = {a}' for a in data_dict["a_values"]], columns=[f'x = {x:.3f}' for x in data_dict["prob1"]["x_values"]]) + + # Pretty print DataFrame for Case 1 temperature + print("Analytical Case 1 Temperature Results:") + print(df_case1) + print("\n" * 2) + + # Plotting Case 1 temperature + plt.figure(figsize=(10, 6)) + for idx, a_value in enumerate(data_dict["a_values"]): + plt.plot(data_dict["prob1"]["x_values_fine"], data_dict["prob1"]["case1_temp_results"][idx], label=f'α = {a_value}') + plt.xlabel('Position (cm)') + plt.ylabel('Temperature (°C)') + plt.legend() + plt.grid(True) + plt.savefig('prob1_case1_analytical_temperature_vs_position.png', dpi=300) + #plt.show() + plt.close() + + # Case 2 temperature calculations + results = [] + results_fine = [] + for a_value in data_dict["a_values"]: + result = case2.analytical(a=a_value, x=data_dict["prob1"]["x_values"]) + result_fine = case2.analytical(a=a_value, x=data_dict["prob1"]["x_values_fine"]) + results.append(result) + results_fine.append(result_fine) + + data_dict["prob1"]["case2_temp_results"] = np.array(results_fine) + + df_case2 = pd.DataFrame(results, index=[f'a = {a}' for a in data_dict["a_values"]], columns=[f'x = {x:.3f}' for x in data_dict["prob1"]["x_values"]]) + + # Pretty print DataFrame for Case 2 + print("Analytical Case 2 Temperature Results:") + print(df_case2) + print("\n" * 2) + + # Plotting Case 2 + plt.figure(figsize=(10, 6)) + for idx, a_value in enumerate(data_dict["a_values"]): + plt.plot(data_dict["prob1"]["x_values_fine"], data_dict["prob1"]["case2_temp_results"][idx], label=f'α = {a_value}') + plt.xlabel('Position (cm)') + plt.ylabel('Temperature (°C)') + plt.legend() + plt.grid(True) + plt.savefig('prob1_case2_analytical_temperature_vs_position.png', dpi=300) + #plt.show() + plt.close() + + # Comparison plots between cases for temperature distribution + fig, axes = plt.subplots(3, 2, figsize=(12, 12), sharex=True, sharey=True) + + for idx, a_value in enumerate(data_dict["a_values"]): + ax = axes[idx // 2, idx % 2] + ax.plot(data_dict["prob1"]["x_values_fine"], data_dict["prob1"]["case1_temp_results"][idx], label='Case 1') + ax.plot(data_dict["prob1"]["x_values_fine"], data_dict["prob1"]["case2_temp_results"][idx], label='Case 2') + ax.set_title(f'α = {a_value}') + ax.set_xlabel('Position (cm)') + ax.set_ylabel('Temperature (°C)') + ax.legend() + ax.grid(True) + + plt.tight_layout(rect=[0, 0, 1, 0.95]) # Adjust layout to make room for the main title + plt.savefig('prob1_comparison_cases.png', dpi=300) + #plt.show() + plt.close() + + # Case 1 heat flux calculations + results = [] + for a_value in data_dict["a_values"]: + result = case1.analytical_heat_loss(a=a_value) + results.append(result) + + data_dict["prob1"]["case1_heat_flux_results"] = np.array(results) + + # Create a DataFrame with alpha as the index and heat flux as the data + df_case1_heat_flux = pd.DataFrame(results, index=[f'a = {a}' for a in data_dict["a_values"]], columns=['Heat Flux']) + + # Pretty print DataFrame for Case 1 heat flux + print("Analytical Case 1 Heat Flux Results:") + print(df_case1_heat_flux) + print("\n" * 2) + + # Case 2 heat flux calculations + results = [] + for a_value in data_dict["a_values"]: + result = case2.analytical_heat_loss(a=a_value) + results.append(result) + + data_dict["prob1"]["case2_heat_flux_results"] = np.array(results) + + # Create a DataFrame with alpha as the index and heat flux as the data + df_case2_heat_flux = pd.DataFrame(results, index=[f'a = {a}' for a in data_dict["a_values"]], columns=['Heat Flux']) + + # Pretty print DataFrame for Case 2 heat flux + print("Analytical Case 2 Heat Flux Results:") + print(df_case2_heat_flux) + print("\n" * 2) + + # Plotting heat flux vs alpha for both cases + plt.figure(figsize=(10, 6)) + plt.plot(data_dict["a_values"], data_dict["prob1"]["case1_heat_flux_results"], label='Case 1') + plt.plot(data_dict["a_values"], data_dict["prob1"]["case2_heat_flux_results"], label='Case 2') + plt.xlabel('Alpha ($cm^{-1}$)') + plt.ylabel('Heat Flux (W)') + plt.legend() + plt.grid(True) + plt.savefig('prob1_heat_flux_comparison.png', dpi=300) + #plt.show() + plt.close() + +def prob2(): + '''FDM with dx = 0.125 and alpha varying''' + print("Problem 2") + data_dict["prob2"] = {} + data_dict["prob2"]["num_point"] = 8 # This does not consider the final T(L) point. So actually we have 9 points + data_dict["prob2"]["dx"] = 0.125 + + # Case 1 + results = [] + # num_point does not consider T(L). So "4" points is T0, T1, T2, T3, and then we add back T(L) + for a_value in data_dict["a_values"]: + fdm_array = case1.fdm_array(data_dict["prob2"]["num_point"], a = a_value) + fdm_array_inverse = np.linalg.inv(fdm_array) + + right_array = case1.right_array(data_dict["prob2"]["num_point"]) + + unkown_temps_array = fdm_array_inverse @ right_array + solution = [0] # First point is 0 from BC + solution[1:] = unkown_temps_array + solution.append(100) # T(L) BC + + results.append(solution) + + data_dict["prob2"]["case1"] = {} + data_dict["prob2"]["case1"]["temp_results"] = np.array(results) + + data_dict["prob2"]["x_values"] = np.array([0, 0.125, 0.25, 0.375, 0.5, 0.625, 0.75, 0.875, 1.0]) + df_case1 = pd.DataFrame(results, index=[f'a = {a}' for a in data_dict["a_values"]], columns=[f'x = {x:.3f}' for x in data_dict["prob2"]["x_values"]]) + + # Pretty print DataFrame for Case 1 temperature + print("FDM Case 1 Temperature Results:") + print(df_case1) + print("\n" * 2) + + # Plotting Case 1 temperature + plt.figure(figsize=(10, 6)) + for idx, a_value in enumerate(data_dict["a_values"]): + plt.plot(data_dict["prob2"]["x_values"], data_dict["prob2"]["case1"]["temp_results"][idx], label=f'α = {a_value}') + plt.xlabel('Position (cm)') + plt.ylabel('Temperature (°C)') + plt.legend() + plt.grid(True) + plt.savefig('prob2_case1_fdm_temperature_vs_position.png', dpi=300) + #plt.show() + plt.close() + + # Case 2 + results = [] + # num_point does not consider T(L). So "4" points is T0, T1, T2, T3, and then we add back T(L) + for a_value in data_dict["a_values"]: + fdm_array = case2.fdm_array(data_dict["prob2"]["num_point"], a = a_value) + fdm_array_inverse = np.linalg.inv(fdm_array) + + right_array = case2.right_array(data_dict["prob2"]["num_point"]) + + unkown_temps_array = fdm_array_inverse @ right_array + + solution = unkown_temps_array.tolist() + solution.append(100) # T(L) BC + + results.append(solution) + + data_dict["prob2"]["case2"] = {} + data_dict["prob2"]["case2"]["temp_results"] = np.array(results) + + data_dict["prob2"]["x_values"] = np.array([0, 0.125, 0.25, 0.375, 0.5, 0.625, 0.75, 0.875, 1.0]) + df_case2 = pd.DataFrame(results, index=[f'a = {a}' for a in data_dict["a_values"]], columns=[f'x = {x:.3f}' for x in data_dict["prob2"]["x_values"]]) + + # Pretty print DataFrame for Case 2 temperature + print("FDM Case 2 Temperature Results:") + print(df_case2) + print("\n" * 2) + + # Plotting Case 2 temperature + plt.figure(figsize=(10, 6)) + for idx, a_value in enumerate(data_dict["a_values"]): + plt.plot(data_dict["prob2"]["x_values"], data_dict["prob2"]["case2"]["temp_results"][idx], label=f'α = {a_value}') + plt.xlabel('Position (cm)') + plt.ylabel('Temperature (°C)') + plt.legend() + plt.grid(True) + plt.savefig('prob2_case2_fdm_temperature_vs_position.png', dpi=300) + #plt.show() + plt.close() + + + # Plot the comparisons similar to problem 1 + # Comparison plots between cases for temperature distribution + fig, axes = plt.subplots(3, 2, figsize=(12, 12), sharex=True, sharey=True) + + for idx, a_value in enumerate(data_dict["a_values"]): + ax = axes[idx // 2, idx % 2] + ax.plot(data_dict["prob2"]["x_values"], data_dict["prob2"]["case1"]["temp_results"][idx], label='Case 1') + ax.plot(data_dict["prob2"]["x_values"], data_dict["prob2"]["case2"]["temp_results"][idx], label='Case 2') + ax.set_title(f'α = {a_value}') + ax.set_xlabel('Position (cm)') + ax.set_ylabel('Temperature (°C)') + ax.legend() + ax.grid(True) + + plt.tight_layout(rect=[0, 0, 1, 0.95]) # Adjust layout to make room for the main title + plt.savefig('prob2_comparison_cases.png', dpi=300) + #plt.show() + plt.close() + + + + # Heat flux extraction + # Case 1 + results = [] + for i in range(len(data_dict["a_values"])): + a = data_dict["a_values"][i] + (t_0, t_1) = data_dict["prob2"]["case1"]["temp_results"][i][-2:] + dx = data_dict["prob2"]["dx"] + first_order = common.taylor_extraction(t_0, t_1, dx, a, 1) + second_order = common.taylor_extraction(t_0, t_1, dx, a, 2) + results.append([first_order, second_order]) + + data_dict["prob2"]["case1"]["heat_results"] = np.array(results) + + # Create a DataFrame with alpha as the index and heat flux as the data + df_case1_heat_flux = pd.DataFrame(results, index=[f'a = {a}' for a in data_dict["a_values"]], columns=['1st Order', '2nd Order']) + + # Pretty print DataFrame for Case 1 heat flux + print("FDM Case 1 Heat Flux Results:") + print(df_case1_heat_flux) + print("\n" * 2) + + # Plotting heat flux vs alpha for both extractions + plt.figure(figsize=(10, 6)) + plt.plot(data_dict["a_values"], [i[0] for i in data_dict["prob2"]["case1"]["heat_results"]], label='1st Order Extraction') + plt.plot(data_dict["a_values"], [i[1] for i in data_dict["prob2"]["case1"]["heat_results"]], label='2nd Order Extraction') + plt.xlabel('Alpha ($cm^{-1}$)') + plt.ylabel('Heat Flux (W)') + plt.legend() + plt.grid(True) + plt.savefig('prob2_case1_heat_flux.png', dpi=300) + #plt.show() + plt.close() + + + + # Case 2 + results = [] + for i in range(len(data_dict["a_values"])): + a = data_dict["a_values"][i] + (t_0, t_1) = data_dict["prob2"]["case2"]["temp_results"][i][-2:] + dx = data_dict["prob2"]["dx"] + first_order = common.taylor_extraction(t_0, t_1, dx, a, 1) + second_order = common.taylor_extraction(t_0, t_1, dx, a, 2) + results.append([first_order, second_order]) + + data_dict["prob2"]["case2"]["heat_results"] = np.array(results) + + # Create a DataFrame with alpha as the index and heat flux as the data + df_case2_heat_flux = pd.DataFrame(results, index=[f'a = {a}' for a in data_dict["a_values"]], columns=['1st Order', '2nd Order']) + + # Pretty print DataFrame for Case 1 heat flux + print("FDM Case 2 Heat Flux Results:") + print(df_case2_heat_flux) + print("\n" * 2) + + # Plotting heat flux vs alpha for both extractions + plt.figure(figsize=(10, 6)) + plt.plot(data_dict["a_values"], [i[0] for i in data_dict["prob2"]["case2"]["heat_results"]], label='1st Order Extraction') + plt.plot(data_dict["a_values"], [i[1] for i in data_dict["prob2"]["case2"]["heat_results"]], label='2nd Order Extraction') + plt.xlabel('Alpha ($cm^{-1}$)') + plt.ylabel('Heat Flux (W)') + plt.legend() + plt.grid(True) + plt.savefig('prob2_case2_heat_flux.png', dpi=300) + #plt.show() + plt.close() + +def prob3(): + '''FEM with dx = 0.125 and alpha varying''' + print("Problem 3") + data_dict["prob3"] = {} + data_dict["prob3"]["num_point"] = 8 # This does not consider the final T(L) point. So actually we have 9 points + data_dict["prob3"]["dx"] = 0.125 + + # Case 1 + results = [] + # num_point does not consider T(L). So "4" points is T0, T1, T2, T3, and then we add back T(L) + for a_value in data_dict["a_values"]: + fdm_array = case1.fem_array(data_dict["prob3"]["num_point"], a = a_value) + fdm_array_inverse = np.linalg.inv(fdm_array) + + right_array = case1.right_array(data_dict["prob3"]["num_point"]) + + unkown_temps_array = fdm_array_inverse @ right_array + solution = [0] # First point is 0 from BC + solution[1:] = unkown_temps_array + solution.append(100) # T(L) BC + + results.append(solution) + + data_dict["prob3"]["case1"] = {} + data_dict["prob3"]["case1"]["temp_results"] = np.array(results) + + data_dict["prob3"]["x_values"] = np.array([0, 0.125, 0.25, 0.375, 0.5, 0.625, 0.75, 0.875, 1.0]) + df_case1 = pd.DataFrame(results, index=[f'a = {a}' for a in data_dict["a_values"]], columns=[f'x = {x:.3f}' for x in data_dict["prob3"]["x_values"]]) + + # Pretty print DataFrame for Case 1 temperature + print("FEM Case 1 Temperature Results:") + print(df_case1) + print("\n" * 2) + + # Plotting Case 1 temperature + plt.figure(figsize=(10, 6)) + for idx, a_value in enumerate(data_dict["a_values"]): + plt.plot(data_dict["prob3"]["x_values"], data_dict["prob3"]["case1"]["temp_results"][idx], label=f'α = {a_value}') + plt.xlabel('Position (cm)') + plt.ylabel('Temperature (°C)') + plt.legend() + plt.grid(True) + plt.savefig('prob3_case1_fem_temperature_vs_position.png', dpi=300) + #plt.show() + plt.close() + + # Case 2 + results = [] + # num_point does not consider T(L). So "4" points is T0, T1, T2, T3, and then we add back T(L) + for a_value in data_dict["a_values"]: + fdm_array = case2.fem_array(data_dict["prob3"]["num_point"], a = a_value) + fdm_array_inverse = np.linalg.inv(fdm_array) + + right_array = case2.right_array(data_dict["prob3"]["num_point"]) + + unkown_temps_array = fdm_array_inverse @ right_array + + solution = unkown_temps_array.tolist() + solution.append(100) # T(L) BC + + results.append(solution) + + data_dict["prob3"]["case2"] = {} + data_dict["prob3"]["case2"]["temp_results"] = np.array(results) + + data_dict["prob3"]["x_values"] = np.array([0, 0.125, 0.25, 0.375, 0.5, 0.625, 0.75, 0.875, 1.0]) + df_case2 = pd.DataFrame(results, index=[f'a = {a}' for a in data_dict["a_values"]], columns=[f'x = {x:.3f}' for x in data_dict["prob3"]["x_values"]]) + + # Pretty print DataFrame for Case 2 temperature + print("FEM Case 2 Temperature Results:") + print(df_case2) + print("\n" * 2) + + # Plotting Case 2 temperature + plt.figure(figsize=(10, 6)) + for idx, a_value in enumerate(data_dict["a_values"]): + plt.plot(data_dict["prob3"]["x_values"], data_dict["prob3"]["case2"]["temp_results"][idx], label=f'α = {a_value}') + plt.xlabel('Position (cm)') + plt.ylabel('Temperature (°C)') + plt.legend() + plt.grid(True) + plt.savefig('prob3_case2_fem_temperature_vs_position.png', dpi=300) + #plt.show() + plt.close() + + + # Plot the comparisons similar to problem 1 + # Comparison plots between cases for temperature distribution + fig, axes = plt.subplots(3, 2, figsize=(12, 12), sharex=True, sharey=True) + + for idx, a_value in enumerate(data_dict["a_values"]): + ax = axes[idx // 2, idx % 2] + ax.plot(data_dict["prob3"]["x_values"], data_dict["prob3"]["case1"]["temp_results"][idx], label='Case 1') + ax.plot(data_dict["prob3"]["x_values"], data_dict["prob3"]["case2"]["temp_results"][idx], label='Case 2') + ax.set_title(f'α = {a_value}') + ax.set_xlabel('Position (cm)') + ax.set_ylabel('Temperature (°C)') + ax.legend() + ax.grid(True) + + plt.tight_layout(rect=[0, 0, 1, 0.95]) # Adjust layout to make room for the main title + plt.savefig('prob3_comparison_cases.png', dpi=300) + #plt.show() + plt.close() + + + + # Heat flux extraction + # Case 1 + results = [] + for i in range(len(data_dict["a_values"])): + a = data_dict["a_values"][i] + (t_0, t_1) = data_dict["prob3"]["case1"]["temp_results"][i][-2:] + dx = data_dict["prob3"]["dx"] + result = common.fem_heat_extraction(t_0, t_1, dx, a) + results.append([result]) + + data_dict["prob3"]["case1"]["heat_results"] = np.array(results) + + # Create a DataFrame with alpha as the index and heat flux as the data + df_case1_heat_flux = pd.DataFrame(results, index=[f'a = {a}' for a in data_dict["a_values"]], columns=['Heat Extraction']) + + # Pretty print DataFrame for Case 1 heat flux + print("FEM Case 1 Heat Flux Results:") + print(df_case1_heat_flux) + print("\n" * 2) + + # Plotting heat flux vs alpha for both extractions + plt.figure(figsize=(10, 6)) + plt.plot(data_dict["a_values"], [i[0] for i in data_dict["prob3"]["case1"]["heat_results"]], label='Heat Extraction') + plt.xlabel('Alpha ($cm^{-1}$)') + plt.ylabel('Heat Flux (W)') + plt.legend() + plt.grid(True) + plt.savefig('prob3_case1_heat_flux.png', dpi=300) + #plt.show() + plt.close() + + + + # Case 2 + results = [] + for i in range(len(data_dict["a_values"])): + a = data_dict["a_values"][i] + (t_0, t_1) = data_dict["prob3"]["case2"]["temp_results"][i][-2:] + dx = data_dict["prob3"]["dx"] + result = common.fem_heat_extraction(t_0, t_1, dx, a) + results.append([result]) + + data_dict["prob3"]["case2"]["heat_results"] = np.array(results) + + # Create a DataFrame with alpha as the index and heat flux as the data + df_case2_heat_flux = pd.DataFrame(results, index=[f'a = {a}' for a in data_dict["a_values"]], columns=['Heat Extraction']) + + # Pretty print DataFrame for Case 1 heat flux + print("FEM Case 2 Heat Flux Results:") + print(df_case2_heat_flux) + print("\n" * 2) + + # Plotting heat flux vs alpha for both extractions + plt.figure(figsize=(10, 6)) + plt.plot(data_dict["a_values"], [i[0] for i in data_dict["prob3"]["case2"]["heat_results"]], label='Heat Extraction') + plt.xlabel('Alpha ($cm^{-1}$)') + plt.ylabel('Heat Flux (W)') + plt.legend() + plt.grid(True) + plt.savefig('prob3_case2_heat_flux.png', dpi=300) + #plt.show() + plt.close() + +def prob4(): + '''Convergence analysis of the cases''' + print("Problem 4") + data_dict["prob4"] = {} + data_dict["prob4"]["num_points"] = [2**i for i in range(2, 8)] # This does not consider the final T(L) point. So actually we have n + 1 points + data_dict["prob4"]["dx_values"] = [1 / i for i in data_dict["prob4"]["num_points"]] + + # Case 1 + # Get fdm temp results + data_dict["prob4"]["case1"] = {} + data_dict["prob4"]["case1"]["fdm"] = {} + data_dict["prob4"]["case1"]["fdm"]["temp_results"] = [] + # num_point does not consider T(L). So "4" points is T0, T1, T2, T3, and then we add back T(L) + for num_point in data_dict["prob4"]["num_points"]: + fdm_array = case1.fdm_array(num_point) + fdm_array_inverse = np.linalg.inv(fdm_array) + + right_array = case1.right_array(num_point) + + unkown_temps_array = fdm_array_inverse @ right_array + solution = [0] # First point is 0 from BC + solution[1:] = unkown_temps_array + solution.append(100) # T(L) BC + + data_dict["prob4"]["case1"]["fdm"]["temp_results"].append(solution) + + # Get fem temp results + data_dict["prob4"]["case1"]["fem"] = {} + data_dict["prob4"]["case1"]["fem"]["temp_results"] = [] + # num_point does not consider T(L). So "4" points is T0, T1, T2, T3, and then we add back T(L) + for num_point in data_dict["prob4"]["num_points"]: + fdm_array = case1.fem_array(num_point) + fdm_array_inverse = np.linalg.inv(fdm_array) + + right_array = case1.right_array(num_point) + + unkown_temps_array = fdm_array_inverse @ right_array + solution = [0] # First point is 0 from BC + solution[1:] = unkown_temps_array + solution.append(100) # T(L) BC + + data_dict["prob4"]["case1"]["fem"]["temp_results"].append(solution) + + # We have all of the temperature results for varying dx for both fdm and fem + # For each dx, get the midpoint temperature from fdm and fem + results = [] + for i in range(len(data_dict["prob4"]["num_points"])): + a = 2.75 + num_points = data_dict["prob4"]["num_points"][i] + midpoint_index = int(num_points / 2) + t_fdm = data_dict["prob4"]["case1"]["fdm"]["temp_results"][i][midpoint_index] + t_fem = data_dict["prob4"]["case1"]["fem"]["temp_results"][i][midpoint_index] + + results.append([t_fdm, t_fem]) + + data_dict["prob4"]["case1"]["midpoint_temp_results"] = np.array(results) + data_dict["prob4"]["case1"]["midpoint_temp_true"] = case1.analytical(a = 2.75, x = 0.5) + + # Calculate % error and beta values for midpoint temperature + errors = [] + betas = [] + t_exact = data_dict["prob4"]["case1"]["midpoint_temp_true"] + t_results = data_dict["prob4"]["case1"]["midpoint_temp_results"] + + for i in range(0, len(t_results)): + # % Error calculation + t_fdm, t_fem = results[i] + fdm_error = common.calc_error(t_exact, t_fdm) + fem_error = common.calc_error(t_exact, t_fem) + + # Beta (convergence rate) calculation + if i != 0: + t_fdm_prev, t_fem_prev = results[i-1] + dx_1 = data_dict["prob4"]["dx_values"][i-1] + dx_2 = data_dict["prob4"]["dx_values"][i] + fdm_beta = common.calc_beta(t_exact, t_fdm, t_fdm_prev, dx_2, dx_1) + fem_beta = common.calc_beta(t_exact, t_fem, t_fem_prev, dx_2, dx_1) + else: + fdm_beta = 0 + fem_beta = 0 + + errors.append([fdm_error, fem_error]) + betas.append([fdm_beta, fem_beta]) + + data_dict["prob4"]["case1"]["temp_errors"] = errors + data_dict["prob4"]["case1"]["temp_betas"] = betas + + # Combine dx values, results, errors, and betas into a DataFrame for display + table_data = [] + for i in range(len(data_dict["prob4"]["dx_values"])): + table_data.append([ + results[i][0], # fdm result + results[i][1], # fem result + data_dict["prob4"]["case1"]["midpoint_temp_true"], # True T + errors[i][0], # fdm % error + errors[i][1], # fem % error + betas[i][0], # fdm beta + betas[i][1] # fem beta + ]) + + columns = ['FDM T', 'FEM T', 'True T', 'FDM % Error', 'FEM % Error', 'FDM β', 'FEM β'] + df_case1 = pd.DataFrame(table_data, index=[f'dx = {i}' for i in data_dict["prob4"]["dx_values"]], columns=columns) + + print("FDM and FEM Case 1 Midpoint Temperature Convergence Results:") + print(df_case1) + print("\n" * 2) + # Plotting + plt.figure(figsize=(8, 6)) + plt.plot(data_dict["prob4"]["dx_values"], [err[0] for err in data_dict["prob4"]["case1"]["temp_errors"]], label='FDM Temp Error') + plt.plot(data_dict["prob4"]["dx_values"], [err[1] for err in data_dict["prob4"]["case1"]["temp_errors"]], label='FEM Temp Error') + plt.xscale('log') + plt.yscale('log') + plt.xlabel('Δx') + plt.ylabel('% Error') + plt.legend() + plt.grid(True) + plt.savefig("prob4_case1_temp_convergence.png", dpi=300) + #plt.show() + plt.close() + + + + # For each dx, calculate the 2nd order heat flux for fdm and the heat flux for fem + results = [] + for i in range(len(data_dict["prob4"]["dx_values"])): + a = 2.75 + dx = data_dict["prob4"]["dx_values"][i] + (t_0_fdm, t_1_fdm) = data_dict["prob4"]["case1"]["fdm"]["temp_results"][i][-2:] + (t_0_fem, t_1_fem) = data_dict["prob4"]["case1"]["fem"]["temp_results"][i][-2:] + + fdm = common.taylor_extraction(t_0_fdm, t_1_fdm, dx, a, 2) + fem = common.fem_heat_extraction(t_0_fem, t_1_fem, dx, a) + results.append([fdm, fem]) + + data_dict["prob4"]["case1"]["heat_results"] = np.array(results) + data_dict["prob4"]["case1"]["heat_results_true"] = case1.analytical_heat_loss(a=2.75) + + # Calculate % error and beta values for heat loss + errors = [] + betas = [] + q_exact = data_dict["prob4"]["case1"]["heat_results_true"] + q_results = data_dict["prob4"]["case1"]["heat_results"] + + for i in range(0, len(q_results)): + # % Error calculation + q_fdm, q_fem = results[i] + fdm_error = common.calc_error(q_exact, q_fdm) + fem_error = common.calc_error(q_exact, q_fem) + + # Beta (convergence rate) calculation + if i != 0: + q_fdm_prev, q_fem_prev = results[i-1] + dx_1 = data_dict["prob4"]["dx_values"][i-1] + dx_2 = data_dict["prob4"]["dx_values"][i] + fdm_beta = common.calc_beta(q_exact, q_fdm, q_fdm_prev, dx_2, dx_1) + fem_beta = common.calc_beta(q_exact, q_fem, q_fem_prev, dx_2, dx_1) + else: + fdm_beta = 0 + fem_beta = 0 + + errors.append([fdm_error, fem_error]) + betas.append([fdm_beta, fem_beta]) + + data_dict["prob4"]["case1"]["heat_errors"] = errors + data_dict["prob4"]["case1"]["heat_betas"] = betas + + # Combine dx values, results, errors, and betas into a DataFrame for display + table_data = [] + for i in range(len(data_dict["prob4"]["dx_values"])): + table_data.append([ + results[i][0], # fdm result + results[i][1], # fem result + q_exact, # True Q + errors[i][0], # fdm % error + errors[i][1], # fem % error + betas[i][0], # fdm beta + betas[i][1] # fem beta + ]) + + columns = ['FDM Q', 'FEM Q', 'True Q', 'FDM % Error', 'FEM % Error', 'FDM β', 'FEM β'] + df_case1 = pd.DataFrame(table_data, index=[f'dx = {i}' for i in data_dict["prob4"]["dx_values"]], columns=columns) + + print("FDM and FEM Case 1 Heat Loss Convergence Results:") + print(df_case1) + print("\n" * 2) + + # Plotting + plt.figure(figsize=(8, 6)) + plt.plot(data_dict["prob4"]["dx_values"], [err[0] for err in data_dict["prob4"]["case1"]["heat_errors"]], label='FDM Heat Flux Error') + plt.plot(data_dict["prob4"]["dx_values"], [err[1] for err in data_dict["prob4"]["case1"]["heat_errors"]], label='FEM Heat Flux Error') + plt.xscale('log') + plt.yscale('log') + plt.xlabel('Δx') + plt.ylabel('% Error') + plt.legend() + plt.grid(True) + plt.savefig("prob4_case1_heat_convergence.png", dpi=300) + #plt.show() + plt.close() + + + + + # Case 2 + # Get fdm temp results + data_dict["prob4"]["case2"] = {} + data_dict["prob4"]["case2"]["fdm"] = {} + data_dict["prob4"]["case2"]["fdm"]["temp_results"] = [] + # num_point does not consider T(L). So "4" points is T0, T1, T2, T3, and then we add back T(L) + for num_point in data_dict["prob4"]["num_points"]: + fdm_array = case2.fdm_array(num_point) + fdm_array_inverse = np.linalg.inv(fdm_array) + + right_array = case2.right_array(num_point) + + unkown_temps_array = fdm_array_inverse @ right_array + solution = [] + solution[0:] = unkown_temps_array + solution.append(100) # T(L) BC + + data_dict["prob4"]["case2"]["fdm"]["temp_results"].append(solution) + + # Get fem temp results + data_dict["prob4"]["case2"]["fem"] = {} + data_dict["prob4"]["case2"]["fem"]["temp_results"] = [] + # num_point does not consider T(L). So "4" points is T0, T1, T2, T3, and then we add back T(L) + for num_point in data_dict["prob4"]["num_points"]: + fdm_array = case2.fem_array(num_point) + fdm_array_inverse = np.linalg.inv(fdm_array) + + right_array = case2.right_array(num_point) + + unkown_temps_array = fdm_array_inverse @ right_array + solution = [] + solution[0:] = unkown_temps_array + solution.append(100) # T(L) BC + + data_dict["prob4"]["case2"]["fem"]["temp_results"].append(solution) + + # We have all of the temperature results for varying dx for both fdm and fem + # For each dx, get the midpoint temperature from fdm and fem + results = [] + for i in range(len(data_dict["prob4"]["num_points"])): + a = 2.75 + num_points = data_dict["prob4"]["num_points"][i] + midpoint_index = int(num_points / 2) + t_fdm = data_dict["prob4"]["case2"]["fdm"]["temp_results"][i][midpoint_index] + t_fem = data_dict["prob4"]["case2"]["fem"]["temp_results"][i][midpoint_index] + + results.append([t_fdm, t_fem]) + + data_dict["prob4"]["case2"]["midpoint_temp_results"] = np.array(results) + data_dict["prob4"]["case2"]["midpoint_temp_true"] = case2.analytical(a = 2.75, x = 0.5) + + # Calculate % error and beta values for midpoint temperature + errors = [] + betas = [] + t_exact = data_dict["prob4"]["case2"]["midpoint_temp_true"] + t_results = data_dict["prob4"]["case2"]["midpoint_temp_results"] + + for i in range(0, len(t_results)): + # % Error calculation + t_fdm, t_fem = results[i] + fdm_error = common.calc_error(t_exact, t_fdm) + fem_error = common.calc_error(t_exact, t_fem) + + # Beta (convergence rate) calculation + if i != 0: + t_fdm_prev, t_fem_prev = results[i-1] + dx_1 = data_dict["prob4"]["dx_values"][i-1] + dx_2 = data_dict["prob4"]["dx_values"][i] + fdm_beta = common.calc_beta(t_exact, t_fdm, t_fdm_prev, dx_2, dx_1) + fem_beta = common.calc_beta(t_exact, t_fem, t_fem_prev, dx_2, dx_1) + else: + fdm_beta = 0 + fem_beta = 0 + + errors.append([fdm_error, fem_error]) + betas.append([fdm_beta, fem_beta]) + + data_dict["prob4"]["case2"]["temp_errors"] = errors + data_dict["prob4"]["case2"]["temp_betas"] = betas + + # Combine dx values, results, errors, and betas into a DataFrame for display + table_data = [] + for i in range(len(data_dict["prob4"]["dx_values"])): + table_data.append([ + results[i][0], # fdm result + results[i][1], # fem result + data_dict["prob4"]["case2"]["midpoint_temp_true"], # True T + errors[i][0], # fdm % error + errors[i][1], # fem % error + betas[i][0], # fdm beta + betas[i][1] # fem beta + ]) + + columns = ['FDM T', 'FEM T', 'True T', 'FDM % Error', 'FEM % Error', 'FDM β', 'FEM β'] + df_case2 = pd.DataFrame(table_data, index=[f'dx = {i}' for i in data_dict["prob4"]["dx_values"]], columns=columns) + + print("FDM and FEM Case 2 Midpoint Temperature Convergence Results:") + print(df_case2) + print("\n" * 2) + # Plotting + plt.figure(figsize=(8, 6)) + plt.plot(data_dict["prob4"]["dx_values"], [err[0] for err in data_dict["prob4"]["case2"]["temp_errors"]], label='FDM Temp Error') + plt.plot(data_dict["prob4"]["dx_values"], [err[1] for err in data_dict["prob4"]["case2"]["temp_errors"]], label='FEM Temp Error') + plt.xscale('log') + plt.yscale('log') + plt.xlabel('Δx') + plt.ylabel('% Error') + plt.legend() + plt.grid(True) + plt.savefig("prob4_case2_temp_convergence.png", dpi=300) + #plt.show() + plt.close() + + + + # For each dx, calculate the 2nd order heat flux for fdm and the heat flux for fem + results = [] + for i in range(len(data_dict["prob4"]["dx_values"])): + a = 2.75 + dx = data_dict["prob4"]["dx_values"][i] + (t_0_fdm, t_1_fdm) = data_dict["prob4"]["case2"]["fdm"]["temp_results"][i][-2:] + (t_0_fem, t_1_fem) = data_dict["prob4"]["case2"]["fem"]["temp_results"][i][-2:] + + fdm = common.taylor_extraction(t_0_fdm, t_1_fdm, dx, a, 2) + fem = common.fem_heat_extraction(t_0_fem, t_1_fem, dx, a) + results.append([fdm, fem]) + + data_dict["prob4"]["case2"]["heat_results"] = np.array(results) + data_dict["prob4"]["case2"]["heat_results_true"] = case2.analytical_heat_loss(a=2.75) + + # Calculate % error and beta values for heat loss + errors = [] + betas = [] + q_exact = data_dict["prob4"]["case2"]["heat_results_true"] + q_results = data_dict["prob4"]["case2"]["heat_results"] + + for i in range(0, len(q_results)): + # % Error calculation + q_fdm, q_fem = results[i] + fdm_error = common.calc_error(q_exact, q_fdm) + fem_error = common.calc_error(q_exact, q_fem) + + # Beta (convergence rate) calculation + if i != 0: + q_fdm_prev, q_fem_prev = results[i-1] + dx_1 = data_dict["prob4"]["dx_values"][i-1] + dx_2 = data_dict["prob4"]["dx_values"][i] + fdm_beta = common.calc_beta(q_exact, q_fdm, q_fdm_prev, dx_2, dx_1) + fem_beta = common.calc_beta(q_exact, q_fem, q_fem_prev, dx_2, dx_1) + else: + fdm_beta = 0 + fem_beta = 0 + + errors.append([fdm_error, fem_error]) + betas.append([fdm_beta, fem_beta]) + + data_dict["prob4"]["case2"]["heat_errors"] = errors + data_dict["prob4"]["case2"]["heat_betas"] = betas + + # Combine dx values, results, errors, and betas into a DataFrame for display + table_data = [] + for i in range(len(data_dict["prob4"]["dx_values"])): + table_data.append([ + results[i][0], # fdm result + results[i][1], # fem result + q_exact, # True Q + errors[i][0], # fdm % error + errors[i][1], # fem % error + betas[i][0], # fdm beta + betas[i][1] # fem beta + ]) + + columns = ['FDM Q', 'FEM Q', 'True Q', 'FDM % Error', 'FEM % Error', 'FDM β', 'FEM β'] + df_case2 = pd.DataFrame(table_data, index=[f'dx = {i}' for i in data_dict["prob4"]["dx_values"]], columns=columns) + + print("FDM and FEM Case 2 Heat Loss Convergence Results:") + print(df_case2) + print("\n" * 2) + + # Plotting + plt.figure(figsize=(8, 6)) + plt.plot(data_dict["prob4"]["dx_values"], [err[0] for err in data_dict["prob4"]["case2"]["heat_errors"]], label='FDM Heat Flux Error') + plt.plot(data_dict["prob4"]["dx_values"], [err[1] for err in data_dict["prob4"]["case2"]["heat_errors"]], label='FEM Heat Flux Error') + plt.xscale('log') + plt.yscale('log') + plt.xlabel('Δx') + plt.ylabel('% Error') + plt.legend() + plt.grid(True) + plt.savefig("prob4_case2_heat_convergence.png", dpi=300) + #plt.show() + plt.close() + + + +if __name__ == "__main__": + print("Homework 1 by Judson Upchurch") + print("Please note that some of the tables are transposed compared to the LaTeX equivalent") + print("") + + prob1() # Analyitical temperature distribution + + prob2() # FDM with dx = 0.125 and varying alpha + + prob3() # FEM with dx = 0.125 and varying alpha + + prob4() # Convergence analysis \ No newline at end of file diff --git a/HW3/Derivations.pdf b/HW3/Derivations.pdf index 64602d4..1af9c93 100644 Binary files a/HW3/Derivations.pdf and b/HW3/Derivations.pdf differ diff --git a/HW3/Judson_Upchurch_HW3.zip b/HW3/Judson_Upchurch_HW3.zip deleted file mode 100644 index 4cdb4a8..0000000 Binary files a/HW3/Judson_Upchurch_HW3.zip and /dev/null differ diff --git a/HW3/Judson_Upchurch_HW3/Judson_Upchurch_HW3.pdf b/HW3/Judson_Upchurch_HW3/Judson_Upchurch_HW3.pdf deleted file mode 100644 index 1c633a0..0000000 Binary files a/HW3/Judson_Upchurch_HW3/Judson_Upchurch_HW3.pdf and /dev/null differ diff --git a/HW3/Judson_Upchurch_HW3/case1.py b/HW3/Judson_Upchurch_HW3/case1.py deleted file mode 100644 index 4021a09..0000000 --- a/HW3/Judson_Upchurch_HW3/case1.py +++ /dev/null @@ -1,244 +0,0 @@ -# case1.py - -import numpy as np -import matplotlib.pyplot as plt - -from Bar import Bar, set_k_ratio - -def get_analytical_constants(bar1:'Bar', bar2:'Bar', x_bar=2/np.pi, l=1): - '''Solve for C1, D1, C2, and D2 - Returns np.array([C1, D1, C2, D2])''' - epsilon = (bar1.k*bar1.area*bar1.alpha) / (bar2.k*bar2.area*bar2.alpha) - A = np.array([ - #C1 D1 C2 D2 - [0, 1, 0, 0], - [0, 0, np.sinh(bar2.alpha*l), np.cosh(bar2.alpha*l)], - [np.sinh(bar1.alpha*x_bar), 0, -1*np.sinh(bar2.alpha*x_bar), -1*np.cosh(bar2.alpha*x_bar)], - [epsilon*np.cosh(bar1.alpha*x_bar), 0, -1*np.cosh(bar2.alpha*x_bar), -1*np.sinh(bar2.alpha*x_bar)] - ]) - - B = np.array([ - 0, - 100, - 0, - 0 - ]) - - return np.linalg.solve(A, B) - -def get_analytical_datapoints(x_points, bar1:'Bar', bar2:'Bar', x_bar=2/np.pi, l=1): - '''Generates the temperature distribution given x_points. - Returns np.array of tempature values''' - constants = get_analytical_constants(bar1=bar1,bar2=bar2,x_bar=x_bar,l=1) - C1, D1, C2, D2 = constants[0], constants[1], constants[2], constants[3] - - # Two temp functions for the left and right side of the interface - left_temp = lambda x: C1*np.sinh(bar1.alpha*x) + D1*np.cosh(bar1.alpha*x) - right_temp = lambda x: C2*np.sinh(bar2.alpha*x) + D2*np.cosh(bar2.alpha*x) - - temp_values = np.array([]) - for x in x_points: - if x <= x_bar: - temp = left_temp(x) - else: - temp = right_temp(x) - temp_values = np.append(temp_values, temp) - - return temp_values - -def get_analytical_heat_convection(x, bar1:'Bar', bar2:'Bar', x_bar=2/np.pi, l=1): - '''Gets the analytical heat convection at x from heat flux conservation''' - constants = get_analytical_constants(bar1=bar1,bar2=bar2,x_bar=x_bar,l=1) - C1, D1, C2, D2 = constants[0], constants[1], constants[2], constants[3] - - t_prime = C2*bar2.alpha*np.cosh(bar2.alpha*x) + D2*bar2.alpha*np.sinh(bar2.alpha*x) - - q_dot = -bar2.k*bar2.area*t_prime - return q_dot - -def fdm_array(bar1:'Bar', bar2:'Bar', num_sections: int=6, x_bar=2/np.pi, l=1): - '''num_sections = total sections to cut the bar. Note that this is NOT evenly distributed over the entire - bar. Half of the sections are left of x_bar, half are to the right. - Returns the A matrix of the FDM equation Ax = B''' - dx1 = x_bar / (num_sections / 2) - dx2 = (l - x_bar) / (num_sections / 2) - k1 = 2 + bar1.alpha**2 * dx1**2 - k2 = 2 + bar2.alpha**2 * dx2**2 - - beta1 = (bar1.k * bar1.area) / (dx1) - beta2 = (bar2.k * bar2.area) / (dx2) - - #rho = beta1 - beta2 - (bar1.k * bar1.area * dx1 * bar1.alpha**2) / 2 + (bar2.k * bar2.area * dx2 * bar2.alpha**2) / 2 - rho = beta1 + beta2 + (bar1.k * bar1.area * dx1 * bar1.alpha**2) / 2 + (bar2.k * bar2.area * dx2 * bar2.alpha**2) / 2 - # Making the matrix - # There are num_sections - 1 rows and columns - # row 0, row n - 2, and row num_sections/2 - 1 are unique - # the rest are -1, k, -1 where k changes from k1 to k2 at num_sections/2 - - # Initialize matrix A with zeros - A = np.zeros((num_sections - 1, num_sections - 1)) - - # Fill the matrix A - for row in range(num_sections - 1): - if row == 0: - # First row for boundary at x = 0 (for example Dirichlet or Neumann condition) - A[row, row] = k1 - A[row, row+1] = -1 - elif row == num_sections // 2 - 1: - # Special row at the interface between bar1 and bar2 - A[row, row-1] = -beta1 - A[row, row] = rho # This is the rho value you computed - A[row, row+1] = -beta2 - elif row == num_sections - 2: - # Last row for boundary at x = l (again assuming Dirichlet or Neumann condition) - A[row, row-1] = -1 - A[row, row] = k2 - else: - # Interior rows for bar1 and bar2 (uniform grid) - if row < num_sections // 2 - 1: - # In bar1 region - A[row, row-1] = -1 - A[row, row] = k1 - A[row, row+1] = -1 - else: - # In bar2 region - A[row, row-1] = -1 - A[row, row] = k2 - A[row, row+1] = -1 - return A - -def fem_array(bar1:'Bar', bar2:'Bar', num_sections: int=6, x_bar=2/np.pi, l=1): - '''num_sections = total sections to cut the bar. Note that this is NOT evenly distributed over the entire - bar. Half of the sections are left of x_bar, half are to the right. - Returns the A matrix of the FEM equation Ax = B''' - dx1 = x_bar / (num_sections / 2) - dx2 = (l - x_bar) / (num_sections / 2) - k1 = (2/dx1 + 4*bar1.alpha**2*dx1/6) / (1/dx1 - bar1.alpha**2*dx1/6) - k2 = (2/dx2 + 4*bar2.alpha**2*dx2/6) / (1/dx2 - bar2.alpha**2*dx2/6) - - beta1 = (bar1.k * bar1.area) / (dx1) - beta2 = (bar2.k * bar2.area) / (dx2) - - rho = beta1 + beta2 + (bar1.k * bar1.area * dx1 * bar1.alpha**2) / 2 + (bar2.k * bar2.area * dx2 * bar2.alpha**2) / 2 - # Making the matrix - # There are num_sections - 1 rows and columns - # row 0, row n - 2, and row num_sections/2 - 1 are unique - # the rest are -1, k, -1 where k changes from k1 to k2 at num_sections/2 - - # Initialize matrix A with zeros - A = np.zeros((num_sections - 1, num_sections - 1)) - - # Fill the matrix A - for row in range(num_sections - 1): - if row == 0: - # First row for boundary at x = 0 (for example Dirichlet or Neumann condition) - A[row, row] = k1 - A[row, row+1] = -1 - elif row == num_sections // 2 - 1: - # Special row at the interface between bar1 and bar2 - A[row, row-1] = -beta1 - A[row, row] = rho # This is the rho value you computed - A[row, row+1] = -beta2 - elif row == num_sections - 2: - # Last row for boundary at x = l (again assuming Dirichlet or Neumann condition) - A[row, row-1] = -1 - A[row, row] = k2 - else: - # Interior rows for bar1 and bar2 (uniform grid) - if row < num_sections // 2 - 1: - # In bar1 region - A[row, row-1] = -1 - A[row, row] = k1 - A[row, row+1] = -1 - else: - # In bar2 region - A[row, row-1] = -1 - A[row, row] = k2 - A[row, row+1] = -1 - return A - -def solve(bar1:'Bar', bar2:'Bar', num_sections: int=6, x_bar=2/np.pi, l=1, method="FDM"): - '''Solves using FDM or FEM as specified. Returns (temps, x_values)''' - if method == "FDM": - A = fdm_array(bar1, - bar2, - num_sections=num_sections, - x_bar=x_bar, - l=l) - elif method == "FEM": - A = fem_array(bar1, - bar2, - num_sections=num_sections, - x_bar=x_bar, - l=l) - - B = np.zeros((num_sections - 1)) - B[-1] = 100 - - # Add boundary conditions - interior_temps = np.linalg.solve(A, B) - all_temps = np.array([0]) - all_temps = np.append(all_temps, interior_temps) - all_temps = np.append(all_temps, 100) - - # Generate the x_values to return along with the temps - dx2 = (l - x_bar) / (num_sections / 2) - x_values = np.linspace(0, x_bar, num_sections // 2 + 1) # [0, x_bar] - x_values = np.append(x_values, np.linspace(x_bar+dx2, l, num_sections // 2)) - return all_temps, x_values - - -if __name__ == "__main__": - bar1 = Bar( - radius=0.1, - k=0.5, - h=0.25 - ) - bar2 = Bar( - radius=0.1, - k=2, - h=0.25 - ) - - set_k_ratio(0.5, bar1, bar2) - - x_bar = 0.5 - - x_values = np.linspace(0, 1, 1000) - temp_values = get_analytical_datapoints(x_points=x_values, - bar1=bar1, - bar2=bar2, - x_bar=x_bar) - - - # fdm tests - l = 1 - num_sections = 4 - dx1 = x_bar / (num_sections / 2) - dx2 = (l - x_bar) / (num_sections / 2) - fdm_temps, x_fdm = solve(bar1=bar1, - bar2=bar2, - num_sections=num_sections, - x_bar=x_bar, - l=1, - method="FDM") - fem_temps, x_fem = solve(bar1=bar1, - bar2=bar2, - num_sections=num_sections, - x_bar=x_bar, - l=1, - method="FEM") - - # Plot the data - plt.plot(x_values, temp_values, label='Temperature Distribution') - plt.axvline(x=x_bar, color='r', linestyle='--', label='x_bar') - plt.plot(x_fdm, fdm_temps, 'o-', label='Temperature Distribution (FDM)', color='g') - plt.plot(x_fem, fem_temps, 'o-', label='Temperature Distribution (FEM)', color='r') - plt.xlabel('x') - plt.ylabel('Temperature') - plt.title('Temperature Distribution Along the Bar') - plt.legend() - plt.grid(True) - - # Show plot - plt.show() \ No newline at end of file diff --git a/HW3/Judson_Upchurch_HW3/case2.py b/HW3/Judson_Upchurch_HW3/case2.py deleted file mode 100644 index 5231180..0000000 --- a/HW3/Judson_Upchurch_HW3/case2.py +++ /dev/null @@ -1,230 +0,0 @@ -# case2.py - -import numpy as np -import matplotlib.pyplot as plt - -from Bar import Bar - -def get_analytical_constants(bar1:'Bar', bar2:'Bar', x_bar=2/np.pi, l=1): - '''Solve for C1, D1, C2, and D2 - Returns np.array([C1, D1, C2, D2])''' - epsilon = (bar1.k*bar1.area*bar1.alpha) / (bar2.k*bar2.area*bar2.alpha) - A = np.array([ - #C1 D1 C2 D2 - [1, 0, 0, 0], - [0, 0, np.sinh(bar2.alpha*l), np.cosh(bar2.alpha*l)], - [0, np.cosh(bar1.alpha*x_bar), -1*np.sinh(bar2.alpha*x_bar), -1*np.cosh(bar2.alpha*x_bar)], - [0, epsilon*np.sinh(bar1.alpha*x_bar), -1*np.cosh(bar2.alpha*x_bar), -1*np.sinh(bar2.alpha*x_bar)] - ]) - - B = np.array([ - 0, - 100, - 0, - 0 - ]) - - return np.linalg.solve(A, B) - -def get_analytical_datapoints(x_points, bar1:'Bar', bar2:'Bar', x_bar=2/np.pi, l=1): - '''Generates the temperature distribution given x_points. - Returns np.array of tempature values''' - constants = get_analytical_constants(bar1=bar1,bar2=bar2,x_bar=x_bar,l=1) - C1, D1, C2, D2 = constants[0], constants[1], constants[2], constants[3] - - # Two temp functions for the left and right side of the interface - left_temp = lambda x: C1*np.sinh(bar1.alpha*x) + D1*np.cosh(bar1.alpha*x) - right_temp = lambda x: C2*np.sinh(bar2.alpha*x) + D2*np.cosh(bar2.alpha*x) - - temp_values = np.array([]) - for x in x_points: - if x <= x_bar: - temp = left_temp(x) - else: - temp = right_temp(x) - temp_values = np.append(temp_values, temp) - - return temp_values - -def fdm_array(bar1:'Bar', bar2:'Bar', num_sections: int=6, x_bar=2/np.pi, l=1): - '''num_sections = total sections to cut the bar. Note that this is NOT evenly distributed over the entire - bar. Half of the sections are left of x_bar, half are to the right. - Returns the A matrix of the FDM equation Ax = B''' - dx1 = x_bar / (num_sections / 2) - dx2 = (l - x_bar) / (num_sections / 2) - k1 = 2 + bar1.alpha**2 * dx1**2 - k2 = 2 + bar2.alpha**2 * dx2**2 - k1_prime = k1/2 - - beta1 = (bar1.k * bar1.area) / (dx1) - beta2 = (bar2.k * bar2.area) / (dx2) - - #rho = beta1 - beta2 - (bar1.k * bar1.area * dx1 * bar1.alpha**2) / 2 + (bar2.k * bar2.area * dx2 * bar2.alpha**2) / 2 - rho = beta1 + beta2 + (bar1.k * bar1.area * dx1 * bar1.alpha**2) / 2 + (bar2.k * bar2.area * dx2 * bar2.alpha**2) / 2 - # Making the matrix - # There are num_sections rows and columns - # row 0, row n - 2, and row num_sections/2 are unique - # the rest are -1, k, -1 where k changes from k1 to k2 at num_sections/2 - - # Initialize matrix A with zeros - A = np.zeros((num_sections, num_sections)) - - # Fill the matrix A - for row in range(num_sections): - if row == 0: - # First row for boundary at x = 0 ( Neumann condition) - A[row, row] = k1_prime - A[row, row+1] = -1 - elif row == num_sections // 2: - # Special row at the interface between bar1 and bar2 - A[row, row-1] = -beta1 - A[row, row] = rho # This is the rho value you computed - A[row, row+1] = -beta2 - elif row == num_sections - 1: - # Last row for boundary at x = l (again assuming Dirichlet) - A[row, row-1] = -1 - A[row, row] = k2 - else: - # Interior rows for bar1 and bar2 (uniform grid) - if row < num_sections // 2 - 1: - # In bar1 region - A[row, row-1] = -1 - A[row, row] = k1 - A[row, row+1] = -1 - else: - # In bar2 region - A[row, row-1] = -1 - A[row, row] = k2 - A[row, row+1] = -1 - return A - -def fem_array(bar1:'Bar', bar2:'Bar', num_sections: int=6, x_bar=2/np.pi, l=1): - '''num_sections = total sections to cut the bar. Note that this is NOT evenly distributed over the entire - bar. Half of the sections are left of x_bar, half are to the right. - Returns the A matrix of the FDM equation Ax = B''' - dx1 = x_bar / (num_sections / 2) - dx2 = (l - x_bar) / (num_sections / 2) - k1 = (2/dx1 + 4*bar1.alpha**2*dx1/6) / (1/dx1 - bar1.alpha**2*dx1/6) - k2 = (2/dx2 + 4*bar2.alpha**2*dx2/6) / (1/dx2 - bar2.alpha**2*dx2/6) - k1_prime = k1/2 - - beta1 = (bar1.k * bar1.area) / (dx1) - beta2 = (bar2.k * bar2.area) / (dx2) - - #rho = beta1 - beta2 - (bar1.k * bar1.area * dx1 * bar1.alpha**2) / 2 + (bar2.k * bar2.area * dx2 * bar2.alpha**2) / 2 - rho = beta1 + beta2 + (bar1.k * bar1.area * dx1 * bar1.alpha**2) / 2 + (bar2.k * bar2.area * dx2 * bar2.alpha**2) / 2 - # Making the matrix - # There are num_sections rows and columns - # row 0, row n - 2, and row num_sections/2 are unique - # the rest are -1, k, -1 where k changes from k1 to k2 at num_sections/2 - - # Initialize matrix A with zeros - A = np.zeros((num_sections, num_sections)) - - # Fill the matrix A - for row in range(num_sections): - if row == 0: - # First row for boundary at x = 0 ( Neumann condition) - A[row, row] = k1_prime - A[row, row+1] = -1 - elif row == num_sections // 2: - # Special row at the interface between bar1 and bar2 - A[row, row-1] = -beta1 - A[row, row] = rho # This is the rho value you computed - A[row, row+1] = -beta2 - elif row == num_sections - 1: - # Last row for boundary at x = l (again assuming Dirichlet) - A[row, row-1] = -1 - A[row, row] = k2 - else: - # Interior rows for bar1 and bar2 (uniform grid) - if row < num_sections // 2 - 1: - # In bar1 region - A[row, row-1] = -1 - A[row, row] = k1 - A[row, row+1] = -1 - else: - # In bar2 region - A[row, row-1] = -1 - A[row, row] = k2 - A[row, row+1] = -1 - return A - -def solve(bar1:'Bar', bar2:'Bar', num_sections: int=6, x_bar=2/np.pi, l=1, method="FDM"): - if method == "FDM": - A = fdm_array(bar1, - bar2, - num_sections=num_sections, - x_bar=x_bar, - l=l) - elif method == "FEM": - A = fem_array(bar1, - bar2, - num_sections=num_sections, - x_bar=x_bar, - l=l) - - B = np.zeros((num_sections)) - B[-1] = 100 - - # Append the boundary condition - interior_temps = np.linalg.solve(A, B) - all_temps = np.append(interior_temps, 100) - - # Generate the x_values to return along with the temps - dx2 = (l - x_bar) / (num_sections / 2) - x_values = np.linspace(0, x_bar, num_sections // 2 + 1) # [0, x_bar] - x_values = np.append(x_values, np.linspace(x_bar+dx2, l, num_sections // 2)) - return all_temps, x_values - - -if __name__ == "__main__": - bar1 = Bar( - radius=0.1, - k=0.5, - h=0.25 - ) - bar2 = Bar( - radius=0.1, - k=2, - h=0.25 - ) - - x_bar = 2/np.pi - - - x_values = np.linspace(0, 1, 1000) - temp_values = get_analytical_datapoints(x_points=x_values, - bar1=bar1, - bar2=bar2) - - - # fdm tests - l = 1 - num_sections = 6 - fdm_temps, x_fdm = solve(bar1=bar1, - bar2=bar2, - num_sections=num_sections, - x_bar=x_bar, - l=1, - method="FDM") - fem_temps, x_fem = solve(bar1=bar1, - bar2=bar2, - num_sections=num_sections, - x_bar=x_bar, - l=1, - method="FEM") - - # Plot the data - plt.plot(x_values, temp_values, label='Temperature Distribution') - plt.axvline(x=x_bar, color='r', linestyle='--', label='x_bar') - plt.plot(x_fdm, fdm_temps, 'o-', label='Temperature Distribution (FDM)', color='g') - plt.plot(x_fem, fem_temps, 'o-', label='Temperature Distribution (FEM)', color='r') - plt.xlabel('x') - plt.ylabel('Temperature') - plt.title('Temperature Distribution Along the Bar') - plt.legend() - plt.grid(True) - - # Show plot - plt.show() \ No newline at end of file diff --git a/HW3/Judson_Upchurch_HW3/common.py b/HW3/Judson_Upchurch_HW3/common.py deleted file mode 100644 index bb54345..0000000 --- a/HW3/Judson_Upchurch_HW3/common.py +++ /dev/null @@ -1,30 +0,0 @@ -# common.py - -import numpy as np -from Bar import Bar - -def fdm_heat_extraction(t_0, t_1, dx, bar:'Bar', order=2): - '''Get the heat conduction at the point t_1 using Taylor series''' - if order == 1: - return -1 * bar.k * bar.area * (t_1 - t_0) / dx - elif order == 2: - return -1 * bar.k * bar.area * (((t_1 - t_0) / dx) + (bar.alpha**2 * dx * t_1 / 2)) - -def fem_heat_extraction(t_0, t_1, dx, bar:'Bar'): - '''Get the heat conduction at the point t_1 using FEM equation''' - term_1 = (-1/dx + bar.alpha**2*dx/6) * t_0 - term_2 = (1/dx + 2*bar.alpha**2*dx/6) * t_1 - return -1 * bar.k * bar.area * (term_1 + term_2) - -def calc_error(exact, q_1): - return np.abs((exact - q_1) / exact) - -def calc_beta(exact, q_1, q_2, dx_1, dx_2): - return np.log(np.abs((exact - q_1)/(exact - q_2))) / np.log(dx_1 / dx_2) - -def calc_extrapolated(q1, q2, q3): - '''Calcs the Richardson Extrapolation value based on 3 different meshes. - Assumes that q3 is 2x finer than q2 is 2x finer than q1''' - numerator = q1*q3 - q2**2 - denominator = q1 + q3 - 2*q2 - return numerator / denominator \ No newline at end of file diff --git a/HW3/Judson_Upchurch_HW3/constants.py b/HW3/Judson_Upchurch_HW3/constants.py deleted file mode 100644 index 5248508..0000000 --- a/HW3/Judson_Upchurch_HW3/constants.py +++ /dev/null @@ -1,19 +0,0 @@ -from numpy import pi - -h = 0.0025 # W / cm^2*K - -class Bar1(): - def __init__(self): - self.k = 0.5 # W / cm*K - self.r = 0.1 # cm - self.A = pi*self.r**2 # cm^2 - self.P = 2*pi*self.r # cm - -class Bar2(): - def __init__(self): - self.k = 0.5 # W / cm*K - self.r = 0.1 # cm - self.A = pi*self.r**2 # cm^2 - self.P = 2*pi*self.r # cm - - self.alpha = ((h*self.P)/(self.k*self.A))**0.5 \ No newline at end of file diff --git a/HW3/Judson_Upchurch_HW3/images/section2/x_bar_1/heat_convection_vs_k_ratio.png b/HW3/Judson_Upchurch_HW3/images/section2/x_bar_1/heat_convection_vs_k_ratio.png deleted file mode 100644 index 77c2a96..0000000 Binary files a/HW3/Judson_Upchurch_HW3/images/section2/x_bar_1/heat_convection_vs_k_ratio.png and /dev/null differ diff --git a/HW3/Judson_Upchurch_HW3/images/section2/x_bar_2/heat_convection_vs_k_ratio.png b/HW3/Judson_Upchurch_HW3/images/section2/x_bar_2/heat_convection_vs_k_ratio.png deleted file mode 100644 index d040ec3..0000000 Binary files a/HW3/Judson_Upchurch_HW3/images/section2/x_bar_2/heat_convection_vs_k_ratio.png and /dev/null differ diff --git a/HW3/Judson_Upchurch_HW3/images/section3/x_bar_1/heat_convergences.png b/HW3/Judson_Upchurch_HW3/images/section3/x_bar_1/heat_convergences.png deleted file mode 100644 index fa8bcdd..0000000 Binary files a/HW3/Judson_Upchurch_HW3/images/section3/x_bar_1/heat_convergences.png and /dev/null differ diff --git a/HW3/Judson_Upchurch_HW3/images/section3/x_bar_1/temp_convergences.png b/HW3/Judson_Upchurch_HW3/images/section3/x_bar_1/temp_convergences.png deleted file mode 100644 index 1e47f92..0000000 Binary files a/HW3/Judson_Upchurch_HW3/images/section3/x_bar_1/temp_convergences.png and /dev/null differ diff --git a/HW3/Judson_Upchurch_HW3/images/section3/x_bar_2/heat_convergences.png b/HW3/Judson_Upchurch_HW3/images/section3/x_bar_2/heat_convergences.png deleted file mode 100644 index 78613b6..0000000 Binary files a/HW3/Judson_Upchurch_HW3/images/section3/x_bar_2/heat_convergences.png and /dev/null differ diff --git a/HW3/Judson_Upchurch_HW3/images/section3/x_bar_2/temp_convergences.png b/HW3/Judson_Upchurch_HW3/images/section3/x_bar_2/temp_convergences.png deleted file mode 100644 index 3aa08aa..0000000 Binary files a/HW3/Judson_Upchurch_HW3/images/section3/x_bar_2/temp_convergences.png and /dev/null differ diff --git a/HW3/Judson_Upchurch_HW3/main.py b/HW3/Judson_Upchurch_HW3/main.py deleted file mode 100644 index e36efe4..0000000 --- a/HW3/Judson_Upchurch_HW3/main.py +++ /dev/null @@ -1,722 +0,0 @@ -# main.py - -import numpy as np -import pandas as pd -import matplotlib.pyplot as plt -import math - -import case1 -import case2 -import common -import Bar - - -bar1 = Bar.Bar( - radius=0.1, - k=0.5, - h=0.25 -) -bar2 = Bar.Bar( - radius=0.1, - k=2, - h=0.25 -) - -data_dict = {} -data_dict["k_ratios"] = np.array([1/16, 1/8, 1/4, 1/2, 1, 2, 4, 8, 16]) -data_dict["x_bar_values"] = np.array([1/2, 2/np.pi]) -data_dict["length"] = 1 - -def section_1(): - '''Analytical solutions with varying k_ratio''' - print("Section 1: Analytical") - - l = data_dict["length"] - - # Calculate the results for every k ratio for x_bar_1 - x_bar_1 = data_dict["x_bar_values"][0] - - data_dict["section1"] = {} - data_dict["section1"]["x_bar_1"] = {} - data_dict["section1"]["x_bar_1"]["x_values_fine"] = np.linspace(0, l, 50) - data_dict["section1"]["x_bar_1"]["x_values_fine"] = np.sort(np.append(data_dict["section1"]["x_bar_1"]["x_values_fine"], x_bar_1)) - data_dict["section1"]["x_bar_1"]["x_values_course"] = np.linspace(0, l, 9) - data_dict["section1"]["x_bar_1"]["x_values_course"] = np.sort(np.append(data_dict["section1"]["x_bar_1"]["x_values_course"], x_bar_1)) - - results = [] - results_course = [] - for k_ratio in data_dict["k_ratios"]: - Bar.set_k_ratio(k_ratio, bar1, bar2) # Set the k value of bar2 = k*bar1 - result = case1.get_analytical_datapoints(data_dict["section1"]["x_bar_1"]["x_values_fine"], - bar1=bar1, - bar2=bar2, - x_bar=x_bar_1, - l=l) - result_course = case1.get_analytical_datapoints(data_dict["section1"]["x_bar_1"]["x_values_course"], - bar1=bar1, - bar2=bar2, - x_bar=x_bar_1, - l=l) - results.append(result) - results_course.append(result_course) - - data_dict["section1"]["x_bar_1"]["temp_results"] = np.array(results) - - df_x_bar_1 = pd.DataFrame(results_course, index=[f'k2/k1 = {a}' for a in data_dict["k_ratios"]], columns=[f'x = {x:.3f}' for x in data_dict["section1"]["x_bar_1"]["x_values_course"]]) - - print("Analytical Temperature Results x_bar = 0.5:") - print(df_x_bar_1.to_string()) - print("\n" * 2) - - # Plotting x_bar_1 - plt.figure(figsize=(10, 6)) - for idx, k_ratio in enumerate(data_dict["k_ratios"]): - plt.plot(data_dict["section1"]["x_bar_1"]["x_values_fine"], data_dict["section1"]["x_bar_1"]["temp_results"][idx], label=f'k2/k1 = {k_ratio}') - plt.axvline(x=x_bar_1, color='r', linestyle='--', label='x_bar') - plt.xlabel('Position (cm)') - plt.ylabel('Temperature (°C)') - plt.legend() - plt.grid(True) - plt.savefig('images/section1/x_bar_1/analytical_temperature_vs_position.png', dpi=300) - #plt.show() - plt.clf() - - # Calculate the temperature results for every k ratio for x_bar_1 - x_bar_2 = data_dict["x_bar_values"][1] - - data_dict["section1"]["x_bar_2"] = {} - data_dict["section1"]["x_bar_2"]["x_values_fine"] = np.linspace(0, l, 50) - data_dict["section1"]["x_bar_2"]["x_values_fine"] = np.sort(np.append(data_dict["section1"]["x_bar_2"]["x_values_fine"], x_bar_2)) - data_dict["section1"]["x_bar_2"]["x_values_course"] = np.linspace(0, l, 9) - data_dict["section1"]["x_bar_2"]["x_values_course"] = np.sort(np.append(data_dict["section1"]["x_bar_2"]["x_values_course"], x_bar_2)) - - results = [] - results_course = [] - for k_ratio in data_dict["k_ratios"]: - Bar.set_k_ratio(k_ratio, bar1, bar2) - result = case1.get_analytical_datapoints(data_dict["section1"]["x_bar_2"]["x_values_fine"], - bar1=bar1, - bar2=bar2, - x_bar=x_bar_2, - l=l) - result_course = case1.get_analytical_datapoints(data_dict["section1"]["x_bar_2"]["x_values_course"], - bar1=bar1, - bar2=bar2, - x_bar=x_bar_2, - l=l) - results.append(result) - results_course.append(result_course) - - data_dict["section1"]["x_bar_2"]["temp_results"] = np.array(results) - - df_x_bar_2 = pd.DataFrame(results_course, index=[f'k2/k1 = {a}' for a in data_dict["k_ratios"]], columns=[f'x = {x:.3f}' for x in data_dict["section1"]["x_bar_2"]["x_values_course"]]) - - print("Analytical Temperature Results x_bar = 2/pi:") - print(df_x_bar_2.to_string()) - print("\n" * 2) - - # Plotting x_bar_2 - plt.figure(figsize=(10, 6)) - for idx, k_ratio in enumerate(data_dict["k_ratios"]): - plt.plot(data_dict["section1"]["x_bar_2"]["x_values_fine"], data_dict["section1"]["x_bar_2"]["temp_results"][idx], label=f'k2/k1 = {k_ratio}') - plt.axvline(x=x_bar_2, color='r', linestyle='--', label='x_bar') - plt.xlabel('Position (cm)') - plt.ylabel('Temperature (°C)') - plt.legend() - plt.grid(True) - plt.savefig('images/section1/x_bar_2/analytical_temperature_vs_position.png', dpi=300) - #plt.show() - plt.clf() - - - - # Calculate the analytical heat convection leaving the rod at x=l for varying k ratio - - results_1 = [] - results_2 = [] - for k_ratio in data_dict["k_ratios"]: - Bar.set_k_ratio(k_ratio, bar1, bar2) - result_1 = case1.get_analytical_heat_convection(x=l, - bar1=bar1, - bar2=bar2, - x_bar=x_bar_1, - l=l) - result_2 = case1.get_analytical_heat_convection(x=l, - bar1=bar1, - bar2=bar2, - x_bar=x_bar_2, - l=l) - results_1.append([result_1]) - results_2.append([result_2]) - - data_dict["section1"]["x_bar_1"]["heat_results"] = np.array(results_1) - data_dict["section1"]["x_bar_2"]["heat_results"] = np.array(results_2) - - df_x_bar_1 = pd.DataFrame(results_1, index=[f'k2/k1 = {a}' for a in data_dict["k_ratios"]], columns=["Heat Convection"]) - df_x_bar_2 = pd.DataFrame(results_2, index=[f'k2/k1 = {a}' for a in data_dict["k_ratios"]], columns=["Heat Convection"]) - - print("Analytical Heat Convection Results x_bar = 0.5:") - print(df_x_bar_1.to_string()) - print("\n" * 2) - - print("Analytical Heat Convection Results x_bar = 2/pi:") - print(df_x_bar_2.to_string()) - print("\n" * 2) - - # Plotting x_bar_1 heat convection - plt.figure(figsize=(10, 6)) - plt.plot(data_dict["k_ratios"], data_dict["section1"]["x_bar_1"]["heat_results"], label=f'Heat Convection') - plt.xlabel('k2/k1') - plt.ylabel('Q_Dot (W)') - plt.legend() - plt.grid(True) - plt.savefig('images/section1/x_bar_1/analytical_heat_convection_vs_k_ratio.png', dpi=300) - #plt.show() - plt.clf() - - # Plotting x_bar_2 heat convection - plt.figure(figsize=(10, 6)) - plt.plot(data_dict["k_ratios"], data_dict["section1"]["x_bar_2"]["heat_results"], label=f'Heat Convection') - plt.xlabel('k2/k1') - plt.ylabel('Q_Dot (W)') - plt.legend() - plt.grid(True) - plt.savefig('images/section1/x_bar_2/analytical_heat_convection_vs_k_ratio.png', dpi=300) - #plt.show() - plt.clf() - - -def section_2(): - '''FDM and FEM with varying k_ratio''' - print("Section 2: FDM and FEM with Varying k_ratio") - - l = data_dict["length"] - - data_dict["section2"] = {} - data_dict["section2"]["num_sections"] = 8 - - - # Calculate the results for every k ratio for x_bar_1 - x_bar_1 = data_dict["x_bar_values"][0] - - # For every k_ratio, calculate the FDM and FEM temperature results - fdm_results = [] - fem_results = [] - x_fdm = [] - x_fem = [] - for k_ratio in data_dict["k_ratios"]: - Bar.set_k_ratio(k_ratio, bar1, bar2) # Set the k value of bar2 = k*bar1 - fdm_temps, x_fdm = case1.solve(bar1=bar1, - bar2=bar2, - num_sections=data_dict["section2"]["num_sections"], - x_bar=x_bar_1, - l=l, - method="FDM") - fem_temps, x_fem = case1.solve(bar1=bar1, - bar2=bar2, - num_sections=data_dict["section2"]["num_sections"], - x_bar=x_bar_1, - l=l, - method="FEM") - - fdm_results.append(fdm_temps) - fem_results.append(fem_temps) - - data_dict["section2"]["x_bar_1"] = {} - data_dict["section2"]["x_bar_1"]["x_values"] = x_fdm # fdm and fem use same x_values - data_dict["section2"]["x_bar_1"]["fdm_results"] = np.array(fdm_results) - data_dict["section2"]["x_bar_1"]["fem_results"] = np.array(fem_results) - - df_fdm = pd.DataFrame(fdm_results, index=[f'k2/k1 = {a}' for a in data_dict["k_ratios"]], columns=[f'x = {x:.3f}' for x in x_fdm]) - df_fem = pd.DataFrame(fem_results, index=[f'k2/k1 = {a}' for a in data_dict["k_ratios"]], columns=[f'x = {x:.3f}' for x in x_fem]) - - print("FDM Temperature Results x_bar = 0.5:") - print(df_fdm.to_string()) - print("\n" * 2) - print("FEM Temperature Results x_bar = 0.5:") - print(df_fem.to_string()) - print("\n" * 2) - - # Now that the data is gathered for FDM and FEM, plot it - # Plotting x_bar_1, FDM - plt.figure(figsize=(10, 6)) - for idx, k_ratio in enumerate(data_dict["k_ratios"]): - plt.plot(data_dict["section2"]["x_bar_1"]["x_values"], data_dict["section2"]["x_bar_1"]["fdm_results"][idx], label=f'k2/k1 = {k_ratio}') - plt.axvline(x=x_bar_1, color='r', linestyle='--', label='x_bar') - plt.xlabel('Position (cm)') - plt.ylabel('Temperature (°C)') - plt.legend() - plt.grid(True) - plt.savefig('images/section2/x_bar_1/fdm_temperature_vs_position.png', dpi=300) - #plt.show() - plt.clf() - - # Plotting x_bar_1, FEM - plt.figure(figsize=(10, 6)) - for idx, k_ratio in enumerate(data_dict["k_ratios"]): - plt.plot(data_dict["section2"]["x_bar_1"]["x_values"], data_dict["section2"]["x_bar_1"]["fem_results"][idx], label=f'k2/k1 = {k_ratio}') - plt.axvline(x=x_bar_1, color='r', linestyle='--', label='x_bar') - plt.xlabel('Position (cm)') - plt.ylabel('Temperature (°C)') - plt.legend() - plt.grid(True) - plt.savefig('images/section2/x_bar_1/fem_temperature_vs_position.png', dpi=300) - #plt.show() - plt.clf() - - - # Calculate the results for every k ratio for x_bar_2 - x_bar_2 = data_dict["x_bar_values"][1] - - # For every k_ratio, calculate the FDM and FEM temperature results - fdm_results = [] - fem_results = [] - x_fdm = [] - x_fem = [] - for k_ratio in data_dict["k_ratios"]: - Bar.set_k_ratio(k_ratio, bar1, bar2) # Set the k value of bar2 = k*bar1 - fdm_temps, x_fdm = case1.solve(bar1=bar1, - bar2=bar2, - num_sections=data_dict["section2"]["num_sections"], - x_bar=x_bar_2, - l=l, - method="FDM") - fem_temps, x_fem = case1.solve(bar1=bar1, - bar2=bar2, - num_sections=data_dict["section2"]["num_sections"], - x_bar=x_bar_2, - l=l, - method="FEM") - - fdm_results.append(fdm_temps) - fem_results.append(fem_temps) - - data_dict["section2"]["x_bar_2"] = {} - data_dict["section2"]["x_bar_2"]["x_values"] = x_fdm # fdm and fem use same x_values - data_dict["section2"]["x_bar_2"]["fdm_results"] = np.array(fdm_results) - data_dict["section2"]["x_bar_2"]["fem_results"] = np.array(fem_results) - - df_fdm = pd.DataFrame(fdm_results, index=[f'k2/k1 = {a}' for a in data_dict["k_ratios"]], columns=[f'x = {x:.3f}' for x in x_fdm]) - df_fem = pd.DataFrame(fem_results, index=[f'k2/k1 = {a}' for a in data_dict["k_ratios"]], columns=[f'x = {x:.3f}' for x in x_fem]) - - print("FDM Temperature Results x_bar = 2/pi:") - print(df_fdm.to_string()) - print("\n" * 2) - print("FEM Temperature Results x_bar = 2/pi:") - print(df_fem.to_string()) - print("\n" * 2) - - # Plotting x_bar_2, FDM - plt.figure(figsize=(10, 6)) - for idx, k_ratio in enumerate(data_dict["k_ratios"]): - plt.plot(data_dict["section2"]["x_bar_2"]["x_values"], data_dict["section2"]["x_bar_2"]["fdm_results"][idx], label=f'k2/k1 = {k_ratio}') - plt.axvline(x=x_bar_2, color='r', linestyle='--', label='x_bar') - plt.xlabel('Position (cm)') - plt.ylabel('Temperature (°C)') - plt.legend() - plt.grid(True) - plt.savefig('images/section2/x_bar_2/fdm_temperature_vs_position.png', dpi=300) - #plt.show() - plt.clf() - - # Plotting x_bar_2, FEM - plt.figure(figsize=(10, 6)) - for idx, k_ratio in enumerate(data_dict["k_ratios"]): - plt.plot(data_dict["section2"]["x_bar_2"]["x_values"], data_dict["section2"]["x_bar_2"]["fem_results"][idx], label=f'k2/k1 = {k_ratio}') - plt.axvline(x=x_bar_2, color='r', linestyle='--', label='x_bar') - plt.xlabel('Position (cm)') - plt.ylabel('Temperature (°C)') - plt.legend() - plt.grid(True) - plt.savefig('images/section2/x_bar_2/fem_temperature_vs_position.png', dpi=300) - #plt.show() - plt.clf() - - - - # After calculating temperature values, extract the heat convection at x=l - - # x_bar_1 - # for every k ratio, calculate the heat convection from fdm and fem temp results - fdm_heat_results = [] - fem_heat_results = [] - for i, k_ratio in enumerate(data_dict["k_ratios"]): - Bar.set_k_ratio(k_ratio, bar1, bar2) # Set the k value of bar2 = k*bar1 - dx = data_dict["section2"]["x_bar_1"]["x_values"][-1] - data_dict["section2"]["x_bar_1"]["x_values"][-2] - (fdm_t0, fdm_t1) = data_dict["section2"]["x_bar_1"]["fdm_results"][i][-2:] - fdm_heat_result = common.fdm_heat_extraction(fdm_t0, fdm_t1, dx, bar2, order=2) - fdm_heat_results.append(fdm_heat_result) - - (fem_t0, fem_t1) = data_dict["section2"]["x_bar_1"]["fem_results"][i][-2:] - fem_heat_result = common.fem_heat_extraction(fem_t0, fem_t1, dx, bar2) - fem_heat_results.append(fem_heat_result) - - - data_dict["section2"]["x_bar_1"]["fdm_heat_results"] = np.array(fdm_heat_results) - data_dict["section2"]["x_bar_1"]["fem_heat_results"] = np.array(fem_heat_results) - - df_fdm = pd.DataFrame(fdm_heat_results, index=[f'k2/k1 = {a}' for a in data_dict["k_ratios"]], columns=["Heat Convection"]) - df_fem = pd.DataFrame(fem_heat_results, index=[f'k2/k1 = {a}' for a in data_dict["k_ratios"]], columns=["Heat Convection"]) - - print("FDM Heat Convection Results x_bar = 0.5:") - print(df_fdm.to_string()) - print("\n" * 2) - - print("FEM Heat Convection Results x_bar = 0.5:") - print(df_fem.to_string()) - print("\n" * 2) - - # x_bar_2 - # for every k ratio, calculate the heat convection from fdm and fem temp results - fdm_heat_results = [] - fem_heat_results = [] - for i, k_ratio in enumerate(data_dict["k_ratios"]): - Bar.set_k_ratio(k_ratio, bar1, bar2) # Set the k value of bar2 = k*bar1 - dx = data_dict["section2"]["x_bar_2"]["x_values"][-1] - data_dict["section2"]["x_bar_2"]["x_values"][-2] - (fdm_t0, fdm_t1) = data_dict["section2"]["x_bar_2"]["fdm_results"][i][-2:] - fdm_heat_result = common.fdm_heat_extraction(fdm_t0, fdm_t1, dx, bar2, order=2) - fdm_heat_results.append(fdm_heat_result) - - (fem_t0, fem_t1) = data_dict["section2"]["x_bar_2"]["fem_results"][i][-2:] - fem_heat_result = common.fem_heat_extraction(fem_t0, fem_t1, dx, bar2) - fem_heat_results.append(fem_heat_result) - - - data_dict["section2"]["x_bar_2"]["fdm_heat_results"] = np.array(fdm_heat_results) - data_dict["section2"]["x_bar_2"]["fem_heat_results"] = np.array(fem_heat_results) - - df_fdm = pd.DataFrame(fdm_heat_results, index=[f'k2/k1 = {a}' for a in data_dict["k_ratios"]], columns=["Heat Convection"]) - df_fem = pd.DataFrame(fem_heat_results, index=[f'k2/k1 = {a}' for a in data_dict["k_ratios"]], columns=["Heat Convection"]) - - print("FDM Heat Convection Results x_bar = 2/pi:") - print(df_fdm.to_string()) - print("\n" * 2) - - print("FEM Heat Convection Results x_bar = 2/pi:") - print(df_fem.to_string()) - print("\n" * 2) - - # Plotting x_bar_1 heat convection - plt.figure(figsize=(10, 6)) - plt.plot(data_dict["k_ratios"], data_dict["section2"]["x_bar_1"]["fdm_heat_results"], label=f'FDM Heat Convection') - plt.plot(data_dict["k_ratios"], data_dict["section2"]["x_bar_1"]["fem_heat_results"], label=f'FEM Heat Convection') - #plt.plot(data_dict["k_ratios"], data_dict["section1"]["x_bar_1"]["heat_results"], label=f'Analytical Heat Convection') - plt.xlabel('k2/k1') - plt.ylabel('Q_Dot (W)') - plt.legend() - plt.grid(True) - plt.savefig('images/section2/x_bar_1/heat_convection_vs_k_ratio.png', dpi=300) - #plt.show() - plt.clf() - - # Plotting x_bar_2 heat convection - plt.figure(figsize=(10, 6)) - plt.plot(data_dict["k_ratios"], data_dict["section2"]["x_bar_2"]["fdm_heat_results"], label=f'FDM Heat Convection') - plt.plot(data_dict["k_ratios"], data_dict["section2"]["x_bar_2"]["fem_heat_results"], label=f'FEM Heat Convection') - #plt.plot(data_dict["k_ratios"], data_dict["section1"]["x_bar_2"]["heat_results"], label=f'Analytical Heat Convection') - plt.xlabel('k2/k1') - plt.ylabel('Q_Dot (W)') - plt.legend() - plt.grid(True) - plt.savefig('images/section2/x_bar_2/heat_convection_vs_k_ratio.png', dpi=300) - #plt.show() - plt.clf() - - - -def section_3(): - '''Convergence of FDM and FEM of interface temperature and heat convection''' - print("Section 3: Convergence of FDM and FEM with Varying k Ratio") - - l = data_dict["length"] - - data_dict["section3"] = {} - data_dict["section3"]["num_sections"] = [4, 8, 16, 32, 64, 128] - - for k, x_bar_1 in enumerate(data_dict["x_bar_values"]): - # Calculate the number of rows needed for two columns of subplots - num_k_ratios = len(data_dict["k_ratios"]) - num_rows = math.ceil(num_k_ratios / 2) - - # Define the figure for temperature convergence (two columns) - fig_temp, axs_temp = plt.subplots(num_rows, 2, figsize=(15, 5 * num_rows)) - - # Define the figure for heat convergence (two columns) - fig_heat, axs_heat = plt.subplots(num_rows, 2, figsize=(15, 5 * num_rows)) - - # Flatten the axs arrays for easier indexing - axs_temp = axs_temp.flatten() - axs_heat = axs_heat.flatten() - - # For every k ratio, iterate through every number of points, calculate convergence (compared to analytical and extrapolated), print and add a subplot - for idx, k_ratio in enumerate(data_dict["k_ratios"]): - Bar.set_k_ratio(k_ratio, bar1, bar2) # Set the k value of bar2 = k*bar1 - - # Get the analytical data - analy_interface_temp = case1.get_analytical_datapoints([x_bar_1], bar1, bar2, x_bar_1, l) - analy_heat = case1.get_analytical_heat_convection(l, bar1, bar2, x_bar_1, l) - - # Setup data arrays - fdm_interface_temps = [] - fem_interface_temps = [] - fdm_extrap_temps = [None, None] - fem_extrap_temps = [None, None] - fdm_heats = [] - fem_heats = [] - fdm_extrap_heats = [None, None] - fem_extrap_heats = [None, None] - fdm_interface_temp_errors = [] - fem_interface_temp_errors = [] - fdm_interface_temp_betas = [[None]] - fem_interface_temp_betas = [[None]] - fdm_heat_errors = [] - fem_heat_errors = [] - fdm_heat_betas = [[None]] - fem_heat_betas = [[None]] - fdm_interface_temp_extrap_errors = [None, None] - fem_interface_temp_extrap_errors = [None, None] - fdm_interface_temp_extrap_betas = [None, None] - fem_interface_temp_extrap_betas = [None, None] - fdm_heat_extrap_errors = [None, None] - fem_heat_extrap_errors = [None, None] - fdm_heat_extrap_betas = [None, None] - fem_heat_extrap_betas = [None, None] - - # Get the fdm and fem data - dx = 0 - for i, num_sections in enumerate(data_dict["section3"]["num_sections"]): - fdm_temps, x_fdm = case1.solve(bar1=bar1,bar2=bar2,num_sections=num_sections,x_bar=x_bar_1,l=l,method="FDM") - fem_temps, x_fem = case1.solve(bar1=bar1,bar2=bar2,num_sections=num_sections,x_bar=x_bar_1,l=l,method="FEM") - # Get the interface temperature - fdm_interface_temp = fdm_temps[num_sections // 2] - fem_interface_temp = fem_temps[num_sections // 2] - fdm_interface_temps.append(fdm_interface_temp) - fem_interface_temps.append(fem_interface_temp) - - # Get the 2 last temperature to calculate heat convection - dx_prev = dx - dx = x_fdm[-1] - x_fdm[-2] - (fdm_t0, fdm_t1) = fdm_temps[-2:] - fdm_heat = common.fdm_heat_extraction(fdm_t0, fdm_t1, dx, bar2, order=2) - (fem_t0, fem_t1) = fem_temps[-2:] - fem_heat = common.fem_heat_extraction(fem_t0, fem_t1, dx, bar2) - fdm_heats.append(fdm_heat) - fem_heats.append(fem_heat) - - # Calculated the Richardson extrpolation of interface temperature and heat convection - if i >= 2: - fdm_extrap_temp = common.calc_extrapolated(fdm_interface_temps[-3], fdm_interface_temps[-2], fdm_interface_temps[-1]) - fem_extrap_temp = common.calc_extrapolated(fem_interface_temps[-3], fem_interface_temps[-2], fem_interface_temps[-1]) - fdm_extrap_heat = common.calc_extrapolated(fdm_heats[-3], fdm_heats[-2], fdm_heats[-1]) - fem_extrap_heat = common.calc_extrapolated(fem_heats[-3], fem_heats[-2], fem_heats[-1]) - fdm_extrap_temps.append(fdm_extrap_temp) - fem_extrap_temps.append(fem_extrap_temp) - fdm_extrap_heats.append(fdm_extrap_heat) - fem_extrap_heats.append(fem_extrap_heat) - - # Calculate the errors in reference to extrapolated values - fdm_interface_temp_extrap_error = common.calc_error(fdm_extrap_temp, fdm_interface_temp) - fem_interface_temp_extrap_error = common.calc_error(fem_extrap_temp, fem_interface_temp) - fdm_heat_extrap_error = common.calc_error(fdm_extrap_heat, fdm_heat) - fem_heat_extrap_error = common.calc_error(fem_extrap_heat, fem_heat) - fdm_interface_temp_extrap_errors.append(fdm_interface_temp_extrap_error) - fem_interface_temp_extrap_errors.append(fem_interface_temp_extrap_error) - fdm_heat_extrap_errors.append(fdm_heat_extrap_error) - fem_heat_extrap_errors.append(fem_heat_extrap_error) - - # Calculate the betas in reference to extrapolated values - fdm_interface_temp_extrap_beta = common.calc_beta(fdm_extrap_temp, fdm_interface_temps[-1], fdm_interface_temps[-2], dx, dx_prev) - fem_interface_temp_extrap_beta = common.calc_beta(fem_extrap_temp, fem_interface_temps[-1], fem_interface_temps[-2], dx, dx_prev) - fdm_heat_extrap_beta = common.calc_beta(fdm_extrap_heat, fdm_heats[-1], fdm_heats[-2], dx, dx_prev) - fem_heat_extrap_beta = common.calc_beta(fem_extrap_heat, fem_heats[-1], fem_heats[-2], dx, dx_prev) - fdm_interface_temp_extrap_betas.append(fdm_interface_temp_extrap_beta) - fem_interface_temp_extrap_betas.append(fem_interface_temp_extrap_beta) - fdm_heat_extrap_betas.append(fdm_heat_extrap_beta) - fem_heat_extrap_betas.append(fem_heat_extrap_beta) - - - # Calculate the error and convergence rates for fdm temp, fem temp, fdm heat, and fem heat - fdm_interface_temp_error = common.calc_error(analy_interface_temp, fdm_interface_temp) - fem_interface_temp_error = common.calc_error(analy_interface_temp, fem_interface_temp) - fdm_heat_error = common.calc_error(analy_heat, fdm_heat) - fem_heat_error = common.calc_error(analy_heat, fem_heat) - fdm_interface_temp_errors.append(fdm_interface_temp_error) - fem_interface_temp_errors.append(fem_interface_temp_error) - fdm_heat_errors.append(fdm_heat_error) - fem_heat_errors.append(fem_heat_error) - - if i >= 1: # if i == 0 then we cannot calculate convergence - fdm_interface_temp_beta = common.calc_beta(analy_interface_temp, fdm_interface_temps[-1], fdm_interface_temps[-2], dx, dx_prev) - fem_interface_temp_beta = common.calc_beta(analy_interface_temp, fem_interface_temps[-1], fem_interface_temps[-2], dx, dx_prev) - fdm_heat_beta = common.calc_beta(analy_heat, fdm_heats[-1], fdm_heats[-2], dx, dx_prev) - fem_heat_beta = common.calc_beta(analy_heat, fem_heats[-1], fem_heats[-2], dx, dx_prev) - fdm_interface_temp_betas.append(fdm_interface_temp_beta) - fem_interface_temp_betas.append(fem_interface_temp_beta) - fdm_heat_betas.append(fdm_heat_beta) - fem_heat_betas.append(fem_heat_beta) - - - # Print the interface temps for this k ratio - table_data = [] - for i in range(len(data_dict["section3"]["num_sections"])): - table_data.append([ - analy_interface_temp[0], # True T - - fdm_interface_temps[i], # fdm result - fdm_extrap_temps[i], - fdm_interface_temp_errors[i][0], # fdm % error in reference to analytical - fdm_interface_temp_betas[i][0], # fdm beta - fdm_interface_temp_extrap_errors[i], # fdm % error in reference to extrapolated value - fdm_interface_temp_extrap_betas[i], # fdm beta - - fem_interface_temps[i], # fem result - fem_extrap_temps[i], - fem_interface_temp_errors[i][0], # fem % error - fem_interface_temp_betas[i][0], # fem beta - fem_interface_temp_extrap_errors[i], # fem extrap % error - fem_interface_temp_extrap_betas[i], # fem beta - ]) - - columns = ['True T', 'FDM T', 'FDM Extrap T', 'FDM Exact % Error', 'FDM Exact B', 'FDM Extrap % Error', 'FDM Extrap B', 'FEM T', 'FEM Extrap T', 'FEM Exact % Error', 'FEM Exact B', 'FEM Extrap % Error', 'FEM Extrap B'] - df = pd.DataFrame(table_data, index=[f'N = {i}' for i in data_dict["section3"]["num_sections"]], columns=columns) - - print(f"Convergence of FDM and FEM Temperature at x_bar = {x_bar_1:.3f} and k_ratio = {k_ratio}") - print(df.to_string()) - print("\n" * 2) - - # Print the heat convection results for this k ratio - table_data = [] - for i in range(len(data_dict["section3"]["num_sections"])): - table_data.append([ - analy_heat, # True Q - fdm_heats[i], # fdm result - fdm_extrap_heats[i], # fdm extrapolated heat - fdm_heat_errors[i], # fdm % error in reference to analytical - fdm_heat_betas[i], # fdm beta in reference to analytical - fdm_heat_extrap_errors[i], # fdm % error in reference to extrapolated value - fdm_heat_extrap_betas[i], # fdm beta - - fem_heats[i], # fem result - fem_extrap_heats[i], # fem extrapolated heat - fem_heat_errors[i], # fem % error - fem_heat_betas[i], # fem beta - fem_heat_extrap_errors[i], # fem % error - fem_heat_extrap_betas[i] # fem beta - ]) - - columns = ['True Q', 'FDM Q', 'FDM Extrap Q', 'FDM Exact % Error', 'FDM Exact B', 'FDM Extrap % Error', 'FDM Extrap B', 'FEM Q', 'FEM Extrap Q', 'FEM Exact % Error', 'FEM Exact B', 'FEM Extrap % Error', 'FEM Extrap B'] - df = pd.DataFrame(table_data, index=[f'N = {i}' for i in data_dict["section3"]["num_sections"]], columns=columns) - - print(f"Convergence of FDM and FEM Heat Convection with x_bar = {x_bar_1:.3f} and k_ratio = {k_ratio}") - print(df.to_string()) - print("\n" * 2) - - # Add a subplot of the interface temp convergence for this k ratio - ax_temp = axs_temp[idx] - - # Data to plot for temperature convergence - num_sections = data_dict["section3"]["num_sections"] - fdm_exact_errors = [e[0] for e in fdm_interface_temp_errors] - fem_exact_errors = [e[0] for e in fem_interface_temp_errors] - fdm_extrap_errors = fdm_interface_temp_extrap_errors - fem_extrap_errors = fem_interface_temp_extrap_errors - - # Plotting temperature lines - ax_temp.plot(num_sections, fdm_exact_errors, label="FDM Exact") - ax_temp.plot(num_sections, fem_exact_errors, label="FEM Exact") - ax_temp.plot(num_sections, fdm_extrap_errors, label="FDM Extrap") - ax_temp.plot(num_sections, fem_extrap_errors, label="FEM Extrap") - - ax_temp.set_xscale("log") - ax_temp.set_yscale("log") - ax_temp.set_xlabel("Number of Sections (N)") - ax_temp.set_ylabel("% Error") - ax_temp.set_title(f"k_ratio = {k_ratio}") - ax_temp.grid(True) - ax_temp.legend() - - # Add a subplot of the heat convergence for this k ratio - ax_heat = axs_heat[idx] - - # Data to plot for heat convergence - fdm_exact_heat_errors = fdm_heat_errors - fem_exact_heat_errors = fem_heat_errors - fdm_extrap_heat_errors = fdm_heat_extrap_errors - fem_extrap_heat_errors = fem_heat_extrap_errors - - # Plotting heat lines - ax_heat.plot(num_sections, fdm_exact_heat_errors, label="FDM Exact") - ax_heat.plot(num_sections, fem_exact_heat_errors, label="FEM Exact") - ax_heat.plot(num_sections, fdm_extrap_heat_errors, label="FDM Extrap") - ax_heat.plot(num_sections, fem_extrap_heat_errors, label="FEM Extrap") - - ax_heat.set_xscale("log") - ax_heat.set_yscale("log") - ax_heat.set_xlabel("Number of Sections (N)") - ax_heat.set_ylabel("% Error") - ax_heat.set_title(f"k_ratio = {k_ratio}") - ax_heat.grid(True) - ax_heat.legend() - - # Hide any unused subplots (in case of an odd number of k_ratios) - for i in range(num_k_ratios, len(axs_temp)): - fig_temp.delaxes(axs_temp[i]) - fig_heat.delaxes(axs_heat[i]) - - # Adjust layout for better spacing - fig_temp.tight_layout(rect=[0, 0.03, 1, 0.95]) - fig_heat.tight_layout(rect=[0, 0.03, 1, 0.95]) - - # Save the plots - if k == 0: - fig_temp.savefig("images/section3/x_bar_1/temp_convergences.png", dpi=300) - fig_heat.savefig("images/section3/x_bar_1/heat_convergences.png", dpi=300) - else: - fig_temp.savefig("images/section3/x_bar_2/temp_convergences.png", dpi=300) - fig_heat.savefig("images/section3/x_bar_2/heat_convergences.png", dpi=300) - - - -def main(): - # Make directories for plots - import os - import shutil - - base_dir = "images" - sub_dirs = ["section1", "section2", "section3"] - nested_dirs = ["x_bar_1", "x_bar_2"] - - # Create the base directory if it doesn't exist - if not os.path.exists(base_dir): - os.mkdir(base_dir) - - # Create or clear subdirectories and their nested directories - for sub_dir in sub_dirs: - section_path = os.path.join(base_dir, sub_dir) - if os.path.exists(section_path): - # Remove all contents of the directory - shutil.rmtree(section_path) - # Create the section directory - os.makedirs(section_path) - - # Create nested directories within each section - for nested_dir in nested_dirs: - nested_path = os.path.join(section_path, nested_dir) - os.makedirs(nested_path) - - # import sys - - # # Redirect all print statements to a file - # sys.stdout = open("output.txt", "w", encoding="utf-8") - - section_1() # Analytical solutions - section_2() # FDM and FEM temperature and heat convection - section_3() # Convergence of FDM and FEM temperature and heat convection - - # # Restore original stdout and close the file - # sys.stdout.close() - # sys.stdout = sys.__stdout__ - - -if __name__ == "__main__": - main() \ No newline at end of file diff --git a/HW3/Judson_Upchurch_HW3/output.txt b/HW3/Judson_Upchurch_HW3/output.txt deleted file mode 100644 index 722312c..0000000 Binary files a/HW3/Judson_Upchurch_HW3/output.txt and /dev/null differ diff --git a/HW3/case1.py b/HW3/case1.py index 4021a09..77b692f 100644 --- a/HW3/case1.py +++ b/HW3/case1.py @@ -68,7 +68,6 @@ def fdm_array(bar1:'Bar', bar2:'Bar', num_sections: int=6, x_bar=2/np.pi, l=1): beta1 = (bar1.k * bar1.area) / (dx1) beta2 = (bar2.k * bar2.area) / (dx2) - #rho = beta1 - beta2 - (bar1.k * bar1.area * dx1 * bar1.alpha**2) / 2 + (bar2.k * bar2.area * dx2 * bar2.alpha**2) / 2 rho = beta1 + beta2 + (bar1.k * bar1.area * dx1 * bar1.alpha**2) / 2 + (bar2.k * bar2.area * dx2 * bar2.alpha**2) / 2 # Making the matrix # There are num_sections - 1 rows and columns diff --git a/HW3/main.py b/HW3/main.py index e36efe4..acacc15 100644 --- a/HW3/main.py +++ b/HW3/main.py @@ -6,7 +6,6 @@ import matplotlib.pyplot as plt import math import case1 -import case2 import common import Bar diff --git a/HW3/Judson_Upchurch_HW3/Bar.py b/HW4/Bar.py similarity index 100% rename from HW3/Judson_Upchurch_HW3/Bar.py rename to HW4/Bar.py diff --git a/HW4/Derivations.pdf b/HW4/Derivations.pdf new file mode 100644 index 0000000..64fa788 Binary files /dev/null and b/HW4/Derivations.pdf differ diff --git a/HW4/Images/FDM/x_bar_1/heat_convection.png b/HW4/Images/FDM/x_bar_1/heat_convection.png new file mode 100644 index 0000000..e005fba Binary files /dev/null and b/HW4/Images/FDM/x_bar_1/heat_convection.png differ diff --git a/HW3/Judson_Upchurch_HW3/images/section2/x_bar_1/fdm_temperature_vs_position.png b/HW4/Images/FDM/x_bar_1/temperature_distribution_1.png similarity index 100% rename from HW3/Judson_Upchurch_HW3/images/section2/x_bar_1/fdm_temperature_vs_position.png rename to HW4/Images/FDM/x_bar_1/temperature_distribution_1.png diff --git a/HW4/Images/FDM/x_bar_1/temperature_distribution_2.png b/HW4/Images/FDM/x_bar_1/temperature_distribution_2.png new file mode 100644 index 0000000..cabc800 Binary files /dev/null and b/HW4/Images/FDM/x_bar_1/temperature_distribution_2.png differ diff --git a/HW4/Images/FDM/x_bar_2/heat_convection.png b/HW4/Images/FDM/x_bar_2/heat_convection.png new file mode 100644 index 0000000..3c9ae4e Binary files /dev/null and b/HW4/Images/FDM/x_bar_2/heat_convection.png differ diff --git a/HW3/Judson_Upchurch_HW3/images/section2/x_bar_2/fdm_temperature_vs_position.png b/HW4/Images/FDM/x_bar_2/temperature_distribution_1.png similarity index 100% rename from HW3/Judson_Upchurch_HW3/images/section2/x_bar_2/fdm_temperature_vs_position.png rename to HW4/Images/FDM/x_bar_2/temperature_distribution_1.png diff --git a/HW4/Images/FDM/x_bar_2/temperature_distribution_2.png b/HW4/Images/FDM/x_bar_2/temperature_distribution_2.png new file mode 100644 index 0000000..d8ebb82 Binary files /dev/null and b/HW4/Images/FDM/x_bar_2/temperature_distribution_2.png differ diff --git a/HW4/Images/FEM/x_bar_1/heat_convection.png b/HW4/Images/FEM/x_bar_1/heat_convection.png new file mode 100644 index 0000000..5299b13 Binary files /dev/null and b/HW4/Images/FEM/x_bar_1/heat_convection.png differ diff --git a/HW3/Judson_Upchurch_HW3/images/section2/x_bar_1/fem_temperature_vs_position.png b/HW4/Images/FEM/x_bar_1/temperature_distribution_1.png similarity index 100% rename from HW3/Judson_Upchurch_HW3/images/section2/x_bar_1/fem_temperature_vs_position.png rename to HW4/Images/FEM/x_bar_1/temperature_distribution_1.png diff --git a/HW4/Images/FEM/x_bar_1/temperature_distribution_2.png b/HW4/Images/FEM/x_bar_1/temperature_distribution_2.png new file mode 100644 index 0000000..f901a8f Binary files /dev/null and b/HW4/Images/FEM/x_bar_1/temperature_distribution_2.png differ diff --git a/HW4/Images/FEM/x_bar_2/heat_convection.png b/HW4/Images/FEM/x_bar_2/heat_convection.png new file mode 100644 index 0000000..463d1ab Binary files /dev/null and b/HW4/Images/FEM/x_bar_2/heat_convection.png differ diff --git a/HW3/Judson_Upchurch_HW3/images/section2/x_bar_2/fem_temperature_vs_position.png b/HW4/Images/FEM/x_bar_2/temperature_distribution_1.png similarity index 100% rename from HW3/Judson_Upchurch_HW3/images/section2/x_bar_2/fem_temperature_vs_position.png rename to HW4/Images/FEM/x_bar_2/temperature_distribution_1.png diff --git a/HW4/Images/FEM/x_bar_2/temperature_distribution_2.png b/HW4/Images/FEM/x_bar_2/temperature_distribution_2.png new file mode 100644 index 0000000..5f962b4 Binary files /dev/null and b/HW4/Images/FEM/x_bar_2/temperature_distribution_2.png differ diff --git a/HW3/Judson_Upchurch_HW3/images/section1/x_bar_1/analytical_heat_convection_vs_k_ratio.png b/HW4/Images/analytical/x_bar_1/heat_convection.png similarity index 100% rename from HW3/Judson_Upchurch_HW3/images/section1/x_bar_1/analytical_heat_convection_vs_k_ratio.png rename to HW4/Images/analytical/x_bar_1/heat_convection.png diff --git a/HW3/Judson_Upchurch_HW3/images/section1/x_bar_1/analytical_temperature_vs_position.png b/HW4/Images/analytical/x_bar_1/temperature_distribution.png similarity index 100% rename from HW3/Judson_Upchurch_HW3/images/section1/x_bar_1/analytical_temperature_vs_position.png rename to HW4/Images/analytical/x_bar_1/temperature_distribution.png diff --git a/HW3/Judson_Upchurch_HW3/images/section1/x_bar_2/analytical_heat_convection_vs_k_ratio.png b/HW4/Images/analytical/x_bar_2/heat_convection.png similarity index 100% rename from HW3/Judson_Upchurch_HW3/images/section1/x_bar_2/analytical_heat_convection_vs_k_ratio.png rename to HW4/Images/analytical/x_bar_2/heat_convection.png diff --git a/HW3/Judson_Upchurch_HW3/images/section1/x_bar_2/analytical_temperature_vs_position.png b/HW4/Images/analytical/x_bar_2/temperature_distribution.png similarity index 100% rename from HW3/Judson_Upchurch_HW3/images/section1/x_bar_2/analytical_temperature_vs_position.png rename to HW4/Images/analytical/x_bar_2/temperature_distribution.png diff --git a/HW4/Images/convergence/x_bar_1/heat_convergence.png b/HW4/Images/convergence/x_bar_1/heat_convergence.png new file mode 100644 index 0000000..b86e7d5 Binary files /dev/null and b/HW4/Images/convergence/x_bar_1/heat_convergence.png differ diff --git a/HW4/Images/convergence/x_bar_1/temp_convergence.png b/HW4/Images/convergence/x_bar_1/temp_convergence.png new file mode 100644 index 0000000..fcf0674 Binary files /dev/null and b/HW4/Images/convergence/x_bar_1/temp_convergence.png differ diff --git a/HW4/Images/convergence/x_bar_2/heat_convergence.png b/HW4/Images/convergence/x_bar_2/heat_convergence.png new file mode 100644 index 0000000..d50f6a4 Binary files /dev/null and b/HW4/Images/convergence/x_bar_2/heat_convergence.png differ diff --git a/HW4/Images/convergence/x_bar_2/temp_convergence.png b/HW4/Images/convergence/x_bar_2/temp_convergence.png new file mode 100644 index 0000000..8249854 Binary files /dev/null and b/HW4/Images/convergence/x_bar_2/temp_convergence.png differ diff --git a/HW4/Judson_Upchurch_HW4.pdf b/HW4/Judson_Upchurch_HW4.pdf new file mode 100644 index 0000000..bee7f09 Binary files /dev/null and b/HW4/Judson_Upchurch_HW4.pdf differ diff --git a/HW4/__pycache__/Bar.cpython-312.pyc b/HW4/__pycache__/Bar.cpython-312.pyc new file mode 100644 index 0000000..79bf262 Binary files /dev/null and b/HW4/__pycache__/Bar.cpython-312.pyc differ diff --git a/HW4/__pycache__/case1.cpython-312.pyc b/HW4/__pycache__/case1.cpython-312.pyc new file mode 100644 index 0000000..50330f8 Binary files /dev/null and b/HW4/__pycache__/case1.cpython-312.pyc differ diff --git a/HW4/__pycache__/case2.cpython-312.pyc b/HW4/__pycache__/case2.cpython-312.pyc new file mode 100644 index 0000000..9402c57 Binary files /dev/null and b/HW4/__pycache__/case2.cpython-312.pyc differ diff --git a/HW4/__pycache__/common.cpython-312.pyc b/HW4/__pycache__/common.cpython-312.pyc new file mode 100644 index 0000000..eba3a70 Binary files /dev/null and b/HW4/__pycache__/common.cpython-312.pyc differ diff --git a/HW4/case1.py b/HW4/case1.py new file mode 100644 index 0000000..2a70f0e --- /dev/null +++ b/HW4/case1.py @@ -0,0 +1,422 @@ +# case1.py + +import numpy as np +import matplotlib.pyplot as plt + +from Bar import Bar, set_k_ratio + +def get_analytical_constants(bar1:'Bar', bar2:'Bar', x_bar=2/np.pi, l=1): + '''Solve for C1, D1, C2, and D2 + Returns np.array([C1, D1, C2, D2])''' + epsilon = (bar1.k*bar1.area*bar1.alpha) / (bar2.k*bar2.area*bar2.alpha) + A = np.array([ + #C1 D1 C2 D2 + [0, 1, 0, 0], + [0, 0, np.sinh(bar2.alpha*l), np.cosh(bar2.alpha*l)], + [np.sinh(bar1.alpha*x_bar), 0, -1*np.sinh(bar2.alpha*x_bar), -1*np.cosh(bar2.alpha*x_bar)], + [epsilon*np.cosh(bar1.alpha*x_bar), 0, -1*np.cosh(bar2.alpha*x_bar), -1*np.sinh(bar2.alpha*x_bar)] + ]) + + B = np.array([ + 0, + 100, + 0, + 0 + ]) + + return np.linalg.solve(A, B) + +def get_analytical_datapoints(x_points, bar1:'Bar', bar2:'Bar', x_bar=2/np.pi, l=1): + '''Generates the temperature distribution given x_points. + Returns np.array of tempature values''' + constants = get_analytical_constants(bar1=bar1,bar2=bar2,x_bar=x_bar,l=1) + C1, D1, C2, D2 = constants[0], constants[1], constants[2], constants[3] + + # Two temp functions for the left and right side of the interface + left_temp = lambda x: C1*np.sinh(bar1.alpha*x) + D1*np.cosh(bar1.alpha*x) + right_temp = lambda x: C2*np.sinh(bar2.alpha*x) + D2*np.cosh(bar2.alpha*x) + + temp_values = np.array([]) + for x in x_points: + if x <= x_bar: + temp = left_temp(x) + else: + temp = right_temp(x) + temp_values = np.append(temp_values, temp) + + return temp_values + +def get_analytical_heat_convection(x, bar1:'Bar', bar2:'Bar', x_bar=2/np.pi, l=1): + '''Gets the analytical heat convection at x from heat flux conservation''' + constants = get_analytical_constants(bar1=bar1,bar2=bar2,x_bar=x_bar,l=1) + C1, D1, C2, D2 = constants[0], constants[1], constants[2], constants[3] + + t_prime = C2*bar2.alpha*np.cosh(bar2.alpha*x) + D2*bar2.alpha*np.sinh(bar2.alpha*x) + + q_dot = -bar2.k*bar2.area*t_prime + return q_dot + +def fdm_array(bar1:'Bar', bar2:'Bar', num_sections: int=6, x_bar=2/np.pi, l=1, order=2): + '''num_sections = total sections to cut the bar. Note that this is NOT evenly distributed over the entire + bar. Half of the sections are left of x_bar, half are to the right. + Returns the A matrix of the FDM equation Ax = B''' + dx1 = x_bar / (num_sections / 2) + dx2 = (l - x_bar) / (num_sections / 2) + + if order == 2: + w1 = dx1 + w2 = dx2 + + epsilon1 = 1 + dx1**2 * bar1.alpha**2 / 2 + epsilon2 = 1 + dx2**2 * bar2.alpha**2 / 2 + + beta1 = bar1.k * bar1.area / w1 + beta2 = bar2.k * bar2.area / w2 + + k1 = 2*beta1*epsilon1 + k2 = 2*beta2*epsilon2 + + rho = beta1*epsilon1 + beta2*epsilon2 + elif order == 4: + w1 = dx1 + dx1**3 * bar1.alpha**2 / 6 + w2 = dx2 + dx2**3 * bar2.alpha**2 / 6 + + epsilon1 = 1 + dx1**2 * bar1.alpha**2 / 2 + dx1**4 * bar1.alpha**4 / 24 + epsilon2 = 1 + dx2**2 * bar2.alpha**2 / 2 + dx2**4 * bar2.alpha**4 / 24 + + beta1 = bar1.k * bar1.area / w1 + beta2 = bar2.k * bar2.area / w2 + + k1 = 2*beta1*epsilon1 + k2 = 2*beta2*epsilon2 + + rho = beta1*epsilon1 + beta2*epsilon2 + + # Making the matrix + # There are num_sections - 1 rows and columns + # row 0, row n - 2, and row num_sections/2 - 1 are unique + # the rest are -1, k, -1 where k changes from k1 to k2 at num_sections/2 + + # Initialize matrix A with zeros + A = np.zeros((num_sections - 1, num_sections - 1)) + + # Fill the matrix A + for row in range(num_sections - 1): + if row == 0: + # First row for boundary at x = 0 (for example Dirichlet or Neumann condition) + A[row, row] = k1 + A[row, row+1] = -beta1 + elif row == num_sections // 2 - 1: + # Special row at the interface between bar1 and bar2 + A[row, row-1] = -beta1 + A[row, row] = rho + A[row, row+1] = -beta2 + elif row == num_sections - 2: + # Last row for boundary at x = l (again assuming Dirichlet or Neumann condition) + A[row, row-1] = -beta2 + A[row, row] = k2 + else: + # Interior rows for bar1 and bar2 (uniform grid) + if row < num_sections // 2 - 1: + # In bar1 region + A[row, row-1] = -beta1 + A[row, row] = k1 + A[row, row+1] = -beta1 + else: + # In bar2 region + A[row, row-1] = -beta2 + A[row, row] = k2 + A[row, row+1] = -beta2 + return A + +def fem_array(bar1:'Bar', bar2:'Bar', num_sections: int=6, x_bar=2/np.pi, l=1): + '''num_sections = total sections to cut the bar. Note that this is NOT evenly distributed over the entire + bar. Half of the sections are left of x_bar, half are to the right. + Returns the A matrix of the FEM equation Ax = B''' + dx1 = x_bar / (num_sections / 2) + dx2 = (l - x_bar) / (num_sections / 2) + + k1 = (2/dx1 + 4*bar1.alpha**2*dx1/6) / (1/dx1 - bar1.alpha**2*dx1/6) + k2 = (2/dx2 + 4*bar2.alpha**2*dx2/6) / (1/dx2 - bar2.alpha**2*dx2/6) + beta1 = (bar1.k * bar1.area) / (dx1) + beta2 = (bar2.k * bar2.area) / (dx2) + rho = beta1 + beta2 + (bar1.k * bar1.area * dx1 * bar1.alpha**2) / 2 + (bar2.k * bar2.area * dx2 * bar2.alpha**2) / 2 + + # Making the matrix + # There are num_sections - 1 rows and columns + # row 0, row n - 2, and row num_sections/2 - 1 are unique + # the rest are -1, k, -1 where k changes from k1 to k2 at num_sections/2 + + # Initialize matrix A with zeros + A = np.zeros((num_sections - 1, num_sections - 1)) + + # Fill the matrix A + for row in range(num_sections - 1): + if row == 0: + # First row for boundary at x = 0 (for example Dirichlet or Neumann condition) + A[row, row] = k1 + A[row, row+1] = -1 + elif row == num_sections // 2 - 1: + # Special row at the interface between bar1 and bar2 + A[row, row-1] = -beta1 + A[row, row] = rho # This is the rho value you computed + A[row, row+1] = -beta2 + elif row == num_sections - 2: + # Last row for boundary at x = l (again assuming Dirichlet or Neumann condition) + A[row, row-1] = -1 + A[row, row] = k2 + else: + # Interior rows for bar1 and bar2 (uniform grid) + if row < num_sections // 2 - 1: + # In bar1 region + A[row, row-1] = -1 + A[row, row] = k1 + A[row, row+1] = -1 + else: + # In bar2 region + A[row, row-1] = -1 + A[row, row] = k2 + A[row, row+1] = -1 + return A + +def get_fem_p2_k(row, col, bar:'Bar', dx): + if (row == 1 and col == 1) or (row == 2 and col == 2): + return bar.k * bar.area / dx + bar.h * bar.p * dx / 3.0 + elif row == 3 and col == 3: + return 1 * bar.k * bar.area / (3*dx) + bar.h * bar.p * dx / 30 + elif (row == 1 and col == 2) or (row == 2 and col == 1): + return -1 * bar.k * bar.area / dx + bar.h * bar.p * dx / 6 + elif (row == 1 and col == 3) or (row == 3 and col == 1) or (row == 2 and col == 3) or (row == 3 and col == 2): + return bar.h * bar.p * dx / 12 + +def get_all_fem_p2_k(bar:'Bar', dx): + K = np.zeros((3, 3)) + for row in range(3): + for col in range(3): + K[row, col] = get_fem_p2_k(row+1, col+1, bar, dx) + return K + +def fem_p_2_array(bar1:'Bar', bar2:'Bar', num_sections: int=6, x_bar=2/np.pi, l=1): + '''num_sections = total sections to cut the bar. Note that this is NOT evenly distributed over the entire + bar. Half of the sections are left of x_bar, half are to the right. + Returns the A matrix of the FEM equation Ax = B''' + dx1 = x_bar / (num_sections / 2) + dx2 = (l - x_bar) / (num_sections / 2) + + K_1 = get_all_fem_p2_k(bar1, dx1) + K_2 = get_all_fem_p2_k(bar2, dx2) + + # Initialize matrix A with zeros + rows = 2 * num_sections - 1 + cols = 2 * num_sections - 1 + A = np.zeros((rows, cols)) + + omega_col_index = num_sections - 1 + num_omega = num_sections + for i in range(num_sections): + row1 = i*2 + row2 = row1 + 1 + if i == 0: + A[row1][0] = K_1[2-1, 2-1] + K_1[1-1, 1-1] + A[row1][1] = K_1[1-1, 2-1] + A[row1][omega_col_index] = K_1[2-1, 3-1] + A[row1][omega_col_index+1] = K_1[1-1, 3-1] + + A[row2][0] = K_1[3-1, 2-1] + A[row2][omega_col_index] = K_1[3-1, 3-1] + elif i == num_sections - 2: # Second last pair of rows + A[row1][i-1] = K_2[2-1, 1-1] + A[row1][i] = K_2[2-1, 2-1] + K_2[1-1, 1-1] + A[row1][omega_col_index+i] = K_2[2-1, 3-1] + A[row1][omega_col_index+i+1] = K_2[1-1, 3-1] + + A[row2][i-1] = K_2[3-1, 1-1] + A[row2][i] = K_2[3-1, 2-1] + A[row2][omega_col_index+i] = K_2[3-1, 3-1] + elif i == num_sections - 1: # Last pair of rows, use only omega equation + A[row1][omega_col_index-1] = K_2[3-1, 1-1] + A[row1][-1] = K_2[3-1, 3-1] + elif i == num_sections // 2 - 1: # Interface element + A[row1][i-1] = K_1[2-1, 1-1] + A[row1][i] = K_1[2-1, 2-1] + K_2[1-1, 1-1] + A[row1][i+1] = K_2[1-1, 2-1] + A[row1][omega_col_index + i] = K_1[2-1, 3-1] + A[row1][omega_col_index + i + 1] = K_2[1-1, 3-1] + + A[row2][i-1] = K_1[3-1, 1-1] + A[row2][i] = K_1[3-1, 2-1] + A[row2][omega_col_index + i] = K_1[3-1, 3-1] + else: + if i < num_sections // 2: # We are in the first bar + A[row1][i-1] = K_1[2-1, 1-1] + A[row1][i] = K_1[2-1, 2-1] + K_1[1-1, 1-1] + A[row1][i+1] = K_1[1-1, 2-1] + A[row1][omega_col_index + i] = K_1[2-1, 3-1] + A[row1][omega_col_index + i + 1] = K_1[1-1, 3-1] + + A[row2][i-1] = K_1[3-1, 1-1] + A[row2][i] = K_1[3-1, 2-1] + A[row2][omega_col_index + i] = K_1[3-1, 3-1] + else: # We are in the second bar + A[row1][i-1] = K_2[2-1, 1-1] + A[row1][i] = K_2[2-1, 2-1] + K_2[1-1, 1-1] + A[row1][i+1] = K_2[1-1, 2-1] + A[row1][omega_col_index + i] = K_2[2-1, 3-1] + A[row1][omega_col_index + i + 1] = K_2[1-1, 3-1] + + A[row2][i-1] = K_2[3-1, 1-1] + A[row2][i] = K_2[3-1, 2-1] + A[row2][omega_col_index + i] = K_2[3-1, 3-1] + return A + + + +def solve(bar1:'Bar', bar2:'Bar', num_sections: int=6, x_bar=2/np.pi, l=1, method="FDM", order=2): + '''Solves using FDM or FEM as specified. Returns (temps, x_values)''' + if method == "FDM": + A = fdm_array(bar1, + bar2, + num_sections=num_sections, + x_bar=x_bar, + l=l, + order=order) + # Generate the B vector + if order == 2: + dx2 = (l - x_bar) / (num_sections / 2) + w2 = dx2 + beta2 = bar2.k * bar2.area / w2 + elif order == 4: + dx2 = (l - x_bar) / (num_sections / 2) + w2 = dx2 + dx2**3 * bar2.alpha**2 / 6 + beta2 = bar2.k * bar2.area / w2 + + B = np.zeros((num_sections - 1)) + B[-1] = beta2*100 + + # Add boundary conditions + interior_temps = np.linalg.solve(A, B) + all_temps = np.array([0]) + all_temps = np.append(all_temps, interior_temps) + all_temps = np.append(all_temps, 100) + + # Generate the x_values to return along with the temps + dx2 = (l - x_bar) / (num_sections / 2) + x_values = np.linspace(0, x_bar, num_sections // 2 + 1) # [0, x_bar] + x_values = np.append(x_values, np.linspace(x_bar+dx2, l, num_sections // 2)) + + elif method == "FEM": + if order == 2: + A = fem_array(bar1, + bar2, + num_sections=num_sections, + x_bar=x_bar, + l=l) + # Generate the B vector + B = np.zeros((num_sections - 1)) + B[-1] = 100 + + # Add boundary conditions + interior_temps = np.linalg.solve(A, B) + all_temps = np.array([0]) + all_temps = np.append(all_temps, interior_temps) + all_temps = np.append(all_temps, 100) + + # Generate the x_values to return along with the temps + dx2 = (l - x_bar) / (num_sections / 2) + x_values = np.linspace(0, x_bar, num_sections // 2 + 1) # [0, x_bar] + x_values = np.append(x_values, np.linspace(x_bar+dx2, l, num_sections // 2)) + elif order == 4: + A = fem_p_2_array(bar1, + bar2, + num_sections=num_sections, + x_bar=x_bar, + l=l) + + # Generate the B vector + dx2 = (l - x_bar) / (num_sections / 2) + B = np.zeros((num_sections*2-1)) + K_2 = get_all_fem_p2_k(bar2, dx2) + B[0] = 0 + B[1] = 0 + B[-3] = -1 * K_2[1-1, 2-1] * 100 + B[-2] = 0 + B[-1] = -1 * K_2[3-1, 2-1] * 100 + + # Add boundary conditions + solution = np.linalg.solve(A, B) + all_temps = np.array([0]) + all_temps = np.append(all_temps, solution[0:num_sections-1]) + all_temps = np.append(all_temps, 100) + + # Generate the x_values to return along with the temps + dx2 = (l - x_bar) / (num_sections / 2) + x_values = np.linspace(0, x_bar, num_sections // 2 + 1) # [0, x_bar] + x_values = np.append(x_values, np.linspace(x_bar+dx2, l, num_sections // 2)) + + return all_temps, x_values + + +if __name__ == "__main__": + bar1 = Bar( + radius=0.1, + k=0.5, + h=0.25 + ) + bar2 = Bar( + radius=0.1, + k=0.5, + h=0.25 + ) + + #set_k_ratio(8, bar1, bar2) + + + x_bar = 0.7 + + x_values = np.linspace(0, 1, 1000) + temp_values = get_analytical_datapoints(x_points=x_values, + bar1=bar1, + bar2=bar2, + x_bar=x_bar) + + + # fdm tests + l = 1 + num_sections = 16 + dx1 = x_bar / (num_sections / 2) + dx2 = (l - x_bar) / (num_sections / 2) + fdm_temps, x_fdm = solve(bar1=bar1, + bar2=bar2, + num_sections=num_sections, + x_bar=x_bar, + l=1, + method="FEM", + order=2) + fem_temps, x_fem = solve(bar1=bar1, + bar2=bar2, + num_sections=num_sections, + x_bar=x_bar, + l=1, + method="FEM", + order=4) + + print(f"A: {bar1.area}") + print(f"k: {bar1.k}") + print(f"h: {bar1.h}") + print(f"P: {bar1.p}") + print(f"dx: {dx1}") + + + # Plot the data + plt.plot(x_values, temp_values, label='Temperature Distribution') + plt.axvline(x=x_bar, color='r', linestyle='--', label='x_bar') + plt.plot(x_fdm, fdm_temps, 'o-', label='Temperature Distribution (FDM)', color='g') + plt.plot(x_fem, fem_temps, 'o-', label='Temperature Distribution (FEM)', color='r') + plt.xlabel('x') + plt.ylabel('Temperature') + plt.title('Temperature Distribution Along the Bar') + plt.legend() + plt.grid(True) + + # Show plot + plt.show() \ No newline at end of file diff --git a/HW4/common.py b/HW4/common.py new file mode 100644 index 0000000..9c60c7d --- /dev/null +++ b/HW4/common.py @@ -0,0 +1,46 @@ +# common.py + +import numpy as np +from Bar import Bar + +def fdm_heat_extraction(t_0, t_1, dx, bar:'Bar', order=2): + '''Get the heat conduction at the point t_1 using Taylor series''' + if order == 1: + return -1 * bar.k * bar.area * (t_1 - t_0) / dx + elif order == 2: + return -1 * bar.k * bar.area * (((t_1 - t_0) / dx) + (bar.alpha**2 * dx * t_1 / 2)) + elif order == 4: + return -1 * bar.k * bar.area * ((144*t_1 - 144*t_0 + 72*dx**2*bar.alpha**2*t_1 + 6*dx**4*bar.alpha**4*t_1) / (144 * dx + 24*dx**3 * bar.alpha**2)) + +def fem_heat_extraction(t_0, t_1, dx, bar:'Bar', order=2): + '''Get the heat conduction at the point t_1 using FEM equation''' + if order == 2: + # term_1 = (-1/dx + bar.alpha**2*dx/6) * t_0 + # term_2 = (1/dx + 2*bar.alpha**2*dx/6) * t_1 + term_1 = (t_1 - t_0) / dx + term_2 = bar.alpha**2 * dx * t_1 / 2 + return -1 * bar.k * bar.area * (term_1 + term_2) + elif order == 4: + term_1 = (-1/dx + bar.alpha**2*dx/6) * t_0 + term_2 = (1/dx + 2*bar.alpha**2*dx/6) * t_1 + return -1 * bar.k * bar.area * (term_1 + term_2) + +def heat_extraction(t_0, t_1, dx, bar:'Bar', order=2, method="FDM"): + if method == "FDM": + return fdm_heat_extraction(t_0, t_1, dx, bar, order) + elif method == "FEM": + return fdm_heat_extraction(t_0, t_1, dx, bar, order) + +def calc_error(exact, q_1): + return np.abs((exact - q_1) / exact) + +def calc_beta(exact, q_1, q_2, dx_1, dx_2): + return np.log(np.abs((exact - q_1)/(exact - q_2))) / np.log(dx_1 / dx_2) + +def calc_extrapolated(q1, q2, q3, tolerance=1e-10): + '''Calculate Richardson extrapolation, returns NaN if denominator is too small.''' + numerator = q1 * q3 - q2**2 + denominator = q1 + q3 - 2 * q2 + if abs(denominator) < tolerance: + return float('NaN') # Return NaN if denominator is close to zero + return numerator / denominator \ No newline at end of file diff --git a/HW4/main.py b/HW4/main.py new file mode 100644 index 0000000..95bd495 --- /dev/null +++ b/HW4/main.py @@ -0,0 +1,900 @@ +# main.py + +import numpy as np +import pandas as pd +import matplotlib.pyplot as plt +import math +import sys + +import Bar +from case1 import solve, get_analytical_datapoints, get_analytical_heat_convection +from common import calc_extrapolated, calc_error, calc_beta, fdm_heat_extraction, fem_heat_extraction, heat_extraction + + +bar1 = Bar.Bar( + radius=0.1, + k=0.5, + h=0.25 +) +bar2 = Bar.Bar( + radius=0.1, + k=2, + h=0.25 +) + +data_dict = {} +data_dict["k_ratios"] = np.array([1/16, 1/8, 1/4, 1/2, 1, 2, 4, 8, 16]) +data_dict["x_bar_values"] = np.array([1/2, 2/np.pi]) +data_dict["length"] = 1 + +def analytical(): + '''Analytical solutions with varying k_ratio''' + print("Section 1: Analytical") + file_path = "images/analytical/" + + l = data_dict["length"] + + # Calculate the results for every k ratio for x_bar_1 + x_bar_1 = data_dict["x_bar_values"][0] + + data_dict["analytical"] = {} + data_dict["analytical"]["x_bar_1"] = {} + data_dict["analytical"]["x_bar_1"]["x_values_fine"] = np.linspace(0, l, 50) + data_dict["analytical"]["x_bar_1"]["x_values_fine"] = np.sort(np.append(data_dict["analytical"]["x_bar_1"]["x_values_fine"], x_bar_1)) + data_dict["analytical"]["x_bar_1"]["x_values_course"] = np.linspace(0, l, 9) + data_dict["analytical"]["x_bar_1"]["x_values_course"] = np.sort(np.append(data_dict["analytical"]["x_bar_1"]["x_values_course"], x_bar_1)) + + results = [] + results_course = [] + for k_ratio in data_dict["k_ratios"]: + Bar.set_k_ratio(k_ratio, bar1, bar2) # Set the k value of bar2 = k*bar1 + result = get_analytical_datapoints(data_dict["analytical"]["x_bar_1"]["x_values_fine"], + bar1=bar1, + bar2=bar2, + x_bar=x_bar_1, + l=l) + result_course = get_analytical_datapoints(data_dict["analytical"]["x_bar_1"]["x_values_course"], + bar1=bar1, + bar2=bar2, + x_bar=x_bar_1, + l=l) + results.append(result) + results_course.append(result_course) + + data_dict["analytical"]["x_bar_1"]["temp_results"] = np.array(results) + + df_x_bar_1 = pd.DataFrame(results_course, index=[f'k2/k1 = {a}' for a in data_dict["k_ratios"]], columns=[f'x = {x:.3f}' for x in data_dict["analytical"]["x_bar_1"]["x_values_course"]]) + + print("Analytical Temperature Results x_bar = 0.5:") + print(df_x_bar_1.to_string()) + print("\n" * 2) + + # Plotting x_bar_1 + plt.figure(figsize=(10, 6)) + for idx, k_ratio in enumerate(data_dict["k_ratios"]): + plt.plot(data_dict["analytical"]["x_bar_1"]["x_values_fine"], data_dict["analytical"]["x_bar_1"]["temp_results"][idx], label=f'k2/k1 = {k_ratio}') + plt.axvline(x=x_bar_1, color='r', linestyle='--', label='x_bar') + plt.xlabel('Position (cm)') + plt.ylabel('Temperature (°C)') + plt.legend() + plt.grid(True) + plt.savefig(f'{file_path}x_bar_1/temperature_distribution.png', dpi=300) + #plt.show() + plt.clf() + + # Calculate the temperature results for every k ratio for x_bar_1 + x_bar_2 = data_dict["x_bar_values"][1] + + data_dict["analytical"]["x_bar_2"] = {} + data_dict["analytical"]["x_bar_2"]["x_values_fine"] = np.linspace(0, l, 50) + data_dict["analytical"]["x_bar_2"]["x_values_fine"] = np.sort(np.append(data_dict["analytical"]["x_bar_2"]["x_values_fine"], x_bar_2)) + data_dict["analytical"]["x_bar_2"]["x_values_course"] = np.linspace(0, l, 9) + data_dict["analytical"]["x_bar_2"]["x_values_course"] = np.sort(np.append(data_dict["analytical"]["x_bar_2"]["x_values_course"], x_bar_2)) + + results = [] + results_course = [] + for k_ratio in data_dict["k_ratios"]: + Bar.set_k_ratio(k_ratio, bar1, bar2) + result = get_analytical_datapoints(data_dict["analytical"]["x_bar_2"]["x_values_fine"], + bar1=bar1, + bar2=bar2, + x_bar=x_bar_2, + l=l) + result_course = get_analytical_datapoints(data_dict["analytical"]["x_bar_2"]["x_values_course"], + bar1=bar1, + bar2=bar2, + x_bar=x_bar_2, + l=l) + results.append(result) + results_course.append(result_course) + + data_dict["analytical"]["x_bar_2"]["temp_results"] = np.array(results) + + df_x_bar_2 = pd.DataFrame(results_course, index=[f'k2/k1 = {a}' for a in data_dict["k_ratios"]], columns=[f'x = {x:.3f}' for x in data_dict["analytical"]["x_bar_2"]["x_values_course"]]) + + print("Analytical Temperature Results x_bar = 2/pi:") + print(df_x_bar_2.to_string()) + print("\n" * 2) + + # Plotting x_bar_2 + plt.figure(figsize=(10, 6)) + for idx, k_ratio in enumerate(data_dict["k_ratios"]): + plt.plot(data_dict["analytical"]["x_bar_2"]["x_values_fine"], data_dict["analytical"]["x_bar_2"]["temp_results"][idx], label=f'k2/k1 = {k_ratio}') + plt.axvline(x=x_bar_2, color='r', linestyle='--', label='x_bar') + plt.xlabel('Position (cm)') + plt.ylabel('Temperature (°C)') + plt.legend() + plt.grid(True) + plt.savefig(f'{file_path}x_bar_2/temperature_distribution.png', dpi=300) + #plt.show() + plt.clf() + + + + # Calculate the analytical heat convection leaving the rod at x=l for varying k ratio + + results_1 = [] + results_2 = [] + for k_ratio in data_dict["k_ratios"]: + Bar.set_k_ratio(k_ratio, bar1, bar2) + result_1 = get_analytical_heat_convection(x=l, + bar1=bar1, + bar2=bar2, + x_bar=x_bar_1, + l=l) + result_2 = get_analytical_heat_convection(x=l, + bar1=bar1, + bar2=bar2, + x_bar=x_bar_2, + l=l) + results_1.append([result_1]) + results_2.append([result_2]) + + data_dict["analytical"]["x_bar_1"]["heat_results"] = np.array(results_1) + data_dict["analytical"]["x_bar_2"]["heat_results"] = np.array(results_2) + + df_x_bar_1 = pd.DataFrame(results_1, index=[f'k2/k1 = {a}' for a in data_dict["k_ratios"]], columns=["Heat Convection"]) + df_x_bar_2 = pd.DataFrame(results_2, index=[f'k2/k1 = {a}' for a in data_dict["k_ratios"]], columns=["Heat Convection"]) + + print("Analytical Heat Convection Results x_bar = 0.5:") + print(df_x_bar_1.to_string()) + print("\n" * 2) + + print("Analytical Heat Convection Results x_bar = 2/pi:") + print(df_x_bar_2.to_string()) + print("\n" * 2) + + # Plotting x_bar_1 heat convection + plt.figure(figsize=(10, 6)) + plt.plot(data_dict["k_ratios"], data_dict["analytical"]["x_bar_1"]["heat_results"], label=f'Heat Convection') + plt.xlabel('k2/k1') + plt.ylabel('Q_Dot (W)') + plt.legend() + plt.grid(True) + plt.savefig(f'{file_path}x_bar_1/heat_convection.png', dpi=300) + #plt.show() + plt.clf() + + # Plotting x_bar_2 heat convection + plt.figure(figsize=(10, 6)) + plt.plot(data_dict["k_ratios"], data_dict["analytical"]["x_bar_2"]["heat_results"], label=f'Heat Convection') + plt.xlabel('k2/k1') + plt.ylabel('Q_Dot (W)') + plt.legend() + plt.grid(True) + plt.savefig(f'{file_path}x_bar_2/heat_convection.png', dpi=300) + #plt.show() + plt.clf() + + +def section_2(method="FDM"): + '''FDM and FEM with varying k_ratio''' + print(f"Section 2: {method} with Varying k_ratio") + file_path = f"images/{method}/" + + l = data_dict["length"] + + data_dict["section2"] = {} + data_dict["section2"]["num_sections"] = 8 + + + # Calculate the results for every k ratio for x_bar_1 + x_bar_1 = data_dict["x_bar_values"][0] + + # For every k_ratio, calculate the FDM and FEM temperature results + fdm_results = [] + fem_results = [] + x_fdm = [] + x_fem = [] + for k_ratio in data_dict["k_ratios"]: + Bar.set_k_ratio(k_ratio, bar1, bar2) # Set the k value of bar2 = k*bar1 + fdm_temps, x_fdm = solve(bar1=bar1, + bar2=bar2, + num_sections=data_dict["section2"]["num_sections"], + x_bar=x_bar_1, + l=l, + method=method, + order=2) + fem_temps, x_fem = solve(bar1=bar1, + bar2=bar2, + num_sections=data_dict["section2"]["num_sections"], + x_bar=x_bar_1, + l=l, + method=method, + order=4) + + fdm_results.append(fdm_temps) + fem_results.append(fem_temps) + + data_dict["section2"]["x_bar_1"] = {} + data_dict["section2"]["x_bar_1"]["x_values"] = x_fdm # fdm and fem use same x_values + data_dict["section2"]["x_bar_1"]["fdm_results"] = np.array(fdm_results) + data_dict["section2"]["x_bar_1"]["fem_results"] = np.array(fem_results) + + df_fdm = pd.DataFrame(fdm_results, index=[f'k2/k1 = {a}' for a in data_dict["k_ratios"]], columns=[f'x = {x:.3f}' for x in x_fdm]) + df_fem = pd.DataFrame(fem_results, index=[f'k2/k1 = {a}' for a in data_dict["k_ratios"]], columns=[f'x = {x:.3f}' for x in x_fem]) + + + foo = "2nd Order" if method=="FDM" else "p=1" + bar = "4th Order" if method=="FDM" else "p=2" + + print(f"{method} {foo} Temperature Results x_bar = 0.5:") + print(df_fdm.to_string()) + print("\n" * 2) + print(f"{method} {bar} Temperature Results x_bar = 0.5:") + print(df_fem.to_string()) + print("\n" * 2) + + # Now that the data is gathered for FDM and FEM, plot it + # Plotting x_bar_1, FDM + plt.figure(figsize=(10, 6)) + for idx, k_ratio in enumerate(data_dict["k_ratios"]): + plt.plot(data_dict["section2"]["x_bar_1"]["x_values"], data_dict["section2"]["x_bar_1"]["fdm_results"][idx], label=f'k2/k1 = {k_ratio}') + plt.axvline(x=x_bar_1, color='r', linestyle='--', label='x_bar') + plt.xlabel('Position (cm)') + plt.ylabel('Temperature (°C)') + plt.legend() + plt.grid(True) + plt.savefig(f'{file_path}x_bar_1/temperature_distribution_1.png', dpi=300) + #plt.show() + plt.clf() + + # Plotting x_bar_1 + plt.figure(figsize=(10, 6)) + for idx, k_ratio in enumerate(data_dict["k_ratios"]): + plt.plot(data_dict["section2"]["x_bar_1"]["x_values"], data_dict["section2"]["x_bar_1"]["fem_results"][idx], label=f'k2/k1 = {k_ratio}') + plt.axvline(x=x_bar_1, color='r', linestyle='--', label='x_bar') + plt.xlabel('Position (cm)') + plt.ylabel('Temperature (°C)') + plt.legend() + plt.grid(True) + plt.savefig(f'{file_path}x_bar_1/temperature_distribution_2.png', dpi=300) + #plt.show() + plt.clf() + + + # Calculate the results for every k ratio for x_bar_2 + x_bar_2 = data_dict["x_bar_values"][1] + + # For every k_ratio, calculate the FDM and FEM temperature results + fdm_results = [] + fem_results = [] + x_fdm = [] + x_fem = [] + for k_ratio in data_dict["k_ratios"]: + Bar.set_k_ratio(k_ratio, bar1, bar2) # Set the k value of bar2 = k*bar1 + fdm_temps, x_fdm = solve(bar1=bar1, + bar2=bar2, + num_sections=data_dict["section2"]["num_sections"], + x_bar=x_bar_2, + l=l, + method=method, order=2) + fem_temps, x_fem = solve(bar1=bar1, + bar2=bar2, + num_sections=data_dict["section2"]["num_sections"], + x_bar=x_bar_2, + l=l, + method=method, order=4) + + fdm_results.append(fdm_temps) + fem_results.append(fem_temps) + + data_dict["section2"]["x_bar_2"] = {} + data_dict["section2"]["x_bar_2"]["x_values"] = x_fdm # fdm and fem use same x_values + data_dict["section2"]["x_bar_2"]["fdm_results"] = np.array(fdm_results) + data_dict["section2"]["x_bar_2"]["fem_results"] = np.array(fem_results) + + df_fdm = pd.DataFrame(fdm_results, index=[f'k2/k1 = {a}' for a in data_dict["k_ratios"]], columns=[f'x = {x:.3f}' for x in x_fdm]) + df_fem = pd.DataFrame(fem_results, index=[f'k2/k1 = {a}' for a in data_dict["k_ratios"]], columns=[f'x = {x:.3f}' for x in x_fem]) + + print(f"{method} {foo} Temperature Results x_bar = 2/pi:") + print(df_fdm.to_string()) + print("\n" * 2) + print(f"{method} {bar} Temperature Results x_bar = 2/pi:") + print(df_fem.to_string()) + print("\n" * 2) + + # Plotting x_bar_2, FDM + plt.figure(figsize=(10, 6)) + for idx, k_ratio in enumerate(data_dict["k_ratios"]): + plt.plot(data_dict["section2"]["x_bar_2"]["x_values"], data_dict["section2"]["x_bar_2"]["fdm_results"][idx], label=f'k2/k1 = {k_ratio}') + plt.axvline(x=x_bar_2, color='r', linestyle='--', label='x_bar') + plt.xlabel('Position (cm)') + plt.ylabel('Temperature (°C)') + plt.legend() + plt.grid(True) + plt.savefig(f'{file_path}x_bar_2/temperature_distribution_1.png', dpi=300) + #plt.show() + plt.clf() + + # Plotting x_bar_2, FEM + plt.figure(figsize=(10, 6)) + for idx, k_ratio in enumerate(data_dict["k_ratios"]): + plt.plot(data_dict["section2"]["x_bar_2"]["x_values"], data_dict["section2"]["x_bar_2"]["fem_results"][idx], label=f'k2/k1 = {k_ratio}') + plt.axvline(x=x_bar_2, color='r', linestyle='--', label='x_bar') + plt.xlabel('Position (cm)') + plt.ylabel('Temperature (°C)') + plt.legend() + plt.grid(True) + plt.savefig(f'{file_path}x_bar_2/temperature_distribution_2.png', dpi=300) + #plt.show() + plt.clf() + + + + # After calculating temperature values, extract the heat convection at x=l + + # x_bar_1 + # for every k ratio, calculate the heat convection from fdm and fem temp results + fdm_heat_results = [] + fem_heat_results = [] + for i, k_ratio in enumerate(data_dict["k_ratios"]): + Bar.set_k_ratio(k_ratio, bar1, bar2) # Set the k value of bar2 = k*bar1 + dx = data_dict["section2"]["x_bar_1"]["x_values"][-1] - data_dict["section2"]["x_bar_1"]["x_values"][-2] + (fdm_t0, fdm_t1) = data_dict["section2"]["x_bar_1"]["fdm_results"][i][-2:] + fdm_heat_result = heat_extraction(fdm_t0, fdm_t1, dx, bar2, order=2, method=method) + fdm_heat_results.append(fdm_heat_result) + + (fem_t0, fem_t1) = data_dict["section2"]["x_bar_1"]["fem_results"][i][-2:] + fem_heat_result = heat_extraction(fem_t0, fem_t1, dx, bar2, order=2, method=method) + fem_heat_results.append(fem_heat_result) + + + data_dict["section2"]["x_bar_1"]["fdm_heat_results"] = np.array(fdm_heat_results) + data_dict["section2"]["x_bar_1"]["fem_heat_results"] = np.array(fem_heat_results) + + # Create DataFrame with two columns for FDM and FEM heat results + df_heat = pd.DataFrame( + { + f"{foo} Heat Convection": fdm_heat_results, + f"{bar} Heat Convection": fem_heat_results + }, + index=[f'k2/k1 = {a}' for a in data_dict["k_ratios"]] + ) + + # Print the DataFrame with labeled columns and indices + print(f"{method} Heat Convection Results for x_bar = 0.5:") + print(df_heat.to_string()) + print("\n") + + # x_bar_2 + # for every k ratio, calculate the heat convection from fdm and fem temp results + fdm_heat_results = [] + fem_heat_results = [] + for i, k_ratio in enumerate(data_dict["k_ratios"]): + Bar.set_k_ratio(k_ratio, bar1, bar2) # Set the k value of bar2 = k*bar1 + dx = data_dict["section2"]["x_bar_2"]["x_values"][-1] - data_dict["section2"]["x_bar_2"]["x_values"][-2] + (fdm_t0, fdm_t1) = data_dict["section2"]["x_bar_2"]["fdm_results"][i][-2:] + fdm_heat_result = heat_extraction(fdm_t0, fdm_t1, dx, bar2, order=2, method=method) + fdm_heat_results.append(fdm_heat_result) + + (fem_t0, fem_t1) = data_dict["section2"]["x_bar_2"]["fem_results"][i][-2:] + fem_heat_result = heat_extraction(fem_t0, fem_t1, dx, bar2, order=4, method=method) + fem_heat_results.append(fem_heat_result) + + + data_dict["section2"]["x_bar_2"]["fdm_heat_results"] = np.array(fdm_heat_results) + data_dict["section2"]["x_bar_2"]["fem_heat_results"] = np.array(fem_heat_results) + + # Create DataFrame with two columns for FDM and FEM heat results + df_heat = pd.DataFrame( + { + f"{foo} Heat Convection": fdm_heat_results, + f"{bar} Heat Convection": fem_heat_results + }, + index=[f'k2/k1 = {a}' for a in data_dict["k_ratios"]] + ) + + # Print the DataFrame with labeled columns and indices + print(f"{method} Heat Convection Results for x_bar = 2/pi:") + print(df_heat.to_string()) + print("\n") + + # Plotting x_bar_1 heat convection + plt.figure(figsize=(10, 6)) + plt.plot(data_dict["k_ratios"], data_dict["section2"]["x_bar_1"]["fdm_heat_results"], label=f'2nd Order') + plt.plot(data_dict["k_ratios"], data_dict["section2"]["x_bar_1"]["fem_heat_results"], label=f'4th Order') + #plt.plot(data_dict["k_ratios"], data_dict["analytical"]["x_bar_1"]["heat_results"], label=f'Analytical Heat Convection') + plt.xlabel('k2/k1') + plt.ylabel('Q_Dot (W)') + plt.legend() + plt.grid(True) + plt.savefig(f'{file_path}x_bar_1/heat_convection.png', dpi=300) + #plt.show() + plt.clf() + + # Plotting x_bar_2 heat convection + plt.figure(figsize=(10, 6)) + plt.plot(data_dict["k_ratios"], data_dict["section2"]["x_bar_2"]["fdm_heat_results"], label=f'2nd Order') + plt.plot(data_dict["k_ratios"], data_dict["section2"]["x_bar_2"]["fem_heat_results"], label=f'4th Order') + #plt.plot(data_dict["k_ratios"], data_dict["analytical"]["x_bar_2"]["heat_results"], label=f'Analytical Heat Convection') + plt.xlabel('k2/k1') + plt.ylabel('Q_Dot (W)') + plt.legend() + plt.grid(True) + plt.savefig(f'{file_path}x_bar_2/heat_convection.png', dpi=300) + #plt.show() + plt.clf() + + +def temp_convergence(): + '''Convergence of FDM and FEM of interface temperature''' + print("Section 3 Temp: Convergence of FDM and FEM Temp with Varying k Ratio") + file_path = "images/convergence/" + l = data_dict["length"] + + data_dict["convergence"] = {} + data_dict["convergence"]["num_sections"] = [4, 8, 16, 32, 64, 128, 256, 512] + + for x_bar_idx, x_bar in enumerate(data_dict["x_bar_values"]): + num_k_ratios = len(data_dict["k_ratios"]) + num_rows = math.ceil(num_k_ratios / 2) + + fig_temp, axs_temp = plt.subplots(num_rows, 2, figsize=(15, 5 * num_rows)) + + axs_temp = axs_temp.flatten() + + for idx, k_ratio in enumerate(data_dict["k_ratios"]): + Bar.set_k_ratio(k_ratio, bar1, bar2) + + # Analytical temperature at the interface + analy_interface_temp = get_analytical_datapoints([x_bar], bar1, bar2, x_bar, l)[0] + convergence_data = { + "fdm_2_values": [], "fdm_4_values": [], "fem_2_values": [], "fem_4_values": [], + "fdm_2_errors": [], "fdm_4_errors": [], "fem_2_errors": [], "fem_4_errors": [], + "fdm_2_extrap": [], "fdm_4_extrap": [], "fem_2_extrap": [], "fem_4_extrap": [], + "fdm_2_b": [], "fdm_4_b": [], "fem_2_b": [], "fem_4_b": [] + } + + # Calculate temperature values and errors for different section counts + for num_sections in data_dict["convergence"]["num_sections"]: + temp_results = { + "FDM_2": solve(bar1, bar2, num_sections, x_bar, l, method="FDM", order=2)[0], + "FDM_4": solve(bar1, bar2, num_sections, x_bar, l, method="FDM", order=4)[0], + "FEM_2": solve(bar1, bar2, num_sections, x_bar, l, method="FEM", order=2)[0], + "FEM_4": solve(bar1, bar2, num_sections, x_bar, l, method="FEM", order=4)[0] + } + + interface_idx = num_sections // 2 + for method, temps in temp_results.items(): + interface_temp = temps[interface_idx] + convergence_data[f"{method.lower()}_values"].append(interface_temp) + error = calc_error(analy_interface_temp, interface_temp) + convergence_data[f"{method.lower()}_errors"].append(error) + + # Calculate convergence rates `B` for each method and apply extrapolation from the third entry onward + for method in ["fdm_2", "fdm_4", "fem_2", "fem_4"]: + values = convergence_data[f"{method}_values"] + errors = convergence_data[f"{method}_errors"] + + # Initialize `extrap` with NaNs for the first two entries + extrapolated_values = [float('NaN')] * 2 + b_values = [float('NaN')] # Initialize `B` list with NaN for the first entry + + # Compute extrapolated values starting from the third entry if possible + for i in range(2, len(values)): + if i >= 2: + extrap_value = calc_extrapolated(values[i - 2], values[i - 1], values[i]) + extrapolated_values.append(extrap_value) + + # Calculate extrapolated error for the current value + extrap_error = calc_error(extrap_value, values[i]) + errors[i] = extrap_error + else: + extrapolated_values.append(float('NaN')) + + # Calculate convergence rates `B` for each consecutive pair + for i in range(1, len(values)): + beta = calc_beta(analy_interface_temp, values[i], values[i - 1], + data_dict["convergence"]["num_sections"][i], + data_dict["convergence"]["num_sections"][i - 1]) + b_values.append(beta) + + # Store the calculated `B` and extrapolated values in the convergence data + convergence_data[f"{method}_b"] = b_values + convergence_data[f"{method}_extrap"] = extrapolated_values + + + + # Prepare data for FDM and FEM tables + rows = data_dict["convergence"]["num_sections"] + fdm_table_data = [] + fem_table_data = [] + + for i, num_sections in enumerate(rows): + # Append data for FDM + fdm_table_data.append([ + analy_interface_temp, + convergence_data["fdm_2_values"][i], + convergence_data["fdm_2_extrap"][i], + convergence_data["fdm_2_errors"][i], + convergence_data["fdm_2_b"][i], + calc_error(convergence_data["fdm_2_extrap"][i], convergence_data["fdm_2_values"][i]) if i >= 2 else float('NaN'), + calc_beta(convergence_data["fdm_2_extrap"][i], convergence_data["fdm_2_values"][i], convergence_data["fdm_2_values"][i-1], num_sections, rows[i-1]) if i >= 3 else float('NaN'), + + convergence_data["fdm_4_values"][i], + convergence_data["fdm_4_extrap"][i], + convergence_data["fdm_4_errors"][i], + convergence_data["fdm_4_b"][i], + calc_error(convergence_data["fdm_4_extrap"][i], convergence_data["fdm_4_values"][i]) if i >= 2 else float('NaN'), + calc_beta(convergence_data["fdm_4_extrap"][i], convergence_data["fdm_4_values"][i], convergence_data["fdm_4_values"][i-1], num_sections, rows[i-1]) if i >= 3 else float('NaN'), + ]) + + # Append data for FEM + fem_table_data.append([ + analy_interface_temp, + convergence_data["fem_2_values"][i], + convergence_data["fem_2_extrap"][i], + convergence_data["fem_2_errors"][i], + convergence_data["fem_2_b"][i], + calc_error(convergence_data["fem_2_extrap"][i], convergence_data["fem_2_values"][i]) if i >= 2 else float('NaN'), + calc_beta(convergence_data["fem_2_extrap"][i], convergence_data["fem_2_values"][i], convergence_data["fem_2_values"][i-1], num_sections, rows[i-1]) if i >= 3 else float('NaN'), + + convergence_data["fem_4_values"][i], + convergence_data["fem_4_extrap"][i], + convergence_data["fem_4_errors"][i], + convergence_data["fem_4_b"][i], + calc_error(convergence_data["fem_4_extrap"][i], convergence_data["fem_4_values"][i]) if i >= 2 else float('NaN'), + calc_beta(convergence_data["fem_4_extrap"][i], convergence_data["fem_4_values"][i], convergence_data["fem_4_values"][i-1], num_sections, rows[i-1]) if i >= 3 else float('NaN'), + ]) + + # Store extrapolated % errors for plotting + if i >= 2: + if "fdm_2_extrap_errors" not in convergence_data: + convergence_data["fdm_2_extrap_errors"] = [float('NaN')] * 2 + convergence_data["fdm_4_extrap_errors"] = [float('NaN')] * 2 + convergence_data["fem_2_extrap_errors"] = [float('NaN')] * 2 + convergence_data["fem_4_extrap_errors"] = [float('NaN')] * 2 + convergence_data["fdm_2_extrap_errors"].append(calc_error(convergence_data["fdm_2_extrap"][i], convergence_data["fdm_2_values"][i])) + convergence_data["fdm_4_extrap_errors"].append(calc_error(convergence_data["fdm_4_extrap"][i], convergence_data["fdm_4_values"][i])) + convergence_data["fem_2_extrap_errors"].append(calc_error(convergence_data["fem_2_extrap"][i], convergence_data["fem_2_values"][i])) + convergence_data["fem_4_extrap_errors"].append(calc_error(convergence_data["fem_4_extrap"][i], convergence_data["fem_4_values"][i])) + else: + if "fdm_2_extrap_errors" in convergence_data: + convergence_data["fdm_2_extrap_errors"].append(float('NaN')) + convergence_data["fdm_4_extrap_errors"].append(float('NaN')) + convergence_data["fem_2_extrap_errors"].append(float('NaN')) + convergence_data["fem_4_extrap_errors"].append(float('NaN')) + + + # Update columns for new fields + fdm_columns = [ + 'True T', 'FDM 2 T', 'FDM 2 Extrap T', 'FDM 2 % Error', 'FDM 2 Exact B', + 'FDM 2 Extrap % Error', 'FDM 2 Extrap B', + 'FDM 4 T', 'FDM 4 Extrap T', 'FDM 4 % Error', 'FDM 4 Exact B', + 'FDM 4 Extrap % Error', 'FDM 4 Extrap B' + ] + + fem_columns = [ + 'True T', 'FEM 2 T', 'FEM 2 Extrap T', 'FEM 2 % Error', 'FEM 2 Exact B', + 'FEM 2 Extrap % Error', 'FEM 2 Extrap B', + 'FEM 4 T', 'FEM 4 Extrap T', 'FEM 4 % Error', 'FEM 4 Exact B', + 'FEM 4 Extrap % Error', 'FEM 4 Extrap B' + ] + + fdm_df = pd.DataFrame(fdm_table_data, index=[f'N = {n}' for n in rows], columns=fdm_columns) + fem_df = pd.DataFrame(fem_table_data, index=[f'N = {n}' for n in rows], columns=fem_columns) + + print(f"Convergence of FDM Temperature at x_bar = {x_bar:.3f} and k_ratio = {k_ratio}") + print(fdm_df.to_string()) + print("\n") + + print(f"Convergence of FEM Temperature at x_bar = {x_bar:.3f} and k_ratio = {k_ratio}") + print(fem_df.to_string()) + print("\n") + + # Plot convergence for FDM and FEM errors and extrapolated errors + ax_temp = axs_temp[idx] + num_sections = data_dict["convergence"]["num_sections"] + + # Plot analytical error convergence for FDM and FEM, orders 2 and 4 + ax_temp.plot(num_sections, convergence_data["fdm_2_errors"], 'o-', label="FDM 2 % Error (Analytical)") + ax_temp.plot(num_sections, convergence_data["fdm_4_errors"], 's-', label="FDM 4 % Error (Analytical)") + ax_temp.plot(num_sections, convergence_data["fem_2_errors"], '^-', label="FEM 2 % Error (Analytical)") + ax_temp.plot(num_sections, convergence_data["fem_4_errors"], 'd-', label="FEM 4 % Error (Analytical)") + + # Plot extrapolated error convergence for FDM and FEM, orders 2 and 4 + ax_temp.plot(num_sections, convergence_data["fdm_2_extrap_errors"], 'o--', label="FDM 2 % Error (Extrapolated)") + ax_temp.plot(num_sections, convergence_data["fdm_4_extrap_errors"], 's--', label="FDM 4 % Error (Extrapolated)") + ax_temp.plot(num_sections, convergence_data["fem_2_extrap_errors"], '^--', label="FEM 2 % Error (Extrapolated)") + ax_temp.plot(num_sections, convergence_data["fem_4_extrap_errors"], 'd--', label="FEM 4 % Error (Extrapolated)") + + # Set log scales, labels, and legends + ax_temp.set_xscale("log") + ax_temp.set_yscale("log") + ax_temp.set_xlabel("Number of Sections (N)") + ax_temp.set_ylabel("% Error") + ax_temp.set_title(f"Interface Temp Convergence (k_ratio={k_ratio})") + ax_temp.legend() + ax_temp.grid(True) + + + fig_temp.tight_layout(rect=[0, 0.03, 1, 0.95]) + x_bar_path = "x_bar_1/" if x_bar_idx == 0 else "x_bar_2/" + fig_temp.savefig(f"{file_path+x_bar_path}temp_convergence.png", dpi=300) + + +def heat_convergence(): + '''Convergence of FDM and FEM of interface heat convection''' + print("Section 3 Temp: Convergence of FDM and FEM Temp with Varying k Ratio") + file_path = "images/convergence/" + l = data_dict["length"] + + data_dict["convergence"] = {} + data_dict["convergence"]["num_sections"] = [4, 8, 16, 32, 64, 128, 256, 512] + + for x_bar_idx, x_bar in enumerate(data_dict["x_bar_values"]): + num_k_ratios = len(data_dict["k_ratios"]) + num_rows = math.ceil(num_k_ratios / 2) + + fig_heat, axs_heat = plt.subplots(num_rows, 2, figsize=(15, 5 * num_rows)) + + axs_heat = axs_heat.flatten() + + for idx, k_ratio in enumerate(data_dict["k_ratios"]): + Bar.set_k_ratio(k_ratio, bar1, bar2) + + # Analytical temperature at the interface + analy_heat = get_analytical_heat_convection(l, bar1, bar2, x_bar, l) + convergence_data = { + "fdm_2_values": [], "fdm_4_values": [], "fem_2_values": [], "fem_4_values": [], + "fdm_2_errors": [], "fdm_4_errors": [], "fem_2_errors": [], "fem_4_errors": [], + "fdm_2_extrap": [], "fdm_4_extrap": [], "fem_2_extrap": [], "fem_4_extrap": [], + "fdm_2_b": [], "fdm_4_b": [], "fem_2_b": [], "fem_4_b": [] + } + + # Calculate temperature values and errors for different section counts + for num_sections in data_dict["convergence"]["num_sections"]: + temp_results = { + "FDM_2": solve(bar1, bar2, num_sections, x_bar, l, method="FDM", order=2)[0], + "FDM_4": solve(bar1, bar2, num_sections, x_bar, l, method="FDM", order=4)[0], + "FEM_2": solve(bar1, bar2, num_sections, x_bar, l, method="FEM", order=2)[0], + "FEM_4": solve(bar1, bar2, num_sections, x_bar, l, method="FEM", order=4)[0] + } + + dx = (l - x_bar) / (num_sections // 2) + for method, temps in temp_results.items(): + heat = heat_extraction(temps[-2], temps[-1], dx, bar2, order=int(method[-1]), method=method[:3]) + convergence_data[f"{method.lower()}_values"].append(heat) + error = calc_error(analy_heat, heat) + convergence_data[f"{method.lower()}_errors"].append(error) + + # Calculate convergence rates `B` for each method and apply extrapolation from the third entry onward + for method in ["fdm_2", "fdm_4", "fem_2", "fem_4"]: + values = convergence_data[f"{method}_values"] + errors = convergence_data[f"{method}_errors"] + + # Initialize `extrap` with NaNs for the first two entries + extrapolated_values = [float('NaN')] * 2 + b_values = [float('NaN')] # Initialize `B` list with NaN for the first entry + + # Compute extrapolated values starting from the third entry if possible + for i in range(2, len(values)): + if i >= 2: + extrap_value = calc_extrapolated(values[i - 2], values[i - 1], values[i]) + extrapolated_values.append(extrap_value) + + # Calculate extrapolated error for the current value + extrap_error = calc_error(extrap_value, values[i]) + errors[i] = extrap_error + else: + extrapolated_values.append(float('NaN')) + + # Calculate convergence rates `B` for each consecutive pair + for i in range(1, len(values)): + beta = calc_beta(analy_heat, values[i], values[i - 1], + data_dict["convergence"]["num_sections"][i], + data_dict["convergence"]["num_sections"][i - 1]) + b_values.append(beta) + + # Store the calculated `B` and extrapolated values in the convergence data + convergence_data[f"{method}_b"] = b_values + convergence_data[f"{method}_extrap"] = extrapolated_values + + + + # Prepare data for FDM and FEM tables + rows = data_dict["convergence"]["num_sections"] + fdm_table_data = [] + fem_table_data = [] + + for i, num_sections in enumerate(rows): + # Append data for FDM + fdm_table_data.append([ + analy_heat, + convergence_data["fdm_2_values"][i], + convergence_data["fdm_2_extrap"][i], + convergence_data["fdm_2_errors"][i], + convergence_data["fdm_2_b"][i], + calc_error(convergence_data["fdm_2_extrap"][i], convergence_data["fdm_2_values"][i]) if i >= 2 else float('NaN'), + calc_beta(convergence_data["fdm_2_extrap"][i], convergence_data["fdm_2_values"][i], convergence_data["fdm_2_values"][i-1], num_sections, rows[i-1]) if i >= 3 else float('NaN'), + + convergence_data["fdm_4_values"][i], + convergence_data["fdm_4_extrap"][i], + convergence_data["fdm_4_errors"][i], + convergence_data["fdm_4_b"][i], + calc_error(convergence_data["fdm_4_extrap"][i], convergence_data["fdm_4_values"][i]) if i >= 2 else float('NaN'), + calc_beta(convergence_data["fdm_4_extrap"][i], convergence_data["fdm_4_values"][i], convergence_data["fdm_4_values"][i-1], num_sections, rows[i-1]) if i >= 3 else float('NaN'), + ]) + + # Append data for FEM + fem_table_data.append([ + analy_heat, + convergence_data["fem_2_values"][i], + convergence_data["fem_2_extrap"][i], + convergence_data["fem_2_errors"][i], + convergence_data["fem_2_b"][i], + calc_error(convergence_data["fem_2_extrap"][i], convergence_data["fem_2_values"][i]) if i >= 2 else float('NaN'), + calc_beta(convergence_data["fem_2_extrap"][i], convergence_data["fem_2_values"][i], convergence_data["fem_2_values"][i-1], num_sections, rows[i-1]) if i >= 3 else float('NaN'), + + convergence_data["fem_4_values"][i], + convergence_data["fem_4_extrap"][i], + convergence_data["fem_4_errors"][i], + convergence_data["fem_4_b"][i], + calc_error(convergence_data["fem_4_extrap"][i], convergence_data["fem_4_values"][i]) if i >= 2 else float('NaN'), + calc_beta(convergence_data["fem_4_extrap"][i], convergence_data["fem_4_values"][i], convergence_data["fem_4_values"][i-1], num_sections, rows[i-1]) if i >= 3 else float('NaN'), + ]) + + # Store extrapolated % errors for plotting + if i >= 2: + if "fdm_2_extrap_errors" not in convergence_data: + convergence_data["fdm_2_extrap_errors"] = [float('NaN')] * 2 + convergence_data["fdm_4_extrap_errors"] = [float('NaN')] * 2 + convergence_data["fem_2_extrap_errors"] = [float('NaN')] * 2 + convergence_data["fem_4_extrap_errors"] = [float('NaN')] * 2 + convergence_data["fdm_2_extrap_errors"].append(calc_error(convergence_data["fdm_2_extrap"][i], convergence_data["fdm_2_values"][i])) + convergence_data["fdm_4_extrap_errors"].append(calc_error(convergence_data["fdm_4_extrap"][i], convergence_data["fdm_4_values"][i])) + convergence_data["fem_2_extrap_errors"].append(calc_error(convergence_data["fem_2_extrap"][i], convergence_data["fem_2_values"][i])) + convergence_data["fem_4_extrap_errors"].append(calc_error(convergence_data["fem_4_extrap"][i], convergence_data["fem_4_values"][i])) + else: + if "fdm_2_extrap_errors" in convergence_data: + convergence_data["fdm_2_extrap_errors"].append(float('NaN')) + convergence_data["fdm_4_extrap_errors"].append(float('NaN')) + convergence_data["fem_2_extrap_errors"].append(float('NaN')) + convergence_data["fem_4_extrap_errors"].append(float('NaN')) + + + # Update columns for new fields + fdm_columns = [ + 'True Q', 'FDM 2 Q', 'FDM 2 Extrap Q', 'FDM 2 % Error', 'FDM 2 Exact B', + 'FDM 2 Extrap % Error', 'FDM 2 Extrap B', + 'FDM 4 Q', 'FDM 4 Extrap Q', 'FDM 4 % Error', 'FDM 4 Exact B', + 'FDM 4 Extrap % Error', 'FDM 4 Extrap B' + ] + + fem_columns = [ + 'True Q', 'FEM 2 Q', 'FEM 2 Extrap Q', 'FEM 2 % Error', 'FEM 2 Exact B', + 'FEM 2 Extrap % Error', 'FEM 2 Extrap B', + 'FEM 4 Q', 'FEM 4 Extrap Q', 'FEM 4 % Error', 'FEM 4 Exact B', + 'FEM 4 Extrap % Error', 'FEM 4 Extrap B' + ] + + fdm_df = pd.DataFrame(fdm_table_data, index=[f'N = {n}' for n in rows], columns=fdm_columns) + fem_df = pd.DataFrame(fem_table_data, index=[f'N = {n}' for n in rows], columns=fem_columns) + + print(f"Convergence of FDM Heat with x_bar = {x_bar:.3f} and k_ratio = {k_ratio}") + print(fdm_df.to_string()) + print("\n") + + print(f"Convergence of FEM Heat with x_bar = {x_bar:.3f} and k_ratio = {k_ratio}") + print(fem_df.to_string()) + print("\n") + + # Plot convergence for FDM and FEM errors and extrapolated errors + ax_heat = axs_heat[idx] + num_sections = data_dict["convergence"]["num_sections"] + + # Plot analytical error convergence for FDM and FEM, orders 2 and 4 + ax_heat.plot(num_sections, convergence_data["fdm_2_errors"], 'o-', label="FDM 2 % Error (Analytical)") + ax_heat.plot(num_sections, convergence_data["fdm_4_errors"], 's-', label="FDM 4 % Error (Analytical)") + ax_heat.plot(num_sections, convergence_data["fem_2_errors"], '^-', label="FEM 2 % Error (Analytical)") + ax_heat.plot(num_sections, convergence_data["fem_4_errors"], 'd-', label="FEM 4 % Error (Analytical)") + + # Plot extrapolated error convergence for FDM and FEM, orders 2 and 4 + ax_heat.plot(num_sections, convergence_data["fdm_2_extrap_errors"], 'o--', label="FDM 2 % Error (Extrapolated)") + ax_heat.plot(num_sections, convergence_data["fdm_4_extrap_errors"], 's--', label="FDM 4 % Error (Extrapolated)") + ax_heat.plot(num_sections, convergence_data["fem_2_extrap_errors"], '^--', label="FEM 2 % Error (Extrapolated)") + ax_heat.plot(num_sections, convergence_data["fem_4_extrap_errors"], 'd--', label="FEM 4 % Error (Extrapolated)") + + # Set log scales, labels, and legends + ax_heat.set_xscale("log") + ax_heat.set_yscale("log") + ax_heat.set_xlabel("Number of Sections (N)") + ax_heat.set_ylabel("% Error") + ax_heat.set_title(f"Interface Heat Convergence (k_ratio={k_ratio})") + ax_heat.legend() + ax_heat.grid(True) + + + fig_heat.tight_layout(rect=[0, 0.03, 1, 0.95]) + x_bar_path = "x_bar_1/" if x_bar_idx == 0 else "x_bar_2/" + fig_heat.savefig(f"{file_path+x_bar_path}heat_convergence.png", dpi=300) + + + + + +def clear_directory(): + # Make directories for plots + import os + import shutil + + base_dir = "images" + sub_dirs = ["analytical", "convergence", "FDM", "FEM"] + nested_dirs = ["x_bar_1", "x_bar_2"] + + # Create the base directory if it doesn't exist + if not os.path.exists(base_dir): + os.mkdir(base_dir) + + # Create or clear subdirectories and their nested directories + for sub_dir in sub_dirs: + section_path = os.path.join(base_dir, sub_dir) + try: + if os.path.exists(section_path): + shutil.rmtree(section_path) # Remove all contents of the directory + os.makedirs(section_path) # Recreate the directory + except PermissionError as e: + pass + except Exception as e: + pass + + # Create nested directories within each section + for nested_dir in nested_dirs: + nested_path = os.path.join(section_path, nested_dir) + try: + os.makedirs(nested_path) # Create the nested directory + except PermissionError as e: + pass + except Exception as e: + pass + +def redirect_stdout(): + # Redirect all print statements to a file + sys.stdout = open("output.txt", "w", encoding="utf-8") + +def restore_stdout(): + # Restore original stdout and close the file + sys.stdout.close() + sys.stdout = sys.__stdout__ + + +def main(): + # Delete previous images from other runs + clear_directory() + + + redirect_stdout() # Redirects the stdout to output.txt + + analytical() # Analytical solutions + section_2(method="FDM") # FDM temperature and heat convection for different k ratios + section_2(method="FEM") # FEM temperature and heat convection for different k ratios + temp_convergence() # Convergence of FDM and FEM temperature + heat_convergence() # Convergence of FDM and FEM temperature + + restore_stdout() + + + +if __name__ == "__main__": + main() \ No newline at end of file diff --git a/HW4/output.txt b/HW4/output.txt new file mode 100644 index 0000000..ef73a17 --- /dev/null +++ b/HW4/output.txt @@ -0,0 +1,1089 @@ +Section 1: Analytical +Analytical Temperature Results x_bar = 0.5: + x = 0.000 x = 0.125 x = 0.250 x = 0.375 x = 0.500 x = 0.500 x = 0.625 x = 0.750 x = 0.875 x = 1.000 +k2/k1 = 0.0625 0.0 0.011667 0.025181 0.042681 0.066937 0.066937 0.847794 4.228179 20.573130 100.0 +k2/k1 = 0.125 0.0 0.097641 0.210739 0.357195 0.560194 0.560194 3.303981 10.626282 32.674022 100.0 +k2/k1 = 0.25 0.0 0.464798 1.003171 1.700341 2.666666 2.666666 8.626608 20.264910 45.242343 100.0 +k2/k1 = 0.5 0.0 1.470842 3.174511 5.380689 8.438605 8.438605 17.437015 32.027881 56.890833 100.0 +k2/k1 = 1.0 0.0 3.440413 7.425426 12.585848 19.738549 19.738549 30.015765 45.044332 67.203196 100.0 +k2/k1 = 2.0 0.0 6.351689 13.708819 23.235988 36.441301 36.441301 45.815586 58.792577 76.392720 100.0 +k2/k1 = 4.0 0.0 9.653341 20.834759 35.314219 55.383747 55.383747 62.464754 71.993744 84.344156 100.0 +k2/k1 = 8.0 0.0 12.567937 27.125318 45.976504 72.105546 72.105546 76.701212 82.797389 90.513336 100.0 +k2/k1 = 16.0 0.0 14.652807 31.625083 53.603455 84.066993 84.066993 86.741990 90.264767 94.669752 100.0 + + + +Analytical Temperature Results x_bar = 2/pi: + x = 0.000 x = 0.125 x = 0.250 x = 0.375 x = 0.500 x = 0.625 x = 0.637 x = 0.750 x = 0.875 x = 1.000 +k2/k1 = 0.0625 0.0 0.043265 0.093379 0.158275 0.248224 0.377466 0.392138 4.086217 20.545109 100.0 +k2/k1 = 0.125 0.0 0.217770 0.470012 0.796654 1.249403 1.899926 1.973771 10.004385 32.490342 100.0 +k2/k1 = 0.25 0.0 0.723845 1.562272 2.647999 4.152891 6.315166 6.560619 18.929061 44.739811 100.0 +k2/k1 = 0.5 0.0 1.775153 3.831304 6.493931 10.184517 15.487261 16.089210 30.677503 56.308955 100.0 +k2/k1 = 1.0 0.0 3.440413 7.425426 12.585848 19.738549 30.015765 31.182398 45.044332 67.203196 100.0 +k2/k1 = 2.0 0.0 5.484175 11.836467 20.062415 31.464146 47.846498 49.706164 60.645947 77.284348 100.0 +k2/k1 = 4.0 0.0 7.434698 16.046273 27.197894 42.654810 64.863775 67.384857 74.763593 85.702464 100.0 +k2/k1 = 8.0 0.0 8.921798 19.255874 32.638061 51.186694 77.837932 80.863285 85.279652 91.742445 100.0 +k2/k1 = 16.0 0.0 9.877475 21.318505 36.134152 56.669658 86.175696 89.525116 91.966805 95.516633 100.0 + + + +Analytical Heat Convection Results x_bar = 0.5: + Heat Convection +k2/k1 = 0.0625 -1.241829 +k2/k1 = 0.125 -1.756437 +k2/k1 = 0.25 -2.486946 +k2/k1 = 0.5 -3.529489 +k2/k1 = 1.0 -4.985127 +k2/k1 = 2.0 -6.832006 +k2/k1 = 4.0 -8.797049 +k2/k1 = 8.0 -10.486214 +k2/k1 = 16.0 -11.680625 + + + +Analytical Heat Convection Results x_bar = 2/pi: + Heat Convection +k2/k1 = 0.0625 -1.241978 +k2/k1 = 0.125 -1.758799 +k2/k1 = 0.25 -2.501202 +k2/k1 = 0.5 -3.564213 +k2/k1 = 1.0 -4.985127 +k2/k1 = 2.0 -6.610807 +k2/k1 = 4.0 -8.118713 +k2/k1 = 8.0 -9.254592 +k2/k1 = 16.0 -9.980639 + + + +Section 2: FDM with Varying k_ratio +FDM 2nd Order Temperature Results x_bar = 0.5: + x = 0.000 x = 0.125 x = 0.250 x = 0.375 x = 0.500 x = 0.625 x = 0.750 x = 0.875 x = 1.000 +k2/k1 = 0.0625 0.0 0.023566 0.050814 0.086002 0.134628 1.249213 5.486829 23.441518 100.0 +k2/k1 = 0.125 0.0 0.131160 0.282813 0.478656 0.749289 3.850963 11.766340 34.389643 100.0 +k2/k1 = 0.25 0.0 0.522237 1.126073 1.905858 2.983433 9.158380 21.057315 46.117073 100.0 +k2/k1 = 0.5 0.0 1.534785 3.309379 5.601064 8.767916 17.841592 32.490766 57.293304 100.0 +k2/k1 = 1.0 0.0 3.487383 7.519670 12.726906 19.922720 30.231460 45.263865 67.368749 100.0 +k2/k1 = 2.0 0.0 6.373779 13.743460 23.260557 36.412116 45.832593 58.833740 76.431273 100.0 +k2/k1 = 4.0 0.0 9.664493 20.839062 35.269736 55.211305 62.353389 71.931152 84.318726 100.0 +k2/k1 = 8.0 0.0 12.587755 27.142347 45.937931 71.911316 76.562507 82.709060 90.471024 100.0 +k2/k1 = 16.0 0.0 14.689868 31.675027 53.609410 83.920263 86.634225 90.194225 94.635027 100.0 + + + +FDM 4th Order Temperature Results x_bar = 0.5: + x = 0.000 x = 0.125 x = 0.250 x = 0.375 x = 0.500 x = 0.625 x = 0.750 x = 0.875 x = 1.000 +k2/k1 = 0.0625 0.0 0.012407 0.026778 0.045387 0.071181 0.872956 4.311784 20.775791 100.0 +k2/k1 = 0.125 0.0 0.099063 0.213805 0.362390 0.568335 3.324588 10.669465 32.740427 100.0 +k2/k1 = 0.25 0.0 0.466246 1.006291 1.705616 2.674914 8.638042 20.281132 45.260122 100.0 +k2/k1 = 0.5 0.0 1.471712 3.176373 5.383805 8.443410 17.441951 32.033043 56.895148 100.0 +k2/k1 = 1.0 0.0 3.440655 7.425912 12.586575 19.739499 30.016879 45.045466 67.204053 100.0 +k2/k1 = 2.0 0.0 6.351568 13.708490 23.235255 36.439800 45.814649 58.792070 76.392524 100.0 +k2/k1 = 4.0 0.0 9.653156 20.834256 35.313096 55.381453 62.463124 71.992703 84.343652 100.0 +k2/k1 = 8.0 0.0 12.567869 27.125037 45.975677 72.103555 76.699755 82.796434 90.512864 100.0 +k2/k1 = 16.0 0.0 14.652898 31.625124 53.603116 84.065651 86.740995 90.264109 94.669425 100.0 + + + +FDM 2nd Order Temperature Results x_bar = 2/pi: + x = 0.000 x = 0.159 x = 0.318 x = 0.477 x = 0.637 x = 0.727 x = 0.818 x = 0.909 x = 1.000 +k2/k1 = 0.0625 0.0 0.077055 0.173629 0.314183 0.534322 3.515595 11.139042 33.471059 100.0 +k2/k1 = 0.125 0.0 0.319719 0.720423 1.303613 2.217011 8.401972 20.134133 45.159372 100.0 +k2/k1 = 0.25 0.0 0.980497 2.209358 3.997855 6.799021 16.282888 31.141948 56.281369 100.0 +k2/k1 = 0.5 0.0 2.330072 5.250358 9.500576 16.157318 27.426136 43.221817 66.151538 100.0 +k2/k1 = 1.0 0.0 4.469024 10.070065 18.221884 30.989359 41.796025 56.052044 74.933939 100.0 +k2/k1 = 2.0 0.0 7.113289 16.028395 29.003540 49.325368 57.925784 68.916457 82.750907 100.0 +k2/k1 = 4.0 0.0 9.660074 21.767073 39.387737 66.985431 72.825251 80.167607 89.163985 100.0 +k2/k1 = 8.0 0.0 11.617645 26.178075 47.369488 80.559732 84.071349 88.450249 93.741604 100.0 +k2/k1 = 16.0 0.0 12.883057 29.029430 52.529043 89.334419 91.281472 93.699357 96.600545 100.0 + + + +FDM 4th Order Temperature Results x_bar = 2/pi: + x = 0.000 x = 0.159 x = 0.318 x = 0.477 x = 0.637 x = 0.727 x = 0.818 x = 0.909 x = 1.000 +k2/k1 = 0.0625 0.0 0.056906 0.128532 0.233402 0.398641 3.008594 10.028399 31.747344 100.0 +k2/k1 = 0.125 0.0 0.282730 0.638587 1.159615 1.980577 7.908859 19.346064 44.258786 100.0 +k2/k1 = 0.25 0.0 0.937019 2.116398 3.843183 6.564006 15.927669 30.693906 55.871337 100.0 +k2/k1 = 0.5 0.0 2.296558 5.187121 9.419332 16.087851 27.280752 43.038453 65.997640 100.0 +k2/k1 = 1.0 0.0 4.450576 10.052292 18.254031 31.177173 41.886144 56.075679 74.924868 100.0 +k2/k1 = 2.0 0.0 7.094631 16.024287 29.098623 49.699312 58.180432 69.070572 82.820650 100.0 +k2/k1 = 4.0 0.0 9.618383 21.724560 39.449790 67.378702 73.109297 80.350881 89.253120 100.0 +k2/k1 = 8.0 0.0 11.542702 26.070922 47.342381 80.858940 84.291953 88.595273 93.813330 100.0 +k2/k1 = 16.0 0.0 12.779433 28.864263 52.414830 89.522484 91.421372 93.792016 96.646648 100.0 + + + +FDM Heat Convection Results for x_bar = 0.5: + 2nd Order Heat Convection 4th Order Heat Convection +k2/k1 = 0.0625 -1.583037 -1.603973 +k2/k1 = 0.125 -2.012353 -2.038259 +k2/k1 = 0.25 -2.674530 -2.701452 +k2/k1 = 0.5 -3.665089 -3.690105 +k2/k1 = 1.0 -5.082312 -5.103008 +k2/k1 = 2.0 -6.905215 -6.914954 +k2/k1 = 4.0 -8.864016 -8.851486 +k2/k1 = 8.0 -10.561319 -10.519257 +k2/k1 = 16.0 -11.768665 -11.699504 + + +FDM Heat Convection Results for x_bar = 2/pi: + 2nd Order Heat Convection 4th Order Heat Convection +k2/k1 = 0.0625 -1.432463 -1.253695 +k2/k1 = 0.125 -1.898803 -1.763475 +k2/k1 = 0.25 -2.603336 -2.502977 +k2/k1 = 0.5 -3.639854 -3.564905 +k2/k1 = 1.0 -5.047653 -4.985553 +k2/k1 = 2.0 -6.678556 -6.611422 +k2/k1 = 4.0 -8.208090 -8.119747 +k2/k1 = 8.0 -9.370579 -9.256061 +k2/k1 = 16.0 -10.118258 -9.982436 + + +Section 2: FEM with Varying k_ratio +FEM p=1 Temperature Results x_bar = 0.5: + x = 0.000 x = 0.125 x = 0.250 x = 0.375 x = 0.500 x = 0.625 x = 0.750 x = 0.875 x = 1.000 +k2/k1 = 0.0625 0.0 0.008040 0.017369 0.029485 0.046331 0.431694 2.667176 16.333414 100.0 +k2/k1 = 0.125 0.0 0.092421 0.199668 0.338947 0.532604 2.747608 9.300941 30.539969 100.0 +k2/k1 = 0.25 0.0 0.461952 0.998014 1.694185 2.662150 8.197855 19.452994 44.279989 100.0 +k2/k1 = 0.5 0.0 1.463251 3.161248 5.366397 8.432466 17.199749 31.637279 56.504681 100.0 +k2/k1 = 1.0 0.0 3.408346 7.363486 12.499933 19.641717 29.852520 44.852497 67.048062 100.0 +k2/k1 = 2.0 0.0 6.282365 13.572595 23.040247 36.204196 45.614623 58.635706 76.298138 100.0 +k2/k1 = 4.0 0.0 9.556088 20.645239 35.046460 55.070107 62.227195 71.830962 84.259013 100.0 +k2/k1 = 8.0 0.0 12.463187 26.925816 45.708094 71.823222 76.490410 82.656431 90.442107 100.0 +k2/k1 = 16.0 0.0 14.553527 31.441845 53.374310 83.869497 86.594484 90.166500 94.620483 100.0 + + + +FEM p=2 Temperature Results x_bar = 0.5: + x = 0.000 x = 0.125 x = 0.250 x = 0.375 x = 0.500 x = 0.625 x = 0.750 x = 0.875 x = 1.000 +k2/k1 = 0.0625 0.0 0.012068 0.026047 0.044148 0.069238 0.867408 4.294089 20.733162 100.0 +k2/k1 = 0.125 0.0 0.098218 0.211984 0.359304 0.563499 3.316456 10.653512 32.716155 100.0 +k2/k1 = 0.25 0.0 0.465290 1.004231 1.702131 2.669460 8.632229 20.273710 45.252255 100.0 +k2/k1 = 0.5 0.0 1.471126 3.175116 5.381693 8.440137 17.439069 32.030325 56.892999 100.0 +k2/k1 = 1.0 0.0 3.440538 7.425677 12.586223 19.739039 30.016340 45.044917 67.203638 100.0 +k2/k1 = 2.0 0.0 6.351749 13.708915 23.236059 36.441232 45.815587 58.792618 76.392764 100.0 +k2/k1 = 4.0 0.0 9.653407 20.834849 35.314232 55.383492 62.464580 71.993637 84.344107 100.0 +k2/k1 = 8.0 0.0 12.568039 27.125469 45.976580 72.105307 76.701038 82.797275 90.513280 100.0 +k2/k1 = 16.0 0.0 14.652946 31.625303 53.603617 84.066829 86.741869 90.264686 94.669712 100.0 + + + +FEM p=1 Temperature Results x_bar = 2/pi: + x = 0.000 x = 0.159 x = 0.318 x = 0.477 x = 0.637 x = 0.727 x = 0.818 x = 0.909 x = 1.000 +k2/k1 = 0.0625 0.0 0.051867 0.117450 0.214096 0.367363 2.434575 8.623646 29.412987 100.0 +k2/k1 = 0.125 0.0 0.275874 0.624708 1.138757 1.953971 7.451625 18.477330 43.210596 100.0 +k2/k1 = 0.25 0.0 0.917965 2.078702 3.789190 6.501798 15.648464 30.261653 55.446231 100.0 +k2/k1 = 0.5 0.0 2.241155 5.075024 9.251075 15.873740 27.039252 42.794017 65.812018 100.0 +k2/k1 = 1.0 0.0 4.339198 9.825975 17.911409 30.733838 41.542855 55.828147 74.785094 100.0 +k2/k1 = 2.0 0.0 6.933484 15.700652 28.620142 49.108745 57.744459 68.779447 82.672214 100.0 +k2/k1 = 4.0 0.0 9.434441 21.363990 38.943632 66.822621 72.697960 80.078383 89.116689 100.0 +k2/k1 = 8.0 0.0 11.358900 25.721867 46.887445 80.453254 83.990156 88.394995 93.713291 100.0 +k2/k1 = 16.0 0.0 12.604001 28.541357 52.026991 89.272101 91.234400 93.667692 96.584539 100.0 + + + +FEM p=2 Temperature Results x_bar = 2/pi: + x = 0.000 x = 0.159 x = 0.318 x = 0.477 x = 0.637 x = 0.727 x = 0.818 x = 0.909 x = 1.000 +k2/k1 = 0.0625 0.0 0.056356 0.127290 0.231150 0.394802 3.000696 10.011857 31.721242 100.0 +k2/k1 = 0.125 0.0 0.282083 0.637133 1.156990 1.976128 7.903319 19.338326 44.250198 100.0 +k2/k1 = 0.25 0.0 0.936679 2.115650 3.841878 6.561891 15.925358 30.691359 55.869129 100.0 +k2/k1 = 0.5 0.0 2.296689 5.187467 9.420092 16.089426 27.281478 43.038618 65.997532 100.0 +k2/k1 = 1.0 0.0 4.451072 10.053508 18.256499 31.181922 41.889346 56.077632 74.925778 100.0 +k2/k1 = 2.0 0.0 7.095212 16.025752 29.101694 49.705410 58.184789 69.073373 82.822018 100.0 +k2/k1 = 4.0 0.0 9.618769 21.725639 39.452308 67.384157 73.113291 80.353498 89.254414 100.0 +k2/k1 = 8.0 0.0 11.542780 26.071346 47.343822 80.862788 84.294805 88.597158 93.814267 100.0 +k2/k1 = 16.0 0.0 12.779243 28.864110 52.415295 89.524814 91.423109 93.793169 96.647223 100.0 + + + +FEM Heat Convection Results for x_bar = 0.5: + p=1 Heat Convection p=2 Heat Convection +k2/k1 = 0.0625 -1.638864 -1.604308 +k2/k1 = 0.125 -2.072823 -2.038640 +k2/k1 = 0.25 -2.732243 -2.701699 +k2/k1 = 0.5 -3.714639 -3.690240 +k2/k1 = 1.0 -5.122610 -5.103060 +k2/k1 = 2.0 -6.938675 -6.914893 +k2/k1 = 4.0 -8.894031 -8.851258 +k2/k1 = 8.0 -10.590389 -10.518839 +k2/k1 = 16.0 -11.797909 -11.698927 + + +FEM Heat Convection Results for x_bar = 2/pi: + p=1 Heat Convection p=2 Heat Convection +k2/k1 = 0.0625 -1.476318 -1.253926 +k2/k1 = 0.125 -1.940923 -1.763642 +k2/k1 = 0.25 -2.639437 -2.503068 +k2/k1 = 0.5 -3.669207 -3.564914 +k2/k1 = 1.0 -5.073389 -4.985398 +k2/k1 = 2.0 -6.705769 -6.610952 +k2/k1 = 4.0 -8.240802 -8.118855 +k2/k1 = 8.0 -9.409744 -9.254767 +k2/k1 = 16.0 -10.162539 -9.980847 + + +Section 3 Temp: Convergence of FDM and FEM Temp with Varying k Ratio +Convergence of FDM Temperature at x_bar = 0.500 and k_ratio = 0.0625 + True T FDM 2 T FDM 2 Extrap T FDM 2 % Error FDM 2 Exact B FDM 2 Extrap % Error FDM 2 Extrap B FDM 4 T FDM 4 Extrap T FDM 4 % Error FDM 4 Exact B FDM 4 Extrap % Error FDM 4 Extrap B +N = 4 0.066937 0.400229 NaN 4.979197 NaN NaN NaN 0.104810 NaN 5.658100e-01 NaN NaN NaN +N = 8 0.066937 0.134628 NaN 1.011272 -2.299743 NaN NaN 0.071181 NaN 6.340026e-02 -3.157757 NaN NaN +N = 16 0.066937 0.082453 0.069697 0.183010 -2.125242 0.183010 NaN 0.067277 0.066765 7.677697e-03 -3.640568 7.677697e-03 NaN +N = 32 0.066937 0.070718 0.067312 0.050588 -2.036995 0.050588 -2.152561 0.066960 0.066932 4.195795e-04 -3.891466 4.195795e-04 -3.620631 +N = 64 0.066937 0.067876 0.066968 0.013561 -2.009682 0.013561 -2.045906 0.066938 0.066937 2.326877e-05 -3.971390 2.326877e-05 -3.885859 +N = 128 0.066937 0.067171 0.066939 0.003469 -2.002449 0.003469 -2.012080 0.066937 0.066937 1.395107e-06 -3.992773 1.395107e-06 -3.969945 +N = 256 0.066937 0.066995 0.066937 0.000873 -2.000614 0.000873 -2.003060 0.066937 0.066937 8.620313e-08 -3.998578 8.620313e-08 -3.992525 +N = 512 0.066937 0.066952 0.066937 0.000219 -2.000154 0.000219 -2.000768 0.066937 0.066937 5.560008e-09 -4.005552 5.560008e-09 -3.951767 + + +Convergence of FEM Temperature at x_bar = 0.500 and k_ratio = 0.0625 + True T FEM 2 T FEM 2 Extrap T FEM 2 % Error FEM 2 Exact B FEM 2 Extrap % Error FEM 2 Extrap B FEM 4 T FEM 4 Extrap T FEM 4 % Error FEM 4 Exact B FEM 4 Extrap % Error FEM 4 Extrap B +N = 4 0.066937 -0.363773 NaN 6.434572 NaN NaN NaN 0.125341 NaN 8.725219e-01 NaN NaN NaN +N = 8 0.066937 0.046331 NaN 0.307843 -4.385579 NaN NaN 0.069238 NaN 3.437611e-02 -4.665713 NaN NaN +N = 16 0.066937 0.062673 0.063352 0.010706 -2.272928 0.010706 NaN 0.067069 0.066982 1.301621e-03 -4.117651 1.301621e-03 NaN +N = 32 0.066937 0.065888 0.066675 0.011806 -2.023150 0.011806 -2.345888 0.066945 0.066937 1.131235e-04 -4.025230 1.131235e-04 -4.123498 +N = 64 0.066937 0.066671 0.066924 0.003772 -1.982240 0.003772 -2.036753 0.066937 0.066937 7.455960e-06 -4.006027 7.455960e-06 -4.026495 +N = 128 0.066937 0.066870 0.066937 0.001005 -1.984061 0.001005 -1.981623 0.066937 0.066937 4.709251e-07 -4.001558 4.709251e-07 -4.006325 +N = 256 0.066937 0.066920 0.066937 0.000254 -1.990328 0.000254 -1.981947 0.066937 0.066937 2.948335e-08 -4.001514 2.948335e-08 -4.002541 +N = 512 0.066937 0.066933 0.066937 0.000064 -1.994748 0.000064 -1.988845 0.066937 0.066937 2.462299e-09 -4.018498 2.462299e-09 -3.613957 + + +Convergence of FDM Temperature at x_bar = 0.500 and k_ratio = 0.125 + True T FDM 2 T FDM 2 Extrap T FDM 2 % Error FDM 2 Exact B FDM 2 Extrap % Error FDM 2 Extrap B FDM 4 T FDM 4 Extrap T FDM 4 % Error FDM 4 Exact B FDM 4 Extrap % Error FDM 4 Extrap B +N = 4 0.560194 1.321586 NaN 1.359157 NaN NaN NaN 0.644433 NaN 1.503736e-01 NaN NaN NaN +N = 8 0.560194 0.749289 NaN 0.337552 -2.009531 NaN NaN 0.568335 NaN 1.453274e-02 -3.371173 NaN NaN +N = 16 0.560194 0.607201 0.560273 0.083760 -2.008170 0.083760 NaN 0.560783 0.559951 1.485903e-03 -3.788394 1.485903e-03 NaN +N = 32 0.560194 0.571925 0.560274 0.020794 -2.002601 0.020794 -2.010016 0.560233 0.560189 7.737417e-05 -3.942014 7.737417e-05 -3.777069 +N = 64 0.560194 0.563125 0.560201 0.005220 -2.000690 0.005220 -2.003237 0.560197 0.560194 4.471350e-06 -3.985145 4.471350e-06 -3.939060 +N = 128 0.560194 0.560927 0.560195 0.001307 -2.000175 0.001307 -2.000862 0.560194 0.560194 2.731656e-07 -3.996264 2.731656e-07 -3.984413 +N = 256 0.560194 0.560377 0.560194 0.000327 -2.000044 0.000327 -2.000219 0.560194 0.560194 1.695761e-08 -3.999156 1.695761e-08 -3.997252 +N = 512 0.560194 0.560240 0.560194 0.000082 -2.000011 0.000082 -2.000055 0.560194 0.560194 1.457216e-09 -4.000608 1.457216e-09 -3.572239 + + +Convergence of FEM Temperature at x_bar = 0.500 and k_ratio = 0.125 + True T FEM 2 T FEM 2 Extrap T FEM 2 % Error FEM 2 Exact B FEM 2 Extrap % Error FEM 2 Extrap B FEM 4 T FEM 4 Extrap T FEM 4 % Error FEM 4 Exact B FEM 4 Extrap % Error FEM 4 Extrap B +N = 4 0.560194 0.284007 NaN 0.493020 NaN NaN NaN 0.622268 NaN 1.108077e-01 NaN NaN NaN +N = 8 0.560194 0.532604 NaN 0.049252 -3.323401 NaN NaN 0.563499 NaN 5.898885e-03 -4.231472 NaN NaN +N = 16 0.560194 0.553343 0.555230 0.003400 -2.009667 0.003400 NaN 0.560394 0.560221 3.090697e-04 -4.046545 3.090697e-04 NaN +N = 32 0.560194 0.558340 0.559926 0.002833 -1.885500 0.002833 -2.053153 0.560207 0.560195 2.153037e-05 -4.010664 2.153037e-05 -4.048887 +N = 64 0.560194 0.559704 0.560217 0.000915 -1.920215 0.000915 -1.872828 0.560195 0.560194 1.372921e-06 -4.002600 1.372921e-06 -4.011199 +N = 128 0.560194 0.560068 0.560200 0.000236 -1.955459 0.000236 -1.907766 0.560194 0.560194 8.618886e-08 -4.000648 8.618886e-08 -4.002640 +N = 256 0.560194 0.560162 0.560195 0.000059 -1.976687 0.000059 -1.948157 0.560194 0.560194 5.269850e-09 -4.000264 5.269850e-09 -4.031720 +N = 512 0.560194 0.560186 0.560194 0.000015 -1.988098 0.000015 -1.972821 0.560194 0.560194 1.244402e-09 -4.007095 1.244402e-09 -1.615813 + + +Convergence of FDM Temperature at x_bar = 0.500 and k_ratio = 0.25 + True T FDM 2 T FDM 2 Extrap T FDM 2 % Error FDM 2 Exact B FDM 2 Extrap % Error FDM 2 Extrap B FDM 4 T FDM 4 Extrap T FDM 4 % Error FDM 4 Exact B FDM 4 Extrap % Error FDM 4 Extrap B +N = 4 2.666666 3.862069 NaN 0.448276 NaN NaN NaN 2.766445 NaN 3.741715e-02 NaN NaN NaN +N = 8 2.666666 2.983433 NaN 0.118788 -1.916002 NaN NaN 2.674914 NaN 3.092841e-03 -3.596695 NaN NaN +N = 16 2.666666 2.747136 2.660209 0.032677 -1.976907 0.032677 NaN 2.667225 2.666520 2.643938e-04 -3.882410 2.643938e-04 NaN +N = 32 2.666666 2.686866 2.666231 0.007739 -1.994067 0.007739 -1.971109 2.666702 2.666664 1.434611e-05 -3.969306 1.434611e-05 -3.876288 +N = 64 2.666666 2.671721 2.666638 0.001906 -1.998506 0.001906 -1.992582 2.666668 2.666666 8.567257e-07 -3.992241 8.567257e-07 -3.967753 +N = 128 2.666666 2.667930 2.666664 0.000475 -1.999626 0.000475 -1.998132 2.666666 2.666666 5.289006e-08 -3.998054 5.289006e-08 -3.992024 +N = 256 2.666666 2.666982 2.666666 0.000119 -1.999906 0.000119 -1.999532 2.666666 2.666666 2.955733e-09 -3.999619 2.955733e-09 -4.145738 +N = 512 2.666666 2.666745 2.666666 0.000030 -1.999977 0.000030 -1.999883 2.666666 2.666666 1.072377e-09 -4.006796 1.072377e-09 -0.909712 + + +Convergence of FEM Temperature at x_bar = 0.500 and k_ratio = 0.25 + True T FEM 2 T FEM 2 Extrap T FEM 2 % Error FEM 2 Exact B FEM 2 Extrap % Error FEM 2 Extrap B FEM 4 T FEM 4 Extrap T FEM 4 % Error FEM 4 Exact B FEM 4 Extrap % Error FEM 4 Extrap B +N = 4 2.666666 2.715719 NaN 1.839487e-02 NaN NaN NaN 2.714187 NaN 1.782020e-02 NaN NaN NaN +N = 8 2.666666 2.662150 NaN 1.693516e-03 -3.441210 NaN NaN 2.669460 NaN 1.047764e-03 -4.088127 NaN NaN +N = 16 2.666666 2.661848 2.661847 6.420173e-07 0.093302 6.420173e-07 NaN 2.666838 2.666675 6.121488e-05 -4.018859 6.121488e-05 NaN +N = 32 2.666666 2.664898 2.662123 1.042592e-03 -1.446493 1.042592e-03 3.337586 2.666677 2.666666 3.981784e-06 -4.004467 3.981784e-06 -4.019811 +N = 64 2.666666 2.666147 2.667012 3.244563e-04 -1.767683 3.244563e-04 -1.288577 2.666667 2.666666 2.508414e-07 -4.001100 2.508414e-07 -4.004687 +N = 128 2.666666 2.666526 2.666692 6.204964e-05 -1.891986 6.204964e-05 -1.718994 2.666666 2.666666 1.572281e-08 -4.000269 1.572281e-08 -3.999707 +N = 256 2.666666 2.666630 2.666669 1.460619e-05 -1.947776 1.460619e-05 -1.871943 2.666666 2.666666 1.020082e-09 -4.000371 1.020082e-09 -3.948992 +N = 512 2.666666 2.666657 2.666666 3.577514e-06 -1.974309 3.577514e-06 -1.938606 2.666666 2.666666 7.946340e-09 -4.026006 7.946340e-09 0.177873 + + +Convergence of FDM Temperature at x_bar = 0.500 and k_ratio = 0.5 + True T FDM 2 T FDM 2 Extrap T FDM 2 % Error FDM 2 Exact B FDM 2 Extrap % Error FDM 2 Extrap B FDM 4 T FDM 4 Extrap T FDM 4 % Error FDM 4 Exact B FDM 4 Extrap % Error FDM 4 Extrap B +N = 4 8.438605 9.674633 NaN 0.146473 NaN NaN NaN 8.503685 NaN 7.712231e-03 NaN NaN NaN +N = 8 8.438605 8.767916 NaN 0.039024 -1.908190 NaN NaN 8.443410 NaN 5.694530e-04 -3.759500 NaN NaN +N = 16 8.438605 8.522370 8.431179 0.010816 -1.975035 0.010816 NaN 8.438919 8.438557 4.285047e-05 -3.935125 4.285047e-05 NaN +N = 32 8.438605 8.459639 8.438114 0.002551 -1.993614 0.002551 -1.968752 8.438625 8.438604 2.445375e-06 -3.983452 2.445375e-06 -3.931805 +N = 64 8.438605 8.443869 8.438574 0.000628 -1.998394 0.000628 -1.992015 8.438606 8.438605 1.489725e-07 -3.995842 1.489725e-07 -3.982625 +N = 128 8.438605 8.439921 8.438603 0.000156 -1.999598 0.000156 -1.997993 8.438605 8.438605 9.219334e-09 -3.998990 9.219334e-09 -4.000064 +N = 256 8.438605 8.438934 8.438605 0.000039 -1.999899 0.000039 -1.999497 8.438605 8.438605 7.023049e-10 -4.001623 7.023049e-10 -3.735251 +N = 512 8.438605 8.438687 8.438605 0.000010 -1.999975 0.000010 -1.999874 8.438605 8.438605 2.961137e-08 -4.057284 2.961137e-08 -0.026140 + + +Convergence of FEM Temperature at x_bar = 0.500 and k_ratio = 0.5 + True T FEM 2 T FEM 2 Extrap T FEM 2 % Error FEM 2 Exact B FEM 2 Extrap % Error FEM 2 Extrap B FEM 4 T FEM 4 Extrap T FEM 4 % Error FEM 4 Exact B FEM 4 Extrap % Error FEM 4 Extrap B +N = 4 8.438605 8.652638 NaN 0.025364 NaN NaN NaN 8.463770 NaN 2.982193e-03 NaN NaN NaN +N = 8 8.438605 8.432466 NaN 0.000727 -5.123736 NaN NaN 8.440137 NaN 1.816114e-04 -4.037447 NaN NaN +N = 16 8.438605 8.429022 8.428967 0.000006 0.642537 0.000006 NaN 8.438700 8.438607 1.102988e-05 -4.008491 1.102988e-05 NaN +N = 32 8.438605 8.435145 8.431226 0.000465 -1.469764 0.000465 0.830074 8.438611 8.438605 7.006905e-07 -4.002060 7.006905e-07 -4.008915 +N = 64 8.438605 8.437603 8.439252 0.000195 -1.788181 0.000195 -1.316727 8.438605 8.438605 4.395466e-08 -4.000510 4.395466e-08 -4.001907 +N = 128 8.438605 8.438337 8.438650 0.000037 -1.903464 0.000037 -1.743720 8.438605 8.438605 2.756925e-09 -4.000105 2.756925e-09 -3.996608 +N = 256 8.438605 8.438536 8.438609 0.000009 -1.953754 0.000009 -1.885546 8.438605 8.438605 9.335272e-09 -4.006893 9.335272e-09 -0.351898 +N = 512 8.438605 8.438587 8.438605 0.000002 -1.977347 0.000002 -1.945635 8.438605 8.438605 3.033763e-08 -4.109874 3.033763e-08 0.007683 + + +Convergence of FDM Temperature at x_bar = 0.500 and k_ratio = 1.0 + True T FDM 2 T FDM 2 Extrap T FDM 2 % Error FDM 2 Exact B FDM 2 Extrap % Error FDM 2 Extrap B FDM 4 T FDM 4 Extrap T FDM 4 % Error FDM 4 Exact B FDM 4 Extrap % Error FDM 4 Extrap B +N = 4 19.738549 20.447284 NaN 0.035906 NaN NaN NaN 19.752762 NaN 7.200901e-04 NaN NaN NaN +N = 8 19.738549 19.922720 NaN 0.009331 -1.944198 NaN NaN 19.739499 NaN 4.813553e-05 -3.903003 NaN NaN +N = 16 19.738549 19.785060 19.736081 0.002482 -1.985391 0.002482 NaN 19.738609 19.738545 3.241007e-06 -3.975074 3.241007e-06 NaN +N = 32 19.738549 19.750206 19.738390 0.000599 -1.996303 0.000599 -1.981722 19.738553 19.738549 1.949892e-07 -3.993725 1.949892e-07 -3.973832 +N = 64 19.738549 19.741465 19.738539 0.000148 -1.999073 0.000148 -1.995378 19.738549 19.738549 1.196502e-08 -3.998427 1.196502e-08 -4.004838 +N = 128 19.738549 19.739278 19.738548 0.000037 -1.999768 0.000037 -1.998841 19.738549 19.738549 7.604435e-10 -3.999475 7.604435e-10 -3.788746 +N = 256 19.738549 19.738731 19.738549 0.000009 -1.999942 0.000009 -1.999710 19.738549 19.738549 1.678576e-08 -4.027237 1.678576e-08 0.061951 +N = 512 19.738549 19.738594 19.738549 0.000002 -1.999986 0.000002 -1.999924 19.738549 19.738549 3.410828e-09 -3.453726 3.410828e-09 -0.017611 + + +Convergence of FEM Temperature at x_bar = 0.500 and k_ratio = 1.0 + True T FEM 2 T FEM 2 Extrap T FEM 2 % Error FEM 2 Exact B FEM 2 Extrap % Error FEM 2 Extrap B FEM 4 T FEM 4 Extrap T FEM 4 % Error FEM 4 Exact B FEM 4 Extrap % Error FEM 4 Extrap B +N = 4 19.738549 19.679634 NaN 0.002985 NaN NaN NaN 19.746583 NaN 4.070439e-04 NaN NaN NaN +N = 8 19.738549 19.641717 NaN 0.004906 0.716842 NaN NaN 19.739039 NaN 2.483155e-05 -4.034938 NaN NaN +N = 16 19.738549 19.703350 19.665192 0.001940 -1.459966 0.001940 NaN 19.738579 19.738549 1.511130e-06 -4.008826 1.511130e-06 NaN +N = 32 19.738549 19.728328 19.745349 0.000862 -1.784051 0.000862 -1.303049 19.738551 19.738549 9.574890e-08 -4.002212 9.574890e-08 -4.009400 +N = 64 19.738549 19.735813 19.739016 0.000162 -1.901696 0.000162 -1.738548 19.738549 19.738549 6.080926e-09 -4.000546 6.080926e-09 -3.985562 +N = 128 19.738549 19.737842 19.738597 0.000038 -1.952962 0.000038 -1.883408 19.738549 19.738549 5.916877e-10 -4.000085 5.916877e-10 -3.396266 +N = 256 19.738549 19.738369 19.738554 0.000009 -1.976979 0.000009 -1.944692 19.738549 19.738548 1.464429e-08 -4.036310 1.464429e-08 -0.034358 +N = 512 19.738549 19.738504 19.738549 0.000002 -1.988614 0.000002 -1.973033 19.738549 19.738557 4.197772e-07 -4.681374 4.197772e-07 0.000076 + + +Convergence of FDM Temperature at x_bar = 0.500 and k_ratio = 2.0 + True T FDM 2 T FDM 2 Extrap T FDM 2 % Error FDM 2 Exact B FDM 2 Extrap % Error FDM 2 Extrap B FDM 4 T FDM 4 Extrap T FDM 4 % Error FDM 4 Exact B FDM 4 Extrap % Error FDM 4 Extrap B +N = 4 36.441301 36.351342 NaN 2.468603e-03 NaN NaN NaN 36.420043 NaN 5.833573e-04 NaN NaN NaN +N = 8 36.441301 36.412116 NaN 8.008765e-04 -1.624043 NaN NaN 36.439800 NaN 4.120741e-05 -3.823404 NaN NaN +N = 16 36.441301 36.433533 36.445188 3.197816e-04 -1.909614 3.197816e-04 NaN 36.441204 36.441312 2.950879e-06 -3.954542 2.950879e-06 NaN +N = 32 36.441301 36.439329 36.441479 5.900323e-05 -1.977577 5.900323e-05 -1.885733 36.441295 36.441301 1.720071e-07 -3.988550 1.720071e-07 -3.952224 +N = 64 36.441301 36.440806 36.441312 1.387073e-05 -1.994404 1.387073e-05 -1.971895 36.441301 36.441301 1.057241e-08 -3.997120 1.057241e-08 -3.986035 +N = 128 36.441301 36.441177 36.441302 3.416958e-06 -1.998602 3.416958e-06 -1.993002 36.441301 36.441301 5.361641e-10 -3.998868 5.361641e-10 -4.115557 +N = 256 36.441301 36.441270 36.441301 8.511403e-07 -1.999650 8.511403e-07 -1.998241 36.441301 36.441300 2.333626e-08 -3.967098 2.333626e-08 0.038464 +N = 512 36.441301 36.441294 36.441301 2.127102e-07 -1.999937 2.127102e-07 -1.998956 36.441301 36.441308 1.884169e-07 -2.798008 1.884169e-07 -0.000275 + + +Convergence of FEM Temperature at x_bar = 0.500 and k_ratio = 2.0 + True T FEM 2 T FEM 2 Extrap T FEM 2 % Error FEM 2 Exact B FEM 2 Extrap % Error FEM 2 Extrap B FEM 4 T FEM 4 Extrap T FEM 4 % Error FEM 4 Exact B FEM 4 Extrap % Error FEM 4 Extrap B +N = 4 36.441301 35.832852 NaN 0.016697 NaN NaN NaN 36.440338 NaN 2.644585e-05 NaN NaN NaN +N = 8 36.441301 36.204196 NaN 0.006507 -1.359606 NaN NaN 36.441232 NaN 1.912466e-06 -3.789535 NaN NaN +N = 16 36.441301 36.370470 36.505289 0.003693 -1.743070 0.003693 NaN 36.441297 36.441302 1.406682e-07 -3.949079 1.406682e-07 NaN +N = 32 36.441301 36.422094 36.445339 0.000638 -1.882741 0.000638 -1.687447 36.441301 36.441301 8.056553e-09 -3.987367 8.056553e-09 -3.944881 +N = 64 36.441301 36.436309 36.441710 0.000148 -1.943854 0.000148 -1.860649 36.441301 36.441301 4.410936e-10 -3.996880 4.410936e-10 -3.962608 +N = 128 36.441301 36.440029 36.441348 0.000036 -1.972518 0.000036 -1.933921 36.441301 36.441302 2.726522e-08 -3.988805 2.726522e-08 -0.024043 +N = 256 36.441301 36.440980 36.441307 0.000009 -1.986403 0.000009 -1.967801 36.441301 36.441285 4.388124e-07 -3.749232 4.388124e-07 0.000094 +N = 512 36.441301 36.441221 36.441302 0.000002 -1.993237 0.000002 -1.984105 36.441301 36.441142 4.360262e-06 0.671980 4.360262e-06 0.000002 + + +Convergence of FDM Temperature at x_bar = 0.500 and k_ratio = 4.0 + True T FDM 2 T FDM 2 Extrap T FDM 2 % Error FDM 2 Exact B FDM 2 Extrap % Error FDM 2 Extrap B FDM 4 T FDM 4 Extrap T FDM 4 % Error FDM 4 Exact B FDM 4 Extrap % Error FDM 4 Extrap B +N = 4 55.383747 54.738450 NaN 1.165138e-02 NaN NaN NaN 55.350493 NaN 6.004303e-04 NaN NaN NaN +N = 8 55.383747 55.211305 NaN 3.113580e-03 -1.903854 NaN NaN 55.381453 NaN 4.141831e-05 -3.857656 NaN NaN +N = 16 55.383747 55.339880 55.387898 8.669335e-04 -1.974909 8.669335e-04 NaN 55.383600 55.383760 2.888108e-06 -3.963085 2.888108e-06 NaN +N = 32 55.383747 55.372732 55.384006 2.035705e-04 -1.993656 2.035705e-04 -1.968568 55.383737 55.383747 1.707474e-07 -3.990684 1.707474e-07 -3.961178 +N = 64 55.383747 55.380990 55.383763 5.006916e-05 -1.998410 5.006916e-05 -1.992066 55.383746 55.383747 1.052346e-08 -3.997669 1.052346e-08 -3.989239 +N = 128 55.383747 55.383057 55.383748 1.246579e-05 -1.999602 1.246579e-05 -1.998012 55.383747 55.383747 3.603694e-10 -3.998908 3.603694e-10 -4.817891 +N = 256 55.383747 55.383574 55.383747 3.113229e-06 -1.999900 3.113229e-06 -1.999503 55.383747 55.383746 1.414303e-08 -4.010329 1.414303e-08 0.063983 +N = 512 55.383747 55.383704 55.383747 7.781141e-07 -1.999979 7.781141e-07 -1.999865 55.383747 55.383739 1.297991e-07 -4.028543 1.297991e-07 0.000424 + + +Convergence of FEM Temperature at x_bar = 0.500 and k_ratio = 4.0 + True T FEM 2 T FEM 2 Extrap T FEM 2 % Error FEM 2 Exact B FEM 2 Extrap % Error FEM 2 Extrap B FEM 4 T FEM 4 Extrap T FEM 4 % Error FEM 4 Exact B FEM 4 Extrap % Error FEM 4 Extrap B +N = 4 55.383747 54.410234 NaN 0.017578 NaN NaN NaN 55.379824 NaN 7.082611e-05 NaN NaN NaN +N = 8 55.383747 55.070107 NaN 0.005663 -1.634093 NaN NaN 55.383492 NaN 4.592963e-06 -3.946784 NaN NaN +N = 16 55.383747 55.295589 55.412632 0.002112 -1.830954 0.002112 NaN 55.383731 55.383747 2.989977e-07 -3.986123 2.989977e-07 NaN +N = 32 55.383747 55.360424 55.386591 0.000472 -1.918370 0.000472 -1.798167 55.383746 55.383747 1.831004e-08 -3.996495 1.831004e-08 -3.985276 +N = 64 55.383747 55.377752 55.384071 0.000114 -1.959856 0.000114 -1.903734 55.383747 55.383747 1.826820e-09 -3.999134 1.826820e-09 -3.367154 +N = 128 55.383747 55.382227 55.383786 0.000028 -1.980090 0.000028 -1.952921 55.383747 55.383747 3.753217e-09 -3.997425 3.753217e-09 -0.360222 +N = 256 55.383747 55.383364 55.383751 0.000007 -1.990085 0.000007 -1.976712 55.383747 55.383739 1.296623e-07 -3.951150 1.296623e-07 0.000740 +N = 512 55.383747 55.383651 55.383747 0.000002 -1.995056 0.000002 -1.988421 55.383747 55.383907 2.899492e-06 -1.097392 2.899492e-06 -0.000003 + + +Convergence of FDM Temperature at x_bar = 0.500 and k_ratio = 8.0 + True T FDM 2 T FDM 2 Extrap T FDM 2 % Error FDM 2 Exact B FDM 2 Extrap % Error FDM 2 Extrap B FDM 4 T FDM 4 Extrap T FDM 4 % Error FDM 4 Exact B FDM 4 Extrap % Error FDM 4 Extrap B +N = 4 72.105546 71.363029 NaN 1.029764e-02 NaN NaN NaN 72.076518 NaN 4.025792e-04 NaN NaN NaN +N = 8 72.105546 71.911316 NaN 2.693691e-03 -1.934658 NaN NaN 72.103555 NaN 2.761201e-05 -3.865905 NaN NaN +N = 16 72.105546 72.056411 72.108626 7.241098e-04 -1.982937 7.241098e-04 NaN 72.105419 72.105557 1.913110e-06 -3.965081 1.913110e-06 NaN +N = 32 72.105546 72.093226 72.105743 1.735887e-04 -1.995685 1.735887e-04 -1.978646 72.105538 72.105547 1.134920e-07 -3.991177 1.134920e-07 -3.963367 +N = 64 72.105546 72.102464 72.105559 4.292014e-05 -1.998918 4.292014e-05 -1.994605 72.105546 72.105546 6.975706e-09 -3.997776 6.975706e-09 -3.994622 +N = 128 72.105546 72.104776 72.105547 1.070002e-05 -1.999729 1.070002e-05 -1.998648 72.105546 72.105547 1.299462e-09 -3.998574 1.299462e-09 -2.589904 +N = 256 72.105546 72.105354 72.105547 2.673124e-06 -1.999933 2.673124e-06 -1.999662 72.105546 72.105545 1.857040e-08 -3.932799 1.857040e-08 0.031962 +N = 512 72.105546 72.105498 72.105546 6.682154e-07 -1.999972 6.682154e-07 -1.999828 72.105546 72.105562 2.200364e-07 -1.539356 2.200364e-07 -0.000123 + + +Convergence of FEM Temperature at x_bar = 0.500 and k_ratio = 8.0 + True T FEM 2 T FEM 2 Extrap T FEM 2 % Error FEM 2 Exact B FEM 2 Extrap % Error FEM 2 Extrap B FEM 4 T FEM 4 Extrap T FEM 4 % Error FEM 4 Exact B FEM 4 Extrap % Error FEM 4 Extrap B +N = 4 72.105546 71.167084 NaN 0.013015 NaN NaN NaN 72.101833 NaN 5.150457e-05 NaN NaN NaN +N = 8 72.105546 71.823222 NaN 0.003915 -1.732945 NaN NaN 72.105307 NaN 3.321129e-06 -3.954955 NaN NaN +N = 16 72.105546 72.028173 72.121272 0.001291 -1.867448 0.001291 NaN 72.105531 72.105547 2.148524e-07 -3.988195 2.148524e-07 NaN +N = 32 72.105546 72.085293 72.107363 0.000306 -1.933672 0.000306 -1.843217 72.105546 72.105546 1.314747e-08 -3.997014 1.314747e-08 -3.992830 +N = 64 72.105546 72.100365 72.105768 0.000075 -1.966785 0.000075 -1.922112 72.105546 72.105546 9.292971e-10 -3.999105 9.292971e-10 -3.830052 +N = 128 72.105546 72.104236 72.105574 0.000019 -1.983374 0.000019 -1.961125 72.105546 72.105548 2.624584e-08 -3.997261 2.624584e-08 -0.041629 +N = 256 72.105546 72.105217 72.105550 0.000005 -1.991682 0.000005 -1.980572 72.105546 72.105550 5.247377e-08 -4.811127 5.247377e-08 -0.001360 +N = 512 72.105546 72.105464 72.105547 0.000001 -1.995831 0.000001 -1.990264 72.105546 72.105640 1.292537e-06 1.420703 1.292537e-06 0.000003 + + +Convergence of FDM Temperature at x_bar = 0.500 and k_ratio = 16.0 + True T FDM 2 T FDM 2 Extrap T FDM 2 % Error FDM 2 Exact B FDM 2 Extrap % Error FDM 2 Extrap B FDM 4 T FDM 4 Extrap T FDM 4 % Error FDM 4 Exact B FDM 4 Extrap % Error FDM 4 Extrap B +N = 4 84.066993 83.499938 NaN 6.745276e-03 NaN NaN NaN 84.047391 NaN 2.331775e-04 NaN NaN NaN +N = 8 84.066993 83.920263 NaN 1.745393e-03 -1.950326 NaN NaN 84.065651 NaN 1.596694e-05 -3.868269 NaN NaN +N = 16 84.066993 84.029979 84.068733 4.609836e-04 -1.986999 4.609836e-04 NaN 84.066907 84.067000 1.104246e-06 -3.965621 1.104246e-06 NaN +N = 32 84.066993 84.057718 84.067105 1.116594e-04 -1.996710 1.116594e-04 -1.983738 84.066988 84.066993 6.557651e-08 -3.991309 6.557651e-08 -3.963928 +N = 64 84.066993 84.064673 84.067000 2.768125e-05 -1.999175 2.768125e-05 -1.995887 84.066993 84.066993 3.988095e-09 -3.997789 3.988095e-09 -4.009398 +N = 128 84.066993 84.066413 84.066994 6.905557e-06 -1.999794 6.905557e-06 -1.998968 84.066993 84.066993 8.955373e-10 -4.000157 8.955373e-10 -2.381555 +N = 256 84.066993 84.066848 84.066993 1.725477e-06 -1.999949 1.725477e-06 -1.999734 84.066993 84.066996 3.310265e-08 -3.987292 3.310265e-08 -0.010228 +N = 512 84.066993 84.066957 84.066993 4.313023e-07 -1.999980 4.313023e-07 -1.999948 84.066993 84.067022 3.427462e-07 -1.022110 3.427462e-07 -0.000034 + + +Convergence of FEM Temperature at x_bar = 0.500 and k_ratio = 16.0 + True T FEM 2 T FEM 2 Extrap T FEM 2 % Error FEM 2 Exact B FEM 2 Extrap % Error FEM 2 Extrap B FEM 4 T FEM 4 Extrap T FEM 4 % Error FEM 4 Exact B FEM 4 Extrap % Error FEM 4 Extrap B +N = 4 84.066993 83.389648 NaN 8.057211e-03 NaN NaN NaN 84.064444 NaN 3.031942e-05 NaN NaN NaN +N = 8 84.066993 83.869497 NaN 2.349269e-03 -1.778069 NaN NaN 84.066829 NaN 1.952881e-06 -3.956566 NaN NaN +N = 16 84.066993 84.013509 84.075262 7.345061e-04 -1.884628 7.345061e-04 NaN 84.066983 84.066993 1.261802e-07 -3.988602 1.261802e-07 NaN +N = 32 84.066993 84.053063 84.068040 1.781610e-04 -1.940876 1.781610e-04 -1.864285 84.066993 84.066993 7.651180e-09 -3.997117 7.651180e-09 -4.006481 +N = 64 84.066993 84.063437 84.067126 4.387892e-05 -1.970029 4.387892e-05 -1.930747 84.066993 84.066993 1.028087e-09 -3.999169 1.028087e-09 -2.591014 +N = 128 84.066993 84.066095 84.067010 1.088523e-05 -1.984906 1.088523e-05 -1.964966 84.066993 84.066990 3.353068e-08 -3.996938 3.353068e-08 0.019564 +N = 256 84.066993 84.066767 84.066995 2.710530e-06 -1.992425 2.710530e-06 -1.982372 84.066993 84.066957 4.318022e-07 -4.806789 4.318022e-07 0.000097 +N = 512 84.066993 84.066937 84.066993 6.762546e-07 -1.996214 6.762546e-07 -1.991181 84.066993 84.066953 4.734119e-07 1.292403 4.734119e-07 -0.000005 + + +Convergence of FDM Temperature at x_bar = 0.637 and k_ratio = 0.0625 + True T FDM 2 T FDM 2 Extrap T FDM 2 % Error FDM 2 Exact B FDM 2 Extrap % Error FDM 2 Extrap B FDM 4 T FDM 4 Extrap T FDM 4 % Error FDM 4 Exact B FDM 4 Extrap % Error FDM 4 Extrap B +N = 4 0.392138 0.964920 NaN 1.460667 NaN NaN NaN 0.458151 NaN 1.683420e-01 NaN NaN NaN +N = 8 0.392138 0.534322 NaN 0.362587 -2.010228 NaN NaN 0.398641 NaN 1.658442e-02 -3.343494 NaN NaN +N = 16 0.392138 0.427450 0.392169 0.089965 -2.009513 0.089965 NaN 0.392612 0.391933 1.733889e-03 -3.775895 1.733889e-03 NaN +N = 32 0.392138 0.400947 0.392207 0.022284 -2.003074 0.022284 -2.011646 0.392169 0.392133 8.993455e-05 -3.938252 8.993455e-05 -3.763853 +N = 64 0.392138 0.394339 0.392144 0.005597 -2.000819 0.005597 -2.003825 0.392140 0.392138 5.175510e-06 -3.984440 5.175510e-06 -3.935083 +N = 128 0.392138 0.392688 0.392138 0.001402 -2.000209 0.001402 -2.001022 0.392138 0.392138 3.157303e-07 -4.000641 3.157303e-07 -3.983349 +N = 256 0.392138 0.392275 0.392138 0.000351 -2.000055 0.000351 -2.000260 0.392138 0.392138 1.959448e-08 -4.075163 1.959448e-08 -3.996810 +N = 512 0.392138 0.392172 0.392138 0.000088 -2.000026 0.000088 -2.000065 0.392138 0.392138 1.347800e-09 -6.903970 1.347800e-09 -3.868545 + + +Convergence of FEM Temperature at x_bar = 0.637 and k_ratio = 0.0625 + True T FEM 2 T FEM 2 Extrap T FEM 2 % Error FEM 2 Exact B FEM 2 Extrap % Error FEM 2 Extrap B FEM 4 T FEM 4 Extrap T FEM 4 % Error FEM 4 Exact B FEM 4 Extrap % Error FEM 4 Extrap B +N = 4 0.392138 0.149088 NaN 0.619806 NaN NaN NaN 0.442756 NaN 1.290824e-01 NaN NaN NaN +N = 8 0.392138 0.367363 NaN 0.063178 -3.294328 NaN NaN 0.394802 NaN 6.793787e-03 -4.247932 NaN NaN +N = 16 0.392138 0.386079 0.387834 0.004526 -2.031788 0.004526 NaN 0.392299 0.392161 3.515340e-04 -4.048947 3.515340e-04 NaN +N = 32 0.392138 0.390525 0.391911 0.003535 -1.909892 0.003535 -2.073563 0.392148 0.392138 2.470996e-05 -4.011164 2.470996e-05 -4.051410 +N = 64 0.392138 0.391716 0.392151 0.001110 -1.934512 0.001110 -1.901067 0.392138 0.392138 1.577555e-06 -4.003611 1.577555e-06 -4.011665 +N = 128 0.392138 0.392029 0.392142 0.000286 -1.962964 0.000286 -1.924564 0.392138 0.392138 9.904100e-08 -4.015325 9.904100e-08 -4.002930 +N = 256 0.392138 0.392110 0.392138 0.000071 -1.980497 0.000071 -1.956965 0.392138 0.392138 6.265574e-09 -4.257532 6.265574e-09 -3.985877 +N = 512 0.392138 0.392131 0.392138 0.000018 -1.989961 0.000018 -1.977299 0.392138 0.392138 9.583398e-10 -2.911770 9.583398e-10 -2.340668 + + +Convergence of FDM Temperature at x_bar = 0.637 and k_ratio = 0.125 + True T FDM 2 T FDM 2 Extrap T FDM 2 % Error FDM 2 Exact B FDM 2 Extrap % Error FDM 2 Extrap B FDM 4 T FDM 4 Extrap T FDM 4 % Error FDM 4 Exact B FDM 4 Extrap % Error FDM 4 Extrap B +N = 4 1.973771 2.884832 NaN 0.461584 NaN NaN NaN 2.054428 NaN 4.086461e-02 NaN NaN NaN +N = 8 1.973771 2.217011 NaN 0.123236 -1.905166 NaN NaN 1.980577 NaN 3.448250e-03 -3.566916 NaN NaN +N = 16 1.973771 2.035705 1.968139 0.034330 -1.973570 0.034330 NaN 1.974235 1.973640 3.018150e-04 -3.872719 3.018150e-04 NaN +N = 32 1.973771 1.989328 1.973387 0.008078 -1.993183 0.008078 -1.966930 1.973800 1.973768 1.622337e-05 -3.966691 1.622337e-05 -3.866069 +N = 64 1.973771 1.977665 1.973746 0.001985 -1.998282 0.001985 -1.991477 1.973773 1.973771 9.652899e-07 -3.991576 9.652899e-07 -3.965005 +N = 128 1.973771 1.974744 1.973769 0.000494 -1.999570 0.000494 -1.997852 1.973771 1.973771 5.954558e-08 -3.997927 5.954558e-08 -3.990989 +N = 256 1.973771 1.974014 1.973771 0.000123 -1.999892 0.000123 -1.999462 1.973771 1.973771 3.607388e-09 -4.000377 3.607388e-09 -4.035270 +N = 512 1.973771 1.973832 1.973771 0.000031 -1.999973 0.000031 -1.999865 1.973771 1.973771 5.886205e-10 -3.994490 5.886205e-10 -2.785349 + + +Convergence of FEM Temperature at x_bar = 0.637 and k_ratio = 0.125 + True T FEM 2 T FEM 2 Extrap T FEM 2 % Error FEM 2 Exact B FEM 2 Extrap % Error FEM 2 Extrap B FEM 4 T FEM 4 Extrap T FEM 4 % Error FEM 4 Exact B FEM 4 Extrap % Error FEM 4 Extrap B +N = 4 1.973771 1.950437 NaN 0.011822 NaN NaN NaN 2.014040 NaN 2.040236e-02 NaN NaN NaN +N = 8 1.973771 1.953971 NaN 0.010032 -0.236949 NaN NaN 1.976128 NaN 1.194381e-03 -4.094401 NaN NaN +N = 16 1.973771 1.965537 1.948881 0.008546 -1.265896 0.008546 NaN 1.973916 1.973779 6.944648e-05 -4.019974 6.944648e-05 NaN +N = 32 1.973771 1.971213 1.976683 0.002767 -1.686822 0.002767 -1.026937 1.973780 1.973771 4.531587e-06 -4.004707 4.531587e-06 -4.020982 +N = 64 1.973771 1.973063 1.973958 0.000453 -1.854433 0.000453 -1.617231 1.973771 1.973771 2.856214e-07 -4.001166 2.856214e-07 -4.004940 +N = 128 1.973771 1.973585 1.973790 0.000104 -1.929744 0.000104 -1.826653 1.973771 1.973771 1.783865e-08 -4.000415 1.783865e-08 -4.004762 +N = 256 1.973771 1.973723 1.973773 0.000025 -1.965480 0.000025 -1.917237 1.973771 1.973771 9.406020e-10 -4.002193 9.406020e-10 -4.235639 +N = 512 1.973771 1.973759 1.973771 0.000006 -1.982889 0.000006 -1.959536 1.973771 1.973771 2.906984e-09 -4.013522 2.906984e-09 0.644742 + + +Convergence of FDM Temperature at x_bar = 0.637 and k_ratio = 0.25 + True T FDM 2 T FDM 2 Extrap T FDM 2 % Error FDM 2 Exact B FDM 2 Extrap % Error FDM 2 Extrap B FDM 4 T FDM 4 Extrap T FDM 4 % Error FDM 4 Exact B FDM 4 Extrap % Error FDM 4 Extrap B +N = 4 6.560619 7.452341 NaN 0.135920 NaN NaN NaN 6.606093 NaN 6.931221e-03 NaN NaN NaN +N = 8 6.560619 6.799021 NaN 0.036338 -1.903201 NaN NaN 6.564006 NaN 5.161932e-04 -3.747126 NaN NaN +N = 16 6.560619 6.621332 6.554951 0.010127 -1.973315 0.010127 NaN 6.560841 6.560584 3.921835e-05 -3.931271 3.921835e-05 NaN +N = 32 6.560619 6.575870 6.560239 0.002383 -1.993146 0.002383 -1.966601 6.560633 6.560619 2.229184e-06 -3.982433 2.229184e-06 -3.927750 +N = 64 6.560619 6.564437 6.560595 0.000586 -1.998275 0.000586 -1.991430 6.560620 6.560619 1.356016e-07 -3.995583 1.356016e-07 -3.981561 +N = 128 6.560619 6.561574 6.560618 0.000146 -1.999568 0.000146 -1.997843 6.560619 6.560619 8.425880e-09 -3.998939 8.425880e-09 -3.993782 +N = 256 6.560619 6.560858 6.560619 0.000036 -1.999892 0.000036 -1.999460 6.560619 6.560619 1.339557e-09 -4.001360 1.339557e-09 -2.781327 +N = 512 6.560619 6.560679 6.560619 0.000009 -1.999973 0.000009 -1.999865 6.560619 6.560619 1.112903e-08 -3.955342 1.112903e-08 -0.062203 + + +Convergence of FEM Temperature at x_bar = 0.637 and k_ratio = 0.25 + True T FEM 2 T FEM 2 Extrap T FEM 2 % Error FEM 2 Exact B FEM 2 Extrap % Error FEM 2 Extrap B FEM 4 T FEM 4 Extrap T FEM 4 % Error FEM 4 Exact B FEM 4 Extrap % Error FEM 4 Extrap B +N = 4 6.560619 6.572238 NaN 0.001771 NaN NaN NaN 6.581686 NaN 3.211104e-03 NaN NaN NaN +N = 8 6.560619 6.501798 NaN 0.008966 2.339890 NaN NaN 6.561891 NaN 1.938194e-04 -4.050285 NaN NaN +N = 16 6.560619 6.537168 6.525344 0.001812 -1.326678 0.001812 NaN 6.560698 6.560622 1.165695e-05 -4.011875 1.165695e-05 NaN +N = 32 6.560619 6.553589 6.567820 0.002167 -1.738076 0.002167 -1.106969 6.560624 6.560619 7.441118e-07 -4.002917 7.441118e-07 -4.012469 +N = 64 6.560619 6.558712 6.561034 0.000354 -1.881813 0.000354 -1.680666 6.560620 6.560619 4.675026e-08 -4.000727 4.675026e-08 -4.002539 +N = 128 6.560619 6.560124 6.560661 0.000082 -1.943682 0.000082 -1.859435 6.560619 6.560619 2.986564e-09 -4.000190 2.986564e-09 -3.972231 +N = 256 6.560619 6.560493 6.560624 0.000020 -1.972494 0.000020 -1.933696 6.560619 6.560619 5.124541e-09 -4.004226 5.124541e-09 -0.618512 +N = 512 6.560619 6.560588 6.560620 0.000005 -1.986406 0.000005 -1.967768 6.560619 6.560619 5.223584e-08 -3.907740 5.223584e-08 -0.004692 + + +Convergence of FDM Temperature at x_bar = 0.637 and k_ratio = 0.5 + True T FDM 2 T FDM 2 Extrap T FDM 2 % Error FDM 2 Exact B FDM 2 Extrap % Error FDM 2 Extrap B FDM 4 T FDM 4 Extrap T FDM 4 % Error FDM 4 Exact B FDM 4 Extrap % Error FDM 4 Extrap B +N = 4 16.08921 16.377482 NaN 0.017917 NaN NaN NaN 16.072588 NaN 1.033089e-03 NaN NaN NaN +N = 8 16.08921 16.157318 NaN 0.004233 -2.081543 NaN NaN 16.087851 NaN 8.444136e-05 -3.612871 NaN NaN +N = 16 16.08921 16.105900 16.090233 0.000974 -2.028836 0.000974 NaN 16.089119 16.089234 7.136454e-06 -3.901042 7.136454e-06 NaN +N = 32 16.08921 16.093360 16.089315 0.000251 -2.007904 0.000251 -2.035696 16.089204 16.089210 3.811676e-07 -3.975106 3.811676e-07 -3.895879 +N = 64 16.08921 16.090246 16.089218 0.000064 -2.002023 0.000064 -2.009856 16.089210 16.089210 2.290596e-08 -3.993769 2.290596e-08 -3.973248 +N = 128 16.08921 16.089469 16.089211 0.000016 -2.000509 0.000016 -2.002527 16.089210 16.089210 2.318551e-09 -3.998132 2.318551e-09 -3.339367 +N = 256 16.08921 16.089275 16.089210 0.000004 -2.000127 0.000004 -2.000635 16.089210 16.089210 2.682228e-09 -4.007949 2.682228e-09 0.981833 +N = 512 16.08921 16.089226 16.089210 0.000001 -2.000027 0.000001 -2.000139 16.089210 16.089212 1.419220e-07 -3.851093 1.419220e-07 -0.000830 + + +Convergence of FEM Temperature at x_bar = 0.637 and k_ratio = 0.5 + True T FEM 2 T FEM 2 Extrap T FEM 2 % Error FEM 2 Exact B FEM 2 Extrap % Error FEM 2 Extrap B FEM 4 T FEM 4 Extrap T FEM 4 % Error FEM 4 Exact B FEM 4 Extrap % Error FEM 4 Extrap B +N = 4 16.08921 15.648397 NaN 0.027398 NaN NaN NaN 16.093157 NaN 2.453157e-04 NaN NaN NaN +N = 8 16.08921 15.873740 NaN 0.013392 -1.032680 NaN NaN 16.089426 NaN 1.343464e-05 -4.190611 NaN NaN +N = 16 16.08921 16.020446 16.294141 0.016797 -1.647759 0.016797 NaN 16.089223 16.089211 7.271523e-07 -4.055423 7.271523e-07 NaN +N = 32 16.08921 16.070057 16.095406 0.001575 -1.844072 0.001575 -1.564197 16.089211 16.089210 4.840807e-08 -4.014442 4.840807e-08 -4.058229 +N = 64 16.08921 16.084171 16.089784 0.000349 -1.926462 0.000349 -1.813482 16.089210 16.089210 2.737377e-09 -4.003653 2.737377e-09 -4.180015 +N = 128 16.08921 16.087919 16.089273 0.000084 -1.964289 0.000084 -1.913195 16.089210 16.089210 3.562759e-09 -4.000903 3.562759e-09 2.475812 +N = 256 16.08921 16.088883 16.089218 0.000021 -1.982405 0.000021 -1.958100 16.089210 16.089210 3.995362e-09 -3.978635 3.995362e-09 -0.064383 +N = 512 16.08921 16.089128 16.089211 0.000005 -1.991265 0.000005 -1.979413 16.089210 16.089220 6.038491e-07 -3.906710 6.038491e-07 0.000031 + + +Convergence of FDM Temperature at x_bar = 0.637 and k_ratio = 1.0 + True T FDM 2 T FDM 2 Extrap T FDM 2 % Error FDM 2 Exact B FDM 2 Extrap % Error FDM 2 Extrap B FDM 4 T FDM 4 Extrap T FDM 4 % Error FDM 4 Exact B FDM 4 Extrap % Error FDM 4 Extrap B +N = 4 31.182398 30.514477 NaN 0.021420 NaN NaN NaN 31.111549 NaN 2.272105e-03 NaN NaN NaN +N = 8 31.182398 30.989359 NaN 0.006191 -1.790787 NaN NaN 31.177173 NaN 1.675687e-04 -3.761205 NaN NaN +N = 16 31.182398 31.132234 31.193717 0.001971 -1.944144 0.001971 NaN 31.182057 31.182450 1.259443e-05 -3.937174 1.259443e-05 NaN +N = 32 31.182398 31.169733 31.183078 0.000428 -1.985785 0.000428 -1.929804 31.182377 31.182399 7.174384e-07 -3.984083 7.174384e-07 -3.933953 +N = 64 31.182398 31.179224 31.182440 0.000103 -1.996430 0.000103 -1.982208 31.182397 31.182398 4.374637e-08 -3.996006 4.374637e-08 -3.982923 +N = 128 31.182398 31.181604 31.182401 0.000026 -1.999106 0.000026 -1.995536 31.182398 31.182398 2.606778e-09 -3.998900 2.606778e-09 -4.051425 +N = 256 31.182398 31.182200 31.182398 0.000006 -1.999777 0.000006 -1.998883 31.182398 31.182398 3.856539e-09 -3.998694 3.856539e-09 1.550952 +N = 512 31.182398 31.182349 31.182398 0.000002 -1.999941 0.000002 -1.999717 31.182398 31.182398 1.478152e-08 -3.697036 1.478152e-08 0.015351 + + +Convergence of FEM Temperature at x_bar = 0.637 and k_ratio = 1.0 + True T FEM 2 T FEM 2 Extrap T FEM 2 % Error FEM 2 Exact B FEM 2 Extrap % Error FEM 2 Extrap B FEM 4 T FEM 4 Extrap T FEM 4 % Error FEM 4 Exact B FEM 4 Extrap % Error FEM 4 Extrap B +N = 4 31.182398 29.932292 NaN 0.040090 NaN NaN NaN 31.175417 NaN 2.238893e-04 NaN NaN NaN +N = 8 31.182398 30.733838 NaN 0.014385 -1.478678 NaN NaN 31.181922 NaN 1.527575e-05 -3.873470 NaN NaN +N = 16 31.182398 31.050756 31.258002 0.006630 -1.768681 0.006630 NaN 31.182368 31.182401 1.052223e-06 -3.967146 1.052223e-06 NaN +N = 32 31.182398 31.146901 31.188771 0.001342 -1.890838 0.001342 -1.720830 31.182396 31.182398 6.260357e-08 -3.991707 6.260357e-08 -3.965417 +N = 64 31.182398 31.173192 31.183087 0.000317 -1.947032 0.000317 -1.870631 31.182398 31.182398 3.987232e-09 -3.997921 3.987232e-09 -3.948103 +N = 128 31.182398 31.180055 31.182479 0.000078 -1.973922 0.000078 -1.937733 31.182398 31.182398 3.060232e-09 -3.998459 3.060232e-09 2.496761 +N = 256 31.182398 31.181807 31.182408 0.000019 -1.987063 0.000019 -1.969462 31.182398 31.182398 1.082074e-08 -4.017430 1.082074e-08 0.030395 +N = 512 31.182398 31.182250 31.182400 0.000005 -1.993556 0.000005 -1.984879 31.182398 31.182407 2.634205e-07 -4.040315 2.634205e-07 -0.000086 + + +Convergence of FDM Temperature at x_bar = 0.637 and k_ratio = 2.0 + True T FDM 2 T FDM 2 Extrap T FDM 2 % Error FDM 2 Exact B FDM 2 Extrap % Error FDM 2 Extrap B FDM 4 T FDM 4 Extrap T FDM 4 % Error FDM 4 Exact B FDM 4 Extrap % Error FDM 4 Extrap B +N = 4 49.706164 48.318359 NaN 0.027920 NaN NaN NaN 49.611795 NaN 1.898533e-03 NaN NaN NaN +N = 8 49.706164 49.325368 NaN 0.007661 -1.865716 NaN NaN 49.699312 NaN 1.378513e-04 -3.783700 NaN NaN +N = 16 49.706164 49.608556 49.719351 0.002228 -1.963950 0.002228 NaN 49.705718 49.706224 1.017998e-05 -3.942655 1.017998e-05 NaN +N = 32 49.706164 49.681606 49.707000 0.000511 -1.990813 0.000511 -1.954806 49.706136 49.706165 5.854912e-07 -3.985442 5.854912e-07 -3.939727 +N = 64 49.706164 49.700015 49.706216 0.000125 -1.997692 0.000125 -1.988508 49.706162 49.706164 3.576368e-08 -3.996343 3.576368e-08 -3.984994 +N = 128 49.706164 49.704626 49.706167 0.000031 -1.999422 0.000031 -1.997114 49.706164 49.706164 1.928803e-09 -3.999244 1.928803e-09 -4.188806 +N = 256 49.706164 49.705779 49.706164 0.000008 -1.999856 0.000008 -1.999278 49.706164 49.706164 3.469626e-09 -3.992717 3.469626e-09 -0.677194 +N = 512 49.706164 49.706068 49.706164 0.000002 -1.999965 0.000002 -1.999824 49.706164 49.706165 1.676751e-08 -4.252497 1.676751e-08 -0.011313 + + +Convergence of FEM Temperature at x_bar = 0.637 and k_ratio = 2.0 + True T FEM 2 T FEM 2 Extrap T FEM 2 % Error FEM 2 Exact B FEM 2 Extrap % Error FEM 2 Extrap B FEM 4 T FEM 4 Extrap T FEM 4 % Error FEM 4 Exact B FEM 4 Extrap % Error FEM 4 Extrap B +N = 4 49.706164 47.861343 NaN 0.037115 NaN NaN NaN 49.694823 NaN 2.281547e-04 NaN NaN NaN +N = 8 49.706164 49.108745 NaN 0.012019 -1.626666 NaN NaN 49.705410 NaN 1.516824e-05 -3.910886 NaN NaN +N = 16 49.706164 49.536981 49.760850 0.004499 -1.820156 0.004499 NaN 49.706116 49.706166 1.015037e-06 -3.976421 1.015037e-06 NaN +N = 32 49.706164 49.661198 49.711952 0.001021 -1.911699 0.001021 -1.785533 49.706161 49.706164 6.131217e-08 -3.994020 6.131217e-08 -3.975493 +N = 64 49.706164 49.694576 49.706841 0.000247 -1.956261 0.000247 -1.895902 49.706164 49.706164 3.568787e-09 -3.998501 3.568787e-09 -4.077754 +N = 128 49.706164 49.703223 49.706246 0.000061 -1.978235 0.000061 -1.948711 49.706164 49.706164 1.470481e-09 -4.000422 1.470481e-09 -1.770777 +N = 256 49.706164 49.705423 49.706174 0.000015 -1.989144 0.000015 -1.974544 49.706164 49.706166 4.850477e-08 -3.922125 4.850477e-08 -0.006553 +N = 512 49.706164 49.705978 49.706165 0.000004 -1.994578 0.000004 -1.987318 49.706164 49.706153 2.272247e-07 -5.434926 2.272247e-07 0.000101 + + +Convergence of FDM Temperature at x_bar = 0.637 and k_ratio = 4.0 + True T FDM 2 T FDM 2 Extrap T FDM 2 % Error FDM 2 Exact B FDM 2 Extrap % Error FDM 2 Extrap B FDM 4 T FDM 4 Extrap T FDM 4 % Error FDM 4 Exact B FDM 4 Extrap % Error FDM 4 Extrap B +N = 4 67.384857 65.895105 NaN 0.022108 NaN NaN NaN 67.299703 NaN 1.263688e-03 NaN NaN NaN +N = 8 67.384857 66.985431 NaN 0.005928 -1.899072 NaN NaN 67.378702 NaN 9.133429e-05 -3.790340 NaN NaN +N = 16 67.384857 67.283107 67.394899 0.001659 -1.972907 0.001659 NaN 67.384457 67.384909 6.709802e-06 -3.944130 6.709802e-06 NaN +N = 32 67.384857 67.359297 67.385506 0.000389 -1.993096 0.000389 -1.966071 67.384831 67.384858 3.870843e-07 -3.985796 3.870843e-07 -3.941284 +N = 64 67.384857 67.378459 67.384898 0.000096 -1.998265 0.000096 -1.991365 67.384855 67.384857 2.370051e-08 -3.996432 2.370051e-08 -3.982999 +N = 128 67.384857 67.383257 67.384859 0.000024 -1.999566 0.000024 -1.997832 67.384857 67.384857 1.671876e-09 -3.999119 1.671876e-09 -3.823551 +N = 256 67.384857 67.384457 67.384857 0.000006 -1.999891 0.000006 -1.999458 67.384857 67.384856 3.788890e-09 -3.982202 3.788890e-09 0.650219 +N = 512 67.384857 67.384757 67.384857 0.000001 -1.999966 0.000001 -1.999863 67.384857 67.384869 1.874138e-07 -4.196962 1.874138e-07 -0.000676 + + +Convergence of FEM Temperature at x_bar = 0.637 and k_ratio = 4.0 + True T FEM 2 T FEM 2 Extrap T FEM 2 % Error FEM 2 Exact B FEM 2 Extrap % Error FEM 2 Extrap B FEM 4 T FEM 4 Extrap T FEM 4 % Error FEM 4 Exact B FEM 4 Extrap % Error FEM 4 Extrap B +N = 4 67.384857 65.562359 NaN 0.027046 NaN NaN NaN 67.374295 NaN 1.567351e-04 NaN NaN NaN +N = 8 67.384857 66.822621 NaN 0.008344 -1.696669 NaN NaN 67.384157 NaN 1.037839e-05 -3.916674 NaN NaN +N = 16 67.384857 67.228445 67.421196 0.002859 -1.845831 0.002859 NaN 67.384812 67.384859 6.914151e-07 -3.977871 6.914151e-07 NaN +N = 32 67.384857 67.343581 67.389183 0.000677 -1.921976 0.000677 -1.817524 67.384854 67.384857 4.190551e-08 -3.994383 4.190551e-08 -3.975621 +N = 64 67.384857 67.374253 67.385391 0.000165 -1.960712 0.000165 -1.908339 67.384857 67.384857 2.046963e-09 -3.998556 2.046963e-09 -4.316630 +N = 128 67.384857 67.382169 67.384923 0.000041 -1.980281 0.000041 -1.954008 67.384857 67.384857 2.172310e-09 -4.000123 2.172310e-09 3.109563 +N = 256 67.384857 67.384180 67.384865 0.000010 -1.990121 0.000010 -1.976956 67.384857 67.384855 3.177752e-08 -4.072990 3.177752e-08 0.006917 +N = 512 67.384857 67.384687 67.384858 0.000003 -1.995056 0.000003 -1.988465 67.384857 67.384981 1.850506e-06 -5.906415 1.850506e-06 -0.000007 + + +Convergence of FDM Temperature at x_bar = 0.637 and k_ratio = 8.0 + True T FDM 2 T FDM 2 Extrap T FDM 2 % Error FDM 2 Exact B FDM 2 Extrap % Error FDM 2 Extrap B FDM 4 T FDM 4 Extrap T FDM 4 % Error FDM 4 Exact B FDM 4 Extrap % Error FDM 4 Extrap B +N = 4 80.863285 79.714831 NaN 1.420242e-02 NaN NaN NaN 80.803072 NaN 7.446247e-04 NaN NaN NaN +N = 8 80.863285 80.559732 NaN 3.753903e-03 -1.919673 NaN NaN 80.858940 NaN 5.373535e-05 -3.792570 NaN NaN +N = 16 80.863285 80.786251 80.869227 1.026052e-03 -1.978385 1.026052e-03 NaN 80.863003 80.863321 3.940703e-06 -3.944551 3.940703e-06 NaN +N = 32 80.863285 80.843953 80.863675 2.438962e-04 -1.994488 2.438962e-04 -1.972949 80.863267 80.863285 2.276011e-07 -3.985891 2.276011e-07 -3.941695 +N = 64 80.863285 80.858447 80.863310 6.013105e-05 -1.998615 6.013105e-05 -1.993108 80.863284 80.863285 1.389183e-08 -3.996466 1.389183e-08 -3.987572 +N = 128 80.863285 80.862075 80.863286 1.497913e-05 -1.999653 1.497913e-05 -1.998269 80.863285 80.863285 6.440270e-10 -3.998829 6.440270e-10 -4.254628 +N = 256 80.863285 80.862982 80.863285 3.741411e-06 -1.999913 3.741411e-06 -1.999568 80.863285 80.863284 1.479848e-08 -4.006559 1.479848e-08 0.081162 +N = 512 80.863285 80.863209 80.863285 9.351445e-07 -1.999979 9.351445e-07 -1.999890 80.863285 80.863293 9.851203e-08 -4.963517 9.851203e-08 -0.000812 + + +Convergence of FEM Temperature at x_bar = 0.637 and k_ratio = 8.0 + True T FEM 2 T FEM 2 Extrap T FEM 2 % Error FEM 2 Exact B FEM 2 Extrap % Error FEM 2 Extrap B FEM 4 T FEM 4 Extrap T FEM 4 % Error FEM 4 Exact B FEM 4 Extrap % Error FEM 4 Extrap B +N = 4 80.863285 79.498914 NaN 0.016873 NaN NaN NaN 80.855768 NaN 9.295800e-05 NaN NaN NaN +N = 8 80.863285 80.453254 NaN 0.005071 -1.734431 NaN NaN 80.862788 NaN 6.149609e-06 -3.918013 NaN NaN +N = 16 80.863285 80.750296 80.884534 0.001660 -1.859558 0.001660 NaN 80.863253 80.863286 4.092696e-07 -3.978196 4.092696e-07 NaN +N = 32 80.863285 80.833578 80.866025 0.000401 -1.927308 0.000401 -1.834600 80.863283 80.863285 2.482608e-08 -3.994463 2.482608e-08 -3.975571 +N = 64 80.863285 80.855665 80.863637 0.000099 -1.962954 0.000099 -1.914803 80.863285 80.863285 1.084340e-09 -3.998642 1.084340e-09 -4.470206 +N = 128 80.863285 80.861355 80.863330 0.000024 -1.981291 0.000024 -1.956682 80.863285 80.863285 1.012989e-09 -3.995944 1.012989e-09 1.261409 +N = 256 80.863285 80.862799 80.863290 0.000006 -1.990597 0.000006 -1.978148 80.863285 80.863295 1.229648e-07 -4.071341 1.229648e-07 -0.001059 +N = 512 80.863285 80.863163 80.863286 0.000002 -1.995285 0.000002 -1.989011 80.863285 80.863291 7.828902e-08 -5.162794 7.828902e-08 -0.000108 + + +Convergence of FDM Temperature at x_bar = 0.637 and k_ratio = 16.0 + True T FDM 2 T FDM 2 Extrap T FDM 2 % Error FDM 2 Exact B FDM 2 Extrap % Error FDM 2 Extrap B FDM 4 T FDM 4 Extrap T FDM 4 % Error FDM 4 Exact B FDM 4 Extrap % Error FDM 4 Extrap B +N = 4 89.525116 88.797458 NaN 8.127968e-03 NaN NaN NaN 89.488625 NaN 4.076008e-04 NaN NaN NaN +N = 8 89.525116 89.334419 NaN 2.130095e-03 -1.931977 NaN NaN 89.522484 NaN 2.939692e-05 -3.793420 NaN NaN +N = 16 89.525116 89.476830 89.528233 5.741568e-04 -1.981624 5.741568e-04 NaN 89.524945 89.525138 2.154388e-06 -3.944680 2.154388e-06 NaN +N = 32 89.525116 89.513005 89.525323 1.375906e-04 -1.995309 1.375906e-04 -1.977014 89.525105 89.525116 1.244935e-07 -3.985917 1.244935e-07 -3.941793 +N = 64 89.525116 89.522085 89.525129 3.399383e-05 -1.998821 3.399383e-05 -1.994135 89.525115 89.525116 7.612812e-09 -3.996463 7.612812e-09 -3.985113 +N = 128 89.525116 89.524358 89.525116 8.472662e-06 -1.999705 8.472662e-06 -1.998526 89.525116 89.525116 8.748161e-11 -3.998068 8.748161e-11 -6.320010 +N = 256 89.525116 89.524926 89.525116 2.116535e-06 -1.999925 2.116535e-06 -1.999635 89.525116 89.525118 2.897972e-08 -4.004300 2.897972e-08 -0.021888 +N = 512 89.525116 89.525068 89.525116 5.290376e-07 -1.999984 5.290376e-07 -1.999904 89.525116 89.525119 3.980727e-08 -1.948540 3.980727e-08 -0.000790 + + +Convergence of FEM Temperature at x_bar = 0.637 and k_ratio = 16.0 + True T FEM 2 T FEM 2 Extrap T FEM 2 % Error FEM 2 Exact B FEM 2 Extrap % Error FEM 2 Extrap B FEM 4 T FEM 4 Extrap T FEM 4 % Error FEM 4 Exact B FEM 4 Extrap % Error FEM 4 Extrap B +N = 4 89.525116 88.671094 NaN 9.539464e-03 NaN NaN NaN 89.520554 NaN 5.095274e-05 NaN NaN NaN +N = 8 89.525116 89.272101 NaN 2.826187e-03 -1.755051 NaN NaN 89.524814 NaN 3.369930e-06 -3.918369 NaN NaN +N = 16 89.525116 89.455749 89.536559 9.025348e-04 -1.866912 9.025348e-04 NaN 89.525096 89.525117 2.242150e-07 -3.978276 2.242150e-07 NaN +N = 32 89.525116 89.506913 89.526672 2.207033e-04 -1.930093 2.207033e-04 -1.843749 89.525114 89.525116 1.353063e-08 -3.994481 1.353063e-08 -3.982852 +N = 64 89.525116 89.520450 89.525321 5.440306e-05 -1.964098 5.440306e-05 -1.918185 89.525116 89.525116 1.848159e-09 -3.998667 1.848159e-09 -2.964279 +N = 128 89.525116 89.523934 89.525142 1.348824e-05 -1.981797 1.348824e-05 -1.958049 89.525116 89.525117 1.247827e-08 -4.003756 1.247827e-08 -0.088223 +N = 256 89.525116 89.524818 89.525119 3.356780e-06 -1.990833 3.356780e-06 -1.978749 89.525116 89.525130 1.627852e-07 -4.078042 1.627852e-07 -0.000436 +N = 512 89.525116 89.525041 89.525116 8.372148e-07 -1.995395 8.372148e-07 -1.989289 89.525116 89.525379 2.942796e-06 -4.742373 2.942796e-06 -0.000001 + + +Section 3 Temp: Convergence of FDM and FEM Temp with Varying k Ratio +Convergence of FDM Heat with x_bar = 0.500 and k_ratio = 0.0625 + True Q FDM 2 Q FDM 2 Extrap Q FDM 2 % Error FDM 2 Exact B FDM 2 Extrap % Error FDM 2 Extrap B FDM 4 Q FDM 4 Extrap Q FDM 4 % Error FDM 4 Exact B FDM 4 Extrap % Error FDM 4 Extrap B +N = 4 -1.241829 -2.323339 NaN 0.870901 NaN NaN NaN -1.489915 NaN 1.997754e-01 NaN NaN NaN +N = 8 -1.241829 -1.583037 NaN 0.274763 -1.664323 NaN NaN -1.276591 NaN 2.799300e-02 -2.835241 NaN NaN +N = 16 -1.241829 -1.335328 -1.210764 0.102880 -1.867617 0.102880 NaN -1.244804 -1.239238 4.491405e-03 -3.546385 4.491405e-03 NaN +N = 32 -1.241829 -1.265851 -1.238768 0.021863 -1.960577 0.021863 -1.834029 -1.242032 -1.241768 2.131856e-04 -3.867273 2.131856e-04 -3.519703 +N = 64 -1.241829 -1.247878 -1.241605 0.005052 -1.989623 0.005052 -1.950668 -1.241842 -1.241827 1.136302e-05 -3.965316 1.136302e-05 -3.860317 +N = 128 -1.241829 -1.243344 -1.241814 0.001232 -1.997371 0.001232 -1.987025 -1.241829 -1.241829 6.746119e-07 -3.991275 6.746119e-07 -3.963554 +N = 256 -1.241829 -1.242207 -1.241828 0.000306 -1.999340 0.000306 -1.996713 -1.241829 -1.241829 4.157855e-08 -3.998542 4.157855e-08 -3.991048 +N = 512 -1.241829 -1.241923 -1.241828 0.000076 -1.999835 0.000076 -1.999175 -1.241829 -1.241829 2.836237e-09 -4.011395 2.836237e-09 -3.875262 + + +Convergence of FEM Heat with x_bar = 0.500 and k_ratio = 0.0625 + True Q FEM 2 Q FEM 2 Extrap Q FEM 2 % Error FEM 2 Exact B FEM 2 Extrap % Error FEM 2 Extrap B FEM 4 Q FEM 4 Extrap Q FEM 4 % Error FEM 4 Exact B FEM 4 Extrap % Error FEM 4 Extrap B +N = 4 -1.241829 -2.386292 NaN 0.921596 NaN NaN NaN -1.488766 NaN 1.988502e-01 NaN NaN NaN +N = 8 -1.241829 -1.638864 NaN 0.319718 -1.527334 NaN NaN -1.276827 NaN 2.818331e-02 -2.818769 NaN NaN +N = 16 -1.241829 -1.364788 -1.206097 0.131575 -1.691080 0.131575 NaN -1.244914 -1.239256 4.565149e-03 -3.503830 4.565149e-03 NaN +N = 32 -1.241829 -1.276744 -1.235074 0.033739 -1.816262 0.033739 -1.638264 -1.242045 -1.241762 2.281106e-04 -3.829927 2.281106e-04 -3.475886 +N = 64 -1.241829 -1.251195 -1.240750 0.008418 -1.898303 0.008418 -1.784977 -1.241843 -1.241827 1.243065e-05 -3.942524 1.243065e-05 -3.821757 +N = 128 -1.241829 -1.244259 -1.241674 0.002081 -1.946248 0.002081 -1.881117 -1.241829 -1.241829 7.417125e-07 -3.978996 7.417125e-07 -3.940018 +N = 256 -1.241829 -1.242448 -1.241808 0.000515 -1.972331 0.000515 -1.937219 -1.241829 -1.241829 4.576965e-08 -3.992154 4.576965e-08 -3.977715 +N = 512 -1.241829 -1.241985 -1.241826 0.000128 -1.985958 0.000128 -1.967700 -1.241829 -1.241829 3.130100e-09 -4.007118 3.130100e-09 -3.864662 + + +Convergence of FDM Heat with x_bar = 0.500 and k_ratio = 0.125 + True Q FDM 2 Q FDM 2 Extrap Q FDM 2 % Error FDM 2 Exact B FDM 2 Extrap % Error FDM 2 Extrap B FDM 4 Q FDM 4 Extrap Q FDM 4 % Error FDM 4 Exact B FDM 4 Extrap % Error FDM 4 Extrap B +N = 4 -1.756437 -2.635211 NaN 0.500316 NaN NaN NaN -1.898178 NaN 8.069805e-02 NaN NaN NaN +N = 8 -1.756437 -2.012353 NaN 0.145701 -1.779824 NaN NaN -1.771468 NaN 8.557588e-03 -3.237258 NaN NaN +N = 16 -1.756437 -1.823780 -1.741900 0.047006 -1.926064 0.047006 NaN -1.757555 -1.755839 9.773508e-04 -3.748951 9.773508e-04 NaN +N = 32 -1.756437 -1.773512 -1.755242 0.010409 -1.979630 0.010409 -1.907407 -1.756511 -1.756426 4.829010e-05 -3.931668 4.829010e-05 -3.735225 +N = 64 -1.756437 -1.760722 -1.756356 0.002486 -1.994770 0.002486 -1.974522 -1.756442 -1.756437 2.747175e-06 -3.982525 2.747175e-06 -3.928168 +N = 128 -1.756437 -1.757509 -1.756432 0.000613 -1.998684 0.000613 -1.993462 -1.756438 -1.756437 1.671405e-07 -3.995610 1.671405e-07 -3.981650 +N = 256 -1.756437 -1.756705 -1.756437 0.000153 -1.999670 0.000153 -1.998354 -1.756437 -1.756437 1.041028e-08 -3.998942 1.041028e-08 -3.990638 +N = 512 -1.756437 -1.756504 -1.756437 0.000038 -1.999918 0.000038 -1.999588 -1.756437 -1.756437 1.383606e-09 -4.000125 1.383606e-09 -3.001915 + + +Convergence of FEM Heat with x_bar = 0.500 and k_ratio = 0.125 + True Q FEM 2 Q FEM 2 Extrap Q FEM 2 % Error FEM 2 Exact B FEM 2 Extrap % Error FEM 2 Extrap B FEM 4 Q FEM 4 Extrap Q FEM 4 % Error FEM 4 Exact B FEM 4 Extrap % Error FEM 4 Extrap B +N = 4 -1.756437 -2.724280 NaN 0.551026 NaN NaN NaN -1.897893 NaN 8.053547e-02 NaN NaN NaN +N = 8 -1.756437 -2.072823 NaN 0.180129 -1.613087 NaN NaN -1.771784 NaN 8.737232e-03 -3.204376 NaN NaN +N = 16 -1.756437 -1.849907 -1.733951 0.066874 -1.759120 0.066874 NaN -1.757613 -1.755819 1.021680e-03 -3.706141 1.021680e-03 NaN +N = 32 -1.756437 -1.782145 -1.752552 0.016886 -1.862264 0.016886 -1.717974 -1.756516 -1.756424 5.242384e-05 -3.901773 5.242384e-05 -3.691040 +N = 64 -1.756437 -1.763204 -1.755855 0.004186 -1.925724 0.004186 -1.838899 -1.756442 -1.756437 3.015804e-06 -3.965659 3.015804e-06 -3.897299 +N = 128 -1.756437 -1.758175 -1.756357 0.001035 -1.961334 0.001035 -1.913214 -1.756438 -1.756437 1.838668e-07 -3.986774 1.838668e-07 -3.964188 +N = 256 -1.756437 -1.756878 -1.756427 0.000257 -1.980259 0.000257 -1.954852 -1.756437 -1.756437 1.141355e-08 -3.994454 1.141355e-08 -3.986272 +N = 512 -1.756437 -1.756548 -1.756436 0.000064 -1.990024 0.000064 -1.976959 -1.756437 -1.756437 7.108086e-10 -3.997585 7.108086e-10 -3.996485 + + +Convergence of FDM Heat with x_bar = 0.500 and k_ratio = 0.25 + True Q FDM 2 Q FDM 2 Extrap Q FDM 2 % Error FDM 2 Exact B FDM 2 Extrap % Error FDM 2 Extrap B FDM 4 Q FDM 4 Extrap Q FDM 4 % Error FDM 4 Exact B FDM 4 Extrap % Error FDM 4 Extrap B +N = 4 -2.486946 -3.171745 NaN 0.275357 NaN NaN NaN -2.556595 NaN 2.800566e-02 NaN NaN NaN +N = 8 -2.486946 -2.674530 NaN 0.075427 -1.868146 NaN NaN -2.492907 NaN 2.396673e-03 -3.546613 NaN NaN +N = 16 -2.486946 -2.535136 -2.480834 0.021889 -1.960724 0.021889 NaN -2.487355 -2.486824 2.132094e-04 -3.867344 2.132094e-04 NaN +N = 32 -2.486946 -2.499080 -2.486500 0.005059 -1.989662 0.005059 -1.950854 -2.486972 -2.486944 1.136517e-05 -3.965333 1.136517e-05 -3.860392 +N = 64 -2.486946 -2.489985 -2.486917 0.001234 -1.997380 0.001234 -1.987073 -2.486948 -2.486946 6.747542e-07 -3.991233 6.747542e-07 -3.963582 +N = 128 -2.486946 -2.487706 -2.486944 0.000306 -1.999343 0.000306 -1.996725 -2.486946 -2.486946 4.159483e-08 -3.997803 4.159483e-08 -3.990827 +N = 256 -2.486946 -2.487136 -2.486946 0.000076 -1.999836 0.000076 -1.999178 -2.486946 -2.486946 2.466753e-09 -3.999493 2.466753e-09 -4.064070 +N = 512 -2.486946 -2.486994 -2.486946 0.000019 -1.999959 0.000019 -1.999794 -2.486946 -2.486946 4.903515e-10 -3.995488 4.903515e-10 -1.980183 + + +Convergence of FEM Heat with x_bar = 0.500 and k_ratio = 0.25 + True Q FEM 2 Q FEM 2 Extrap Q FEM 2 % Error FEM 2 Exact B FEM 2 Extrap % Error FEM 2 Extrap B FEM 4 Q FEM 4 Extrap Q FEM 4 % Error FEM 4 Exact B FEM 4 Extrap % Error FEM 4 Extrap B +N = 4 -2.486946 -3.277606 NaN 0.317924 NaN NaN NaN -2.557137 NaN 2.822377e-02 NaN NaN NaN +N = 8 -2.486946 -2.732243 NaN 0.098634 -1.688525 NaN NaN -2.493130 NaN 2.486681e-03 -3.504617 NaN NaN +N = 16 -2.486946 -2.556640 -2.473243 0.033720 -1.815438 0.033720 NaN -2.487381 -2.486814 2.281691e-04 -3.830158 2.281691e-04 NaN +N = 32 -2.486946 -2.505646 -2.484779 0.008398 -1.897969 0.008398 -1.783949 -2.486974 -2.486944 1.243751e-05 -3.942603 1.243751e-05 -3.822000 +N = 64 -2.486946 -2.491799 -2.486637 0.002076 -1.946097 0.002076 -1.880714 -2.486948 -2.486946 7.421638e-07 -3.978987 7.421638e-07 -3.940106 +N = 128 -2.486946 -2.488183 -2.486905 0.000514 -1.972258 0.000514 -1.937039 -2.486946 -2.486946 4.576309e-08 -3.991494 4.576309e-08 -3.978786 +N = 256 -2.486946 -2.487258 -2.486941 0.000128 -1.985922 0.000128 -1.967615 -2.486946 -2.486946 2.933993e-09 -3.996286 2.933993e-09 -3.952648 +N = 512 -2.486946 -2.487025 -2.486946 0.000032 -1.992908 0.000032 -1.983571 -2.486946 -2.486946 1.338225e-09 -3.995277 1.338225e-09 0.015005 + + +Convergence of FDM Heat with x_bar = 0.500 and k_ratio = 0.5 + True Q FDM 2 Q FDM 2 Extrap Q FDM 2 % Error FDM 2 Exact B FDM 2 Extrap % Error FDM 2 Extrap B FDM 4 Q FDM 4 Extrap Q FDM 4 % Error FDM 4 Exact B FDM 4 Extrap % Error FDM 4 Extrap B +N = 4 -3.529489 -4.044925 NaN 0.146037 NaN NaN NaN -3.559595 NaN 8.529659e-03 NaN NaN NaN +N = 8 -3.529489 -3.665089 NaN 0.038419 -1.926443 NaN NaN -3.531728 NaN 6.341705e-04 -3.749546 NaN NaN +N = 16 -3.529489 -3.563869 -3.527097 0.010426 -1.979723 0.010426 NaN -3.529636 -3.529466 4.809035e-05 -3.931843 4.809035e-05 NaN +N = 32 -3.529489 -3.538115 -3.529327 0.002490 -1.994793 0.002490 -1.974639 -3.529499 -3.529489 2.736381e-06 -3.982571 2.736381e-06 -3.928352 +N = 64 -3.529489 -3.531648 -3.529479 0.000614 -1.998689 0.000614 -1.993491 -3.529490 -3.529489 1.664953e-07 -3.995618 1.664953e-07 -3.981696 +N = 128 -3.529489 -3.530029 -3.529489 0.000153 -1.999672 0.000153 -1.998362 -3.529489 -3.529489 1.035257e-08 -3.998886 1.035257e-08 -3.992959 +N = 256 -3.529489 -3.529624 -3.529489 0.000038 -1.999918 0.000038 -1.999590 -3.529489 -3.529489 1.143815e-09 -3.999052 1.143815e-09 -3.239972 +N = 512 -3.529489 -3.529523 -3.529489 0.000010 -1.999979 0.000010 -1.999898 -3.529489 -3.529489 7.826466e-10 -3.962070 7.826466e-10 2.125343 + + +Convergence of FEM Heat with x_bar = 0.500 and k_ratio = 0.5 + True Q FEM 2 Q FEM 2 Extrap Q FEM 2 % Error FEM 2 Exact B FEM 2 Extrap % Error FEM 2 Extrap B FEM 4 Q FEM 4 Extrap Q FEM 4 % Error FEM 4 Exact B FEM 4 Extrap % Error FEM 4 Extrap B +N = 4 -3.529489 -4.151337 NaN 0.176186 NaN NaN NaN -3.560400 NaN 8.757825e-03 NaN NaN NaN +N = 8 -3.529489 -3.714639 NaN 0.052458 -1.747869 NaN NaN -3.531856 NaN 6.705386e-04 -3.707180 NaN NaN +N = 16 -3.529489 -3.580543 -3.521119 0.016876 -1.858611 0.016876 NaN -3.529648 -3.529462 5.246721e-05 -3.902139 5.246721e-05 NaN +N = 32 -3.529489 -3.542941 -3.528289 0.004153 -1.924207 0.004153 -1.834401 -3.529499 -3.529489 3.019131e-06 -3.965805 3.019131e-06 -3.897682 +N = 64 -3.529489 -3.532945 -3.529326 0.001026 -1.960639 0.001026 -1.911393 -3.529490 -3.529489 1.840754e-07 -3.986834 1.840754e-07 -3.964387 +N = 128 -3.529489 -3.530365 -3.529468 0.000254 -1.979926 0.000254 -1.954030 -3.529489 -3.529489 1.149619e-08 -3.994426 1.149619e-08 -3.978192 +N = 256 -3.529489 -3.529710 -3.529487 0.000063 -1.989861 0.000063 -1.976568 -3.529489 -3.529489 1.754708e-09 -3.996694 1.754708e-09 -2.821280 +N = 512 -3.529489 -3.529545 -3.529489 0.000016 -1.994905 0.000016 -1.988168 -3.529489 -3.529489 7.304833e-09 -3.985645 7.304833e-09 0.138062 + + +Convergence of FDM Heat with x_bar = 0.500 and k_ratio = 1.0 + True Q FDM 2 Q FDM 2 Extrap Q FDM 2 % Error FDM 2 Exact B FDM 2 Extrap % Error FDM 2 Extrap B FDM 4 Q FDM 4 Extrap Q FDM 4 % Error FDM 4 Exact B FDM 4 Extrap % Error FDM 4 Extrap B +N = 4 -4.985127 -5.363661 NaN 0.075933 NaN NaN NaN -4.997127 NaN 2.407224e-03 NaN NaN NaN +N = 8 -4.985127 -5.082312 NaN 0.019495 -1.961618 NaN NaN -4.985949 NaN 1.649282e-04 -3.867460 NaN NaN +N = 16 -4.985127 -5.009594 -4.984248 0.005085 -1.989885 0.005085 NaN -4.985179 -4.985122 1.141325e-05 -3.965359 1.141325e-05 NaN +N = 32 -4.985127 -4.991254 -4.985069 0.001241 -1.997436 0.001241 -1.987353 -4.985130 -4.985126 6.776447e-07 -3.991240 6.776447e-07 -3.963608 +N = 64 -4.985127 -4.986659 -4.985123 0.000308 -1.999357 0.000308 -1.996795 -4.985127 -4.985127 4.178327e-08 -3.997804 4.178327e-08 -3.990514 +N = 128 -4.985127 -4.985510 -4.985126 0.000077 -1.999839 0.000077 -1.999196 -4.985127 -4.985127 2.828357e-09 -3.999474 2.828357e-09 -3.885074 +N = 256 -4.985127 -4.985222 -4.985126 0.000019 -1.999960 0.000019 -1.999799 -4.985127 -4.985127 3.892385e-12 -3.994823 3.892385e-12 -9.291580 +N = 512 -4.985127 -4.985150 -4.985127 0.000005 -1.999990 0.000005 -1.999950 -4.985127 -4.985126 1.878544e-08 -4.146631 1.878544e-08 -0.011762 + + +Convergence of FEM Heat with x_bar = 0.500 and k_ratio = 1.0 + True Q FEM 2 Q FEM 2 Extrap Q FEM 2 % Error FEM 2 Exact B FEM 2 Extrap % Error FEM 2 Extrap B FEM 4 Q FEM 4 Extrap Q FEM 4 % Error FEM 4 Exact B FEM 4 Extrap % Error FEM 4 Extrap B +N = 4 -4.985127 -5.459208 NaN 0.095099 NaN NaN NaN -4.997547 NaN 2.491440e-03 NaN NaN NaN +N = 8 -4.985127 -5.122610 NaN 0.027579 -1.785873 NaN NaN -4.985999 NaN 1.751167e-04 -3.830591 NaN NaN +N = 16 -4.985127 -5.022303 -4.979722 0.008551 -1.886793 0.008551 NaN -4.985183 -4.985121 1.245343e-05 -3.942758 1.245343e-05 NaN +N = 32 -4.985127 -4.994808 -4.984424 0.002083 -1.941161 0.002083 -1.867152 -4.985130 -4.985126 7.431957e-07 -3.979049 7.431957e-07 -3.940265 +N = 64 -4.985127 -4.987598 -4.985035 0.000514 -1.969937 0.000514 -1.931164 -4.985127 -4.985127 4.586722e-08 -3.991520 4.586722e-08 -3.977691 +N = 128 -4.985127 -4.985751 -4.985115 0.000128 -1.984797 0.000128 -1.964878 -4.985127 -4.985127 3.217920e-09 -3.996280 3.217920e-09 -3.830308 +N = 256 -4.985127 -4.985283 -4.985125 0.000032 -1.992354 0.000032 -1.982251 -4.985127 -4.985126 2.619162e-09 -3.995181 2.619162e-09 -1.012964 +N = 512 -4.985127 -4.985166 -4.985126 0.000008 -1.996167 0.000008 -1.991076 -4.985127 -4.985127 2.627928e-08 -3.954802 2.627928e-08 0.009191 + + +Convergence of FDM Heat with x_bar = 0.500 and k_ratio = 2.0 + True Q FDM 2 Q FDM 2 Extrap Q FDM 2 % Error FDM 2 Exact B FDM 2 Extrap % Error FDM 2 Extrap B FDM 4 Q FDM 4 Extrap Q FDM 4 % Error FDM 4 Exact B FDM 4 Extrap % Error FDM 4 Extrap B +N = 4 -6.832006 -7.120389 NaN 0.042211 NaN NaN NaN -6.837657 NaN 8.271733e-04 NaN NaN NaN +N = 8 -6.832006 -6.905215 NaN 0.010716 -1.977901 NaN NaN -6.832382 NaN 5.498761e-05 -3.911011 NaN NaN +N = 16 -6.832006 -6.850381 -6.831629 0.002745 -1.994255 0.002745 NaN -6.832030 -6.832005 3.679505e-06 -3.976922 3.679505e-06 NaN +N = 32 -6.832006 -6.836605 -6.831982 0.000677 -1.998549 0.000677 -1.992819 -6.832008 -6.832006 2.221497e-07 -3.994176 2.221497e-07 -3.975751 +N = 64 -6.832006 -6.833156 -6.832005 0.000169 -1.999636 0.000169 -1.998186 -6.832006 -6.832006 1.379322e-08 -3.998527 1.379322e-08 -3.990379 +N = 128 -6.832006 -6.832294 -6.832006 0.000042 -1.999909 0.000042 -1.999545 -6.832006 -6.832006 1.862709e-09 -3.999120 1.862709e-09 -2.981877 +N = 256 -6.832006 -6.832078 -6.832006 0.000011 -1.999977 0.000011 -1.999886 -6.832006 -6.832006 1.324195e-08 -3.970921 1.324195e-08 0.090221 +N = 512 -6.832006 -6.832024 -6.832006 0.000003 -1.999997 0.000003 -1.999971 -6.832006 -6.832005 2.031033e-07 -2.712521 2.031033e-07 -0.000329 + + +Convergence of FEM Heat with x_bar = 0.500 and k_ratio = 2.0 + True Q FEM 2 Q FEM 2 Extrap Q FEM 2 % Error FEM 2 Exact B FEM 2 Extrap % Error FEM 2 Extrap B FEM 4 Q FEM 4 Extrap Q FEM 4 % Error FEM 4 Exact B FEM 4 Extrap % Error FEM 4 Extrap B +N = 4 -6.832006 -7.202967 NaN 0.054297 NaN NaN NaN -6.836734 NaN 6.919495e-04 NaN NaN NaN +N = 8 -6.832006 -6.938675 NaN 0.015613 -1.798121 NaN NaN -6.832322 NaN 4.628007e-05 -3.902204 NaN NaN +N = 16 -6.832006 -6.860626 -6.827918 0.004790 -1.898047 0.004790 NaN -6.832026 -6.832005 3.115230e-06 -3.965787 3.115230e-06 NaN +N = 32 -6.832006 -6.839422 -6.831512 0.001158 -1.948400 0.001158 -1.880015 -6.832007 -6.832006 1.899456e-07 -3.986822 1.899456e-07 -3.964396 +N = 64 -6.832006 -6.833894 -6.831944 0.000285 -1.974008 0.000285 -1.939550 -6.832006 -6.832006 1.170627e-08 -3.994421 1.170627e-08 -3.996168 +N = 128 -6.832006 -6.832482 -6.831998 0.000071 -1.986952 0.000071 -1.969614 -6.832006 -6.832006 4.876349e-10 -3.996829 4.876349e-10 -4.556528 +N = 256 -6.832006 -6.832126 -6.832005 0.000018 -1.993462 0.000018 -1.984762 -6.832006 -6.832006 4.071656e-09 -3.990079 4.071656e-09 0.267031 +N = 512 -6.832006 -6.832036 -6.832006 0.000004 -1.996727 0.000004 -1.992369 -6.832006 -6.832006 5.252254e-08 -4.462020 5.252254e-08 0.001327 + + +Convergence of FDM Heat with x_bar = 0.500 and k_ratio = 4.0 + True Q FDM 2 Q FDM 2 Extrap Q FDM 2 % Error FDM 2 Exact B FDM 2 Extrap % Error FDM 2 Extrap B FDM 4 Q FDM 4 Extrap Q FDM 4 % Error FDM 4 Exact B FDM 4 Extrap % Error FDM 4 Extrap B +N = 4 -8.797049 -9.060288 NaN 0.029924 NaN NaN NaN -8.802357 NaN 6.033795e-04 NaN NaN NaN +N = 8 -8.797049 -8.864016 NaN 0.007612 -1.974855 NaN NaN -8.797407 NaN 4.074671e-05 -3.888310 NaN NaN +N = 16 -8.797049 -8.813868 -8.796658 0.001956 -1.993338 0.001956 NaN -8.797072 -8.797047 2.774659e-06 -3.970790 2.774659e-06 NaN +N = 32 -8.797049 -8.801259 -8.797023 0.000481 -1.998309 0.000481 -1.991674 -8.797050 -8.797049 1.660966e-07 -3.992612 1.660966e-07 -3.969303 +N = 64 -8.797049 -8.798102 -8.797047 0.000120 -1.999576 0.000120 -1.997886 -8.797049 -8.797049 1.028146e-08 -3.998156 1.028146e-08 -3.989594 +N = 128 -8.797049 -8.797312 -8.797049 0.000030 -1.999894 0.000030 -1.999469 -8.797049 -8.797049 4.932746e-10 -3.998186 4.932746e-10 -4.202856 +N = 256 -8.797049 -8.797115 -8.797049 0.000007 -1.999973 0.000007 -1.999867 -8.797049 -8.797049 1.765533e-09 -4.027343 1.765533e-09 -0.422141 +N = 512 -8.797049 -8.797065 -8.797049 0.000002 -1.999997 0.000002 -1.999954 -8.797049 -8.797046 2.985972e-07 -3.904864 2.985972e-07 -0.000177 + + +Convergence of FEM Heat with x_bar = 0.500 and k_ratio = 4.0 + True Q FEM 2 Q FEM 2 Extrap Q FEM 2 % Error FEM 2 Exact B FEM 2 Extrap % Error FEM 2 Extrap B FEM 4 Q FEM 4 Extrap Q FEM 4 % Error FEM 4 Exact B FEM 4 Extrap % Error FEM 4 Extrap B +N = 4 -8.797049 -9.133348 NaN 0.038229 NaN NaN NaN -8.799070 NaN 2.297472e-04 NaN NaN NaN +N = 8 -8.797049 -8.894031 NaN 0.011024 -1.793956 NaN NaN -8.797180 NaN 1.494372e-05 -3.942436 NaN NaN +N = 16 -8.797049 -8.823091 -8.793202 0.003399 -1.896890 0.003399 NaN -8.797057 -8.797049 9.755775e-07 -3.979737 9.755775e-07 NaN +N = 32 -8.797049 -8.803797 -8.796590 0.000819 -1.948194 0.000819 -1.878506 -8.797049 -8.797049 6.012137e-08 -3.992123 6.012137e-08 -3.978619 +N = 64 -8.797049 -8.798767 -8.796992 0.000202 -1.974011 0.000202 -1.939272 -8.797049 -8.797049 3.963173e-09 -3.996647 3.963173e-09 -3.914403 +N = 128 -8.797049 -8.797482 -8.797042 0.000050 -1.986981 0.000050 -1.969609 -8.797049 -8.797049 2.397599e-09 -3.996510 2.397599e-09 1.127149 +N = 256 -8.797049 -8.797158 -8.797048 0.000012 -1.993485 0.000012 -1.984794 -8.797049 -8.797048 6.950475e-08 -3.965261 6.950475e-08 -0.004532 +N = 512 -8.797049 -8.797076 -8.797049 0.000003 -1.996745 0.000003 -1.992394 -8.797049 -8.797060 1.303768e-06 -1.647698 1.303768e-06 0.000022 + + +Convergence of FDM Heat with x_bar = 0.500 and k_ratio = 8.0 + True Q FDM 2 Q FDM 2 Extrap Q FDM 2 % Error FDM 2 Exact B FDM 2 Extrap % Error FDM 2 Extrap B FDM 4 Q FDM 4 Extrap Q FDM 4 % Error FDM 4 Exact B FDM 4 Extrap % Error FDM 4 Extrap B +N = 4 -10.486214 -10.779857 NaN 0.028003 NaN NaN NaN -10.493612 NaN 7.054714e-04 NaN NaN NaN +N = 8 -10.486214 -10.561319 NaN 0.007162 -1.967076 NaN NaN -10.486719 NaN 4.814601e-05 -3.873099 NaN NaN +N = 16 -10.486214 -10.505104 -10.485636 0.001857 -1.991276 0.001857 NaN -10.486246 -10.486211 3.317279e-06 -3.966863 3.317279e-06 NaN +N = 32 -10.486214 -10.490944 -10.486176 0.000455 -1.997786 0.000455 -1.989096 -10.486216 -10.486214 1.973876e-07 -3.991621 1.973876e-07 -3.965170 +N = 64 -10.486214 -10.487397 -10.486211 0.000113 -1.999444 0.000113 -1.997232 -10.486214 -10.486214 1.213030e-08 -3.997866 1.213030e-08 -3.996212 +N = 128 -10.486214 -10.486510 -10.486214 0.000028 -1.999861 0.000028 -1.999305 -10.486214 -10.486214 2.131372e-09 -3.997144 2.131372e-09 -2.661836 +N = 256 -10.486214 -10.486288 -10.486214 0.000007 -1.999966 0.000007 -1.999826 -10.486214 -10.486214 4.274711e-09 -3.846239 4.274711e-09 -0.220515 +N = 512 -10.486214 -10.486232 -10.486214 0.000002 -1.999975 0.000002 -1.999969 -10.486214 -10.486214 4.898006e-09 -0.513431 4.898006e-09 -0.004645 + + +Convergence of FEM Heat with x_bar = 0.500 and k_ratio = 8.0 + True Q FEM 2 Q FEM 2 Extrap Q FEM 2 % Error FEM 2 Exact B FEM 2 Extrap % Error FEM 2 Extrap B FEM 4 Q FEM 4 Extrap Q FEM 4 % Error FEM 4 Exact B FEM 4 Extrap % Error FEM 4 Extrap B +N = 4 -10.486214 -10.847776 NaN 0.034480 NaN NaN NaN -10.487582 NaN 1.304358e-04 NaN NaN NaN +N = 8 -10.486214 -10.590389 NaN 0.009935 -1.795226 NaN NaN -10.486302 NaN 8.398688e-06 -3.957032 NaN NaN +N = 16 -10.486214 -10.514219 -10.482202 0.003054 -1.895250 0.003054 NaN -10.486219 -10.486214 5.423604e-07 -3.986778 5.423604e-07 NaN +N = 32 -10.486214 -10.493478 -10.485717 0.000740 -1.946777 0.000740 -1.876758 -10.486214 -10.486214 3.340698e-08 -3.995622 3.340698e-08 -3.987629 +N = 64 -10.486214 -10.488064 -10.486151 0.000182 -1.973142 0.000182 -1.937655 -10.486214 -10.486214 2.688212e-09 -3.998136 2.688212e-09 -3.653156 +N = 128 -10.486214 -10.486681 -10.486206 0.000045 -1.986505 0.000045 -1.968604 -10.486214 -10.486214 6.990587e-09 -3.995967 6.990587e-09 -0.354642 +N = 256 -10.486214 -10.486331 -10.486213 0.000011 -1.993235 0.000011 -1.984241 -10.486214 -10.486213 8.708136e-08 -5.849693 8.708136e-08 -0.002119 +N = 512 -10.486214 -10.486243 -10.486214 0.000003 -1.996597 0.000003 -1.992109 -10.486214 -10.486224 9.472036e-07 3.111172 9.472036e-07 -0.000026 + + +Convergence of FDM Heat with x_bar = 0.500 and k_ratio = 16.0 + True Q FDM 2 Q FDM 2 Extrap Q FDM 2 % Error FDM 2 Exact B FDM 2 Extrap % Error FDM 2 Extrap B FDM 4 Q FDM 4 Extrap Q FDM 4 % Error FDM 4 Exact B FDM 4 Extrap % Error FDM 4 Extrap B +N = 4 -11.680625 -12.024326 NaN 0.029425 NaN NaN NaN -11.690359 NaN 8.333062e-04 NaN NaN NaN +N = 8 -11.680625 -11.768665 NaN 0.007537 -1.964919 NaN NaN -11.681291 NaN 5.699702e-05 -3.869888 NaN NaN +N = 16 -11.680625 -11.702777 -11.679901 0.001959 -1.990732 0.001959 NaN -11.680668 -11.680622 3.936877e-06 -3.966020 3.936877e-06 NaN +N = 32 -11.680625 -11.686172 -11.680577 0.000479 -1.997649 0.000479 -1.988414 -11.680628 -11.680625 2.339626e-07 -3.991409 2.339626e-07 -3.964284 +N = 64 -11.680625 -11.682012 -11.680622 0.000119 -1.999410 0.000119 -1.997062 -11.680625 -11.680625 1.444745e-08 -3.997772 1.444745e-08 -3.989014 +N = 128 -11.680625 -11.680972 -11.680625 0.000030 -1.999852 0.000030 -1.999263 -11.680625 -11.680625 1.394570e-09 -4.001136 1.394570e-09 -3.412796 +N = 256 -11.680625 -11.680712 -11.680625 0.000007 -1.999964 0.000007 -1.999815 -11.680625 -11.680625 1.645965e-08 -3.981056 1.645965e-08 -0.071781 +N = 512 -11.680625 -11.680647 -11.680625 0.000002 -1.999977 0.000002 -1.999958 -11.680625 -11.680624 1.365727e-07 0.019875 1.365727e-07 0.000008 + + +Convergence of FEM Heat with x_bar = 0.500 and k_ratio = 16.0 + True Q FEM 2 Q FEM 2 Extrap Q FEM 2 % Error FEM 2 Exact B FEM 2 Extrap % Error FEM 2 Extrap B FEM 4 Q FEM 4 Extrap Q FEM 4 % Error FEM 4 Exact B FEM 4 Extrap % Error FEM 4 Extrap B +N = 4 -11.680625 -12.090051 NaN 0.035052 NaN NaN NaN -11.682009 NaN 1.185027e-04 NaN NaN NaN +N = 8 -11.680625 -11.797909 NaN 0.010041 -1.803594 NaN NaN -11.680714 NaN 7.625382e-06 -3.957966 NaN NaN +N = 16 -11.680625 -11.712125 -11.676464 0.003054 -1.896582 0.003054 NaN -11.680631 -11.680625 4.921369e-07 -3.988478 4.921369e-07 NaN +N = 32 -11.680625 -11.688797 -11.680083 0.000746 -1.946658 0.000746 -1.878621 -11.680625 -11.680625 3.029433e-08 -3.996830 3.029433e-08 -3.987749 +N = 64 -11.680625 -11.682707 -11.680555 0.000184 -1.972873 0.000184 -1.937587 -11.680625 -11.680625 1.396672e-09 -3.998848 1.396672e-09 -4.405824 +N = 128 -11.680625 -11.681150 -11.680616 0.000046 -1.986316 0.000046 -1.968306 -11.680625 -11.680625 4.998899e-09 -3.994560 4.998899e-09 -0.436061 +N = 256 -11.680625 -11.680757 -11.680624 0.000011 -1.993128 0.000011 -1.984024 -11.680625 -11.680624 9.229468e-08 -6.569744 9.229468e-08 -0.001825 +N = 512 -11.680625 -11.680658 -11.680625 0.000003 -1.996572 0.000003 -1.991978 -11.680625 -11.680638 1.106963e-06 4.036521 1.106963e-06 -0.000025 + + +Convergence of FDM Heat with x_bar = 0.637 and k_ratio = 0.0625 + True Q FDM 2 Q FDM 2 Extrap Q FDM 2 % Error FDM 2 Exact B FDM 2 Extrap % Error FDM 2 Extrap B FDM 4 Q FDM 4 Extrap Q FDM 4 % Error FDM 4 Exact B FDM 4 Extrap % Error FDM 4 Extrap B +N = 4 -1.241978 -1.892412 NaN 0.523708 NaN NaN NaN -1.350272 NaN 8.719507e-02 NaN NaN NaN +N = 8 -1.241978 -1.432463 NaN 0.153372 -1.771728 NaN NaN -1.253695 NaN 9.433953e-03 -3.208312 NaN NaN +N = 16 -1.241978 -1.292229 -1.230720 0.049978 -1.922447 0.049978 NaN -1.242857 -1.241487 1.103433e-03 -3.736406 1.103433e-03 NaN +N = 32 -1.241978 -1.254729 -1.241041 0.011030 -1.978528 0.011030 -1.902870 -1.242036 -1.241968 5.422868e-05 -3.927976 5.422868e-05 -3.721927 +N = 64 -1.241978 -1.245178 -1.241914 0.002628 -1.994480 0.002628 -1.973144 -1.241982 -1.241978 3.071666e-06 -3.982155 3.071666e-06 -3.924241 +N = 128 -1.241978 -1.242779 -1.241974 0.000648 -1.998612 0.000648 -1.993098 -1.241978 -1.241978 1.866167e-07 -4.005072 1.866167e-07 -3.980600 +N = 256 -1.241978 -1.242178 -1.241978 0.000161 -1.999661 0.000161 -1.998262 -1.241978 -1.241978 1.167171e-08 -4.163740 1.167171e-08 -3.984220 +N = 512 -1.241978 -1.242028 -1.241978 0.000040 -1.999948 0.000040 -1.999565 -1.241978 -1.241978 1.129908e-09 -4.093738 1.129908e-09 -3.403237 + + +Convergence of FEM Heat with x_bar = 0.637 and k_ratio = 0.0625 + True Q FEM 2 Q FEM 2 Extrap Q FEM 2 % Error FEM 2 Exact B FEM 2 Extrap % Error FEM 2 Extrap B FEM 4 Q FEM 4 Extrap Q FEM 4 % Error FEM 4 Exact B FEM 4 Extrap % Error FEM 4 Extrap B +N = 4 -1.241978 -1.955601 NaN 0.574586 NaN NaN NaN -1.350006 NaN 8.698070e-02 NaN NaN NaN +N = 8 -1.241978 -1.476318 NaN 0.188683 -1.606560 NaN NaN -1.253926 NaN 9.620105e-03 -3.176571 NaN NaN +N = 16 -1.241978 -1.311448 -1.224995 0.070574 -1.754142 0.070574 NaN -1.242902 -1.241473 1.150974e-03 -3.693351 1.150974e-03 NaN +N = 32 -1.241978 -1.261128 -1.239024 0.017840 -1.859012 0.017840 -1.712139 -1.242040 -1.241967 5.881873e-05 -3.897482 5.881873e-05 -3.677491 +N = 64 -1.241978 -1.247025 -1.241533 0.004424 -1.923832 0.004424 -1.835089 -1.241982 -1.241978 3.371315e-06 -3.964820 3.371315e-06 -3.892758 +N = 128 -1.241978 -1.243275 -1.241917 0.001094 -1.960308 0.001094 -1.910998 -1.241978 -1.241978 2.052741e-07 -3.995169 2.052741e-07 -3.962755 +N = 256 -1.241978 -1.242307 -1.241970 0.000271 -1.979729 0.000271 -1.953652 -1.241978 -1.241978 1.268251e-08 -4.143718 1.268251e-08 -3.991678 +N = 512 -1.241978 -1.242061 -1.241977 0.000067 -1.989772 0.000067 -1.976334 -1.241978 -1.241978 1.753379e-09 -4.424299 1.753379e-09 -2.957447 + + +Convergence of FDM Heat with x_bar = 0.637 and k_ratio = 0.125 + True Q FDM 2 Q FDM 2 Extrap Q FDM 2 % Error FDM 2 Exact B FDM 2 Extrap % Error FDM 2 Extrap B FDM 4 Q FDM 4 Extrap Q FDM 4 % Error FDM 4 Exact B FDM 4 Extrap % Error FDM 4 Extrap B +N = 4 -1.758799 -2.268096 NaN 0.289571 NaN NaN NaN -1.812674 NaN 3.063204e-02 NaN NaN NaN +N = 8 -1.758799 -1.898803 NaN 0.079602 -1.863040 NaN NaN -1.763475 NaN 2.658650e-03 -3.526276 NaN NaN +N = 16 -1.758799 -1.794813 -1.754052 0.023238 -1.958837 0.023238 NaN -1.759121 -1.758698 2.403705e-04 -3.860338 2.403705e-04 NaN +N = 32 -1.758799 -1.767870 -1.758449 0.005358 -1.989132 0.005358 -1.948491 -1.758819 -1.758797 1.273760e-05 -3.963414 1.273760e-05 -3.853001 +N = 64 -1.758799 -1.761071 -1.758776 0.001305 -1.997244 0.001305 -1.986411 -1.758800 -1.758799 7.542667e-07 -3.990746 7.542667e-07 -3.961560 +N = 128 -1.758799 -1.759367 -1.758797 0.000324 -1.999308 0.000324 -1.996554 -1.758799 -1.758799 4.646868e-08 -3.997740 4.646868e-08 -3.990090 +N = 256 -1.758799 -1.758941 -1.758799 0.000081 -1.999827 0.000081 -1.999136 -1.758799 -1.758799 2.749222e-09 -4.000295 2.749222e-09 -4.066683 +N = 512 -1.758799 -1.758834 -1.758799 0.000020 -1.999957 0.000020 -1.999784 -1.758799 -1.758799 1.148633e-09 -4.020561 1.148633e-09 -0.442350 + + +Convergence of FEM Heat with x_bar = 0.637 and k_ratio = 0.125 + True Q FEM 2 Q FEM 2 Extrap Q FEM 2 % Error FEM 2 Exact B FEM 2 Extrap % Error FEM 2 Extrap B FEM 4 Q FEM 4 Extrap Q FEM 4 % Error FEM 4 Exact B FEM 4 Extrap % Error FEM 4 Extrap B +N = 4 -1.758799 -2.343653 NaN 0.332530 NaN NaN NaN -1.813018 NaN 3.082735e-02 NaN NaN NaN +N = 8 -1.758799 -1.940923 NaN 0.103550 -1.683153 NaN NaN -1.763642 NaN 2.753720e-03 -3.484757 NaN NaN +N = 16 -1.758799 -1.810685 -1.748438 0.035602 -1.811494 0.035602 NaN -1.759141 -1.758690 2.566924e-04 -3.822634 2.566924e-04 NaN +N = 32 -1.758799 -1.772745 -1.757148 0.008876 -1.895524 0.008876 -1.779334 -1.758821 -1.758797 1.392563e-05 -3.940173 1.392563e-05 -3.814075 +N = 64 -1.758799 -1.762421 -1.758563 0.002194 -1.944724 0.002194 -1.877853 -1.758800 -1.758799 8.290856e-07 -3.978186 8.290856e-07 -3.937561 +N = 128 -1.758799 -1.759723 -1.758767 0.000543 -1.971529 0.000543 -1.935435 -1.758799 -1.758799 5.110725e-08 -3.991256 5.110725e-08 -3.977434 +N = 256 -1.758799 -1.759032 -1.758795 0.000135 -1.985546 0.000135 -1.966763 -1.758799 -1.758799 3.091361e-09 -3.997014 3.091361e-09 -4.030266 +N = 512 -1.758799 -1.758857 -1.758798 0.000034 -1.992717 0.000034 -1.983132 -1.758799 -1.758799 3.903887e-11 -4.015170 3.903887e-11 -6.231455 + + +Convergence of FDM Heat with x_bar = 0.637 and k_ratio = 0.25 + True Q FDM 2 Q FDM 2 Extrap Q FDM 2 % Error FDM 2 Exact B FDM 2 Extrap % Error FDM 2 Extrap B FDM 4 Q FDM 4 Extrap Q FDM 4 % Error FDM 4 Exact B FDM 4 Extrap % Error FDM 4 Extrap B +N = 4 -2.501202 -2.888923 NaN 0.155014 NaN NaN NaN -2.524883 NaN 9.467815e-03 NaN NaN NaN +N = 8 -2.501202 -2.603336 NaN 0.040834 -1.924555 NaN NaN -2.502977 NaN 7.099598e-04 -3.737222 NaN NaN +N = 16 -2.501202 -2.527108 -2.499354 0.011105 -1.979071 0.011105 NaN -2.501318 -2.501182 5.435757e-05 -3.928158 5.435757e-05 NaN +N = 32 -2.501202 -2.507703 -2.501075 0.002650 -1.994616 0.002650 -1.973826 -2.501209 -2.501201 3.079948e-06 -3.981605 3.079948e-06 -3.924474 +N = 64 -2.501202 -2.502828 -2.501194 0.000654 -1.998644 0.000654 -1.993269 -2.501202 -2.501202 1.871398e-07 -3.995374 1.871398e-07 -3.980634 +N = 128 -2.501202 -2.501608 -2.501201 0.000163 -1.999660 0.000163 -1.998305 -2.501202 -2.501202 1.160713e-08 -3.998840 1.160713e-08 -3.995524 +N = 256 -2.501202 -2.501303 -2.501202 0.000041 -1.999915 0.000041 -1.999576 -2.501202 -2.501202 3.385139e-10 -3.999523 3.385139e-10 -4.957265 +N = 512 -2.501202 -2.501227 -2.501202 0.000010 -1.999979 0.000010 -1.999894 -2.501202 -2.501202 2.176780e-08 -4.006309 2.176780e-08 -0.044305 + + +Convergence of FEM Heat with x_bar = 0.637 and k_ratio = 0.25 + True Q FEM 2 Q FEM 2 Extrap Q FEM 2 % Error FEM 2 Exact B FEM 2 Extrap % Error FEM 2 Extrap B FEM 4 Q FEM 4 Extrap Q FEM 4 % Error FEM 4 Exact B FEM 4 Extrap % Error FEM 4 Extrap B +N = 4 -2.501202 -2.964641 NaN 0.185287 NaN NaN NaN -2.525373 NaN 9.664044e-03 NaN NaN NaN +N = 8 -2.501202 -2.639437 NaN 0.055267 -1.745259 NaN NaN -2.503068 NaN 7.461252e-04 -3.695137 NaN NaN +N = 16 -2.501202 -2.539384 -2.494922 0.017821 -1.856151 0.017821 NaN -2.501327 -2.501179 5.893199e-05 -3.898067 5.893199e-05 NaN +N = 32 -2.501202 -2.511273 -2.500289 0.004393 -1.922655 0.004393 -1.831559 -2.501210 -2.501201 3.379471e-06 -3.964507 3.379471e-06 -3.893406 +N = 64 -2.501202 -2.503791 -2.501077 0.001085 -1.959773 0.001085 -1.909585 -2.501202 -2.501202 2.057958e-07 -3.986394 2.057958e-07 -3.963003 +N = 128 -2.501202 -2.501858 -2.501185 0.000269 -1.979469 0.000269 -1.953020 -2.501202 -2.501202 1.273715e-08 -3.994267 1.273715e-08 -3.989443 +N = 256 -2.501202 -2.501367 -2.501200 0.000067 -1.989627 0.000067 -1.976035 -2.501202 -2.501202 1.639429e-09 -3.997049 1.639429e-09 -3.045573 +N = 512 -2.501202 -2.501243 -2.501201 0.000017 -1.994786 0.000017 -1.987895 -2.501202 -2.501202 9.024079e-09 -4.008757 9.024079e-09 -0.114514 + + +Convergence of FDM Heat with x_bar = 0.637 and k_ratio = 0.5 + True Q FDM 2 Q FDM 2 Extrap Q FDM 2 % Error FDM 2 Exact B FDM 2 Extrap % Error FDM 2 Extrap B FDM 4 Q FDM 4 Extrap Q FDM 4 % Error FDM 4 Exact B FDM 4 Extrap % Error FDM 4 Extrap B +N = 4 -3.564213 -3.858649 NaN 0.082609 NaN NaN NaN -3.574224 NaN 2.808695e-03 NaN NaN NaN +N = 8 -3.564213 -3.639854 NaN 0.021222 -1.960716 NaN NaN -3.564905 NaN 1.940781e-04 -3.855191 NaN NaN +N = 16 -3.564213 -3.583260 -3.563514 0.005541 -1.989586 0.005541 NaN -3.564257 -3.564209 1.355828e-05 -3.961911 1.355828e-05 NaN +N = 32 -3.564213 -3.568983 -3.564167 0.001351 -1.997356 0.001351 -1.986980 -3.564216 -3.564213 8.014377e-07 -3.990351 8.014377e-07 -3.959982 +N = 64 -3.564213 -3.565406 -3.564210 0.000336 -1.999336 0.000336 -1.996695 -3.564213 -3.564213 4.932485e-08 -3.997581 4.932485e-08 -3.990263 +N = 128 -3.564213 -3.564511 -3.564213 0.000084 -1.999834 0.000084 -1.999170 -3.564213 -3.564213 2.989209e-09 -3.999323 2.989209e-09 -4.034364 +N = 256 -3.564213 -3.564287 -3.564213 0.000021 -1.999958 0.000021 -1.999792 -3.564213 -3.564213 4.437690e-09 -4.004355 4.437690e-09 -0.720881 +N = 512 -3.564213 -3.564231 -3.564213 0.000005 -1.999990 0.000005 -1.999949 -3.564213 -3.564213 1.230940e-08 -3.892410 1.230940e-08 0.021047 + + +Convergence of FEM Heat with x_bar = 0.637 and k_ratio = 0.5 + True Q FEM 2 Q FEM 2 Extrap Q FEM 2 % Error FEM 2 Exact B FEM 2 Extrap % Error FEM 2 Extrap B FEM 4 Q FEM 4 Extrap Q FEM 4 % Error FEM 4 Exact B FEM 4 Extrap % Error FEM 4 Extrap B +N = 4 -3.564213 -3.926446 NaN 0.101631 NaN NaN NaN -3.574143 NaN 2.786130e-03 NaN NaN NaN +N = 8 -3.564213 -3.669207 NaN 0.029458 -1.786611 NaN NaN -3.564914 NaN 1.966313e-04 -3.824698 NaN NaN +N = 16 -3.564213 -3.592628 -3.560167 0.009118 -1.885584 0.009118 NaN -3.564258 -3.564208 1.404724e-05 -3.940985 1.404724e-05 NaN +N = 32 -3.564213 -3.571617 -3.563673 0.002229 -1.940239 0.002229 -1.865819 -3.564216 -3.564213 8.366621e-07 -3.978534 8.366621e-07 -3.938406 +N = 64 -3.564213 -3.566104 -3.564142 0.000550 -1.969405 0.000550 -1.930100 -3.564213 -3.564213 5.159298e-08 -3.991362 5.159298e-08 -3.977450 +N = 128 -3.564213 -3.564691 -3.564204 0.000137 -1.984514 0.000137 -1.964260 -3.564213 -3.564213 3.111179e-09 -3.996222 3.111179e-09 -4.034282 +N = 256 -3.564213 -3.564333 -3.564212 0.000034 -1.992209 0.000034 -1.981922 -3.564213 -3.564213 5.160476e-09 -3.999598 5.160476e-09 -0.661124 +N = 512 -3.564213 -3.564243 -3.564213 0.000008 -1.996091 0.000008 -1.990908 -3.564213 -3.564213 4.864156e-08 -3.819867 4.864156e-08 0.005524 + + +Convergence of FDM Heat with x_bar = 0.637 and k_ratio = 1.0 + True Q FDM 2 Q FDM 2 Extrap Q FDM 2 % Error FDM 2 Exact B FDM 2 Extrap % Error FDM 2 Extrap B FDM 4 Q FDM 4 Extrap Q FDM 4 % Error FDM 4 Exact B FDM 4 Extrap % Error FDM 4 Extrap B +N = 4 -4.985127 -5.229953 NaN 0.049111 NaN NaN NaN -4.991324 NaN 1.243210e-03 NaN NaN NaN +N = 8 -4.985127 -5.047653 NaN 0.012543 -1.969225 NaN NaN -4.985553 NaN 8.562086e-05 -3.859964 NaN NaN +N = 16 -4.985127 -5.000849 -4.984681 0.003243 -1.991676 0.003243 NaN -4.985154 -4.985124 5.959042e-06 -3.962550 5.959042e-06 NaN +N = 32 -4.985127 -4.989063 -4.985096 0.000796 -1.997874 0.000796 -1.989601 -4.985128 -4.985126 3.532359e-07 -3.990470 3.532359e-07 -3.960660 +N = 64 -4.985127 -4.986111 -4.985125 0.000198 -1.999466 0.000198 -1.997343 -4.985127 -4.985127 2.177549e-08 -3.997603 2.177549e-08 -3.988623 +N = 128 -4.985127 -4.985373 -4.985126 0.000049 -1.999866 0.000049 -1.999332 -4.985127 -4.985127 1.004778e-09 -3.999222 1.004778e-09 -4.404782 +N = 256 -4.985127 -4.985188 -4.985127 0.000012 -1.999967 0.000012 -1.999833 -4.985127 -4.985127 1.382190e-08 -4.001567 1.382190e-08 0.138848 +N = 512 -4.985127 -4.985142 -4.985127 0.000003 -1.999989 0.000003 -1.999960 -4.985127 -4.985127 9.249491e-09 -3.239600 9.249491e-09 0.011826 + + +Convergence of FEM Heat with x_bar = 0.637 and k_ratio = 1.0 + True Q FEM 2 Q FEM 2 Extrap Q FEM 2 % Error FEM 2 Exact B FEM 2 Extrap % Error FEM 2 Extrap B FEM 4 Q FEM 4 Extrap Q FEM 4 % Error FEM 4 Exact B FEM 4 Extrap % Error FEM 4 Extrap B +N = 4 -4.985127 -5.290994 NaN 0.061356 NaN NaN NaN -4.989179 NaN 8.128531e-04 NaN NaN NaN +N = 8 -4.985127 -5.073389 NaN 0.017705 -1.793026 NaN NaN -4.985398 NaN 5.448497e-05 -3.899064 NaN NaN +N = 16 -4.985127 -5.008894 -4.981727 0.005453 -1.892797 0.005453 NaN -4.985144 -4.985126 3.676566e-06 -3.965409 3.676566e-06 NaN +N = 32 -4.985127 -4.991298 -4.984696 0.001324 -1.945278 0.001324 -1.873929 -4.985128 -4.985126 2.237553e-07 -3.986976 2.237553e-07 -3.963947 +N = 64 -4.985127 -4.986699 -4.985072 0.000326 -1.972350 0.000326 -1.935902 -4.985127 -4.985127 1.393229e-08 -3.994584 1.393229e-08 -3.981692 +N = 128 -4.985127 -4.985524 -4.985120 0.000081 -1.986102 0.000081 -1.967677 -4.985127 -4.985127 8.685149e-11 -3.997184 8.685149e-11 -7.228264 +N = 256 -4.985127 -4.985226 -4.985126 0.000020 -1.993033 0.000020 -1.983770 -4.985127 -4.985126 1.520828e-08 -4.005209 1.520828e-08 -0.074896 +N = 512 -4.985127 -4.985152 -4.985126 0.000005 -1.996511 0.000005 -1.991868 -4.985127 -4.985126 1.693590e-07 -5.484669 1.693590e-07 -0.000448 + + +Convergence of FDM Heat with x_bar = 0.637 and k_ratio = 2.0 + True Q FDM 2 Q FDM 2 Extrap Q FDM 2 % Error FDM 2 Exact B FDM 2 Extrap % Error FDM 2 Extrap B FDM 4 Q FDM 4 Extrap Q FDM 4 % Error FDM 4 Exact B FDM 4 Extrap % Error FDM 4 Extrap B +N = 4 -6.610807 -6.872679 NaN 0.039613 NaN NaN NaN -6.619428 NaN 1.304078e-03 NaN NaN NaN +N = 8 -6.610807 -6.678556 NaN 0.010248 -1.950595 NaN NaN -6.611422 NaN 9.300092e-05 -3.809641 NaN NaN +N = 16 -6.610807 -6.627905 -6.610024 0.002705 -1.986349 0.002705 NaN -6.610847 -6.610802 6.730247e-06 -3.949086 6.730247e-06 NaN +N = 32 -6.610807 -6.615092 -6.610753 0.000656 -1.996494 0.000656 -1.982940 -6.610809 -6.610807 3.913050e-07 -3.987045 3.913050e-07 -3.946493 +N = 64 -6.610807 -6.611879 -6.610804 0.000163 -1.999117 0.000163 -1.995618 -6.610807 -6.610807 2.399182e-08 -3.996738 2.399182e-08 -3.985134 +N = 128 -6.610807 -6.611075 -6.610807 0.000041 -1.999779 0.000041 -1.998897 -6.610807 -6.610807 1.566345e-09 -3.999742 1.566345e-09 -3.929495 +N = 256 -6.610807 -6.610874 -6.610807 0.000010 -1.999945 0.000010 -1.999724 -6.610807 -6.610807 8.518639e-09 -3.981280 8.518639e-09 -0.218471 +N = 512 -6.610807 -6.610824 -6.610807 0.000003 -1.999987 0.000003 -1.999931 -6.610807 -6.610807 7.573610e-08 -4.739885 7.573610e-08 0.001727 + + +Convergence of FEM Heat with x_bar = 0.637 and k_ratio = 2.0 + True Q FEM 2 Q FEM 2 Extrap Q FEM 2 % Error FEM 2 Exact B FEM 2 Extrap % Error FEM 2 Extrap B FEM 4 Q FEM 4 Extrap Q FEM 4 % Error FEM 4 Exact B FEM 4 Extrap % Error FEM 4 Extrap B +N = 4 -6.610807 -6.934589 NaN 0.048978 NaN NaN NaN -6.613014 NaN 3.338215e-04 NaN NaN NaN +N = 8 -6.610807 -6.705769 NaN 0.014365 -1.769597 NaN NaN -6.610952 NaN 2.191865e-05 -3.928846 NaN NaN +N = 16 -6.610807 -6.636589 -6.606609 0.004538 -1.881011 0.004538 NaN -6.610816 -6.610807 1.446114e-06 -3.977416 1.446114e-06 NaN +N = 32 -6.610807 -6.617529 -6.610280 0.001097 -1.939466 0.001097 -1.859818 -6.610808 -6.610807 8.847010e-08 -3.992259 8.847010e-08 -3.976406 +N = 64 -6.610807 -6.612523 -6.610741 0.000270 -1.969471 0.000270 -1.929031 -6.610807 -6.610807 5.449351e-09 -3.997041 5.449351e-09 -4.003670 +N = 128 -6.610807 -6.611241 -6.610799 0.000067 -1.984670 0.000067 -1.964295 -6.610807 -6.610807 1.042794e-10 -3.999791 1.042794e-10 -5.591900 +N = 256 -6.610807 -6.610916 -6.610806 0.000017 -1.992319 0.000017 -1.982094 -6.610807 -6.610807 2.507770e-09 -3.897269 2.507770e-09 -0.172920 +N = 512 -6.610807 -6.610834 -6.610807 0.000004 -1.996154 0.000004 -1.991032 -6.610807 -6.610808 1.838673e-07 -3.969016 1.838673e-07 0.000192 + + +Convergence of FDM Heat with x_bar = 0.637 and k_ratio = 4.0 + True Q FDM 2 Q FDM 2 Extrap Q FDM 2 % Error FDM 2 Exact B FDM 2 Extrap % Error FDM 2 Extrap B FDM 4 Q FDM 4 Extrap Q FDM 4 % Error FDM 4 Exact B FDM 4 Extrap % Error FDM 4 Extrap B +N = 4 -8.118713 -8.460794 NaN 0.042135 NaN NaN NaN -8.133066 NaN 1.767875e-03 NaN NaN NaN +N = 8 -8.118713 -8.208090 NaN 0.011009 -1.936363 NaN NaN -8.119747 NaN 1.273164e-04 -3.795526 NaN NaN +N = 16 -8.118713 -8.141329 -8.117358 0.002953 -1.982599 0.002953 NaN -8.118781 -8.118705 9.315394e-06 -3.945395 9.315394e-06 NaN +N = 32 -8.118713 -8.124385 -8.118622 0.000710 -1.995544 0.000710 -1.978241 -8.118718 -8.118713 5.385828e-07 -3.986111 5.385828e-07 -3.942616 +N = 64 -8.118713 -8.120132 -8.118708 0.000175 -1.998879 0.000175 -1.994429 -8.118714 -8.118713 3.291068e-08 -3.996505 3.291068e-08 -3.986725 +N = 128 -8.118713 -8.119068 -8.118713 0.000044 -1.999719 0.000044 -1.998599 -8.118713 -8.118713 1.880380e-09 -3.999265 1.880380e-09 -4.111819 +N = 256 -8.118713 -8.118802 -8.118713 0.000011 -1.999929 0.000011 -1.999650 -8.118713 -8.118713 6.711957e-09 -3.957658 6.711957e-09 -0.361555 +N = 512 -8.118713 -8.118736 -8.118713 0.000003 -1.999969 0.000003 -1.999914 -8.118713 -8.118713 3.259909e-08 -4.511233 3.259909e-08 -0.005554 + + +Convergence of FEM Heat with x_bar = 0.637 and k_ratio = 4.0 + True Q FEM 2 Q FEM 2 Extrap Q FEM 2 % Error FEM 2 Exact B FEM 2 Extrap % Error FEM 2 Extrap B FEM 4 Q FEM 4 Extrap Q FEM 4 % Error FEM 4 Exact B FEM 4 Extrap % Error FEM 4 Extrap B +N = 4 -8.118713 -8.531236 NaN 0.050811 NaN NaN NaN -8.120861 NaN 2.645577e-04 NaN NaN NaN +N = 8 -8.118713 -8.240802 NaN 0.015038 -1.756541 NaN NaN -8.118855 NaN 1.741262e-05 -3.925377 NaN NaN +N = 16 -8.118713 -8.152065 -8.113024 0.004812 -1.872107 0.004812 NaN -8.118722 -8.118713 1.152191e-06 -3.979180 1.152191e-06 NaN +N = 32 -8.118713 -8.127440 -8.117983 0.001165 -1.934202 0.001165 -1.849443 -8.118714 -8.118713 7.010843e-08 -3.994197 7.010843e-08 -3.978225 +N = 64 -8.118713 -8.120946 -8.118620 0.000287 -1.966597 0.000287 -1.922894 -8.118713 -8.118713 4.102870e-09 -3.998206 4.102870e-09 -4.072979 +N = 128 -8.118713 -8.119278 -8.118702 0.000071 -1.983167 0.000071 -1.960943 -8.118713 -8.118713 3.686867e-09 -4.000771 3.686867e-09 3.285984 +N = 256 -8.118713 -8.118855 -8.118712 0.000018 -1.991549 0.000018 -1.980339 -8.118713 -8.118713 3.290053e-08 -4.170778 3.290053e-08 -0.011173 +N = 512 -8.118713 -8.118749 -8.118713 0.000004 -1.995766 0.000004 -1.990135 -8.118713 -8.118720 8.054074e-07 -5.371643 8.054074e-07 0.000028 + + +Convergence of FDM Heat with x_bar = 0.637 and k_ratio = 8.0 + True Q FDM 2 Q FDM 2 Extrap Q FDM 2 % Error FDM 2 Exact B FDM 2 Extrap % Error FDM 2 Extrap B FDM 4 Q FDM 4 Extrap Q FDM 4 % Error FDM 4 Exact B FDM 4 Extrap % Error FDM 4 Extrap B +N = 4 -9.254592 -9.698320 NaN 0.047947 NaN NaN NaN -9.274971 NaN 2.202047e-03 NaN NaN NaN +N = 8 -9.254592 -9.370579 NaN 0.012533 -1.935704 NaN NaN -9.256061 NaN 1.587889e-04 -3.793663 NaN NaN +N = 16 -9.254592 -9.283942 -9.252810 0.003365 -1.982521 0.003365 NaN -9.254687 -9.254579 1.163493e-05 -3.944816 1.163493e-05 NaN +N = 32 -9.254592 -9.261952 -9.254472 0.000808 -1.995531 0.000808 -1.978140 -9.254598 -9.254591 6.722891e-07 -3.985957 6.722891e-07 -3.942006 +N = 64 -9.254592 -9.256433 -9.254584 0.000200 -1.998876 0.000200 -1.994413 -9.254592 -9.254592 4.113100e-08 -3.996495 4.113100e-08 -3.984620 +N = 128 -9.254592 -9.255052 -9.254591 0.000050 -1.999719 0.000050 -1.998595 -9.254592 -9.254592 2.593194e-09 -3.998491 2.593194e-09 -3.976249 +N = 256 -9.254592 -9.254707 -9.254592 0.000012 -1.999930 0.000012 -1.999649 -9.254592 -9.254592 9.260652e-10 -4.020792 9.260652e-10 -0.664331 +N = 512 -9.254592 -9.254620 -9.254592 0.000003 -1.999984 0.000003 -1.999911 -9.254592 -9.254591 7.338935e-08 -2.728397 7.338935e-08 -0.003551 + + +Convergence of FEM Heat with x_bar = 0.637 and k_ratio = 8.0 + True Q FEM 2 Q FEM 2 Extrap Q FEM 2 % Error FEM 2 Exact B FEM 2 Extrap % Error FEM 2 Extrap B FEM 4 Q FEM 4 Extrap Q FEM 4 % Error FEM 4 Exact B FEM 4 Extrap % Error FEM 4 Extrap B +N = 4 -9.254592 -9.779991 NaN 0.056772 NaN NaN NaN -9.257242 NaN 2.863730e-04 NaN NaN NaN +N = 8 -9.254592 -9.409744 NaN 0.016765 -1.759727 NaN NaN -9.254767 NaN 1.891276e-05 -3.920464 NaN NaN +N = 16 -9.254592 -9.297012 -9.247662 0.005337 -1.870848 0.005337 NaN -9.254603 -9.254591 1.256283e-06 -3.978635 1.256283e-06 NaN +N = 32 -9.254592 -9.265704 -9.253665 0.001301 -1.932621 0.001301 -1.848271 -9.254592 -9.254592 7.620138e-08 -3.994470 7.620138e-08 -3.977814 +N = 64 -9.254592 -9.257437 -9.254471 0.000321 -1.965528 0.000321 -1.921119 -9.254592 -9.254592 4.584467e-09 -3.998630 4.584467e-09 -4.034829 +N = 128 -9.254592 -9.255312 -9.254576 0.000079 -1.982557 0.000079 -1.959714 -9.254592 -9.254592 3.057780e-10 -3.990863 3.057780e-10 -3.947723 +N = 256 -9.254592 -9.254773 -9.254590 0.000020 -1.991225 0.000020 -1.979633 -9.254592 -9.254592 7.358738e-09 -4.171614 7.358738e-09 0.055911 +N = 512 -9.254592 -9.254637 -9.254591 0.000005 -1.995597 0.000005 -1.989760 -9.254592 -9.254590 2.246012e-07 -2.898591 2.246012e-07 -0.000120 + + +Convergence of FDM Heat with x_bar = 0.637 and k_ratio = 16.0 + True Q FDM 2 Q FDM 2 Extrap Q FDM 2 % Error FDM 2 Exact B FDM 2 Extrap % Error FDM 2 Extrap B FDM 4 Q FDM 4 Extrap Q FDM 4 % Error FDM 4 Exact B FDM 4 Extrap % Error FDM 4 Extrap B +N = 4 -9.980639 -10.508396 NaN 0.052878 NaN NaN NaN -10.005565 NaN 2.497488e-03 NaN NaN NaN +N = 8 -9.980639 -10.118258 NaN 0.013789 -1.939192 NaN NaN -9.982436 NaN 1.800926e-04 -3.793667 NaN NaN +N = 16 -9.980639 -10.015440 -9.978646 0.003687 -1.983481 0.003687 NaN -9.980755 -9.980624 1.319577e-05 -3.944740 1.319577e-05 NaN +N = 32 -9.980639 -9.989364 -9.980505 0.000888 -1.995777 0.000888 -1.979342 -9.980646 -9.980638 7.625708e-07 -3.985932 7.625708e-07 -3.941925 +N = 64 -9.980639 -9.982822 -9.980630 0.000220 -1.998938 0.000220 -1.994720 -9.980639 -9.980639 4.663319e-08 -3.996465 4.663319e-08 -3.985180 +N = 128 -9.980639 -9.981185 -9.980638 0.000055 -1.999734 0.000055 -1.998673 -9.980639 -9.980639 3.043996e-09 -3.997001 3.043996e-09 -3.929875 +N = 256 -9.980639 -9.980775 -9.980639 0.000014 -1.999931 0.000014 -1.999669 -9.980639 -9.980639 1.196629e-09 -4.015425 1.196629e-09 -0.345699 +N = 512 -9.980639 -9.980673 -9.980639 0.000003 -1.999988 0.000003 -1.999911 -9.980639 -9.980638 8.575384e-08 -1.042866 8.575384e-08 -0.001550 + + +Convergence of FEM Heat with x_bar = 0.637 and k_ratio = 16.0 + True Q FEM 2 Q FEM 2 Extrap Q FEM 2 % Error FEM 2 Exact B FEM 2 Extrap % Error FEM 2 Extrap B FEM 4 Q FEM 4 Extrap Q FEM 4 % Error FEM 4 Exact B FEM 4 Extrap % Error FEM 4 Extrap B +N = 4 -9.980639 -10.599453 NaN 0.062001 NaN NaN NaN -9.983783 NaN 3.150905e-04 NaN NaN NaN +N = 8 -9.980639 -10.162539 NaN 0.018225 -1.766361 NaN NaN -9.980847 NaN 2.083072e-05 -3.918981 NaN NaN +N = 16 -9.980639 -10.030332 -9.972971 0.005752 -1.872008 0.005752 NaN -9.980652 -9.980638 1.385283e-06 -3.978393 1.385283e-06 NaN +N = 32 -9.980639 -9.993657 -9.979577 0.001411 -1.932506 0.001411 -1.849908 -9.980639 -9.980639 8.398012e-08 -3.994484 8.398012e-08 -3.977219 +N = 64 -9.980639 -9.983973 -9.980498 0.000348 -1.965272 0.000348 -1.921052 -9.980639 -9.980639 5.199889e-09 -3.998709 5.199889e-09 -3.995296 +N = 128 -9.980639 -9.981482 -9.980620 0.000086 -1.982375 0.000086 -1.959430 -9.980639 -9.980639 9.369049e-10 -4.010246 9.369049e-10 -2.067819 +N = 256 -9.980639 -9.980851 -9.980636 0.000021 -1.991121 0.000021 -1.979424 -9.980639 -9.980638 2.628290e-08 -4.208162 2.628290e-08 -0.016616 +N = 512 -9.980639 -9.980692 -9.980638 0.000005 -1.995533 0.000005 -1.989640 -9.980639 -9.980633 5.895397e-07 -3.717511 5.895397e-07 -0.000039 + + diff --git a/HW5/Analytical.py b/HW5/Analytical.py new file mode 100644 index 0000000..bb7a519 --- /dev/null +++ b/HW5/Analytical.py @@ -0,0 +1,77 @@ +# analytical.py + +import numpy as np +from Bar import Bar + + +class Analytical(): + def __init__(self, bar:'Bar'): + self.bar:'Bar' = bar + + def get_disp_amp(self, freq, x_vals:np.ndarray=None): + '''Gets the analytical displacement amplitude values for a given forcing frequency. + Provides output for a given x_vals. If x_vals is not provided, returns 1000 points''' + if x_vals is None: + x_vals = np.linspace(0, 1, 1000) + + alpha = freq*(self.bar.density / self.bar.E)**0.5 + return 100 * np.sin(alpha*x_vals) / np.sin(alpha) + + def get_strain_amp(self, freq, x_vals:np.ndarray=None): + '''Gets the analytical strain amplitude values for a given forcing frequency. + Provides output for a given x_vals. If x_vals is not provided, returns 1000 points''' + if x_vals is None: + x_vals = np.linspace(0, 1, 1000) + + alpha = freq*(self.bar.density / self.bar.E)**0.5 + return 100 * alpha * np.cos(alpha*x_vals) / np.sin(alpha) + + def get_force_amp(self, freq, x_vals:np.ndarray=None): + '''Gets the analytical force amplitude values for a given forcing frequency. + Provides output for a given x_vals. If x_vals is not provided, returns 1000 points. + Units are in MN''' + return self.bar.area * self.bar.E * self.get_strain_amp(freq, x_vals) / (1e9) + + +if __name__ == "__main__": + import matplotlib.pyplot as plt + from common import freq_from_alpha + bar = Bar() + analytical = Analytical(bar) + + x_vals = np.linspace(0, 1, 1000) + + # Specific alpha values + alpha_values = np.linspace(0, 20, 6) + + freq = freq_from_alpha(bar, 4) + strain_amplitude = analytical.get_strain_amp(freq, x_vals=np.array([0.31])) + print(f"Analytical strain at x = {0.31}: {strain_amplitude}") + + # Plotting displacement amplitude + plt.figure(figsize=(12, 6)) + for alpha in [20]: + freq = freq_from_alpha(bar, alpha) + disp_amplitude = analytical.get_disp_amp(freq, x_vals) + plt.plot(x_vals, disp_amplitude, label=f'α = {alpha:.2f}') + + plt.title("Displacement Amplitude vs x for Various α Values") + plt.xlabel("x (Normalized Position)") + plt.ylabel("Displacement Amplitude") + plt.legend() + plt.grid(True) + plt.show() + + # # Plotting strain amplitude + # plt.figure(figsize=(12, 6)) + # for alpha in alpha_values: + # freq = freq_from_alpha(bar, alpha) + # strain_amplitude = analytical.strain_amp(freq, x_vals) + # plt.plot(x_vals, strain_amplitude, label=f'α = {alpha:.2f}') + + # plt.title("Strain Amplitude vs x for Various α Values") + # plt.xlabel("x (Normalized Position)") + # plt.ylabel("Strain Amplitude") + # plt.legend() + # plt.grid(True) + # plt.show() \ No newline at end of file diff --git a/HW5/Bar.py b/HW5/Bar.py new file mode 100644 index 0000000..114703e --- /dev/null +++ b/HW5/Bar.py @@ -0,0 +1,18 @@ +# Bar.py + +from numpy import pi + +class Bar(): + def __init__(self, radius:float=0.1, k:float=0.5, h:float=0.0025, E:float=7e9, density:float=2710): + self.radius:float = radius + self.k:float = k + self.h:float = h + self.E:float = E + self.density:float = density + + self.update_properties() + + def update_properties(self): + self.area:float = pi*self.radius**2 + self.p: float = 2*pi*self.radius + self.alpha = ((self.h*self.p)/(self.k*self.area))**0.5 diff --git a/HW5/Convergence.py b/HW5/Convergence.py new file mode 100644 index 0000000..881524c --- /dev/null +++ b/HW5/Convergence.py @@ -0,0 +1,223 @@ +# convergence.py + +import numpy as np +import matplotlib.pyplot as plt + +from DiscreteMethod import DiscreteMethod + +class Convergence: + def __init__(self, analytical, fdm, fem): + """ + Initialize the Convergence class. + + Parameters: + - analytical: + - fdm: Instance of the FDM class. + - fem: Instance of the FEM class. + """ + self.analytical = analytical + self.fdm: 'DiscreteMethod' = fdm + self.fem: 'DiscreteMethod' = fem + + def calc_error(self, exact, q_1): + """Calculate relative error.""" + return np.abs((exact - q_1) / exact) + + def calc_beta(self, exact, q_1, q_2, dx_1, dx_2): + """Calculate convergence rate beta.""" + return np.log(np.abs((exact - q_1) / (exact - q_2))) / np.log(dx_1 / dx_2) + + def calc_extrapolated(self, q1, q2, q3, tolerance=1e-10): + """Calculate Richardson extrapolation, returns NaN if denominator is too small.""" + numerator = q1 * q3 - q2**2 + denominator = q1 + q3 - 2 * q2 + if abs(denominator) < tolerance: + return float('NaN') # Return NaN if denominator is close to zero + return numerator / denominator + + def run_convergence(self, forcing_freq: float, num_sections_range, metric_func): + """ + Run convergence analysis for FDM and FEM. + + Parameters: + - forcing_freq: The forcing frequency to test. + - num_sections_range: Array of num_sections to test. + - metric_func: Callable defining the metric to analyze (e.g., U'(L) or U(1 / (2pi))). + + Returns: + - results: Dictionary containing errors, betas, extrapolated values, and analytical values for both methods. + """ + results = { + "fdm": { + "num_sections": [], + "errors": [], + "betas": [], + "extrapolated_errors": [], + "extrapolated_values": [], + "analytical_values": [], + }, + "fem": { + "num_sections": [], + "errors": [], + "betas": [], + "extrapolated_errors": [], + "extrapolated_values": [], + "analytical_values": [], + }, + } + + # Analytical value for the metric + analytical_value = metric_func(self.analytical, forcing_freq) + + for num_sections in num_sections_range: + dx = 1 / num_sections + + # Run FDM + self.fdm.run(forcing_freq, num_sections) + fdm_metric = metric_func(self.fdm) + fdm_error = self.calc_error(analytical_value, fdm_metric) + + # Run FEM + self.fem.run(forcing_freq, num_sections) + fem_metric = metric_func(self.fem) + fem_error = self.calc_error(analytical_value, fem_metric) + + # Store results + results["fdm"]["num_sections"].append(num_sections) + results["fdm"]["errors"].append(fdm_error) + results["fdm"]["extrapolated_values"].append(fdm_metric) + results["fdm"]["analytical_values"].append(analytical_value) + + results["fem"]["num_sections"].append(num_sections) + results["fem"]["errors"].append(fem_error) + results["fem"]["extrapolated_values"].append(fem_metric) + results["fem"]["analytical_values"].append(analytical_value) + + # Compute extrapolated errors and betas + for method in ["fdm", "fem"]: + extrapolated_errors = [np.nan] # Padding for the first run + betas = [np.nan] # Padding for the first run + extrapolated_betas = [np.nan] # Padding for the first run + + values = results[method]["extrapolated_values"] + num_sections = results[method]["num_sections"] + + # Extrapolation and beta calculations + for i in range(len(num_sections) - 1): + q1 = values[i] + q2 = values[i + 1] + dx1 = 1 / num_sections[i] + dx2 = 1 / num_sections[i + 1] + + beta = self.calc_beta(analytical_value, q1, q2, dx1, dx2) + + if i >= 1: + extrapolated_value = self.calc_extrapolated( + values[i - 1], q1, q2 + ) # Requires 3 consecutive values for extrapolation + extrapolated_error = self.calc_error(extrapolated_value, q2) + extrapolated_beta = self.calc_beta(extrapolated_value, q1, q2, dx1, dx2) + else: + extrapolated_value = np.nan + extrapolated_error = np.nan + extrapolated_beta = np.nan + + if i >= 1: + extrapolated_errors.append(extrapolated_error) + extrapolated_betas.append(extrapolated_beta) + else: + extrapolated_errors.append(np.nan) + extrapolated_betas.append(np.nan) + + betas.append(beta) + + results[method]["extrapolated_errors"] = extrapolated_errors + results[method]["betas"] = betas + results[method]["extrapolated_betas"] = extrapolated_betas + + return results + + + + def plot_convergence(self, results): + """ + Plot convergence results for FDM and FEM, including errors relative to analytical + and extrapolated values. + + Parameters: + - results: Dictionary from run_convergence. + """ + plt.figure(figsize=(12, 6)) + + for method in ["fdm", "fem"]: + num_sections = results[method]["num_sections"] + errors = results[method]["errors"] + extrapolated_errors = results[method]["extrapolated_errors"] + + # Pad num_sections to match extrapolated_errors length + padded_num_sections = [np.nan] * 2 + num_sections[:-2] + + # Plot true error relative to the analytical solution + plt.loglog( + num_sections, errors, '-o', label=f"{method.upper()} Analytical Error" + ) + + # Plot error relative to the extrapolated solution + plt.loglog( + num_sections, extrapolated_errors, '--s', label=f"{method.upper()} Extrapolated Error" + ) + + plt.xlabel("Number of Sections") + plt.ylabel("Error (Relative)") + plt.title("Convergence Analysis: True and Extrapolated Errors") + plt.legend() + plt.grid(True, which="both", linestyle="--") + plt.show() + + +if __name__ == "__main__": + from Analytical import Analytical + from Bar import Bar + from common import freq_from_alpha + from DiscreteMethod import DiscreteMethod + from FDM import FDM + from FEM import FEM + + def metric_u_prime_l(method:'DiscreteMethod', forcing_freq:float = None): + """Extract U'(L) from the method.""" + if forcing_freq is None: # Finite method + return method.get_strain_amp(1.0) + else: + return method.get_strain_amp(forcing_freq, 1.0) # Analytical + + def metric_u_half_pi(method:'DiscreteMethod', forcing_freq:float = None): + """Extract U(1 / (2pi)) from the method.""" + x_half_pi = 1 / (2 * np.pi) + if forcing_freq is None: # Finite method + return method.get_disp_amp(x_half_pi) + else: + return method.get_disp_amp(forcing_freq, x_half_pi) # Analytical + + # Initialize Bar, FDM, FEM + bar = Bar() + analy = Analytical(bar) + fdm = FDM(bar, desired_order="2") + fem = FEM(bar, desired_order="2") + + # Set boundary conditions + fdm.set_boundary_conditions(U_0=0, U_L=100) + fem.set_boundary_conditions(U_0=0, U_L=100) + + # Initialize Convergence + convergence = Convergence(analy, fdm, fem) + + alpha = 0.25 + forcing_freq = freq_from_alpha(bar, alpha) + + # Run convergence for U'(L) + num_sections_range = [2**n for n in range(1, 12)] + + results = convergence.run_convergence(forcing_freq, num_sections_range, metric_u_half_pi) + + # Plot results + convergence.plot_convergence(results) diff --git a/HW5/Derivation.pdf b/HW5/Derivation.pdf new file mode 100644 index 0000000..a3db696 Binary files /dev/null and b/HW5/Derivation.pdf differ diff --git a/HW5/DiscreteMethod.py b/HW5/DiscreteMethod.py new file mode 100644 index 0000000..b2df6f3 --- /dev/null +++ b/HW5/DiscreteMethod.py @@ -0,0 +1,158 @@ +# DiscreteMethod.py + +import numpy as np + +from Bar import Bar + +class DiscreteMethod(): + '''Provides the class for solving via FDM or FEM. + The bar is provided at initiation, as well as the desired order. + The user can change the forcing frequency and num_sections as desired''' + def __init__(self, bar: 'Bar', desired_order:str="2"): + self.bar: 'Bar' = bar + self.desired_order:str = desired_order + + # Finite method solving + self.num_sections: int = None + self.dx: float = None + self.alpha: float = None + self.stiffness_matrix: np.ndarray = None + self.constant_vector: np.ndarray = None + + # Result vectors + self.x_vals: np.ndarray = None + self.forcing_freq: float = None + self.disp_amp: np.ndarray = None + self.strain_amp: np.ndarray = None + + def set_boundary_conditions(self, U_0:float=0, U_L:float=100): + '''Set the left and right amplitude boundary conditions''' + self.U_0 = U_0 + self.U_L = U_L + + def nodal_strain(self, node_idx: int): + '''Calculates the strain (U') at a given node using the 4th-order scheme.''' + dx = self.dx + alpha = self.alpha + if node_idx == 0: # Left boundary + # Use forward difference at the boundary + return ( + (1 - dx**2 * alpha**2 / 2 + dx**4 * alpha**4 / 24) / (-dx + (dx**3*alpha**2/6)) * self.disp_amp[node_idx] + - (1 / (-dx + dx**3 * alpha**2 / 6)) * self.disp_amp[node_idx + 1] + ) + elif node_idx == len(self.disp_amp) - 1: # Right boundary, use backward difference + return ( + (1 - dx**2 * alpha**2 / 2 + dx**4 * alpha**4 / 24) / (dx - (dx**3*alpha**2/6)) * self.disp_amp[node_idx] + - (1 / (dx - (dx**3*alpha**2/6))) * self.disp_amp[node_idx - 1] + ) + else: # Return the average of the backward and forward derivative + return ( + ((1 - dx**2 * alpha**2 / 2 + dx**4 * alpha**4 / 24) / (dx - (dx**3*alpha**2/6)) * self.disp_amp[node_idx] + - (1 / (dx - (dx**3*alpha**2/6))) * self.disp_amp[node_idx - 1] + + + (1 - dx**2 * alpha**2 / 2 + dx**4 * alpha**4 / 24) / (-dx + (dx**3*alpha**2/6)) * self.disp_amp[node_idx] + - (1 / (-dx + dx**3 * alpha**2 / 6)) * self.disp_amp[node_idx + 1]) + / 2.0 + ) + + def calc_all_nodal_strain(self): + '''Calculates all of the nodal strains after running the method''' + nodal_strains = np.array([]) + for i in range(self.num_sections+1): + nodal_strains = np.append(nodal_strains, self.nodal_strain(i)) + self.strain_amp = nodal_strains + + def get_interpolated_disp_amp(self, x_val: float): + """Returns the interpolated displacement amplitude for a given x_val.""" + # Find the closest node to x_val + idx = np.argmin(np.abs(self.x_vals - x_val)) # Closest node index + alpha = self.alpha + + # Calculate h (distance from the nearest node) + h = x_val - self.x_vals[idx] + + U_i = self.disp_amp[idx] + + if h == 0: + return U_i + + # Calculate U' at the closest node + U_prime = self.strain_amp[idx] + + # Apply the fourth-order Taylor series + + interpolated_value = ( + (1 - h**2 * alpha**2 / 2 + h**4 * alpha**4 / 24) * U_i + + (h - h**3 * alpha**2 / 6) * U_prime + ) + + return interpolated_value + + def get_interpolated_strain_amp(self, x_val: float): + '''Returns the interpolated strain (U') amplitude for a given x_val.''' + # Find the closest node to x_val + idx = np.argmin(np.abs(self.x_vals - x_val)) # Closest node index + dx = 1 / (len(self.x_vals) - 1) # Spacing between nodes + alpha = self.forcing_freq * (self.bar.density / self.bar.E)**0.5 + + # Calculate h (distance from the nearest node) + h = x_val - self.x_vals[idx] + + # Get U at the closest node + U_at_node = self.disp_amp[idx] + + # Calculate U' at the closest node + U_prime_at_node = self.strain_amp[idx] + + if h == 0: + return U_prime_at_node + + # Apply the fourth-order Taylor series + # Taylor series expansion for strain + U_prime_interpolated = ( + (-h*alpha**2 + h**3 * alpha**4 / 6) * U_at_node + + (1 - h**2 * alpha**2 / 2 + h**4 * alpha**4 / 24) * U_prime_at_node + ) + + return U_prime_interpolated + + def build_stiffness_matrix(self): + pass + + def build_constant_vector(self): + pass + + def run(self, forcing_freq:float, num_sections:int=4): + '''Runs the method for the given forcing frequency and num_sections. + Stores displacment ampltitude data in self.disp_amp + Stores strain amplitude data in self.strain_amp''' + # Save the appropriate values + self.num_sections = num_sections + self.dx = 1 / num_sections + self.alpha = forcing_freq*(self.bar.density / self.bar.E)**0.5 + self.forcing_freq = forcing_freq + + self.build_stiffness_matrix() + self.build_constant_vector() + + # Solve the system + self.disp_amp = np.linalg.solve(self.stiffness_matrix, self.constant_vector) + + # Calculate all of the nodal strains + self.calc_all_nodal_strain() + + # Save the x values for the nodal values + self.x_vals = np.linspace(0, 1, num_sections+1) # sections + endpoints + + def get_disp_amp(self, x): + '''Returns the displacement amplitude at x''' + return self.get_interpolated_disp_amp(x) + + def get_strain_amp(self, x): + '''Returns the strain amplitude at x''' + return self.get_interpolated_strain_amp(x) + + def get_force_amp(self, x): + '''Returns the force amplitude at x. + Units are in MN''' + return self.bar.area * self.bar.E* self.get_interpolated_strain_amp(x) / (1e9) \ No newline at end of file diff --git a/HW5/FDM.py b/HW5/FDM.py new file mode 100644 index 0000000..b5640d4 --- /dev/null +++ b/HW5/FDM.py @@ -0,0 +1,113 @@ +# FDM.py + +import numpy as np + +from Bar import Bar +from DiscreteMethod import DiscreteMethod + +class FDM(DiscreteMethod): + def __init__(self, bar:'Bar', desired_order="2"): + super().__init__(bar, desired_order) + + def get_kappa(self): + '''Returns the 2nd or 4th order kappa value''' + dx = self.dx + alpha = self.alpha + + kappa = 2 - alpha**2 * dx**2 + + if self.desired_order == "4": # Add the 4th order term + kappa += alpha**4 * dx**4 / 12 + + return kappa + + def build_stiffness_matrix(self): + '''Given a number of sections, build the stiffness_matrix''' + # The stiffness matrix follows the form [1, -kappa, 1] in a diagonal + kappa = self.get_kappa() + + size = self.num_sections + 1 # Include boundary points + self.stiffness_matrix = np.zeros((size, size)) + + for i in range(1, size - 1): # Internal points + self.stiffness_matrix[i, i - 1] = 1 # Left neighbor + self.stiffness_matrix[i, i] = -kappa # Center + self.stiffness_matrix[i, i + 1] = 1 # Right neighbor + + # Enforce boundary conditions in the stiffness matrix + self.stiffness_matrix[0, 0] = 1 # Left boundary + self.stiffness_matrix[-1, -1] = 1 # Right boundary + + def build_constant_vector(self): + '''Given a number of sections, build the constant_vector where the + first and last elements come from boundary conditions''' + self.constant_vector = np.zeros(self.num_sections + 1) # Include endpoints + self.constant_vector[0] = self.U_0 # Left boundary + self.constant_vector[-1] = self.U_L # Right boundary + + def run(self, forcing_freq:float, num_sections:int=4): + '''Runs FDM for the given forcing frequency and num_sections. + Stores displacment ampltitude data in self.disp_amp + Stores strain amplitude data in self.strain_amp''' + # Save the appropriate values + self.num_sections = num_sections + self.dx = 1 / num_sections + self.alpha = forcing_freq*(self.bar.density / self.bar.E)**0.5 + self.forcing_freq = forcing_freq + + self.build_stiffness_matrix() + self.build_constant_vector() + + # Solve the system + self.disp_amp = np.linalg.solve(self.stiffness_matrix, self.constant_vector) + + # Calculate all of the nodal strains + self.calc_all_nodal_strain() + + # Save the x values for the nodal values + self.x_vals = np.linspace(0, 1, num_sections+1) # sections + endpoints + + +if __name__ == "__main__": + import matplotlib.pyplot as plt + from common import freq_from_alpha + bar = Bar() + + # Initialize FDM + fdm_2 = FDM(bar, desired_order="2") + + # Define alpha values for testing + alpha_values = np.linspace(0, 20, 6) + + # Set boundary conditions + fdm_2.set_boundary_conditions(U_0=0, U_L=100) + + # Plot displacement amplitudes for varying alpha values + plt.figure(figsize=(12, 6)) + for alpha in [100]: + forcing_freq = freq_from_alpha(bar, alpha) + fdm_2.run(forcing_freq, num_sections=4) + plt.plot(fdm_2.x_vals, fdm_2.disp_amp, label=f'α = {alpha:.2f}') + + plt.title("FDM Displacement Amplitude vs x for Various α Values") + plt.xlabel("x (Normalized Position)") + plt.ylabel("Displacement Amplitude") + plt.legend() + plt.grid(True) + plt.show() + + # Set boundary conditions and run the solver + fdm_4 = FDM(bar, desired_order="4") + fdm_4.set_boundary_conditions(U_0=0, U_L=100) + freq = freq_from_alpha(bar, 4) + num_sections = 10 + fdm_4.run(freq, num_sections) + fdm_2.run(freq, num_sections) + + # Interpolate at a specific x_val + x_val = 0.31 + interpolated_strain = fdm_4.get_interpolated_strain_amp(x_val) + print(f"Interpolated Strain Amplitude at x = {x_val}: {interpolated_strain}") + + interpolated_strain = fdm_2.get_interpolated_strain_amp(x_val) + print(f"Interpolated Strain Amplitude at x = {x_val}: {interpolated_strain}") \ No newline at end of file diff --git a/HW5/FEM.py b/HW5/FEM.py new file mode 100644 index 0000000..aedbc8d --- /dev/null +++ b/HW5/FEM.py @@ -0,0 +1,187 @@ +# FEM.py + +import numpy as np + +from Bar import Bar +from DiscreteMethod import DiscreteMethod + +class FEM(DiscreteMethod): + def __init__(self, bar:'Bar', desired_order="2"): + super().__init__(bar, desired_order) + + def get_kappa(self, row:int, col:int): + dx = self.dx + alpha = self.alpha + + if (row == 1 and col == 1) or (row == 2 and col == 2): + return -1/dx + alpha**2*dx/ 3.0 + elif row == 3 and col == 3: + return -1/(3*dx) + alpha**2*dx/30.0 + elif (row == 1 and col == 2) or (row == 2 and col == 1): + return 1/dx + alpha**2*dx/6.0 + elif (row == 1 and col == 3) or (row == 3 and col == 1) or (row == 2 and col == 3) or (row == 3 and col == 2): + return alpha**2*dx/12.0 + + def get_all_kappa(self): + '''Returns the kappa matrix for p=1 or p=2 FEM. + Note that both matrices are equivalent regardless of p=1 or p=2, but p=1 does not use row 3 or col 3''' + + K = np.zeros((3, 3)) + for row in range(3): + for col in range(3): + K[row, col] = self.get_kappa(row+1, col+1) + return K + + + def build_stiffness_matrix(self): + '''Given a number of sections, build the stiffness_matrix for P=1 FEM''' + num_sections = self.num_sections + if self.desired_order == "2": # p=1 + size = num_sections + 1 # Number of nodes for P=1 + self.stiffness_matrix = np.zeros((size, size)) + + # Get local stiffness matrix (K) for a single section + K_local = self.get_all_kappa() + + # Extract local stiffness terms for P=1 + k11 = K_local[0, 0] + k12 = K_local[0, 1] + k21 = K_local[1, 0] + k22 = K_local[1, 1] + + # Loop through each section and assemble the global stiffness matrix + for section in range(num_sections): + self.stiffness_matrix[section, section - 1] = k21 + self.stiffness_matrix[section, section] = k22 + k11 + self.stiffness_matrix[section, section + 1] = k12 + + # Enforce boundary conditions by fixing the first and last nodes + self.stiffness_matrix[0, :] = 0 # Set first row to zero + self.stiffness_matrix[0, 0] = 1 # Fix the left boundary + + self.stiffness_matrix[-1, :] = 0 # Set last row to zero + self.stiffness_matrix[-1, -1] = 1 # Fix the right boundary + + elif self.desired_order == "4": # p=2 + size = 2 * num_sections + 1 # Number of linear + quadratic nodes + self.stiffness_matrix = np.zeros((size, size)) + + # Get local stiffness matrix (K) for a single section + K_local = self.get_all_kappa() + + # Extract local stiffness terms for P=2 + k11 = K_local[0, 0] + k12 = K_local[0, 1] + k13 = K_local[0, 2] + k21 = K_local[1, 0] + k22 = K_local[1, 1] + k23 = K_local[1, 2] + k31 = K_local[2, 0] + k32 = K_local[2, 1] + k33 = K_local[2, 2] + + # Loop through each section and assemble the global stiffness matrix for similar to p=1 + for section in range(num_sections): + # Assemble contributions from K_local + self.stiffness_matrix[section, section - 1] = k21 + self.stiffness_matrix[section, section] = k22 + k11 + self.stiffness_matrix[section, section + 1] = k12 + + # Add the k23 and k13 terms in that correspond to Ei and Ei+1 + self.stiffness_matrix[section, num_sections+section] = k23 + self.stiffness_matrix[section, num_sections+section+1] = k13 + + + # Add the quadratic element relations + for section in range(num_sections): + # Assemble contributions from K_local + self.stiffness_matrix[num_sections+section+1, section] = k31 + self.stiffness_matrix[num_sections+section+1, section+1] = k32 + self.stiffness_matrix[num_sections+section+1, num_sections+section+1] = k33 + + # Enforce boundary conditions by fixing the first and last nodes + self.stiffness_matrix[0, :] = 0 # Set first row to zero + self.stiffness_matrix[0, 0] = 1 # Fix the left boundary + + self.stiffness_matrix[num_sections, :] = 0 # Set last temperature row to 0 + self.stiffness_matrix[num_sections, num_sections] = 1 # Fix the right boundary + + def build_constant_vector(self): + '''Given a number of sections, build the constant_vector where the + first and last elements come from boundary conditions''' + num_sections = self.num_sections + if self.desired_order == "2": # p=1 + self.constant_vector = np.zeros(num_sections + 1) # Include endpoints + self.constant_vector[0] = self.U_0 # Left boundary + self.constant_vector[-1] = self.U_L # Right boundary + if self.desired_order == "4": # p=2 + self.constant_vector = np.zeros(2*num_sections + 1) # Include endpoints + self.constant_vector[0] = self.U_0 # Left boundary + self.constant_vector[num_sections] = self.U_L # Right boundary + + def run(self, forcing_freq:float, num_sections:int=4): + '''Runs FDM for the given forcing frequency and num_sections. + Stores displacment ampltitude data in self.disp_amp + Stores strain amplitude data in self.strain_amp''' + # Save the appropriate values + self.num_sections = num_sections + self.dx = 1 / num_sections + self.alpha = forcing_freq*(self.bar.density / self.bar.E)**0.5 + self.forcing_freq = forcing_freq + + self.build_stiffness_matrix() + self.build_constant_vector() + + # Solve the system + if self.desired_order == "2": # p=1 + self.disp_amp = np.linalg.solve(self.stiffness_matrix, self.constant_vector) + elif self.desired_order == "4": # p=3 + self.disp_amp = np.linalg.solve(self.stiffness_matrix, self.constant_vector) + self.disp_amp = self.disp_amp[0:self.num_sections+1] + + # Calculate all of the nodal strains + self.calc_all_nodal_strain() + + # Save the x values for the nodal values + self.x_vals = np.linspace(0, 1, self.num_sections+1) # sections + endpoints + + + +if __name__ == "__main__": + import matplotlib.pyplot as plt + from common import freq_from_alpha + bar = Bar() + + # Initialize FDM + fem = FEM(bar, desired_order="4") + + # Define alpha values for testing + alpha_values = np.linspace(0, 20, 6) + + # Set boundary conditions + fem.set_boundary_conditions(U_0=0, U_L=100) + + # Plot displacement amplitudes for varying alpha values + plt.figure(figsize=(12, 6)) + for alpha in [20]: + forcing_freq = freq_from_alpha(bar, alpha) + fem.run(forcing_freq, num_sections=100) + plt.plot(fem.x_vals, fem.disp_amp, label=f'α = {alpha:.2f}') + + plt.title("FEM Displacement Amplitude vs x for Various α Values") + plt.xlabel("x (Normalized Position)") + plt.ylabel("Displacement Amplitude") + plt.legend() + plt.grid(True) + plt.show() + + # Set boundary conditions and run the solver + fem.set_boundary_conditions(U_0=0, U_L=100) + freq = freq_from_alpha(bar, 4) + num_sections = 100 + fem.run(freq, num_sections) + + # Interpolate at a specific x_val + x_val = 0.31 + interpolated_strain = fem.get_interpolated_strain_amp(x_val) + print(f"Interpolated Strain Amplitude at x = {x_val}: {interpolated_strain}") \ No newline at end of file diff --git a/HW5/Images/1_Displacement_vs_Position.png b/HW5/Images/1_Displacement_vs_Position.png new file mode 100644 index 0000000..fc6c970 Binary files /dev/null and b/HW5/Images/1_Displacement_vs_Position.png differ diff --git a/HW5/Images/1_Strain_Frequency_Sweep.png b/HW5/Images/1_Strain_Frequency_Sweep.png new file mode 100644 index 0000000..2ed9b12 Binary files /dev/null and b/HW5/Images/1_Strain_Frequency_Sweep.png differ diff --git a/HW5/Images/1_Strain_vs_Position.png b/HW5/Images/1_Strain_vs_Position.png new file mode 100644 index 0000000..ad7f6c1 Binary files /dev/null and b/HW5/Images/1_Strain_vs_Position.png differ diff --git a/HW5/Images/2_Fourth_Order_Convergence.png b/HW5/Images/2_Fourth_Order_Convergence.png new file mode 100644 index 0000000..7f3665d Binary files /dev/null and b/HW5/Images/2_Fourth_Order_Convergence.png differ diff --git a/HW5/Images/2_Second_Order_Convergence.png b/HW5/Images/2_Second_Order_Convergence.png new file mode 100644 index 0000000..1e621f2 Binary files /dev/null and b/HW5/Images/2_Second_Order_Convergence.png differ diff --git a/HW5/Images/3_Frequency_Sweep_FDM2_FEM1.png b/HW5/Images/3_Frequency_Sweep_FDM2_FEM1.png new file mode 100644 index 0000000..b734353 Binary files /dev/null and b/HW5/Images/3_Frequency_Sweep_FDM2_FEM1.png differ diff --git a/HW5/Images/3_Frequency_Sweep_FDM4_FEM2.png b/HW5/Images/3_Frequency_Sweep_FDM4_FEM2.png new file mode 100644 index 0000000..eb66344 Binary files /dev/null and b/HW5/Images/3_Frequency_Sweep_FDM4_FEM2.png differ diff --git a/HW5/Judson_Upchurch_HW5_6.pdf b/HW5/Judson_Upchurch_HW5_6.pdf new file mode 100644 index 0000000..219a8fc Binary files /dev/null and b/HW5/Judson_Upchurch_HW5_6.pdf differ diff --git a/HW5/__pycache__/Analytical.cpython-312.pyc b/HW5/__pycache__/Analytical.cpython-312.pyc new file mode 100644 index 0000000..3a3f692 Binary files /dev/null and b/HW5/__pycache__/Analytical.cpython-312.pyc differ diff --git a/HW5/__pycache__/Bar.cpython-312.pyc b/HW5/__pycache__/Bar.cpython-312.pyc new file mode 100644 index 0000000..561ae5c Binary files /dev/null and b/HW5/__pycache__/Bar.cpython-312.pyc differ diff --git a/HW5/__pycache__/Convergence.cpython-312.pyc b/HW5/__pycache__/Convergence.cpython-312.pyc new file mode 100644 index 0000000..a3ae6e5 Binary files /dev/null and b/HW5/__pycache__/Convergence.cpython-312.pyc differ diff --git a/HW5/__pycache__/DiscreteMethod.cpython-312.pyc b/HW5/__pycache__/DiscreteMethod.cpython-312.pyc new file mode 100644 index 0000000..f2db8e9 Binary files /dev/null and b/HW5/__pycache__/DiscreteMethod.cpython-312.pyc differ diff --git a/HW5/__pycache__/FDM.cpython-312.pyc b/HW5/__pycache__/FDM.cpython-312.pyc new file mode 100644 index 0000000..56dab46 Binary files /dev/null and b/HW5/__pycache__/FDM.cpython-312.pyc differ diff --git a/HW5/__pycache__/FEM.cpython-312.pyc b/HW5/__pycache__/FEM.cpython-312.pyc new file mode 100644 index 0000000..0b11f62 Binary files /dev/null and b/HW5/__pycache__/FEM.cpython-312.pyc differ diff --git a/HW5/__pycache__/common.cpython-312.pyc b/HW5/__pycache__/common.cpython-312.pyc new file mode 100644 index 0000000..5987491 Binary files /dev/null and b/HW5/__pycache__/common.cpython-312.pyc differ diff --git a/HW5/common.py b/HW5/common.py new file mode 100644 index 0000000..407bb8e --- /dev/null +++ b/HW5/common.py @@ -0,0 +1,6 @@ +# common.py +from Bar import Bar + +def freq_from_alpha(bar:'Bar', desired_alpha): + '''Returns the forcing frequency that corresponds to the desired alpha''' + return desired_alpha * (bar.E / bar.density)**0.5 \ No newline at end of file diff --git a/HW5/main.py b/HW5/main.py new file mode 100644 index 0000000..0af1ca7 --- /dev/null +++ b/HW5/main.py @@ -0,0 +1,396 @@ +# main.py + +import numpy as np +import matplotlib.pyplot as plt + +from Bar import Bar +from Analytical import Analytical +from DiscreteMethod import DiscreteMethod +from FDM import FDM +from FEM import FEM +from Convergence import Convergence +from common import freq_from_alpha + +bar = Bar() +alpha_values = np.array([0.25, 0.5, 1.0, 2.0, 4.0, 10.0, 20.0]) +alpha_sweep_values = np.linspace(0.1, 50, 1000) + +def analytical(): + analytical = Analytical(bar) + + x_vals = np.linspace(0, 1, 1000) + x_vals_table = np.array([0.0, 0.125, 1/(2*np.pi), 0.25, 0.375, 0.5, 0.625, 0.75, 0.875, 1.0]) + displacement_data = [] + strain_data = [] + + # Plotting displacement amplitude + plt.figure(figsize=(12, 6)) + for alpha in alpha_values: + freq = freq_from_alpha(bar, alpha) + disp_amplitude = analytical.get_disp_amp(freq, x_vals) + displacement_data.append(analytical.get_disp_amp(freq, x_vals_table)) + plt.plot(x_vals, disp_amplitude, label=f'α = {alpha:.2f}') + + plt.title("Analytical Displacement Amplitude") + plt.xlabel("x") + plt.ylabel("Displacement Amplitude") + plt.legend() + plt.grid(True) + plt.savefig("Images/1_Displacement_vs_Position.png") + plt.close() + + # Plotting strain amplitude + plt.figure(figsize=(12, 6)) + for alpha in alpha_values: + freq = freq_from_alpha(bar, alpha) + strain_amplitude = analytical.get_strain_amp(freq, x_vals) + strain_data.append(analytical.get_strain_amp(freq, x_vals_table)) + plt.plot(x_vals, strain_amplitude, label=f'α = {alpha:.2f}') + + plt.title("Analytical Strain Amplitude") + plt.xlabel("x") + plt.ylabel("Strain Amplitude") + plt.legend() + plt.grid(True) + plt.savefig("Images/1_Strain_vs_Position.png") + plt.close() + + # Display Displacement Table + print("\nAnalytical Results") + print("Analytical Displacement") + header = ["x"] + [f"α = {alpha:.2f}" for alpha in alpha_values] + print("{:<10}".format(header[0]) + "".join(f"{val:<15}" for val in header[1:])) + print("-" * (10 + 15 * len(alpha_values))) + + for i, x in enumerate(x_vals_table): + row = [f"{x:.3f}"] + [f"{disp[i]:.4f}" for disp in displacement_data] + print("{:<10}".format(row[0]) + "".join(f"{val:<15}" for val in row[1:])) + + # Display Strain Table + print("\nAnalytical Strain") + print("{:<10}".format(header[0]) + "".join(f"{val:<15}" for val in header[1:])) + print("-" * (10 + 15 * len(alpha_values))) + + for i, x in enumerate(x_vals_table): + row = [f"{x:.3f}"] + [f"{strain[i]:.4f}" for strain in strain_data] + print("{:<10}".format(row[0]) + "".join(f"{val:<15}" for val in row[1:])) + + # Frequency sweep of strain at x = 1 + plt.figure(figsize=(12, 6)) + disp_amplitudes = np.array([]) + for alpha in alpha_sweep_values: + freq = freq_from_alpha(bar, alpha) + disp_amplitude = analytical.get_disp_amp(freq, x_vals=np.array([1/(2*np.pi)])) + disp_amplitudes = np.append(disp_amplitudes, disp_amplitude) + + plt.plot(alpha_sweep_values, disp_amplitudes) + plt.ylim((-10000, 10000)) + plt.title("Analytical Frequency Sweep for Displacement at x = 1/(2pi)") + plt.xlabel("α") + plt.ylabel("Displacement Amplitude") + plt.legend() + plt.grid(True) + #plt.show() + plt.savefig("Images/1_Strain_Frequency_Sweep.png") + plt.close() + + +def convergence(): + def convergence_metric(method: 'DiscreteMethod', forcing_freq: float = None): + """Extract U(1/(2pi)) from the method.""" + x = 1 / (2 * np.pi) + if forcing_freq is None: # Finite method + return method.get_disp_amp(x) + else: + return method.get_disp_amp(forcing_freq, x) # Analytical + + print("\nConvergence Results") + print("\n2nd Order FDM and P=1 FEM Convergence of U(x=1/(2pi))") + + # Initialize Bar, FDM, FEM + bar = Bar() + analy = Analytical(bar) + fdm = FDM(bar, desired_order="2") + fem = FEM(bar, desired_order="2") + + # Set boundary conditions + fdm.set_boundary_conditions(U_0=0, U_L=100) + fem.set_boundary_conditions(U_0=0, U_L=100) + + # Initialize Convergence + convergence = Convergence(analy, fdm, fem) + + num_sections_range = [2**n for n in range(1, 12)] + alpha_values = [0.25, 0.5, 1.0, 2.0, 4.0] + + # Create a figure with 2 columns of subplots + fig, axs = plt.subplots((len(alpha_values) + 1) // 2, 2, figsize=(14, 12), sharex=True, sharey=True) + axs = axs.flatten() + + for i, alpha in enumerate(alpha_values): + forcing_freq = freq_from_alpha(bar, alpha) + + # Run convergence + results = convergence.run_convergence(forcing_freq, num_sections_range, convergence_metric) + + # Plot results in the subplot + ax = axs[i] + ax.loglog(results['fdm']['num_sections'], results['fdm']['errors'], '-o', label='FDM Analytical Error') + ax.loglog(results['fem']['num_sections'], results['fem']['errors'], '--s', label='FEM Analytical Error') + ax.loglog(results['fdm']['num_sections'], results['fdm']['extrapolated_errors'], '-x', label='FDM Extrapolated Error') + ax.loglog(results['fem']['num_sections'], results['fem']['extrapolated_errors'], '--d', label='FEM Extrapolated Error') + ax.set_title(f"Convergence for α = {alpha}") + ax.set_ylabel("Error (Relative)") + ax.grid(True, which="both", linestyle="--") + if i >= len(alpha_values) - 2: + ax.set_xlabel("Number of Sections") + ax.legend() + + # Output table for this alpha + print(f"\nConvergence Table for α = {alpha}") + print("{:<15} {:<20} {:<20} {:<20} {:<15} {:<15} {:<15} {:<15}".format( + "dx", "Analytical Value", "Method Value", "Extrap Value", + "% Error", "β", "% Extrap Error", "β Extrap" + )) + print("-" * 135) + for j in range(len(results['fdm']['num_sections'])): + num_sections = results['fdm']['num_sections'][j] + dx = 1 / num_sections + analytical_value = results['fdm']['analytical_values'][j] + fdm_value = results['fdm']['extrapolated_values'][j] + fdm_error = results['fdm']['errors'][j] + fdm_beta = results['fdm']['betas'][j] if j >= 1 else float('nan') # Beta starts at index 1 + fdm_extrap_err = results['fdm']['extrapolated_errors'][j] + fdm_extrap_beta = results['fdm']['extrapolated_betas'][j] if j >= 2 else float('nan') # Extrap Beta starts at index 2 + + print("{:<15} {:<15.6f} {:<15.6f} {:<15.6f} {:<15.6f} {:<15.6f} {:<15.6f} {:<15.6f}".format( + dx, analytical_value, fdm_value, fdm_value, fdm_error, fdm_beta, fdm_extrap_err, fdm_extrap_beta + )) + + # Hide any unused subplots + for j in range(len(alpha_values), len(axs)): + fig.delaxes(axs[j]) + + # Save and show the plot + plt.tight_layout() + plt.savefig("Images/2_Second_Order_Convergence.png") + plt.show() + + + + print("\n4th Order FDM and P=2 FEM Convergence of U(x=1/(2pi))") + # Initialize Bar, FDM, FEM for 4th order convergence + bar = Bar() + analy = Analytical(bar) + fdm = FDM(bar, desired_order="4") + fem = FEM(bar, desired_order="4") + + # Set boundary conditions + fdm.set_boundary_conditions(U_0=0, U_L=100) + fem.set_boundary_conditions(U_0=0, U_L=100) + + # Initialize Convergence + convergence = Convergence(analy, fdm, fem) + + num_sections_range = [2**n for n in range(1, 12)] + alpha_values = [0.25, 0.5, 1.0, 2.0, 4.0] + + # Create a figure with 2 columns of subplots + fig, axs = plt.subplots((len(alpha_values) + 1) // 2, 2, figsize=(14, 12), sharex=True, sharey=True) + axs = axs.flatten() + + for i, alpha in enumerate(alpha_values): + forcing_freq = freq_from_alpha(bar, alpha) + + # Run convergence + results = convergence.run_convergence(forcing_freq, num_sections_range, convergence_metric) + + # Plot results in the subplot + ax = axs[i] + ax.loglog(results['fdm']['num_sections'], results['fdm']['errors'], '-o', label='FDM Analytical Error') + ax.loglog(results['fem']['num_sections'], results['fem']['errors'], '--s', label='FEM Analytical Error') + ax.loglog(results['fdm']['num_sections'], results['fdm']['extrapolated_errors'], '-x', label='FDM Extrapolated Error') + ax.loglog(results['fem']['num_sections'], results['fem']['extrapolated_errors'], '--d', label='FEM Extrapolated Error') + ax.set_title(f"Convergence for α = {alpha}") + ax.set_ylabel("Error (Relative)") + ax.grid(True, which="both", linestyle="--") + if i >= len(alpha_values) - 2: + ax.set_xlabel("Number of Sections") + ax.legend() + + # Output table for this alpha + print(f"\nConvergence Table for α = {alpha}") + print("{:<15} {:<20} {:<20} {:<20} {:<15} {:<15} {:<15} {:<15}".format( + "dx", "Analytical Value", "Method Value", "Extrap Value", + "% Error", "β", "% Extrap Error", "β Extrap" + )) + print("-" * 135) + for j in range(len(results['fdm']['num_sections'])): + num_sections = results['fdm']['num_sections'][j] + dx = 1 / num_sections + analytical_value = results['fdm']['analytical_values'][j] + fdm_value = results['fdm']['extrapolated_values'][j] + fdm_error = results['fdm']['errors'][j] + fdm_beta = results['fdm']['betas'][j] if j >= 1 else float('nan') # Beta starts at index 1 + fdm_extrap_err = results['fdm']['extrapolated_errors'][j] + fdm_extrap_beta = results['fdm']['extrapolated_betas'][j] if j >= 2 else float('nan') # Extrap Beta starts at index 2 + + print("{:<15} {:<15.6f} {:<15.6f} {:<15.6f} {:<15.6f} {:<15.6f} {:<15.6f} {:<15.6f}".format( + dx, analytical_value, fdm_value, fdm_value, fdm_error, fdm_beta, fdm_extrap_err, fdm_extrap_beta + )) + + # Hide any unused subplots + for j in range(len(alpha_values), len(axs)): + fig.delaxes(axs[j]) + + # Save and show the plot + plt.tight_layout() + plt.savefig("Images/2_Fourth_Order_Convergence.png") + plt.show() + + +import numpy as np +import matplotlib.pyplot as plt + +def frequency_sweep(): + # Alpha sweep values + alpha_sweep_values = np.linspace(0.1, 50, 1000) + + # Section sweep values + num_sections_range = [2**n for n in range(1, 10)] + + # Initialize Bar, Analytical, FDM, FEM + bar = Bar() + analytical = Analytical(bar) + + # Plot 1: Analytical, FDM 2nd Order, FEM P=1 + fdm_2nd = FDM(bar, desired_order="2") + fem_p1 = FEM(bar, desired_order="2") + + fdm_2nd.set_boundary_conditions(U_0=0, U_L=100) + fem_p1.set_boundary_conditions(U_0=0, U_L=100) + + fig, axs = plt.subplots(len(num_sections_range), 1, figsize=(16, 20)) # 10 rows, 1 column + axs = axs.flatten() + + for idx, num_sections in enumerate(num_sections_range): + dx = 1 / num_sections + disp_amplitudes_analytical = [] + disp_amplitudes_fdm_2nd = [] + disp_amplitudes_fem_p1 = [] + + for alpha in alpha_sweep_values: + freq = freq_from_alpha(bar, alpha) + + # Analytical + disp_amplitudes_analytical.append(analytical.get_disp_amp(freq, x_vals=np.array([1 / (2 * np.pi)]))) + + # FDM 2nd Order + fdm_2nd.run(freq, num_sections) + disp_amplitudes_fdm_2nd.append(fdm_2nd.get_disp_amp(x=np.array([1 / (2 * np.pi)]))) + + # FEM P=1 + fem_p1.run(freq, num_sections) + disp_amplitudes_fem_p1.append(fem_p1.get_disp_amp(x=np.array([1 / (2 * np.pi)]))) + + # Subplot for this number of sections + ax = axs[idx] + ax.plot(alpha_sweep_values, disp_amplitudes_analytical, label="Analytical", linestyle="-") + ax.plot(alpha_sweep_values, disp_amplitudes_fdm_2nd, label="FDM 2nd Order", linestyle="--") + ax.plot(alpha_sweep_values, disp_amplitudes_fem_p1, label="FEM P=1", linestyle=":") + ax.set_ylim((-10000, 10000)) # Set uniform y-limits for all subplots + ax.set_title(f"dx = {dx:.5f} (Num Sections = {num_sections})") + ax.set_xlabel("α") + ax.set_ylabel("Displacement Amplitude") + ax.legend() + ax.grid(True) + + plt.tight_layout() + plt.suptitle("Frequency Sweep (Displacement Amplitude, FDM 2nd Order, FEM P=1)", y=1.02) + plt.savefig("Images/3_Frequency_Sweep_FDM2_FEM1.png") + plt.close() + + # Plot 2: Analytical, FDM 4th Order, FEM P=2 + fdm_4th = FDM(bar, desired_order="4") + fem_p2 = FEM(bar, desired_order="4") + + fdm_4th.set_boundary_conditions(U_0=0, U_L=100) + fem_p2.set_boundary_conditions(U_0=0, U_L=100) + + fig, axs = plt.subplots(len(num_sections_range), 1, figsize=(16, 20)) # 10 rows, 1 column + axs = axs.flatten() + + for idx, num_sections in enumerate(num_sections_range): + dx = 1 / num_sections + disp_amplitudes_analytical = [] + disp_amplitudes_fdm_4th = [] + disp_amplitudes_fem_p2 = [] + + for alpha in alpha_sweep_values: + freq = freq_from_alpha(bar, alpha) + + # Analytical + disp_amplitudes_analytical.append(analytical.get_disp_amp(freq, x_vals=np.array([1 / (2 * np.pi)]))) + + # FDM 4th Order + fdm_4th.run(freq, num_sections) + disp_amplitudes_fdm_4th.append(fdm_4th.get_disp_amp(x=np.array([1 / (2 * np.pi)]))) + + # FEM P=2 + fem_p2.run(freq, num_sections) + disp_amplitudes_fem_p2.append(fem_p2.get_disp_amp(x=np.array([1 / (2 * np.pi)]))) + + # Subplot for this number of sections + ax = axs[idx] + ax.plot(alpha_sweep_values, disp_amplitudes_analytical, label="Analytical", linestyle="-") + ax.plot(alpha_sweep_values, disp_amplitudes_fdm_4th, label="FDM 4th Order", linestyle="--") + ax.plot(alpha_sweep_values, disp_amplitudes_fem_p2, label="FEM P=2", linestyle=":") + ax.set_ylim((-10000, 10000)) # Set uniform y-limits for all subplots + ax.set_title(f"dx = {dx:.5f} (Num Sections = {num_sections})") + ax.set_xlabel("α") + ax.set_ylabel("Displacement Amplitude") + ax.legend() + ax.grid(True) + + plt.tight_layout() + plt.suptitle("Frequency Sweep (Displacement Amplitude, FDM 4th Order, FEM P=2)", y=1.02) + plt.savefig("Images/3_Frequency_Sweep_FDM4_FEM2.png") + plt.close() + + + + + +if __name__ == "__main__": + import os + os.system('cls' if os.name == 'nt' else 'clear') + analytical() + + convergence() + + frequency_sweep() + +# if __name__ == "__main__": +# import os +# import sys +# os.system('cls' if os.name == 'nt' else 'clear') +# # Redirect stdout and stderr to a file +# with open("output.txt", "w", encoding="utf-8") as output_file: +# # Redirect stdout +# sys.stdout = output_file +# # Redirect stderr +# sys.stderr = output_file + +# # Run the main functions +# try: +# analytical() +# convergence() +# # frequency_sweep() +# except Exception as e: +# print(f"An error occurred: {e}") + +# # Restore stdout and stderr +# sys.stdout = sys.__stdout__ +# sys.stderr = sys.__stderr__ + +# print("Execution completed. Output saved to output.txt.") \ No newline at end of file diff --git a/HW5/output.txt b/HW5/output.txt new file mode 100644 index 0000000..cdcbdef --- /dev/null +++ b/HW5/output.txt @@ -0,0 +1,186 @@ + +Analytical Results +Analytical Displacement +x α = 0.25 α = 0.50 α = 1.00 α = 2.00 α = 4.00 α = 10.00 α = 20.00 +------------------------------------------------------------------------------------------------------------------- +0.000 0.0000 0.0000 0.0000 0.0000 -0.0000 -0.0000 0.0000 +0.125 12.6291 13.0279 14.8163 27.2083 -63.3488 -174.4389 65.5540 +0.159 16.0783 16.5810 18.8341 34.4180 -78.5516 -183.7768 -4.5451 +0.250 25.2459 26.0050 29.4014 52.7248 -111.1877 -110.0090 -105.0363 +0.375 37.8380 38.8806 43.5276 74.9632 -131.8039 105.0623 102.7444 +0.500 50.3932 51.6043 56.9747 92.5408 -120.1499 176.2660 -59.5897 +0.625 62.8992 64.1264 69.5327 104.3646 -79.0790 6.0989 -7.2646 +0.750 75.3437 76.3982 81.0056 109.6995 -18.6469 -172.4198 71.2297 +0.875 87.7147 88.3716 91.2145 108.2139 46.3507 -114.8345 -106.8658 +1.000 100.0000 100.0000 100.0000 100.0000 100.0000 100.0000 100.0000 + +Analytical Strain +x α = 0.25 α = 0.50 α = 1.00 α = 2.00 α = 4.00 α = 10.00 α = 20.00 +------------------------------------------------------------------------------------------------------------------- +0.000 101.0493 104.2915 118.8395 219.9500 -528.5395 -1838.1640 2190.7119 +0.125 101.0000 104.0879 117.9123 213.1123 -463.8370 -579.6142 -1755.0748 +0.159 100.9693 103.9614 117.3376 208.9010 -425.0038 38.1449 -2188.8251 +0.250 100.8520 103.4778 115.1451 193.0243 -285.5711 1472.6333 621.4221 +0.375 100.6056 102.4636 110.5811 160.9350 -37.3874 1508.3226 759.3781 +0.500 100.2609 101.0493 104.2915 118.8395 219.9500 -521.4176 -1838.1640 +0.625 99.8183 99.2404 96.3745 69.3552 423.4360 -1837.1519 2185.8885 +0.750 99.2783 97.0440 86.9535 15.5586 523.2501 -637.1725 -1664.2573 +0.875 98.6413 94.4687 76.1758 -39.2052 494.9543 1435.3224 480.7297 +1.000 97.9079 91.5244 64.2093 -91.5315 345.4765 1542.3510 893.9902 +No artists with labels found to put in legend. Note that artists whose label start with an underscore are ignored when legend() is called with no argument. + +Convergence Results + +2nd Order FDM and P=1 FEM Convergence of U(x=1/(2pi)) + +Convergence Table for α = 0.25 +dx Analytical Value Method Value Extrap Value % Error β % Extrap Error β Extrap +--------------------------------------------------------------------------------------------------------------------------------------- +0.5 16.078254 16.078452 16.078452 0.000012 nan nan nan +0.25 16.078254 16.078310 16.078310 0.000003 1.814778 nan nan +0.125 16.078254 16.078268 16.078268 0.000001 2.068323 0.000001 1.725316 +0.0625 16.078254 16.078258 16.078258 0.000000 1.998164 0.000000 2.091062 +0.03125 16.078254 16.078255 16.078255 0.000000 2.004412 0.000000 1.993886 +0.015625 16.078254 16.078255 16.078255 0.000000 2.000002 0.000000 2.233528 +0.0078125 16.078254 16.078254 16.078254 0.000000 1.999997 0.000000 0.752269 +0.00390625 16.078254 16.078254 16.078254 0.000000 1.999987 0.000000 -0.082906 +0.001953125 16.078254 16.078254 16.078254 0.000000 2.000812 0.000000 -0.003978 +0.0009765625 16.078254 16.078254 16.078254 0.000000 1.992182 0.000000 0.005319 +0.00048828125 16.078254 16.078254 16.078254 0.000000 2.201742 0.000003 -0.000020 + +Convergence Table for α = 0.5 +dx Analytical Value Method Value Extrap Value % Error β % Extrap Error β Extrap +--------------------------------------------------------------------------------------------------------------------------------------- +0.5 16.580992 16.584311 16.584311 0.000200 nan nan nan +0.25 16.580992 16.581930 16.581930 0.000057 1.823229 nan nan +0.125 16.580992 16.581215 16.581215 0.000013 2.069082 0.000018 1.736830 +0.0625 16.580992 16.581048 16.581048 0.000003 1.998625 0.000003 2.091852 +0.03125 16.580992 16.581006 16.581006 0.000001 2.004462 0.000001 1.996719 +0.015625 16.580992 16.580995 16.580995 0.000000 2.000028 0.000000 2.006221 +0.0078125 16.580992 16.580993 16.580993 0.000000 2.000007 0.000000 1.994125 +0.00390625 16.580992 16.580992 16.580992 0.000000 2.000035 0.000000 1.891296 +0.001953125 16.580992 16.580992 16.580992 0.000000 2.000010 0.000000 1.843723 +0.0009765625 16.580992 16.580992 16.580992 0.000000 1.999286 0.000000 0.668336 +0.00048828125 16.580992 16.580992 16.580992 0.000000 2.003076 0.000000 0.007129 + +Convergence Table for α = 1.0 +dx Analytical Value Method Value Extrap Value % Error β % Extrap Error β Extrap +--------------------------------------------------------------------------------------------------------------------------------------- +0.5 18.834148 18.899840 18.899840 0.003488 nan nan nan +0.25 18.834148 18.852241 18.852241 0.000961 1.860259 nan nan +0.125 18.834148 18.838449 18.838449 0.000228 2.072629 0.000299 1.787081 +0.0625 18.834148 18.835222 18.835222 0.000057 2.000605 0.000052 2.095846 +0.03125 18.834148 18.834415 18.834415 0.000014 2.004686 0.000014 1.999248 +0.015625 18.834148 18.834214 18.834214 0.000004 2.000145 0.000004 2.006198 +0.0078125 18.834148 18.834164 18.834164 0.000001 2.000036 0.000001 2.000161 +0.00390625 18.834148 18.834152 18.834152 0.000000 2.000039 0.000000 1.999982 +0.001953125 18.834148 18.834149 18.834149 0.000000 2.000002 0.000000 1.998332 +0.0009765625 18.834148 18.834148 18.834148 0.000000 2.000046 0.000000 2.109196 +0.00048828125 18.834148 18.834148 18.834148 0.000000 2.000014 0.000000 2.133319 + +Convergence Table for α = 2.0 +dx Analytical Value Method Value Extrap Value % Error β % Extrap Error β Extrap +--------------------------------------------------------------------------------------------------------------------------------------- +0.5 34.417979 37.552156 37.552156 0.091062 nan nan nan +0.25 34.417979 35.150695 35.150695 0.021289 2.096760 nan nan +0.125 34.417979 34.588873 34.588873 0.004965 2.100152 0.004985 2.095727 +0.0625 34.417979 34.460351 34.460351 0.001231 2.011902 0.001107 2.128103 +0.03125 34.417979 34.428526 34.428526 0.000306 2.006294 0.000304 2.013755 +0.015625 34.417979 34.420614 34.420614 0.000077 2.000814 0.000076 2.008115 +0.0078125 34.417979 34.418638 34.418638 0.000019 2.000204 0.000019 2.001018 +0.00390625 34.417979 34.418144 34.418144 0.000005 2.000073 0.000005 2.000246 +0.001953125 34.417979 34.418020 34.418020 0.000001 2.000013 0.000001 2.000097 +0.0009765625 34.417979 34.417989 34.417989 0.000000 2.000004 0.000000 1.999770 +0.00048828125 34.417979 34.417981 34.417981 0.000000 2.000059 0.000000 2.001842 + +Convergence Table for α = 4.0 +dx Analytical Value Method Value Extrap Value % Error β % Extrap Error β Extrap +--------------------------------------------------------------------------------------------------------------------------------------- +0.5 -78.551640 -44.521329 -44.521329 0.433222 nan nan nan +0.25 -78.551640 -72.147403 -72.147403 0.081529 2.409722 nan nan +0.125 -78.551640 -76.519925 -76.519925 0.025865 1.656329 0.010631 2.659493 +0.0625 -78.551640 -78.029415 -78.029415 0.006648 1.959954 0.010096 1.534405 +0.03125 -78.551640 -78.419329 -78.419329 0.001684 1.980741 0.001729 1.952832 +0.015625 -78.551640 -78.518501 -78.518501 0.000422 1.997361 0.000431 1.975144 +0.0078125 -78.551640 -78.543351 -78.543351 0.000106 1.999341 0.000106 1.996700 +0.00390625 -78.551640 -78.549567 -78.549567 0.000026 1.999770 0.000026 1.999198 +0.001953125 -78.551640 -78.551121 -78.551121 0.000007 1.999957 0.000007 1.999708 +0.0009765625 -78.551640 -78.551510 -78.551510 0.000002 1.999982 0.000002 1.999958 +0.00048828125 -78.551640 -78.551607 -78.551607 0.000000 1.999999 0.000000 1.999993 + +4th Order FDM and P=2 FEM Convergence of U(x=1/(2pi)) + +Convergence Table for α = 0.25 +dx Analytical Value Method Value Extrap Value % Error β % Extrap Error β Extrap +--------------------------------------------------------------------------------------------------------------------------------------- +0.5 16.078254 16.078287 16.078287 0.000002 nan nan nan +0.25 16.078254 16.078253 16.078253 0.000000 4.811274 nan nan +0.125 16.078254 16.078254 16.078254 0.000000 5.424900 0.000000 4.730211 +0.0625 16.078254 16.078254 16.078254 0.000000 4.272605 0.000000 0.909708 +0.03125 16.078254 16.078254 16.078254 0.000000 7.515896 0.000000 -0.004096 +0.015625 16.078254 16.078254 16.078254 0.000000 2.391135 0.000003 0.000000 +0.0078125 16.078254 16.078254 16.078254 0.000000 -1.007072 nan nan +0.00390625 16.078254 16.078254 16.078254 0.000000 -2.314502 nan nan +0.001953125 16.078254 16.078254 16.078254 0.000000 -1.799075 nan nan +0.0009765625 16.078254 16.078254 16.078254 0.000000 -2.029648 0.000025 0.000001 +0.00048828125 16.078254 16.078254 16.078254 0.000000 0.207580 0.000011 -0.000000 + +Convergence Table for α = 0.5 +dx Analytical Value Method Value Extrap Value % Error β % Extrap Error β Extrap +--------------------------------------------------------------------------------------------------------------------------------------- +0.5 16.580992 16.581525 16.581525 0.000032 nan nan nan +0.25 16.580992 16.580973 16.580973 0.000001 4.786253 nan nan +0.125 16.580992 16.580992 16.580992 0.000000 5.521549 0.000000 4.806285 +0.0625 16.580992 16.580992 16.580992 0.000000 4.118326 0.000000 5.636740 +0.03125 16.580992 16.580992 16.580992 0.000000 9.365088 0.000000 -0.509052 +0.015625 16.580992 16.580992 16.580992 0.000000 3.536667 0.000000 -0.000026 +0.0078125 16.580992 16.580992 16.580992 0.000000 -0.410172 nan nan +0.00390625 16.580992 16.580992 16.580992 0.000000 -1.704184 nan nan +0.001953125 16.580992 16.580992 16.580992 0.000000 -2.067930 nan nan +0.0009765625 16.580992 16.580992 16.580992 0.000000 -1.875636 0.000006 0.000002 +0.00048828125 16.580992 16.580992 16.580992 0.000000 -2.081360 0.000004 -0.000016 + +Convergence Table for α = 1.0 +dx Analytical Value Method Value Extrap Value % Error β % Extrap Error β Extrap +--------------------------------------------------------------------------------------------------------------------------------------- +0.5 18.834148 18.843758 18.843758 0.000510 nan nan nan +0.25 18.834148 18.833772 18.833772 0.000020 4.677470 nan nan +0.125 18.834148 18.834153 18.834153 0.000000 5.985224 0.000001 4.710179 +0.0625 18.834148 18.834147 18.834147 0.000000 3.448116 0.000000 5.882540 +0.03125 18.834148 18.834148 18.834148 0.000000 6.498357 0.000000 4.031577 +0.015625 18.834148 18.834148 18.834148 0.000000 4.002814 0.000000 -0.047321 +0.0078125 18.834148 18.834148 18.834148 0.000000 4.262898 0.000001 0.000029 +0.00390625 18.834148 18.834148 18.834148 0.000000 0.326859 0.000019 -0.000000 +0.001953125 18.834148 18.834148 18.834148 0.000000 -2.024489 nan nan +0.0009765625 18.834148 18.834148 18.834148 0.000000 -2.030078 0.000013 0.000001 +0.00048828125 18.834148 18.834148 18.834148 0.000000 -1.997818 0.000003 0.000017 + +Convergence Table for α = 2.0 +dx Analytical Value Method Value Extrap Value % Error β % Extrap Error β Extrap +--------------------------------------------------------------------------------------------------------------------------------------- +0.5 34.417979 34.663528 34.663528 0.007134 nan nan nan +0.25 34.417979 34.402614 34.402614 0.000446 3.998268 nan nan +0.125 34.417979 34.417862 34.417862 0.000003 7.037851 0.000024 4.096854 +0.0625 34.417979 34.417945 34.417945 0.000001 1.808584 0.000000 7.511752 +0.03125 34.417979 34.417978 34.417978 0.000000 4.687210 0.000001 1.381023 +0.015625 34.417979 34.417979 34.417979 0.000000 4.000567 0.000000 4.592474 +0.0078125 34.417979 34.417979 34.417979 0.000000 4.000935 0.000000 -5.512228 +0.00390625 34.417979 34.417979 34.417979 0.000000 4.056899 0.000000 -0.001227 +0.001953125 34.417979 34.417979 34.417979 0.000000 1.119402 0.000001 0.000016 +0.0009765625 34.417979 34.417979 34.417979 0.000000 -2.128619 nan nan +0.00048828125 34.417979 34.417979 34.417979 0.000000 -2.005417 0.000000 0.000241 + +Convergence Table for α = 4.0 +dx Analytical Value Method Value Extrap Value % Error β % Extrap Error β Extrap +--------------------------------------------------------------------------------------------------------------------------------------- +0.5 -78.551640 -133.563988 -133.563988 0.700334 nan nan nan +0.25 -78.551640 -78.603880 -78.603880 0.000665 10.040387 nan nan +0.125 -78.551640 -78.578508 -78.578508 0.000342 0.959249 0.000000 11.080952 +0.0625 -78.551640 -78.552404 -78.552404 0.000010 5.135275 0.011709 -0.041042 +0.03125 -78.551640 -78.551711 -78.551711 0.000001 3.412791 0.000000 5.235885 +0.015625 -78.551640 -78.551644 -78.551644 0.000000 4.002608 0.000000 3.363585 +0.0078125 -78.551640 -78.551640 -78.551640 0.000000 4.001591 0.000000 3.942435 +0.00390625 -78.551640 -78.551640 -78.551640 0.000000 4.071443 0.000000 -1.652138 +0.001953125 -78.551640 -78.551640 -78.551640 0.000000 4.137881 0.000000 -0.003593 +0.0009765625 -78.551640 -78.551640 -78.551640 0.000000 1.177470 0.000000 0.000789 +0.00048828125 -78.551640 -78.551640 -78.551640 0.000000 -2.229793 0.000015 -0.000002 diff --git a/README.md b/README.md index e69de29..ef2f387 100644 --- a/README.md +++ b/README.md @@ -0,0 +1,10 @@ +# Texas A&M Aerospace Engineering - AERO 430 - Numerical Simulation +## HW1 + +## HW2 + +## HW3 + +## HW4 + +## HW5