# Arbitrary data. parallel = MR.parallel_default_instance nx = 50 ny = 30 nz = 20 x = N.linspace(0, 1, nx) y = N.logspace(1, 2, ny) z = N.linspace(0, 1, nz)**2 if parallel.is_rank_zero(): for snap in direct_snapshots + adjoint_snapshots: snap.put(CustomVector([x, y, z], N.random.random((nx, ny, nz)))) parallel.barrier() # Compute and save Balanced POD modes. my_BPOD = MR.BPODHandles(inner_product) my_BPOD.sanity_check(direct_snapshots[0]) L_sing_vecs, sing_vals, R_sing_vecs = \ my_BPOD.compute_decomp(direct_snapshots, adjoint_snapshots) # less than 10% error sing_vals_norm = sing_vals / N.sum(sing_vals) num_modes = N.nonzero(N.cumsum(sing_vals_norm) > 0.9)[0][0] + 1 mode_nums = range(num_modes) direct_modes = [CustomVecHandle('direct_mode%d.pkl'%i) for i in mode_nums] adjoint_modes = [CustomVecHandle('adjoint_mode%d.pkl'%i) for i in mode_nums] my_BPOD.compute_direct_modes(mode_nums, direct_modes) my_BPOD.compute_adjoint_modes(mode_nums, adjoint_modes)
] # 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: snap.put(CustomVector([x, y, z], np.random.random((nx, ny, nz)))) parallel.barrier() # Compute and save balanced POD modes my_BPOD = mr.BPODHandles(inner_product) my_BPOD.sanity_check(direct_snapshots[0]) sing_vals, L_sing_vecs, R_sing_vecs = my_BPOD.compute_decomp( direct_snapshots, adjoint_snapshots) # Choose modes so that BPOD projection has less than 10% error sing_vals_norm = sing_vals / np.sum(sing_vals) num_modes = np.nonzero(np.cumsum(sing_vals_norm) > 0.9)[0][0] + 1 mode_nums = list(mr.range(num_modes)) direct_modes = [ CustomVecHandle('%s/direct_mode%d.pkl' % (out_dir, i)) for i in mode_nums ] adjoint_modes = [ CustomVecHandle('%s/adjoint_mode%d.pkl' % (out_dir, i)) for i in mode_nums ] my_BPOD.compute_direct_modes(mode_nums, direct_modes)
import numpy as N import modred as MR # Define the handles for the snapshots num_vecs = 30 direct_snapshots = [MR.VecHandleArrayText('direct_vec%d.txt' % i) for i in range(num_vecs)] adjoint_snapshots = [MR.VecHandleArrayText('adjoint_vec%d.txt' % i) for i in range(num_vecs)] # Save arbitrary data in text files x = N.linspace(0, N.pi, 200) for i, snap in enumerate(direct_snapshots): snap.put(N.sin(x*i)) for i, snap in enumerate(adjoint_snapshots): snap.put(N.cos(0.5*x*i)) # Calculate and save BPOD modes my_BPOD = MR.BPODHandles(N.vdot, max_vecs_per_node=10) L_sing_vecs, sing_vals, R_sing_vecs = \ my_BPOD.compute_decomp(direct_snapshots, adjoint_snapshots) num_modes = 10 mode_nums = range(num_modes) direct_modes = [MR.VecHandleArrayText('direct_mode%d' % i) for i in mode_nums] adjoint_modes = [MR.VecHandleArrayText('adjoint_mode%d' % i) for i in mode_nums] my_BPOD.compute_direct_modes(mode_nums, direct_modes) my_BPOD.compute_adjoint_modes(mode_nums, adjoint_modes)
def modal_decomposition(obj, kind='pod', obj2=None, wanted_modes='all', max_vecs_per_node=1000, verbose=True): """ Compute POD modes of the given fields using the snapshot method. Parameters ---------- obj : TemporalFields, Profile or Points object Fields to extract modes from obj2 : same as obj Only used as second dataset for BPOD kind : string, optional Kind of decomposition, can be 'pod' (default), 'bpod' or 'dmd'. wanted_modes : string or number or array of numbers If 'all', extract all modes, If a number, extract first modes, If an array, extract the associated modes. max_vecs_per_node : integer, optional Number of fields that can be charged in memory. (More is faster but can lead to MemoryError) verbose : boolean, optional If 'True', display information. Returns ------- modal_field : ModalField object . Notes ----- You can use partially masked fields as input. If so, the asked values are lineary interpolated before doing the decomposition. """ # check if modred is available if not MODRED: raise Exception("This feature need 'modred' to be installed") # Test parameters if not isinstance(obj, (TemporalFields)): raise TypeError() if kind == "bpod": if obj2 is None: raise ValueError() if not isinstance(obj2, obj.__class__): raise TypeError() if not obj2.shape == obj.shape: raise ValueError() if not isinstance(kind, STRINGTYPES): raise TypeError() if kind not in ['pod', 'bpod', 'dmd']: raise ValueError() if isinstance(wanted_modes, STRINGTYPES): if not wanted_modes == 'all': raise ValueError() wanted_modes = np.arange(len(obj.fields)) elif isinstance(wanted_modes, NUMBERTYPES): wanted_modes = np.arange(wanted_modes) elif isinstance(wanted_modes, ARRAYTYPES): wanted_modes = np.array(wanted_modes) if wanted_modes.min() < 0 or wanted_modes.max() > len(obj.fields): raise ValueError() else: raise TypeError() try: max_vecs_per_node = int(max_vecs_per_node) except: raise TypeError() # getting datas if isinstance(obj, TemporalScalarFields): obj_type = 'TSF' snaps, props = _tsf_to_POD(obj) if kind == "bpod": snaps2, _ = _tsf_to_POD(obj2) elif isinstance(obj, TemporalVectorFields): obj_type = 'TVF' snaps, props = _tvf_to_POD(obj) if kind == "bpod": snaps2, _ = _tvf_to_POD(obj2) else: raise TypeError() globals().update(props) # Setting the decomposition mode eigvals = None eigvect = None ritz_vals = None mode_norms = None growth_rate = None pulsation = None if kind == 'pod': my_decomp = modred.PODHandles(np.vdot, max_vecs_per_node=max_vecs_per_node, verbosity=verbose) eigvals, eigvect = my_decomp.compute_decomp(snaps) del snaps wanted_modes = wanted_modes[wanted_modes < len(eigvals)] eigvect = np.array(eigvect) eigvect = eigvect[:, wanted_modes] eigvals = Profile(wanted_modes, eigvals[wanted_modes], mask=False, unit_x=props['unit_times'], unit_y='') elif kind == 'bpod': my_decomp = modred.BPODHandles(np.vdot, max_vecs_per_node=max_vecs_per_node, verbosity=verbose) eigvect, eigvals, eigvect_l = my_decomp.compute_decomp(snaps, snaps2) del snaps del snaps2 wanted_modes = wanted_modes[wanted_modes < len(eigvals)] eigvect = np.array(eigvect) eigvect = eigvect[:, wanted_modes] eigvals = Profile(wanted_modes, eigvals[wanted_modes], mask=False, unit_x=props['unit_times'], unit_y='') elif kind == 'dmd': my_decomp = modred.DMDHandles(np.vdot, max_vecs_per_node=max_vecs_per_node, verbosity=verbose) ritz_vals, mode_norms, build_coeffs = my_decomp.compute_decomp(snaps) del snaps wanted_modes = wanted_modes[wanted_modes < len(ritz_vals)] # supplementary charac delta_t = props['times'][1] - props['times'][0] lambd_i = np.imag(ritz_vals) lambd_r = np.real(ritz_vals) lambd_mod = np.abs(ritz_vals) lambd_arg = np.zeros((len(ritz_vals))) mask = np.logical_and(lambd_i == 0, lambd_r <= 0) filt = np.logical_not(mask) lambd_arg[mask] = np.pi lambd_arg[filt] = 2*np.arctan(lambd_i[filt]/(lambd_r[filt] + lambd_mod[filt])) sigma = np.log(lambd_mod)/delta_t omega = lambd_arg/delta_t # creating profiles unit_times = props['unit_times'] ritz_vals = Profile(wanted_modes, ritz_vals[wanted_modes], mask=False, unit_x=unit_times, unit_y='') mode_norms = Profile(wanted_modes, mode_norms[wanted_modes], mask=False, unit_x=unit_times, unit_y='') growth_rate = Profile(wanted_modes, sigma[wanted_modes], mask=False, unit_x=unit_times, unit_y=1./unit_times) pulsation = Profile(wanted_modes, omega[wanted_modes], mask=False, unit_x=unit_times, unit_y=make_unit('rad')/unit_times) else: raise ValueError("Unknown kind of decomposition : {}".format(kind)) f_shape = props['f_shape'] unit_values = props['unit_values'] unit_times = props['unit_times'] times = props['times'] ind_fields = props['ind_fields'] # Decomposing and getting modes if kind in ['pod', 'dmd']: modes = [modred.VecHandleInMemory(np.zeros(f_shape)) for i in np.arange(len(wanted_modes))] my_decomp.compute_modes(wanted_modes, modes) elif kind in ['bpod']: modes = [modred.VecHandleInMemory(np.zeros(f_shape)) for i in np.arange(len(wanted_modes))] adj_modes = [modred.VecHandleInMemory(np.zeros(f_shape)) for i in np.arange(len(wanted_modes))] my_decomp.compute_direct_modes(wanted_modes, modes) my_decomp.compute_adjoint_modes(wanted_modes, adj_modes) # Getting temporal evolution temporal_prof = [] if kind in ['pod']: for n in np.arange(len(modes)): tmp_prof = eigvect[:, n]*eigvals.y[n]**.5 tmp_prof = Profile(times, tmp_prof, mask=False, unit_x=unit_times, unit_y=unit_values) temporal_prof.append(tmp_prof) if kind in ['bpod']: for n in np.arange(len(modes)): tmp_prof = eigvect[:, n]*eigvals.y[n]**.5 tmp_times = times[0:len(tmp_prof)] tmp_prof = Profile(tmp_times, tmp_prof, mask=False, unit_x=unit_times, unit_y=unit_values) temporal_prof.append(tmp_prof) elif kind == 'dmd': for n in np.arange(len(modes)): tmp_prof = np.real([ritz_vals.y[n]**(k) for k in ind_fields]) tmp_prof = Profile(times, tmp_prof, mask=False, unit_x=unit_times, unit_y=obj.unit_values) temporal_prof.append(tmp_prof) # Returning if obj_type == "TSF": modes_f = _POD_to_tsf(modes, props) elif obj_type == "TVF": modes_f = _POD_to_tvf(modes, props) del modes modal_field = ModalFields(kind, props['mean_field'], modes_f, wanted_modes, temporal_prof, eigvals=eigvals, eigvects=eigvect, ritz_vals=ritz_vals, mode_norms=mode_norms, growth_rate=growth_rate, pulsation=pulsation) return modal_field
# Define the handles for the snapshots num_vecs = 30 direct_snapshots = [ mr.VecHandleArrayText('direct_vec%d.txt' % i) for i in range(num_vecs) ] adjoint_snapshots = [ mr.VecHandleArrayText('adjoint_vec%d.txt' % i) for i in range(num_vecs) ] # Save arbitrary 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) num_modes = 10 mode_nums = list(range(num_modes)) direct_modes = [mr.VecHandleArrayText('direct_mode%d' % i) for i in mode_nums] adjoint_modes = [ mr.VecHandleArrayText('adjoint_mode%d' % i) for i in mode_nums ] my_BPOD.compute_direct_modes(mode_nums, direct_modes) my_BPOD.compute_adjoint_modes(mode_nums, adjoint_modes)
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) sing_vals, L_sing_vecs, R_sing_vecs = my_BPOD.compute_decomp( direct_snapshots, adjoint_snapshots) num_modes = 10 mode_nums = list(mr.range(num_modes)) direct_modes = [ mr.VecHandleArrayText('%s/direct_mode%d' % (out_dir, i)) for i in mode_nums ] adjoint_modes = [ mr.VecHandleArrayText('%s/adjoint_mode%d' % (out_dir, i)) for i in mode_nums ] my_BPOD.compute_direct_modes(mode_nums, direct_modes) my_BPOD.compute_adjoint_modes(mode_nums, adjoint_modes)