Loading dthydro_cfd/rom_cfd/pod_rom.py +28 −11 Original line number Diff line number Diff line """ Proper Orthogonal Decomposition method implementations Proper Orthogonal Decomposition method with interpolation Author: William Gurecky. wll@ornl.gov. May 2023 """ import numpy as np from scipy.stats import norm Loading Loading @@ -114,11 +116,16 @@ class PODInterpModel(object): return np.matmul(self.pod_modes, pod_weights_hat) def pod_example_a(): def pod_example_a(n_pod_modes=14): """ Example using POD with interpolation to create model of 1D pressure field data as a fn on vane angle. Uses simple, synthetic data for testing. Args: n_pod_modes: Number of eigen modes to retain in the pod model. A truncated SVD is done to find the dominate modes. A larger number of retained modes is more accurate but slower. """ # Construct synthetic data n_avail_snapshots = 20 Loading Loading @@ -161,11 +168,11 @@ def pod_example_a(): p_profile = norm(loc=p_center, scale=p_wave_sd * (1. + u)).pdf(grid_x) * p_scale test_p_snaps.append(p_profile) test_p_t.append(u) plt.plot(grid_x, p_profile, label="vane: %0.2f" % u) plt.plot(grid_x, p_profile, label="vane u: %0.2f" % u) plt.ylabel("Pressure [arbitrary scale]") plt.xlabel("Space [m]") plt.grid(ls="--") plt.legend(bbox_to_anchor=(1.1, 1.1)) plt.legend(bbox_to_anchor=(1.05, 1.1)) plt.tight_layout() plt.savefig("pod_example_a_p_snaps.png") plt.close() Loading @@ -174,7 +181,7 @@ def pod_example_a(): test_p_t = np.asarray(test_p_t) # POD model fitting pod_model = PODInterpModel(max_modes=14, pod_method="svd") pod_model = PODInterpModel(max_modes=n_pod_modes, pod_method="svd") pod_model.fit(test_p_snaps, test_p_t) # Check POD model modes at known snapshot points Loading @@ -182,7 +189,7 @@ def pod_example_a(): # predict at known vane angle point pred_p = pod_model.predict(grid_u[0]) # predict at unknown vane angle u_test = (grid_u[0] + grid_u[1]) / 2. u_test = (grid_u[3] + grid_u[4]) / 2. known_p_test = gen_p_profile(u_test) pred_p_test = pod_model.predict(u_test) plt.plot(grid_x, known_p, label="train, u=%0.2f" % grid_u[0]) Loading @@ -192,20 +199,30 @@ def pod_example_a(): plt.ylabel("Pressure [arbitrary scale]") plt.xlabel("Space [m]") plt.grid(ls="--") plt.legend(bbox_to_anchor=(1.1, 1.1)) plt.legend(bbox_to_anchor=(1.05, 1.1)) plt.title("POD N-Modes: %d \n POD L2 error at train u: %0.2e \n POD L2 error at test u: %0.2e" % \ (pod_model.max_modes, np.linalg.norm(known_p - pred_p), np.linalg.norm(known_p_test - pred_p_test))) plt.tight_layout() plt.savefig("pod_example_a_p_check.png") plt.savefig("pod_" + str(n_pod_modes) + "_example_a_p_check.png") train_l2_err = np.linalg.norm(known_p - pred_p) test_l2_err = np.linalg.norm(known_p_test - pred_p_test) # Make more predictions at unknown vane angles for u_test in np.linspace(0.2, 0.8, 5): pred_p_test = pod_model.predict(u_test) plt.plot(grid_x, pred_p_test, ls='', marker=".", label="POD, u=%0.2f" % u_test) plt.legend(bbox_to_anchor=(1.1, 1.1)) plt.legend(bbox_to_anchor=(1.05, 1.1)) plt.tight_layout() plt.savefig("pod_example_a_p_check_many.png") plt.savefig("pod_" + str(n_pod_modes) + "_example_a_p_check_many.png") plt.close() return train_l2_err, test_l2_err if __name__ == "__main__": pod_example_a() print("N Modes, Train L2, Test L2 error") errs = [] for n_modes in [1, 2, 3, 4, 6, 8, 10, 12, 14]: train_l2_err, test_l2_err = pod_example_a(n_modes) errs.append([n_modes, train_l2_err, test_l2_err]) for n_modes, train_l2_err, test_l2_err in errs: print("%d, %0.8e, %0.8e" % (n_modes, train_l2_err, test_l2_err)) Loading
dthydro_cfd/rom_cfd/pod_rom.py +28 −11 Original line number Diff line number Diff line """ Proper Orthogonal Decomposition method implementations Proper Orthogonal Decomposition method with interpolation Author: William Gurecky. wll@ornl.gov. May 2023 """ import numpy as np from scipy.stats import norm Loading Loading @@ -114,11 +116,16 @@ class PODInterpModel(object): return np.matmul(self.pod_modes, pod_weights_hat) def pod_example_a(): def pod_example_a(n_pod_modes=14): """ Example using POD with interpolation to create model of 1D pressure field data as a fn on vane angle. Uses simple, synthetic data for testing. Args: n_pod_modes: Number of eigen modes to retain in the pod model. A truncated SVD is done to find the dominate modes. A larger number of retained modes is more accurate but slower. """ # Construct synthetic data n_avail_snapshots = 20 Loading Loading @@ -161,11 +168,11 @@ def pod_example_a(): p_profile = norm(loc=p_center, scale=p_wave_sd * (1. + u)).pdf(grid_x) * p_scale test_p_snaps.append(p_profile) test_p_t.append(u) plt.plot(grid_x, p_profile, label="vane: %0.2f" % u) plt.plot(grid_x, p_profile, label="vane u: %0.2f" % u) plt.ylabel("Pressure [arbitrary scale]") plt.xlabel("Space [m]") plt.grid(ls="--") plt.legend(bbox_to_anchor=(1.1, 1.1)) plt.legend(bbox_to_anchor=(1.05, 1.1)) plt.tight_layout() plt.savefig("pod_example_a_p_snaps.png") plt.close() Loading @@ -174,7 +181,7 @@ def pod_example_a(): test_p_t = np.asarray(test_p_t) # POD model fitting pod_model = PODInterpModel(max_modes=14, pod_method="svd") pod_model = PODInterpModel(max_modes=n_pod_modes, pod_method="svd") pod_model.fit(test_p_snaps, test_p_t) # Check POD model modes at known snapshot points Loading @@ -182,7 +189,7 @@ def pod_example_a(): # predict at known vane angle point pred_p = pod_model.predict(grid_u[0]) # predict at unknown vane angle u_test = (grid_u[0] + grid_u[1]) / 2. u_test = (grid_u[3] + grid_u[4]) / 2. known_p_test = gen_p_profile(u_test) pred_p_test = pod_model.predict(u_test) plt.plot(grid_x, known_p, label="train, u=%0.2f" % grid_u[0]) Loading @@ -192,20 +199,30 @@ def pod_example_a(): plt.ylabel("Pressure [arbitrary scale]") plt.xlabel("Space [m]") plt.grid(ls="--") plt.legend(bbox_to_anchor=(1.1, 1.1)) plt.legend(bbox_to_anchor=(1.05, 1.1)) plt.title("POD N-Modes: %d \n POD L2 error at train u: %0.2e \n POD L2 error at test u: %0.2e" % \ (pod_model.max_modes, np.linalg.norm(known_p - pred_p), np.linalg.norm(known_p_test - pred_p_test))) plt.tight_layout() plt.savefig("pod_example_a_p_check.png") plt.savefig("pod_" + str(n_pod_modes) + "_example_a_p_check.png") train_l2_err = np.linalg.norm(known_p - pred_p) test_l2_err = np.linalg.norm(known_p_test - pred_p_test) # Make more predictions at unknown vane angles for u_test in np.linspace(0.2, 0.8, 5): pred_p_test = pod_model.predict(u_test) plt.plot(grid_x, pred_p_test, ls='', marker=".", label="POD, u=%0.2f" % u_test) plt.legend(bbox_to_anchor=(1.1, 1.1)) plt.legend(bbox_to_anchor=(1.05, 1.1)) plt.tight_layout() plt.savefig("pod_example_a_p_check_many.png") plt.savefig("pod_" + str(n_pod_modes) + "_example_a_p_check_many.png") plt.close() return train_l2_err, test_l2_err if __name__ == "__main__": pod_example_a() print("N Modes, Train L2, Test L2 error") errs = [] for n_modes in [1, 2, 3, 4, 6, 8, 10, 12, 14]: train_l2_err, test_l2_err = pod_example_a(n_modes) errs.append([n_modes, train_l2_err, test_l2_err]) for n_modes, train_l2_err, test_l2_err in errs: print("%d, %0.8e, %0.8e" % (n_modes, train_l2_err, test_l2_err))