def inner_product_array( num_states, num_rows, num_cols, max_vecs_per_node, verbosity=1): """ Computes inner products from known vecs. Remember that rows correspond to adjoint modes and cols to direct modes """ col_vec_handles = [mr.VecHandlePickle(join(data_dir, col_vec_name%col_num)) for col_num in mr.range(num_cols)] row_vec_handles = [mr.VecHandlePickle(join(data_dir, row_vec_name%row_num)) for row_num in mr.range(num_rows)] generate_vecs(data_dir, num_states, row_vec_handles+col_vec_handles) my_VS = mr.VectorSpaceHandles( np.vdot, max_vecs_per_node=max_vecs_per_node, verbosity=verbosity) prof = cProfile.Profile() start_time = time.time() prof.runcall( my_VS.compute_inner_product_array, *(col_vec_handles, row_vec_handles)) total_time = time.time() - start_time prof.dump_stats('IP_array_r%d.prof'%mr.parallel.get_rank()) return total_time
def lin_combine( num_states, num_bases, num_products, max_vecs_per_node, verbosity=1): """ Computes linear combination of vecs from saved vecs and random coeffs num_bases is number of vecs to be linearly combined num_products is the resulting number of vecs """ basis_handles = [mr.VecHandlePickle(join(data_dir, basis_name%basis_num)) for basis_num in mr.range(num_bases)] product_handles = [mr.VecHandlePickle(join(data_dir, product_name%product_num)) for product_num in mr.range(num_products)] generate_vecs(data_dir, num_states, basis_handles) my_VS = mr.VectorSpaceHandles( inner_product=np.vdot, max_vecs_per_node=max_vecs_per_node, verbosity=verbosity) coeff_array = np.random.random((num_bases, num_products)) mr.parallel.barrier() prof = cProfile.Profile() start_time = time.time() prof.runcall(my_VS.lin_combine, *(product_handles, basis_handles, coeff_array)) total_time = time.time() - start_time prof.dump_stats('lincomb_r%d.prof'%mr.parallel.get_rank()) return total_time
def inner_product_array( num_states, num_rows, num_cols, max_vecs_per_node, verbosity=1): """ Computes inner products from known vecs. Remember that rows correspond to adjoint modes and cols to direct modes """ col_vec_handles = [mr.VecHandlePickle(join(data_dir, col_vec_name%col_num)) for col_num in mr.range(num_cols)] row_vec_handles = [mr.VecHandlePickle(join(data_dir, row_vec_name%row_num)) for row_num in mr.range(num_rows)] generate_vecs(data_dir, num_states, row_vec_handles+col_vec_handles) my_VS = mr.VectorSpaceHandles( inner_product=np.vdot, max_vecs_per_node=max_vecs_per_node, verbosity=verbosity) prof = cProfile.Profile() start_time = time.time() prof.runcall( my_VS.compute_inner_product_array, *(col_vec_handles, row_vec_handles)) total_time = time.time() - start_time prof.dump_stats('IP_array_r%d.prof'%mr.parallel.get_rank()) return total_time
def lin_combine( num_states, num_bases, num_products, max_vecs_per_node, verbosity=1): """ Computes linear combination of vecs from saved vecs and random coeffs num_bases is number of vecs to be linearly combined num_products is the resulting number of vecs """ basis_handles = [mr.VecHandlePickle(join(data_dir, basis_name%basis_num)) for basis_num in mr.range(num_bases)] product_handles = [mr.VecHandlePickle(join(data_dir, product_name%product_num)) for product_num in mr.range(num_products)] generate_vecs(data_dir, num_states, basis_handles) my_VS = mr.VectorSpaceHandles(np.vdot, max_vecs_per_node=max_vecs_per_node, verbosity=verbosity) coeff_array = np.random.random((num_bases, num_products)) mr.parallel.barrier() prof = cProfile.Profile() start_time = time.time() prof.runcall(my_VS.lin_combine, *(product_handles, basis_handles, coeff_array)) total_time = time.time() - start_time prof.dump_stats('lincomb_r%d.prof'%mr.parallel.get_rank()) return total_time
def herdif(n, m, b): """Computes differentiation arrays D1, D2, ..., Dm on Hermite points. Args: n: Number of points, which is also the order of accuracy. m: Number of derivative arrays to return. b: Scaling parameter. Real and positive. Returns: x: Array of nodes, zeros of Hermite polynomial of degree n, scaled by b. Dm: A list s.t. Dm[i] is the (i+1)-th derivative array, i=0...m-1. Note: 0 < m < n-1. """ x = herroots(n) # Compute weights alpha = np.exp(-x ** 2 / 2.) # Set up beta array s.t. beta[i,j] = # ( (i+1)-th derivative of alpha(x) )/alpha(x), evaluated at x = x(j) beta = np.zeros((m + 1, x.shape[0])) beta[0] = 1. beta[1] = -x for i in mr.range(2, m + 1): beta[i] = -x * beta[i - 1] - (i - 1) * beta[i - 2] # Remove initializing row from beta beta = np.delete(beta, 0, 0) # Compute differentiation array (b=1) Dm = poldif(x, alpha=alpha, B=beta) # Scale nodes by the factor b x = x/b # Adjust derivatives for b not equal to 1 for i in mr.range(1, m + 1): Dm[i-1] *= b ** i return x, Dm
def symm_inner_product_array( num_states, num_vecs, max_vecs_per_node, verbosity=1): """ Computes symmetric inner product array from known vecs (as in POD). """ vec_handles = [mr.VecHandlePickle(join(data_dir, row_vec_name%row_num)) for row_num in mr.range(num_vecs)] generate_vecs(data_dir, num_states, vec_handles) my_VS = mr.VectorSpaceHandles( np.vdot, max_vecs_per_node=max_vecs_per_node, verbosity=verbosity) prof = cProfile.Profile() start_time = time.time() prof.runcall(my_VS.compute_symm_inner_product_array, vec_handles) total_time = time.time() - start_time prof.dump_stats('IP_symm_array_r%d.prof'%mr.parallel.get_rank()) return total_time
import numpy as np import modred as mr # Create random data num_vecs = 100 nx = 100 vecs = np.random.random((nx, num_vecs)) # Define non-uniform grid and corresponding inner product weights x_grid = 1. - np.cos(np.linspace(0, np.pi, nx)) x_diff = np.diff(x_grid) weights = 0.5 * np.append(np.append(x_diff[0], x_diff[:-1] + x_diff[1:]), x_diff[-1]) # Compute POD num_modes = 10 POD_res = mr.compute_POD_arrays_direct_method(vecs, list(mr.range(num_modes)), inner_product_weights=weights) modes = POD_res.modes eigvals = POD_res.eigvals
# Create directory for output files out_dir = 'tutorial_ex5_out' if not os.path.isdir(out_dir): os.makedirs(out_dir) # Create artificial sample times used as quadrature weights in POD num_vecs = 100 quad_weights = np.logspace(1., 3., num=num_vecs) base_vec_handle = mr.VecHandlePickle('%s/base_vec.pkl' % out_dir) snapshots = [ mr.VecHandlePickle( '%s/vec%d.pkl' % (out_dir, i),base_vec_handle=base_vec_handle, scale=quad_weights[i]) for i in mr.range(num_vecs)] # Save arbitrary snapshot data num_elements = 2000 if parallel.is_rank_zero(): for snap in snapshots + [base_vec_handle]: snap.put(np.random.random(num_elements)) parallel.barrier() # Compute and save POD modes my_POD = mr.PODHandles(np.vdot) my_POD.compute_decomp(snapshots) my_POD.put_decomp('%s/sing_vals.txt' % out_dir, '%s/sing_vecs.txt' % out_dir) my_POD.put_correlation_array('%s/correlation_array.txt' % out_dir) mode_indices = [1, 4, 5, 0, 10] modes = [
#!/usr/bin/env python import os from modred import parallel import modred as mr # modred must be installed. # Run tutorial scripts for i in mr.range(1, 7): if not parallel.is_distributed(): mr.run_script('tutorial_ex%d.py' % i) if parallel.is_distributed() and i >= 3: parallel.barrier() mr.run_script('tutorial_ex%d.py' % i) parallel.barrier() # Run reduced-order model scripts for i in mr.range(1, 3): if not parallel.is_distributed(): mr.run_script('rom_ex%d.py' % i) if parallel.is_distributed() and i > 1: mr.run_script('rom_ex%d.py' % i) parallel.barrier() # Run CGL scripts if not parallel.is_distributed(): mr.run_script('main_CGL.py')
import numpy as np import modred as mr # Create random data num_vecs = 100 nx = 100 vecs = np.random.random((nx, num_vecs)) # Define non-uniform grid and corresponding inner product weights x_grid = 1. - np.cos(np.linspace(0, np.pi, nx)) x_diff = np.diff(x_grid) weights = 0.5 * np.append(np.append( x_diff[0], x_diff[:-1] + x_diff[1:]), x_diff[-1]) # Compute POD num_modes = 10 POD_res = mr.compute_POD_arrays_direct_method( vecs, list(mr.range(num_modes)), inner_product_weights=weights) modes = POD_res.modes eigvals = POD_res.eigvals
weights[-1] = 0.5 * (x[-1] - x[-2]) weights[1:-1] = 0.5 * (x[2:] - x[0:-2]) M = np.diag(weights) inv_M = np.linalg.inv(M) M_sqrt = np.diag(weights ** 0.5) inv_M_sqrt = np.diag(weights ** -0.5) # LTI system arrays for direct and adjoint ("_adj") systems mu = (mu_0 - c_u ** 2) + mu_2 * x ** 2 / 2. A = -nu * Ds[0] + gamma * Ds[1] + np.diag(mu) # Compute optimal disturbance and use it as B array A_discrete = spla.expm(A * dt) exp_array = np.identity(nx, dtype=complex) max_sing_val = 0 for i in mr.range(1, 100): exp_array = exp_array.dot(A_discrete) U, E, VH = np.linalg.svd(M_sqrt.dot(exp_array.dot(inv_M_sqrt))) if max_sing_val < E[0]: max_sing_val = E[0] optimal_dist = VH.conj().T[:, 0] B = -inv_M_sqrt.dot(optimal_dist) C = np.exp(-((x - x_s) / s) ** 2).dot(M) A_adj = inv_M.dot(A.conj().T.dot(M)) C_adj = inv_M.dot(C.conj().T) # Plot spatial distributions of B and C if plots: plt.figure() plt.plot(x, B.real, 'b') plt.plot(x, B.imag, 'r')
import os import numpy as np import modred as mr # Create directory for output files out_dir = 'tutorial_ex3_out' if not os.path.isdir(out_dir): os.makedirs(out_dir) # Define handles for snapshots num_vecs = 30 direct_snapshots = [ mr.VecHandleArrayText('%s/direct_vec%d.txt' % (out_dir, i)) for i in mr.range(num_vecs) ] adjoint_snapshots = [ mr.VecHandleArrayText('%s/adjoint_vec%d.txt' % (out_dir, i)) for i in mr.range(num_vecs) ] # Save random snapshot data in text files x = np.linspace(0, np.pi, 200) for i, snap in enumerate(direct_snapshots): snap.put(np.sin(x * i)) for i, snap in enumerate(adjoint_snapshots): snap.put(np.cos(0.5 * x * i)) # Calculate and save BPOD modes my_BPOD = mr.BPODHandles(inner_product=np.vdot, max_vecs_per_node=10)
#!/usr/bin/env python """Helper script for looking at the scaling and profiling in parallel. Give this script a number of processors and optionally a number of lines of stats to print, e.g. ``python load_prof_parallel.py 24 40`` """ import sys import pstats as ps import modred as mr prof_path = 'lincomb_r%d.prof' num_procs = 1 num_stats = 30 if len(sys.argv) == 2: num_procs = int(sys.argv[1]) if len(sys.argv) == 3: num_procs = int(sys.argv[1]) num_stats = int(sys.argv[2]) stats = ps.Stats(prof_path%0) for rank in mr.range(1, num_procs): stats.add(prof_path % rank) print('\n----- Sum of all processors stats -----') stats.strip_dirs().sort_stats('cumulative').print_stats(num_stats)
import numpy as np from modred import parallel import modred as mr # Create directory for output files out_dir = 'rom_ex2_out' if not os.path.isdir(out_dir): os.makedirs(out_dir) # Create handles for modes num_modes = 10 basis_vecs = [ mr.VecHandlePickle('%s/dir_mode_%02d.pkl' % (out_dir, i)) for i in mr.range(num_modes) ] adjoint_basis_vecs = [ mr.VecHandlePickle('%s/adj_mode_%02d.pkl' % (out_dir, i)) for i in mr.range(num_modes) ] # Define system dimensions and create handles for action on modes num_inputs = 2 num_outputs = 4 A_on_basis_vecs = [ mr.VecHandlePickle('%s/A_on_dir_mode_%02d.pkl' % (out_dir, i)) for i in mr.range(num_modes) ] B_on_bases = [ mr.VecHandlePickle('%s/B_on_basis_%02d.pkl' % (out_dir, i))
def poldif(x, m=None, alpha=None, B=None): """ Computes the differentiation arrays D1, D2, ..., Dm on arbitrary nodes. The function is called with either keyword argument m OR keyword args alpha and B. If m is given, then the weight function is constant. If alpha and B are given, then the weights are defined by alpha and B. Args: x: 1D array of n distinct nodes. Kwargs: m: Number of derivatives. alpha: 1D array of weight values alpha[x], evaluated at x = x[k]. B: Array of size m x n where B[i,j] = beta[i,j] = ((i+1)-th derivative of alpha(x))/alpha(x), evaluated at x = x[j]. Returns: Dm: A list s.t. Dm[i] is the (i+1)-th derivative array, i=0...m-1. Note: 0 < m < n-1. """ x = x.flatten() n = x.shape[0] if m is not None and B is None and alpha is None: alpha = np.ones(n) B = np.zeros((m, n)) elif m is None and B is not None and alpha is not None: alpha = alpha.flatten() m = B.shape[0] else: raise RuntimeError('Keyword args to poldif are inconsistent.') XX = np.tile(x, (n, 1)).transpose() # DX contains entries x[k] - x[j]. DX = XX - XX.transpose() # Put 1's one the main diagonal. np.fill_diagonal(DX, 1.) # C has entries c[k]/c[j]. c = alpha * np.prod(DX, 1) C = np.tile(c, (n, 1)).transpose() C = C / C.transpose() # Z has entries 1/(x[k]-x[j]) Z = 1. / DX np.fill_diagonal(Z, 0.) # X is Z' but with the diagonal entries removed. X = Z.T X = ma.array(X.T, mask=np.identity(n)).compressed().reshape((n, n-1)).T # Y is array of cumulative sums and D is a differentiation array. Y = np.ones((n, n)) D = np.eye(n) Dm = [] for i in mr.range(1, m + 1): # Diagonals Y = np.cumsum( np.concatenate( (B[i - 1].reshape((1, n)), i * Y[0:n - 1] * X), axis=0), axis=0) # Off-diagonals D = i * Z * (C * np.tile(np.diag(D), (n, 1)).T - D) # Correct the diagonal D.flat[::n + 1] = Y[-1] Dm.append(D) return Dm
import numpy as np from modred import parallel import modred as mr from customvector import CustomVector, CustomVecHandle, inner_product # Create directory for output files out_dir = 'tutorial_ex6_out' if not os.path.isdir(out_dir): os.makedirs(out_dir) # Define snapshot handles direct_snapshots = [ CustomVecHandle('%s/direct_snap%d.pkl' % (out_dir, i), scale=np.pi) for i in mr.range(10) ] adjoint_snapshots = [ CustomVecHandle('%s/adjoint_snap%d.pkl' % (out_dir, i), scale=np.pi) for i in mr.range(10) ] # Create random snapshot data nx = 50 ny = 30 nz = 20 x = np.linspace(0, 1, nx) y = np.logspace(1, 2, ny) z = np.linspace(0, 1, nz)**2 if parallel.is_rank_zero(): for snap in direct_snapshots + adjoint_snapshots:
out_dir = 'tutorial_ex4_out' if not os.path.isdir(out_dir): os.makedirs(out_dir) # Define non-uniform grid and corresponding inner product weights nx = 80 ny = 100 x_grid = 1. - np.cos(np.linspace(0, np.pi, nx)) y_grid = np.linspace(0, 1., ny)**2 Y, X = np.meshgrid(y_grid, x_grid) # Create random snapshot data num_vecs = 100 snapshots = [ mr.VecHandlePickle('%s/vec%d.pkl' % (out_dir, i)) for i in mr.range(num_vecs) ] if parallel.is_rank_zero(): for i, snap in enumerate(snapshots): snap.put(np.sin(X * i) + np.cos(Y * i)) parallel.barrier() # Calculate DMD modes and save them to pickle files weighted_IP = mr.InnerProductTrapz(x_grid, y_grid) my_DMD = mr.DMDHandles(inner_product=weighted_IP) my_DMD.compute_decomp(snapshots) my_DMD.put_decomp('%s/eigvals.txt' % out_dir, '%s/R_low_order_eigvecs.txt' % out_dir, '%s/L_low_order_eigvecs.txt' % out_dir, '%s/correlation_array_eigvals.txt' % out_dir, '%s/correlation_array_eigvecs.txt' % out_dir)
from modred import parallel import modred as mr # Create directory for output files out_dir = 'tutorial_ex5_out' if not os.path.isdir(out_dir): os.makedirs(out_dir) # Create artificial sample times used as quadrature weights in POD num_vecs = 100 quad_weights = np.logspace(1., 3., num=num_vecs) base_vec_handle = mr.VecHandlePickle('%s/base_vec.pkl' % out_dir) snapshots = [ mr.VecHandlePickle('%s/vec%d.pkl' % (out_dir, i), base_vec_handle=base_vec_handle, scale=quad_weights[i]) for i in mr.range(num_vecs) ] # Save arbitrary snapshot data num_elements = 2000 if parallel.is_rank_zero(): for snap in snapshots + [base_vec_handle]: snap.put(np.random.random(num_elements)) parallel.barrier() # Compute and save POD modes my_POD = mr.PODHandles(np.vdot) my_POD.compute_decomp(snapshots) my_POD.put_decomp('%s/sing_vals.txt' % out_dir, '%s/sing_vecs.txt' % out_dir) my_POD.put_correlation_array('%s/correlation_array.txt' % out_dir) mode_indices = [1, 4, 5, 0, 10]
import numpy as np import modred as mr # Create directory for output files out_dir = 'tutorial_ex3_out' if not os.path.isdir(out_dir): os.makedirs(out_dir) # Define handles for snapshots num_vecs = 30 direct_snapshots = [ mr.VecHandleArrayText('%s/direct_vec%d.txt' % (out_dir, i)) for i in mr.range(num_vecs)] adjoint_snapshots = [ mr.VecHandleArrayText('%s/adjoint_vec%d.txt' % (out_dir, i)) for i in mr.range(num_vecs)] # Save random snapshot data in text files x = np.linspace(0, np.pi, 200) for i, snap in enumerate(direct_snapshots): snap.put(np.sin(x * i)) for i, snap in enumerate(adjoint_snapshots): snap.put(np.cos(0.5 * x * i)) # Calculate and save BPOD modes my_BPOD = mr.BPODHandles(np.vdot, max_vecs_per_node=10) sing_vals, L_sing_vecs, R_sing_vecs = my_BPOD.compute_decomp( direct_snapshots, adjoint_snapshots)
import numpy as np import modred as mr # Create random data num_vecs = 30 vecs = np.random.random((100, num_vecs)) # Compute POD num_modes = 5 POD_res = mr.compute_POD_arrays_snaps_method( vecs, list(mr.range(num_modes))) modes = POD_res.modes eigvals = POD_res.eigvals
weights[-1] = 0.5 * (x[-1] - x[-2]) weights[1:-1] = 0.5 * (x[2:] - x[0:-2]) M = np.diag(weights) inv_M = np.linalg.inv(M) M_sqrt = np.diag(weights**0.5) inv_M_sqrt = np.diag(weights**-0.5) # LTI system arrays for direct and adjoint ("_adj") systems mu = (mu_0 - c_u**2) + mu_2 * x**2 / 2. A = -nu * Ds[0] + gamma * Ds[1] + np.diag(mu) # Compute optimal disturbance and use it as B array A_discrete = spla.expm(A * dt) exp_array = np.identity(nx, dtype=complex) max_sing_val = 0 for i in mr.range(1, 100): exp_array = exp_array.dot(A_discrete) U, E, VH = np.linalg.svd(M_sqrt.dot(exp_array.dot(inv_M_sqrt))) if max_sing_val < E[0]: max_sing_val = E[0] optimal_dist = VH.conj().T[:, 0] B = -inv_M_sqrt.dot(optimal_dist) C = np.exp(-((x - x_s) / s)**2).dot(M) A_adj = inv_M.dot(A.conj().T.dot(M)) C_adj = inv_M.dot(C.conj().T) # Plot spatial distributions of B and C if plots: plt.figure() plt.plot(x, B.real, 'b') plt.plot(x, B.imag, 'r')
import numpy as np from modred import parallel import modred as mr # Create directory for output files out_dir = 'rom_ex2_out' if not os.path.isdir(out_dir): os.makedirs(out_dir) # Create handles for modes num_modes = 10 basis_vecs = [ mr.VecHandlePickle('%s/dir_mode_%02d.pkl' % (out_dir, i)) for i in mr.range(num_modes)] adjoint_basis_vecs = [ mr.VecHandlePickle('%s/adj_mode_%02d.pkl' % (out_dir, i)) for i in mr.range(num_modes)] # Define system dimensions and create handles for action on modes num_inputs = 2 num_outputs = 4 A_on_basis_vecs = [ mr.VecHandlePickle('%s/A_on_dir_mode_%02d.pkl' % (out_dir, i)) for i in mr.range(num_modes)] B_on_bases = [ mr.VecHandlePickle('%s/B_on_basis_%02d.pkl' % (out_dir, i)) for i in mr.range(num_inputs)] C_on_basis_vecs = [ np.sin(np.linspace(0, 0.1 * i, num_outputs)) for i in mr.range(num_modes)]