def compute(self, key, SAVE_IN_DICT=True, RAISE_ERROR=True): it = self.sim.time_stepping.it if key in self.vars_computed and it == self.it_computed[key]: return self.vars_computed[key] if key == "rotz": vx_fft = self.get_var("vx_fft") vy_fft = self.get_var("vy_fft") rotz_fft = self.oper.rotzfft_from_vxvyfft(vx_fft, vy_fft) result = self.oper.ifft3d(rotz_fft) elif key == "divh": vx_fft = self.get_var("vx_fft") vy_fft = self.get_var("vy_fft") divh_fft = self.oper.divhfft_from_vxvyfft(vx_fft, vy_fft) result = self.oper.ifft3d(divh_fft) else: to_print = 'Do not know how to compute "' + key + '".' if RAISE_ERROR: raise ValueError(to_print) else: mpi.printby0(to_print + "\nreturn an array of zeros.") result = self.oper.create_arrayX(value=0.0) if SAVE_IN_DICT: self.vars_computed[key] = result self.it_computed[key] = it return result
def modif_box_size(params, n0, n1, n2=None): """Modify box size, such that the aspect ratio is square / cube Parameters ---------- params : ParamContainer Input parameters n0 : int Number of grid points in 0-axis of the grid n1 : int Number of grid points in 1-axis of the grid n2 : Number of grid points in 2-axis of the grid Returns ------- """ if n2 is None: nx = n1 ny = n0 else: nx = n2 ny = n1 nz = n0 if nx != ny: if nx < ny: params.oper.Ly = params.oper.Ly * ny / nx else: params.oper.Lx = params.oper.Lx * nx / ny if n2 is None: mpi.printby0("nh = ({}, {}); Lh = ({}, {})".format( n0, n1, params.oper.Ly, params.oper.Lx)) if n2 is not None and n2 != n0: params.oper.Lz = params.oper.Lx * nz / nx mpi.printby0("n = ({}, {}, {}); L = ({}, {}, {})".format( n0, n1, n2, params.oper.Lz, params.oper.Ly, params.oper.Lx))
def __init__(self, output): params = output.sim.params pspatiotemp_spectra = params.output.spatio_temporal_spectra super().__init__( output, period_save=params.output.periods_save.spatio_temporal_spectra, has_to_plot_saved=pspatiotemp_spectra.HAS_TO_PLOT_SAVED, ) # Parameters self.time_start = pspatiotemp_spectra.time_start self.time_decimate = pspatiotemp_spectra.time_decimate self.spatial_decimate = pspatiotemp_spectra.spatial_decimate self.size_max_file = pspatiotemp_spectra.size_max_file self.kx_max = pspatiotemp_spectra.kx_max self.kz_max = pspatiotemp_spectra.kz_max # By default: kxmax_dealiasing or kymax_dealiasing if self.kx_max is None: self.kx_max = self.sim.oper.kxmax_dealiasing if self.kz_max is None: self.kz_max = self.sim.oper.kymax_dealiasing self.has_to_save = bool( params.output.periods_save.spatio_temporal_spectra) # Check: In restart... time_start == time last state. path_dir = Path(self.sim.output.path_run) path_spatio_temp_files = path_dir / "spatio_temporal" if sorted(path_spatio_temp_files.glob("spatio_temp*")): time_last_file = float( sorted(path_dir.glob("state_phys*"))[-1].stem.split( "state_phys_t")[1]) if round(self.time_start, 3) != time_last_file: self.time_start = time_last_file # Compute arrays nK0, nK1 = self.sim.oper.shapeK_seq # The maximum value kx_max should be the dealiased value if self.kx_max > self.sim.oper.kxmax_dealiasing: self.kx_max = self.sim.oper.kxmax_dealiasing # The maximum value kz_max should be the dealiased value if self.kz_max > self.sim.oper.kymax_dealiasing: self.kz_max = self.sim.oper.kymax_dealiasing # Modified values to take into account kx_max and kz_max self.nK0 = np.argmin(abs(self.sim.oper.kxE - self.kx_max)) self.nK1 = np.argmin(abs(self.sim.oper.kyE - self.kz_max)) nK0_dec = len(list(range(0, self.nK0, self.spatial_decimate))) nK1_dec = len(list(range(0, self.nK1, self.spatial_decimate))) # Compute size in bytes of one array # self.size_max_file is given in Mbytes. 1 Mbyte == 1024 ** 2 bytes nb_bytes = np.empty([nK0_dec, nK1_dec], dtype=complex).nbytes self.nb_arr_in_file = int(self.size_max_file * (1024**2) // nb_bytes) mpi.printby0("nb_arr_in_file", self.nb_arr_in_file) # Check: duration file <= duration simulation self.duration_file = (self.nb_arr_in_file * self.params.time_stepping.deltat0 * self.time_decimate) if (self.duration_file > self.params.time_stepping.t_end and self.has_to_save): raise ValueError( "The duration of the simulation is not enough to fill a file.") # Check: self.nb_arr_in_file should be > 0 if self.nb_arr_in_file <= 0 and self.has_to_save: raise ValueError("The size of the file should be larger.") else: # Create array 4D (2 keys, times, n0, n1) self.spatio_temp_new = np.empty( [2, self.nb_arr_in_file, nK0_dec, nK1_dec], dtype=complex) # Convert time_start to it_start. if not self.sim.time_stepping.it: self.it_start = int(self.time_start / self.params.time_stepping.deltat0) else: # If simulation starts from a specific time... self.it_start = self.sim.time_stepping.it + int( (self.time_start - round(self.sim.time_stepping.t, 3)) / self.params.time_stepping.deltat0) if self.it_start < self.sim.time_stepping.it: self.it_start = self.sim.time_stepping.it # Create empty array with times self.times_arr = np.empty([self.nb_arr_in_file]) self.its_arr = np.empty([self.nb_arr_in_file]) if params.time_stepping.USE_CFL and self.has_to_save: raise ValueError( "To compute the spatio temporal: \n" "USE_CFL = FALSE and periods_save.spatio_temporal_spectra > 0") # Create directory to save files dir_name = "spatio_temporal" self.path_dir = Path(self.sim.output.path_run) / dir_name if self.has_to_save and mpi.rank == 0: self.path_dir.mkdir(exist_ok=True) # Start loop in _online_save self.it_last_run = self.it_start self.nb_times_in_spatio_temp = 0
def __init__(self, sim): super().__init__(sim) params = sim.params self.forcing_fft = SetOfVariables( like=sim.state.state_spect, info="forcing_fft", value=0.0 ) if params.forcing.nkmax_forcing < params.forcing.nkmin_forcing: raise ValueError( "params.forcing.nkmax_forcing < \n" "params.forcing.nkmin_forcing" ) self.kmax_forcing = self.oper.deltak * params.forcing.nkmax_forcing self.kmin_forcing = self.oper.deltak * params.forcing.nkmin_forcing self.forcing_rate = params.forcing.forcing_rate if params.forcing.key_forced is not None: self.key_forced = params.forcing.key_forced else: self.key_forced = self._key_forced_default try: n = 2 * fftw_grid_size(params.forcing.nkmax_forcing) except ImportError: warn("To use smaller forcing arrays: pip install pulp") i = 0 while 2 * params.forcing.nkmax_forcing > 2 ** i: i += 1 n = 2 ** i self._check_forcing_shape([n], sim.oper.shapeX_seq) try: angle = self.params.forcing[self.tag].angle except AttributeError: pass else: if isinstance(angle, str): if angle.endswith("°"): angle = radians(float(angle[:-1])) else: raise ValueError( "Angle should be a string with \n" + "the degree symbol or a float in radians" ) self.angle = angle self.kxmax_forcing = np.sin(angle) * self.kmax_forcing self.kymax_forcing = np.cos(angle) * self.kmax_forcing if mpi.rank == 0: params_coarse = deepcopy(params) params_coarse.oper.nx = n # The "+ 1" aims to give some gap between the kxmax and # the boundary of the oper_coarse. try: params_coarse.oper.nx = 2 * fftw_grid_size( int(self.kxmax_forcing / self.oper.deltakx) + 1 ) except AttributeError: pass try: params_coarse.oper.ny = n try: params_coarse.oper.ny = 2 * fftw_grid_size( int(self.kymax_forcing / self.oper.deltaky) + 1 ) except AttributeError: pass except AttributeError: pass try: params_coarse.oper.nz = n except AttributeError: pass params_coarse.oper.type_fft = "sequential" params_coarse.oper.coef_dealiasing = 1.0 self.oper_coarse = sim.oper.__class__(params=params_coarse) self.shapeK_loc_coarse = self.oper_coarse.shapeK_loc self.COND_NO_F = self._compute_cond_no_forcing() self.nb_forced_modes = ( self.COND_NO_F.size - np.array(self.COND_NO_F, dtype=np.int32).sum() ) if not self.nb_forced_modes: raise ValueError("0 modes forced.") try: hasattr(self, "plot_forcing_region") except NotImplementedError: pass else: mpi.printby0( "To plot the forcing modes, you can use:\n" "sim.forcing.forcing_maker.plot_forcing_region()" ) self.ind_forcing = ( np.logical_not(self.COND_NO_F).flatten().nonzero()[0] ) self.fstate_coarse = sim.state.__class__(sim, oper=self.oper_coarse) else: self.shapeK_loc_coarse = None if mpi.nb_proc > 1: self.shapeK_loc_coarse = mpi.comm.bcast( self.shapeK_loc_coarse, root=0 )
fx = sigma * maskx * (coef_forcing_time_x * vxtarget - vx) fy = sigma * masky * (coef_forcing_time_y * vytarget - vy) result = {"vx_fft": fx, "vy_fft": fy} return result sim.forcing.forcing_maker.monkeypatch_compute_forcing_each_time( compute_forcing_each_time) # finally we start the simulation sim.time_stepping.start() mpi.printby0(f""" # To visualize the output with Paraview, create a file states_phys.xmf with: fluidsim-create-xml-description {sim.output.path_run} # To visualize with fluidsim: cd {sim.output.path_run} ipython # in ipython: from fluidsim import load_sim_for_plot sim = load_sim_for_plot() sim.output.phys_fields.set_equation_crosssection('x={lx/2}') sim.output.phys_fields.animate('b') """)
params.forcing.nkmax_forcing = 2.1 params.forcing.forcing_rate = forcing_rate params.forcing.key_forced = key_forced params.forcing.tcrandom_anisotropic.kz_negative_enable = neg_enable params.forcing.normalized.constant_rate_of = "energy" params.output.sub_directory = "examples" params.output.periods_print.print_stdout = 0.5 params.output.periods_save.phys_fields = 0.5 params.output.periods_save.spatial_means = 0.2 params.output.periods_save.spectra = 0.5 params.output.periods_save.spect_energy_budg = 0.5 params.output.periods_save.spectra_multidim = 1.0 params.output.periods_save.increments = 1.0 sim = Simul(params) sim.time_stepping.start() mpi.printby0("\nTo display a video of this simulation, you can do:\n" f"cd {sim.output.path_run}" + """ ipython # then in ipython (copy the 3 lines in the terminal): from fluidsim import load_sim_for_plot sim = load_sim_for_plot() sim.output.phys_fields.animate('b', dt_frame_in_sec=0.1, dt_equations=0.1) """)
if __name__ == "__main__": sim.time_stepping.start() from fluiddyn.util.mpi import printby0 printby0(f""" To visualize the output with Paraview, create a file states_phys.xmf with: fluidsim-create-xml-description {sim.output.path_run} # To visualize with fluidsim: cd {sim.output.path_run} ipython # in ipython: from fluidsim import load_sim_for_plot sim = load_sim_for_plot() sim.output.phys_fields.set_equation_crosssection(f'x={{sim.oper.Lx/4}}') sim.output.phys_fields.animate('vx') sim.output.phys_fields.plot(field="vx", time=10) sim.output.spatial_means.plot() sim.output.spectra.plot1d(tmin=12, tmax=16, coef_compensate=5/3) """)
import os import sys if "FLUIDSIM_PATH" in os.environ: os.environ["TRANSONIC_DIR"] = str( Path(os.environ["FLUIDSIM_PATH"]) / ".transonic") _is_testing = False if any( any(test_tool in arg for arg in sys.argv) for test_tool in ("pytest", "unittest", "fluidsim-test", "coverage")): _is_testing = True from fluiddyn.util import mpi mpi.printby0("Fluidsim guesses that it is tested so it " "loads the Agg Matplotlib backend.") import matplotlib matplotlib.use("Agg") import matplotlib.pyplot as plt def _show(*args, **kwargs): pass plt.show = _show if all(env_var not in os.environ for env_var in ("FLUID_COMPILE_CACHEDJIT", "TRANSONIC_COMPILE_JIT")): mpi.printby0("Compilation of jit functions disabled.") from transonic import set_compile_jit
$$ {\eta_n}^{n - 2/3} = \frac{\varepsilon^{1/3}}{\nu_n} $$ We want that $dx < \eta_n$, so we choose $\nu_n$ such that $dx = C \eta_n$ where $C$ is a constant of order 1. """ n = 8 C = 1.0 dx = Lx / nx B = 1 D = 1 eps = 1e-2 * B**(3 / 2) * D**(1 / 2) params.nu_8 = (dx / C)**((3 * n - 2) / 3) * eps**(1 / 3) printby0(f"nu_8 = {params.nu_8:.3e}") params.time_stepping.USE_T_END = True params.time_stepping.t_end = 10.0 params.init_fields.type = "in_script" params.output.periods_print.print_stdout = 1e-1 params.output.periods_save.phys_fields = 0.5 params.output.periods_save.spatial_means = 0.1 sim = Simul(params) # here we have to initialize the flow fields
# don't import any random modules in a Pythran file. Here, no problem! from fluiddyn.util import mpi from transonic import boost # transonic def func(float[][], float[][]) # transonic def func(int[][], float[][]) @boost def func(a, b): return (a * np.log(b)).max() if __name__ == "__main__": n0, n1 = 100, 200 a0 = np.random.rand(n0, n1) a1 = np.random.rand(n0, n1) result = func(a0, a1) if mpi.nb_proc > 1: result = mpi.comm.allreduce(result, op=mpi.MPI.MAX) mpi.printby0(result) a0 = (1000 * a0).astype(int) result = func(a0, a1) if mpi.nb_proc > 1: result = mpi.comm.allreduce(result, op=mpi.MPI.MAX) mpi.printby0(result)