diff --git a/libpympb/pympb.cpp b/libpympb/pympb.cpp index 6bfe04ae7..77c6c9979 100644 --- a/libpympb/pympb.cpp +++ b/libpympb/pympb.cpp @@ -694,12 +694,12 @@ void mode_solver::init(int p, bool reset_fields, geometric_object_list geometry, n[1] = grid_size.y; n[2] = grid_size.z; - if (target_freq != 0.0 && mpb_verbosity >= 2) { meep::master_printf("Target frequency is %g\n", target_freq); } + if (target_freq != 0.0 && mpb_verbosity >= 1) { meep::master_printf("Target frequency is %g\n", target_freq); } int true_rank = n[2] > 1 ? 3 : (n[1] > 1 ? 2 : 1); if (true_rank < dimensions) { dimensions = true_rank; } else if (true_rank > dimensions) { - if (mpb_verbosity >= 2) + if (mpb_verbosity >= 1) meep::master_printf("WARNING: rank of grid is > dimensions.\n" " setting extra grid dims. to 1.\n"); // force extra dims to be 1 @@ -707,7 +707,7 @@ void mode_solver::init(int p, bool reset_fields, geometric_object_list geometry, if (dimensions <= 1) { n[1] = 1; } } - if (mpb_verbosity >= 2) { + if (mpb_verbosity >= 1) { meep::master_printf("Working in %d dimensions.\n", dimensions); meep::master_printf("Grid size is %d x %d x %d.\n", n[0], n[1], n[2]); } @@ -721,7 +721,7 @@ void mode_solver::init(int p, bool reset_fields, geometric_object_list geometry, block_size = (num_bands - block_size - 1) / (-block_size); block_size = (num_bands + block_size - 1) / block_size; } - if (mpb_verbosity >= 2) + if (mpb_verbosity >= 1) meep::master_printf("Solving for %d bands at a time.\n", block_size); } else { @@ -762,7 +762,7 @@ void mode_solver::init(int p, bool reset_fields, geometric_object_list geometry, srand(314159); // * (rank + 1)); } - if (mpb_verbosity >= 2) + if (mpb_verbosity >= 1) meep::master_printf("Creating Maxwell data...\n"); mdata = create_maxwell_data(n[0], n[1], n[2], &local_N, &N_start, &alloc_N, block_size, NUM_FFT_BANDS); @@ -774,7 +774,7 @@ void mode_solver::init(int p, bool reset_fields, geometric_object_list geometry, if (check_maxwell_dielectric(mdata, 0)) { meep::abort("invalid dielectric function for MPB"); } if (!have_old_fields) { - if (mpb_verbosity >= 2) + if (mpb_verbosity >= 1) meep::master_printf("Allocating fields...\n"); int N = n[0] * n[1] * n[2]; @@ -814,14 +814,14 @@ void mode_solver::init_epsilon(geometric_object_list *geometry) { mpb_real no_size_y = geometry_lattice.size.y == 0 ? 1 : geometry_lattice.size.y; mpb_real no_size_z = geometry_lattice.size.z == 0 ? 1 : geometry_lattice.size.z; - if (mpb_verbosity >= 2) + if (mpb_verbosity >= 1) meep::master_printf("Mesh size is %d.\n", mesh_size); Rm.c0 = vector3_scale(no_size_x, geometry_lattice.basis.c0); Rm.c1 = vector3_scale(no_size_y, geometry_lattice.basis.c1); Rm.c2 = vector3_scale(no_size_z, geometry_lattice.basis.c2); - if (mpb_verbosity >= 2) { + if (mpb_verbosity >= 1) { meep::master_printf("Lattice vectors:\n"); meep::master_printf(" (%g, %g, %g)\n", Rm.c0.x, Rm.c0.y, Rm.c0.z); meep::master_printf(" (%g, %g, %g)\n", Rm.c1.x, Rm.c1.y, Rm.c1.z); @@ -829,11 +829,11 @@ void mode_solver::init_epsilon(geometric_object_list *geometry) { } vol = fabs(matrix3x3_determinant(Rm)); - if (mpb_verbosity >= 2) + if (mpb_verbosity >= 1) meep::master_printf("Cell volume = %g\n", vol); Gm = matrix3x3_inverse(matrix3x3_transpose(Rm)); - if (mpb_verbosity >= 2) { + if (mpb_verbosity >= 1) { meep::master_printf("Reciprocal lattice vectors (/ 2 pi):\n"); meep::master_printf(" (%g, %g, %g)\n", Gm.c0.x, Gm.c0.y, Gm.c0.z); meep::master_printf(" (%g, %g, %g)\n", Gm.c1.x, Gm.c1.y, Gm.c1.z); @@ -845,7 +845,7 @@ void mode_solver::init_epsilon(geometric_object_list *geometry) { geom_fix_object_list(*geometry); - if (mpb_verbosity >= 2) + if (mpb_verbosity >= 1) meep::master_printf("Geometric objects:\n"); if (meep::am_master()) { for (int i = 0; i < geometry->num_items; ++i) { @@ -886,7 +886,7 @@ void mode_solver::init_epsilon(geometric_object_list *geometry) { } if (verbose && meep::am_master()) { - if (mpb_verbosity >= 2) + if (mpb_verbosity >= 1) meep::master_printf("Geometry object bounding box tree:\n"); display_geom_box_tree(5, geometry_tree); } @@ -894,7 +894,7 @@ void mode_solver::init_epsilon(geometric_object_list *geometry) { int tree_depth; int tree_nobjects; geom_box_tree_stats(geometry_tree, &tree_depth, &tree_nobjects); - if (mpb_verbosity >= 2) + if (mpb_verbosity >= 1) meep::master_printf("Geometric object tree has depth %d and %d object nodes" " (vs. %d actual objects)\n", tree_depth, tree_nobjects, geometry->num_items); @@ -919,13 +919,13 @@ void mode_solver::reset_epsilon(geometric_object_list *geometry) { // if (!mu_input_file.empty()) { // } - if (mpb_verbosity >= 2) + if (mpb_verbosity >= 1) meep::master_printf("Initializing epsilon function...\n"); set_maxwell_dielectric(mdata, mesh, R, G, dielectric_function, mean_epsilon_func, static_cast(this)); if (has_mu(geometry)) { - if (mpb_verbosity >= 2) + if (mpb_verbosity >= 1) meep::master_printf("Initializing mu function...\n"); eps = false; set_maxwell_mu(mdata, mesh, R, G, dielectric_function, mean_epsilon_func, @@ -970,7 +970,6 @@ bool mode_solver::material_has_mu(void *mt) { } void mode_solver::set_parity(integer p) { - if (!mdata) { meep::master_fprintf(stderr, "init must be called before set-parity!\n"); return; @@ -983,7 +982,7 @@ void mode_solver::set_parity(integer p) { meep::master_fprintf(stderr, "k vector incompatible with parity\n"); exit(EXIT_FAILURE); } - if (mpb_verbosity >= 2) + if (mpb_verbosity >= 1) meep::master_printf("Solving for band polarization: %s.\n", parity_string(mdata)); last_parity = p; @@ -1002,7 +1001,7 @@ void mode_solver::set_kpoint_index(int i) { kpoint_index = i; } void mode_solver::randomize_fields() { if (!mdata) { return; } - if (mpb_verbosity >= 2) + if (mpb_verbosity >= 1) meep::master_printf("Initializing fields to random numbers...\n"); for (int i = 0; i < H.n * H.p; ++i) { @@ -1011,18 +1010,17 @@ void mode_solver::randomize_fields() { } void mode_solver::solve_kpoint(vector3 kvector) { - // if we get too close to singular k==0 point, just set k=0 exploit our // special handling of this k if (vector3_norm(kvector) < 1e-10) { kvector.x = kvector.y = kvector.z = 0; } - if (mpb_verbosity >= 2) + if (mpb_verbosity >= 1) meep::master_printf("solve_kpoint (%g,%g,%g):\n", kvector.x, kvector.y, kvector.z); curfield_reset(); if (num_bands == 0) { - if (mpb_verbosity >= 2) + if (mpb_verbosity >= 1) meep::master_printf(" num-bands is zero, not solving for any bands\n"); return; } @@ -1034,7 +1032,7 @@ void mode_solver::solve_kpoint(vector3 kvector) { // If this is the first k point, print out a header line for the frequency // grep data. - if (mpb_verbosity >= 2) { + if (mpb_verbosity >= 1) { if (!kpoint_index && meep::am_master()) { meep::master_printf("%sfreqs:, k index, k1, k2, k3, kmag/2pi", parity_string(mdata)); @@ -1056,7 +1054,7 @@ void mode_solver::solve_kpoint(vector3 kvector) { // TODO: Get flags from python int flags = EIGS_DEFAULT_FLAGS; - if (verbose || mpb_verbosity >= 2) { flags |= EIGS_VERBOSE; } + if (verbose || mpb_verbosity >= 1) { flags |= EIGS_VERBOSE; } // Constant (zero frequency) bands at k=0 are handled specially, so remove // them from the solutions for the eigensolver. @@ -1101,7 +1099,7 @@ void mode_solver::solve_kpoint(vector3 kvector) { evectmatrix_resize(&Hblock, num_bands - ib, 0); } - if (mpb_verbosity >= 2) + if (mpb_verbosity >= 1) meep::master_printf("Solving for bands %d to %d...\n", ib + 1, ib + Hblock.p); constraints = NULL; @@ -1160,14 +1158,14 @@ void mode_solver::solve_kpoint(vector3 kvector) { evect_destroy_constraints(constraints); - if (mpb_verbosity >= 2) + if (mpb_verbosity >= 1) meep::master_printf("Finished solving for bands %d to %d after %d iterations.\n", ib + 1, ib + Hblock.p, num_iters); total_iters += num_iters * Hblock.p; } - if (num_bands - ib0 > Hblock.alloc_p && mpb_verbosity >= 2) { + if (num_bands - ib0 > Hblock.alloc_p && mpb_verbosity >= 1) { meep::master_printf("Finished k-point with %g mean iterations/band.\n", total_iters * 1.0 / num_bands); } @@ -1204,17 +1202,17 @@ void mode_solver::solve_kpoint(vector3 kvector) { set_kpoint_index(kpoint_index + 1); - if (mpb_verbosity >= 2) + if (mpb_verbosity >= 1) meep::master_printf("%sfreqs:, %d, %g, %g, %g, %g", parity_string(mdata), kpoint_index, (double)k[0], (double)k[1], (double)k[2], vector3_norm(matrix3x3_vector3_mult(Gm, kvector))); for (int i = 0; i < num_bands; ++i) { freqs[i] = negative_epsilon_ok ? eigvals[i] : sqrt(eigvals[i]); - if (mpb_verbosity >= 2) + if (mpb_verbosity >= 1) meep::master_printf(", %g", freqs[i]); } - if (mpb_verbosity >= 2) + if (mpb_verbosity >= 1) meep::master_printf("\n"); eigensolver_flops = evectmatrix_flops; @@ -1268,7 +1266,7 @@ void mode_solver::get_epsilon() { eps_mean /= N; eps_inv_mean = N / eps_inv_mean; - if (mpb_verbosity >= 2) + if (mpb_verbosity >= 1) meep::master_printf("epsilon: %g-%g, mean %g, harm. mean %g, %g%% > 1, %g%% \"fill\"\n", eps_low, eps_high, eps_mean, eps_inv_mean, (100.0 * fill_count) / N, eps_high == eps_low ? 100.0 @@ -1324,7 +1322,7 @@ void mode_solver::get_mu() { eps_mean /= N; mu_inv_mean = N / mu_inv_mean; - if (mpb_verbosity >= 2) + if (mpb_verbosity >= 1) meep::master_printf("mu: %g-%g, mean %g, harm. mean %g, %g%% > 1, %g%% \"fill\"\n", eps_low, eps_high, eps_mean, mu_inv_mean, (100.0 * fill_count) / N, eps_high == eps_low ? 100.0 @@ -1392,7 +1390,6 @@ void mode_solver::get_efield(int band) { } void mode_solver::get_efield_from_dfield() { - if (!curfield || curfield_type != 'd') { meep::master_fprintf(stderr, "get_dfield must be called before get-efield-from-dfield!\n"); return; @@ -1403,7 +1400,6 @@ void mode_solver::get_efield_from_dfield() { } void mode_solver::get_dfield(int band) { - if (!kpoint_index) { meep::master_fprintf(stderr, "solve_kpoint must be called before get_dfield\n"); return; @@ -1653,15 +1649,15 @@ std::vector mode_solver::compute_field_energy() { mpb_real comp_sum[6]; mpb_real energy_sum = compute_field_energy_internal(comp_sum); - if (mpb_verbosity >= 2) + if (mpb_verbosity >= 1) meep::master_printf("%c-energy-components:, %d, %d", curfield_type, kpoint_index, curfield_band); for (int i = 0; i < 6; ++i) { comp_sum[i] /= (energy_sum == 0 ? 1 : energy_sum); - if (i % 2 == 1 && mpb_verbosity >= 2) { + if (i % 2 == 1 && mpb_verbosity >= 1) { meep::master_printf(", %g", comp_sum[i] + comp_sum[i - 1]); } } - if (mpb_verbosity >= 2) + if (mpb_verbosity >= 1) meep::master_printf("\n"); /* The return value is a list of 7 items: the total energy, @@ -2076,7 +2072,7 @@ void mode_solver::fix_field_phase() { ASSIGN_SCALAR(phase, SCALAR_RE(phase) * maxabs_sign, SCALAR_IM(phase) * maxabs_sign); - if (mpb_verbosity >= 2) + if (mpb_verbosity >= 1) meep::master_printf("Fixing %c-field (band %d) phase by %g + %gi; " "max ampl. = %g\n", curfield_type, curfield_band, SCALAR_RE(phase), SCALAR_IM(phase), maxabs); @@ -2659,7 +2655,7 @@ void map_data(mpb_real *d_in_re, int size_in_re, mpb_real *d_in_im, int size_in_ #undef IN_INDEX } - if (verbose || mpb_verbosity >= 2) { + if (verbose || mpb_verbosity >= 1) { meep::master_printf("real part range: %g .. %g\n", min_out_re, max_out_re); if (size_out_im > 0) meep::master_printf("imag part range: %g .. %g\n", min_out_im, max_out_im); } diff --git a/python/Makefile.am b/python/Makefile.am index 54c3c9f1a..3b2d167b6 100644 --- a/python/Makefile.am +++ b/python/Makefile.am @@ -154,7 +154,8 @@ HPPFILES= \ $(top_srcdir)/src/meep/vec.hpp \ $(top_srcdir)/src/meep/mympi.hpp \ $(top_srcdir)/src/meepgeom.hpp \ - $(top_srcdir)/src/material_data.hpp + $(top_srcdir)/src/material_data.hpp \ + $(top_srcdir)/src/adjust_verbosity.hpp meep-python.cxx: $(MEEP_SWIG_SRC) $(HPPFILES) $(SWIG) -Wextra $(AM_CPPFLAGS) -outdir $(builddir) -c++ -nofastunpack -python -o $@ $(srcdir)/meep.i diff --git a/python/mpb.i b/python/mpb.i index f96319cd9..98060a7d2 100644 --- a/python/mpb.i +++ b/python/mpb.i @@ -349,10 +349,15 @@ static mpb_real field_integral_energy_callback(mpb_real energy, mpb_real epsilon %rename(verbosity) mpb_verbosity; %include "pympb.hpp" +const int MPB_VERSION_MAJOR; +const int MPB_VERSION_MINOR; +const int MPB_VERSION_PATCH; %pythoncode %{ + __version__ = (_mpb.cvar.MPB_VERSION_MAJOR, _mpb.cvar.MPB_VERSION_MINOR, _mpb.cvar.MPB_VERSION_PATCH) + from meep.verbosity_mgr import Verbosity - verbosity = Verbosity(_mpb.cvar, 1) + verbosity = Verbosity(_mpb.cvar, 'mpb', 1) from .solver import ( MPBArray, diff --git a/python/simulation.py b/python/simulation.py index 7c1e19546..50817f3f0 100644 --- a/python/simulation.py +++ b/python/simulation.py @@ -38,7 +38,7 @@ except ImportError: do_progress = False -verbosity = Verbosity(mp.cvar, 1) +verbosity = Verbosity(mp.cvar, 'meep', 1) # Send output from Meep, ctlgeom, and MPB to Python's stdout @@ -1634,7 +1634,7 @@ def _compute_fragment_stats(self, gv): return stats def _init_structure(self, k=False): - if verbosity > 0: + if verbosity.meep > 0: print('-' * 11) print('Initializing structure...') @@ -1657,7 +1657,7 @@ def _init_structure(self, k=False): if self.collect_stats and isinstance(self.default_material, mp.Medium): self.fragment_stats = self._compute_fragment_stats(gv) - if self._output_stats and isinstance(self.default_material, mp.Medium) and verbosity > 0: + if self._output_stats and isinstance(self.default_material, mp.Medium) and verbosity.meep > 0: stats = self._compute_fragment_stats(gv) print("STATS: aniso_eps: {}".format(stats.num_anisotropic_eps_pixels)) print("STATS: anis_mu: {}".format(stats.num_anisotropic_mu_pixels)) @@ -1929,7 +1929,7 @@ def use_real(self): if use_real(self): self.fields.use_real_fields() - elif verbosity > 0: + elif verbosity.meep > 0: print("Meep: using complex fields.") if self.k_point: @@ -2133,7 +2133,7 @@ def use_output_directory(self, dname=''): closure = {'trashed': False} def hook(): - if verbosity > 0: + if verbosity.meep > 0: print("Meep: using output directory '{}'".format(dname)) self.fields.set_output_directory(dname) if not closure['trashed']: @@ -2194,7 +2194,7 @@ def stop_cond(sim): self.progress.value = t0 + stop_time self.progress.description = "100% done " - if verbosity > 0: + if verbosity.meep > 0: print("run {} finished at t = {} ({} timesteps)".format(self.run_index, self.meep_time(), self.fields.t)) self.run_index += 1 @@ -4230,7 +4230,7 @@ def _stop(sim): closure['cur_max'] = 0 closure['t0'] = sim.round_time() closure['max_abs'] = max(closure['max_abs'], old_cur) - if closure['max_abs'] != 0 and verbosity > 0: + if closure['max_abs'] != 0 and verbosity.meep > 0: fmt = "field decay(t = {}): {} / {} = {}" print(fmt.format(sim.meep_time(), old_cur, closure['max_abs'], old_cur / closure['max_abs'])) return old_cur <= closure['max_abs'] * decay_by @@ -4348,7 +4348,7 @@ def _disp(sim): sim.progress.value = val1 sim.progress.description = "{}% done ".format(int(val2)) - if verbosity > 0: + if verbosity.meep > 0: print(msg_fmt.format(val1, t, val2, val3, val4)) closure['tlast'] = t1 diff --git a/python/solver.py b/python/solver.py index 90dd0a212..38f31bf5f 100644 --- a/python/solver.py +++ b/python/solver.py @@ -510,7 +510,7 @@ def update_brd(brd, freqs, br_start): return update_brd(brd, freqs, []) def output_band_range_data(self, br_data): - if verbosity >= 2: + if verbosity.mpb >= 1: for tup, band in zip(br_data, range(1, len(br_data) + 1)): fmt = "Band {} range: {} at {} to {} at {}" min_band, max_band = tup @@ -537,7 +537,7 @@ def ogaps(br_cur, br_rest, i, gaps): else: gap_size = ((200 * (br_rest_min_f - br_cur_max_f)) / (br_rest_min_f + br_cur_max_f)) - if verbosity >= 2: + if verbosity.mpb >= 1: fmt = "Gap from band {} ({}) to band {} ({}), {}%" print(fmt.format(i, br_cur_max_f, i + 1, br_rest_min_f, gap_size)) return ogaps(br_rest[0], br_rest[1:], i + 1, @@ -642,7 +642,7 @@ def _output_complex_scalar_field(self, fname_prefix, output_k): self.freqs[curfield_band - 1] ) fname = self._create_fname(fname, fname_prefix, True) - if verbosity >= 2: + if verbosity.mpb >= 1: print("Outputting complex scalar field to {}...".format(fname)) with h5py.File(fname, 'w') as f: @@ -676,7 +676,7 @@ def _output_vector_field(self, curfield_type, fname_prefix, output_k, component) ) fname = self._create_fname(fname, fname_prefix, True) - if verbosity >= 2: + if verbosity.mpb >= 1: print("Outputting fields to {}...".format(fname)) with h5py.File(fname, 'w') as f: @@ -721,7 +721,7 @@ def _output_scalar_field(self, curfield_type, fname_prefix): parity_suffix = False if curfield_type in 'mn' else True fname = self._create_fname(fname, fname_prefix, parity_suffix) - if verbosity >= 2: + if verbosity.mpb >= 1: print("Outputting {}...".format(fname)) with h5py.File(fname, 'w') as f: @@ -810,7 +810,7 @@ def randomize_fields(self): def display_kpoint_data(self, name, data): k_index = self.mode_solver.get_kpoint_index() - if verbosity >= 2: + if verbosity.mpb >= 1: print("{}{}:, {}".format(self.parity, name, k_index), end='') for d in data: @@ -826,7 +826,7 @@ def display_eigensolver_stats(self): min_iters = min(self.eigensolver_iters) max_iters = max(self.eigensolver_iters) mean_iters = np.mean(self.eigensolver_iters) - if verbosity >= 2: + if verbosity.mpb >= 1: fmt = "eigensolver iterations for {} kpoints: {}-{}, mean = {}" print(fmt.format(num_runs, min_iters, max_iters, mean_iters), end='') @@ -834,15 +834,15 @@ def display_eigensolver_stats(self): idx1 = num_runs // 2 idx2 = ((num_runs + 1) // 2) - 1 median_iters = 0.5 * (sorted_iters[idx1] + sorted_iters[idx2]) - if verbosity >= 2: + if verbosity.mpb >= 1: print(", median = {}".format(median_iters)) mean_flops = self.eigensolver_flops / (num_runs * mean_iters) - if verbosity >= 2: + if verbosity.mpb >= 1: print("mean flops per iteration = {}".format(mean_flops)) mean_time = self.total_run_time / (mean_iters * num_runs) - if verbosity >= 2: + if verbosity.mpb >= 1: print("mean time per iteration = {} s".format(mean_time)) def _get_grid_size(self): @@ -896,7 +896,7 @@ def run_parity(self, p, reset_fields, *band_functions): init_time = time.time() - if verbosity >= 2: + if verbosity.mpb >= 1: print("Initializing eigensolver data") print("Computing {} bands with {} tolerance".format(self.num_bands, self.tolerance)) @@ -905,7 +905,7 @@ def run_parity(self, p, reset_fields, *band_functions): if isinstance(reset_fields, basestring): self.load_eigenvectors(reset_fields) - if verbosity >= 2: + if verbosity.mpb >= 1: print("{} k-points".format(len(self.k_points))) for kp in self.k_points: @@ -924,7 +924,7 @@ def run_parity(self, p, reset_fields, *band_functions): solve_kpoint_time = time.time() self.mode_solver.solve_kpoint(k) self.iterations = self.mode_solver.get_iterations() - if verbosity >= 2: + if verbosity.mpb >= 1: print("elapsed time for k point: {}".format(time.time() - solve_kpoint_time)) self.freqs = self.get_freqs() self.all_freqs[i, :] = np.array(self.freqs) @@ -952,12 +952,12 @@ def run_parity(self, p, reset_fields, *band_functions): self.gap_list = [] end = time.time() - start - if verbosity >= 2: + if verbosity.mpb >= 1: print("total elapsed time for run: {}".format(end)) self.total_run_time += end self.eigensolver_flops = self.mode_solver.get_eigensolver_flops() self.parity = self.mode_solver.get_parity_string() - if verbosity >= 2: + if verbosity.mpb >= 1: print("done") def run(self, *band_functions): @@ -1024,7 +1024,7 @@ def _rootfun(k): # First, look in the cached table tab_val = bktab.get((b, k), None) if tab_val: - if verbosity >= 2: + if verbosity.mpb >= 1: print("find-k {} at {}: {} (cached)".format(b, k, tab_val[0])) return tab_val # Otherwise, compute bands and cache results @@ -1046,7 +1046,7 @@ def _rootfun(k): bktab[(_b, k)] = (_f - omega, _v) fun = self.freqs[-1] - omega - if verbosity >= 2: + if verbosity.mpb >= 1: print("find-k {} at {}: {}".format(b, k, fun)) return (fun, v[-1]) @@ -1075,7 +1075,7 @@ def bfunc(ms, b_prime): self.num_bands = num_bands_save self.k_points = kpoints_save ks = list(reversed(ks)) - if verbosity >= 2: + if verbosity.mpb >= 1: print("{}kvals:, {}, {}, {}".format(self.parity, omega, band_min, band_max), end='') for k in korig: print(", {}".format(k), end='') @@ -1239,7 +1239,7 @@ def _output(ms, which_band): ms.get_dfield(which_band, False) ms.compute_field_energy() energy = ms.compute_energy_in_objects(objects) - if verbosity >= 2: + if verbosity.mpb >= 1: fmt = "dpwr:, {}, {}, {} " print(fmt.format(which_band, ms.freqs[which_band - 1], energy)) if energy >= min_energy: diff --git a/python/tests/test_verbosity_mgr.py b/python/tests/test_verbosity_mgr.py new file mode 100644 index 000000000..da5f4b432 --- /dev/null +++ b/python/tests/test_verbosity_mgr.py @@ -0,0 +1,71 @@ +import unittest +from meep.verbosity_mgr import Verbosity + +class MyCvar: + def __init__(self): self.verbosity = 1 + + +class TestVerbosity(unittest.TestCase): + + def setUp(self): + Verbosity.reset() + self.v1 = Verbosity(name='foo') + self.v2 = Verbosity(MyCvar(), 'bar') + + + def test_identity(self): + # Ensure each verbosity is really the same singleton instance + v1, v2 = self.v1, self.v2 + self.assertTrue(v1 is v2) + self.assertEqual(id(v1), id(v2)) + self.assertEqual(v1.get_all(), [1,1]) + + + def test_initial_value(self): + v1, v2 = self.v1, self.v2 + self.assertEqual(v1.get(), 1) + v2.set(2) + self.assertEqual(v1.get(), 2) + + + def test_properties(self): + v1, v2 = self.v1, self.v2 + self.assertEqual(v1.foo, 1) + self.assertEqual(v1.bar, 1) + v1.foo = 2 + v2.bar = 3 + self.assertEqual(v2.foo, 2) + self.assertEqual(v2.bar, 3) + + + def test_operators(self): + v1, v2 = self.v1, self.v2 + + self.assertTrue(v1 == 1) + self.assertFalse(v1 == 2) + self.assertFalse(v1 > 1) + self.assertTrue(v1 < 3) + self.assertFalse(v1 >= 2) + self.assertTrue(v1 <= 1) + + v1(3) + self.assertFalse(v2 == 1) + self.assertFalse(v2 == 2) + self.assertTrue(v2 == 3) + + def test_out_of_range(self): + v1, v2 = self.v1, self.v2 + + with self.assertRaises(ValueError): + v1.set(5) + with self.assertRaises(ValueError): + v1.set(-5) + with self.assertRaises(ValueError): + v2.foo = 5 + with self.assertRaises(ValueError): + v2.bar = -5 + + + +if __name__ == '__main__': + unittest.main() diff --git a/python/verbosity_mgr.py b/python/verbosity_mgr.py index 7d7037015..825779744 100644 --- a/python/verbosity_mgr.py +++ b/python/verbosity_mgr.py @@ -19,8 +19,8 @@ class Verbosity(object): as `meep.verbosity`. Note that this class is a Singleton, meaning that each call to - `Verbosity(cvar)` gives you the same instance. The new `cvar` will be added to a - list of verbosity flags managed by this class. + `Verbosity(cvar)` gives you the same instance. The new `cvar` will be added + to a list of verbosity flags managed by this class. """ _instance = None @@ -37,14 +37,23 @@ def _init(self): Set up the initial state of the singleton. Called only when the first instance is created. """ - self._master_verbosity = 1 - self._cvars = list() + self._master_verbosity = -1 + self._cvars = dict() + + @classmethod + def reset(cls): + # Probably just for testing. Drops the existing the singleton instance + # so a new one will be created the next time a new Verbosity is + # instantiated. + if cls._instance is not None: + cls._instance._init() + cls._instance = None - def __init__(self, cvar=None, initial_level=None): + def __init__(self, cvar=None, name=None, initial_level=1): """See `add_verbosity_var()`""" - self.add_verbosity_var(cvar, initial_level) + self.add_verbosity_var(cvar, name, initial_level) - def add_verbosity_var(self, cvar=None, initial_level=None): + def add_verbosity_var(self, cvar=None, name=None, initial_level=1): """ Add a new verbosity flag to be managed. `cvar` should be some object that has a `verbosity` attribute, such as `meep.cvar` or `mpb.cvar`. @@ -57,13 +66,22 @@ def add_verbosity_var(self, cvar=None, initial_level=None): class _dummy(): def __init__(self): self.verbosity = 1 cvar = _dummy() - self._cvars.append(cvar) - if initial_level is not None: + + # If a name is not given then manufacture one + if name is None: + name = 'cvar_{}'.format(len(self._cvars)) + self._cvars[name] = cvar + + # And create a property for so it can be accessed like `verbosity.mpb` + self.make_property(name) + + # The initial master (global) level is determined by the first instance created + if self._master_verbosity == -1: self.set(initial_level) def get(self): """ - Returns the current verbosity level. + Returns the current global verbosity level. """ return self._master_verbosity @@ -73,7 +91,7 @@ def get_all(self): is mostly intended for debugging this class and won't likely be useful otherwise. """ - return [cvar.verbosity for cvar in self._cvars ] + return [value.verbosity for value in self._cvars.values() ] def set(self, level): """ @@ -83,16 +101,17 @@ def set(self, level): if level < 0 or level > 3: raise ValueError('Only verbosity levels 0-3 are supported') old = self._master_verbosity - for cvar in self._cvars: + for cvar in self._cvars.values(): cvar.verbosity = level self._master_verbosity = level return old def __call__(self, level): """ - Convenience for setting the verbosity level. This lets you set the level - by calling the instance like a function. For example, if `verbosity` is - an instance of this class, then it's value can be changed like this: + Convenience for setting the verbosity level. This lets you set the + global level by calling the instance like a function. For example, if + `verbosity` is an instance of this class, then it's value can be changed + like this: ``` verbosity(0) @@ -102,8 +121,8 @@ def __call__(self, level): def __int__(self): """ - A convenience for getting the verbosity level anywhere an integer is - expected. + A convenience for getting the global verbosity level anywhere an integer + is expected. """ return self.get() @@ -118,42 +137,17 @@ def __ne__(self, o): return self.get() != o def __le__(self, o): return self.get() <= o def __ge__(self, o): return self.get() >= o + def make_property(self, name): + """ + Add a property to the class with the given name that gets or sets the + verbosity in the cvar with that name in self._cvars. + """ + def _getter(self, name=name): + return self._cvars[name].verbosity + def _setter(self, level, name=name): + if level < 0 or level > 3: + raise ValueError('Only verbosity levels 0-3 are supported') + self._cvars[name].verbosity = level + setattr(Verbosity, name, property(_getter, _setter)) - -def main(): - # simple test code - import sys - - class MyCvar: - def __init__(self): self.verbosity = 1 - - verbosity = Verbosity() - v2 = Verbosity(MyCvar()) - print(verbosity is v2) - print(id(verbosity), id(v2)) - print(verbosity.get_all()) - - print('initial value: {}'.format(verbosity.get())) - - print('v==1: {}'.format(verbosity == 1)) - print('v==2: {}'.format(verbosity == 2)) - - print('v>1: {}'.format(verbosity > 1)) - print('v<3: {}'.format(verbosity < 3)) - print('v>=2: {}'.format(verbosity >= 2)) - print('v<=1: {}'.format(verbosity <= 1)) - - verbosity(3) - print('v==1: {}'.format(verbosity == 1)) - print('v==2: {}'.format(verbosity == 2)) - print('v==3: {}'.format(verbosity == 3)) - - print(verbosity.get_all()) - - # should raise ValueError - verbosity(5) - - -if __name__ == '__main__': - main() diff --git a/python/visualization.py b/python/visualization.py index a2a9cb425..41c8f547d 100644 --- a/python/visualization.py +++ b/python/visualization.py @@ -844,7 +844,7 @@ def __call__(self,sim,todo): # Normalize the frames, if requested, and export if self.normalize and mp.am_master(): - if mp.verbosity > 0: + if mp.verbosity.meep > 0: print("Normalizing field data...") fields = np.array(self.cumulative_fields) / np.max(np.abs(self.cumulative_fields),axis=(0,1,2)) for k in range(len(self.cumulative_fields)): @@ -949,7 +949,7 @@ def to_gif(self,fps,filename): '-vf', 'pad=width=ceil(iw/2)*2:height=ceil(ih/2)*2', '-an', filename # output filename ] - if mp.verbosity > 0: + if mp.verbosity.meep > 0: print("Generating GIF...") proc = Popen(command, stdin=PIPE, stdout=PIPE, stderr=PIPE) for i in range(len(self._saved_frames)): @@ -986,7 +986,7 @@ def to_mp4(self,fps,filename): '-vf', 'pad=width=ceil(iw/2)*2:height=ceil(ih/2)*2', '-an', filename # output filename ] - if mp.verbosity > 0: + if mp.verbosity.meep > 0: print("Generating MP4...") proc = Popen(command, stdin=PIPE, stdout=PIPE, stderr=PIPE) for i in range(len(self._saved_frames)): diff --git a/src/Makefile.am b/src/Makefile.am index 52327d491..f7b629021 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -1,13 +1,13 @@ lib_LTLIBRARIES = libmeep.la include_HEADERS = meep.hpp -pkginclude_HEADERS = meep/mympi.hpp meep/vec.hpp meepgeom.hpp material_data.hpp +pkginclude_HEADERS = meep/mympi.hpp meep/vec.hpp meepgeom.hpp material_data.hpp adjust_verbosity.hpp AM_CPPFLAGS = -I$(top_srcdir)/src BUILT_SOURCES = sphere-quad.h step_generic_stride1.cpp HDRS = meep.hpp meep_internals.hpp meep/mympi.hpp meep/vec.hpp \ -bicgstab.hpp meepgeom.hpp material_data.hpp +bicgstab.hpp meepgeom.hpp material_data.hpp adjust_verbosity.hpp libmeep_la_SOURCES = array_slice.cpp anisotropic_averaging.cpp \ bands.cpp boundaries.cpp bicgstab.cpp casimir.cpp \ diff --git a/src/adjust_verbosity.hpp b/src/adjust_verbosity.hpp new file mode 100644 index 000000000..21c63674a --- /dev/null +++ b/src/adjust_verbosity.hpp @@ -0,0 +1,54 @@ +/* Copyright (C) 2005-2020 Massachusetts Institute of Technology. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#ifndef ADJUST_VERBOSITY_H +#define ADJUST_VERBOSITY_H + +// NOTE: This header assumes it has been #included *after* headers that declare +// verbosity, HAVE_MPB, and mpb_verbosity. + +namespace meep { + +// This is a RAII (Resource Allocation Is Initialization) class which adjusts +// the mpb_verbosity level when created, and restores it when deleted. +class adjust_mpb_verbosity { +public: + adjust_mpb_verbosity() { + #ifdef HAVE_MPB + old_level = mpb_verbosity; + mpb_verbosity = verbosity - 1; + if (mpb_verbosity < 0) mpb_verbosity = 0; + if (mpb_verbosity > 3) mpb_verbosity = 3; + #else + // avoid warnings + (void)amount; + (void)old_level; + #endif + } + + ~adjust_mpb_verbosity() { + #ifdef HAVE_MPB + mpb_verbosity = old_level; + #endif + } + +private: + int old_level; +}; + +} + +#endif // ADJUST_VERBOSITY_H diff --git a/src/mpb.cpp b/src/mpb.cpp index 822dce30d..a9c540bda 100644 --- a/src/mpb.cpp +++ b/src/mpb.cpp @@ -24,6 +24,7 @@ #ifdef HAVE_MPB #include +#include "adjust_verbosity.hpp" #ifndef SCALAR_COMPLEX #error Meep requires complex version of MPB #endif @@ -54,6 +55,7 @@ typedef struct { static int meep_mpb_eps(symmetric_matrix *eps, symmetric_matrix *eps_inv, mpb_real n[3], mpb_real d1, mpb_real d2, mpb_real d3, mpb_real tol, const mpb_real r[3], void *eps_data_) { + adjust_mpb_verbosity amv; meep_mpb_eps_data *eps_data = (meep_mpb_eps_data *)eps_data_; size_t i = eps_data->icache; @@ -317,6 +319,7 @@ void *fields::get_eigenmode(double frequency, direction d, const volume where, c /*--------------------------------------------------------------*/ /*- part 1: preliminary setup for calling MPB -----------------*/ /*--------------------------------------------------------------*/ + adjust_mpb_verbosity amv; // if the mode region extends over the full computational grid and we are bloch-periodic // in any direction, set the corresponding component of the eigenmode initial-guess @@ -763,6 +766,7 @@ void *fields::get_eigenmode(double frequency, direction d, const volume where, c } void destroy_eigenmode_data(void *vedata, bool destroy_mdata) { + adjust_mpb_verbosity amv; eigenmode_data *edata = (eigenmode_data *)vedata; destroy_evectmatrix(edata->H); if (destroy_mdata) destroy_maxwell_data(edata->mdata); @@ -794,6 +798,7 @@ void fields::add_eigenmode_source(component c0, const src_time &src, direction d /*--------------------------------------------------------------*/ /* step 1: call MPB to compute the eigenmode */ /*--------------------------------------------------------------*/ + adjust_mpb_verbosity amv; double frequency = real(src.frequency()); am_now_working_on(MPBTime); @@ -881,6 +886,7 @@ void fields::get_eigenmode_coefficients(dft_flux flux, const volume &eig_vol, in double *vgrp, kpoint_func user_kpoint_func, void *user_kpoint_data, vec *kpoints, vec *kdom_list, double *cscale, direction d, diffractedplanewave *dp) { + adjust_mpb_verbosity amv; int num_freqs = flux.freq.size(); bool match_frequency = true; if (flux.use_symmetry && S.multiplicity() > 1 && parity == 0)