Commit de8468ba authored by William Gurecky's avatar William Gurecky
Browse files

improve pod ex figures and result summary

parent bb57591a
Loading
Loading
Loading
Loading
+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
@@ -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
@@ -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()
@@ -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
@@ -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])
@@ -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))