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)
示例#2
0
###############################################################################
########################   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)
示例#4
0
 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)
示例#5
0
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)
示例#6
0
    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'}