def _create_solver(self): """Instantiate a IRAMSolver.""" self.solver = openmoc.CPUSolver(self.track_generator) self.solver.setNumThreads(self.num_threads) self.solver.setConvergenceThreshold(self.tolerance) # Initialize IRAMSolver to perform forward eigenmode calculation self.solver = openmoc.krylov.IRAMSolver(self.solver)
############################################################################### ######################## Creating the TrackGenerator ###################### ############################################################################### openmoc.log.py_printf('NORMAL', 'Initializing the track generator...') track_generator = openmoc.TrackGenerator(geometry, opts.num_azim, opts.azim_spacing) track_generator.setNumThreads(opts.num_omp_threads) track_generator.generateTracks() ############################################################################### ########################### Running a Simulation ########################## ############################################################################### solver = openmoc.CPUSolver(track_generator) solver.setNumThreads(opts.num_omp_threads) solver.setConvergenceThreshold(opts.tolerance) solver.computeEigenvalue(opts.max_iters) solver.printTimerReport() ############################################################################### ############################ Generating Plots ############################ ############################################################################### openmoc.log.py_printf('NORMAL', 'Plotting data...') openmoc.plotter.plot_materials(geometry, gridsize=100) openmoc.plotter.plot_cells(geometry, gridsize=100) openmoc.plotter.plot_flat_source_regions(geometry, gridsize=100) openmoc.plotter.plot_spatial_fluxes(solver, energy_groups=[1])
def _create_solver(self): """Instantiate a CPUSolver.""" self.solver = openmoc.CPUSolver() self.solver.setNumThreads(self.num_threads) self.solver.setConvergenceThreshold(self.tolerance)
def _create_solver(self): """Instantiate a CPUSolver.""" self.solver = openmoc.CPUSolver(self.track_generator) self.solver.setNumThreads(self.num_threads) self.solver.setConvergenceThreshold(self.tolerance) self.solver.setSolverMode(self.calculation_mode)
def compute_sph_factors(mgxs_lib, max_sph_iters=30, sph_tol=1E-5, fix_src_tol=1E-5, num_azim=4, azim_spacing=0.1, zcoord=0.0, num_threads=1, throttle_output=True, geometry=None, track_generator=None, solver=None, sph_domains=None): """Compute SPH factors for an OpenMC multi-group cross section library. This routine coputes SuPerHomogenisation (SPH) factors for an OpenMC MGXS library. The SPH scheme is outlined by Alain Hebert in the following paper: Hebert, A., "A Consistent Technique for the Pin-by-Pin Homogenization of a Pressurized Water Reactor Assembly." Nuclear Science and Engineering, 113 (3), pp. 227-233, 1993. The SPH factors are needed to preserve reaction rates in heterogeneous geometries. The energy condensation process leads to a bias between ultrafine and coarse energy group calculations. This bias is a result of the use of scalar flux-weighting to compute MGXS without properly accounting for angular-dependence of the flux. Parameters ---------- mgxs_lib : openmc.mgxs.Library An OpenMC multi-group cross section library max_sph_iters : Integral The maximum number of SPH iterations (default is 30) sph_tol : Real The tolerance on the SPH factor convergence (default is 1E-5) fix_src_tol : Real The tolerance on the MOC fixed source calculations (default is 1E-5) num_azim : Integral The number of azimuthal angles (default is 4) azim_spacing : Real The track spacing (default is 0.1 centimeters) zcoord : Real The coordinate on the z-axis (default is 0.) num_threads : Real The number of OpenMP threads (default is 1) throttle_output : bool Whether to suppress output from fixed source calculations (default is True) geometry : openmoc.Geometry An optional openmoc geometry to compute SPH factors on track_generator : openmoc.TrackGenerator An optional track generator to avoid initializing it in this routine solver : openmoc.Solver An optional openmoc solver to compute SPH factors with sph_domains : list of int A list of domain (cell or material, based on mgxs_lib domain type) ids, in which SPH factors should be computed. Default is only fissonable FSRs Returns ------- fsrs_to_sph : numpy.ndarray of Real A NumPy array of SPH factors indexed by FSR and energy group sph_mgxs_lib : openmc.mgxs.Library An OpenMC MGXS library with the SPH factors applied to each MGXS sph_to_fsrs_indices : numpy.ndarray of Integral A NumPy array of all FSRs to which SPH factors were applied """ import openmc.mgxs cv.check_type('mgxs_lib', mgxs_lib, openmc.mgxs.Library) # For Python 2.X.X if sys.version_info[0] == 2: from openmc.openmoc_compatible import get_openmoc_geometry from process import get_scalar_fluxes # For Python 3.X.X else: from openmc.openmoc_compatible import get_openmoc_geometry from openmoc.process import get_scalar_fluxes py_printf('NORMAL', 'Computing SPH factors...') if not geometry: # Create an OpenMOC Geometry from the OpenMC Geometry geometry = get_openmoc_geometry(mgxs_lib.geometry) # Load the MGXS library data into the OpenMOC geometry load_openmc_mgxs_lib(mgxs_lib, geometry) if not track_generator: # Initialize an OpenMOC TrackGenerator track_generator = openmoc.TrackGenerator(geometry, num_azim, azim_spacing) track_generator.setZCoord(zcoord) track_generator.generateTracks() track_generator.initializeVolumes() else: track_generator.initializeVolumes() py_printf( 'WARNING', 'Using provided track generator, ignoring ' 'arguments for track generation settings') if not solver: # Initialize an OpenMOC Solver solver = openmoc.CPUSolver(track_generator) solver.setConvergenceThreshold(fix_src_tol) solver.setNumThreads(num_threads) else: py_printf( 'WARNING', 'Using provided solver, ignoring arguments for ' 'solver settings') # Get all OpenMOC domains if mgxs_lib.domain_type == 'material': openmoc_domains = geometry.getAllMaterials() elif mgxs_lib.domain_type == 'cell': openmoc_domains = geometry.getAllMaterialCells() else: py_printf( 'ERROR', 'SPH factors cannot be applied for an OpenMC MGXS ' 'library of domain type %s', mgxs_lib.domain_type) if not sph_domains: sph_domains = [] # If unspecified, apply sph factors in fissionable regions for openmoc_domain in openmoc_domains.values(): if openmoc_domain.isFissionable(): sph_domains.append(openmoc_domain.getId()) openmc_fluxes = _load_openmc_src(mgxs_lib, solver) # Initialize SPH factors num_groups = geometry.getNumEnergyGroups() num_fsrs = geometry.getNumFSRs() # Map FSRs to domains (and vice versa) to compute domain-averaged fluxes fsrs_to_domains = np.zeros(num_fsrs) domains_to_fsrs = collections.defaultdict(list) sph_to_fsr_indices = [] for fsr in range(num_fsrs): cell = geometry.findCellContainingFSR(fsr) if mgxs_lib.domain_type == 'material': domain = cell.getFillMaterial() else: domain = cell fsrs_to_domains[fsr] = domain.getId() domains_to_fsrs[domain.getId()].append(fsr) if domain.getId() in sph_domains: sph_to_fsr_indices.append(fsr) # Build a list of indices into the SPH array for fissionable domains sph_to_domain_indices = [] for i, openmc_domain in enumerate(mgxs_lib.domains): if openmc_domain.id in openmoc_domains: openmoc_domain = openmoc_domains[openmc_domain.id] if openmoc_domain.getId() in sph_domains: sph_to_domain_indices.append(i) py_printf('NORMAL', 'Computing SPH factors for %d "%s" domains', len(sph_to_domain_indices), mgxs_lib.domain_type) # Initialize array of domain-averaged fluxes and SPH factors num_domains = len(mgxs_lib.domains) openmoc_fluxes = np.zeros((num_domains, num_groups)) sph = np.ones((num_domains, num_groups)) # Store starting verbosity log level log_level = openmoc.get_log_level() # SPH iteration loop for i in range(max_sph_iters): # Run fixed source calculation with suppressed output if throttle_output: openmoc.set_log_level('WARNING') # Disable flux resets between SPH iterations for speed if i == 1: solver.setRestartStatus(True) # Fixed source calculation solver.computeFlux() # Restore log output level if throttle_output: openmoc.set_log_level('NORMAL') # Extract the FSR scalar fluxes fsr_fluxes = get_scalar_fluxes(solver) # Compute the domain-averaged flux in each energy group for j, openmc_domain in enumerate(mgxs_lib.domains): domain_fluxes = fsr_fluxes[fsrs_to_domains == openmc_domain.id, :] openmoc_fluxes[j, :] = np.mean(domain_fluxes, axis=0) # Compute SPH factors old_sph = np.copy(sph) sph = openmc_fluxes / openmoc_fluxes sph = np.nan_to_num(sph) sph[sph == 0.0] = 1.0 # Compute SPH factor residuals res = np.abs((sph - old_sph) / old_sph) res = np.nan_to_num(res) # Extract residuals for fissionable domains only res = res[sph_to_domain_indices, :] # Report maximum SPH factor residual py_printf('NORMAL', 'SPH Iteration %d:\tres = %1.3e', i, res.max()) # Create a new MGXS library with cross sections updated by SPH factors sph_mgxs_lib = _apply_sph_factors(mgxs_lib, geometry, sph, sph_domains) # Load the new MGXS library data into the OpenMOC geometry load_openmc_mgxs_lib(sph_mgxs_lib, geometry) # Check max SPH factor residual for this domain for convergence if res.max() < sph_tol and i > 0: break # Warn user if SPH factors did not converge else: py_printf('WARNING', 'SPH factors did not converge') # Collect SPH factors for each FSR, energy group fsrs_to_sph = np.ones((num_fsrs, num_groups), dtype=np.float) for i, openmc_domain in enumerate(mgxs_lib.domains): if openmc_domain.id in openmoc_domains: openmoc_domain = openmoc_domains[openmc_domain.id] if openmoc_domain.getId() in sph_domains: fsr_ids = domains_to_fsrs[openmc_domain.id] fsrs_to_sph[fsr_ids, :] = sph[i, :] return fsrs_to_sph, sph_mgxs_lib, np.array(sph_to_fsr_indices)
def _run_openmoc(self): runtime = openmoc.RuntimeParameters() string_input = [ '-debug', '1', '-log_level', 'NORMAL', '-domain_decompose', '2,2,2', '-num_domain_modules', '1,1,1', '-num_threads', '1', '-log_filename', 'test_problem.log', '-geo_filename', 'geometry_file.geo', '-azim_spacing', '0.22 ', '-num_azim', '4', '-polar_spacing', '0.8', '-num_polar', '6', '-seg_zones', '-5.0,5.0', '-segmentation_type', '3', '-quadraturetype', '2', '-CMFD_group_structure', '1/2,3,4/5,6,7', '-CMFD_lattice', '2,3,3', '-widths_x', '1,2*1,1', '-widths_y', '1,2*1,1', '-widths_z', '3.5,2.5*2,1.5', '-CMFD_flux_update_on', '1', '-knearest', '2', '-CMFD_centroid_update_on', '1', '-use_axial_interpolation', '2', '-SOR_factor', '1.5', '-CMFD_relaxation_factor', '0.7', '-ls_solver', '1', '-max_iters', '15', '-MOC_src_residual_type', '1', '-MOC_src_tolerance', '1.0E-2', '-output_mesh_lattice', '-output_mesh_lattice', ' 5,5,9', ' -output_type', ' 0', '-output_mesh_lattice', '-output_mesh_lattice', ' 5,5,9', ' -output_type', ' 1', '-non_uniform_output', '1.26*3/1*3/4.*3/-1.,1.,-1.', ' -output_type 1 ', '-verbose_report', '1', '-time_report', '1' ] string_input = [s.encode('utf8') for s in string_input] runtime.setRuntimeParameters(string_input) print(string_input) # Define simulation parameters num_threads = runtime._num_threads # Set logging information if (runtime._log_filename): openmoc.set_log_filename(runtime._log_filename) openmoc.set_log_level(runtime._log_level) openmoc.set_line_length(120) py_printf('NORMAL', 'Geometry file = %s', runtime._geo_filename) py_printf('NORMAL', 'Azimuthal spacing = %f', runtime._azim_spacing) py_printf('NORMAL', 'Azimuthal angles = %d', runtime._num_azim) py_printf('NORMAL', 'Polar spacing = %f', runtime._polar_spacing) py_printf('NORMAL', 'Polar angles = %d', runtime._num_polar) # Create the geometry py_printf('NORMAL', 'Creating geometry...') geometry = openmoc.Geometry() self.input_set.geometry = geometry if (not runtime._geo_filename): py_printf('ERROR', 'No geometry file is provided') geometry.loadFromFile(runtime._geo_filename) if False: #FIXME geometry.setDomainDecomposition(runtime._NDx, runtime._NDy, runtime._NDz, MPI_COMM_WORLD) geometry.setNumDomainModules(runtime._NMx, runtime._NMy, runtime._NMz) if ((runtime._NCx > 0 and runtime._NCy > 0 and runtime._NCz > 0) or (not runtime._cell_widths_x.empty() and not runtime._cell_widths_y.empty() and not runtime._cell_widths_z.empty())): # Create CMFD mesh py_printf('NORMAL', 'Creating CMFD mesh...') cmfd = openmoc.Cmfd() cmfd.setSORRelaxationFactor(runtime._SOR_factor) cmfd.setCMFDRelaxationFactor(runtime._CMFD_relaxation_factor) if (runtime._cell_widths_x.empty() or runtime._cell_widths_y.empty() or runtime._cell_widths_z.empty()): cmfd.setLatticeStructure(runtime._NCx, runtime._NCy, runtime._NCz) else: cmfd_widths = [ runtime._cell_widths_x, runtime._cell_widths_y, runtime._cell_widths_z ] cmfd.setWidths(cmfd_widths) if (not runtime._CMFD_group_structure.empty()): cmfd.setGroupStructure(runtime._CMFD_group_structure) cmfd.setKNearest(runtime._knearest) cmfd.setCentroidUpdateOn(runtime._CMFD_centroid_update_on) cmfd.useAxialInterpolation(runtime._use_axial_interpolation) geometry.setCmfd(cmfd) geometry.initializeFlatSourceRegions() # Initialize track generator and generate tracks py_printf('NORMAL', 'Initializing the track generator...') if runtime._quadraturetype == 0: quad = openmoc.TYPolarQuad() if runtime._quadraturetype == 1: quad = openmoc.LeonardPolarQuad() if runtime._quadraturetype == 2: quad = openmoc.GLPolarQuad() if runtime._quadraturetype == 3: quad = openmoc.EqualWeightPolarQuad() if runtime._quadraturetype == 4: quad = openmoc.EqualAnglePolarQuad() quad.setNumAzimAngles(runtime._num_azim) quad.setNumPolarAngles(runtime._num_polar) track_generator = openmoc.TrackGenerator3D(geometry, runtime._num_azim, runtime._num_polar, runtime._azim_spacing, runtime._polar_spacing) track_generator.setNumThreads(num_threads) track_generator.setQuadrature(quad) track_generator.setSegmentFormation(runtime._segmentation_type) if (len(runtime._seg_zones) > 0): track_generator.setSegmentationZones(runtime._seg_zones) track_generator.generateTracks() self.track_generator = track_generator # Initialize solver and run simulation if (runtime._linear_solver): self.solver = openmoc.CPULSSolver(track_generator) else: self.solver = openmoc.CPUSolver(track_generator) if (runtime._verbose_report): self.solver.setVerboseIterationReport() self.solver.setNumThreads(num_threads) self.solver.setConvergenceThreshold(runtime._tolerance) self.solver.computeEigenvalue(runtime._max_iters, runtime._MOC_src_residual_type) if (runtime._time_report): self.solver.printTimerReport() # Extract reaction rates my_rank = 0 #if False: #FIXME #MPI_Comm_rank(MPI_COMM_WORLD, &my_rank); rxtype = {'FISSION_RX', 'TOTAL_RX', 'ABSORPTION_RX', 'FLUX_RX'}