From 98b6dc15a94e6911e73c40fd3d0b9a9163aa4513 Mon Sep 17 00:00:00 2001 From: amandalund Date: Sun, 25 Mar 2018 13:47:47 -0500 Subject: [PATCH 01/77] Fix that ensures TRISO particles are completely contained within the domain --- openmc/model/triso.py | 95 +++++++++++++++++++++++++++---------------- 1 file changed, 59 insertions(+), 36 deletions(-) diff --git a/openmc/model/triso.py b/openmc/model/triso.py index 5fe51b6644..b5ee74f90b 100644 --- a/openmc/model/triso.py +++ b/openmc/model/triso.py @@ -113,8 +113,7 @@ class _Domain(metaclass=ABCMeta): Length in x-, y-, and z- directions of each cell in mesh overlaid on domain. limits : list of float - Minimum and maximum position in x-, y-, and z-directions where particle - center can be placed. + Constraint on where particle center can be placed. volume : float Volume of the container. @@ -158,8 +157,6 @@ class _Domain(metaclass=ABCMeta): raise ValueError('Unable to set domain center to {} since it must ' 'be of length 3'.format(center)) self._center = [float(x) for x in center] - self._limits = None - self._cell_length = None def mesh_cell(self, p): """Calculate the index of the cell in a mesh overlaid on the domain in @@ -211,6 +208,19 @@ class _Domain(metaclass=ABCMeta): """ pass + @abstractmethod + def enforce_boundary(self, particle): + """Update the position of the particle if necessary to ensure that the + particle remains entirely within the domain. + + Parameters + ---------- + particle : numpy.ndarray + Cartesian coordinates of particle center. + + """ + pass + class _CubicDomain(_Domain): """Cubic container in which to pack particles. @@ -238,7 +248,7 @@ class _CubicDomain(_Domain): Length in x-, y-, and z- directions of each cell in mesh overlaid on domain. limits : list of float - Minimum and maximum position in x-, y-, and z-directions where particle + Maximum distance from center in x-, y-, or z-direction where particle center can be placed. volume : float Volume of the container. @@ -256,9 +266,7 @@ class _CubicDomain(_Domain): @property def limits(self): if self._limits is None: - xlim = self.length/2 - self.particle_radius - self._limits = [[x - xlim for x in self.center], - [x + xlim for x in self.center]] + self._limits = [self.length/2 - self.particle_radius] return self._limits @property @@ -284,9 +292,14 @@ class _CubicDomain(_Domain): self._limits = limits def random_point(self): - return [uniform(self.limits[0][0], self.limits[1][0]), - uniform(self.limits[0][1], self.limits[1][1]), - uniform(self.limits[0][2], self.limits[1][2])] + x_max = self.limits[0] + return [uniform(-x_max, x_max), + uniform(-x_max, x_max), + uniform(-x_max, x_max)] + + def enforce_boundary(self, particle): + x_max = self.limits[0] + particle[:] = np.clip(particle, -x_max, x_max) class _CylindricalDomain(_Domain): @@ -317,8 +330,8 @@ class _CylindricalDomain(_Domain): Length in x-, y-, and z- directions of each cell in mesh overlaid on domain. limits : list of float - Minimum and maximum position in x-, y-, and z-directions where particle - center can be placed. + Maximum radial distance and maximum distance from center in z-direction + where particle center can be placed. volume : float Volume of the container. @@ -340,12 +353,8 @@ class _CylindricalDomain(_Domain): @property def limits(self): if self._limits is None: - xlim = self.length/2 - self.particle_radius - rlim = self.radius - self.particle_radius - self._limits = [[self.center[0] - rlim, self.center[1] - rlim, - self.center[2] - xlim], - [self.center[0] + rlim, self.center[1] + rlim, - self.center[2] + xlim]] + self._limits = [self.radius - self.particle_radius, + self.length/2 - self.particle_radius] return self._limits @property @@ -377,10 +386,20 @@ class _CylindricalDomain(_Domain): self._limits = limits def random_point(self): - r = sqrt(uniform(0, (self.radius - self.particle_radius)**2)) + r_max = self.limits[0] + z_max = self.limits[1] + r = sqrt(uniform(0, r_max**2)) t = uniform(0, 2*pi) - return [r*cos(t) + self.center[0], r*sin(t) + self.center[1], - uniform(self.limits[0][2], self.limits[1][2])] + return [r*cos(t), r*sin(t), uniform(-z_max, z_max)] + + def enforce_boundary(self, particle): + r_max = self.limits[0] + z_max = self.limits[1] + d = sqrt(particle[0]**2 + particle[1]**2) + if d > r_max: + particle[0] *= r_max / d + particle[1] *= r_max / d + particle[2] = np.clip(particle[2], -z_max, z_max) class _SphericalDomain(_Domain): @@ -407,8 +426,7 @@ class _SphericalDomain(_Domain): Length in x-, y-, and z- directions of each cell in mesh overlaid on domain. limits : list of float - Minimum and maximum position in x-, y-, and z-directions where particle - center can be placed. + Maximum radial distance where particle center can be placed. volume : float Volume of the container. @@ -425,9 +443,7 @@ class _SphericalDomain(_Domain): @property def limits(self): if self._limits is None: - rlim = self.radius - self.particle_radius - self._limits = [[x - rlim for x in self.center], - [x + rlim for x in self.center]] + self._limits = [self.radius - self.particle_radius] return self._limits @property @@ -453,10 +469,18 @@ class _SphericalDomain(_Domain): self._limits = limits def random_point(self): + r_max = self.limits[0] x = (gauss(0, 1), gauss(0, 1), gauss(0, 1)) - r = (uniform(0, (self.radius - self.particle_radius)**3)**(1/3) / - sqrt(x[0]**2 + x[1]**2 + x[2]**2)) - return [r*x[i] + self.center[i] for i in range(3)] + r = (uniform(0, r_max**3)**(1/3) / sqrt(x[0]**2 + x[1]**2 + x[2]**2)) + return [r*s for s in x] + + def enforce_boundary(self, particle): + r_max = self.limits[0] + d = sqrt(particle[0]**2 + particle[1]**2 + particle[2]**2) + if d > r_max: + particle[0] *= r_max / d + particle[1] *= r_max / d + particle[2] *= r_max / d def create_triso_lattice(trisos, lower_left, pitch, shape, background): @@ -767,9 +791,9 @@ def _close_random_pack(domain, particles, contraction_rate): particles[i] += r*v particles[j] -= r*v - # Apply reflective boundary conditions - particles[i] = particles[i].clip(domain.limits[0], domain.limits[1]) - particles[j] = particles[j].clip(domain.limits[0], domain.limits[1]) + # Apply boundary conditions + domain.enforce_boundary(particles[i]) + domain.enforce_boundary(particles[j]) update_mesh(i) update_mesh(j) @@ -1008,8 +1032,7 @@ def pack_trisos(radius, fill, domain_shape='cylinder', domain_length=None, # Recalculate the limits for the initial random sequential packing using # the desired final particle radius to ensure particles are fully contained # within the domain during the close random pack - domain.limits = [[x - initial_radius + radius for x in domain.limits[0]], - [x + initial_radius - radius for x in domain.limits[1]]] + domain.limits = [x + initial_radius - radius for x in domain.limits] # Generate non-overlapping particles for an initial inner radius using # random sequential packing algorithm @@ -1024,5 +1047,5 @@ def pack_trisos(radius, fill, domain_shape='cylinder', domain_length=None, trisos = [] for p in particles: - trisos.append(TRISO(radius, fill, p)) + trisos.append(TRISO(radius, fill, [x + c for x, c in zip(p, domain.center)])) return trisos From 00cb9149082e274dedacade9a0b171b467ab004c Mon Sep 17 00:00:00 2001 From: amandalund Date: Mon, 26 Mar 2018 17:14:26 -0500 Subject: [PATCH 02/77] Add unit tests for TRISO --- openmc/model/triso.py | 213 ++++++++++++++------------- tests/unit_tests/test_model_triso.py | 75 ++++++++++ 2 files changed, 187 insertions(+), 101 deletions(-) create mode 100644 tests/unit_tests/test_model_triso.py diff --git a/openmc/model/triso.py b/openmc/model/triso.py index b5ee74f90b..77488b891b 100644 --- a/openmc/model/triso.py +++ b/openmc/model/triso.py @@ -209,14 +209,21 @@ class _Domain(metaclass=ABCMeta): pass @abstractmethod - def enforce_boundary(self, particle): - """Update the position of the particle if necessary to ensure that the - particle remains entirely within the domain. + def repel_particles(self, p, q, d, d_new): + """Move particles p and q apart according to the following + transformation (accounting for boundary conditions on domain): + + r_i^(n+1) = r_i^(n) + 1/2(d_out^(n+1) - d^(n)) + r_j^(n+1) = r_j^(n) - 1/2(d_out^(n+1) - d^(n)) Parameters ---------- - particle : numpy.ndarray + p, q : numpy.ndarray Cartesian coordinates of particle center. + d : float + distance between centers of particles i and j. + d_new : float + final distance between centers of particles i and j. """ pass @@ -297,9 +304,20 @@ class _CubicDomain(_Domain): uniform(-x_max, x_max), uniform(-x_max, x_max)] - def enforce_boundary(self, particle): + def repel_particles(self, p, q, d, d_new): + # Moving each particle distance 'r' away from the other along the line + # joining the particle centers will ensure their final distance is + # equal to the outer diameter + r = (d_new - d)/2 + + v = (p - q)/d + p += r*v + q -= r*v + + # Apply boundary conditions x_max = self.limits[0] - particle[:] = np.clip(particle, -x_max, x_max) + p[:] = np.clip(p, -x_max, x_max) + q[:] = np.clip(q, -x_max, x_max) class _CylindricalDomain(_Domain): @@ -392,14 +410,29 @@ class _CylindricalDomain(_Domain): t = uniform(0, 2*pi) return [r*cos(t), r*sin(t), uniform(-z_max, z_max)] - def enforce_boundary(self, particle): + def repel_particles(self, p, q, d, d_new): + # Moving each particle distance 'r' away from the other along the line + # joining the particle centers will ensure their final distance is + # equal to the outer diameter + r = (d_new - d)/2 + + v = (p - q)/d + p += r*v + q -= r*v + + # Apply boundary conditions r_max = self.limits[0] z_max = self.limits[1] - d = sqrt(particle[0]**2 + particle[1]**2) + + d = sqrt(p[0]**2 + p[1]**2) if d > r_max: - particle[0] *= r_max / d - particle[1] *= r_max / d - particle[2] = np.clip(particle[2], -z_max, z_max) + p[0:2] *= r_max/d + p[2] = np.clip(p[2], -z_max, z_max) + + d = sqrt(q[0]**2 + q[1]**2) + if d > r_max: + q[0:2] *= r_max/d + q[2] = np.clip(q[2], -z_max, z_max) class _SphericalDomain(_Domain): @@ -474,13 +507,26 @@ class _SphericalDomain(_Domain): r = (uniform(0, r_max**3)**(1/3) / sqrt(x[0]**2 + x[1]**2 + x[2]**2)) return [r*s for s in x] - def enforce_boundary(self, particle): + def repel_particles(self, p, q, d, d_new): + # Moving each particle distance 'r' away from the other along the line + # joining the particle centers will ensure their final distance is + # equal to the outer diameter + r = (d_new - d)/2 + + v = (p - q)/d + p += r*v + q -= r*v + + # Apply boundary conditions r_max = self.limits[0] - d = sqrt(particle[0]**2 + particle[1]**2 + particle[2]**2) + + d = sqrt(p[0]**2 + p[1]**2 + p[2]**2) if d > r_max: - particle[0] *= r_max / d - particle[1] *= r_max / d - particle[2] *= r_max / d + p *= r_max/d + + d = sqrt(q[0]**2 + q[1]**2 + q[2]**2) + if d > r_max: + q *= r_max/d def create_triso_lattice(trisos, lower_left, pitch, shape, background): @@ -711,13 +757,8 @@ def _close_random_pack(domain, particles, contraction_rate): for d, i, j in r: add_rod(d, i, j) - # Inner diameter is set initially to the shortest center-to-center - # distance between any two particles - if rods: - inner_diameter[0] = rods[0][0] - - def update_mesh(i): - """Update which mesh cells the particle is in based on new particle + def update_mesh(indices): + """Update which mesh cells the particles are in based on new particle center coordinates. 'mesh'/'mesh_map' is a two way dictionary used to look up which @@ -727,22 +768,23 @@ def _close_random_pack(domain, particles, contraction_rate): Parameters ---------- - i : int - Index of particle in particles array. + indices : List of int + Indices of particles in particles array. """ - # Determine which mesh cells the particle is in and remove the - # particle id from those cells - for idx in mesh_map[i]: - mesh[idx].remove(i) - del mesh_map[i] + for i in indices: + # Determine which mesh cells the particle is in and remove the + # particle id from those cells + for idx in mesh_map[i]: + mesh[idx].remove(i) + del mesh_map[i] - # Determine which mesh cells are within one diameter of particle's - # center and add this particle to the list of particles in those cells - for idx in domain.nearby_mesh_cells(particles[i]): - mesh[idx].add(i) - mesh_map[i].add(idx) + # Determine which mesh cells are within one diameter of particle's + # center and add this particle to the list of particles in those cells + for idx in domain.nearby_mesh_cells(particles[i]): + mesh[idx].add(i) + mesh_map[i].add(idx) def reduce_outer_diameter(): """Reduce the outer diameter so that at the (i+1)-st iteration it is: @@ -753,50 +795,19 @@ def _close_random_pack(domain, particles, contraction_rate): j = floor(-log10(pf_out - pf_in)). + Returns + ------- + float + New outer diameter + """ - inner_pf = (4/3 * pi * (inner_diameter[0]/2)**3 * n_particles / - domain.volume) - outer_pf = (4/3 * pi * (outer_diameter[0]/2)**3 * n_particles / - domain.volume) + inner_pf = 4/3*pi*(inner_diameter/2)**3*n_particles/domain.volume + outer_pf = 4/3*pi*(outer_diameter/2)**3*n_particles/domain.volume j = floor(-log10(outer_pf - inner_pf)) - outer_diameter[0] = (outer_diameter[0] - 0.5**j * contraction_rate * - initial_outer_diameter / n_particles) - - - def repel_particles(i, j, d): - """Move particles p and q apart according to the following - transformation (accounting for reflective boundary conditions on - domain): - - r_i^(n+1) = r_i^(n) + 1/2(d_out^(n+1) - d^(n)) - r_j^(n+1) = r_j^(n) - 1/2(d_out^(n+1) - d^(n)) - - Parameters - ---------- - i, j : int - Index of particles in particles array. - d : float - distance between centers of particles i and j. - - """ - - # Moving each particle distance 'r' away from the other along the line - # joining the particle centers will ensure their final distance is equal - # to the outer diameter - r = (outer_diameter[0] - d)/2 - - v = (particles[i] - particles[j])/d - particles[i] += r*v - particles[j] -= r*v - - # Apply boundary conditions - domain.enforce_boundary(particles[i]) - domain.enforce_boundary(particles[j]) - - update_mesh(i) - update_mesh(j) + return (outer_diameter - 0.5**j * contraction_rate * + initial_outer_diameter / n_particles) def nearest(i): """Find index of nearest neighbor of particle i. @@ -827,33 +838,25 @@ def _close_random_pack(domain, particles, contraction_rate): else: return None, None - def update_rod_list(i, j): - """Update the rod list with the new nearest neighbors of particles i - and j since their overlap was eliminated. + def update_rod_list(indices): + """Update the rod list with the new nearest neighbors of particles in + list since their overlap was eliminated. Parameters ---------- - i, j : int - Index of particles in particles array. + indices : List of int + Indices of particles in particles array. """ # If the nearest neighbor k of particle i has no nearer neighbors, # remove the rod currently containing k from the rod list and add rod # k-i, keeping the rod list sorted - k, d_ik = nearest(i) - if k and nearest(k)[0] == i: - remove_rod(k) - add_rod(d_ik, i, k) - l, d_jl = nearest(j) - if l and nearest(l)[0] == j: - remove_rod(l) - add_rod(d_jl, j, l) - - # Set inner diameter to the shortest distance between two particle - # centers - if rods: - inner_diameter[0] = rods[0][0] + for i in indices: + k, d_ik = nearest(i) + if k and nearest(k)[0] == i: + remove_rod(k) + add_rod(d_ik, i, k) n_particles = len(particles) diameter = 2*domain.particle_radius @@ -865,8 +868,8 @@ def _close_random_pack(domain, particles, contraction_rate): initial_outer_diameter = 2*(domain.volume/(n_particles*4/3*pi))**(1/3) # Inner and outer diameter of particles will change during packing - outer_diameter = [initial_outer_diameter] - inner_diameter = [0] + outer_diameter = initial_outer_diameter + inner_diameter = 0. rods = [] rods_map = {} @@ -880,14 +883,22 @@ def _close_random_pack(domain, particles, contraction_rate): while True: create_rod_list() - if inner_diameter[0] >= diameter: + if rods: + # Set inner diameter to the shortest center-to-center distance + # between any two particles + inner_diameter = rods[0][0] + if inner_diameter >= diameter: break while True: d, i, j = pop_rod() - reduce_outer_diameter() - repel_particles(i, j, d) - update_rod_list(i, j) - if inner_diameter[0] >= diameter or not rods: + outer_diameter = reduce_outer_diameter() + domain.repel_particles(particles[i], particles[j], d, outer_diameter) + update_mesh([i, j]) + update_rod_list([i, j]) + if not rods: + break + inner_diameter = rods[0][0] + if inner_diameter >= diameter: break @@ -957,7 +968,7 @@ def pack_trisos(radius, fill, domain_shape='cylinder', domain_length=None, to speed up the nearest neighbor search by only searching for a particle's neighbors within that mesh cell. - In CRP, each particle is assigned two diameters, and inner and an outer, + In CRP, each particle is assigned two diameters, an inner and an outer, which approach each other during the simulation. The inner diameter, defined as the minimum center-to-center distance, is the true diameter of the particles and defines the pf. At each iteration the worst overlap diff --git a/tests/unit_tests/test_model_triso.py b/tests/unit_tests/test_model_triso.py new file mode 100644 index 0000000000..c6f717d0b2 --- /dev/null +++ b/tests/unit_tests/test_model_triso.py @@ -0,0 +1,75 @@ +#!/usr/bin/env python + +from math import pi + +import numpy as np +from numpy.linalg import norm +import openmc +import openmc.model +import pytest +import scipy.spatial + + +_PACKING_FRACTION = 0.35 +_RADIUS = 1. +_PARAMS = [{'shape' : 'cube', 'length' : 20., 'radius' : 0.}, + {'shape' : 'cylinder', 'length' : 10., 'radius' : 10.}, + {'shape' : 'sphere', 'length' : 0., 'radius' : 10.}] + + +@pytest.fixture(scope='module', params=_PARAMS) +def domain(request): + return request.param + + +@pytest.fixture(scope='module') +def trisos(domain): + return openmc.model.pack_trisos( + radius=_RADIUS, + fill=openmc.Universe(), + domain_shape=domain['shape'], + domain_length=domain['length'], + domain_radius=domain['radius'], + domain_center=[0., 0., 0.], + initial_packing_fraction=0.2, + packing_fraction=_PACKING_FRACTION + ) + + +def test_overlap(trisos): + """Check that no TRISO particles overlap.""" + tree = scipy.spatial.cKDTree([t.center for t in trisos]) + r = min(tree.query([t.center for t in trisos], k=2)[0][:,1])/2 + assert r > _RADIUS or r == pytest.approx(_RADIUS) + + +def test_contained(trisos, domain): + """Make sure all particles are entirely contained within the domain.""" + if domain['shape'] == 'cube': + x = 2*(max(np.hstack([abs(t.center) for t in trisos])) + _RADIUS) + assert x < domain['length'] or x == pytest.approx(domain['length']) + + elif domain['shape'] == 'cylinder': + r = max([norm(t.center[0:2]) for t in trisos]) + _RADIUS + z = 2*(max([abs(t.center[2]) for t in trisos]) + _RADIUS) + assert r < domain['radius'] or r == pytest.approx(domain['radius']) + assert z < domain['length'] or z == pytest.approx(domain['length']) + + elif domain['shape'] == 'sphere': + r = max([norm(t.center) for t in trisos]) + _RADIUS + assert r < domain['radius'] or r == pytest.approx(domain['radius']) + + +def test_packing_fraction(trisos, domain): + """Check that the actual PF is close to the requested PF.""" + if domain['shape'] == 'cube': + volume = domain['length']**3 + + elif domain['shape'] == 'cylinder': + volume = domain['length']*pi*domain['radius']**2 + + elif domain['shape'] == 'sphere': + volume = 4/3*pi*domain['radius']**3 + + pf = len(trisos)*4/3*pi*_RADIUS**3/volume + assert pf == pytest.approx(_PACKING_FRACTION, rel=1e-2) From 8838f14720f23c198bc112a2a0fc957917b3379a Mon Sep 17 00:00:00 2001 From: amandalund Date: Fri, 30 Mar 2018 20:00:28 -0500 Subject: [PATCH 03/77] Added some more TRISO unit tests --- openmc/model/triso.py | 12 ++- tests/unit_tests/test_model_triso.py | 144 ++++++++++++++++++++++----- 2 files changed, 127 insertions(+), 29 deletions(-) diff --git a/openmc/model/triso.py b/openmc/model/triso.py index 77488b891b..7040d02cab 100644 --- a/openmc/model/triso.py +++ b/openmc/model/triso.py @@ -314,7 +314,9 @@ class _CubicDomain(_Domain): p += r*v q -= r*v - # Apply boundary conditions + # Enforce the rigid boundary by moving each particle back along the + # surface normal until it is completely within the container if it + # overlaps the surface x_max = self.limits[0] p[:] = np.clip(p, -x_max, x_max) q[:] = np.clip(q, -x_max, x_max) @@ -420,7 +422,9 @@ class _CylindricalDomain(_Domain): p += r*v q -= r*v - # Apply boundary conditions + # Enforce the rigid boundary by moving each particle back along the + # surface normal until it is completely within the container if it + # overlaps the surface r_max = self.limits[0] z_max = self.limits[1] @@ -517,7 +521,9 @@ class _SphericalDomain(_Domain): p += r*v q -= r*v - # Apply boundary conditions + # Enforce the rigid boundary by moving each particle back along the + # surface normal until it is completely within the container if it + # overlaps the surface r_max = self.limits[0] d = sqrt(p[0]**2 + p[1]**2 + p[2]**2) diff --git a/tests/unit_tests/test_model_triso.py b/tests/unit_tests/test_model_triso.py index c6f717d0b2..bfd7319d21 100644 --- a/tests/unit_tests/test_model_triso.py +++ b/tests/unit_tests/test_model_triso.py @@ -11,49 +11,75 @@ import scipy.spatial _PACKING_FRACTION = 0.35 -_RADIUS = 1. -_PARAMS = [{'shape' : 'cube', 'length' : 20., 'radius' : 0.}, - {'shape' : 'cylinder', 'length' : 10., 'radius' : 10.}, - {'shape' : 'sphere', 'length' : 0., 'radius' : 10.}] +_RADIUS = 4.25e-2 -@pytest.fixture(scope='module', params=_PARAMS) +@pytest.fixture(scope='module', + params=[{'shape': 'cube', + 'length': 0.75, + 'radius': 0., + 'volume': 0.75**3}, + {'shape': 'cylinder', + 'length': 0.5, + 'radius': 0.5, + 'volume': 0.5*pi*0.5**2}, + {'shape': 'sphere', + 'length': 0., + 'radius': 0.5, + 'volume': 4/3*pi*0.5**3}]) def domain(request): return request.param @pytest.fixture(scope='module') -def trisos(domain): - return openmc.model.pack_trisos( +def triso_universe(): + sphere = openmc.Sphere(R=_RADIUS) + cell = openmc.Cell(region=-sphere) + univ = openmc.Universe(cells=[cell]) + return univ + + +@pytest.fixture(scope='module') +def trisos(domain, triso_universe): + trisos = openmc.model.pack_trisos( radius=_RADIUS, - fill=openmc.Universe(), + fill=triso_universe, domain_shape=domain['shape'], domain_length=domain['length'], domain_radius=domain['radius'], - domain_center=[0., 0., 0.], + domain_center=(0., 0., 0.), initial_packing_fraction=0.2, packing_fraction=_PACKING_FRACTION ) + return trisos def test_overlap(trisos): """Check that no TRISO particles overlap.""" - tree = scipy.spatial.cKDTree([t.center for t in trisos]) - r = min(tree.query([t.center for t in trisos], k=2)[0][:,1])/2 - assert r > _RADIUS or r == pytest.approx(_RADIUS) + centers = [t.center for t in trisos] + + # Create KD tree for quick nearest neighbor search + tree = scipy.spatial.cKDTree(centers) + + # Find distance to nearest neighbor for all particles + d = tree.query(centers, k=2)[0] + + # Get the smallest distance between any two particles + d_min = min(d[:,1]) + assert d_min > 2*_RADIUS or d_min == pytest.approx(2*_RADIUS) def test_contained(trisos, domain): """Make sure all particles are entirely contained within the domain.""" if domain['shape'] == 'cube': - x = 2*(max(np.hstack([abs(t.center) for t in trisos])) + _RADIUS) - assert x < domain['length'] or x == pytest.approx(domain['length']) + x = max(np.hstack([abs(t.center) for t in trisos])) + _RADIUS + assert x < 0.5*domain['length'] or x == pytest.approx(0.5*domain['length']) elif domain['shape'] == 'cylinder': r = max([norm(t.center[0:2]) for t in trisos]) + _RADIUS - z = 2*(max([abs(t.center[2]) for t in trisos]) + _RADIUS) + z = max([abs(t.center[2]) for t in trisos]) + _RADIUS assert r < domain['radius'] or r == pytest.approx(domain['radius']) - assert z < domain['length'] or z == pytest.approx(domain['length']) + assert z < 0.5*domain['length'] or z == pytest.approx(0.5*domain['length']) elif domain['shape'] == 'sphere': r = max([norm(t.center) for t in trisos]) + _RADIUS @@ -62,14 +88,80 @@ def test_contained(trisos, domain): def test_packing_fraction(trisos, domain): """Check that the actual PF is close to the requested PF.""" - if domain['shape'] == 'cube': - volume = domain['length']**3 - - elif domain['shape'] == 'cylinder': - volume = domain['length']*pi*domain['radius']**2 - - elif domain['shape'] == 'sphere': - volume = 4/3*pi*domain['radius']**3 - - pf = len(trisos)*4/3*pi*_RADIUS**3/volume + pf = len(trisos)*4/3*pi*_RADIUS**3/domain['volume'] assert pf == pytest.approx(_PACKING_FRACTION, rel=1e-2) + + +def test_n_particles(triso_universe): + """Check that the function returns the correct number of particles""" + trisos = openmc.model.pack_trisos( + radius=_RADIUS, fill=triso_universe, domain_shape='cube', + domain_length=1.0, n_particles=800 + ) + assert len(trisos) == 800 + + +def test_triso_lattice(triso_universe): + trisos = openmc.model.pack_trisos( + radius=_RADIUS, fill=triso_universe, domain_shape='cube', + domain_length=1.0, domain_center=(0., 0., 0.), packing_fraction=0.2 + ) + + lower_left = np.array((-.5, -.5, -.5)) + upper_right = np.array((.5, .5, .5)) + shape = (3, 3, 3) + pitch = (upper_right - lower_left)/shape + background = openmc.Material() + + lattice = openmc.model.create_triso_lattice( + trisos, lower_left, pitch, shape, background + ) + + +def test_domain_input(triso_universe): + # Invalid domain shape + with pytest.raises(ValueError): + trisos = openmc.model.pack_trisos( + radius=1, fill=triso_universe, n_particles=100, + domain_shape='circle' + ) + # Don't specify domain length on a cube + with pytest.raises(ValueError): + trisos = openmc.model.pack_trisos( + radius=1, fill=triso_universe, n_particles=100, + domain_shape='cube' + ) + # Don't specify domain radius on a sphere + with pytest.raises(ValueError): + trisos = openmc.model.pack_trisos( + radius=1, fill=triso_universe, n_particles=100, + domain_shape='sphere' + ) + + +def test_packing_fraction_input(triso_universe): + # Provide neither packing fraction nor number of particles + with pytest.raises(ValueError): + trisos = openmc.model.pack_trisos( + radius=1, fill=triso_universe, domain_shape='cube', + domain_length=10 + ) + # Provide both packing fraction and number of particles + with pytest.raises(ValueError): + trisos = openmc.model.pack_trisos( + radius=1, fill=triso_universe, domain_shape='cube', + domain_length=10, n_particles=100, packing_fraction=0.2 + ) + # Specify a packing fraction that is too high for CRP + with pytest.raises(ValueError): + trisos = openmc.model.pack_trisos( + radius=1, fill=triso_universe, domain_shape='cube', + domain_length=10, packing_fraction=1 + ) + # Specify a packing fraction that is too high for RSP + with pytest.raises(ValueError): + trisos = openmc.model.pack_trisos( + radius=1, fill=triso_universe, domain_shape='cube', + domain_length=10, packing_fraction=0.5, + initial_packing_fraction=0.4 + ) From 8a6c6d139813c3abf6836ab760b95a8a97afdd1b Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Sun, 1 Apr 2018 07:50:14 -0500 Subject: [PATCH 04/77] Add C API bindings to create/modify meshes (and filters) --- docs/source/pythonapi/capi.rst | 3 + include/openmc.h | 8 + openmc/capi/__init__.py | 1 + openmc/capi/cell.py | 2 +- openmc/capi/filter.py | 39 ++++- openmc/capi/mesh.py | 172 ++++++++++++++++++++ src/cmfd_input.F90 | 2 +- src/mesh_header.F90 | 197 ++++++++++++++++++++++- src/tallies/tally_filter_mesh.F90 | 56 ++++--- src/tallies/tally_filter_meshsurface.F90 | 60 ++++--- tests/unit_tests/test_capi.py | 35 ++++ 11 files changed, 519 insertions(+), 56 deletions(-) create mode 100644 openmc/capi/mesh.py diff --git a/docs/source/pythonapi/capi.rst b/docs/source/pythonapi/capi.rst index f358233992..38ce61fb35 100644 --- a/docs/source/pythonapi/capi.rst +++ b/docs/source/pythonapi/capi.rst @@ -44,5 +44,8 @@ Classes EnergyFilter MaterialFilter Material + Mesh + MeshFilter + MeshSurfaceFilter Nuclide Tally diff --git a/include/openmc.h b/include/openmc.h index 1c2106432a..785aaeba53 100644 --- a/include/openmc.h +++ b/include/openmc.h @@ -53,7 +53,15 @@ extern "C" { int openmc_material_set_id(int32_t index, int32_t id); int openmc_material_filter_get_bins(int32_t index, int32_t** bins, int32_t* n); int openmc_material_filter_set_bins(int32_t index, int32_t n, const int32_t* bins); + int openmc_mesh_filter_get_mesh(int32_t index, int32_t* index_mesh); int openmc_mesh_filter_set_mesh(int32_t index, int32_t index_mesh); + int openmc_mesh_get_id(int32_t index, int32_t* id); + int openmc_mesh_get_dimension(int32_t index, int** id, int* n); + int openmc_mesh_get_params(int32_t index, double** ll, double** ur, double** width, int* n); + int openmc_mesh_set_id(int32_t index, int32_t id); + int openmc_mesh_set_dimension(int32_t index, int n, const int* dims); + int openmc_mesh_set_params(int32_t index, const double* ll, const double* ur, const double* width, int n); + int openmc_meshsurface_filter_get_mesh(int32_t index, int32_t* index_mesh); int openmc_meshsurface_filter_set_mesh(int32_t index, int32_t index_mesh); int openmc_next_batch(); int openmc_nuclide_name(int index, char** name); diff --git a/openmc/capi/__init__.py b/openmc/capi/__init__.py index bc173f9946..217e782a84 100644 --- a/openmc/capi/__init__.py +++ b/openmc/capi/__init__.py @@ -43,6 +43,7 @@ from .core import * from .nuclide import * from .material import * from .cell import * +from .mesh import * from .filter import * from .tally import * from .settings import settings diff --git a/openmc/capi/cell.py b/openmc/capi/cell.py index 0ab3f2583e..8f0c0e1bb4 100644 --- a/openmc/capi/cell.py +++ b/openmc/capi/cell.py @@ -44,7 +44,7 @@ class Cell(_FortranObjectWithID): This class exposes a cell that is stored internally in the OpenMC library. To obtain a view of a cell with a given ID, use the - :data:`openmc.capi.nuclides` mapping. + :data:`openmc.capi.cells` mapping. Parameters ---------- diff --git a/openmc/capi/filter.py b/openmc/capi/filter.py index 691ecc09cc..a2b77fa927 100644 --- a/openmc/capi/filter.py +++ b/openmc/capi/filter.py @@ -10,13 +10,14 @@ from . import _dll from .core import _FortranObjectWithID from .error import _error_handler, AllocationError, InvalidIDError from .material import Material +from .mesh import Mesh __all__ = ['Filter', 'AzimuthalFilter', 'CellFilter', 'CellbornFilter', 'CellfromFilter', 'DistribcellFilter', 'DelayedGroupFilter', 'EnergyFilter', 'EnergyoutFilter', 'EnergyFunctionFilter', 'MaterialFilter', 'MeshFilter', - 'MuFilter', 'PolarFilter', 'SurfaceFilter', + 'MeshSurfaceFilter', 'MuFilter', 'PolarFilter', 'SurfaceFilter', 'UniverseFilter', 'filters'] # Tally functions @@ -52,9 +53,15 @@ _dll.openmc_material_filter_get_bins.errcheck = _error_handler _dll.openmc_material_filter_set_bins.argtypes = [c_int32, c_int32, POINTER(c_int32)] _dll.openmc_material_filter_set_bins.restype = c_int _dll.openmc_material_filter_set_bins.errcheck = _error_handler +_dll.openmc_mesh_filter_get_mesh.argtypes = [c_int32, POINTER(c_int32)] +_dll.openmc_mesh_filter_get_mesh.restype = c_int +_dll.openmc_mesh_filter_get_mesh.errcheck = _error_handler _dll.openmc_mesh_filter_set_mesh.argtypes = [c_int32, c_int32] _dll.openmc_mesh_filter_set_mesh.restype = c_int _dll.openmc_mesh_filter_set_mesh.errcheck = _error_handler +_dll.openmc_meshsurface_filter_get_mesh.argtypes = [c_int32, POINTER(c_int32)] +_dll.openmc_meshsurface_filter_get_mesh.restype = c_int +_dll.openmc_meshsurface_filter_get_mesh.errcheck = _error_handler _dll.openmc_meshsurface_filter_set_mesh.argtypes = [c_int32, c_int32] _dll.openmc_meshsurface_filter_set_mesh.restype = c_int _dll.openmc_meshsurface_filter_set_mesh.errcheck = _error_handler @@ -190,10 +197,40 @@ class MaterialFilter(Filter): class MeshFilter(Filter): filter_type = 'mesh' + def __init__(self, mesh=None, uid=None, new=True, index=None): + super().__init__(uid, new, index) + if mesh is not None: + self.mesh = mesh + + @property + def mesh(self): + index_mesh = c_int32() + _dll.openmc_mesh_filter_get_mesh(self._index, index_mesh) + return Mesh(index=index_mesh.value) + + @mesh.setter + def mesh(self, mesh): + _dll.openmc_mesh_filter_set_mesh(self._index, mesh._index) + class MeshSurfaceFilter(Filter): filter_type = 'meshsurface' + def __init__(self, mesh=None, uid=None, new=True, index=None): + super().__init__(uid, new, index) + if mesh is not None: + self.mesh = mesh + + @property + def mesh(self): + index_mesh = c_int32() + _dll.openmc_meshsurface_filter_get_mesh(self._index, index_mesh) + return Mesh(index=index_mesh.value) + + @mesh.setter + def mesh(self, mesh): + _dll.openmc_meshsurface_filter_set_mesh(self._index, mesh._index) + class MuFilter(Filter): filter_type = 'mu' diff --git a/openmc/capi/mesh.py b/openmc/capi/mesh.py new file mode 100644 index 0000000000..c7430f9f3e --- /dev/null +++ b/openmc/capi/mesh.py @@ -0,0 +1,172 @@ +from collections.abc import Mapping, Iterable +from ctypes import c_int, c_int32, c_double, POINTER +from weakref import WeakValueDictionary + +import numpy as np +from numpy.ctypeslib import as_array + +from . import _dll +from .core import _FortranObjectWithID +from .error import _error_handler, AllocationError, InvalidIDError +from .material import Material + +__all__ = ['Mesh', 'meshes'] + +# Mesh functions +_dll.openmc_extend_meshes.argtypes = [c_int32, POINTER(c_int32), POINTER(c_int32)] +_dll.openmc_extend_meshes.restype = c_int +_dll.openmc_extend_meshes.errcheck = _error_handler +_dll.openmc_mesh_get_id.argtypes = [c_int32, POINTER(c_int32)] +_dll.openmc_mesh_get_id.restype = c_int +_dll.openmc_mesh_get_id.errcheck = _error_handler +_dll.openmc_mesh_get_dimension.argtypes = [c_int32, POINTER(POINTER(c_int)), POINTER(c_int)] +_dll.openmc_mesh_get_dimension.restype = c_int +_dll.openmc_mesh_get_dimension.errcheck = _error_handler +_dll.openmc_mesh_get_params.argtypes = [ + c_int32, POINTER(POINTER(c_double)), POINTER(POINTER(c_double)), + POINTER(POINTER(c_double)), POINTER(c_int)] +_dll.openmc_mesh_get_params.restype = c_int +_dll.openmc_mesh_get_params.errcheck = _error_handler +_dll.openmc_mesh_set_id.argtypes = [c_int32, c_int32] +_dll.openmc_mesh_set_id.restype = c_int +_dll.openmc_mesh_set_id.errcheck = _error_handler +_dll.openmc_mesh_set_dimension.argtypes = [c_int32, c_int, POINTER(c_int)] +_dll.openmc_mesh_set_dimension.restype = c_int +_dll.openmc_mesh_set_dimension.errcheck = _error_handler +_dll.openmc_mesh_set_params.argtypes = [ + c_int32, c_int, POINTER(c_double), POINTER(c_double), POINTER(c_double)] +_dll.openmc_mesh_set_params.restype = c_int +_dll.openmc_mesh_set_params.errcheck = _error_handler +_dll.openmc_get_mesh_index.argtypes = [c_int32, POINTER(c_int32)] +_dll.openmc_get_mesh_index.restype = c_int +_dll.openmc_get_mesh_index.errcheck = _error_handler + + +class Mesh(_FortranObjectWithID): + """Mesh stored internally. + + This class exposes a mesh that is stored internally in the OpenMC + library. To obtain a view of a mesh with a given ID, use the + :data:`openmc.capi.meshes` mapping. + + Parameters + ---------- + index : int + Index in the `meshes` array. + + Attributes + ---------- + id : int + ID of the mesh + + """ + __instances = WeakValueDictionary() + + def __new__(cls, uid=None, new=True, index=None): + mapping = meshes + if index is None: + if new: + # Determine ID to assign + if uid is None: + uid = max(mapping, default=0) + 1 + else: + if uid in mapping: + raise AllocationError('A mesh with ID={} has already ' + 'been allocated.'.format(uid)) + + index = c_int32() + _dll.openmc_extend_meshes(1, index, None) + index = index.value + else: + index = mapping[uid]._index + + if index not in cls.__instances: + instance = super().__new__(cls) + instance._index = index + if uid is not None: + instance.id = uid + cls.__instances[index] = instance + + return cls.__instances[index] + + @property + def id(self): + mesh_id = c_int32() + _dll.openmc_mesh_get_id(self._index, mesh_id) + return mesh_id.value + + @id.setter + def id(self, mesh_id): + _dll.openmc_mesh_set_id(self._index, mesh_id) + + @property + def dimension(self): + dims = POINTER(c_int)() + n = c_int() + _dll.openmc_mesh_get_dimension(self._index, dims, n) + return tuple(as_array(dims, (n.value,))) + + @dimension.setter + def dimension(self, dimension): + n = len(dimension) + dimension = (c_int*n)(*dimension) + _dll.openmc_mesh_set_dimension(self._index, n, dimension) + + @property + def lower_left(self): + return self._get_parameters()[0] + + @property + def upper_right(self): + return self._get_parameters()[1] + + @property + def width(self): + return self._get_parameters()[2] + + def _get_parameters(self): + ll = POINTER(c_double)() + ur = POINTER(c_double)() + w = POINTER(c_double)() + n = c_int() + _dll.openmc_mesh_get_params(self._index, ll, ur, w, n) + return ( + as_array(ll, (n.value,)), + as_array(ur, (n.value,)), + as_array(w, (n.value,)) + ) + + def set_parameters(self, lower_left=None, upper_right=None, width=None): + if lower_left is not None: + n = len(lower_left) + lower_left = (c_double*n)(*lower_left) + if upper_right is not None: + n = len(upper_right) + upper_right = (c_double*n)(*upper_right) + if width is not None: + n = len(width) + width = (c_double*n)(*width) + _dll.openmc_mesh_set_params(self._index, n, lower_left, upper_right, width) + + +class _MeshMapping(Mapping): + def __getitem__(self, key): + index = c_int32() + try: + _dll.openmc_get_mesh_index(key, index) + except (AllocationError, InvalidIDError) as e: + # __contains__ expects a KeyError to work correctly + raise KeyError(str(e)) + return Mesh(index=index.value) + + def __iter__(self): + for i in range(len(self)): + yield Mesh(index=i + 1).id + + def __len__(self): + return c_int32.in_dll(_dll, 'n_meshes').value + + def __repr__(self): + return repr(dict(self)) + +meshes = _MeshMapping() diff --git a/src/cmfd_input.F90 b/src/cmfd_input.F90 index 86f4e2400e..40b4abf572 100644 --- a/src/cmfd_input.F90 +++ b/src/cmfd_input.F90 @@ -278,7 +278,7 @@ contains m % id = i_start ! Set mesh type to rectangular - m % type = LATTICE_RECT + m % type = MESH_REGULAR ! Get pointer to mesh XML node node_mesh = root % child("mesh") diff --git a/src/mesh_header.F90 b/src/mesh_header.F90 index 8a2d61fd92..b1751a4676 100644 --- a/src/mesh_header.F90 +++ b/src/mesh_header.F90 @@ -6,7 +6,7 @@ module mesh_header use constants use dict_header, only: DictIntInt - use error, only: warning, fatal_error + use error use hdf5_interface use string, only: to_str, to_lower use xml_interface @@ -15,6 +15,13 @@ module mesh_header private public :: free_memory_mesh public :: openmc_extend_meshes + public :: openmc_get_mesh_index + public :: openmc_mesh_get_id + public :: openmc_mesh_get_dimension + public :: openmc_mesh_get_params + public :: openmc_mesh_set_id + public :: openmc_mesh_set_dimension + public :: openmc_mesh_set_params !=============================================================================== ! STRUCTUREDMESH represents a tessellation of n-dimensional Euclidean space by @@ -23,13 +30,13 @@ module mesh_header type, public :: RegularMesh integer :: id = -1 ! user-specified id - integer :: type ! rectangular, hexagonal - integer :: n_dimension ! rank of mesh + integer :: type = MESH_REGULAR ! rectangular, hexagonal + integer(C_INT) :: n_dimension ! rank of mesh real(8) :: volume_frac ! volume fraction of each cell - integer, allocatable :: dimension(:) ! number of cells in each direction - real(8), allocatable :: lower_left(:) ! lower-left corner of mesh - real(8), allocatable :: upper_right(:) ! upper-right corner of mesh - real(8), allocatable :: width(:) ! width of each mesh cell + integer(C_INT), allocatable :: dimension(:) ! number of cells in each direction + real(C_DOUBLE), allocatable :: lower_left(:) ! lower-left corner of mesh + real(C_DOUBLE), allocatable :: upper_right(:) ! upper-right corner of mesh + real(C_DOUBLE), allocatable :: width(:) ! width of each mesh cell contains procedure :: from_xml => regular_from_xml procedure :: get_bin => regular_get_bin @@ -592,4 +599,180 @@ contains err = 0 end function openmc_extend_meshes + + function openmc_get_mesh_index(id, index) result(err) bind(C) + ! Return the index in the meshes array of a mesh with a given ID + integer(C_INT32_T), value :: id + integer(C_INT32_T), intent(out) :: index + integer(C_INT) :: err + + if (allocated(meshes)) then + if (mesh_dict % has(id)) then + index = mesh_dict % get(id) + err = 0 + else + err = E_INVALID_ID + call set_errmsg("No mesh exists with ID=" // trim(to_str(id)) // ".") + end if + else + err = E_ALLOCATE + call set_errmsg("Memory has not been allocated for meshes.") + end if + end function openmc_get_mesh_index + + + function openmc_mesh_get_id(index, id) result(err) bind(C) + ! Return the ID of a mesh + integer(C_INT32_T), value :: index + integer(C_INT32_T), intent(out) :: id + integer(C_INT) :: err + + if (index >= 1 .and. index <= size(meshes)) then + id = meshes(index) % id + err = 0 + else + err = E_OUT_OF_BOUNDS + call set_errmsg("Index in meshes array is out of bounds.") + end if + end function openmc_mesh_get_id + + + function openmc_mesh_set_id(index, id) result(err) bind(C) + ! Set the ID of a mesh + integer(C_INT32_T), value, intent(in) :: index + integer(C_INT32_T), value, intent(in) :: id + integer(C_INT) :: err + + if (index >= 1 .and. index <= n_meshes) then + meshes(index) % id = id + call mesh_dict % set(id, index) + err = 0 + else + err = E_OUT_OF_BOUNDS + call set_errmsg("Index in meshes array is out of bounds.") + end if + end function openmc_mesh_set_id + + + function openmc_mesh_get_dimension(index, dims, n) result(err) bind(C) + ! Get the dimension of a mesh + integer(C_INT32_T), value, intent(in) :: index + type(C_PTR), intent(out) :: dims + integer(C_INT), intent(out) :: n + integer(C_INT) :: err + + if (index >= 1 .and. index <= n_meshes) then + dims = C_LOC(meshes(index) % dimension) + n = meshes(index) % n_dimension + err = 0 + else + err = E_OUT_OF_BOUNDS + call set_errmsg("Index in meshes array is out of bounds.") + end if + end function openmc_mesh_get_dimension + + + function openmc_mesh_set_dimension(index, n, dims) result(err) bind(C) + ! Set the dimension of a mesh + integer(C_INT32_T), value, intent(in) :: index + integer(C_INT), value, intent(in) :: n + integer(C_INT), intent(in) :: dims(n) + integer(C_INT) :: err + + if (index >= 1 .and. index <= n_meshes) then + associate (m => meshes(index)) + if (allocated(m % dimension)) deallocate (m % dimension) + if (allocated(m % lower_left)) deallocate (m % lower_left) + if (allocated(m % upper_right)) deallocate (m % upper_right) + if (allocated(m % width)) deallocate (m % width) + + m % n_dimension = n + allocate(m % dimension(n)) + allocate(m % lower_left(n)) + allocate(m % upper_right(n)) + allocate(m % width(n)) + + ! Copy dimension + m % dimension(:) = dims + end associate + err = 0 + else + err = E_OUT_OF_BOUNDS + call set_errmsg("Index in meshes array is out of bounds.") + end if + end function openmc_mesh_set_dimension + + + function openmc_mesh_get_params(index, ll, ur, width, n) result(err) bind(C) + ! Get the mesh parameters + integer(C_INT32_T), value, intent(in) :: index + type(C_PTR), intent(out) :: ll + type(C_PTR), intent(out) :: ur + type(C_PTR), intent(out) :: width + integer(C_INT), intent(out) :: n + integer(C_INT) :: err + + err = 0 + if (index >= 1 .and. index <= n_meshes) then + associate (m => meshes(index)) + if (allocated(m % lower_left)) then + ll = C_LOC(m % lower_left) + ur = C_LOC(m % upper_right) + width = C_LOC(m % width) + n = m % n_dimension + else + err = E_ALLOCATE + call set_errmsg("Mesh parameters have not been set.") + end if + end associate + else + err = E_OUT_OF_BOUNDS + call set_errmsg("Index in meshes array is out of bounds.") + end if + end function openmc_mesh_get_params + + + function openmc_mesh_set_params(index, n, ll, ur, width) result(err) bind(C) + ! Set the mesh parameters + integer(C_INT32_T), value, intent(in) :: index + integer(C_INT), value, intent(in) :: n + real(C_DOUBLE), intent(in), optional :: ll(n) + real(C_DOUBLE), intent(in), optional :: ur(n) + real(C_DOUBLE), intent(in), optional :: width(n) + integer(C_INT) :: err + + err = 0 + if (index >= 1 .and. index <= n_meshes) then + associate (m => meshes(index)) + if (allocated(m % lower_left)) deallocate (m % lower_left) + if (allocated(m % upper_right)) deallocate (m % upper_right) + if (allocated(m % width)) deallocate (m % width) + + allocate(m % lower_left(n)) + allocate(m % upper_right(n)) + allocate(m % width(n)) + + if (present(ll) .and. present(ur)) then + m % lower_left(:) = ll + m % upper_right(:) = ur + m % width(:) = (ur - ll) / m % dimension + elseif (present(ll) .and. present(width)) then + m % lower_left(:) = ll + m % width(:) = width + m % upper_right(:) = ll + width * m % dimension + elseif (present(ur) .and. present(width)) then + m % upper_right(:) = ur + m % width(:) = width + m % lower_left(:) = ur - width * m % dimension + else + err = E_INVALID_ARGUMENT + call set_errmsg("At least two parameters must be specified.") + end if + end associate + else + err = E_OUT_OF_BOUNDS + call set_errmsg("Index in meshes array is out of bounds.") + end if + end function openmc_mesh_set_params + end module mesh_header diff --git a/src/tallies/tally_filter_mesh.F90 b/src/tallies/tally_filter_mesh.F90 index 3c0e6250c2..d2acdc4c8a 100644 --- a/src/tallies/tally_filter_mesh.F90 +++ b/src/tallies/tally_filter_mesh.F90 @@ -16,6 +16,7 @@ module tally_filter_mesh implicit none private + public :: openmc_mesh_filter_get_mesh public :: openmc_mesh_filter_set_mesh !=============================================================================== @@ -280,35 +281,46 @@ contains ! C API FUNCTIONS !=============================================================================== + function openmc_mesh_filter_get_mesh(index, index_mesh) result(err) bind(C) + ! Get the mesh for a mesh filter + integer(C_INT32_T), value, intent(in) :: index + integer(C_INT32_T), intent(out) :: index_mesh + integer(C_INT) :: err + + err = verify_filter(index) + if (err == 0) then + select type (f => filters(index) % obj) + type is (MeshFilter) + index_mesh = f % mesh + class default + err = E_INVALID_TYPE + call set_errmsg("Tried to set mesh on a non-mesh filter.") + end select + end if + end function openmc_mesh_filter_get_mesh + + function openmc_mesh_filter_set_mesh(index, index_mesh) result(err) bind(C) ! Set the mesh for a mesh filter integer(C_INT32_T), value, intent(in) :: index integer(C_INT32_T), value, intent(in) :: index_mesh integer(C_INT) :: err - err = 0 - if (index >= 1 .and. index <= n_filters) then - if (allocated(filters(index) % obj)) then - select type (f => filters(index) % obj) - type is (MeshFilter) - if (index_mesh >= 1 .and. index_mesh <= n_meshes) then - f % mesh = index_mesh - f % n_bins = product(meshes(index_mesh) % dimension) - else - err = E_OUT_OF_BOUNDS - call set_errmsg("Index in 'meshes' array is out of bounds.") - end if + err = verify_filter(index) + if (err == 0) then + select type (f => filters(index) % obj) + type is (MeshFilter) + if (index_mesh >= 1 .and. index_mesh <= n_meshes) then + f % mesh = index_mesh + f % n_bins = product(meshes(index_mesh) % dimension) + else + err = E_OUT_OF_BOUNDS + call set_errmsg("Index in 'meshes' array is out of bounds.") + end if class default - err = E_INVALID_TYPE - call set_errmsg("Tried to set mesh on a non-mesh filter.") - end select - else - err = E_ALLOCATE - call set_errmsg("Filter type has not been set yet.") - end if - else - err = E_OUT_OF_BOUNDS - call set_errmsg("Index in filters array out of bounds.") + err = E_INVALID_TYPE + call set_errmsg("Tried to set mesh on a non-mesh filter.") + end select end if end function openmc_mesh_filter_set_mesh diff --git a/src/tallies/tally_filter_meshsurface.F90 b/src/tallies/tally_filter_meshsurface.F90 index e1e8c48033..d90b63664e 100644 --- a/src/tallies/tally_filter_meshsurface.F90 +++ b/src/tallies/tally_filter_meshsurface.F90 @@ -16,6 +16,7 @@ module tally_filter_meshsurface implicit none private + public :: openmc_meshsurface_filter_get_mesh public :: openmc_meshsurface_filter_set_mesh !=============================================================================== @@ -296,6 +297,25 @@ contains ! C API FUNCTIONS !=============================================================================== + function openmc_meshsurface_filter_get_mesh(index, index_mesh) result(err) bind(C) + ! Get the mesh for a mesh surface filter + integer(C_INT32_T), value, intent(in) :: index + integer(C_INT32_T), intent(out) :: index_mesh + integer(C_INT) :: err + + err = verify_filter(index) + if (err == 0) then + select type (f => filters(index) % obj) + type is (MeshSurfaceFilter) + index_mesh = f % mesh + class default + err = E_INVALID_TYPE + call set_errmsg("Tried to set mesh on a non-mesh filter.") + end select + end if + end function openmc_meshsurface_filter_get_mesh + + function openmc_meshsurface_filter_set_mesh(index, index_mesh) result(err) bind(C) ! Set the mesh for a mesh surface filter integer(C_INT32_T), value, intent(in) :: index @@ -304,30 +324,22 @@ contains integer :: n_dim - err = 0 - if (index >= 1 .and. index <= n_filters) then - if (allocated(filters(index) % obj)) then - select type (f => filters(index) % obj) - type is (MeshSurfaceFilter) - if (index_mesh >= 1 .and. index_mesh <= n_meshes) then - f % mesh = index_mesh - n_dim = meshes(index_mesh) % n_dimension - f % n_bins = 4*n_dim*product(meshes(index_mesh) % dimension) - else - err = E_OUT_OF_BOUNDS - call set_errmsg("Index in 'meshes' array is out of bounds.") - end if - class default - err = E_INVALID_TYPE - call set_errmsg("Tried to set mesh on a non-mesh filter.") - end select - else - err = E_ALLOCATE - call set_errmsg("Filter type has not been set yet.") - end if - else - err = E_OUT_OF_BOUNDS - call set_errmsg("Index in filters array out of bounds.") + err = verify_filter(index) + if (err == 0) then + select type (f => filters(index) % obj) + type is (MeshSurfaceFilter) + if (index_mesh >= 1 .and. index_mesh <= n_meshes) then + f % mesh = index_mesh + n_dim = meshes(index_mesh) % n_dimension + f % n_bins = 4*n_dim*product(meshes(index_mesh) % dimension) + else + err = E_OUT_OF_BOUNDS + call set_errmsg("Index in 'meshes' array is out of bounds.") + end if + class default + err = E_INVALID_TYPE + call set_errmsg("Tried to set mesh on a non-mesh filter.") + end select end if end function openmc_meshsurface_filter_set_mesh diff --git a/tests/unit_tests/test_capi.py b/tests/unit_tests/test_capi.py index 8bc6c3d15c..66a6f3bc13 100644 --- a/tests/unit_tests/test_capi.py +++ b/tests/unit_tests/test_capi.py @@ -250,3 +250,38 @@ def test_find_material(capi_init): assert mat is openmc.capi.materials[1] mat = openmc.capi.find_material((0.4, 0., 0.)) assert mat is openmc.capi.materials[2] + + +def test_mesh(capi_init): + mesh = openmc.capi.Mesh() + mesh.dimension = (2, 3, 4) + assert mesh.dimension == (2, 3, 4) + with pytest.raises(openmc.capi.AllocationError): + mesh2 = openmc.capi.Mesh(mesh.id) + + # Make sure each combination of parameters works + ll = (0., 0., 0.) + ur = (10., 10., 10.) + width = (1., 1., 1.) + mesh.set_parameters(lower_left=ll, upper_right=ur) + assert mesh.lower_left == pytest.approx(ll) + assert mesh.upper_right == pytest.approx(ur) + mesh.set_parameters(lower_left=ll, width=width) + assert mesh.lower_left == pytest.approx(ll) + assert mesh.width == pytest.approx(width) + mesh.set_parameters(upper_right=ur, width=width) + assert mesh.upper_right == pytest.approx(ur) + assert mesh.width == pytest.approx(width) + + meshes = openmc.capi.meshes + assert isinstance(meshes, Mapping) + assert len(meshes) == 1 + for mesh_id, mesh in meshes.items(): + assert isinstance(mesh, openmc.capi.Mesh) + assert mesh_id == mesh.id + + mf = openmc.capi.MeshFilter(mesh) + assert mf.mesh == mesh + + msf = openmc.capi.MeshSurfaceFilter(mesh) + assert msf.mesh == mesh From 4be18cb9e905862e939172c5220b1e314fa581a8 Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Mon, 2 Apr 2018 11:41:02 -0500 Subject: [PATCH 05/77] Prevent ICE on gfortran 4.8 --- src/mesh_header.F90 | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/mesh_header.F90 b/src/mesh_header.F90 index b1751a4676..fc13a868e5 100644 --- a/src/mesh_header.F90 +++ b/src/mesh_header.F90 @@ -716,9 +716,9 @@ contains if (index >= 1 .and. index <= n_meshes) then associate (m => meshes(index)) if (allocated(m % lower_left)) then - ll = C_LOC(m % lower_left) - ur = C_LOC(m % upper_right) - width = C_LOC(m % width) + ll = C_LOC(m % lower_left(1)) + ur = C_LOC(m % upper_right(1)) + width = C_LOC(m % width(1)) n = m % n_dimension else err = E_ALLOCATE From f485693fa0c810279a2e74d2d88385ab89fd56e7 Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Wed, 4 Apr 2018 06:46:50 -0500 Subject: [PATCH 06/77] Support void materials in C API Python bindings --- openmc/capi/cell.py | 13 +++++++------ openmc/capi/material.py | 3 +++ src/geometry_header.F90 | 14 +++++--------- 3 files changed, 15 insertions(+), 15 deletions(-) diff --git a/openmc/capi/cell.py b/openmc/capi/cell.py index 8f0c0e1bb4..ccc6b6f6eb 100644 --- a/openmc/capi/cell.py +++ b/openmc/capi/cell.py @@ -115,14 +115,15 @@ class Cell(_FortranObjectWithID): def fill(self, fill): if isinstance(fill, Iterable): n = len(fill) - indices = (c_int*n)(*(m._index for m in fill)) - _dll.openmc_cell_set_fill(self._index, 1, 1, indices) + indices = (c_int32*n)(*(m._index if m is not None else -1 + for m in fill)) + _dll.openmc_cell_set_fill(self._index, 1, n, indices) elif isinstance(fill, Material): - materials = [fill] - indices = (c_int*1)(fill._index) + indices = (c_int32*1)(fill._index) + _dll.openmc_cell_set_fill(self._index, 1, 1, indices) + elif fill is None: + indices = (c_int32*1)(-1) _dll.openmc_cell_set_fill(self._index, 1, 1, indices) - else: - raise NotImplementedError def set_temperature(self, T, instance=None): """Set the temperature of a cell diff --git a/openmc/capi/material.py b/openmc/capi/material.py index 62d6df012a..464b8a1a33 100644 --- a/openmc/capi/material.py +++ b/openmc/capi/material.py @@ -89,6 +89,9 @@ class Material(_FortranObjectWithID): index = index.value else: index = mapping[uid]._index + elif index == -1: + # Special value indicates void material + return None if index not in cls.__instances: instance = super(Material, cls).__new__(cls) diff --git a/src/geometry_header.F90 b/src/geometry_header.F90 index e71916d096..f6206adf99 100644 --- a/src/geometry_header.F90 +++ b/src/geometry_header.F90 @@ -544,16 +544,12 @@ contains c % type = FILL_MATERIAL do i = 1, n j = indices(i) - if (j == 0) then - c % material(i) = MATERIAL_VOID + if ((j >= 1 .and. j <= n_materials) .or. j == MATERIAL_VOID) then + c % material(i) = j else - if (j >= 1 .and. j <= n_materials) then - c % material(i) = j - else - err = E_OUT_OF_BOUNDS - call set_errmsg("Index " // trim(to_str(j)) // " in the & - &materials array is out of bounds.") - end if + err = E_OUT_OF_BOUNDS + call set_errmsg("Index " // trim(to_str(j)) // " in the & + &materials array is out of bounds.") end if end do case (FILL_UNIVERSE) From 5fb3031d99e9de48f6e8f68f61abaa412f598b94 Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Wed, 4 Apr 2018 14:28:10 -0500 Subject: [PATCH 07/77] [backport] Fix/add prototypes in openmc.h --- include/openmc.h | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/include/openmc.h b/include/openmc.h index 785aaeba53..1106bf54ca 100644 --- a/include/openmc.h +++ b/include/openmc.h @@ -30,7 +30,9 @@ extern "C" { int openmc_extend_sources(int32_t n, int32_t* index_start, int32_t* index_end); int openmc_extend_tallies(int32_t n, int32_t* index_start, int32_t* index_end); int openmc_filter_get_id(int32_t index, int32_t* id); + int openmc_filter_get_type(int32_t index, const char** type); int openmc_filter_set_id(int32_t index, int32_t id); + int openmc_filter_set_type(int32_t index, const char* type); void openmc_finalize(); int openmc_find(double* xyz, int rtype, int32_t* id, int32_t* instance); int openmc_get_cell_index(int32_t id, int32_t* index); @@ -91,7 +93,8 @@ extern "C" { int openmc_tally_set_filters(int32_t index, int n, const int32_t* indices); int openmc_tally_set_id(int32_t index, int32_t id); int openmc_tally_set_nuclides(int32_t index, int n, const char** nuclides); - int openmc_tally_set_scores(int32_t index, int n, const int* scores); + int openmc_tally_set_scores(int32_t index, int n, const char** scores); + int openmc_tally_set_type(int32_t index, const char* type); int openmc_zernike_filter_get_order(int32_t index, int* order); int openmc_zernike_filter_get_params(int32_t index, double* x, double* y, double* r); int openmc_zernike_filter_set_order(int32_t index, int order); From c78d296bf69b285459468f1bfc4b94206190eaeb Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Thu, 5 Apr 2018 16:07:51 -0500 Subject: [PATCH 08/77] Have openmc_next_batch return an actual error --- include/openmc.h | 26 ++++++------- openmc/capi/cell.py | 3 +- openmc/capi/core.py | 30 +++++++++----- openmc/capi/error.py | 73 +++++++++-------------------------- openmc/capi/filter.py | 3 +- openmc/capi/material.py | 3 +- openmc/capi/mesh.py | 3 +- openmc/capi/nuclide.py | 3 +- openmc/capi/tally.py | 3 +- openmc/exceptions.py | 38 ++++++++++++++++++ src/error.F90 | 22 +++++------ src/main.F90 | 5 ++- src/simulation.F90 | 40 ++++++++++++------- tests/unit_tests/test_capi.py | 19 ++++----- 14 files changed, 154 insertions(+), 117 deletions(-) create mode 100644 openmc/exceptions.py diff --git a/include/openmc.h b/include/openmc.h index 1106bf54ca..11a39e1ff3 100644 --- a/include/openmc.h +++ b/include/openmc.h @@ -65,11 +65,11 @@ extern "C" { int openmc_mesh_set_params(int32_t index, const double* ll, const double* ur, const double* width, int n); int openmc_meshsurface_filter_get_mesh(int32_t index, int32_t* index_mesh); int openmc_meshsurface_filter_set_mesh(int32_t index, int32_t index_mesh); - int openmc_next_batch(); + int openmc_next_batch(int* status); int openmc_nuclide_name(int index, char** name); void openmc_plot_geometry(); void openmc_reset(); - void openmc_run(); + int openmc_run(); void openmc_simulation_finalize(); void openmc_simulation_init(); int openmc_source_bank(struct Bank** ptr, int64_t* n); @@ -102,17 +102,17 @@ extern "C" { const double* y, const double* r); // Error codes - extern int E_UNASSIGNED; - extern int E_ALLOCATE; - extern int E_OUT_OF_BOUNDS; - extern int E_INVALID_SIZE; - extern int E_INVALID_ARGUMENT; - extern int E_INVALID_TYPE; - extern int E_INVALID_ID; - extern int E_GEOMETRY; - extern int E_DATA; - extern int E_PHYSICS; - extern int E_WARNING; + extern int OPENMC_E_UNASSIGNED; + extern int OPENMC_E_ALLOCATE; + extern int OPENMC_E_OUT_OF_BOUNDS; + extern int OPENMC_E_INVALID_SIZE; + extern int OPENMC_E_INVALID_ARGUMENT; + extern int OPENMC_E_INVALID_TYPE; + extern int OPENMC_E_INVALID_ID; + extern int OPENMC_E_GEOMETRY; + extern int OPENMC_E_DATA; + extern int OPENMC_E_PHYSICS; + extern int OPENMC_E_WARNING; // Global variables extern char openmc_err_msg[256]; diff --git a/openmc/capi/cell.py b/openmc/capi/cell.py index ccc6b6f6eb..258e773dce 100644 --- a/openmc/capi/cell.py +++ b/openmc/capi/cell.py @@ -5,9 +5,10 @@ from weakref import WeakValueDictionary import numpy as np from numpy.ctypeslib import as_array +from openmc.exceptions import AllocationError, InvalidIDError from . import _dll from .core import _FortranObjectWithID -from .error import _error_handler, AllocationError, InvalidIDError +from .error import _error_handler from .material import Material __all__ = ['Cell', 'cells'] diff --git a/openmc/capi/core.py b/openmc/capi/core.py index 415fa2e936..f80b5fe540 100644 --- a/openmc/capi/core.py +++ b/openmc/capi/core.py @@ -6,8 +6,9 @@ from warnings import warn import numpy as np from numpy.ctypeslib import as_array +from openmc.exceptions import AllocationError from . import _dll -from .error import _error_handler, AllocationError +from .error import _error_handler import openmc.capi @@ -31,9 +32,12 @@ _dll.openmc_init.restype = None _dll.openmc_get_keff.argtypes = [POINTER(c_double*2)] _dll.openmc_get_keff.restype = c_int _dll.openmc_get_keff.errcheck = _error_handler +_dll.openmc_next_batch.argtypes = [POINTER(c_int)] _dll.openmc_next_batch.restype = c_int +_dll.openmc_next_batch.errcheck = _error_handler _dll.openmc_plot_geometry.restype = None -_dll.openmc_run.restype = None +_dll.openmc_run.restype = c_int +_dll.openmc_run.errcheck = _error_handler _dll.openmc_reset.restype = None _dll.openmc_source_bank.argtypes = [POINTER(POINTER(_Bank)), POINTER(c_int64)] _dll.openmc_source_bank.restype = c_int @@ -147,13 +151,13 @@ def iter_batches(): """ while True: # Run next batch - retval = next_batch() + status = next_batch() # Provide opportunity for user to perform action between batches yield # End the iteration - if retval < 0: + if status != 0: break @@ -180,12 +184,18 @@ def keff(): def next_batch(): - """Run next batch.""" - retval = _dll.openmc_next_batch() - if retval == -3: - raise AllocationError('Simulation has not been initialized. You must call ' - 'openmc.capi.simulation_init() first.') - return retval + """Run next batch. + + Returns + ------- + int + Status after running a batch (0=normal, 1=reached maximum number of + batches, 2=tally triggers reached) + + """ + status = c_int() + _dll.openmc_next_batch(status) + return status.value def plot_geometry(): diff --git a/openmc/capi/error.py b/openmc/capi/error.py index a11d6ea87d..b35de4e60c 100644 --- a/openmc/capi/error.py +++ b/openmc/capi/error.py @@ -1,45 +1,10 @@ from ctypes import c_int, c_char from warnings import warn +import openmc.exceptions as exc from . import _dll -class OpenMCError(Exception): - """Root exception class for OpenMC.""" - - -class GeometryError(OpenMCError): - """Geometry-related error""" - - -class InvalidIDError(OpenMCError): - """Use of an ID that is invalid.""" - - -class AllocationError(OpenMCError): - """Error related to memory allocation.""" - - -class OutOfBoundsError(OpenMCError): - """Index in array out of bounds.""" - - -class DataError(OpenMCError): - """Error relating to nuclear data.""" - - -class PhysicsError(OpenMCError): - """Error relating to performing physics.""" - - -class InvalidArgumentError(OpenMCError): - """Argument passed was invalid.""" - - -class InvalidTypeError(OpenMCError): - """Tried to perform an operation on the wrong type.""" - - def _error_handler(err, func, args): """Raise exception according to error code.""" @@ -52,23 +17,23 @@ def _error_handler(err, func, args): msg = errmsg.value.decode() # Raise exception type corresponding to error code - if err == errcode('e_allocate'): - raise AllocationError(msg) - elif err == errcode('e_out_of_bounds'): - raise OutOfBoundsError(msg) - elif err == errcode('e_invalid_argument'): - raise InvalidArgumentError(msg) - elif err == errcode('e_invalid_type'): - raise InvalidTypeError(msg) - if err == errcode('e_invalid_id'): - raise InvalidIDError(msg) - elif err == errcode('e_geometry'): - raise GeometryError(msg) - elif err == errcode('e_data'): - raise DataError(msg) - elif err == errcode('e_physics'): - raise PhysicsError(msg) - elif err == errcode('e_warning'): + if err == errcode('OPENMC_E_ALLOCATE'): + raise exc.AllocationError(msg) + elif err == errcode('OPENMC_E_OUT_OF_BOUNDS'): + raise exc.OutOfBoundsError(msg) + elif err == errcode('OPENMC_E_INVALID_ARGUMENT'): + raise exc.InvalidArgumentError(msg) + elif err == errcode('OPENMC_E_INVALID_TYPE'): + raise exc.InvalidTypeError(msg) + if err == errcode('OPENMC_E_INVALID_ID'): + raise exc.InvalidIDError(msg) + elif err == errcode('OPENMC_E_GEOMETRY'): + raise exc.GeometryError(msg) + elif err == errcode('OPENMC_E_DATA'): + raise exc.DataError(msg) + elif err == errcode('OPENMC_E_PHYSICS'): + raise exc.PhysicsError(msg) + elif err == errcode('OPENMC_E_WARNING'): warn(msg) elif err < 0: - raise OpenMCError("Unknown error encountered (code {}).".format(err)) + raise exc.OpenMCError("Unknown error encountered (code {}).".format(err)) diff --git a/openmc/capi/filter.py b/openmc/capi/filter.py index a2b77fa927..5c21c3ef4b 100644 --- a/openmc/capi/filter.py +++ b/openmc/capi/filter.py @@ -6,9 +6,10 @@ from weakref import WeakValueDictionary import numpy as np from numpy.ctypeslib import as_array +from openmc.exceptions import AllocationError, InvalidIDError from . import _dll from .core import _FortranObjectWithID -from .error import _error_handler, AllocationError, InvalidIDError +from .error import _error_handler from .material import Material from .mesh import Mesh diff --git a/openmc/capi/material.py b/openmc/capi/material.py index 464b8a1a33..a6c29a3751 100644 --- a/openmc/capi/material.py +++ b/openmc/capi/material.py @@ -5,9 +5,10 @@ from weakref import WeakValueDictionary import numpy as np from numpy.ctypeslib import as_array +from openmc.exceptions import AllocationError, InvalidIDError from . import _dll, Nuclide from .core import _FortranObjectWithID -from .error import _error_handler, AllocationError, InvalidIDError +from .error import _error_handler __all__ = ['Material', 'materials'] diff --git a/openmc/capi/mesh.py b/openmc/capi/mesh.py index c7430f9f3e..326f5f61ed 100644 --- a/openmc/capi/mesh.py +++ b/openmc/capi/mesh.py @@ -5,9 +5,10 @@ from weakref import WeakValueDictionary import numpy as np from numpy.ctypeslib import as_array +from openmc.exceptions import AllocationError, InvalidIDError from . import _dll from .core import _FortranObjectWithID -from .error import _error_handler, AllocationError, InvalidIDError +from .error import _error_handler from .material import Material __all__ = ['Mesh', 'meshes'] diff --git a/openmc/capi/nuclide.py b/openmc/capi/nuclide.py index f66212c971..e57653c64d 100644 --- a/openmc/capi/nuclide.py +++ b/openmc/capi/nuclide.py @@ -5,9 +5,10 @@ from weakref import WeakValueDictionary import numpy as np from numpy.ctypeslib import as_array +from openmc.exceptions import DataError, AllocationError from . import _dll from .core import _FortranObject -from .error import _error_handler, DataError, AllocationError +from .error import _error_handler __all__ = ['Nuclide', 'nuclides', 'load_nuclide'] diff --git a/openmc/capi/tally.py b/openmc/capi/tally.py index a78347177d..46a967f690 100644 --- a/openmc/capi/tally.py +++ b/openmc/capi/tally.py @@ -6,10 +6,11 @@ import numpy as np from numpy.ctypeslib import as_array import scipy.stats +from openmc.exceptions import AllocationError, InvalidIDError from openmc.data.reaction import REACTION_NAME from . import _dll, Nuclide from .core import _FortranObjectWithID -from .error import _error_handler, AllocationError, InvalidIDError +from .error import _error_handler from .filter import _get_filter diff --git a/openmc/exceptions.py b/openmc/exceptions.py new file mode 100644 index 0000000000..c87bfc82c9 --- /dev/null +++ b/openmc/exceptions.py @@ -0,0 +1,38 @@ +class OpenMCError(Exception): + """Root exception class for OpenMC.""" + + +class GeometryError(OpenMCError): + """Geometry-related error""" + + +class InvalidIDError(OpenMCError): + """Use of an ID that is invalid.""" + + +class AllocationError(OpenMCError): + """Error related to memory allocation.""" + + +class OutOfBoundsError(OpenMCError): + """Index in array out of bounds.""" + + +class DataError(OpenMCError): + """Error relating to nuclear data.""" + + +class PhysicsError(OpenMCError): + """Error relating to performing physics.""" + + +class InvalidArgumentError(OpenMCError): + """Argument passed was invalid.""" + + +class InvalidTypeError(OpenMCError): + """Tried to perform an operation on the wrong type.""" + + +class SetupError(OpenMCError): + """Error while setting up a problem.""" diff --git a/src/error.F90 b/src/error.F90 index 0a5af302d6..f4fb34173c 100644 --- a/src/error.F90 +++ b/src/error.F90 @@ -15,19 +15,19 @@ module error public :: write_message ! Error codes - integer(C_INT), public, bind(C) :: E_UNASSIGNED = -1 - integer(C_INT), public, bind(C) :: E_ALLOCATE = -2 - integer(C_INT), public, bind(C) :: E_OUT_OF_BOUNDS = -3 - integer(C_INT), public, bind(C) :: E_INVALID_SIZE = -4 - integer(C_INT), public, bind(C) :: E_INVALID_ARGUMENT = -5 - integer(C_INT), public, bind(C) :: E_INVALID_TYPE = -6 - integer(C_INT), public, bind(C) :: E_INVALID_ID = -7 - integer(C_INT), public, bind(C) :: E_GEOMETRY = -8 - integer(C_INT), public, bind(C) :: E_DATA = -9 - integer(C_INT), public, bind(C) :: E_PHYSICS = -10 + integer(C_INT), public, bind(C, name='OPENMC_E_UNASSIGNED') :: E_UNASSIGNED = -1 + integer(C_INT), public, bind(C, name='OPENMC_E_ALLOCATE') :: E_ALLOCATE = -2 + integer(C_INT), public, bind(C, name='OPENMC_E_OUT_OF_BOUNDS') :: E_OUT_OF_BOUNDS = -3 + integer(C_INT), public, bind(C, name='OPENMC_E_INVALID_SIZE') :: E_INVALID_SIZE = -4 + integer(C_INT), public, bind(C, name='OPENMC_E_INVALID_ARGUMENT') :: E_INVALID_ARGUMENT = -5 + integer(C_INT), public, bind(C, name='OPENMC_E_INVALID_TYPE') :: E_INVALID_TYPE = -6 + integer(C_INT), public, bind(C, name='OPENMC_E_INVALID_ID') :: E_INVALID_ID = -7 + integer(C_INT), public, bind(C, name='OPENMC_E_GEOMETRY') :: E_GEOMETRY = -8 + integer(C_INT), public, bind(C, name='OPENMC_E_DATA') :: E_DATA = -9 + integer(C_INT), public, bind(C, name='OPENMC_E_PHYSICS') :: E_PHYSICS = -10 ! Warning codes - integer(C_INT), public, bind(C) :: E_WARNING = 1 + integer(C_INT), public, bind(C, name='OPENMC_E_WARNING') :: E_WARNING = 1 ! Error message character(kind=C_CHAR), public, bind(C) :: openmc_err_msg(256) diff --git a/src/main.F90 b/src/main.F90 index 120bdd1e0c..372e993f5d 100644 --- a/src/main.F90 +++ b/src/main.F90 @@ -1,5 +1,7 @@ program main + use, intrinsic :: ISO_C_BINDING + use constants use message_passing use openmc_api, only: openmc_init, openmc_finalize, openmc_run, & @@ -9,6 +11,7 @@ program main implicit none + integer(C_INT) :: err #ifdef OPENMC_MPI integer :: mpi_err ! MPI error code #endif @@ -27,7 +30,7 @@ program main ! start problem based on mode select case (run_mode) case (MODE_FIXEDSOURCE, MODE_EIGENVALUE) - call openmc_run() + err = openmc_run() case (MODE_PLOTTING) call openmc_plot_geometry() case (MODE_PARTICLE) diff --git a/src/simulation.F90 b/src/simulation.F90 index 8fe4f025c3..68debe52ba 100644 --- a/src/simulation.F90 +++ b/src/simulation.F90 @@ -48,6 +48,10 @@ module simulation public :: openmc_simulation_init public :: openmc_simulation_finalize + integer(C_INT), parameter :: STATUS_EXIT_NORMAL = 0 + integer(C_INT), parameter :: STATUS_EXIT_MAX_BATCH = 1 + integer(C_INT), parameter :: STATUS_EXIT_ON_TRIGGER = 2 + contains !=============================================================================== @@ -56,28 +60,36 @@ contains ! calculation. !=============================================================================== - subroutine openmc_run() bind(C) + function openmc_run() result(err) bind(C) + integer(C_INT) :: err + integer(C_INT) :: status call openmc_simulation_init() - do while (openmc_next_batch() == 0) + do + err = openmc_next_batch(status) + if (status /= 0 .or. err < 0) exit end do call openmc_simulation_finalize() - end subroutine openmc_run + end function openmc_run !=============================================================================== ! OPENMC_NEXT_BATCH !=============================================================================== - function openmc_next_batch() result(retval) bind(C) - integer(C_INT) :: retval + function openmc_next_batch(status) result(err) bind(C) + integer(C_INT), intent(out), optional :: status + integer(C_INT) :: err type(Particle) :: p integer(8) :: i_work + err = 0 + ! Make sure simulation has been initialized if (.not. simulation_initialized) then - retval = -3 + err = E_ALLOCATE + call set_errmsg("Simulation has not been initialized yet.") return end if @@ -86,7 +98,7 @@ contains ! Handle restart runs if (restart_run .and. current_batch <= restart_batch) then call replay_batch_history() - retval = 0 + status = STATUS_EXIT_NORMAL return end if @@ -124,12 +136,14 @@ contains call finalize_batch() ! Check simulation ending criteria - if (current_batch == n_max_batches) then - retval = -1 - elseif (satisfy_triggers) then - retval = -2 - else - retval = 0 + if (present(status)) then + if (current_batch == n_max_batches) then + status = STATUS_EXIT_MAX_BATCH + elseif (satisfy_triggers) then + status = STATUS_EXIT_ON_TRIGGER + else + status = STATUS_EXIT_NORMAL + end if end if end function openmc_next_batch diff --git a/tests/unit_tests/test_capi.py b/tests/unit_tests/test_capi.py index 66a6f3bc13..6c05f5d3e3 100644 --- a/tests/unit_tests/test_capi.py +++ b/tests/unit_tests/test_capi.py @@ -4,6 +4,7 @@ import os import numpy as np import pytest import openmc +import openmc.exceptions as exc import openmc.capi from tests import cdtemp @@ -60,7 +61,7 @@ def test_cell(capi_init): def test_new_cell(capi_init): - with pytest.raises(openmc.capi.AllocationError): + with pytest.raises(exc.AllocationError): openmc.capi.Cell(1) new_cell = openmc.capi.Cell() new_cell_with_id = openmc.capi.Cell(10) @@ -91,7 +92,7 @@ def test_material(capi_init): def test_new_material(capi_init): - with pytest.raises(openmc.capi.AllocationError): + with pytest.raises(exc.AllocationError): openmc.capi.Material(1) new_mat = openmc.capi.Material() new_mat_with_id = openmc.capi.Material(10) @@ -109,7 +110,7 @@ def test_nuclide_mapping(capi_init): def test_load_nuclide(capi_init): openmc.capi.load_nuclide('Pu239') - with pytest.raises(openmc.capi.DataError): + with pytest.raises(exc.DataError): openmc.capi.load_nuclide('Pu3') @@ -145,7 +146,7 @@ def test_tally(capi_init): assert isinstance(t.filters[1], openmc.capi.EnergyFilter) # Create new filter and replace existing - with pytest.raises(openmc.capi.AllocationError): + with pytest.raises(exc.AllocationError): openmc.capi.MaterialFilter(uid=1) mats = openmc.capi.materials f = openmc.capi.MaterialFilter([mats[2], mats[1]]) @@ -153,7 +154,7 @@ def test_tally(capi_init): assert t.filters == [f] assert t.nuclides == ['U235', 'U238'] - with pytest.raises(openmc.capi.DataError): + with pytest.raises(exc.DataError): t.nuclides = ['Zr2'] t.nuclides = ['U234', 'Zr90'] assert t.nuclides == ['U234', 'Zr90'] @@ -165,7 +166,7 @@ def test_tally(capi_init): def test_new_tally(capi_init): - with pytest.raises(openmc.capi.AllocationError): + with pytest.raises(exc.AllocationError): openmc.capi.Material(1) new_tally = openmc.capi.Tally() new_tally.scores = ['flux'] @@ -206,7 +207,7 @@ def test_by_batch(capi_run): # Running next batch before simulation is initialized should raise an # exception - with pytest.raises(openmc.capi.AllocationError): + with pytest.raises(exc.AllocationError): openmc.capi.next_batch() openmc.capi.simulation_init() @@ -241,7 +242,7 @@ def test_find_cell(capi_init): assert cell is openmc.capi.cells[1] cell, instance = openmc.capi.find_cell((0.4, 0., 0.)) assert cell is openmc.capi.cells[2] - with pytest.raises(openmc.capi.GeometryError): + with pytest.raises(exc.GeometryError): openmc.capi.find_cell((100., 100., 100.)) @@ -256,7 +257,7 @@ def test_mesh(capi_init): mesh = openmc.capi.Mesh() mesh.dimension = (2, 3, 4) assert mesh.dimension == (2, 3, 4) - with pytest.raises(openmc.capi.AllocationError): + with pytest.raises(exc.AllocationError): mesh2 = openmc.capi.Mesh(mesh.id) # Make sure each combination of parameters works From 336c38da2f1ef9d9be6ba52536765bde3d1ce541 Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Thu, 12 Apr 2018 07:18:47 -0500 Subject: [PATCH 09/77] Fix typo in openmc.h --- include/openmc.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/openmc.h b/include/openmc.h index 11a39e1ff3..d24ca4af96 100644 --- a/include/openmc.h +++ b/include/openmc.h @@ -16,7 +16,7 @@ extern "C" { int delayed_group; }; - void openmc_calculate_voumes(); + void openmc_calculate_volumes(); int openmc_cell_get_fill(int32_t index, int* type, int32_t** indices, int32_t* n); int openmc_cell_get_id(int32_t index, int32_t* id); int openmc_cell_set_fill(int32_t index, int type, int32_t n, const int32_t* indices); From c80379a48816ea17936c108863ed8633046dacc5 Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Fri, 13 Apr 2018 15:04:04 -0500 Subject: [PATCH 10/77] Docfix for openmc.data.Library.get_by_material --- openmc/data/library.py | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/openmc/data/library.py b/openmc/data/library.py index 34cd380a55..adfa3e4cb8 100644 --- a/openmc/data/library.py +++ b/openmc/data/library.py @@ -23,9 +23,14 @@ class DataLibrary(EqualityMixin): def __init__(self): self.libraries = [] - def get_by_material(self, value): + def get_by_material(self, name): """Return the library dictionary containing a given material. + Parameters + ---------- + name : str + Name of material, e.g. 'Am241' + Returns ------- library : dict or None @@ -34,7 +39,7 @@ class DataLibrary(EqualityMixin): """ for library in self.libraries: - if value in library['materials']: + if name in library['materials']: return library return None From 932bb7157e6871a71a841384d278e70fc5444a7b Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Fri, 13 Apr 2018 16:05:46 -0500 Subject: [PATCH 11/77] Fix file format documentation for settings.xml --- docs/source/io_formats/settings.rst | 87 ++++++++++++++--------------- 1 file changed, 43 insertions(+), 44 deletions(-) diff --git a/docs/source/io_formats/settings.rst b/docs/source/io_formats/settings.rst index 0aa058cdba..d2cb3b1253 100644 --- a/docs/source/io_formats/settings.rst +++ b/docs/source/io_formats/settings.rst @@ -93,29 +93,13 @@ or ``multi-group``. *Default*: continuous-energy ---------------------- -```` Element ---------------------- +-------------------------- +```` Element +-------------------------- -The ```` element describes a mesh that is used for calculating Shannon -entropy. This mesh should cover all possible fissionable materials in the -problem. It has the following attributes/sub-elements: - - :dimension: - The number of mesh cells in the x, y, and z directions, respectively. - - *Default*: If this tag is not present, the number of mesh cells is - automatically determined by the code. - - :lower_left: - The Cartesian coordinates of the lower-left corner of the mesh. - - *Default*: None - - :upper_right: - The Cartesian coordinates of the upper-right corner of the mesh. - - *Default*: None +The ```` element indicates the ID of a mesh that is to be used for +calculating Shannon entropy. The mesh should cover all possible fissionable +materials in the problem and is specified using a :ref:`mesh_element`. ----------------------------------- ```` Element @@ -199,6 +183,36 @@ then, OpenMC will only use up to the :math:`P_1` data. .. note:: This element is not used in the continuous-energy :ref:`energy_mode`. +.. _mesh_element: + +------------------ +```` Element +------------------ + +The ```` element describes a mesh that is used either for calculating +Shannon entropy, applying the uniform fission site method, or in tallies. For +Shannon entropy meshes, the mesh should cover all possible fissionable materials +in the problem. It has the following attributes/sub-elements: + + :id: + A unique integer that is used to identify the mesh. + + :dimension: + The number of mesh cells in the x, y, and z directions, respectively. + + *Default*: If this tag is not present, the number of mesh cells is + automatically determined by the code. + + :lower_left: + The Cartesian coordinates of the lower-left corner of the mesh. + + *Default*: None + + :upper_right: + The Cartesian coordinates of the upper-right corner of the mesh. + + *Default*: None + ----------------------- ```` Element ----------------------- @@ -765,30 +779,15 @@ has the following attributes/sub-elements: ------------------------ -```` Element +```` Element ------------------------ -The ```` element describes a mesh that is used for re-weighting -source sites at every generation based on the uniform fission site methodology -described in Kelly et al., "MC21 Analysis of the Nuclear Energy Agency Monte -Carlo Performance Benchmark Problem," Proceedings of *Physor 2012*, Knoxville, -TN (2012). This mesh should cover all possible fissionable materials in the -problem. It has the following attributes/sub-elements: - - :dimension: - The number of mesh cells in the x, y, and z directions, respectively. - - *Default*: None - - :lower_left: - The Cartesian coordinates of the lower-left corner of the mesh. - - *Default*: None - - :upper_right: - The Cartesian coordinates of the upper-right corner of the mesh. - - *Default*: None +The ```` element indicates the ID of a mesh that is used for +re-weighting source sites at every generation based on the uniform fission site +methodology described in Kelly et al., "MC21 Analysis of the Nuclear Energy +Agency Monte Carlo Performance Benchmark Problem," Proceedings of *Physor 2012*, +Knoxville, TN (2012). The mesh should cover all possible fissionable materials +in the problem and is specified using a :ref:`mesh_element`. .. _verbosity: From 4a64e2a93139574a0d913b9b4c8266264a15bea2 Mon Sep 17 00:00:00 2001 From: amandalund Date: Sat, 14 Apr 2018 14:10:35 -0500 Subject: [PATCH 12/77] Address #991 comments; add comments; add stopping condition and warning on early convergence --- openmc/model/triso.py | 150 ++++++++++++++++----------- tests/unit_tests/test_model_triso.py | 22 ++-- 2 files changed, 97 insertions(+), 75 deletions(-) diff --git a/openmc/model/triso.py b/openmc/model/triso.py index 7040d02cab..1e4b4aa9b1 100644 --- a/openmc/model/triso.py +++ b/openmc/model/triso.py @@ -305,14 +305,14 @@ class _CubicDomain(_Domain): uniform(-x_max, x_max)] def repel_particles(self, p, q, d, d_new): - # Moving each particle distance 'r' away from the other along the line + # Moving each particle distance 's' away from the other along the line # joining the particle centers will ensure their final distance is # equal to the outer diameter - r = (d_new - d)/2 + s = (d_new - d)/2 v = (p - q)/d - p += r*v - q -= r*v + p += s*v + q -= s*v # Enforce the rigid boundary by moving each particle back along the # surface normal until it is completely within the container if it @@ -413,14 +413,14 @@ class _CylindricalDomain(_Domain): return [r*cos(t), r*sin(t), uniform(-z_max, z_max)] def repel_particles(self, p, q, d, d_new): - # Moving each particle distance 'r' away from the other along the line + # Moving each particle distance 's' away from the other along the line # joining the particle centers will ensure their final distance is # equal to the outer diameter - r = (d_new - d)/2 + s = (d_new - d)/2 v = (p - q)/d - p += r*v - q -= r*v + p += s*v + q -= s*v # Enforce the rigid boundary by moving each particle back along the # surface normal until it is completely within the container if it @@ -428,14 +428,14 @@ class _CylindricalDomain(_Domain): r_max = self.limits[0] z_max = self.limits[1] - d = sqrt(p[0]**2 + p[1]**2) - if d > r_max: - p[0:2] *= r_max/d + r = sqrt(p[0]**2 + p[1]**2) + if r > r_max: + p[0:2] *= r_max/r p[2] = np.clip(p[2], -z_max, z_max) - d = sqrt(q[0]**2 + q[1]**2) - if d > r_max: - q[0:2] *= r_max/d + r = sqrt(q[0]**2 + q[1]**2) + if r > r_max: + q[0:2] *= r_max/r q[2] = np.clip(q[2], -z_max, z_max) @@ -512,27 +512,27 @@ class _SphericalDomain(_Domain): return [r*s for s in x] def repel_particles(self, p, q, d, d_new): - # Moving each particle distance 'r' away from the other along the line + # Moving each particle distance 's' away from the other along the line # joining the particle centers will ensure their final distance is # equal to the outer diameter - r = (d_new - d)/2 + s = (d_new - d)/2 v = (p - q)/d - p += r*v - q -= r*v + p += s*v + q -= s*v # Enforce the rigid boundary by moving each particle back along the # surface normal until it is completely within the container if it # overlaps the surface r_max = self.limits[0] - d = sqrt(p[0]**2 + p[1]**2 + p[2]**2) - if d > r_max: - p *= r_max/d + r = sqrt(p[0]**2 + p[1]**2 + p[2]**2) + if r > r_max: + p *= r_max/r - d = sqrt(q[0]**2 + q[1]**2 + q[2]**2) - if d > r_max: - q *= r_max/d + r = sqrt(q[0]**2 + q[1]**2 + q[2]**2) + if r > r_max: + q *= r_max/r def create_triso_lattice(trisos, lower_left, pitch, shape, background): @@ -712,6 +712,7 @@ def _close_random_pack(domain, particles, contraction_rate): del rods_map[i] del rods_map[j] return d, i, j + return None, None, None def create_rod_list(): """Generate sorted list of rods (distances between particle centers). @@ -736,8 +737,8 @@ def _close_random_pack(domain, particles, contraction_rate): # Find distance to nearest neighbor and index of nearest neighbor for # all particles d, n = tree.query(particles, k=2) - d = d[:,1] - n = n[:,1] + d = d[:, 1] + n = n[:, 1] # Array of particle indices, indices of nearest neighbors, and # distances to nearest neighbors @@ -746,8 +747,8 @@ def _close_random_pack(domain, particles, contraction_rate): # Sort along second column and swap first and second columns to create # array of nearest neighbor indices, indices of particles they are # nearest neighbors of, and distances between them - b = a[a[:,1].argsort()] - b[:,[0, 1]] = b[:,[1, 0]] + b = a[a[:, 1].argsort()] + b[:, [0, 1]] = b[:, [1, 0]] # Find the intersection between 'a' and 'b': a list of particles who # are each other's nearest neighbors and the distance between them @@ -761,10 +762,11 @@ def _close_random_pack(domain, particles, contraction_rate): del rods[:] rods_map.clear() for d, i, j in r: - add_rod(d, i, j) + if d < outer_diameter and not np.isclose(d, outer_diameter, atol=1.0e-14): + add_rod(d, i, j) - def update_mesh(indices): - """Update which mesh cells the particles are in based on new particle + def update_mesh(i): + """Update which mesh cells the particle is in based on new particle center coordinates. 'mesh'/'mesh_map' is a two way dictionary used to look up which @@ -774,23 +776,22 @@ def _close_random_pack(domain, particles, contraction_rate): Parameters ---------- - indices : List of int - Indices of particles in particles array. + i : int + Index of particle in particles array. """ - for i in indices: - # Determine which mesh cells the particle is in and remove the - # particle id from those cells - for idx in mesh_map[i]: - mesh[idx].remove(i) - del mesh_map[i] + # Determine which mesh cells the particle is in and remove the + # particle id from those cells + for idx in mesh_map[i]: + mesh[idx].remove(i) + del mesh_map[i] - # Determine which mesh cells are within one diameter of particle's - # center and add this particle to the list of particles in those cells - for idx in domain.nearby_mesh_cells(particles[i]): - mesh[idx].add(i) - mesh_map[i].add(idx) + # Determine which mesh cells are within one diameter of particle's + # center and add this particle to the list of particles in those cells + for idx in domain.nearby_mesh_cells(particles[i]): + mesh[idx].add(i) + mesh_map[i].add(idx) def reduce_outer_diameter(): """Reduce the outer diameter so that at the (i+1)-st iteration it is: @@ -844,25 +845,25 @@ def _close_random_pack(domain, particles, contraction_rate): else: return None, None - def update_rod_list(indices): - """Update the rod list with the new nearest neighbors of particles in - list since their overlap was eliminated. + def update_rod_list(i): + """Update the rod list with the new nearest neighbors of particle since + its overlap was eliminated. Parameters ---------- - indices : List of int - Indices of particles in particles array. + i : int + Index of particle in particles array. """ # If the nearest neighbor k of particle i has no nearer neighbors, # remove the rod currently containing k from the rod list and add rod # k-i, keeping the rod list sorted - for i in indices: - k, d_ik = nearest(i) - if k and nearest(k)[0] == i: - remove_rod(k) - add_rod(d_ik, i, k) + k, d_ik = nearest(i) + if (k and nearest(k)[0] == i and d_ik < outer_diameter + and not np.isclose(d, outer_diameter, atol=1.0e-14)): + remove_rod(k) + add_rod(d_ik, i, k) n_particles = len(particles) diameter = 2*domain.particle_radius @@ -877,41 +878,68 @@ def _close_random_pack(domain, particles, contraction_rate): outer_diameter = initial_outer_diameter inner_diameter = 0. + # List of rods arranged in a heap and mapping of particle ids to rods rods = [] rods_map = {} + + # Initialize two-way dictionary that identifies which particles are near a + # given mesh cell and which mesh cells a particle is near mesh = defaultdict(set) mesh_map = defaultdict(set) - for i in range(n_particles): for idx in domain.nearby_mesh_cells(particles[i]): mesh[idx].add(i) mesh_map[i].add(idx) while True: + # Rebuild the sorted list of rods according to the current particle + # configuration create_rod_list() + + # Set the inner diameter to the shortest center-to-center distance + # between any two particles if rods: - # Set inner diameter to the shortest center-to-center distance - # between any two particles inner_diameter = rods[0][0] + + # Reached the desired particle radius if inner_diameter >= diameter: break + + # The algorithm converged before reaching the desired particle radius. + # This can happen when the desired packing fraction is close to the + # packing fraction limit. The packing fraction is a random variable + # that is determined by the particle locations and the contraction + # rate. A higher packing fraction can be achieved with a smaller + # contraction rate, though at the cost of a longer simulation time -- + # the number of iterations needed to remove all overlaps is inversely + # proportional to the contraction rate. + if inner_diameter >= outer_diameter or not rods: + warnings.warn('Close random pack converged before reaching true ' + 'particle radius; some particles may overlap. Try ' + 'reducing contraction rate or packing fraction.') + break + while True: d, i, j = pop_rod() + if not d: + break outer_diameter = reduce_outer_diameter() domain.repel_particles(particles[i], particles[j], d, outer_diameter) - update_mesh([i, j]) - update_rod_list([i, j]) + update_mesh(i) + update_mesh(j) + update_rod_list(i) + update_rod_list(j) if not rods: break inner_diameter = rods[0][0] - if inner_diameter >= diameter: + if inner_diameter >= diameter or inner_diameter >= outer_diameter: break def pack_trisos(radius, fill, domain_shape='cylinder', domain_length=None, domain_radius=None, domain_center=[0., 0., 0.], n_particles=None, packing_fraction=None, - initial_packing_fraction=0.3, contraction_rate=1/400, seed=1): + initial_packing_fraction=0.3, contraction_rate=1.e-3, seed=1): """Generate a random, non-overlapping configuration of TRISO particles within a container. diff --git a/tests/unit_tests/test_model_triso.py b/tests/unit_tests/test_model_triso.py index bfd7319d21..19c4f9081e 100644 --- a/tests/unit_tests/test_model_triso.py +++ b/tests/unit_tests/test_model_triso.py @@ -12,21 +12,15 @@ import scipy.spatial _PACKING_FRACTION = 0.35 _RADIUS = 4.25e-2 +domain_params = [ + {'shape': 'cube', 'length': 0.75, 'radius': 0., 'volume': 0.75**3}, + {'shape': 'cylinder', 'length': 0.5, 'radius': 0.5, 'volume': 0.5*pi*0.5**2}, + {'shape': 'sphere', 'length': 0., 'radius': 0.5, 'volume': 4/3*pi*0.5**3} +] -@pytest.fixture(scope='module', - params=[{'shape': 'cube', - 'length': 0.75, - 'radius': 0., - 'volume': 0.75**3}, - {'shape': 'cylinder', - 'length': 0.5, - 'radius': 0.5, - 'volume': 0.5*pi*0.5**2}, - {'shape': 'sphere', - 'length': 0., - 'radius': 0.5, - 'volume': 4/3*pi*0.5**3}]) +@pytest.fixture(scope='module', params=domain_params, + ids=['cube', 'cylinder', 'sphere']) def domain(request): return request.param @@ -65,7 +59,7 @@ def test_overlap(trisos): d = tree.query(centers, k=2)[0] # Get the smallest distance between any two particles - d_min = min(d[:,1]) + d_min = min(d[:, 1]) assert d_min > 2*_RADIUS or d_min == pytest.approx(2*_RADIUS) From fccb26735ca1b2621aac8af2cb55b64d71527480 Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Tue, 17 Apr 2018 14:16:43 -0500 Subject: [PATCH 13/77] Add missing prototypes in openmc.h --- include/openmc.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/include/openmc.h b/include/openmc.h index d24ca4af96..0837881200 100644 --- a/include/openmc.h +++ b/include/openmc.h @@ -27,6 +27,7 @@ extern "C" { int openmc_extend_cells(int32_t n, int32_t* index_start, int32_t* index_end); int openmc_extend_filters(int32_t n, int32_t* index_start, int32_t* index_end); int openmc_extend_materials(int32_t n, int32_t* index_start, int32_t* index_end); + int openmc_extend_meshes(int32_t n, int32_t* index_start, int32_t* index_end); int openmc_extend_sources(int32_t n, int32_t* index_start, int32_t* index_end); int openmc_extend_tallies(int32_t n, int32_t* index_start, int32_t* index_end); int openmc_filter_get_id(int32_t index, int32_t* id); @@ -40,7 +41,9 @@ extern "C" { void openmc_get_filter_next_id(int32_t* id); int openmc_get_keff(double k_combined[]); int openmc_get_material_index(int32_t id, int32_t* index); + int openmc_get_mesh_index(int32_t id, int32_t* index); int openmc_get_nuclide_index(const char name[], int* index); + int64_t openmc_get_seed(); int openmc_get_tally_index(int32_t id, int32_t* index); void openmc_hard_reset(); void openmc_init(const int* intracomm); @@ -70,6 +73,7 @@ extern "C" { void openmc_plot_geometry(); void openmc_reset(); int openmc_run(); + void openmc_set_seed(int64_t new_seed); void openmc_simulation_finalize(); void openmc_simulation_init(); int openmc_source_bank(struct Bank** ptr, int64_t* n); From 8886313c939da0784ca132883b233cd2335dcc24 Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Wed, 18 Apr 2018 07:17:02 -0500 Subject: [PATCH 14/77] Add description of openmc.capi.Mesh attributes in docstring --- openmc/capi/mesh.py | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/openmc/capi/mesh.py b/openmc/capi/mesh.py index 326f5f61ed..091c5194b9 100644 --- a/openmc/capi/mesh.py +++ b/openmc/capi/mesh.py @@ -59,6 +59,16 @@ class Mesh(_FortranObjectWithID): ---------- id : int ID of the mesh + dimension : iterable of int + The number of mesh cells in each direction. + lower_left : numpy.ndarray + The lower-left corner of the structured mesh. If only two coordinate are + given, it is assumed that the mesh is an x-y mesh. + upper_right : numpy.ndarray + The upper-right corner of the structrued mesh. If only two coordinate + are given, it is assumed that the mesh is an x-y mesh. + width : numpy.ndarray + The width of mesh cells in each direction. """ __instances = WeakValueDictionary() From 39554e4614fcdddc7411dbdabc5dac5bf7cf924f Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Wed, 18 Apr 2018 15:54:04 -0500 Subject: [PATCH 15/77] Allow tallies to be activated from C API (mostly for CMFD) --- include/openmc.h | 2 ++ openmc/capi/tally.py | 18 +++++++++++++++- src/tallies/tally_header.F90 | 39 +++++++++++++++++++++++++++++++++++ tests/unit_tests/test_capi.py | 6 +++++- 4 files changed, 63 insertions(+), 2 deletions(-) diff --git a/include/openmc.h b/include/openmc.h index 0837881200..ed3a86054c 100644 --- a/include/openmc.h +++ b/include/openmc.h @@ -88,12 +88,14 @@ extern "C" { int openmc_sphharm_filter_set_order(int32_t index, int order); int openmc_sphharm_filter_set_cosine(int32_t index, const char cosine[]); void openmc_statepoint_write(const char filename[]); + int openmc_tally_get_active(int32_t index, bool* active); int openmc_tally_get_id(int32_t index, int32_t* id); int openmc_tally_get_filters(int32_t index, int32_t** indices, int* n); int openmc_tally_get_n_realizations(int32_t index, int32_t* n); int openmc_tally_get_nuclides(int32_t index, int** nuclides, int* n); int openmc_tally_get_scores(int32_t index, int** scores, int* n); int openmc_tally_results(int32_t index, double** ptr, int shape_[3]); + int openmc_tally_set_active(int32_t index, bool active); int openmc_tally_set_filters(int32_t index, int n, const int32_t* indices); int openmc_tally_set_id(int32_t index, int32_t id); int openmc_tally_set_nuclides(int32_t index, int n, const char** nuclides); diff --git a/openmc/capi/tally.py b/openmc/capi/tally.py index 46a967f690..a10fae47a3 100644 --- a/openmc/capi/tally.py +++ b/openmc/capi/tally.py @@ -1,5 +1,5 @@ from collections.abc import Mapping -from ctypes import c_int, c_int32, c_double, c_char_p, POINTER +from ctypes import c_int, c_int32, c_double, c_char_p, c_bool, POINTER from weakref import WeakValueDictionary import numpy as np @@ -26,6 +26,9 @@ _dll.openmc_get_tally_index.errcheck = _error_handler _dll.openmc_global_tallies.argtypes = [POINTER(POINTER(c_double))] _dll.openmc_global_tallies.restype = c_int _dll.openmc_global_tallies.errcheck = _error_handler +_dll.openmc_tally_get_active.argtypes = [c_int32, POINTER(c_bool)] +_dll.openmc_tally_get_active.restype = c_int +_dll.openmc_tally_get_active.errcheck = _error_handler _dll.openmc_tally_get_id.argtypes = [c_int32, POINTER(c_int32)] _dll.openmc_tally_get_id.restype = c_int _dll.openmc_tally_get_id.errcheck = _error_handler @@ -48,6 +51,9 @@ _dll.openmc_tally_results.argtypes = [ c_int32, POINTER(POINTER(c_double)), POINTER(c_int*3)] _dll.openmc_tally_results.restype = c_int _dll.openmc_tally_results.errcheck = _error_handler +_dll.openmc_tally_set_active.argtypes = [c_int32, c_bool] +_dll.openmc_tally_set_active.restype = c_int +_dll.openmc_tally_set_active.errcheck = _error_handler _dll.openmc_tally_set_filters.argtypes = [c_int32, c_int, POINTER(c_int32)] _dll.openmc_tally_set_filters.restype = c_int _dll.openmc_tally_set_filters.errcheck = _error_handler @@ -178,6 +184,16 @@ class Tally(_FortranObjectWithID): return cls.__instances[index] + @property + def active(self): + active = c_bool() + _dll.openmc_tally_get_active(self._index, active) + return active.value + + @active.setter + def active(self, active): + _dll.openmc_tally_set_active(self._index, active) + @property def id(self): tally_id = c_int32() diff --git a/src/tallies/tally_header.F90 b/src/tallies/tally_header.F90 index 02a578d7e0..413464b7b5 100644 --- a/src/tallies/tally_header.F90 +++ b/src/tallies/tally_header.F90 @@ -24,12 +24,14 @@ module tally_header public :: openmc_extend_tallies public :: openmc_get_tally_index public :: openmc_global_tallies + public :: openmc_tally_get_active public :: openmc_tally_get_id public :: openmc_tally_get_filters public :: openmc_tally_get_n_realizations public :: openmc_tally_get_nuclides public :: openmc_tally_get_scores public :: openmc_tally_results + public :: openmc_tally_set_active public :: openmc_tally_set_filters public :: openmc_tally_set_id public :: openmc_tally_set_nuclides @@ -512,6 +514,22 @@ contains end function openmc_global_tallies + function openmc_tally_get_active(index, active) result(err) bind(C) + ! Return whether a tally is active + integer(C_INT32_T), value :: index + logical(C_BOOL), intent(out) :: active + integer(C_INT) :: err + + if (index >= 1 .and. index <= size(tallies)) then + active = tallies(index) % obj % active + err = 0 + else + err = E_OUT_OF_BOUNDS + call set_errmsg('Index in tallies array is out of bounds.') + end if + end function openmc_tally_get_active + + function openmc_tally_get_id(index, id) result(err) bind(C) ! Return the ID of a tally integer(C_INT32_T), value :: index @@ -667,6 +685,27 @@ contains end function openmc_tally_set_filters + function openmc_tally_set_active(index, active) result(err) bind(C) + ! Set the ID of a tally + integer(C_INT32_T), value, intent(in) :: index + logical(C_BOOL), value, intent(in) :: active + integer(C_INT) :: err + + if (index >= 1 .and. index <= n_tallies) then + if (allocated(tallies(index) % obj)) then + tallies(index) % obj % active = active + err = 0 + else + err = E_ALLOCATE + call set_errmsg("Tally type has not been set yet.") + end if + else + err = E_OUT_OF_BOUNDS + call set_errmsg('Index in tallies array is out of bounds.') + end if + end function openmc_tally_set_active + + function openmc_tally_set_id(index, id) result(err) bind(C) ! Set the ID of a tally integer(C_INT32_T), value, intent(in) :: index diff --git a/tests/unit_tests/test_capi.py b/tests/unit_tests/test_capi.py index 6c05f5d3e3..a21e858fda 100644 --- a/tests/unit_tests/test_capi.py +++ b/tests/unit_tests/test_capi.py @@ -164,6 +164,10 @@ def test_tally(capi_init): t.scores = new_scores assert t.scores == new_scores + assert not t.active + t.active = True + assert t.active + def test_new_tally(capi_init): with pytest.raises(exc.AllocationError): @@ -177,7 +181,7 @@ def test_new_tally(capi_init): def test_tally_results(capi_run): t = openmc.capi.tallies[1] - assert t.num_realizations == 5 + assert t.num_realizations == 10 # t was made active in test_tally assert np.all(t.mean >= 0) nonzero = (t.mean > 0.0) assert np.all(t.std_dev[nonzero] >= 0) From 14455dc43ee623cf6072e33349c90edfe46d0100 Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Thu, 12 Apr 2018 07:19:25 -0500 Subject: [PATCH 16/77] Write main() from C++ --- CMakeLists.txt | 6 +++-- include/openmc.h | 19 +++++++++++---- openmc/capi/core.py | 5 ++-- openmc/capi/settings.py | 6 ++--- src/main.F90 | 51 --------------------------------------- src/main.cpp | 40 ++++++++++++++++++++++++++++++ src/message_passing.F90 | 4 ++- src/nuclide_header.F90 | 2 +- src/particle_restart.F90 | 11 ++++++--- src/settings.F90 | 4 +-- src/simulation_header.F90 | 7 +++--- 11 files changed, 81 insertions(+), 74 deletions(-) delete mode 100644 src/main.F90 create mode 100644 src/main.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 1797ae5d31..81c16aa484 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -447,7 +447,9 @@ set(LIBOPENMC_CXX_SRC src/pugixml/pugixml.hpp) add_library(libopenmc SHARED ${LIBOPENMC_FORTRAN_SRC} ${LIBOPENMC_CXX_SRC}) set_target_properties(libopenmc PROPERTIES OUTPUT_NAME openmc) -add_executable(${program} src/main.F90) + +add_executable(${program} src/main.cpp) +target_include_directories(${program} PUBLIC include) #=============================================================================== # Add compiler/linker flags @@ -460,7 +462,7 @@ target_include_directories(libopenmc PUBLIC ${HDF5_INCLUDE_DIRS}) # The executable and the faddeeva package use only one language. They can be # set via target_compile_options which accepts a list. -target_compile_options(${program} PUBLIC ${f90flags}) +target_compile_options(${program} PUBLIC ${cxxflags}) target_compile_options(faddeeva PRIVATE ${cflags}) # The libopenmc library has both F90 and C++ so the compile flags must be set diff --git a/include/openmc.h b/include/openmc.h index ed3a86054c..1945453452 100644 --- a/include/openmc.h +++ b/include/openmc.h @@ -70,6 +70,7 @@ extern "C" { int openmc_meshsurface_filter_set_mesh(int32_t index, int32_t index_mesh); int openmc_next_batch(int* status); int openmc_nuclide_name(int index, char** name); + int openmc_particle_restart(); void openmc_plot_geometry(); void openmc_reset(); int openmc_run(); @@ -122,8 +123,9 @@ extern "C" { // Global variables extern char openmc_err_msg[256]; - extern double keff; - extern double keff_std; + extern double openmc_keff; + extern double openmc_keff_std; + extern bool openmc_master; extern int32_t n_batches; extern int32_t n_cells; extern int32_t n_filters; @@ -139,9 +141,16 @@ extern "C" { extern int32_t n_surfaces; extern int32_t n_tallies; extern int32_t n_universes; - extern int run_mode; - extern bool simulation_initialized; - extern int verbosity; + extern int openmc_run_mode; + extern bool openmc_simulation_initialized; + extern int openmc_verbosity; + + // Run modes + constexpr int RUN_MODE_FIXEDSOURCE {1}; + constexpr int RUN_MODE_EIGENVALUE {2}; + constexpr int RUN_MODE_PLOTTING {3}; + constexpr int RUN_MODE_PARTICLE {4}; + constexpr int RUN_MODE_VOLUME {5}; #ifdef __cplusplus } diff --git a/openmc/capi/core.py b/openmc/capi/core.py index f80b5fe540..d356905036 100644 --- a/openmc/capi/core.py +++ b/openmc/capi/core.py @@ -178,8 +178,9 @@ def keff(): return tuple(k) else: # Otherwise, return the tracklength estimator - mean = c_double.in_dll(_dll, 'keff').value - std_dev = c_double.in_dll(_dll, 'keff_std').value if n > 1 else np.inf + mean = c_double.in_dll(_dll, 'openmc_keff').value + std_dev = c_double.in_dll(_dll, 'openmc_keff_std').value \ + if n > 1 else np.inf return (mean, std_dev) diff --git a/openmc/capi/settings.py b/openmc/capi/settings.py index 1063d6463e..d706112c41 100644 --- a/openmc/capi/settings.py +++ b/openmc/capi/settings.py @@ -20,11 +20,11 @@ class _Settings(object): generations_per_batch = _DLLGlobal(c_int32, 'gen_per_batch') inactive = _DLLGlobal(c_int32, 'n_inactive') particles = _DLLGlobal(c_int64, 'n_particles') - verbosity = _DLLGlobal(c_int, 'verbosity') + verbosity = _DLLGlobal(c_int, 'openmc_verbosity') @property def run_mode(self): - i = c_int.in_dll(_dll, 'run_mode').value + i = c_int.in_dll(_dll, 'openmc_run_mode').value try: return _RUN_MODES[i] except KeyError: @@ -32,7 +32,7 @@ class _Settings(object): @run_mode.setter def run_mode(self, mode): - current_idx = c_int.in_dll(_dll, 'run_mode') + current_idx = c_int.in_dll(_dll, 'openmc_run_mode') for idx, mode_value in _RUN_MODES.items(): if mode_value == mode: current_idx.value = idx diff --git a/src/main.F90 b/src/main.F90 deleted file mode 100644 index 372e993f5d..0000000000 --- a/src/main.F90 +++ /dev/null @@ -1,51 +0,0 @@ -program main - - use, intrinsic :: ISO_C_BINDING - - use constants - use message_passing - use openmc_api, only: openmc_init, openmc_finalize, openmc_run, & - openmc_plot_geometry, openmc_calculate_volumes - use particle_restart, only: run_particle_restart - use settings, only: run_mode - - implicit none - - integer(C_INT) :: err -#ifdef OPENMC_MPI - integer :: mpi_err ! MPI error code -#endif - - ! Initialize run -- when run with MPI, pass communicator -#ifdef OPENMC_MPI -#ifdef OPENMC_MPIF08 - call openmc_init(MPI_COMM_WORLD % MPI_VAL) -#else - call openmc_init(MPI_COMM_WORLD) -#endif -#else - call openmc_init() -#endif - - ! start problem based on mode - select case (run_mode) - case (MODE_FIXEDSOURCE, MODE_EIGENVALUE) - err = openmc_run() - case (MODE_PLOTTING) - call openmc_plot_geometry() - case (MODE_PARTICLE) - if (master) call run_particle_restart() - case (MODE_VOLUME) - call openmc_calculate_volumes() - end select - - ! finalize run - call openmc_finalize() - -#ifdef OPENMC_MPI - ! If MPI is in use and enabled, terminate it - call MPI_FINALIZE(mpi_err) -#endif - - -end program main diff --git a/src/main.cpp b/src/main.cpp new file mode 100644 index 0000000000..7b2ccb5c3e --- /dev/null +++ b/src/main.cpp @@ -0,0 +1,40 @@ +#include "openmc.h" + +#ifdef MPI +#include +#else +#define MPI_COMM_WORLD nullptr +#endif + + +int main(int argc, char** argv) { + int err; + + // Initialize run -- when run with MPI, pass communicator + openmc_init(MPI_COMM_WORLD); + + // start problem based on mode + switch (openmc_run_mode) { + case RUN_MODE_FIXEDSOURCE: + case RUN_MODE_EIGENVALUE: + err = openmc_run(); + break; + case RUN_MODE_PLOTTING: + openmc_plot_geometry(); + break; + case RUN_MODE_PARTICLE: + if (openmc_master) err = openmc_particle_restart(); + break; + case RUN_MODE_VOLUME: + openmc_calculate_volumes(); + break; + } + + // Finalize and free up memory + openmc_finalize(); + + // If MPI is in use and enabled, terminate it +#ifdef MPI + err = MPI_Finalize(); +#endif +} diff --git a/src/message_passing.F90 b/src/message_passing.F90 index 7391a632c7..f9a16ee759 100644 --- a/src/message_passing.F90 +++ b/src/message_passing.F90 @@ -1,5 +1,7 @@ module message_passing + use, intrinsic :: ISO_C_BINDING + #ifdef OPENMC_MPI #ifdef OPENMC_MPIF08 use mpi_f08 @@ -14,7 +16,7 @@ module message_passing integer :: n_procs = 1 ! number of processes integer :: rank = 0 ! rank of process - logical :: master = .true. ! master process? + logical(C_BOOL), bind(C, name='openmc_master') :: master = .true. ! master process? logical :: mpi_enabled = .false. ! is MPI in use and initialized? #ifdef OPENMC_MPIF08 type(MPI_Datatype) :: MPI_BANK ! MPI datatype for fission bank diff --git a/src/nuclide_header.F90 b/src/nuclide_header.F90 index 8362f5d41e..76fc26a748 100644 --- a/src/nuclide_header.F90 +++ b/src/nuclide_header.F90 @@ -277,7 +277,7 @@ contains integer, intent(inout) :: method real(8), intent(in) :: tolerance real(8), intent(in) :: minmax(2) ! range of temperatures - logical, intent(in) :: master ! if this is the master proc + logical(C_BOOL), intent(in) :: master ! if this is the master proc integer, intent(in) :: i_nuclide ! Nuclide index in nuclides integer :: i diff --git a/src/particle_restart.F90 b/src/particle_restart.F90 index 2d15f2ddc4..fc8a05277c 100644 --- a/src/particle_restart.F90 +++ b/src/particle_restart.F90 @@ -20,20 +20,23 @@ module particle_restart implicit none private - public :: run_particle_restart + public :: openmc_particle_restart contains !=============================================================================== -! RUN_PARTICLE_RESTART is the main routine that runs the particle restart +! OPENMC_PARTICLE_RESTART is the main routine that runs the particle restart !=============================================================================== - subroutine run_particle_restart() + function openmc_particle_restart() result(err) bind(C) + integer(C_INT) :: err integer(8) :: particle_seed integer :: previous_run_mode type(Particle) :: p + err = 0 + ! Set verbosity high verbosity = 10 @@ -66,7 +69,7 @@ contains deallocate(micro_xs) - end subroutine run_particle_restart + end function openmc_particle_restart !=============================================================================== ! READ_PARTICLE_RESTART reads the particle restart file diff --git a/src/settings.F90 b/src/settings.F90 index 83aebce860..4de72e8c4d 100644 --- a/src/settings.F90 +++ b/src/settings.F90 @@ -75,14 +75,14 @@ module settings real(8) :: weight_survive = ONE ! Mode to run in (fixed source, eigenvalue, plotting, etc) - integer(C_INT), bind(C) :: run_mode = NONE + integer(C_INT), bind(C, name='openmc_run_mode') :: run_mode = NONE ! Restart run logical :: restart_run = .false. ! The verbosity controls how much information will be printed to the screen ! and in logs - integer(C_INT), bind(C) :: verbosity = 7 + integer(C_INT), bind(C, name='openmc_verbosity') :: verbosity = 7 logical :: check_overlaps = .false. diff --git a/src/simulation_header.F90 b/src/simulation_header.F90 index 11be9bf9ca..67bf3062bd 100644 --- a/src/simulation_header.F90 +++ b/src/simulation_header.F90 @@ -23,7 +23,8 @@ module simulation_header integer :: current_batch ! current batch integer :: current_gen ! current generation within a batch integer :: total_gen = 0 ! total number of generations simulated - logical(C_BOOL), bind(C) :: simulation_initialized = .false. + logical(C_BOOL), bind(C, name='openmc_simulation_initialized') :: & + simulation_initialized = .false. logical :: need_depletion_rx ! need to calculate depletion reaction rx? ! ============================================================================ @@ -40,8 +41,8 @@ module simulation_header ! Temporary k-effective values type(VectorReal) :: k_generation ! single-generation estimates of k - real(C_DOUBLE), bind(C) :: keff = ONE ! average k over active batches - real(C_DOUBLE), bind(C) :: keff_std ! standard deviation of average k + real(C_DOUBLE), bind(C, name='openmc_keff') :: keff = ONE ! average k over active batches + real(C_DOUBLE), bind(C, name='openmc_keff_std') :: keff_std ! standard deviation of average k real(8) :: k_col_abs = ZERO ! sum over batches of k_collision * k_absorption real(8) :: k_col_tra = ZERO ! sum over batches of k_collision * k_tracklength real(8) :: k_abs_tra = ZERO ! sum over batches of k_absorption * k_tracklength From faf35d21bcd4b7e8163aa261e5a44ae948e25748 Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Thu, 12 Apr 2018 07:45:47 -0500 Subject: [PATCH 17/77] Move openmc_run to C++ side --- CMakeLists.txt | 5 ++--- src/api.F90 | 1 - src/simulation.F90 | 20 -------------------- src/simulation.cpp | 18 ++++++++++++++++++ 4 files changed, 20 insertions(+), 24 deletions(-) create mode 100644 src/simulation.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 81c16aa484..d246cf57c2 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -440,6 +440,7 @@ set(LIBOPENMC_CXX_SRC src/hdf5_interface.h src/random_lcg.cpp src/random_lcg.h + src/simulation.cpp src/surface.cpp src/surface.h src/xml_interface.h @@ -447,9 +448,7 @@ set(LIBOPENMC_CXX_SRC src/pugixml/pugixml.hpp) add_library(libopenmc SHARED ${LIBOPENMC_FORTRAN_SRC} ${LIBOPENMC_CXX_SRC}) set_target_properties(libopenmc PROPERTIES OUTPUT_NAME openmc) - add_executable(${program} src/main.cpp) -target_include_directories(${program} PUBLIC include) #=============================================================================== # Add compiler/linker flags @@ -458,7 +457,7 @@ target_include_directories(${program} PUBLIC include) set_property(TARGET ${program} libopenmc pugixml_fortran PROPERTY LINKER_LANGUAGE Fortran) -target_include_directories(libopenmc PUBLIC ${HDF5_INCLUDE_DIRS}) +target_include_directories(libopenmc PUBLIC include ${HDF5_INCLUDE_DIRS}) # The executable and the faddeeva package use only one language. They can be # set via target_compile_options which accepts a list. diff --git a/src/api.F90 b/src/api.F90 index df183c292f..d7f3ed0235 100644 --- a/src/api.F90 +++ b/src/api.F90 @@ -80,7 +80,6 @@ module openmc_api public :: openmc_nuclide_name public :: openmc_plot_geometry public :: openmc_reset - public :: openmc_run public :: openmc_set_seed public :: openmc_simulation_finalize public :: openmc_simulation_init diff --git a/src/simulation.F90 b/src/simulation.F90 index 68debe52ba..e9729df038 100644 --- a/src/simulation.F90 +++ b/src/simulation.F90 @@ -44,7 +44,6 @@ module simulation implicit none private public :: openmc_next_batch - public :: openmc_run public :: openmc_simulation_init public :: openmc_simulation_finalize @@ -54,25 +53,6 @@ module simulation contains -!=============================================================================== -! OPENMC_RUN encompasses all the main logic where iterations are performed -! over the batches, generations, and histories in a fixed source or k-eigenvalue -! calculation. -!=============================================================================== - - function openmc_run() result(err) bind(C) - integer(C_INT) :: err - integer(C_INT) :: status - - call openmc_simulation_init() - do - err = openmc_next_batch(status) - if (status /= 0 .or. err < 0) exit - end do - call openmc_simulation_finalize() - - end function openmc_run - !=============================================================================== ! OPENMC_NEXT_BATCH !=============================================================================== diff --git a/src/simulation.cpp b/src/simulation.cpp new file mode 100644 index 0000000000..e9bf81775a --- /dev/null +++ b/src/simulation.cpp @@ -0,0 +1,18 @@ +#include "openmc.h" + +// OPENMC_RUN encompasses all the main logic where iterations are performed +// over the batches, generations, and histories in a fixed source or k-eigenvalue +// calculation. + +int openmc_run() { + openmc_simulation_init(); + + int err = 0; + int status = 0; + while (status == 0 && err == 0) { + err = openmc_next_batch(&status); + } + + openmc_simulation_finalize(); + return err; +} From 05e40a142feae458490704cbf132928919f256de Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Fri, 13 Apr 2018 15:03:16 -0500 Subject: [PATCH 18/77] Get rid of include_directories command in CMakeLists.txt --- CMakeLists.txt | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index d246cf57c2..ca3d837173 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -10,9 +10,6 @@ set(CMAKE_Fortran_MODULE_DIRECTORY ${CMAKE_BINARY_DIR}/include) # Set module path set(CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake/Modules) -# Make sure Fortran module directory is included when building -include_directories(${CMAKE_BINARY_DIR}/include) - #=============================================================================== # Architecture specific definitions #=============================================================================== @@ -457,7 +454,10 @@ add_executable(${program} src/main.cpp) set_property(TARGET ${program} libopenmc pugixml_fortran PROPERTY LINKER_LANGUAGE Fortran) -target_include_directories(libopenmc PUBLIC include ${HDF5_INCLUDE_DIRS}) +target_include_directories(libopenmc + PUBLIC include ${HDF5_INCLUDE_DIRS} + PRIVATE ${CMAKE_BINARY_DIR}/include + ) # The executable and the faddeeva package use only one language. They can be # set via target_compile_options which accepts a list. From b0c7f07d02cce03c89ff2b07bd52c2162cfda37e Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Mon, 16 Apr 2018 15:58:03 -0500 Subject: [PATCH 19/77] Start writing more HDF5 interface functions in C++ --- src/hdf5_interface.h | 158 ++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 148 insertions(+), 10 deletions(-) diff --git a/src/hdf5_interface.h b/src/hdf5_interface.h index 7ec9ada9b6..8a445b21e6 100644 --- a/src/hdf5_interface.h +++ b/src/hdf5_interface.h @@ -1,44 +1,153 @@ #ifndef HDF5_INTERFACE_H #define HDF5_INTERFACE_H -#include -#include +#include "error.h" #include "hdf5.h" +#include "hdf5_hl.h" -#include "error.h" +#include +#include +#include namespace openmc { +bool +using_mpio_device(hid_t obj_id) { + // Determine file that this object is part of + hid_t file_id = H5Iget_file_id(obj_id); + + // Get file access property list + hid_t fapl_id = H5Fget_access_plist(file_id); + + // Get low-level driver identifier + hid_t driver = H5Pget_driver(fapl_id); + + // Free resources + H5Pclose(fapl_id); + H5Fclose(file_id); + + return driver == H5FD_MPIO; +} + hid_t create_group(hid_t parent_id, char const *name) { hid_t out = H5Gcreate(parent_id, name, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT); if (out < 0) { - std::string err_msg{"Failed to create HDF5 group \""}; - err_msg += name; - err_msg += "\""; + std::stringstream err_msg; + err_msg << "Failed to create HDF5 group \"" << name << "\""; fatal_error(err_msg); } return out; } - hid_t create_group(hid_t parent_id, const std::string &name) { return create_group(parent_id, name.c_str()); } +void +close_dataset(hid_t dataset_id) +{ + if (H5Dclose(dataset_id) < 0) fatal_error("Failed to close dataset"); +} + void close_group(hid_t group_id) { - herr_t err = H5Gclose(group_id); - if (err < 0) { - fatal_error("Failed to close HDF5 group"); + if (H5Gclose(group_id) < 0) fatal_error("Failed to close group"); +} + + +hid_t +file_open(const char* filename, char mode, bool parallel=false) +{ + bool create; + unsigned int flags; + switch (mode) { + case 'r': + case 'a': + create = false; + flags = (mode == 'r' ? H5F_ACC_RDONLY : H5F_ACC_RDWR); + break; + case 'w': + case 'x': + create = true; + flags = (mode == 'x' ? H5F_ACC_EXCL : H5F_ACC_TRUNC); + break; + } + + hid_t plist; + if (parallel) { + // Setup file access property list with parallel I/O access + plist = H5Pcreate(H5P_FILE_ACCESS); +#ifdef PHDF5 + H5Pset_fapl_mpio(plist, mpi_intracomm, MPI_INFO_NULL); +#endif + } else { + plist = H5P_DEFAULT; + } + + // Open the file collectively + hid_t file_id; + if (create) { + file_id = H5Fopen(filename, flags, plist); + } else { + file_id = H5Fcreate(filename, flags, H5P_DEFAULT, plist); + } + + // Close the property list + if (parallel) H5Pclose(plist); + + return file_id; +} + +hid_t +file_open(const std::string& filename, char mode, bool parallel=false) { + file_open(filename.c_str(), mode, parallel); +} + +void file_close(hid_t file_id) { + H5Fclose(file_id); +} + +bool +object_exists(hid_t object_id, const char* name) { + htri_t out = H5LTpath_valid(object_id, name, true); + if (out < 0) { + std::stringstream err_msg; + err_msg << "Failed to check if object \"" << name << "\" exists."; + fatal_error(err_msg); + } + return (out > 0); +} + + +hid_t +open_dataset(hid_t group_id, const char* name){ + if (object_exists(group_id, name)) { + return H5Dopen(group_id, name, H5P_DEFAULT); + } else { + std::stringstream err_msg; + err_msg << "Group \"" << name << "\" does not exist"; + fatal_error(err_msg); + } +} + + +hid_t +open_group(hid_t group_id, const char* name){ + if (object_exists(group_id, name)) { + return H5Gopen(group_id, name, H5P_DEFAULT); + } else { + std::stringstream err_msg; + err_msg << "Group \"" << name << "\" does not exist"; + fatal_error(err_msg); } } @@ -60,6 +169,35 @@ write_double_1D(hid_t group_id, char const *name, H5Dclose(dataset); } +void +write_double(hid_t group_id, int ndim, const hsize_t* dims, const char* name, + double* buffer, bool indep) { + hid_t dspace = H5Screate_simple(ndim, dims, nullptr); + hid_t dset = H5Dcreate(group_id, name, H5T_NATIVE_DOUBLE, dspace, + H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT); + + if (using_mpio_device(group_id)) { +#ifdef PHDF5 + // Set up collective vs independent I/O + auto data_xfer_mode {indep ? H5FD_MPIO_INDEPENDENT : H5FD_MPIO_COLLECTIVE}; + + // Create dataset transfer property list + hid_t plist = H5Pcreate(H5P_DATASET_XFER); + H5Pset_dxpl_mpio(plist, data_xfer_mode); + + // Write data + H5Dwrite(dset, H5T_NATIVE_DOUBLE, H5S_ALL, H5S_ALL, plist, buffer); + H5Pclose(plist); +#endif + } else { + H5Dwrite(dset, H5T_NATIVE_DOUBLE, H5S_ALL, H5S_ALL, H5P_DEFAULT, buffer); + } + + // Free resources + H5Dclose(dset); + H5Sclose(dspace); +} + void write_string(hid_t group_id, char const *name, char const *buffer) From c74f4738c12c4bf459335508743439efabc1d735 Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Tue, 17 Apr 2018 14:08:59 -0500 Subject: [PATCH 20/77] Use HDF5 file_open from C side (and remove file_create) --- CMakeLists.txt | 1 + src/error.h | 5 +- src/hdf5_interface.F90 | 98 ++++--------------- src/hdf5_interface.cpp | 212 ++++++++++++++++++++++++++++++++++++++++ src/hdf5_interface.h | 208 +++------------------------------------ src/particle_header.F90 | 2 +- src/plot.F90 | 2 +- src/source.F90 | 4 +- src/state_point.F90 | 8 +- src/summary.F90 | 2 +- src/track_output.F90 | 2 +- src/volume_calc.F90 | 4 +- 12 files changed, 261 insertions(+), 287 deletions(-) create mode 100644 src/hdf5_interface.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index ca3d837173..ff7a3334be 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -435,6 +435,7 @@ set(LIBOPENMC_FORTRAN_SRC set(LIBOPENMC_CXX_SRC src/error.h src/hdf5_interface.h + src/hdf5_interface.cpp src/random_lcg.cpp src/random_lcg.h src/simulation.cpp diff --git a/src/error.h b/src/error.h index 4c3373b3e3..91c2727452 100644 --- a/src/error.h +++ b/src/error.h @@ -12,18 +12,19 @@ namespace openmc { extern "C" void fatal_error_from_c(const char *message, int message_len); +inline void fatal_error(const char *message) { fatal_error_from_c(message, strlen(message)); } - +inline void fatal_error(const std::string &message) { fatal_error_from_c(message.c_str(), message.length()); } - +inline void fatal_error(const std::stringstream &message) { std::string out {message.str()}; diff --git a/src/hdf5_interface.F90 b/src/hdf5_interface.F90 index 410149d9e7..0c8d22239a 100644 --- a/src/hdf5_interface.F90 +++ b/src/hdf5_interface.F90 @@ -19,6 +19,7 @@ module hdf5_interface #ifdef PHDF5 use message_passing, only: mpi_intracomm, MPI_INFO_NULL #endif + use string, only: to_c_string implicit none private @@ -84,7 +85,6 @@ module hdf5_interface public :: attribute_exists public :: write_attribute public :: read_attribute - public :: file_create public :: file_open public :: file_close public :: create_group @@ -101,98 +101,36 @@ module hdf5_interface contains -!=============================================================================== -! FILE_CREATE creates HDF5 file -!=============================================================================== - - function file_create(filename, parallel) result(file_id) - character(*), intent(in) :: filename ! name of file - logical, optional, intent(in) :: parallel ! whether to write in serial - integer(HID_T) :: file_id - - integer(HID_T) :: plist ! property list handle - integer :: hdf5_err ! HDF5 error code - logical :: parallel_ - - ! Check for serial option - parallel_ = .false. -#ifdef PHDF5 - if (present(parallel)) parallel_ = parallel -#endif - - if (parallel_) then - ! Setup file access property list with parallel I/O access - call h5pcreate_f(H5P_FILE_ACCESS_F, plist, hdf5_err) -#ifdef PHDF5 -#ifdef OPENMC_MPIF08 - call h5pset_fapl_mpio_f(plist, mpi_intracomm%MPI_VAL, & - MPI_INFO_NULL%MPI_VAL, hdf5_err) -#else - call h5pset_fapl_mpio_f(plist, mpi_intracomm, MPI_INFO_NULL, hdf5_err) -#endif -#endif - - ! Create the file collectively - call h5fcreate_f(trim(filename), H5F_ACC_TRUNC_F, file_id, hdf5_err, & - access_prp = plist) - - ! Close the property list - call h5pclose_f(plist, hdf5_err) - else - ! Create the file - call h5fcreate_f(trim(filename), H5F_ACC_TRUNC_F, file_id, hdf5_err) - end if - - end function file_create - !=============================================================================== ! FILE_OPEN opens HDF5 file !=============================================================================== function file_open(filename, mode, parallel) result(file_id) - character(*), intent(in) :: filename ! name of file - character(*), intent(in) :: mode ! access mode to file - logical, optional, intent(in) :: parallel ! whether to write in serial + character(*), intent(in) :: filename ! name of file + character, value :: mode ! access mode to file + logical, optional, intent(in) :: parallel ! whether to write in serial integer(HID_T) :: file_id - logical :: parallel_ - integer(HID_T) :: plist ! property list handle - integer :: hdf5_err ! HDF5 error code - integer :: open_mode ! HDF5 open mode + character(kind=C_CHAR) :: mode_ + logical(C_BOOL) :: parallel_ - ! Check for serial option + interface + function file_open_c(name, mode, parallel) bind(C, name='file_open') result(file_id) + import HID_T, C_CHAR, C_BOOL, C_INT + character(kind=C_CHAR) :: name(*) + character(kind=C_CHAR), value :: mode + logical(C_BOOL), value :: parallel + integer(HID_T) :: file_id + end function file_open_c + end interface + + mode_ = mode parallel_ = .false. #ifdef PHDF5 if (present(parallel)) parallel_ = parallel #endif - ! Determine access type - open_mode = H5F_ACC_RDONLY_F - if (mode == 'w') open_mode = H5F_ACC_RDWR_F - - if (parallel_) then - ! Setup file access property list with parallel I/O access - call h5pcreate_f(H5P_FILE_ACCESS_F, plist, hdf5_err) -#ifdef PHDF5 -#ifdef OPENMC_MPIF08 - call h5pset_fapl_mpio_f(plist, mpi_intracomm%MPI_VAL, & - MPI_INFO_NULL%MPI_VAL, hdf5_err) -#else - call h5pset_fapl_mpio_f(plist, mpi_intracomm, MPI_INFO_NULL, hdf5_err) -#endif -#endif - - ! Open the file collectively - call h5fopen_f(trim(filename), open_mode, file_id, hdf5_err, & - access_prp = plist) - - ! Close the property list - call h5pclose_f(plist, hdf5_err) - else - ! Open file - call h5fopen_f(trim(filename), open_mode, file_id, hdf5_err) - end if - + file_id = file_open_c(to_c_string(filename), mode, parallel_) end function file_open !=============================================================================== diff --git a/src/hdf5_interface.cpp b/src/hdf5_interface.cpp new file mode 100644 index 0000000000..10357c91d9 --- /dev/null +++ b/src/hdf5_interface.cpp @@ -0,0 +1,212 @@ +#include "hdf5_interface.h" +#include "error.h" + +#include "hdf5.h" +#include "hdf5_hl.h" + +#include +#include +#include + +namespace openmc { + +bool +using_mpio_device(hid_t obj_id) { + // Determine file that this object is part of + hid_t file_id = H5Iget_file_id(obj_id); + + // Get file access property list + hid_t fapl_id = H5Fget_access_plist(file_id); + + // Get low-level driver identifier + hid_t driver = H5Pget_driver(fapl_id); + + // Free resources + H5Pclose(fapl_id); + H5Fclose(file_id); + + return driver == H5FD_MPIO; +} + + +hid_t +create_group(hid_t parent_id, char const *name) +{ + hid_t out = H5Gcreate(parent_id, name, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT); + if (out < 0) { + std::stringstream err_msg; + err_msg << "Failed to create HDF5 group \"" << name << "\""; + fatal_error(err_msg); + } + return out; +} + +hid_t +create_group(hid_t parent_id, const std::string &name) +{ + return create_group(parent_id, name.c_str()); +} + +void +close_dataset(hid_t dataset_id) +{ + if (H5Dclose(dataset_id) < 0) fatal_error("Failed to close dataset"); +} + + +void +close_group(hid_t group_id) +{ + if (H5Gclose(group_id) < 0) fatal_error("Failed to close group"); +} + + +hid_t +file_open(const char* filename, char mode, bool parallel) +{ + bool create; + unsigned int flags; + switch (mode) { + case 'r': + case 'a': + create = false; + flags = (mode == 'r' ? H5F_ACC_RDONLY : H5F_ACC_RDWR); + break; + case 'w': + case 'x': + create = true; + flags = (mode == 'x' ? H5F_ACC_EXCL : H5F_ACC_TRUNC); + break; + default: + std::stringstream err_msg; + err_msg << "Invalid file mode: " << mode; + fatal_error(err_msg); + } + + hid_t plist = H5P_DEFAULT; +#ifdef PHDF5 + if (parallel) { + // Setup file access property list with parallel I/O access + plist = H5Pcreate(H5P_FILE_ACCESS); + H5Pset_fapl_mpio(plist, mpi_intracomm, MPI_INFO_NULL); + } +#endif + + // Open the file collectively + hid_t file_id; + if (create) { + file_id = H5Fcreate(filename, flags, H5P_DEFAULT, plist); + } else { + file_id = H5Fopen(filename, flags, plist); + } + +#ifdef PHDF5 + // Close the property list + if (parallel) H5Pclose(plist); +#endif + + return file_id; +} + +hid_t +file_open(const std::string& filename, char mode, bool parallel=false) { + file_open(filename.c_str(), mode, parallel); +} + +void file_close(hid_t file_id) { + H5Fclose(file_id); +} + +bool +object_exists(hid_t object_id, const char* name) { + htri_t out = H5LTpath_valid(object_id, name, true); + if (out < 0) { + std::stringstream err_msg; + err_msg << "Failed to check if object \"" << name << "\" exists."; + fatal_error(err_msg); + } + return (out > 0); +} + + +hid_t +open_dataset(hid_t group_id, const char* name){ + if (object_exists(group_id, name)) { + return H5Dopen(group_id, name, H5P_DEFAULT); + } else { + std::stringstream err_msg; + err_msg << "Group \"" << name << "\" does not exist"; + fatal_error(err_msg); + } +} + + +hid_t +open_group(hid_t group_id, const char* name){ + if (object_exists(group_id, name)) { + return H5Gopen(group_id, name, H5P_DEFAULT); + } else { + std::stringstream err_msg; + err_msg << "Group \"" << name << "\" does not exist"; + fatal_error(err_msg); + } +} + + +void +write_double(hid_t group_id, int ndim, const hsize_t* dims, const char* name, + double* buffer, bool indep) { + hid_t dspace = H5Screate_simple(ndim, dims, nullptr); + hid_t dset = H5Dcreate(group_id, name, H5T_NATIVE_DOUBLE, dspace, + H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT); + + if (using_mpio_device(group_id)) { +#ifdef PHDF5 + // Set up collective vs independent I/O + auto data_xfer_mode {indep ? H5FD_MPIO_INDEPENDENT : H5FD_MPIO_COLLECTIVE}; + + // Create dataset transfer property list + hid_t plist = H5Pcreate(H5P_DATASET_XFER); + H5Pset_dxpl_mpio(plist, data_xfer_mode); + + // Write data + H5Dwrite(dset, H5T_NATIVE_DOUBLE, H5S_ALL, H5S_ALL, plist, buffer); + H5Pclose(plist); +#endif + } else { + H5Dwrite(dset, H5T_NATIVE_DOUBLE, H5S_ALL, H5S_ALL, H5P_DEFAULT, buffer); + } + + // Free resources + H5Dclose(dset); + H5Sclose(dspace); +} + + +void +write_string(hid_t group_id, char const *name, char const *buffer) +{ + size_t buffer_len = strlen(buffer); + hid_t datatype = H5Tcopy(H5T_C_S1); + H5Tset_size(datatype, buffer_len); + + hid_t dataspace = H5Screate(H5S_SCALAR); + + hid_t dataset = H5Dcreate(group_id, name, datatype, dataspace, + H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT); + + H5Dwrite(dataset, datatype, H5S_ALL, H5S_ALL, H5P_DEFAULT, buffer); + + H5Tclose(datatype); + H5Sclose(dataspace); + H5Dclose(dataset); +} + + +void +write_string(hid_t group_id, char const *name, const std::string &buffer) +{ + write_string(group_id, name, buffer.c_str()); +} + +} diff --git a/src/hdf5_interface.h b/src/hdf5_interface.h index 8a445b21e6..b79e0a29cb 100644 --- a/src/hdf5_interface.h +++ b/src/hdf5_interface.h @@ -1,8 +1,6 @@ #ifndef HDF5_INTERFACE_H #define HDF5_INTERFACE_H -#include "error.h" - #include "hdf5.h" #include "hdf5_hl.h" @@ -13,143 +11,17 @@ namespace openmc { -bool -using_mpio_device(hid_t obj_id) { - // Determine file that this object is part of - hid_t file_id = H5Iget_file_id(obj_id); - - // Get file access property list - hid_t fapl_id = H5Fget_access_plist(file_id); - - // Get low-level driver identifier - hid_t driver = H5Pget_driver(fapl_id); - - // Free resources - H5Pclose(fapl_id); - H5Fclose(file_id); - - return driver == H5FD_MPIO; -} - - -hid_t -create_group(hid_t parent_id, char const *name) -{ - hid_t out = H5Gcreate(parent_id, name, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT); - if (out < 0) { - std::stringstream err_msg; - err_msg << "Failed to create HDF5 group \"" << name << "\""; - fatal_error(err_msg); - } - return out; -} - -hid_t -create_group(hid_t parent_id, const std::string &name) -{ - return create_group(parent_id, name.c_str()); -} - -void -close_dataset(hid_t dataset_id) -{ - if (H5Dclose(dataset_id) < 0) fatal_error("Failed to close dataset"); -} - - -void -close_group(hid_t group_id) -{ - if (H5Gclose(group_id) < 0) fatal_error("Failed to close group"); -} - - -hid_t -file_open(const char* filename, char mode, bool parallel=false) -{ - bool create; - unsigned int flags; - switch (mode) { - case 'r': - case 'a': - create = false; - flags = (mode == 'r' ? H5F_ACC_RDONLY : H5F_ACC_RDWR); - break; - case 'w': - case 'x': - create = true; - flags = (mode == 'x' ? H5F_ACC_EXCL : H5F_ACC_TRUNC); - break; - } - - hid_t plist; - if (parallel) { - // Setup file access property list with parallel I/O access - plist = H5Pcreate(H5P_FILE_ACCESS); -#ifdef PHDF5 - H5Pset_fapl_mpio(plist, mpi_intracomm, MPI_INFO_NULL); -#endif - } else { - plist = H5P_DEFAULT; - } - - // Open the file collectively - hid_t file_id; - if (create) { - file_id = H5Fopen(filename, flags, plist); - } else { - file_id = H5Fcreate(filename, flags, H5P_DEFAULT, plist); - } - - // Close the property list - if (parallel) H5Pclose(plist); - - return file_id; -} - -hid_t -file_open(const std::string& filename, char mode, bool parallel=false) { - file_open(filename.c_str(), mode, parallel); -} - -void file_close(hid_t file_id) { - H5Fclose(file_id); -} - -bool -object_exists(hid_t object_id, const char* name) { - htri_t out = H5LTpath_valid(object_id, name, true); - if (out < 0) { - std::stringstream err_msg; - err_msg << "Failed to check if object \"" << name << "\" exists."; - fatal_error(err_msg); - } - return (out > 0); -} - - -hid_t -open_dataset(hid_t group_id, const char* name){ - if (object_exists(group_id, name)) { - return H5Dopen(group_id, name, H5P_DEFAULT); - } else { - std::stringstream err_msg; - err_msg << "Group \"" << name << "\" does not exist"; - fatal_error(err_msg); - } -} - - -hid_t -open_group(hid_t group_id, const char* name){ - if (object_exists(group_id, name)) { - return H5Gopen(group_id, name, H5P_DEFAULT); - } else { - std::stringstream err_msg; - err_msg << "Group \"" << name << "\" does not exist"; - fatal_error(err_msg); - } -} +bool using_mpio_device(hid_t obj_id); +hid_t create_group(hid_t parent_id, const char* name); +hid_t create_group(hid_t parent_id, const std::string& name); +void close_dataset(hid_t dataset_id); +void close_group(hid_t group_id); +extern "C" hid_t file_open(const char* filename, char mode, bool parallel); +hid_t file_open(const std::string& filename, char mode, bool parallel); +void file_close(hid_t file_id); +bool object_exists(hid_t object_id, const char* name); +hid_t open_dataset(hid_t group_id, const char* name); +hid_t open_group(hid_t group_id, const char* name); template void @@ -169,61 +41,11 @@ write_double_1D(hid_t group_id, char const *name, H5Dclose(dataset); } -void -write_double(hid_t group_id, int ndim, const hsize_t* dims, const char* name, - double* buffer, bool indep) { - hid_t dspace = H5Screate_simple(ndim, dims, nullptr); - hid_t dset = H5Dcreate(group_id, name, H5T_NATIVE_DOUBLE, dspace, - H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT); +void write_double(hid_t group_id, int ndim, const hsize_t* dims, const char* name, + double* buffer, bool indep); - if (using_mpio_device(group_id)) { -#ifdef PHDF5 - // Set up collective vs independent I/O - auto data_xfer_mode {indep ? H5FD_MPIO_INDEPENDENT : H5FD_MPIO_COLLECTIVE}; - - // Create dataset transfer property list - hid_t plist = H5Pcreate(H5P_DATASET_XFER); - H5Pset_dxpl_mpio(plist, data_xfer_mode); - - // Write data - H5Dwrite(dset, H5T_NATIVE_DOUBLE, H5S_ALL, H5S_ALL, plist, buffer); - H5Pclose(plist); -#endif - } else { - H5Dwrite(dset, H5T_NATIVE_DOUBLE, H5S_ALL, H5S_ALL, H5P_DEFAULT, buffer); - } - - // Free resources - H5Dclose(dset); - H5Sclose(dspace); -} - - -void -write_string(hid_t group_id, char const *name, char const *buffer) -{ - size_t buffer_len = strlen(buffer); - hid_t datatype = H5Tcopy(H5T_C_S1); - H5Tset_size(datatype, buffer_len); - - hid_t dataspace = H5Screate(H5S_SCALAR); - - hid_t dataset = H5Dcreate(group_id, name, datatype, dataspace, - H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT); - - H5Dwrite(dataset, datatype, H5S_ALL, H5S_ALL, H5P_DEFAULT, buffer); - - H5Tclose(datatype); - H5Sclose(dataspace); - H5Dclose(dataset); -} - - -void -write_string(hid_t group_id, char const *name, const std::string &buffer) -{ - write_string(group_id, name, buffer.c_str()); -} +void write_string(hid_t group_id, char const *name, char const *buffer); +void write_string(hid_t group_id, char const *name, const std::string &buffer); } // namespace openmc #endif //HDF5_INTERFACE_H diff --git a/src/particle_header.F90 b/src/particle_header.F90 index 552f9b042d..02fb55405a 100644 --- a/src/particle_header.F90 +++ b/src/particle_header.F90 @@ -312,7 +312,7 @@ contains !$omp critical (WriteParticleRestart) ! Create file - file_id = file_create(filename) + file_id = file_open(filename, 'w') associate (src => source_bank(current_work)) ! Write filetype and version info diff --git a/src/plot.F90 b/src/plot.F90 index 5eb894ce8d..92b8f350df 100644 --- a/src/plot.F90 +++ b/src/plot.F90 @@ -371,7 +371,7 @@ contains p % coord(1) % universe = root_universe ! Open binary plot file for writing - file_id = file_create(pl%path_plot) + file_id = file_open(pl%path_plot, 'w') ! write header info call write_attribute(file_id, "filetype", 'voxel') diff --git a/src/source.F90 b/src/source.F90 index 5beecd8870..9e3a0831de 100644 --- a/src/source.F90 +++ b/src/source.F90 @@ -12,7 +12,7 @@ module source use distribution_multivariate, only: SpatialBox use error, only: fatal_error use geometry, only: find_cell - use hdf5_interface, only: file_create, file_open, file_close, read_dataset + use hdf5_interface, only: file_open, file_close, read_dataset use math use message_passing, only: rank use mgxs_header, only: rev_energy_bins, num_energy_groups @@ -88,7 +88,7 @@ contains if (write_initial_source) then call write_message('Writing out initial source...', 5) filename = trim(path_output) // 'initial_source.h5' - file_id = file_create(filename, parallel=.true.) + file_id = file_open(filename, 'w', parallel=.true.) call write_source_bank(file_id) call file_close(file_id) end if diff --git a/src/state_point.F90 b/src/state_point.F90 index 980a7333cd..62240f110a 100644 --- a/src/state_point.F90 +++ b/src/state_point.F90 @@ -76,7 +76,7 @@ contains if (master) then ! Create statepoint file - file_id = file_create(filename_) + file_id = file_open(filename_, 'w') ! Write file type call write_attribute(file_id, "filetype", "statepoint") @@ -476,7 +476,7 @@ contains ! Create separate source file if (master .or. parallel) then - file_id = file_create(filename, parallel=.true.) + file_id = file_open(filename, 'w', parallel=.true.) call write_dataset(file_id, "filetype", 'source') end if else @@ -485,7 +485,7 @@ contains filename = trim(filename) // '.h5' if (master .or. parallel) then - file_id = file_open(filename, 'w', parallel=.true.) + file_id = file_open(filename, 'a', parallel=.true.) end if end if @@ -498,7 +498,7 @@ contains filename = trim(path_output) // 'source' // '.h5' call write_message("Creating source file " // trim(filename) // "...", 5) if (master .or. parallel) then - file_id = file_create(filename, parallel=.true.) + file_id = file_open(filename, 'w', parallel=.true.) call write_dataset(file_id, "filetype", 'source') end if diff --git a/src/summary.F90 b/src/summary.F90 index 3aeb42178b..9f27694d1b 100644 --- a/src/summary.F90 +++ b/src/summary.F90 @@ -38,7 +38,7 @@ contains call write_message("Writing summary.h5 file...", 5) ! Create a new file using default properties. - file_id = file_create("summary.h5") + file_id = file_open("summary.h5", 'w') call write_header(file_id) call write_nuclides(file_id) diff --git a/src/track_output.F90 b/src/track_output.F90 index 244bf182e0..350e687b1c 100644 --- a/src/track_output.F90 +++ b/src/track_output.F90 @@ -115,7 +115,7 @@ contains end do !$omp critical (FinalizeParticleTrack) - file_id = file_create(fname) + file_id = file_open(fname, 'w') call write_attribute(file_id, 'filetype', 'track') call write_attribute(file_id, 'version', VERSION_TRACK) call write_attribute(file_id, 'n_particles', n_particle_tracks) diff --git a/src/volume_calc.F90 b/src/volume_calc.F90 index e374f21064..ac813a94af 100644 --- a/src/volume_calc.F90 +++ b/src/volume_calc.F90 @@ -11,7 +11,7 @@ module volume_calc use error, only: write_message use geometry, only: find_cell use geometry_header, only: universes, cells - use hdf5_interface, only: file_create, file_close, write_attribute, & + use hdf5_interface, only: file_open, file_close, write_attribute, & create_group, close_group, write_dataset use output, only: header, time_stamp use material_header, only: materials @@ -435,7 +435,7 @@ contains character(MAX_WORD_LEN), allocatable :: nucnames(:) ! names of nuclides ! Create HDF5 file - file_id = file_create(filename) + file_id = file_open(filename, 'w') ! Write header info call write_attribute(file_id, "filetype", "volume") From b3bd34e51b887d4f9099aa089f2c2bdea4255edd Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Tue, 17 Apr 2018 15:29:35 -0500 Subject: [PATCH 21/77] Use file_close from C --- src/hdf5_interface.F90 | 19 +++++++------------ src/hdf5_interface.h | 2 +- 2 files changed, 8 insertions(+), 13 deletions(-) diff --git a/src/hdf5_interface.F90 b/src/hdf5_interface.F90 index 0c8d22239a..fa1f6093b6 100644 --- a/src/hdf5_interface.F90 +++ b/src/hdf5_interface.F90 @@ -99,6 +99,13 @@ module hdf5_interface public :: get_datasets public :: get_name + interface + subroutine file_close(file_id) bind(C) + import HID_T + integer(HID_T), value :: file_id + end subroutine file_close + end interface + contains !=============================================================================== @@ -133,18 +140,6 @@ contains file_id = file_open_c(to_c_string(filename), mode, parallel_) end function file_open -!=============================================================================== -! FILE_CLOSE closes HDF5 file -!=============================================================================== - - subroutine file_close(file_id) - integer(HID_T), intent(in) :: file_id - - integer :: hdf5_err - - call h5fclose_f(file_id, hdf5_err) - end subroutine file_close - !=============================================================================== ! GET_GROUPS Gets a list of all the groups in a given location. !=============================================================================== diff --git a/src/hdf5_interface.h b/src/hdf5_interface.h index b79e0a29cb..3ddd59374e 100644 --- a/src/hdf5_interface.h +++ b/src/hdf5_interface.h @@ -18,7 +18,7 @@ void close_dataset(hid_t dataset_id); void close_group(hid_t group_id); extern "C" hid_t file_open(const char* filename, char mode, bool parallel); hid_t file_open(const std::string& filename, char mode, bool parallel); -void file_close(hid_t file_id); +extern "C" void file_close(hid_t file_id); bool object_exists(hid_t object_id, const char* name); hid_t open_dataset(hid_t group_id, const char* name); hid_t open_group(hid_t group_id, const char* name); From dcde6a331a8ddb0e469a7a0cd04c48ae2892e5f9 Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Tue, 17 Apr 2018 16:14:22 -0500 Subject: [PATCH 22/77] Use HDF5 write_double from C++ --- src/hdf5_interface.F90 | 219 ++++++----------------------------------- src/hdf5_interface.cpp | 2 +- src/hdf5_interface.h | 4 +- 3 files changed, 34 insertions(+), 191 deletions(-) diff --git a/src/hdf5_interface.F90 b/src/hdf5_interface.F90 index fa1f6093b6..040b115482 100644 --- a/src/hdf5_interface.F90 +++ b/src/hdf5_interface.F90 @@ -104,6 +104,17 @@ module hdf5_interface import HID_T integer(HID_T), value :: file_id end subroutine file_close + + subroutine write_double_c(group_id, ndim, dims, name, buffer, indep) & + bind(C, name='write_double') + import HID_T, HSIZE_T, C_INT, C_DOUBLE, C_CHAR, C_BOOL, C_PTR + integer(HID_T), value :: group_id + integer(C_INT), value :: ndim + integer(HSIZE_T), intent(in) :: dims(*) + character(kind=C_CHAR), intent(in) :: name(*) + real(C_DOUBLE), intent(in) :: buffer(*) + logical(C_BOOL), intent(in) :: indep + end subroutine write_double_c end interface contains @@ -472,57 +483,15 @@ contains logical, intent(in), optional :: indep ! independent I/O integer(HSIZE_T) :: dims(1) + logical(C_BOOL) :: indep_ dims(:) = shape(buffer) - if (present(indep)) then - call write_double_1D_explicit(group_id, dims, name, buffer, indep) - else - call write_double_1D_explicit(group_id, dims, name, buffer) - end if + indep_ = .false. + if (present(indep)) indep_ = indep + + call write_double_c(group_id, 1, dims, to_c_string(name), buffer, indep_) end subroutine write_double_1D - subroutine write_double_1D_explicit(group_id, dims, name, buffer, indep) - integer(HID_T), intent(in) :: group_id - integer(HSIZE_T), intent(in) :: dims(1) - character(*), intent(in) :: name ! name of data - real(8), intent(in), target :: buffer(dims(1)) ! data to write - logical, intent(in), optional :: indep ! independent I/O - - integer :: hdf5_err - integer :: data_xfer_mode -#ifdef PHDF5 - integer(HID_T) :: plist ! property list -#endif - integer(HID_T) :: dset ! data set handle - integer(HID_T) :: dspace ! data or file space handle - type(c_ptr) :: f_ptr - - ! Set up collective vs. independent I/O - data_xfer_mode = H5FD_MPIO_COLLECTIVE_F - if (present(indep)) then - if (indep) data_xfer_mode = H5FD_MPIO_INDEPENDENT_F - end if - - call h5screate_simple_f(1, dims, dspace, hdf5_err) - call h5dcreate_f(group_id, trim(name), H5T_NATIVE_DOUBLE, & - dspace, dset, hdf5_err) - f_ptr = c_loc(buffer) - - if (using_mpio_device(group_id)) then -#ifdef PHDF5 - call h5pcreate_f(H5P_DATASET_XFER_F, plist, hdf5_err) - call h5pset_dxpl_mpio_f(plist, data_xfer_mode, hdf5_err) - call h5dwrite_f(dset, H5T_NATIVE_DOUBLE, f_ptr, hdf5_err, xfer_prp=plist) - call h5pclose_f(plist, hdf5_err) -#endif - else - call h5dwrite_f(dset, H5T_NATIVE_DOUBLE, f_ptr, hdf5_err) - end if - - call h5dclose_f(dset, hdf5_err) - call h5sclose_f(dspace, hdf5_err) - end subroutine write_double_1D_explicit - !=============================================================================== ! READ_DOUBLE_1D reads double precision 1-D array data !=============================================================================== @@ -600,57 +569,15 @@ contains logical, intent(in), optional :: indep ! independent I/O integer(HSIZE_T) :: dims(2) + logical(C_BOOL) :: indep_ dims(:) = shape(buffer) - if (present(indep)) then - call write_double_2D_explicit(group_id, dims, name, buffer, indep) - else - call write_double_2D_explicit(group_id, dims, name, buffer) - end if + indep_ = .false. + if (present(indep)) indep_ = indep + + call write_double_c(group_id, 2, dims, to_c_string(name), buffer, indep_) end subroutine write_double_2D - subroutine write_double_2D_explicit(group_id, dims, name, buffer, indep) - integer(HID_T), intent(in) :: group_id - integer(HSIZE_T), intent(in) :: dims(2) - character(*), intent(in) :: name ! name of data - real(8), intent(in), target :: buffer(dims(1),dims(2)) - logical, intent(in), optional :: indep ! independent I/O - - integer :: hdf5_err - integer :: data_xfer_mode -#ifdef PHDF5 - integer(HID_T) :: plist ! property list -#endif - integer(HID_T) :: dset ! data set handle - integer(HID_T) :: dspace ! data or file space handle - type(c_ptr) :: f_ptr - - ! Set up collective vs. independent I/O - data_xfer_mode = H5FD_MPIO_COLLECTIVE_F - if (present(indep)) then - if (indep) data_xfer_mode = H5FD_MPIO_INDEPENDENT_F - end if - - call h5screate_simple_f(2, dims, dspace, hdf5_err) - call h5dcreate_f(group_id, trim(name), H5T_NATIVE_DOUBLE, & - dspace, dset, hdf5_err) - f_ptr = c_loc(buffer) - - if (using_mpio_device(group_id)) then -#ifdef PHDF5 - call h5pcreate_f(H5P_DATASET_XFER_F, plist, hdf5_err) - call h5pset_dxpl_mpio_f(plist, data_xfer_mode, hdf5_err) - call h5dwrite_f(dset, H5T_NATIVE_DOUBLE, f_ptr, hdf5_err, xfer_prp=plist) - call h5pclose_f(plist, hdf5_err) -#endif - else - call h5dwrite_f(dset, H5T_NATIVE_DOUBLE, f_ptr, hdf5_err) - end if - - call h5dclose_f(dset, hdf5_err) - call h5sclose_f(dspace, hdf5_err) - end subroutine write_double_2D_explicit - !=============================================================================== ! READ_DOUBLE_2D reads double precision 2-D array data !=============================================================================== @@ -728,57 +655,15 @@ contains logical, intent(in), optional :: indep ! independent I/O integer(HSIZE_T) :: dims(3) + logical(C_BOOL) :: indep_ dims(:) = shape(buffer) - if (present(indep)) then - call write_double_3D_explicit(group_id, dims, name, buffer, indep) - else - call write_double_3D_explicit(group_id, dims, name, buffer) - end if + indep_ = .false. + if (present(indep)) indep_ = indep + + call write_double_c(group_id, 3, dims, to_c_string(name), buffer, indep_) end subroutine write_double_3D - subroutine write_double_3D_explicit(group_id, dims, name, buffer, indep) - integer(HID_T), intent(in) :: group_id - integer(HSIZE_T), intent(in) :: dims(3) - character(*), intent(in) :: name ! name of data - real(8), intent(in), target :: buffer(dims(1),dims(2),dims(3)) - logical, intent(in), optional :: indep ! independent I/O - - integer :: hdf5_err - integer :: data_xfer_mode -#ifdef PHDF5 - integer(HID_T) :: plist ! property list -#endif - integer(HID_T) :: dset ! data set handle - integer(HID_T) :: dspace ! data or file space handle - type(c_ptr) :: f_ptr - - ! Set up collective vs. independent I/O - data_xfer_mode = H5FD_MPIO_COLLECTIVE_F - if (present(indep)) then - if (indep) data_xfer_mode = H5FD_MPIO_INDEPENDENT_F - end if - - call h5screate_simple_f(3, dims, dspace, hdf5_err) - call h5dcreate_f(group_id, trim(name), H5T_NATIVE_DOUBLE, & - dspace, dset, hdf5_err) - f_ptr = c_loc(buffer) - - if (using_mpio_device(group_id)) then -#ifdef PHDF5 - call h5pcreate_f(H5P_DATASET_XFER_F, plist, hdf5_err) - call h5pset_dxpl_mpio_f(plist, data_xfer_mode, hdf5_err) - call h5dwrite_f(dset, H5T_NATIVE_DOUBLE, f_ptr, hdf5_err, xfer_prp=plist) - call h5pclose_f(plist, hdf5_err) -#endif - else - call h5dwrite_f(dset, H5T_NATIVE_DOUBLE, f_ptr, hdf5_err) - end if - - call h5dclose_f(dset, hdf5_err) - call h5sclose_f(dspace, hdf5_err) - end subroutine write_double_3D_explicit - !=============================================================================== ! READ_DOUBLE_3D reads double precision 3-D array data !=============================================================================== @@ -856,57 +741,15 @@ contains logical, intent(in), optional :: indep ! independent I/O integer(HSIZE_T) :: dims(4) + logical(C_BOOL) :: indep_ dims(:) = shape(buffer) - if (present(indep)) then - call write_double_4D_explicit(group_id, dims, name, buffer, indep) - else - call write_double_4D_explicit(group_id, dims, name, buffer) - end if + indep_ = .false. + if (present(indep)) indep_ = indep + + call write_double_c(group_id, 1, dims, to_c_string(name), buffer, indep_) end subroutine write_double_4D - subroutine write_double_4D_explicit(group_id, dims, name, buffer, indep) - integer(HID_T), intent(in) :: group_id - integer(HSIZE_T), intent(in) :: dims(4) - character(*), intent(in) :: name ! name of data - real(8), intent(in), target :: buffer(dims(1),dims(2),dims(3),dims(4)) - logical, intent(in), optional :: indep ! independent I/O - - integer :: hdf5_err - integer :: data_xfer_mode -#ifdef PHDF5 - integer(HID_T) :: plist ! property list -#endif - integer(HID_T) :: dset ! data set handle - integer(HID_T) :: dspace ! data or file space handle - type(c_ptr) :: f_ptr - - ! Set up collective vs. independent I/O - data_xfer_mode = H5FD_MPIO_COLLECTIVE_F - if (present(indep)) then - if (indep) data_xfer_mode = H5FD_MPIO_INDEPENDENT_F - end if - - call h5screate_simple_f(4, dims, dspace, hdf5_err) - call h5dcreate_f(group_id, trim(name), H5T_NATIVE_DOUBLE, & - dspace, dset, hdf5_err) - f_ptr = c_loc(buffer) - - if (using_mpio_device(group_id)) then -#ifdef PHDF5 - call h5pcreate_f(H5P_DATASET_XFER_F, plist, hdf5_err) - call h5pset_dxpl_mpio_f(plist, data_xfer_mode, hdf5_err) - call h5dwrite_f(dset, H5T_NATIVE_DOUBLE, f_ptr, hdf5_err, xfer_prp=plist) - call h5pclose_f(plist, hdf5_err) -#endif - else - call h5dwrite_f(dset, H5T_NATIVE_DOUBLE, f_ptr, hdf5_err) - end if - - call h5dclose_f(dset, hdf5_err) - call h5sclose_f(dspace, hdf5_err) - end subroutine write_double_4D_explicit - !=============================================================================== ! READ_DOUBLE_4D reads double precision 4-D array data !=============================================================================== diff --git a/src/hdf5_interface.cpp b/src/hdf5_interface.cpp index 10357c91d9..a2ccef7f7d 100644 --- a/src/hdf5_interface.cpp +++ b/src/hdf5_interface.cpp @@ -155,7 +155,7 @@ open_group(hid_t group_id, const char* name){ void write_double(hid_t group_id, int ndim, const hsize_t* dims, const char* name, - double* buffer, bool indep) { + const double* buffer, bool indep) { hid_t dspace = H5Screate_simple(ndim, dims, nullptr); hid_t dset = H5Dcreate(group_id, name, H5T_NATIVE_DOUBLE, dspace, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT); diff --git a/src/hdf5_interface.h b/src/hdf5_interface.h index 3ddd59374e..bbf5ce5e88 100644 --- a/src/hdf5_interface.h +++ b/src/hdf5_interface.h @@ -41,8 +41,8 @@ write_double_1D(hid_t group_id, char const *name, H5Dclose(dataset); } -void write_double(hid_t group_id, int ndim, const hsize_t* dims, const char* name, - double* buffer, bool indep); +extern "C" void write_double(hid_t group_id, int ndim, const hsize_t* dims, const char* name, + const double* buffer, bool indep); void write_string(hid_t group_id, char const *name, char const *buffer); void write_string(hid_t group_id, char const *name, const std::string &buffer); From ef1956e8113db9618693b8aa49b3ff427272b136 Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Tue, 17 Apr 2018 22:55:07 -0500 Subject: [PATCH 23/77] Convert HDF5 read_double to C++ --- src/hdf5_interface.F90 | 274 ++++++++--------------------------------- src/hdf5_interface.cpp | 58 +++++++-- src/hdf5_interface.h | 7 +- 3 files changed, 104 insertions(+), 235 deletions(-) diff --git a/src/hdf5_interface.F90 b/src/hdf5_interface.F90 index 040b115482..b9e6c414e6 100644 --- a/src/hdf5_interface.F90 +++ b/src/hdf5_interface.F90 @@ -105,9 +105,18 @@ module hdf5_interface integer(HID_T), value :: file_id end subroutine file_close + subroutine read_double_c(obj_id, name, buffer, indep) & + bind(C, name='read_double') + import HID_T, C_DOUBLE, C_BOOL, C_PTR + integer(HID_T), value :: obj_id + type(C_PTR), value :: name + real(C_DOUBLE), intent(in) :: buffer(*) + logical(C_BOOL), intent(in) :: indep + end subroutine read_double_c + subroutine write_double_c(group_id, ndim, dims, name, buffer, indep) & bind(C, name='write_double') - import HID_T, HSIZE_T, C_INT, C_DOUBLE, C_CHAR, C_BOOL, C_PTR + import HID_T, HSIZE_T, C_INT, C_DOUBLE, C_CHAR, C_BOOL integer(HID_T), value :: group_id integer(C_INT), value :: ndim integer(HSIZE_T), intent(in) :: dims(*) @@ -388,40 +397,15 @@ contains real(8), intent(in), target :: buffer ! data to write logical, intent(in), optional :: indep ! independent I/O - integer :: hdf5_err - integer :: data_xfer_mode -#ifdef PHDF5 - integer(HID_T) :: plist ! property list -#endif - integer(HID_T) :: dset ! data set handle - integer(HID_T) :: dspace ! data or file space handle - type(c_ptr) :: f_ptr + integer(HSIZE_T) :: dims(0) + logical(C_BOOL) :: indep_ + real(C_DOUBLE) :: value(1) - ! Set up independentive vs. independent I/O - data_xfer_mode = H5FD_MPIO_COLLECTIVE_F - if (present(indep)) then - if (indep) data_xfer_mode = H5FD_MPIO_INDEPENDENT_F - end if + indep_ = .false. + if (present(indep)) indep_ = indep + value(1) = buffer - ! Create dataspace and dataset - call h5screate_f(H5S_SCALAR_F, dspace, hdf5_err) - call h5dcreate_f(group_id, trim(name), H5T_NATIVE_DOUBLE, & - dspace, dset, hdf5_err) - f_ptr = c_loc(buffer) - - if (using_mpio_device(group_id)) then -#ifdef PHDF5 - call h5pcreate_f(H5P_DATASET_XFER_F, plist, hdf5_err) - call h5pset_dxpl_mpio_f(plist, data_xfer_mode, hdf5_err) - call h5dwrite_f(dset, H5T_NATIVE_DOUBLE, f_ptr, hdf5_err, xfer_prp=plist) - call h5pclose_f(plist, hdf5_err) -#endif - else - call h5dwrite_f(dset, H5T_NATIVE_DOUBLE, f_ptr, hdf5_err) - end if - - call h5dclose_f(dset, hdf5_err) - call h5sclose_f(dspace, hdf5_err) + call write_double_c(group_id, 0, dims, to_c_string(name), value, indep_) end subroutine write_double !=============================================================================== @@ -502,62 +486,22 @@ contains character(*), optional, intent(in) :: name logical, optional, intent(in) :: indep ! independent I/O - integer :: hdf5_err - integer(HID_T) :: dset_id - integer(HSIZE_T) :: dims(1) + logical(C_BOOL) :: indep_ + character(kind=C_CHAR), target, allocatable :: name_(:) + + indep_ = .false. + if (present(indep)) indep_ = indep ! If 'name' argument is passed, obj_id is interpreted to be a group and ! 'name' is the name of the dataset we should read from if (present(name)) then - call h5dopen_f(obj_id, trim(name), dset_id, hdf5_err) + name_ = to_c_string(name) + call read_double_c(obj_id, c_loc(name_), buffer, indep_) else - dset_id = obj_id + call read_double_c(obj_id, C_NULL_PTR, buffer, indep_) end if - - dims(:) = shape(buffer) - - if (present(indep)) then - call read_double_1D_explicit(dset_id, dims, buffer, indep) - else - call read_double_1D_explicit(dset_id, dims, buffer) - end if - - if (present(name)) call h5dclose_f(dset_id, hdf5_err) end subroutine read_double_1D - subroutine read_double_1D_explicit(dset_id, dims, buffer, indep) - integer(HID_T), intent(in) :: dset_id - integer(HSIZE_T), intent(in) :: dims(1) - real(8), target, intent(inout) :: buffer(dims(1)) - logical, optional, intent(in) :: indep ! independent I/O - - integer :: hdf5_err - integer :: data_xfer_mode -#ifdef PHDF5 - integer(HID_T) :: plist ! property list -#endif - type(c_ptr) :: f_ptr - - ! Set up collective vs. independent I/O - data_xfer_mode = H5FD_MPIO_COLLECTIVE_F - if (present(indep)) then - if (indep) data_xfer_mode = H5FD_MPIO_INDEPENDENT_F - end if - - f_ptr = c_loc(buffer) - - if (using_mpio_device(dset_id)) then -#ifdef PHDF5 - call h5pcreate_f(H5P_DATASET_XFER_F, plist, hdf5_err) - call h5pset_dxpl_mpio_f(plist, data_xfer_mode, hdf5_err) - call h5dread_f(dset_id, H5T_NATIVE_DOUBLE, f_ptr, hdf5_err, xfer_prp=plist) - call h5pclose_f(plist, hdf5_err) -#endif - else - call h5dread_f(dset_id, H5T_NATIVE_DOUBLE, f_ptr, hdf5_err) - end if - end subroutine read_double_1D_explicit - !=============================================================================== ! WRITE_DOUBLE_2D writes double precision 2-D array data !=============================================================================== @@ -588,62 +532,22 @@ contains character(*), optional, intent(in) :: name logical, optional, intent(in) :: indep ! independent I/O - integer :: hdf5_err - integer(HID_T) :: dset_id - integer(HSIZE_T) :: dims(2) + logical(C_BOOL) :: indep_ + character(kind=C_CHAR), target, allocatable :: name_(:) + + indep_ = .false. + if (present(indep)) indep_ = indep ! If 'name' argument is passed, obj_id is interpreted to be a group and ! 'name' is the name of the dataset we should read from if (present(name)) then - call h5dopen_f(obj_id, trim(name), dset_id, hdf5_err) + name_ = to_c_string(name) + call read_double_c(obj_id, c_loc(name_), buffer, indep_) else - dset_id = obj_id + call read_double_c(obj_id, C_NULL_PTR, buffer, indep_) end if - - dims(:) = shape(buffer) - - if (present(indep)) then - call read_double_2D_explicit(dset_id, dims, buffer, indep) - else - call read_double_2D_explicit(dset_id, dims, buffer) - end if - - if (present(name)) call h5dclose_f(dset_id, hdf5_err) end subroutine read_double_2D - subroutine read_double_2D_explicit(dset_id, dims, buffer, indep) - integer(HID_T), intent(in) :: dset_id - integer(HSIZE_T), intent(in) :: dims(2) - real(8), target, intent(inout) :: buffer(dims(1),dims(2)) - logical, optional, intent(in) :: indep ! independent I/O - - integer :: hdf5_err - integer :: data_xfer_mode -#ifdef PHDF5 - integer(HID_T) :: plist ! property list -#endif - type(c_ptr) :: f_ptr - - ! Set up collective vs. independent I/O - data_xfer_mode = H5FD_MPIO_COLLECTIVE_F - if (present(indep)) then - if (indep) data_xfer_mode = H5FD_MPIO_INDEPENDENT_F - end if - - f_ptr = c_loc(buffer) - - if (using_mpio_device(dset_id)) then -#ifdef PHDF5 - call h5pcreate_f(H5P_DATASET_XFER_F, plist, hdf5_err) - call h5pset_dxpl_mpio_f(plist, data_xfer_mode, hdf5_err) - call h5dread_f(dset_id, H5T_NATIVE_DOUBLE, f_ptr, hdf5_err, xfer_prp=plist) - call h5pclose_f(plist, hdf5_err) -#endif - else - call h5dread_f(dset_id, H5T_NATIVE_DOUBLE, f_ptr, hdf5_err) - end if - end subroutine read_double_2D_explicit - !=============================================================================== ! WRITE_DOUBLE_3D writes double precision 3-D array data !=============================================================================== @@ -674,62 +578,22 @@ contains character(*), optional, intent(in) :: name logical, optional, intent(in) :: indep ! independent I/O - integer :: hdf5_err - integer(HID_T) :: dset_id - integer(HSIZE_T) :: dims(3) + logical(C_BOOL) :: indep_ + character(kind=C_CHAR), target, allocatable :: name_(:) + + indep_ = .false. + if (present(indep)) indep_ = indep ! If 'name' argument is passed, obj_id is interpreted to be a group and ! 'name' is the name of the dataset we should read from if (present(name)) then - call h5dopen_f(obj_id, trim(name), dset_id, hdf5_err) + name_ = to_c_string(name) + call read_double_c(obj_id, c_loc(name_), buffer, indep_) else - dset_id = obj_id + call read_double_c(obj_id, C_NULL_PTR, buffer, indep_) end if - - dims(:) = shape(buffer) - - if (present(indep)) then - call read_double_3D_explicit(dset_id, dims, buffer, indep) - else - call read_double_3D_explicit(dset_id, dims, buffer) - end if - - if (present(name)) call h5dclose_f(dset_id, hdf5_err) end subroutine read_double_3D - subroutine read_double_3D_explicit(dset_id, dims, buffer, indep) - integer(HID_T), intent(in) :: dset_id - integer(HSIZE_T), intent(in) :: dims(3) - real(8), target, intent(inout) :: buffer(dims(1),dims(2),dims(3)) - logical, optional, intent(in) :: indep ! independent I/O - - integer :: hdf5_err - integer :: data_xfer_mode -#ifdef PHDF5 - integer(HID_T) :: plist ! property list -#endif - type(c_ptr) :: f_ptr - - ! Set up collective vs. independent I/O - data_xfer_mode = H5FD_MPIO_COLLECTIVE_F - if (present(indep)) then - if (indep) data_xfer_mode = H5FD_MPIO_INDEPENDENT_F - end if - - f_ptr = c_loc(buffer) - - if (using_mpio_device(dset_id)) then -#ifdef PHDF5 - call h5pcreate_f(H5P_DATASET_XFER_F, plist, hdf5_err) - call h5pset_dxpl_mpio_f(plist, data_xfer_mode, hdf5_err) - call h5dread_f(dset_id, H5T_NATIVE_DOUBLE, f_ptr, hdf5_err, xfer_prp=plist) - call h5pclose_f(plist, hdf5_err) -#endif - else - call h5dread_f(dset_id, H5T_NATIVE_DOUBLE, f_ptr, hdf5_err) - end if - end subroutine read_double_3D_explicit - !=============================================================================== ! WRITE_DOUBLE_4D writes double precision 4-D array data !=============================================================================== @@ -760,62 +624,22 @@ contains character(*), optional, intent(in) :: name logical, optional, intent(in) :: indep ! independent I/O - integer :: hdf5_err - integer(HID_T) :: dset_id - integer(HSIZE_T) :: dims(4) + logical(C_BOOL) :: indep_ + character(kind=C_CHAR), target, allocatable :: name_(:) + + indep_ = .false. + if (present(indep)) indep_ = indep ! If 'name' argument is passed, obj_id is interpreted to be a group and ! 'name' is the name of the dataset we should read from if (present(name)) then - call h5dopen_f(obj_id, trim(name), dset_id, hdf5_err) + name_ = to_c_string(name) + call read_double_c(obj_id, c_loc(name_), buffer, indep_) else - dset_id = obj_id + call read_double_c(obj_id, C_NULL_PTR, buffer, indep_) end if - - dims(:) = shape(buffer) - - if (present(indep)) then - call read_double_4D_explicit(dset_id, dims, buffer, indep) - else - call read_double_4D_explicit(dset_id, dims, buffer) - end if - - if (present(name)) call h5dclose_f(dset_id, hdf5_err) end subroutine read_double_4D - subroutine read_double_4D_explicit(dset_id, dims, buffer, indep) - integer(HID_T), intent(in) :: dset_id - integer(HSIZE_T), intent(in) :: dims(4) - real(8), target, intent(inout) :: buffer(dims(1),dims(2),dims(3),dims(4)) - logical, optional, intent(in) :: indep ! independent I/O - - integer :: hdf5_err - integer :: data_xfer_mode -#ifdef PHDF5 - integer(HID_T) :: plist ! property list -#endif - type(c_ptr) :: f_ptr - - ! Set up collective vs. independent I/O - data_xfer_mode = H5FD_MPIO_COLLECTIVE_F - if (present(indep)) then - if (indep) data_xfer_mode = H5FD_MPIO_INDEPENDENT_F - end if - - f_ptr = c_loc(buffer) - - if (using_mpio_device(dset_id)) then -#ifdef PHDF5 - call h5pcreate_f(H5P_DATASET_XFER_F, plist, hdf5_err) - call h5pset_dxpl_mpio_f(plist, data_xfer_mode, hdf5_err) - call h5dread_f(dset_id, H5T_NATIVE_DOUBLE, f_ptr, hdf5_err, xfer_prp=plist) - call h5pclose_f(plist, hdf5_err) -#endif - else - call h5dread_f(dset_id, H5T_NATIVE_DOUBLE, f_ptr, hdf5_err) - end if - end subroutine read_double_4D_explicit - !=============================================================================== ! WRITE_INTEGER writes integer precision scalar data !=============================================================================== diff --git a/src/hdf5_interface.cpp b/src/hdf5_interface.cpp index a2ccef7f7d..6b9bd97987 100644 --- a/src/hdf5_interface.cpp +++ b/src/hdf5_interface.cpp @@ -11,7 +11,8 @@ namespace openmc { bool -using_mpio_device(hid_t obj_id) { +using_mpio_device(hid_t obj_id) +{ // Determine file that this object is part of hid_t file_id = H5Iget_file_id(obj_id); @@ -109,16 +110,19 @@ file_open(const char* filename, char mode, bool parallel) } hid_t -file_open(const std::string& filename, char mode, bool parallel=false) { +file_open(const std::string& filename, char mode, bool parallel=false) +{ file_open(filename.c_str(), mode, parallel); } -void file_close(hid_t file_id) { +void file_close(hid_t file_id) +{ H5Fclose(file_id); } bool -object_exists(hid_t object_id, const char* name) { +object_exists(hid_t object_id, const char* name) +{ htri_t out = H5LTpath_valid(object_id, name, true); if (out < 0) { std::stringstream err_msg; @@ -130,7 +134,8 @@ object_exists(hid_t object_id, const char* name) { hid_t -open_dataset(hid_t group_id, const char* name){ +open_dataset(hid_t group_id, const char* name) +{ if (object_exists(group_id, name)) { return H5Dopen(group_id, name, H5P_DEFAULT); } else { @@ -142,7 +147,8 @@ open_dataset(hid_t group_id, const char* name){ hid_t -open_group(hid_t group_id, const char* name){ +open_group(hid_t group_id, const char* name) +{ if (object_exists(group_id, name)) { return H5Gopen(group_id, name, H5P_DEFAULT); } else { @@ -153,10 +159,46 @@ open_group(hid_t group_id, const char* name){ } +void +read_double(hid_t obj_id, const char* name, double* buffer, bool indep) +{ + hid_t dset = obj_id; + if (name) dset = H5Dopen(obj_id, name, H5P_DEFAULT); + + if (using_mpio_device(dset)) { +#ifdef PHDF5 + // Set up collective vs independent I/O + auto data_xfer_mode {indep ? H5FD_MPIO_INDEPENDENT : H5FD_MPIO_COLLECTIVE}; + + // Create dataset transfer property list + hid_t plist = H5Pcreate(H5P_DATASET_XFER); + H5Pset_dxpl_mpio(plist, data_xfer_mode); + + // Write data + H5Dread(dset, H5T_NATIVE_DOUBLE, H5S_ALL, H5S_ALL, plist, buffer); + H5Pclose(plist); +#endif + } else { + H5Dread(dset, H5T_NATIVE_DOUBLE, H5S_ALL, H5S_ALL, H5P_DEFAULT, buffer); + } + + if (name) H5Dclose(dset); +} + + void write_double(hid_t group_id, int ndim, const hsize_t* dims, const char* name, - const double* buffer, bool indep) { - hid_t dspace = H5Screate_simple(ndim, dims, nullptr); + const double* buffer, bool indep) +{ + // If array is given, create a simple dataspace. Otherwise, create a scalar + // datascape. + hid_t dspace; + if (ndim > 0) { + dspace = H5Screate_simple(ndim, dims, nullptr); + } else { + dspace = H5Screate(H5S_SCALAR); + } + hid_t dset = H5Dcreate(group_id, name, H5T_NATIVE_DOUBLE, dspace, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT); diff --git a/src/hdf5_interface.h b/src/hdf5_interface.h index bbf5ce5e88..6902493afb 100644 --- a/src/hdf5_interface.h +++ b/src/hdf5_interface.h @@ -41,8 +41,11 @@ write_double_1D(hid_t group_id, char const *name, H5Dclose(dataset); } -extern "C" void write_double(hid_t group_id, int ndim, const hsize_t* dims, const char* name, - const double* buffer, bool indep); +extern "C" void read_double(hid_t obj_id, const char* name, double* buffer, + bool indep); + +extern "C" void write_double(hid_t group_id, int ndim, const hsize_t* dims, + const char* name, const double* buffer, bool indep); void write_string(hid_t group_id, char const *name, char const *buffer); void write_string(hid_t group_id, char const *name, const std::string &buffer); From 1648da04a34b39dd5bd688a1dc301a839e79a407 Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Tue, 17 Apr 2018 22:59:07 -0500 Subject: [PATCH 24/77] Move routines around --- src/hdf5_interface.F90 | 164 +++++++++++++++++------------------------ 1 file changed, 68 insertions(+), 96 deletions(-) diff --git a/src/hdf5_interface.F90 b/src/hdf5_interface.F90 index b9e6c414e6..ece930266e 100644 --- a/src/hdf5_interface.F90 +++ b/src/hdf5_interface.F90 @@ -28,7 +28,7 @@ module hdf5_interface integer(HID_T), public :: hdf5_integer8_t ! type for integer(8) interface write_dataset - module procedure write_double + module procedure write_double_0D module procedure write_double_1D module procedure write_double_2D module procedure write_double_3D @@ -387,27 +387,6 @@ contains end if end subroutine close_dataset -!=============================================================================== -! WRITE_DOUBLE writes double precision scalar data -!=============================================================================== - - subroutine write_double(group_id, name, buffer, indep) - integer(HID_T), intent(in) :: group_id - character(*), intent(in) :: name ! name for data - real(8), intent(in), target :: buffer ! data to write - logical, intent(in), optional :: indep ! independent I/O - - integer(HSIZE_T) :: dims(0) - logical(C_BOOL) :: indep_ - real(C_DOUBLE) :: value(1) - - indep_ = .false. - if (present(indep)) indep_ = indep - value(1) = buffer - - call write_double_c(group_id, 0, dims, to_c_string(name), value, indep_) - end subroutine write_double - !=============================================================================== ! READ_DOUBLE reads double precision scalar data !=============================================================================== @@ -457,9 +436,26 @@ contains end subroutine read_double !=============================================================================== -! WRITE_DOUBLE_1D writes double precision 1-D array data +! WRITE_DOUBLE_ND writes double precision N-D array data !=============================================================================== + subroutine write_double_0D(group_id, name, buffer, indep) + integer(HID_T), intent(in) :: group_id + character(*), intent(in) :: name ! name for data + real(8), intent(in), target :: buffer ! data to write + logical, intent(in), optional :: indep ! independent I/O + + integer(HSIZE_T) :: dims(0) + logical(C_BOOL) :: indep_ + real(C_DOUBLE) :: value(1) + + indep_ = .false. + if (present(indep)) indep_ = indep + value(1) = buffer + + call write_double_c(group_id, 0, dims, to_c_string(name), value, indep_) + end subroutine write_double_0D + subroutine write_double_1D(group_id, name, buffer, indep) integer(HID_T), intent(in) :: group_id character(*), intent(in) :: name ! name of data @@ -476,8 +472,56 @@ contains call write_double_c(group_id, 1, dims, to_c_string(name), buffer, indep_) end subroutine write_double_1D + subroutine write_double_2D(group_id, name, buffer, indep) + integer(HID_T), intent(in) :: group_id + character(*), intent(in) :: name ! name of data + real(8), intent(in), target :: buffer(:,:) ! data to write + logical, intent(in), optional :: indep ! independent I/O + + integer(HSIZE_T) :: dims(2) + logical(C_BOOL) :: indep_ + + dims(:) = shape(buffer) + indep_ = .false. + if (present(indep)) indep_ = indep + + call write_double_c(group_id, 2, dims, to_c_string(name), buffer, indep_) + end subroutine write_double_2D + + subroutine write_double_3D(group_id, name, buffer, indep) + integer(HID_T), intent(in) :: group_id + character(*), intent(in) :: name ! name of data + real(8), intent(in), target :: buffer(:,:,:) ! data to write + logical, intent(in), optional :: indep ! independent I/O + + integer(HSIZE_T) :: dims(3) + logical(C_BOOL) :: indep_ + + dims(:) = shape(buffer) + indep_ = .false. + if (present(indep)) indep_ = indep + + call write_double_c(group_id, 3, dims, to_c_string(name), buffer, indep_) + end subroutine write_double_3D + + subroutine write_double_4D(group_id, name, buffer, indep) + integer(HID_T), intent(in) :: group_id + character(*), intent(in) :: name ! name of data + real(8), intent(in), target :: buffer(:,:,:,:) ! data to write + logical, intent(in), optional :: indep ! independent I/O + + integer(HSIZE_T) :: dims(4) + logical(C_BOOL) :: indep_ + + dims(:) = shape(buffer) + indep_ = .false. + if (present(indep)) indep_ = indep + + call write_double_c(group_id, 1, dims, to_c_string(name), buffer, indep_) + end subroutine write_double_4D + !=============================================================================== -! READ_DOUBLE_1D reads double precision 1-D array data +! READ_DOUBLE_ND reads double precision N-D array data !=============================================================================== subroutine read_double_1D(buffer, obj_id, name, indep) @@ -502,30 +546,6 @@ contains end if end subroutine read_double_1D -!=============================================================================== -! WRITE_DOUBLE_2D writes double precision 2-D array data -!=============================================================================== - - subroutine write_double_2D(group_id, name, buffer, indep) - integer(HID_T), intent(in) :: group_id - character(*), intent(in) :: name ! name of data - real(8), intent(in), target :: buffer(:,:) ! data to write - logical, intent(in), optional :: indep ! independent I/O - - integer(HSIZE_T) :: dims(2) - logical(C_BOOL) :: indep_ - - dims(:) = shape(buffer) - indep_ = .false. - if (present(indep)) indep_ = indep - - call write_double_c(group_id, 2, dims, to_c_string(name), buffer, indep_) - end subroutine write_double_2D - -!=============================================================================== -! READ_DOUBLE_2D reads double precision 2-D array data -!=============================================================================== - subroutine read_double_2D(buffer, obj_id, name, indep) real(8), target, intent(inout) :: buffer(:,:) integer(HID_T), intent(in) :: obj_id @@ -548,30 +568,6 @@ contains end if end subroutine read_double_2D -!=============================================================================== -! WRITE_DOUBLE_3D writes double precision 3-D array data -!=============================================================================== - - subroutine write_double_3D(group_id, name, buffer, indep) - integer(HID_T), intent(in) :: group_id - character(*), intent(in) :: name ! name of data - real(8), intent(in), target :: buffer(:,:,:) ! data to write - logical, intent(in), optional :: indep ! independent I/O - - integer(HSIZE_T) :: dims(3) - logical(C_BOOL) :: indep_ - - dims(:) = shape(buffer) - indep_ = .false. - if (present(indep)) indep_ = indep - - call write_double_c(group_id, 3, dims, to_c_string(name), buffer, indep_) - end subroutine write_double_3D - -!=============================================================================== -! READ_DOUBLE_3D reads double precision 3-D array data -!=============================================================================== - subroutine read_double_3D(buffer, obj_id, name, indep) real(8), target, intent(inout) :: buffer(:,:,:) integer(HID_T), intent(in) :: obj_id @@ -594,30 +590,6 @@ contains end if end subroutine read_double_3D -!=============================================================================== -! WRITE_DOUBLE_4D writes double precision 4-D array data -!=============================================================================== - - subroutine write_double_4D(group_id, name, buffer, indep) - integer(HID_T), intent(in) :: group_id - character(*), intent(in) :: name ! name of data - real(8), intent(in), target :: buffer(:,:,:,:) ! data to write - logical, intent(in), optional :: indep ! independent I/O - - integer(HSIZE_T) :: dims(4) - logical(C_BOOL) :: indep_ - - dims(:) = shape(buffer) - indep_ = .false. - if (present(indep)) indep_ = indep - - call write_double_c(group_id, 1, dims, to_c_string(name), buffer, indep_) - end subroutine write_double_4D - -!=============================================================================== -! READ_DOUBLE_4D reads double precision 4-D array data -!=============================================================================== - subroutine read_double_4D(buffer, obj_id, name, indep) real(8), target, intent(inout) :: buffer(:,:,:,:) integer(HID_T), intent(in) :: obj_id From 46270774c543b81fc20ef24ff2dcab85948332db Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Wed, 18 Apr 2018 06:22:13 -0500 Subject: [PATCH 25/77] Convert HDF5 write_integer to C++ --- src/hdf5_interface.F90 | 352 +++++++++-------------------------------- src/hdf5_interface.cpp | 26 ++- src/hdf5_interface.h | 4 + 3 files changed, 102 insertions(+), 280 deletions(-) diff --git a/src/hdf5_interface.F90 b/src/hdf5_interface.F90 index ece930266e..562e35661e 100644 --- a/src/hdf5_interface.F90 +++ b/src/hdf5_interface.F90 @@ -33,7 +33,7 @@ module hdf5_interface module procedure write_double_2D module procedure write_double_3D module procedure write_double_4D - module procedure write_integer + module procedure write_integer_0D module procedure write_integer_1D module procedure write_integer_2D module procedure write_integer_3D @@ -124,6 +124,17 @@ module hdf5_interface real(C_DOUBLE), intent(in) :: buffer(*) logical(C_BOOL), intent(in) :: indep end subroutine write_double_c + + subroutine write_int_c(group_id, ndim, dims, name, buffer, indep) & + bind(C, name='write_int') + import HID_T, HSIZE_T, C_INT, C_CHAR, C_BOOL + integer(HID_T), value :: group_id + integer(C_INT), value :: ndim + integer(HSIZE_T), intent(in) :: dims(*) + character(kind=C_CHAR), intent(in) :: name(*) + integer(C_INT), intent(in) :: buffer(*) + logical(C_BOOL), intent(in) :: indep + end subroutine write_int_c end interface contains @@ -447,13 +458,13 @@ contains integer(HSIZE_T) :: dims(0) logical(C_BOOL) :: indep_ - real(C_DOUBLE) :: value(1) + real(C_DOUBLE) :: buffer_(1) indep_ = .false. if (present(indep)) indep_ = indep - value(1) = buffer + buffer_(1) = buffer - call write_double_c(group_id, 0, dims, to_c_string(name), value, indep_) + call write_double_c(group_id, 0, dims, to_c_string(name), buffer_, indep_) end subroutine write_double_0D subroutine write_double_1D(group_id, name, buffer, indep) @@ -612,52 +623,6 @@ contains end if end subroutine read_double_4D -!=============================================================================== -! WRITE_INTEGER writes integer precision scalar data -!=============================================================================== - - subroutine write_integer(group_id, name, buffer, indep) - integer(HID_T), intent(in) :: group_id - character(*), intent(in) :: name ! name for data - integer, intent(in), target :: buffer ! data to write - logical, intent(in), optional :: indep ! independent I/O - - integer :: hdf5_err - integer :: data_xfer_mode -#ifdef PHDF5 - integer(HID_T) :: plist ! property list -#endif - integer(HID_T) :: dset ! data set handle - integer(HID_T) :: dspace ! data or file space handle - type(c_ptr) :: f_ptr - - ! Set up collective vs. independent I/O - data_xfer_mode = H5FD_MPIO_COLLECTIVE_F - if (present(indep)) then - if (indep) data_xfer_mode = H5FD_MPIO_INDEPENDENT_F - end if - - ! Create dataspace and dataset - call h5screate_f(H5S_SCALAR_F, dspace, hdf5_err) - call h5dcreate_f(group_id, trim(name), H5T_NATIVE_INTEGER, & - dspace, dset, hdf5_err) - f_ptr = c_loc(buffer) - - if (using_mpio_device(group_id)) then -#ifdef PHDF5 - call h5pcreate_f(H5P_DATASET_XFER_F, plist, hdf5_err) - call h5pset_dxpl_mpio_f(plist, data_xfer_mode, hdf5_err) - call h5dwrite_f(dset, H5T_NATIVE_INTEGER, f_ptr, hdf5_err, xfer_prp=plist) - call h5pclose_f(plist, hdf5_err) -#endif - else - call h5dwrite_f(dset, H5T_NATIVE_INTEGER, f_ptr, hdf5_err) - end if - - call h5dclose_f(dset, hdf5_err) - call h5sclose_f(dspace, hdf5_err) - end subroutine write_integer - !=============================================================================== ! READ_INTEGER reads integer precision scalar data !=============================================================================== @@ -707,9 +672,26 @@ contains end subroutine read_integer !=============================================================================== -! WRITE_INTEGER_1D writes integer precision 1-D array data +! WRITE_INTEGER_ND writes integer precision N-D array data !=============================================================================== + subroutine write_integer_0D(group_id, name, buffer, indep) + integer(HID_T), intent(in) :: group_id + character(*), intent(in) :: name ! name for data + integer, intent(in), target :: buffer ! data to write + logical, intent(in), optional :: indep ! independent I/O + + integer(HSIZE_T) :: dims(0) + logical(C_BOOL) :: indep_ + integer(C_INT) :: buffer_(1) + + indep_ = .false. + if (present(indep)) indep_ = indep + buffer_(1) = buffer + + call write_int_c(group_id, 0, dims, to_c_string(name), buffer_, indep_) + end subroutine write_integer_0D + subroutine write_integer_1D(group_id, name, buffer, indep) integer(HID_T), intent(in) :: group_id character(*), intent(in) :: name ! name of data @@ -717,56 +699,62 @@ contains logical, intent(in), optional :: indep ! independent I/O integer(HSIZE_T) :: dims(1) + logical(C_BOOL) :: indep_ dims(:) = shape(buffer) - if (present(indep)) then - call write_integer_1D_explicit(group_id, dims, name, buffer, indep) - else - call write_integer_1D_explicit(group_id, dims, name, buffer) - end if + indep_ = .false. + if (present(indep)) indep_ = indep + + call write_int_c(group_id, 1, dims, to_c_string(name), buffer, indep_) end subroutine write_integer_1D - subroutine write_integer_1D_explicit(group_id, dims, name, buffer, indep) + subroutine write_integer_2D(group_id, name, buffer, indep) integer(HID_T), intent(in) :: group_id - integer(HSIZE_T), intent(in) :: dims(1) character(*), intent(in) :: name ! name of data - integer, intent(in), target :: buffer(dims(1)) ! data to write + integer, intent(in), target :: buffer(:,:) ! data to write logical, intent(in), optional :: indep ! independent I/O - integer :: hdf5_err - integer :: data_xfer_mode -#ifdef PHDF5 - integer(HID_T) :: plist ! property list -#endif - integer(HID_T) :: dset ! data set handle - integer(HID_T) :: dspace ! data or file space handle - type(c_ptr) :: f_ptr + integer(HSIZE_T) :: dims(2) + logical(C_BOOL) :: indep_ - ! Set up collective vs. independent I/O - data_xfer_mode = H5FD_MPIO_COLLECTIVE_F - if (present(indep)) then - if (indep) data_xfer_mode = H5FD_MPIO_INDEPENDENT_F - end if + dims(:) = shape(buffer) + indep_ = .false. + if (present(indep)) indep_ = indep - call h5screate_simple_f(1, dims, dspace, hdf5_err) - call h5dcreate_f(group_id, trim(name), H5T_NATIVE_INTEGER, & - dspace, dset, hdf5_err) - f_ptr = c_loc(buffer) + call write_int_c(group_id, 2, dims, to_c_string(name), buffer, indep_) + end subroutine write_integer_2D - if (using_mpio_device(group_id)) then -#ifdef PHDF5 - call h5pcreate_f(H5P_DATASET_XFER_F, plist, hdf5_err) - call h5pset_dxpl_mpio_f(plist, data_xfer_mode, hdf5_err) - call h5dwrite_f(dset, H5T_NATIVE_INTEGER, f_ptr, hdf5_err, xfer_prp=plist) - call h5pclose_f(plist, hdf5_err) -#endif - else - call h5dwrite_f(dset, H5T_NATIVE_INTEGER, f_ptr, hdf5_err) - end if + subroutine write_integer_3D(group_id, name, buffer, indep) + integer(HID_T), intent(in) :: group_id + character(*), intent(in) :: name ! name of data + integer, intent(in), target :: buffer(:,:,:) ! data to write + logical, intent(in), optional :: indep ! independent I/O - call h5dclose_f(dset, hdf5_err) - call h5sclose_f(dspace, hdf5_err) - end subroutine write_integer_1D_explicit + integer(HSIZE_T) :: dims(3) + logical(C_BOOL) :: indep_ + + dims(:) = shape(buffer) + indep_ = .false. + if (present(indep)) indep_ = indep + + call write_int_c(group_id, 3, dims, to_c_string(name), buffer, indep_) + end subroutine write_integer_3D + + subroutine write_integer_4D(group_id, name, buffer, indep) + integer(HID_T), intent(in) :: group_id + character(*), intent(in) :: name ! name of data + integer, intent(in), target :: buffer(:,:,:,:) ! data to write + logical, intent(in), optional :: indep ! independent I/O + + integer(HSIZE_T) :: dims(4) + logical(C_BOOL) :: indep_ + + dims(:) = shape(buffer) + indep_ = .false. + if (present(indep)) indep_ = indep + + call write_int_c(group_id, 3, dims, to_c_string(name), buffer, indep_) + end subroutine write_integer_4D !=============================================================================== ! READ_INTEGER_1D reads integer precision 1-D array data @@ -834,68 +822,6 @@ contains end if end subroutine read_integer_1D_explicit -!=============================================================================== -! WRITE_INTEGER_2D writes integer precision 2-D array data -!=============================================================================== - - subroutine write_integer_2D(group_id, name, buffer, indep) - integer(HID_T), intent(in) :: group_id - character(*), intent(in) :: name ! name of data - integer, intent(in), target :: buffer(:,:) ! data to write - logical, intent(in), optional :: indep ! independent I/O - - integer(HSIZE_T) :: dims(2) - - dims(:) = shape(buffer) - if (present(indep)) then - call write_integer_2D_explicit(group_id, dims, name, buffer, indep) - else - call write_integer_2D_explicit(group_id, dims, name, buffer) - end if - end subroutine write_integer_2D - - subroutine write_integer_2D_explicit(group_id, dims, name, buffer, indep) - integer(HID_T), intent(in) :: group_id - integer(HSIZE_T), intent(in) :: dims(2) - character(*), intent(in) :: name ! name of data - integer, intent(in), target :: buffer(dims(1),dims(2)) - logical, intent(in), optional :: indep ! independent I/O - - integer :: hdf5_err - integer :: data_xfer_mode -#ifdef PHDF5 - integer(HID_T) :: plist ! property list -#endif - integer(HID_T) :: dset ! data set handle - integer(HID_T) :: dspace ! data or file space handle - type(c_ptr) :: f_ptr - - ! Set up collective vs. independent I/O - data_xfer_mode = H5FD_MPIO_COLLECTIVE_F - if (present(indep)) then - if (indep) data_xfer_mode = H5FD_MPIO_INDEPENDENT_F - end if - - call h5screate_simple_f(2, dims, dspace, hdf5_err) - call h5dcreate_f(group_id, trim(name), H5T_NATIVE_INTEGER, & - dspace, dset, hdf5_err) - f_ptr = c_loc(buffer) - - if (using_mpio_device(group_id)) then -#ifdef PHDF5 - call h5pcreate_f(H5P_DATASET_XFER_F, plist, hdf5_err) - call h5pset_dxpl_mpio_f(plist, data_xfer_mode, hdf5_err) - call h5dwrite_f(dset, H5T_NATIVE_INTEGER, f_ptr, hdf5_err, xfer_prp=plist) - call h5pclose_f(plist, hdf5_err) -#endif - else - call h5dwrite_f(dset, H5T_NATIVE_INTEGER, f_ptr, hdf5_err) - end if - - call h5dclose_f(dset, hdf5_err) - call h5sclose_f(dspace, hdf5_err) - end subroutine write_integer_2D_explicit - !=============================================================================== ! READ_INTEGER_2D reads integer precision 2-D array data !=============================================================================== @@ -962,68 +888,6 @@ contains end if end subroutine read_integer_2D_explicit -!=============================================================================== -! WRITE_INTEGER_3D writes integer precision 3-D array data -!=============================================================================== - - subroutine write_integer_3D(group_id, name, buffer, indep) - integer(HID_T), intent(in) :: group_id - character(*), intent(in) :: name ! name of data - integer, intent(in), target :: buffer(:,:,:) ! data to write - logical, intent(in), optional :: indep ! independent I/O - - integer(HSIZE_T) :: dims(3) - - dims(:) = shape(buffer) - if (present(indep)) then - call write_integer_3D_explicit(group_id, dims, name, buffer, indep) - else - call write_integer_3D_explicit(group_id, dims, name, buffer) - end if - end subroutine write_integer_3D - - subroutine write_integer_3D_explicit(group_id, dims, name, buffer, indep) - integer(HID_T), intent(in) :: group_id - integer(HSIZE_T), intent(in) :: dims(3) - character(*), intent(in) :: name ! name of data - integer, intent(in), target :: buffer(dims(1),dims(2),dims(3)) - logical, intent(in), optional :: indep ! independent I/O - - integer :: hdf5_err - integer :: data_xfer_mode -#ifdef PHDF5 - integer(HID_T) :: plist ! property list -#endif - integer(HID_T) :: dset ! data set handle - integer(HID_T) :: dspace ! data or file space handle - type(c_ptr) :: f_ptr - - ! Set up collective vs. independent I/O - data_xfer_mode = H5FD_MPIO_COLLECTIVE_F - if (present(indep)) then - if (indep) data_xfer_mode = H5FD_MPIO_INDEPENDENT_F - end if - - call h5screate_simple_f(3, dims, dspace, hdf5_err) - call h5dcreate_f(group_id, trim(name), H5T_NATIVE_INTEGER, & - dspace, dset, hdf5_err) - f_ptr = c_loc(buffer) - - if (using_mpio_device(group_id)) then -#ifdef PHDF5 - call h5pcreate_f(H5P_DATASET_XFER_F, plist, hdf5_err) - call h5pset_dxpl_mpio_f(plist, data_xfer_mode, hdf5_err) - call h5dwrite_f(dset, H5T_NATIVE_INTEGER, f_ptr, hdf5_err, xfer_prp=plist) - call h5pclose_f(plist, hdf5_err) -#endif - else - call h5dwrite_f(dset, H5T_NATIVE_INTEGER, f_ptr, hdf5_err) - end if - - call h5dclose_f(dset, hdf5_err) - call h5sclose_f(dspace, hdf5_err) - end subroutine write_integer_3D_explicit - !=============================================================================== ! READ_INTEGER_3D reads integer precision 3-D array data !=============================================================================== @@ -1090,68 +954,6 @@ contains end if end subroutine read_integer_3D_explicit -!=============================================================================== -! WRITE_INTEGER_4D writes integer precision 4-D array data -!=============================================================================== - - subroutine write_integer_4D(group_id, name, buffer, indep) - integer(HID_T), intent(in) :: group_id - character(*), intent(in) :: name ! name of data - integer, intent(in), target :: buffer(:,:,:,:) ! data to write - logical, intent(in), optional :: indep ! independent I/O - - integer(HSIZE_T) :: dims(4) - - dims(:) = shape(buffer) - if (present(indep)) then - call write_integer_4D_explicit(group_id, dims, name, buffer, indep) - else - call write_integer_4D_explicit(group_id, dims, name, buffer) - end if - end subroutine write_integer_4D - - subroutine write_integer_4D_explicit(group_id, dims, name, buffer, indep) - integer(HID_T), intent(in) :: group_id - integer(HSIZE_T), intent(in) :: dims(4) - character(*), intent(in) :: name ! name of data - integer, intent(in), target :: buffer(dims(1),dims(2),dims(3),dims(4)) - logical, intent(in), optional :: indep ! independent I/O - - integer :: hdf5_err - integer :: data_xfer_mode -#ifdef PHDF5 - integer(HID_T) :: plist ! property list -#endif - integer(HID_T) :: dset ! data set handle - integer(HID_T) :: dspace ! data or file space handle - type(c_ptr) :: f_ptr - - ! Set up collective vs. independent I/O - data_xfer_mode = H5FD_MPIO_COLLECTIVE_F - if (present(indep)) then - if (indep) data_xfer_mode = H5FD_MPIO_INDEPENDENT_F - end if - - call h5screate_simple_f(4, dims, dspace, hdf5_err) - call h5dcreate_f(group_id, trim(name), H5T_NATIVE_INTEGER, & - dspace, dset, hdf5_err) - f_ptr = c_loc(buffer) - - if (using_mpio_device(group_id)) then -#ifdef PHDF5 - call h5pcreate_f(H5P_DATASET_XFER_F, plist, hdf5_err) - call h5pset_dxpl_mpio_f(plist, data_xfer_mode, hdf5_err) - call h5dwrite_f(dset, H5T_NATIVE_INTEGER, f_ptr, hdf5_err, xfer_prp=plist) - call h5pclose_f(plist, hdf5_err) -#endif - else - call h5dwrite_f(dset, H5T_NATIVE_INTEGER, f_ptr, hdf5_err) - end if - - call h5dclose_f(dset, hdf5_err) - call h5sclose_f(dspace, hdf5_err) - end subroutine write_integer_4D_explicit - !=============================================================================== ! READ_INTEGER_4D reads integer precision 4-D array data !=============================================================================== diff --git a/src/hdf5_interface.cpp b/src/hdf5_interface.cpp index 6b9bd97987..349c1876de 100644 --- a/src/hdf5_interface.cpp +++ b/src/hdf5_interface.cpp @@ -187,8 +187,8 @@ read_double(hid_t obj_id, const char* name, double* buffer, bool indep) void -write_double(hid_t group_id, int ndim, const hsize_t* dims, const char* name, - const double* buffer, bool indep) +write_array(hid_t group_id, int ndim, const hsize_t* dims, const char* name, + hid_t mem_type_id, const void* buffer, bool indep) { // If array is given, create a simple dataspace. Otherwise, create a scalar // datascape. @@ -199,7 +199,7 @@ write_double(hid_t group_id, int ndim, const hsize_t* dims, const char* name, dspace = H5Screate(H5S_SCALAR); } - hid_t dset = H5Dcreate(group_id, name, H5T_NATIVE_DOUBLE, dspace, + hid_t dset = H5Dcreate(group_id, name, mem_type_id, dspace, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT); if (using_mpio_device(group_id)) { @@ -212,11 +212,11 @@ write_double(hid_t group_id, int ndim, const hsize_t* dims, const char* name, H5Pset_dxpl_mpio(plist, data_xfer_mode); // Write data - H5Dwrite(dset, H5T_NATIVE_DOUBLE, H5S_ALL, H5S_ALL, plist, buffer); + H5Dwrite(dset, mem_type_id, H5S_ALL, H5S_ALL, plist, buffer); H5Pclose(plist); #endif } else { - H5Dwrite(dset, H5T_NATIVE_DOUBLE, H5S_ALL, H5S_ALL, H5P_DEFAULT, buffer); + H5Dwrite(dset, mem_type_id, H5S_ALL, H5S_ALL, H5P_DEFAULT, buffer); } // Free resources @@ -225,6 +225,22 @@ write_double(hid_t group_id, int ndim, const hsize_t* dims, const char* name, } +void +write_double(hid_t group_id, int ndim, const hsize_t* dims, const char* name, + const double* buffer, bool indep) +{ + write_array(group_id, ndim, dims, name, H5T_NATIVE_DOUBLE, buffer, indep); +} + + +void +write_int(hid_t group_id, int ndim, const hsize_t* dims, const char* name, + const int* buffer, bool indep) +{ + write_array(group_id, ndim, dims, name, H5T_NATIVE_INT, buffer, indep); +} + + void write_string(hid_t group_id, char const *name, char const *buffer) { diff --git a/src/hdf5_interface.h b/src/hdf5_interface.h index 6902493afb..f2bef3b0b7 100644 --- a/src/hdf5_interface.h +++ b/src/hdf5_interface.h @@ -44,8 +44,12 @@ write_double_1D(hid_t group_id, char const *name, extern "C" void read_double(hid_t obj_id, const char* name, double* buffer, bool indep); +void write_array(hid_t group_id, int ndim, const hsize_t* dims, const char* name, + hid_t mem_type_id, const void* buffer, bool indep); extern "C" void write_double(hid_t group_id, int ndim, const hsize_t* dims, const char* name, const double* buffer, bool indep); +extern "C" void write_int(hid_t group_id, int ndim, const hsize_t* dims, + const char* name, const int* buffer, bool indep); void write_string(hid_t group_id, char const *name, char const *buffer); void write_string(hid_t group_id, char const *name, const std::string &buffer); From 8338c0022e992782d367ca0647e91b3ce0516a13 Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Wed, 18 Apr 2018 06:56:41 -0500 Subject: [PATCH 26/77] Convert HDF5 read_integer to C++ --- src/hdf5_interface.F90 | 386 ++++++++++------------------------------- src/hdf5_interface.cpp | 21 ++- src/hdf5_interface.h | 4 + 3 files changed, 114 insertions(+), 297 deletions(-) diff --git a/src/hdf5_interface.F90 b/src/hdf5_interface.F90 index 562e35661e..f1de90d726 100644 --- a/src/hdf5_interface.F90 +++ b/src/hdf5_interface.F90 @@ -44,12 +44,12 @@ module hdf5_interface end interface write_dataset interface read_dataset - module procedure read_double + module procedure read_double_0D module procedure read_double_1D module procedure read_double_2D module procedure read_double_3D module procedure read_double_4D - module procedure read_integer + module procedure read_integer_0D module procedure read_integer_1D module procedure read_integer_2D module procedure read_integer_3D @@ -114,6 +114,15 @@ module hdf5_interface logical(C_BOOL), intent(in) :: indep end subroutine read_double_c + subroutine read_int_c(obj_id, name, buffer, indep) & + bind(C, name='read_int') + import HID_T, C_INT, C_BOOL, C_PTR + integer(HID_T), value :: obj_id + type(C_PTR), value :: name + integer(C_INT), intent(in) :: buffer(*) + logical(C_BOOL), intent(in) :: indep + end subroutine read_int_c + subroutine write_double_c(group_id, ndim, dims, name, buffer, indep) & bind(C, name='write_double') import HID_T, HSIZE_T, C_INT, C_DOUBLE, C_CHAR, C_BOOL @@ -402,49 +411,6 @@ contains ! READ_DOUBLE reads double precision scalar data !=============================================================================== - subroutine read_double(buffer, obj_id, name, indep) - real(8), target, intent(inout) :: buffer - integer(HID_T), intent(in) :: obj_id - character(*), optional, intent(in) :: name - logical, optional, intent(in) :: indep ! independent I/O - - integer :: hdf5_err - integer :: data_xfer_mode -#ifdef PHDF5 - integer(HID_T) :: plist ! property list -#endif - integer(HID_T) :: dset_id - type(c_ptr) :: f_ptr - - ! If 'name' argument is passed, obj_id is interpreted to be a group and - ! 'name' is the name of the dataset we should read from - if (present(name)) then - call h5dopen_f(obj_id, trim(name), dset_id, hdf5_err) - else - dset_id = obj_id - end if - - ! Set up collective vs. independent I/O - data_xfer_mode = H5FD_MPIO_COLLECTIVE_F - if (present(indep)) then - if (indep) data_xfer_mode = H5FD_MPIO_INDEPENDENT_F - end if - - f_ptr = c_loc(buffer) - - if (using_mpio_device(dset_id)) then -#ifdef PHDF5 - call h5pcreate_f(H5P_DATASET_XFER_F, plist, hdf5_err) - call h5pset_dxpl_mpio_f(plist, data_xfer_mode, hdf5_err) - call h5dread_f(dset_id, H5T_NATIVE_DOUBLE, f_ptr, hdf5_err, xfer_prp=plist) - call h5pclose_f(plist, hdf5_err) -#endif - else - call h5dread_f(dset_id, H5T_NATIVE_DOUBLE, f_ptr, hdf5_err) - end if - - if (present(name)) call h5dclose_f(dset_id, hdf5_err) - end subroutine read_double !=============================================================================== ! WRITE_DOUBLE_ND writes double precision N-D array data @@ -535,6 +501,30 @@ contains ! READ_DOUBLE_ND reads double precision N-D array data !=============================================================================== + subroutine read_double_0D(buffer, obj_id, name, indep) + real(8), target, intent(inout) :: buffer + integer(HID_T), intent(in) :: obj_id + character(*), optional, intent(in) :: name + logical, optional, intent(in) :: indep ! independent I/O + + real(C_DOUBLE) :: buffer_(1) + logical(C_BOOL) :: indep_ + character(kind=C_CHAR), target, allocatable :: name_(:) + + indep_ = .false. + if (present(indep)) indep_ = indep + + ! If 'name' argument is passed, obj_id is interpreted to be a group and + ! 'name' is the name of the dataset we should read from + if (present(name)) then + name_ = to_c_string(name) + call read_double_c(obj_id, c_loc(name_), buffer_, indep_) + else + call read_double_c(obj_id, C_NULL_PTR, buffer_, indep_) + end if + buffer = buffer_(1) + end subroutine read_double_0D + subroutine read_double_1D(buffer, obj_id, name, indep) real(8), target, intent(inout) :: buffer(:) integer(HID_T), intent(in) :: obj_id @@ -627,50 +617,6 @@ contains ! READ_INTEGER reads integer precision scalar data !=============================================================================== - subroutine read_integer(buffer, obj_id, name, indep) - integer, target, intent(inout) :: buffer - integer(HID_T), intent(in) :: obj_id - character(*), optional, intent(in) :: name - logical, optional, intent(in) :: indep ! independent I/O - - integer :: hdf5_err - integer :: data_xfer_mode -#ifdef PHDF5 - integer(HID_T) :: plist ! property list -#endif - integer(HID_T) :: dset_id - type(c_ptr) :: f_ptr - - ! If 'name' argument is passed, obj_id is interpreted to be a group and - ! 'name' is the name of the dataset we should read from - if (present(name)) then - call h5dopen_f(obj_id, trim(name), dset_id, hdf5_err) - else - dset_id = obj_id - end if - - ! Set up collective vs. independent I/O - data_xfer_mode = H5FD_MPIO_COLLECTIVE_F - if (present(indep)) then - if (indep) data_xfer_mode = H5FD_MPIO_INDEPENDENT_F - end if - - f_ptr = c_loc(buffer) - - if (using_mpio_device(dset_id)) then -#ifdef PHDF5 - call h5pcreate_f(H5P_DATASET_XFER_F, plist, hdf5_err) - call h5pset_dxpl_mpio_f(plist, data_xfer_mode, hdf5_err) - call h5dread_f(dset_id, H5T_NATIVE_INTEGER, f_ptr, hdf5_err, xfer_prp=plist) - call h5pclose_f(plist, hdf5_err) -#endif - else - call h5dread_f(dset_id, H5T_NATIVE_INTEGER, f_ptr, hdf5_err) - end if - - if (present(name)) call h5dclose_f(dset_id, hdf5_err) - end subroutine read_integer - !=============================================================================== ! WRITE_INTEGER_ND writes integer precision N-D array data !=============================================================================== @@ -757,269 +703,121 @@ contains end subroutine write_integer_4D !=============================================================================== -! READ_INTEGER_1D reads integer precision 1-D array data +! READ_INTEGER_ND reads integer precision N-D array data !=============================================================================== + subroutine read_integer_0D(buffer, obj_id, name, indep) + integer, target, intent(inout) :: buffer + integer(HID_T), intent(in) :: obj_id + character(*), optional, intent(in) :: name + logical, optional, intent(in) :: indep ! independent I/O + + integer(C_INT) :: buffer_(1) + logical(C_BOOL) :: indep_ + character(kind=C_CHAR), target, allocatable :: name_(:) + + indep_ = .false. + if (present(indep)) indep_ = indep + + ! If 'name' argument is passed, obj_id is interpreted to be a group and + ! 'name' is the name of the dataset we should read from + if (present(name)) then + name_ = to_c_string(name) + call read_int_c(obj_id, c_loc(name_), buffer_, indep_) + else + call read_int_c(obj_id, C_NULL_PTR, buffer_, indep_) + end if + buffer = buffer_(1) + end subroutine read_integer_0D + subroutine read_integer_1D(buffer, obj_id, name, indep) integer, target, intent(inout) :: buffer(:) integer(HID_T), intent(in) :: obj_id character(*), optional, intent(in) :: name logical, optional, intent(in) :: indep ! independent I/O - integer :: hdf5_err - integer(HID_T) :: dset_id - integer(HSIZE_T) :: dims(1) + logical(C_BOOL) :: indep_ + character(kind=C_CHAR), target, allocatable :: name_(:) + + indep_ = .false. + if (present(indep)) indep_ = indep ! If 'name' argument is passed, obj_id is interpreted to be a group and ! 'name' is the name of the dataset we should read from if (present(name)) then - call h5dopen_f(obj_id, trim(name), dset_id, hdf5_err) + name_ = to_c_string(name) + call read_int_c(obj_id, c_loc(name_), buffer, indep_) else - dset_id = obj_id + call read_int_c(obj_id, C_NULL_PTR, buffer, indep_) end if - - dims(:) = shape(buffer) - - if (present(indep)) then - call read_integer_1D_explicit(dset_id, dims, buffer, indep) - else - call read_integer_1D_explicit(dset_id, dims, buffer) - end if - - if (present(name)) call h5dclose_f(dset_id, hdf5_err) end subroutine read_integer_1D - subroutine read_integer_1D_explicit(dset_id, dims, buffer, indep) - integer(HID_T), intent(in) :: dset_id - integer(HSIZE_T), intent(in) :: dims(1) - integer, target, intent(inout) :: buffer(dims(1)) - logical, optional, intent(in) :: indep ! independent I/O - - integer :: hdf5_err - integer :: data_xfer_mode -#ifdef PHDF5 - integer(HID_T) :: plist ! property list -#endif - type(c_ptr) :: f_ptr - - ! Set up collective vs. independent I/O - data_xfer_mode = H5FD_MPIO_COLLECTIVE_F - if (present(indep)) then - if (indep) data_xfer_mode = H5FD_MPIO_INDEPENDENT_F - end if - - f_ptr = c_loc(buffer) - - if (using_mpio_device(dset_id)) then -#ifdef PHDF5 - call h5pcreate_f(H5P_DATASET_XFER_F, plist, hdf5_err) - call h5pset_dxpl_mpio_f(plist, data_xfer_mode, hdf5_err) - call h5dread_f(dset_id, H5T_NATIVE_INTEGER, f_ptr, hdf5_err, xfer_prp=plist) - call h5pclose_f(plist, hdf5_err) -#endif - else - call h5dread_f(dset_id, H5T_NATIVE_INTEGER, f_ptr, hdf5_err) - end if - end subroutine read_integer_1D_explicit - -!=============================================================================== -! READ_INTEGER_2D reads integer precision 2-D array data -!=============================================================================== - subroutine read_integer_2D(buffer, obj_id, name, indep) integer, target, intent(inout) :: buffer(:,:) integer(HID_T), intent(in) :: obj_id character(*), optional, intent(in) :: name logical, optional, intent(in) :: indep ! independent I/O - integer :: hdf5_err - integer(HID_T) :: dset_id - integer(HSIZE_T) :: dims(2) + logical(C_BOOL) :: indep_ + character(kind=C_CHAR), target, allocatable :: name_(:) + + indep_ = .false. + if (present(indep)) indep_ = indep ! If 'name' argument is passed, obj_id is interpreted to be a group and ! 'name' is the name of the dataset we should read from if (present(name)) then - call h5dopen_f(obj_id, trim(name), dset_id, hdf5_err) + name_ = to_c_string(name) + call read_int_c(obj_id, c_loc(name_), buffer, indep_) else - dset_id = obj_id + call read_int_c(obj_id, C_NULL_PTR, buffer, indep_) end if - - dims(:) = shape(buffer) - - if (present(indep)) then - call read_integer_2D_explicit(dset_id, dims, buffer, indep) - else - call read_integer_2D_explicit(dset_id, dims, buffer) - end if - - if (present(name)) call h5dclose_f(dset_id, hdf5_err) end subroutine read_integer_2D - subroutine read_integer_2D_explicit(dset_id, dims, buffer, indep) - integer(HID_T), intent(in) :: dset_id - integer(HSIZE_T), intent(in) :: dims(2) - integer, target, intent(inout) :: buffer(dims(1),dims(2)) - logical, optional, intent(in) :: indep ! independent I/O - - integer :: hdf5_err - integer :: data_xfer_mode -#ifdef PHDF5 - integer(HID_T) :: plist ! property list -#endif - type(c_ptr) :: f_ptr - - ! Set up collective vs. independent I/O - data_xfer_mode = H5FD_MPIO_COLLECTIVE_F - if (present(indep)) then - if (indep) data_xfer_mode = H5FD_MPIO_INDEPENDENT_F - end if - - f_ptr = c_loc(buffer) - - if (using_mpio_device(dset_id)) then -#ifdef PHDF5 - call h5pcreate_f(H5P_DATASET_XFER_F, plist, hdf5_err) - call h5pset_dxpl_mpio_f(plist, data_xfer_mode, hdf5_err) - call h5dread_f(dset_id, H5T_NATIVE_INTEGER, f_ptr, hdf5_err, xfer_prp=plist) - call h5pclose_f(plist, hdf5_err) -#endif - else - call h5dread_f(dset_id, H5T_NATIVE_INTEGER, f_ptr, hdf5_err) - end if - end subroutine read_integer_2D_explicit - -!=============================================================================== -! READ_INTEGER_3D reads integer precision 3-D array data -!=============================================================================== - subroutine read_integer_3D(buffer, obj_id, name, indep) integer, target, intent(inout) :: buffer(:,:,:) integer(HID_T), intent(in) :: obj_id character(*), optional, intent(in) :: name logical, optional, intent(in) :: indep ! independent I/O - integer :: hdf5_err - integer(HID_T) :: dset_id - integer(HSIZE_T) :: dims(3) + logical(C_BOOL) :: indep_ + character(kind=C_CHAR), target, allocatable :: name_(:) + + indep_ = .false. + if (present(indep)) indep_ = indep ! If 'name' argument is passed, obj_id is interpreted to be a group and ! 'name' is the name of the dataset we should read from if (present(name)) then - call h5dopen_f(obj_id, trim(name), dset_id, hdf5_err) + name_ = to_c_string(name) + call read_int_c(obj_id, c_loc(name_), buffer, indep_) else - dset_id = obj_id + call read_int_c(obj_id, C_NULL_PTR, buffer, indep_) end if - - dims(:) = shape(buffer) - - if (present(indep)) then - call read_integer_3D_explicit(dset_id, dims, buffer, indep) - else - call read_integer_3D_explicit(dset_id, dims, buffer) - end if - - if (present(name)) call h5dclose_f(dset_id, hdf5_err) end subroutine read_integer_3D - subroutine read_integer_3D_explicit(dset_id, dims, buffer, indep) - integer(HID_T), intent(in) :: dset_id - integer(HSIZE_T), intent(in) :: dims(3) - integer, target, intent(inout) :: buffer(dims(1),dims(2),dims(3)) - logical, optional, intent(in) :: indep ! independent I/O - - integer :: hdf5_err - integer :: data_xfer_mode -#ifdef PHDF5 - integer(HID_T) :: plist ! property list -#endif - type(c_ptr) :: f_ptr - - ! Set up collective vs. independent I/O - data_xfer_mode = H5FD_MPIO_COLLECTIVE_F - if (present(indep)) then - if (indep) data_xfer_mode = H5FD_MPIO_INDEPENDENT_F - end if - - f_ptr = c_loc(buffer) - - if (using_mpio_device(dset_id)) then -#ifdef PHDF5 - call h5pcreate_f(H5P_DATASET_XFER_F, plist, hdf5_err) - call h5pset_dxpl_mpio_f(plist, data_xfer_mode, hdf5_err) - call h5dread_f(dset_id, H5T_NATIVE_INTEGER, f_ptr, hdf5_err, xfer_prp=plist) - call h5pclose_f(plist, hdf5_err) -#endif - else - call h5dread_f(dset_id, H5T_NATIVE_INTEGER, f_ptr, hdf5_err) - end if - end subroutine read_integer_3D_explicit - -!=============================================================================== -! READ_INTEGER_4D reads integer precision 4-D array data -!=============================================================================== - subroutine read_integer_4D(buffer, obj_id, name, indep) integer, target, intent(inout) :: buffer(:,:,:,:) integer(HID_T), intent(in) :: obj_id character(*), optional, intent(in) :: name logical, optional, intent(in) :: indep ! independent I/O - integer :: hdf5_err - integer(HID_T) :: dset_id - integer(HSIZE_T) :: dims(4) + logical(C_BOOL) :: indep_ + character(kind=C_CHAR), target, allocatable :: name_(:) + + indep_ = .false. + if (present(indep)) indep_ = indep ! If 'name' argument is passed, obj_id is interpreted to be a group and ! 'name' is the name of the dataset we should read from if (present(name)) then - call h5dopen_f(obj_id, trim(name), dset_id, hdf5_err) + name_ = to_c_string(name) + call read_int_c(obj_id, c_loc(name_), buffer, indep_) else - dset_id = obj_id + call read_int_c(obj_id, C_NULL_PTR, buffer, indep_) end if - - dims(:) = shape(buffer) - - if (present(indep)) then - call read_integer_4D_explicit(dset_id, dims, buffer, indep) - else - call read_integer_4D_explicit(dset_id, dims, buffer) - end if - - if (present(name)) call h5dclose_f(dset_id, hdf5_err) end subroutine read_integer_4D - subroutine read_integer_4D_explicit(dset_id, dims, buffer, indep) - integer(HID_T), intent(in) :: dset_id - integer(HSIZE_T), intent(in) :: dims(4) - integer, target, intent(inout) :: buffer(dims(1),dims(2),dims(3),dims(4)) - logical, optional, intent(in) :: indep ! independent I/O - - integer :: hdf5_err - integer :: data_xfer_mode -#ifdef PHDF5 - integer(HID_T) :: plist ! property list -#endif - type(c_ptr) :: f_ptr - - ! Set up collective vs. independent I/O - data_xfer_mode = H5FD_MPIO_COLLECTIVE_F - if (present(indep)) then - if (indep) data_xfer_mode = H5FD_MPIO_INDEPENDENT_F - end if - - f_ptr = c_loc(buffer) - - if (using_mpio_device(dset_id)) then -#ifdef PHDF5 - call h5pcreate_f(H5P_DATASET_XFER_F, plist, hdf5_err) - call h5pset_dxpl_mpio_f(plist, data_xfer_mode, hdf5_err) - call h5dread_f(dset_id, H5T_NATIVE_INTEGER, f_ptr, hdf5_err, xfer_prp=plist) - call h5pclose_f(plist, hdf5_err) -#endif - else - call h5dread_f(dset_id, H5T_NATIVE_INTEGER, f_ptr, hdf5_err) - end if - end subroutine read_integer_4D_explicit - !=============================================================================== ! WRITE_LONG writes long integer scalar data !=============================================================================== diff --git a/src/hdf5_interface.cpp b/src/hdf5_interface.cpp index 349c1876de..76b3d6feae 100644 --- a/src/hdf5_interface.cpp +++ b/src/hdf5_interface.cpp @@ -160,7 +160,8 @@ open_group(hid_t group_id, const char* name) void -read_double(hid_t obj_id, const char* name, double* buffer, bool indep) +read_array(hid_t obj_id, const char* name, hid_t mem_type_id, + void* buffer, bool indep) { hid_t dset = obj_id; if (name) dset = H5Dopen(obj_id, name, H5P_DEFAULT); @@ -175,17 +176,31 @@ read_double(hid_t obj_id, const char* name, double* buffer, bool indep) H5Pset_dxpl_mpio(plist, data_xfer_mode); // Write data - H5Dread(dset, H5T_NATIVE_DOUBLE, H5S_ALL, H5S_ALL, plist, buffer); + H5Dread(dset, mem_type_id, H5S_ALL, H5S_ALL, plist, buffer); H5Pclose(plist); #endif } else { - H5Dread(dset, H5T_NATIVE_DOUBLE, H5S_ALL, H5S_ALL, H5P_DEFAULT, buffer); + H5Dread(dset, mem_type_id, H5S_ALL, H5S_ALL, H5P_DEFAULT, buffer); } if (name) H5Dclose(dset); } +void +read_double(hid_t obj_id, const char* name, double* buffer, bool indep) +{ + read_array(obj_id, name, H5T_NATIVE_DOUBLE, buffer, indep); +} + + +void +read_int(hid_t obj_id, const char* name, int* buffer, bool indep) +{ + read_array(obj_id, name, H5T_NATIVE_INT, buffer, indep); +} + + void write_array(hid_t group_id, int ndim, const hsize_t* dims, const char* name, hid_t mem_type_id, const void* buffer, bool indep) diff --git a/src/hdf5_interface.h b/src/hdf5_interface.h index f2bef3b0b7..b3efda48c2 100644 --- a/src/hdf5_interface.h +++ b/src/hdf5_interface.h @@ -41,8 +41,12 @@ write_double_1D(hid_t group_id, char const *name, H5Dclose(dataset); } +void read_array(hid_t obj_id, const char* name, double* buffer, + hid_t mem_type_id, bool indep); extern "C" void read_double(hid_t obj_id, const char* name, double* buffer, bool indep); +extern "C" void read_int(hid_t obj_id, const char* name, int* buffer, + bool indep); void write_array(hid_t group_id, int ndim, const hsize_t* dims, const char* name, hid_t mem_type_id, const void* buffer, bool indep); From aa5a5cf7db0d33e1801e71f02b9fcd0060ede4af Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Wed, 18 Apr 2018 07:14:44 -0500 Subject: [PATCH 27/77] Convert HDF5 read/write_long to C++ --- src/hdf5_interface.F90 | 108 ++++++++++++++--------------------------- src/hdf5_interface.cpp | 15 ++++++ src/hdf5_interface.h | 4 ++ 3 files changed, 56 insertions(+), 71 deletions(-) diff --git a/src/hdf5_interface.F90 b/src/hdf5_interface.F90 index f1de90d726..7514c5ba03 100644 --- a/src/hdf5_interface.F90 +++ b/src/hdf5_interface.F90 @@ -123,6 +123,15 @@ module hdf5_interface logical(C_BOOL), intent(in) :: indep end subroutine read_int_c + subroutine read_llong_c(obj_id, name, buffer, indep) & + bind(C, name='read_llong') + import HID_T, C_INT, C_BOOL, C_PTR, C_LONG_LONG + integer(HID_T), value :: obj_id + type(C_PTR), value :: name + integer(C_LONG_LONG), intent(in) :: buffer(*) + logical(C_BOOL), intent(in) :: indep + end subroutine read_llong_c + subroutine write_double_c(group_id, ndim, dims, name, buffer, indep) & bind(C, name='write_double') import HID_T, HSIZE_T, C_INT, C_DOUBLE, C_CHAR, C_BOOL @@ -144,6 +153,17 @@ module hdf5_interface integer(C_INT), intent(in) :: buffer(*) logical(C_BOOL), intent(in) :: indep end subroutine write_int_c + + subroutine write_llong_c(group_id, ndim, dims, name, buffer, indep) & + bind(C, name='write_llong') + import HID_T, HSIZE_T, C_INT, C_CHAR, C_BOOL, C_LONG_LONG + integer(HID_T), value :: group_id + integer(C_INT), value :: ndim + integer(HSIZE_T), intent(in) :: dims(*) + character(kind=C_CHAR), intent(in) :: name(*) + integer(C_LONG_LONG), intent(in) :: buffer(*) + logical(C_BOOL), intent(in) :: indep + end subroutine write_llong_c end interface contains @@ -407,11 +427,6 @@ contains end if end subroutine close_dataset -!=============================================================================== -! READ_DOUBLE reads double precision scalar data -!=============================================================================== - - !=============================================================================== ! WRITE_DOUBLE_ND writes double precision N-D array data !=============================================================================== @@ -613,10 +628,6 @@ contains end if end subroutine read_double_4D -!=============================================================================== -! READ_INTEGER reads integer precision scalar data -!=============================================================================== - !=============================================================================== ! WRITE_INTEGER_ND writes integer precision N-D array data !=============================================================================== @@ -828,40 +839,15 @@ contains integer(8), intent(in), target :: buffer ! data to write logical, intent(in), optional :: indep ! independent I/O - integer :: hdf5_err - integer :: data_xfer_mode -#ifdef PHDF5 - integer(HID_T) :: plist ! property list -#endif - integer(HID_T) :: dset ! data set handle - integer(HID_T) :: dspace ! data or file space handle - type(c_ptr) :: f_ptr + integer(HSIZE_T) :: dims(0) + logical(C_BOOL) :: indep_ + integer(C_LONG_LONG) :: buffer_(1) - ! Set up collective vs. independent I/O - data_xfer_mode = H5FD_MPIO_COLLECTIVE_F - if (present(indep)) then - if (indep) data_xfer_mode = H5FD_MPIO_INDEPENDENT_F - end if + indep_ = .false. + if (present(indep)) indep_ = indep + buffer_(1) = buffer - ! Create dataspace and dataset - call h5screate_f(H5S_SCALAR_F, dspace, hdf5_err) - call h5dcreate_f(group_id, trim(name), hdf5_integer8_t, & - dspace, dset, hdf5_err) - f_ptr = c_loc(buffer) - - if (using_mpio_device(group_id)) then -#ifdef PHDF5 - call h5pcreate_f(H5P_DATASET_XFER_F, plist, hdf5_err) - call h5pset_dxpl_mpio_f(plist, data_xfer_mode, hdf5_err) - call h5dwrite_f(dset, hdf5_integer8_t, f_ptr, hdf5_err, xfer_prp=plist) - call h5pclose_f(plist, hdf5_err) -#endif - else - call h5dwrite_f(dset, hdf5_integer8_t, f_ptr, hdf5_err) - end if - - call h5dclose_f(dset, hdf5_err) - call h5sclose_f(dspace, hdf5_err) + call write_llong_c(group_id, 0, dims, to_c_string(name), buffer_, indep_) end subroutine write_long !=============================================================================== @@ -874,42 +860,22 @@ contains character(*), optional, intent(in) :: name logical, optional, intent(in) :: indep ! independent I/O - integer :: hdf5_err - integer :: data_xfer_mode -#ifdef PHDF5 - integer(HID_T) :: plist ! property list -#endif - integer(HID_T) :: dset_id - type(c_ptr) :: f_ptr + integer(C_LONG_LONG) :: buffer_(1) + logical(C_BOOL) :: indep_ + character(kind=C_CHAR), target, allocatable :: name_(:) + + indep_ = .false. + if (present(indep)) indep_ = indep ! If 'name' argument is passed, obj_id is interpreted to be a group and ! 'name' is the name of the dataset we should read from if (present(name)) then - call h5dopen_f(obj_id, trim(name), dset_id, hdf5_err) + name_ = to_c_string(name) + call read_llong_c(obj_id, c_loc(name_), buffer_, indep_) else - dset_id = obj_id + call read_llong_c(obj_id, C_NULL_PTR, buffer_, indep_) end if - - ! Set up collective vs. independent I/O - data_xfer_mode = H5FD_MPIO_COLLECTIVE_F - if (present(indep)) then - if (indep) data_xfer_mode = H5FD_MPIO_INDEPENDENT_F - end if - - f_ptr = c_loc(buffer) - - if (using_mpio_device(dset_id)) then -#ifdef PHDF5 - call h5pcreate_f(H5P_DATASET_XFER_F, plist, hdf5_err) - call h5pset_dxpl_mpio_f(plist, data_xfer_mode, hdf5_err) - call h5dread_f(dset_id, hdf5_integer8_t, f_ptr, hdf5_err, xfer_prp=plist) - call h5pclose_f(plist, hdf5_err) -#endif - else - call h5dread_f(dset_id, hdf5_integer8_t, f_ptr, hdf5_err) - end if - - if (present(name)) call h5dclose_f(dset_id, hdf5_err) + buffer = buffer_(1) end subroutine read_long !=============================================================================== diff --git a/src/hdf5_interface.cpp b/src/hdf5_interface.cpp index 76b3d6feae..78fcad349e 100644 --- a/src/hdf5_interface.cpp +++ b/src/hdf5_interface.cpp @@ -201,6 +201,13 @@ read_int(hid_t obj_id, const char* name, int* buffer, bool indep) } +void +read_llong(hid_t obj_id, const char* name, long long* buffer, bool indep) +{ + read_array(obj_id, name, H5T_NATIVE_LLONG, buffer, indep); +} + + void write_array(hid_t group_id, int ndim, const hsize_t* dims, const char* name, hid_t mem_type_id, const void* buffer, bool indep) @@ -256,6 +263,14 @@ write_int(hid_t group_id, int ndim, const hsize_t* dims, const char* name, } +void +write_llong(hid_t group_id, int ndim, const hsize_t* dims, const char* name, + const long long* buffer, bool indep) +{ + write_array(group_id, ndim, dims, name, H5T_NATIVE_LLONG, buffer, indep); +} + + void write_string(hid_t group_id, char const *name, char const *buffer) { diff --git a/src/hdf5_interface.h b/src/hdf5_interface.h index b3efda48c2..8e47b528f7 100644 --- a/src/hdf5_interface.h +++ b/src/hdf5_interface.h @@ -47,6 +47,8 @@ extern "C" void read_double(hid_t obj_id, const char* name, double* buffer, bool indep); extern "C" void read_int(hid_t obj_id, const char* name, int* buffer, bool indep); +extern "C" void read_llong(hid_t obj_id, const char* name, long long* buffer, + bool indep); void write_array(hid_t group_id, int ndim, const hsize_t* dims, const char* name, hid_t mem_type_id, const void* buffer, bool indep); @@ -54,6 +56,8 @@ extern "C" void write_double(hid_t group_id, int ndim, const hsize_t* dims, const char* name, const double* buffer, bool indep); extern "C" void write_int(hid_t group_id, int ndim, const hsize_t* dims, const char* name, const int* buffer, bool indep); +extern "C" void write_llong(hid_t group_id, int ndim, const hsize_t* dims, + const char* name, const long long* buffer, bool indep); void write_string(hid_t group_id, char const *name, char const *buffer); void write_string(hid_t group_id, char const *name, const std::string &buffer); From 2760bce6796c2c120e30bfe48271c2627941896e Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Wed, 18 Apr 2018 09:46:28 -0500 Subject: [PATCH 28/77] Convert HDF5 write_string to C++ --- src/hdf5_interface.F90 | 63 +++++++++--------------------------------- src/hdf5_interface.cpp | 42 ++++++++++++++-------------- src/hdf5_interface.h | 12 ++++---- src/surface.cpp | 34 +++++++++++------------ 4 files changed, 56 insertions(+), 95 deletions(-) diff --git a/src/hdf5_interface.F90 b/src/hdf5_interface.F90 index 7514c5ba03..1a3413820e 100644 --- a/src/hdf5_interface.F90 +++ b/src/hdf5_interface.F90 @@ -164,6 +164,15 @@ module hdf5_interface integer(C_LONG_LONG), intent(in) :: buffer(*) logical(C_BOOL), intent(in) :: indep end subroutine write_llong_c + + subroutine write_string_c(group_id, name, buffer, indep) & + bind(C, name='write_string') + import HID_T, HSIZE_T, C_CHAR, C_BOOL + integer(HID_T), value :: group_id + character(kind=C_CHAR), intent(in) :: name(*) + character(kind=C_CHAR), intent(in) :: buffer(*) + logical(C_BOOL), intent(in) :: indep + end subroutine write_string_c end interface contains @@ -888,58 +897,12 @@ contains character(*), intent(in), target :: buffer ! read data to here logical, intent(in), optional :: indep ! independent I/O - integer :: hdf5_err - integer :: data_xfer_mode -#ifdef PHDF5 - integer(HID_T) :: plist ! property list -#endif - integer(HID_T) :: dset ! data set handle - integer(HID_T) :: dspace ! data or file space handle - integer(HID_T) :: filetype - integer(SIZE_T) :: i, n - character(kind=C_CHAR), allocatable, target :: temp_buffer(:) - type(c_ptr) :: f_ptr + logical(C_BOOL) :: indep_ - ! Set up collective vs. independent I/O - data_xfer_mode = H5FD_MPIO_COLLECTIVE_F - if (present(indep)) then - if (indep) data_xfer_mode = H5FD_MPIO_INDEPENDENT_F - end if + indep_ = .false. + if (present(indep)) indep_ = indep - ! Create datatype for HDF5 file based on C char - n = len_trim(buffer) - if (n > 0) then - call h5tcopy_f(H5T_C_S1, filetype, hdf5_err) - call h5tset_size_f(filetype, n, hdf5_err) - - ! Create dataspace/dataset - call h5screate_f(H5S_SCALAR_F, dspace, hdf5_err) - call h5dcreate_f(group_id, trim(name), filetype, dspace, dset, hdf5_err) - - ! Copy string to temporary buffer - allocate(temp_buffer(n)) - do i = 1, n - temp_buffer(i) = buffer(i:i) - end do - - ! Get pointer to start of string - f_ptr = c_loc(temp_buffer(1)) - - if (using_mpio_device(group_id)) then -#ifdef PHDF5 - call h5pcreate_f(H5P_DATASET_XFER_F, plist, hdf5_err) - call h5pset_dxpl_mpio_f(plist, data_xfer_mode, hdf5_err) - call h5dwrite_f(dset, filetype, f_ptr, hdf5_err, xfer_prp=plist) - call h5pclose_f(plist, hdf5_err) -#endif - else - call h5dwrite_f(dset, filetype, f_ptr, hdf5_err) - end if - - call h5dclose_f(dset, hdf5_err) - call h5sclose_f(dspace, hdf5_err) - call h5tclose_f(filetype, hdf5_err) - end if + call write_string_c(group_id, to_c_string(name), to_c_string(buffer), indep_) end subroutine write_string !=============================================================================== diff --git a/src/hdf5_interface.cpp b/src/hdf5_interface.cpp index 78fcad349e..d78bf83d86 100644 --- a/src/hdf5_interface.cpp +++ b/src/hdf5_interface.cpp @@ -5,6 +5,7 @@ #include "hdf5_hl.h" #include +#include #include #include @@ -160,7 +161,7 @@ open_group(hid_t group_id, const char* name) void -read_array(hid_t obj_id, const char* name, hid_t mem_type_id, +read_data(hid_t obj_id, const char* name, hid_t mem_type_id, void* buffer, bool indep) { hid_t dset = obj_id; @@ -190,26 +191,26 @@ read_array(hid_t obj_id, const char* name, hid_t mem_type_id, void read_double(hid_t obj_id, const char* name, double* buffer, bool indep) { - read_array(obj_id, name, H5T_NATIVE_DOUBLE, buffer, indep); + read_data(obj_id, name, H5T_NATIVE_DOUBLE, buffer, indep); } void read_int(hid_t obj_id, const char* name, int* buffer, bool indep) { - read_array(obj_id, name, H5T_NATIVE_INT, buffer, indep); + read_data(obj_id, name, H5T_NATIVE_INT, buffer, indep); } void read_llong(hid_t obj_id, const char* name, long long* buffer, bool indep) { - read_array(obj_id, name, H5T_NATIVE_LLONG, buffer, indep); + read_data(obj_id, name, H5T_NATIVE_LLONG, buffer, indep); } void -write_array(hid_t group_id, int ndim, const hsize_t* dims, const char* name, +write_data(hid_t group_id, int ndim, const hsize_t* dims, const char* name, hid_t mem_type_id, const void* buffer, bool indep) { // If array is given, create a simple dataspace. Otherwise, create a scalar @@ -251,7 +252,7 @@ void write_double(hid_t group_id, int ndim, const hsize_t* dims, const char* name, const double* buffer, bool indep) { - write_array(group_id, ndim, dims, name, H5T_NATIVE_DOUBLE, buffer, indep); + write_data(group_id, ndim, dims, name, H5T_NATIVE_DOUBLE, buffer, indep); } @@ -259,7 +260,7 @@ void write_int(hid_t group_id, int ndim, const hsize_t* dims, const char* name, const int* buffer, bool indep) { - write_array(group_id, ndim, dims, name, H5T_NATIVE_INT, buffer, indep); + write_data(group_id, ndim, dims, name, H5T_NATIVE_INT, buffer, indep); } @@ -267,34 +268,31 @@ void write_llong(hid_t group_id, int ndim, const hsize_t* dims, const char* name, const long long* buffer, bool indep) { - write_array(group_id, ndim, dims, name, H5T_NATIVE_LLONG, buffer, indep); + write_data(group_id, ndim, dims, name, H5T_NATIVE_LLONG, buffer, indep); } void -write_string(hid_t group_id, char const *name, char const *buffer) +write_string(hid_t group_id, char const* name, const char* buffer, bool indep) { size_t buffer_len = strlen(buffer); - hid_t datatype = H5Tcopy(H5T_C_S1); - H5Tset_size(datatype, buffer_len); + if (buffer_len > 0) { + // Set up appropriate datatype for a fixed-length string + hid_t datatype = H5Tcopy(H5T_C_S1); + H5Tset_size(datatype, buffer_len); - hid_t dataspace = H5Screate(H5S_SCALAR); + write_data(group_id, 0, nullptr, name, datatype, buffer, indep); - hid_t dataset = H5Dcreate(group_id, name, datatype, dataspace, - H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT); - - H5Dwrite(dataset, datatype, H5S_ALL, H5S_ALL, H5P_DEFAULT, buffer); - - H5Tclose(datatype); - H5Sclose(dataspace); - H5Dclose(dataset); + // Free resources + H5Tclose(datatype); + } } void -write_string(hid_t group_id, char const *name, const std::string &buffer) +write_string(hid_t group_id, char const* name, const std::string& buffer, bool indep) { - write_string(group_id, name, buffer.c_str()); + write_string(group_id, name, buffer.c_str(), indep); } } diff --git a/src/hdf5_interface.h b/src/hdf5_interface.h index 8e47b528f7..41883d9267 100644 --- a/src/hdf5_interface.h +++ b/src/hdf5_interface.h @@ -41,8 +41,8 @@ write_double_1D(hid_t group_id, char const *name, H5Dclose(dataset); } -void read_array(hid_t obj_id, const char* name, double* buffer, - hid_t mem_type_id, bool indep); +void read_data(hid_t obj_id, const char* name, double* buffer, + hid_t mem_type_id, bool indep); extern "C" void read_double(hid_t obj_id, const char* name, double* buffer, bool indep); extern "C" void read_int(hid_t obj_id, const char* name, int* buffer, @@ -50,8 +50,8 @@ extern "C" void read_int(hid_t obj_id, const char* name, int* buffer, extern "C" void read_llong(hid_t obj_id, const char* name, long long* buffer, bool indep); -void write_array(hid_t group_id, int ndim, const hsize_t* dims, const char* name, - hid_t mem_type_id, const void* buffer, bool indep); +void write_data(hid_t group_id, int ndim, const hsize_t* dims, const char* name, + hid_t mem_type_id, const void* buffer, bool indep); extern "C" void write_double(hid_t group_id, int ndim, const hsize_t* dims, const char* name, const double* buffer, bool indep); extern "C" void write_int(hid_t group_id, int ndim, const hsize_t* dims, @@ -59,8 +59,8 @@ extern "C" void write_int(hid_t group_id, int ndim, const hsize_t* dims, extern "C" void write_llong(hid_t group_id, int ndim, const hsize_t* dims, const char* name, const long long* buffer, bool indep); -void write_string(hid_t group_id, char const *name, char const *buffer); -void write_string(hid_t group_id, char const *name, const std::string &buffer); +extern "C" void write_string(hid_t group_id, char const *name, char const *buffer, bool indep); +void write_string(hid_t group_id, char const *name, const std::string &buffer, bool indep); } // namespace openmc #endif //HDF5_INTERFACE_H diff --git a/src/surface.cpp b/src/surface.cpp index 9abfd23d2e..9db9db3fa5 100644 --- a/src/surface.cpp +++ b/src/surface.cpp @@ -202,21 +202,21 @@ Surface::to_hdf5(hid_t group_id) const switch(bc) { case BC_TRANSMIT : - write_string(surf_group, "boundary_type", "transmission"); + write_string(surf_group, "boundary_type", "transmission", false); break; case BC_VACUUM : - write_string(surf_group, "boundary_type", "vacuum"); + write_string(surf_group, "boundary_type", "vacuum", false); break; case BC_REFLECT : - write_string(surf_group, "boundary_type", "reflective"); + write_string(surf_group, "boundary_type", "reflective", false); break; case BC_PERIODIC : - write_string(surf_group, "boundary_type", "periodic"); + write_string(surf_group, "boundary_type", "periodic", false); break; } if (!name.empty()) { - write_string(surf_group, "name", name); + write_string(surf_group, "name", name, false); } to_hdf5_inner(surf_group); @@ -297,7 +297,7 @@ inline void SurfaceXPlane::normal(const double xyz[3], double uvw[3]) const void SurfaceXPlane::to_hdf5_inner(hid_t group_id) const { - write_string(group_id, "type", "x-plane"); + write_string(group_id, "type", "x-plane", false); std::array coeffs {{x0}}; write_double_1D(group_id, "coefficients", coeffs); } @@ -362,7 +362,7 @@ inline void SurfaceYPlane::normal(const double xyz[3], double uvw[3]) const void SurfaceYPlane::to_hdf5_inner(hid_t group_id) const { - write_string(group_id, "type", "y-plane"); + write_string(group_id, "type", "y-plane", false); std::array coeffs {{y0}}; write_double_1D(group_id, "coefficients", coeffs); } @@ -428,7 +428,7 @@ inline void SurfaceZPlane::normal(const double xyz[3], double uvw[3]) const void SurfaceZPlane::to_hdf5_inner(hid_t group_id) const { - write_string(group_id, "type", "z-plane"); + write_string(group_id, "type", "z-plane", false); std::array coeffs {{z0}}; write_double_1D(group_id, "coefficients", coeffs); } @@ -489,7 +489,7 @@ SurfacePlane::normal(const double xyz[3], double uvw[3]) const void SurfacePlane::to_hdf5_inner(hid_t group_id) const { - write_string(group_id, "type", "plane"); + write_string(group_id, "type", "plane", false); std::array coeffs {{A, B, C, D}}; write_double_1D(group_id, "coefficients", coeffs); } @@ -621,7 +621,7 @@ inline void SurfaceXCylinder::normal(const double xyz[3], double uvw[3]) const void SurfaceXCylinder::to_hdf5_inner(hid_t group_id) const { - write_string(group_id, "type", "x-cylinder"); + write_string(group_id, "type", "x-cylinder", false); std::array coeffs {{y0, z0, r}}; write_double_1D(group_id, "coefficients", coeffs); } @@ -655,7 +655,7 @@ inline void SurfaceYCylinder::normal(const double xyz[3], double uvw[3]) const void SurfaceYCylinder::to_hdf5_inner(hid_t group_id) const { - write_string(group_id, "type", "y-cylinder"); + write_string(group_id, "type", "y-cylinder", false); std::array coeffs {{x0, z0, r}}; write_double_1D(group_id, "coefficients", coeffs); } @@ -689,7 +689,7 @@ inline void SurfaceZCylinder::normal(const double xyz[3], double uvw[3]) const void SurfaceZCylinder::to_hdf5_inner(hid_t group_id) const { - write_string(group_id, "type", "z-cylinder"); + write_string(group_id, "type", "z-cylinder", false); std::array coeffs {{x0, y0, r}}; write_double_1D(group_id, "coefficients", coeffs); } @@ -760,7 +760,7 @@ inline void SurfaceSphere::normal(const double xyz[3], double uvw[3]) const void SurfaceSphere::to_hdf5_inner(hid_t group_id) const { - write_string(group_id, "type", "sphere"); + write_string(group_id, "type", "sphere", false); std::array coeffs {{x0, y0, z0, r}}; write_double_1D(group_id, "coefficients", coeffs); } @@ -877,7 +877,7 @@ inline void SurfaceXCone::normal(const double xyz[3], double uvw[3]) const void SurfaceXCone::to_hdf5_inner(hid_t group_id) const { - write_string(group_id, "type", "x-cone"); + write_string(group_id, "type", "x-cone", false); std::array coeffs {{x0, y0, z0, r_sq}}; write_double_1D(group_id, "coefficients", coeffs); } @@ -911,7 +911,7 @@ inline void SurfaceYCone::normal(const double xyz[3], double uvw[3]) const void SurfaceYCone::to_hdf5_inner(hid_t group_id) const { - write_string(group_id, "type", "y-cone"); + write_string(group_id, "type", "y-cone", false); std::array coeffs {{x0, y0, z0, r_sq}}; write_double_1D(group_id, "coefficients", coeffs); } @@ -945,7 +945,7 @@ inline void SurfaceZCone::normal(const double xyz[3], double uvw[3]) const void SurfaceZCone::to_hdf5_inner(hid_t group_id) const { - write_string(group_id, "type", "z-cone"); + write_string(group_id, "type", "z-cone", false); std::array coeffs {{x0, y0, z0, r_sq}}; write_double_1D(group_id, "coefficients", coeffs); } @@ -1039,7 +1039,7 @@ SurfaceQuadric::normal(const double xyz[3], double uvw[3]) const void SurfaceQuadric::to_hdf5_inner(hid_t group_id) const { - write_string(group_id, "type", "quadric"); + write_string(group_id, "type", "quadric", false); std::array coeffs {{A, B, C, D, E, F, G, H, J, K}}; write_double_1D(group_id, "coefficients", coeffs); } From f8e7d52d39c8933e96c174fbec91b9c14b6fea13 Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Wed, 18 Apr 2018 13:03:10 -0500 Subject: [PATCH 29/77] Bugfix for writing 4D array --- src/hdf5_interface.F90 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/hdf5_interface.F90 b/src/hdf5_interface.F90 index 1a3413820e..be6bce775e 100644 --- a/src/hdf5_interface.F90 +++ b/src/hdf5_interface.F90 @@ -518,7 +518,7 @@ contains indep_ = .false. if (present(indep)) indep_ = indep - call write_double_c(group_id, 1, dims, to_c_string(name), buffer, indep_) + call write_double_c(group_id, 4, dims, to_c_string(name), buffer, indep_) end subroutine write_double_4D !=============================================================================== From cc5e99eac4c8f7644d86d1367d221e4f1b504e37 Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Wed, 18 Apr 2018 13:38:34 -0500 Subject: [PATCH 30/77] Fix dimension bug and implement write_string_1D using write_string_c --- src/hdf5_interface.F90 | 135 ++++++++++++++++++----------------------- src/hdf5_interface.cpp | 12 ++-- src/hdf5_interface.h | 5 +- 3 files changed, 69 insertions(+), 83 deletions(-) diff --git a/src/hdf5_interface.F90 b/src/hdf5_interface.F90 index be6bce775e..b9787ba1ec 100644 --- a/src/hdf5_interface.F90 +++ b/src/hdf5_interface.F90 @@ -165,10 +165,13 @@ module hdf5_interface logical(C_BOOL), intent(in) :: indep end subroutine write_llong_c - subroutine write_string_c(group_id, name, buffer, indep) & + subroutine write_string_c(group_id, ndim, dims, slen, name, buffer, indep) & bind(C, name='write_string') - import HID_T, HSIZE_T, C_CHAR, C_BOOL + import HID_T, HSIZE_T, C_INT, C_CHAR, C_BOOL, C_SIZE_T integer(HID_T), value :: group_id + integer(C_INT), value :: ndim + integer(HSIZE_T), intent(in) :: dims(*) + integer(C_SIZE_T), value :: slen character(kind=C_CHAR), intent(in) :: name(*) character(kind=C_CHAR), intent(in) :: buffer(*) logical(C_BOOL), intent(in) :: indep @@ -466,7 +469,7 @@ contains integer(HSIZE_T) :: dims(1) logical(C_BOOL) :: indep_ - dims(:) = shape(buffer) + dims(1) = size(buffer) indep_ = .false. if (present(indep)) indep_ = indep @@ -482,7 +485,10 @@ contains integer(HSIZE_T) :: dims(2) logical(C_BOOL) :: indep_ - dims(:) = shape(buffer) + ! Reverse shape of array since it will be written from C + dims(1) = size(buffer, 2) + dims(2) = size(buffer, 1) + indep_ = .false. if (present(indep)) indep_ = indep @@ -498,7 +504,11 @@ contains integer(HSIZE_T) :: dims(3) logical(C_BOOL) :: indep_ - dims(:) = shape(buffer) + ! Reverse shape of array since it will be written from C + dims(1) = size(buffer, 3) + dims(2) = size(buffer, 2) + dims(3) = size(buffer, 1) + indep_ = .false. if (present(indep)) indep_ = indep @@ -514,7 +524,12 @@ contains integer(HSIZE_T) :: dims(4) logical(C_BOOL) :: indep_ - dims(:) = shape(buffer) + ! Reverse shape of array since it will be written from C + dims(1) = size(buffer, 4) + dims(2) = size(buffer, 3) + dims(3) = size(buffer, 2) + dims(4) = size(buffer, 1) + indep_ = .false. if (present(indep)) indep_ = indep @@ -667,7 +682,7 @@ contains integer(HSIZE_T) :: dims(1) logical(C_BOOL) :: indep_ - dims(:) = shape(buffer) + dims(1) = size(buffer) indep_ = .false. if (present(indep)) indep_ = indep @@ -683,7 +698,10 @@ contains integer(HSIZE_T) :: dims(2) logical(C_BOOL) :: indep_ - dims(:) = shape(buffer) + ! Reverse shape of array since it will be written from C + dims(1) = size(buffer, 2) + dims(2) = size(buffer, 1) + indep_ = .false. if (present(indep)) indep_ = indep @@ -699,7 +717,11 @@ contains integer(HSIZE_T) :: dims(3) logical(C_BOOL) :: indep_ - dims(:) = shape(buffer) + ! Reverse shape of array since it will be written from C + dims(1) = size(buffer, 3) + dims(2) = size(buffer, 2) + dims(3) = size(buffer, 1) + indep_ = .false. if (present(indep)) indep_ = indep @@ -715,7 +737,12 @@ contains integer(HSIZE_T) :: dims(4) logical(C_BOOL) :: indep_ - dims(:) = shape(buffer) + ! Reverse shape of array since it will be written from C + dims(1) = size(buffer, 4) + dims(2) = size(buffer, 3) + dims(3) = size(buffer, 2) + dims(4) = size(buffer, 1) + indep_ = .false. if (present(indep)) indep_ = indep @@ -897,12 +924,16 @@ contains character(*), intent(in), target :: buffer ! read data to here logical, intent(in), optional :: indep ! independent I/O + integer(HSIZE_T) :: dims(0) + integer(C_SIZE_T) :: slen logical(C_BOOL) :: indep_ indep_ = .false. if (present(indep)) indep_ = indep + slen = len_trim(buffer) - call write_string_c(group_id, to_c_string(name), to_c_string(buffer), indep_) + call write_string_c(group_id, 0, dims, slen, to_c_string(name), & + to_c_string(buffer), indep_) end subroutine write_string !=============================================================================== @@ -988,74 +1019,28 @@ contains character(*), intent(in), target :: buffer(:) ! read data to here logical, intent(in), optional :: indep ! independent I/O + integer :: i integer(HSIZE_T) :: dims(1) + integer(C_SIZE_T) :: m + logical(C_BOOL) :: indep_ + character(kind=C_CHAR), allocatable :: buffer_(:) - dims(:) = shape(buffer) - if (present(indep)) then - call write_string_1D_explicit(group_id, dims, name, buffer, indep) - else - call write_string_1D_explicit(group_id, dims, name, buffer) - end if + indep_ = .false. + if (present(indep)) indep_ = indep + + ! Copy array of characters into an array of C chars with the right memory + ! layout + dims(1) = size(buffer) + m = maxval(len_trim(buffer)) + 1 + allocate(buffer_(dims(1)*m)) + do i = 0, dims(1) - 1 + buffer_(i*m+1 : (i+1)*m) = to_c_string(buffer(i+1)) + end do + + call write_string_c(group_id, 1, dims, m, to_c_string(name), & + buffer_, indep_) end subroutine write_string_1D - subroutine write_string_1D_explicit(group_id, dims, name, buffer, indep) - integer(HID_T), intent(in) :: group_id - integer(HSIZE_T), intent(in) :: dims(1) - character(*), intent(in) :: name - character(*), intent(in), target :: buffer(dims(1)) - logical, intent(in), optional :: indep ! independent I/O - - integer :: hdf5_err - integer :: data_xfer_mode -#ifdef PHDF5 - integer(HID_T) :: plist ! property list -#endif - integer(HID_T) :: dset ! data set handle - integer(HID_T) :: dspace ! data or file space handle - integer(HID_T) :: filetype - integer(HID_T) :: memtype - integer(SIZE_T) :: n - type(c_ptr) :: f_ptr - - ! Set up collective vs. independent I/O - data_xfer_mode = H5FD_MPIO_COLLECTIVE_F - if (present(indep)) then - if (indep) data_xfer_mode = H5FD_MPIO_INDEPENDENT_F - end if - - ! Create datatype for HDF5 file based on C char - n = maxval(len_trim(buffer)) - call h5tcopy_f(H5T_C_S1, filetype, hdf5_err) - call h5tset_size_f(filetype, n + 1, hdf5_err) - - ! Create datatype in memory based on Fortran character - call h5tcopy_f(H5T_FORTRAN_S1, memtype, hdf5_err) - call h5tset_size_f(memtype, int(len(buffer(1)), SIZE_T), hdf5_err) - - ! Create dataspace/dataset - call h5screate_simple_f(1, dims, dspace, hdf5_err) - call h5dcreate_f(group_id, trim(name), filetype, dspace, dset, hdf5_err) - - ! Get pointer to start of string - f_ptr = c_loc(buffer(1)(1:1)) - - if (using_mpio_device(group_id)) then -#ifdef PHDF5 - call h5pcreate_f(H5P_DATASET_XFER_F, plist, hdf5_err) - call h5pset_dxpl_mpio_f(plist, data_xfer_mode, hdf5_err) - if (n > 0) call h5dwrite_f(dset, memtype, f_ptr, hdf5_err, xfer_prp=plist) - call h5pclose_f(plist, hdf5_err) -#endif - else - if (n > 0) call h5dwrite_f(dset, memtype, f_ptr, hdf5_err) - end if - - call h5dclose_f(dset, hdf5_err) - call h5sclose_f(dspace, hdf5_err) - call h5tclose_f(memtype, hdf5_err) - call h5tclose_f(filetype, hdf5_err) - end subroutine write_string_1D_explicit - !=============================================================================== ! READ_STRING_1D reads string 1-D array data !=============================================================================== diff --git a/src/hdf5_interface.cpp b/src/hdf5_interface.cpp index d78bf83d86..0b8000f706 100644 --- a/src/hdf5_interface.cpp +++ b/src/hdf5_interface.cpp @@ -273,15 +273,15 @@ write_llong(hid_t group_id, int ndim, const hsize_t* dims, const char* name, void -write_string(hid_t group_id, char const* name, const char* buffer, bool indep) +write_string(hid_t group_id, int ndim, const hsize_t* dims, size_t slen, + const char* name, const char* buffer, bool indep) { - size_t buffer_len = strlen(buffer); - if (buffer_len > 0) { + if (slen > 0) { // Set up appropriate datatype for a fixed-length string hid_t datatype = H5Tcopy(H5T_C_S1); - H5Tset_size(datatype, buffer_len); + H5Tset_size(datatype, slen); - write_data(group_id, 0, nullptr, name, datatype, buffer, indep); + write_data(group_id, ndim, dims, name, datatype, buffer, indep); // Free resources H5Tclose(datatype); @@ -292,7 +292,7 @@ write_string(hid_t group_id, char const* name, const char* buffer, bool indep) void write_string(hid_t group_id, char const* name, const std::string& buffer, bool indep) { - write_string(group_id, name, buffer.c_str(), indep); + write_string(group_id, 0, nullptr, buffer.length(), name, buffer.c_str(), indep); } } diff --git a/src/hdf5_interface.h b/src/hdf5_interface.h index 41883d9267..11f26a5f1b 100644 --- a/src/hdf5_interface.h +++ b/src/hdf5_interface.h @@ -59,8 +59,9 @@ extern "C" void write_int(hid_t group_id, int ndim, const hsize_t* dims, extern "C" void write_llong(hid_t group_id, int ndim, const hsize_t* dims, const char* name, const long long* buffer, bool indep); -extern "C" void write_string(hid_t group_id, char const *name, char const *buffer, bool indep); -void write_string(hid_t group_id, char const *name, const std::string &buffer, bool indep); +extern "C" void write_string(hid_t group_id, int ndim, const hsize_t* dims, size_t slen, + const char* name, char const* buffer, bool indep); +void write_string(hid_t group_id, const char* name, const std::string& buffer, bool indep); } // namespace openmc #endif //HDF5_INTERFACE_H From 342d207fc4eaffe1158c4fb7a85fa1c43740e622 Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Wed, 18 Apr 2018 21:57:57 -0500 Subject: [PATCH 31/77] Convert HDF5 write_attribute to C++ --- src/hdf5_interface.F90 | 141 ++++++++++++----------------------------- src/hdf5_interface.cpp | 77 +++++++++++++++++++--- src/hdf5_interface.h | 17 +++-- 3 files changed, 121 insertions(+), 114 deletions(-) diff --git a/src/hdf5_interface.F90 b/src/hdf5_interface.F90 index b9787ba1ec..1d056e1dcd 100644 --- a/src/hdf5_interface.F90 +++ b/src/hdf5_interface.F90 @@ -132,6 +132,34 @@ module hdf5_interface logical(C_BOOL), intent(in) :: indep end subroutine read_llong_c + subroutine write_attr_double_c(obj_id, ndim, dims, name, buffer) & + bind(C, name='write_attr_double') + import HID_T, HSIZE_T, C_INT, C_DOUBLE, C_CHAR + integer(HID_T), value :: obj_id + integer(C_INT), value :: ndim + integer(HSIZE_T), intent(in) :: dims(*) + character(kind=C_CHAR), intent(in) :: name(*) + real(C_DOUBLE), intent(in) :: buffer(*) + end subroutine write_attr_double_c + + subroutine write_attr_int_c(obj_id, ndim, dims, name, buffer) & + bind(C, name='write_attr_int') + import HID_T, HSIZE_T, C_INT, C_CHAR + integer(HID_T), value :: obj_id + integer(C_INT), value :: ndim + integer(HSIZE_T), intent(in) :: dims(*) + character(kind=C_CHAR), intent(in) :: name(*) + integer(C_INT), intent(in) :: buffer(*) + end subroutine write_attr_int_c + + subroutine write_attr_string_c(obj_id, name, buffer) & + bind(C, name='write_attr_string') + import HID_T, C_CHAR + integer(HID_T), value :: obj_id + character(kind=C_CHAR), intent(in) :: name(*) + character(kind=C_CHAR), intent(in) :: buffer(*) + end subroutine write_attr_string_c + subroutine write_double_c(group_id, ndim, dims, name, buffer, indep) & bind(C, name='write_double') import HID_T, HSIZE_T, C_INT, C_DOUBLE, C_CHAR, C_BOOL @@ -1141,41 +1169,8 @@ contains character(*), intent(in) :: name ! name of attribute character(*), intent(in), target :: buffer ! string to write - integer :: hdf5_err - integer(HID_T) :: dspace_id - integer(HID_T) :: attr_id - integer(HID_T) :: filetype - integer(SIZE_T) :: i - integer(SIZE_T) :: n - character(kind=C_CHAR), allocatable, target :: temp_buffer(:) - type(c_ptr) :: f_ptr - ! Create datatype for HDF5 file based on C char - n = len_trim(buffer) - if (n > 0) then - call h5tcopy_f(H5T_C_S1, filetype, hdf5_err) - call h5tset_size_f(filetype, n, hdf5_err) - - ! Create memory space and attribute - call h5screate_f(H5S_SCALAR_F, dspace_id, hdf5_err) - call h5acreate_f(obj_id, trim(name), filetype, dspace_id, & - attr_id, hdf5_err) - - ! Copy string to temporary buffer - allocate(temp_buffer(n)) - do i = 1, n - temp_buffer(i) = buffer(i:i) - end do - - ! Write attribute - f_ptr = c_loc(buffer(1:1)) - call h5awrite_f(attr_id, filetype, f_ptr, hdf5_err) - - ! Close attribute - call h5aclose_f(attr_id, hdf5_err) - call h5sclose_f(dspace_id, hdf5_err) - call h5tclose_f(filetype, hdf5_err) - end if + call write_attr_string_c(obj_id, to_c_string(name), to_c_string(buffer)) end subroutine write_attribute_string subroutine read_attribute_double(buffer, obj_id, name) @@ -1198,18 +1193,11 @@ contains character(*), intent(in) :: name real(8), intent(in), target :: buffer - integer :: hdf5_err - integer(HID_T) :: dspace_id - integer(HID_T) :: attr_id - type(C_PTR) :: f_ptr + integer(HSIZE_T) :: dims(0) + real(C_DOUBLE) :: buffer_(1) - call h5screate_f(H5S_SCALAR_F, dspace_id, hdf5_err) - call h5acreate_f(obj_id, trim(name), H5T_NATIVE_DOUBLE, dspace_id, & - attr_id, hdf5_err) - f_ptr = c_loc(buffer) - call h5awrite_f(attr_id, H5T_NATIVE_DOUBLE, f_ptr, hdf5_err) - call h5aclose_f(attr_id, hdf5_err) - call h5sclose_f(dspace_id, hdf5_err) + buffer_(1) = buffer + call write_attr_double_c(obj_id, 0, dims, to_c_string(name), buffer_) end subroutine write_attribute_double subroutine read_attribute_double_1D(buffer, obj_id, name) @@ -1257,30 +1245,10 @@ contains integer(HSIZE_T) :: dims(1) - dims(:) = shape(buffer) - call write_attribute_double_1D_explicit(obj_id, dims, name, buffer) + dims(1) = size(buffer) + call write_attr_double_c(obj_id, 1, dims, to_c_string(name), buffer) end subroutine write_attribute_double_1D - subroutine write_attribute_double_1D_explicit(obj_id, dims, name, buffer) - integer(HID_T), intent(in) :: obj_id - integer(HSIZE_T), intent(in) :: dims(1) - character(*), intent(in) :: name - real(8), target, intent(in) :: buffer(dims(1)) - - integer :: hdf5_err - integer(HID_T) :: dspace_id - integer(HID_T) :: attr_id - type(C_PTR) :: f_ptr - - call h5screate_simple_f(1, dims, dspace_id, hdf5_err) - call h5acreate_f(obj_id, trim(name), H5T_NATIVE_DOUBLE, dspace_id, & - attr_id, hdf5_err) - f_ptr = c_loc(buffer) - call h5awrite_f(attr_id, H5T_NATIVE_DOUBLE, f_ptr, hdf5_err) - call h5aclose_f(attr_id, hdf5_err) - call h5sclose_f(dspace_id, hdf5_err) - end subroutine write_attribute_double_1D_explicit - subroutine read_attribute_double_2D(buffer, obj_id, name) real(8), target, allocatable, intent(inout) :: buffer(:,:) integer(HID_T), intent(in) :: obj_id @@ -1339,18 +1307,11 @@ contains character(*), intent(in) :: name integer, intent(in), target :: buffer - integer :: hdf5_err - integer(HID_T) :: dspace_id - integer(HID_T) :: attr_id - type(C_PTR) :: f_ptr + integer(HSIZE_T) :: dims(0) + integer(C_INT) :: buffer_(1) - call h5screate_f(H5S_SCALAR_F, dspace_id, hdf5_err) - call h5acreate_f(obj_id, trim(name), H5T_NATIVE_INTEGER, dspace_id, & - attr_id, hdf5_err) - f_ptr = c_loc(buffer) - call h5awrite_f(attr_id, H5T_NATIVE_INTEGER, f_ptr, hdf5_err) - call h5aclose_f(attr_id, hdf5_err) - call h5sclose_f(dspace_id, hdf5_err) + buffer_(1) = buffer + call write_attr_int_c(obj_id, 0, dims, to_c_string(name), buffer_) end subroutine write_attribute_integer subroutine read_attribute_integer_1D(buffer, obj_id, name) @@ -1398,30 +1359,10 @@ contains integer(HSIZE_T) :: dims(1) - dims(:) = shape(buffer) - call write_attribute_integer_1D_explicit(obj_id, dims, name, buffer) + dims(1) = size(buffer) + call write_attr_int_c(obj_id, 1, dims, to_c_string(name), buffer) end subroutine write_attribute_integer_1D - subroutine write_attribute_integer_1D_explicit(obj_id, dims, name, buffer) - integer(HID_T), intent(in) :: obj_id - integer(HSIZE_T), intent(in) :: dims(1) - character(*), intent(in) :: name - integer, target, intent(in) :: buffer(dims(1)) - - integer :: hdf5_err - integer(HID_T) :: dspace_id - integer(HID_T) :: attr_id - type(C_PTR) :: f_ptr - - call h5screate_simple_f(1, dims, dspace_id, hdf5_err) - call h5acreate_f(obj_id, trim(name), H5T_NATIVE_INTEGER, dspace_id, & - attr_id, hdf5_err) - f_ptr = c_loc(buffer) - call h5awrite_f(attr_id, H5T_NATIVE_INTEGER, f_ptr, hdf5_err) - call h5aclose_f(attr_id, hdf5_err) - call h5sclose_f(dspace_id, hdf5_err) - end subroutine write_attribute_integer_1D_explicit - subroutine read_attribute_integer_2D(buffer, obj_id, name) integer, target, allocatable, intent(inout) :: buffer(:,:) integer(HID_T), intent(in) :: obj_id diff --git a/src/hdf5_interface.cpp b/src/hdf5_interface.cpp index 0b8000f706..f482285f26 100644 --- a/src/hdf5_interface.cpp +++ b/src/hdf5_interface.cpp @@ -161,7 +161,7 @@ open_group(hid_t group_id, const char* name) void -read_data(hid_t obj_id, const char* name, hid_t mem_type_id, +read_dataset(hid_t obj_id, const char* name, hid_t mem_type_id, void* buffer, bool indep) { hid_t dset = obj_id; @@ -191,27 +191,84 @@ read_data(hid_t obj_id, const char* name, hid_t mem_type_id, void read_double(hid_t obj_id, const char* name, double* buffer, bool indep) { - read_data(obj_id, name, H5T_NATIVE_DOUBLE, buffer, indep); + read_dataset(obj_id, name, H5T_NATIVE_DOUBLE, buffer, indep); } void read_int(hid_t obj_id, const char* name, int* buffer, bool indep) { - read_data(obj_id, name, H5T_NATIVE_INT, buffer, indep); + read_dataset(obj_id, name, H5T_NATIVE_INT, buffer, indep); } void read_llong(hid_t obj_id, const char* name, long long* buffer, bool indep) { - read_data(obj_id, name, H5T_NATIVE_LLONG, buffer, indep); + read_dataset(obj_id, name, H5T_NATIVE_LLONG, buffer, indep); } void -write_data(hid_t group_id, int ndim, const hsize_t* dims, const char* name, - hid_t mem_type_id, const void* buffer, bool indep) +write_attr(hid_t obj_id, int ndim, const hsize_t* dims, const char* name, + hid_t mem_type_id, const void* buffer) +{ + // If array is given, create a simple dataspace. Otherwise, create a scalar + // datascape. + hid_t dspace; + if (ndim > 0) { + dspace = H5Screate_simple(ndim, dims, nullptr); + } else { + dspace = H5Screate(H5S_SCALAR); + } + + // Create attribute and Write data + hid_t attr = H5Acreate(obj_id, name, mem_type_id, dspace, + H5P_DEFAULT, H5P_DEFAULT); + H5Awrite(attr, mem_type_id, buffer); + + // Free resources + H5Aclose(attr); + H5Sclose(dspace); +} + + +void +write_attr_double(hid_t obj_id, int ndim, const hsize_t* dims, const char* name, + const double* buffer) +{ + write_attr(obj_id, ndim, dims, name, H5T_NATIVE_DOUBLE, buffer); +} + + +void +write_attr_int(hid_t obj_id, int ndim, const hsize_t* dims, const char* name, + const int* buffer) +{ + write_attr(obj_id, ndim, dims, name, H5T_NATIVE_INT, buffer); +} + + +void +write_attr_string(hid_t obj_id, const char* name, const char* buffer) +{ + size_t n = strlen(buffer); + if (n > 0) { + // Set up appropriate datatype for a fixed-length string + hid_t datatype = H5Tcopy(H5T_C_S1); + H5Tset_size(datatype, n); + + write_attr(obj_id, 0, nullptr, name, datatype, buffer); + + // Free resources + H5Tclose(datatype); + } +} + + +void +write_dataset(hid_t group_id, int ndim, const hsize_t* dims, const char* name, + hid_t mem_type_id, const void* buffer, bool indep) { // If array is given, create a simple dataspace. Otherwise, create a scalar // datascape. @@ -252,7 +309,7 @@ void write_double(hid_t group_id, int ndim, const hsize_t* dims, const char* name, const double* buffer, bool indep) { - write_data(group_id, ndim, dims, name, H5T_NATIVE_DOUBLE, buffer, indep); + write_dataset(group_id, ndim, dims, name, H5T_NATIVE_DOUBLE, buffer, indep); } @@ -260,7 +317,7 @@ void write_int(hid_t group_id, int ndim, const hsize_t* dims, const char* name, const int* buffer, bool indep) { - write_data(group_id, ndim, dims, name, H5T_NATIVE_INT, buffer, indep); + write_dataset(group_id, ndim, dims, name, H5T_NATIVE_INT, buffer, indep); } @@ -268,7 +325,7 @@ void write_llong(hid_t group_id, int ndim, const hsize_t* dims, const char* name, const long long* buffer, bool indep) { - write_data(group_id, ndim, dims, name, H5T_NATIVE_LLONG, buffer, indep); + write_dataset(group_id, ndim, dims, name, H5T_NATIVE_LLONG, buffer, indep); } @@ -281,7 +338,7 @@ write_string(hid_t group_id, int ndim, const hsize_t* dims, size_t slen, hid_t datatype = H5Tcopy(H5T_C_S1); H5Tset_size(datatype, slen); - write_data(group_id, ndim, dims, name, datatype, buffer, indep); + write_dataset(group_id, ndim, dims, name, datatype, buffer, indep); // Free resources H5Tclose(datatype); diff --git a/src/hdf5_interface.h b/src/hdf5_interface.h index 11f26a5f1b..615bed24c7 100644 --- a/src/hdf5_interface.h +++ b/src/hdf5_interface.h @@ -41,8 +41,8 @@ write_double_1D(hid_t group_id, char const *name, H5Dclose(dataset); } -void read_data(hid_t obj_id, const char* name, double* buffer, - hid_t mem_type_id, bool indep); +void read_dataset(hid_t obj_id, const char* name, double* buffer, + hid_t mem_type_id, bool indep); extern "C" void read_double(hid_t obj_id, const char* name, double* buffer, bool indep); extern "C" void read_int(hid_t obj_id, const char* name, int* buffer, @@ -50,8 +50,17 @@ extern "C" void read_int(hid_t obj_id, const char* name, int* buffer, extern "C" void read_llong(hid_t obj_id, const char* name, long long* buffer, bool indep); -void write_data(hid_t group_id, int ndim, const hsize_t* dims, const char* name, - hid_t mem_type_id, const void* buffer, bool indep); +void write_attr(hid_t obj_id, int ndim, const hsize_t* dims, const char* name, + hid_t mem_type_id, const void* buffer); +extern "C" void write_attr_double(hid_t obj_id, int ndim, const hsize_t* dims, + const char* name, const double* buffer); +extern "C" void write_attr_int(hid_t obj_id, int ndim, const hsize_t* dims, + const char* name, const int* buffer); +extern "C" void write_attr_string(hid_t obj_id, const char* name, const char* buffer); + + +void write_dataset(hid_t group_id, int ndim, const hsize_t* dims, const char* name, + hid_t mem_type_id, const void* buffer, bool indep); extern "C" void write_double(hid_t group_id, int ndim, const hsize_t* dims, const char* name, const double* buffer, bool indep); extern "C" void write_int(hid_t group_id, int ndim, const hsize_t* dims, From ad3bb0b43acc4ec0ac8b338041205d9f37737904 Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Wed, 18 Apr 2018 22:54:51 -0500 Subject: [PATCH 32/77] Handle most writing of attributes in C++ --- src/hdf5_interface.F90 | 189 ++++++++++++----------------------------- src/hdf5_interface.cpp | 52 +++++++++++- src/hdf5_interface.h | 13 ++- 3 files changed, 115 insertions(+), 139 deletions(-) diff --git a/src/hdf5_interface.F90 b/src/hdf5_interface.F90 index 1d056e1dcd..bd14245526 100644 --- a/src/hdf5_interface.F90 +++ b/src/hdf5_interface.F90 @@ -105,6 +105,19 @@ module hdf5_interface integer(HID_T), value :: file_id end subroutine file_close + subroutine get_shape_c(obj_id, dims) bind(C, name='get_shape') + import HID_T, HSIZE_T + integer(HID_T), value :: obj_id + integer(HSIZE_T), intent(out) :: dims(*) + end subroutine get_shape_c + + subroutine get_shape_attr(obj_id, name, dims) bind(C) + import HID_T, HSIZE_T, C_CHAR + integer(HID_T), value :: obj_id + character(kind=C_CHAR), intent(in) :: name(*) + integer(HSIZE_T), intent(out) :: dims(*) + end subroutine get_shape_attr + subroutine read_double_c(obj_id, name, buffer, indep) & bind(C, name='read_double') import HID_T, C_DOUBLE, C_BOOL, C_PTR @@ -114,6 +127,22 @@ module hdf5_interface logical(C_BOOL), intent(in) :: indep end subroutine read_double_c + subroutine read_attr_int_c(obj_id, name, buffer) & + bind(C, name='read_attr_int') + import HID_T, C_CHAR, C_INT + integer(HID_T), value :: obj_id + character(kind=C_CHAR), intent(in) :: name(*) + integer(C_INT), intent(in) :: buffer(*) + end subroutine read_attr_int_c + + subroutine read_attr_double_c(obj_id, name, buffer) & + bind(C, name='read_attr_double') + import HID_T, C_CHAR, C_DOUBLE + integer(HID_T), value :: obj_id + character(kind=C_CHAR), intent(in) :: name(*) + real(C_DOUBLE), intent(in) :: buffer(*) + end subroutine read_attr_double_c + subroutine read_int_c(obj_id, name, buffer, indep) & bind(C, name='read_int') import HID_T, C_INT, C_BOOL, C_PTR @@ -1178,14 +1207,10 @@ contains integer(HID_T), intent(in) :: obj_id character(*), intent(in) :: name - integer :: hdf5_err - integer(HID_T) :: attr_id - type(c_ptr) :: f_ptr + real(C_DOUBLE) :: buffer_(1) - call h5aopen_f(obj_id, trim(name), attr_id, hdf5_err) - f_ptr = c_loc(buffer) - call h5aread_f(attr_id, H5T_NATIVE_DOUBLE, f_ptr, hdf5_err) - call h5aclose_f(attr_id, hdf5_err) + call read_attr_double_c(obj_id, to_c_string(name), buffer_) + buffer = buffer_(1) end subroutine read_attribute_double subroutine write_attribute_double(obj_id, name, buffer) @@ -1205,39 +1230,16 @@ contains integer(HID_T), intent(in) :: obj_id character(*), intent(in) :: name - integer :: hdf5_err - integer(HID_T) :: space_id - integer(HID_T) :: attr_id integer(HSIZE_T) :: dims(1) - integer(HSIZE_T) :: maxdims(1) - call h5aopen_f(obj_id, trim(name), attr_id, hdf5_err) - - if (allocated(buffer)) then - dims(:) = shape(buffer) - else - call h5aget_space_f(attr_id, space_id, hdf5_err) - call h5sget_simple_extent_dims_f(space_id, dims, maxdims, hdf5_err) + if (.not. allocated(buffer)) then + call get_shape_attr(obj_id, to_c_string(name), dims) allocate(buffer(dims(1))) - call h5sclose_f(space_id, hdf5_err) end if - call read_attribute_double_1D_explicit(attr_id, dims, buffer) - call h5aclose_f(attr_id, hdf5_err) + call read_attr_double_c(obj_id, to_c_string(name), buffer) end subroutine read_attribute_double_1D - subroutine read_attribute_double_1D_explicit(attr_id, dims, buffer) - integer(HID_T), intent(in) :: attr_id - integer(HSIZE_T), intent(in) :: dims(1) - real(8), target, intent(inout) :: buffer(dims(1)) - - integer :: hdf5_err - type(c_ptr) :: f_ptr - - f_ptr = c_loc(buffer) - call h5aread_f(attr_id, H5T_NATIVE_DOUBLE, f_ptr, hdf5_err) - end subroutine read_attribute_double_1D_explicit - subroutine write_attribute_double_1D(obj_id, name, buffer) integer(HID_T), intent(in) :: obj_id character(*), intent(in) :: name @@ -1254,52 +1256,25 @@ contains integer(HID_T), intent(in) :: obj_id character(*), intent(in) :: name - integer :: hdf5_err - integer(HID_T) :: space_id - integer(HID_T) :: attr_id integer(HSIZE_T) :: dims(2) - integer(HSIZE_T) :: maxdims(2) - call h5aopen_f(obj_id, trim(name), attr_id, hdf5_err) - - if (allocated(buffer)) then - dims(:) = shape(buffer) - else - call h5aget_space_f(attr_id, space_id, hdf5_err) - call h5sget_simple_extent_dims_f(space_id, dims, maxdims, hdf5_err) - allocate(buffer(dims(1), dims(2))) - call h5sclose_f(space_id, hdf5_err) + if (.not. allocated(buffer)) then + call get_shape_attr(obj_id, to_c_string(name), dims) + allocate(buffer(dims(2), dims(1))) end if - call read_attribute_double_2D_explicit(attr_id, dims, buffer) - call h5aclose_f(attr_id, hdf5_err) + call read_attr_double_c(obj_id, to_c_string(name), buffer) end subroutine read_attribute_double_2D - subroutine read_attribute_double_2D_explicit(attr_id, dims, buffer) - integer(HID_T), intent(in) :: attr_id - integer(HSIZE_T), intent(in) :: dims(2) - real(8), target, intent(inout) :: buffer(dims(1),dims(2)) - - integer :: hdf5_err - type(c_ptr) :: f_ptr - - f_ptr = c_loc(buffer) - call h5aread_f(attr_id, H5T_NATIVE_DOUBLE, f_ptr, hdf5_err) - end subroutine read_attribute_double_2D_explicit - subroutine read_attribute_integer(buffer, obj_id, name) integer, intent(inout), target :: buffer integer(HID_T), intent(in) :: obj_id character(*), intent(in) :: name - integer :: hdf5_err - integer(HID_T) :: attr_id - type(c_ptr) :: f_ptr + integer(C_INT) :: buffer_(1) - call h5aopen_f(obj_id, trim(name), attr_id, hdf5_err) - f_ptr = c_loc(buffer) - call h5aread_f(attr_id, H5T_NATIVE_INTEGER, f_ptr, hdf5_err) - call h5aclose_f(attr_id, hdf5_err) + call read_attr_int_c(obj_id, to_c_string(name), buffer_) + buffer = buffer_(1) end subroutine read_attribute_integer subroutine write_attribute_integer(obj_id, name, buffer) @@ -1319,39 +1294,16 @@ contains integer(HID_T), intent(in) :: obj_id character(*), intent(in) :: name - integer :: hdf5_err - integer(HID_T) :: space_id - integer(HID_T) :: attr_id integer(HSIZE_T) :: dims(1) - integer(HSIZE_T) :: maxdims(1) - call h5aopen_f(obj_id, trim(name), attr_id, hdf5_err) - - if (allocated(buffer)) then - dims(:) = shape(buffer) - else - call h5aget_space_f(attr_id, space_id, hdf5_err) - call h5sget_simple_extent_dims_f(space_id, dims, maxdims, hdf5_err) + if (.not. allocated(buffer)) then + call get_shape_attr(obj_id, to_c_string(name), dims) allocate(buffer(dims(1))) - call h5sclose_f(space_id, hdf5_err) end if - call read_attribute_integer_1D_explicit(attr_id, dims, buffer) - call h5aclose_f(attr_id, hdf5_err) + call read_attr_int_c(obj_id, to_c_string(name), buffer) end subroutine read_attribute_integer_1D - subroutine read_attribute_integer_1D_explicit(attr_id, dims, buffer) - integer(HID_T), intent(in) :: attr_id - integer(HSIZE_T), intent(in) :: dims(1) - integer, target, intent(inout) :: buffer(dims(1)) - - integer :: hdf5_err - type(c_ptr) :: f_ptr - - f_ptr = c_loc(buffer) - call h5aread_f(attr_id, H5T_NATIVE_INTEGER, f_ptr, hdf5_err) - end subroutine read_attribute_integer_1D_explicit - subroutine write_attribute_integer_1D(obj_id, name, buffer) integer(HID_T), intent(in) :: obj_id character(*), intent(in) :: name @@ -1368,39 +1320,16 @@ contains integer(HID_T), intent(in) :: obj_id character(*), intent(in) :: name - integer :: hdf5_err - integer(HID_T) :: space_id - integer(HID_T) :: attr_id integer(HSIZE_T) :: dims(2) - integer(HSIZE_T) :: maxdims(2) - call h5aopen_f(obj_id, trim(name), attr_id, hdf5_err) - - if (allocated(buffer)) then - dims(:) = shape(buffer) - else - call h5aget_space_f(attr_id, space_id, hdf5_err) - call h5sget_simple_extent_dims_f(space_id, dims, maxdims, hdf5_err) - allocate(buffer(dims(1), dims(2))) - call h5sclose_f(space_id, hdf5_err) + if (.not. allocated(buffer)) then + call get_shape_attr(obj_id, to_c_string(name), dims) + allocate(buffer(dims(2), dims(1))) end if - call read_attribute_integer_2D_explicit(attr_id, dims, buffer) - call h5aclose_f(attr_id, hdf5_err) + call read_attr_int_C(obj_id, to_c_string(name), buffer) end subroutine read_attribute_integer_2D - subroutine read_attribute_integer_2D_explicit(attr_id, dims, buffer) - integer(HID_T), intent(in) :: attr_id - integer(HSIZE_T), intent(in) :: dims(2) - integer, target, intent(inout) :: buffer(dims(1),dims(2)) - - integer :: hdf5_err - type(c_ptr) :: f_ptr - - f_ptr = c_loc(buffer) - call h5aread_f(attr_id, H5T_NATIVE_INTEGER, f_ptr, hdf5_err) - end subroutine read_attribute_integer_2D_explicit - subroutine read_attribute_string(buffer, obj_id, name) character(*), intent(inout) :: buffer ! read data to here integer(HID_T), intent(in) :: obj_id @@ -1533,21 +1462,13 @@ contains integer(HID_T), intent(in) :: obj_id integer(HSIZE_T), intent(out) :: dims(:) - integer :: hdf5_err - integer :: type - integer(HID_T) :: space_id - integer(HSIZE_T) :: maxdims(size(dims)) + integer :: i + integer(HSIZE_T) :: dims_c(size(dims)) - call h5iget_type_f(obj_id, type, hdf5_err) - if (type == H5I_DATASET_F) then - call h5dget_space_f(obj_id, space_id, hdf5_err) - call h5sget_simple_extent_dims_f(space_id, dims, maxdims, hdf5_err) - call h5sclose_f(space_id, hdf5_err) - elseif (type == H5I_ATTR_F) then - call h5aget_space_f(obj_id, space_id, hdf5_err) - call h5sget_simple_extent_dims_f(space_id, dims, maxdims, hdf5_err) - call h5sclose_f(space_id, hdf5_err) - end if + call get_shape_c(obj_id, dims_c) + do i = 1, size(dims) + dims(i) = dims_c(size(dims) - i + 1) + end do end subroutine get_shape subroutine get_ndims(obj_id, ndims) diff --git a/src/hdf5_interface.cpp b/src/hdf5_interface.cpp index f482285f26..3e906a94ab 100644 --- a/src/hdf5_interface.cpp +++ b/src/hdf5_interface.cpp @@ -31,6 +31,32 @@ using_mpio_device(hid_t obj_id) } +void +get_shape(hid_t obj_id, hsize_t* dims) +{ + auto type = H5Iget_type(obj_id); + hid_t dspace; + if (type == H5I_DATASET) { + dspace = H5Dget_space(obj_id); + } else if (type == H5I_ATTR) { + dspace = H5Aget_space(obj_id); + } + H5Sget_simple_extent_dims(dspace, dims, nullptr); + H5Sclose(dspace); +} + + +void +get_shape_attr(hid_t obj_id, const char* name, hsize_t* dims) +{ + hid_t attr = H5Aopen(obj_id, name, H5P_DEFAULT); + hid_t dspace = H5Aget_space(attr); + H5Sget_simple_extent_dims(dspace, dims, nullptr); + H5Sclose(dspace); + H5Aclose(attr); +} + + hid_t create_group(hid_t parent_id, char const *name) { @@ -159,10 +185,32 @@ open_group(hid_t group_id, const char* name) } } +void +read_attr(hid_t obj_id, const char* name, hid_t mem_type_id, void* buffer) +{ + hid_t attr = H5Aopen(obj_id, name, H5P_DEFAULT); + H5Aread(attr, mem_type_id, buffer); + H5Aclose(attr); +} + + +void +read_attr_double(hid_t obj_id, const char* name, double* buffer) +{ + read_attr(obj_id, name, H5T_NATIVE_DOUBLE, buffer); +} + + +void +read_attr_int(hid_t obj_id, const char* name, int* buffer) +{ + read_attr(obj_id, name, H5T_NATIVE_INT, buffer); +} + void read_dataset(hid_t obj_id, const char* name, hid_t mem_type_id, - void* buffer, bool indep) + void* buffer, bool indep) { hid_t dset = obj_id; if (name) dset = H5Dopen(obj_id, name, H5P_DEFAULT); @@ -176,7 +224,7 @@ read_dataset(hid_t obj_id, const char* name, hid_t mem_type_id, hid_t plist = H5Pcreate(H5P_DATASET_XFER); H5Pset_dxpl_mpio(plist, data_xfer_mode); - // Write data + // Read data H5Dread(dset, mem_type_id, H5S_ALL, H5S_ALL, plist, buffer); H5Pclose(plist); #endif diff --git a/src/hdf5_interface.h b/src/hdf5_interface.h index 615bed24c7..ca5e27e7e8 100644 --- a/src/hdf5_interface.h +++ b/src/hdf5_interface.h @@ -11,7 +11,6 @@ namespace openmc { -bool using_mpio_device(hid_t obj_id); hid_t create_group(hid_t parent_id, const char* name); hid_t create_group(hid_t parent_id, const std::string& name); void close_dataset(hid_t dataset_id); @@ -19,9 +18,12 @@ void close_group(hid_t group_id); extern "C" hid_t file_open(const char* filename, char mode, bool parallel); hid_t file_open(const std::string& filename, char mode, bool parallel); extern "C" void file_close(hid_t file_id); +extern "C" void get_shape(hid_t obj_if, hsize_t* dims); +extern "C" void get_shape_attr(hid_t obj_if, const char* name, hsize_t* dims); bool object_exists(hid_t object_id, const char* name); hid_t open_dataset(hid_t group_id, const char* name); hid_t open_group(hid_t group_id, const char* name); +bool using_mpio_device(hid_t obj_id); template void @@ -41,8 +43,13 @@ write_double_1D(hid_t group_id, char const *name, H5Dclose(dataset); } -void read_dataset(hid_t obj_id, const char* name, double* buffer, - hid_t mem_type_id, bool indep); +void read_attr(hid_t obj_id, const char* name, hid_t mem_type_id, + const void* buffer); +extern "C" void read_attr_double(hid_t obj_id, const char* name, double* buffer); +extern "C" void read_attr_int(hid_t obj_id, const char* name, int* buffer); + +void read_dataset(hid_t obj_id, const char* name, hid_t mem_type_id, + void* buffer, bool indep); extern "C" void read_double(hid_t obj_id, const char* name, double* buffer, bool indep); extern "C" void read_int(hid_t obj_id, const char* name, int* buffer, From 422edace492afbe6b9c0a282aa43ad198dcc326d Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Wed, 18 Apr 2018 23:08:43 -0500 Subject: [PATCH 33/77] Use dataset_ndims and object_exists from C++ --- src/hdf5_interface.F90 | 34 ++++++++++++++++++---------------- src/hdf5_interface.cpp | 12 ++++++++++++ src/hdf5_interface.h | 3 ++- 3 files changed, 32 insertions(+), 17 deletions(-) diff --git a/src/hdf5_interface.F90 b/src/hdf5_interface.F90 index bd14245526..56da0def1f 100644 --- a/src/hdf5_interface.F90 +++ b/src/hdf5_interface.F90 @@ -331,11 +331,18 @@ contains character(*), intent(in) :: name ! name of group logical :: exists - integer :: hdf5_err ! HDF5 error code + interface + function object_exists_c(obj_id, name) result(exists) & + bind(C, name='object_exists') + import HID_T, C_CHAR, C_BOOL + integer(HID_T), value :: obj_id + character(kind=C_CHAR), intent(in) :: name(*) + logical(C_BOOL) :: exists + end function object_exists_c + end interface ! Check if group exists - call h5ltpath_valid_f(object_id, trim(name), .true., exists, hdf5_err) - + exists = object_exists_c(object_id, to_c_string(name)) end function object_exists !=============================================================================== @@ -1475,20 +1482,15 @@ contains integer(HID_T), intent(in) :: obj_id integer, intent(out) :: ndims - integer :: hdf5_err - integer :: type - integer(HID_T) :: space_id + interface + function dataset_ndims(dset) result(ndims) bind(C) + import HID_T, C_INT + integer(HID_T), value :: dset + integer(C_INT) :: ndims + end function dataset_ndims + end interface - call h5iget_type_f(obj_id, type, hdf5_err) - if (type == H5I_DATASET_F) then - call h5dget_space_f(obj_id, space_id, hdf5_err) - call h5sget_simple_extent_ndims_f(space_id, ndims, hdf5_err) - call h5sclose_f(space_id, hdf5_err) - elseif (type == H5I_ATTR_F) then - call h5aget_space_f(obj_id, space_id, hdf5_err) - call h5sget_simple_extent_ndims_f(space_id, ndims, hdf5_err) - call h5sclose_f(space_id, hdf5_err) - end if + ndims = dataset_ndims(obj_id) end subroutine get_ndims function using_mpio_device(obj_id) result(mpio) diff --git a/src/hdf5_interface.cpp b/src/hdf5_interface.cpp index 3e906a94ab..8fef1bd951 100644 --- a/src/hdf5_interface.cpp +++ b/src/hdf5_interface.cpp @@ -69,12 +69,14 @@ create_group(hid_t parent_id, char const *name) return out; } + hid_t create_group(hid_t parent_id, const std::string &name) { return create_group(parent_id, name.c_str()); } + void close_dataset(hid_t dataset_id) { @@ -89,6 +91,16 @@ close_group(hid_t group_id) } +int +dataset_ndims(hid_t dset) +{ + hid_t dspace = H5Dget_space(dset); + int ndims = H5Sget_simple_extent_ndims(dspace); + H5Sclose(dspace); + return ndims; +} + + hid_t file_open(const char* filename, char mode, bool parallel) { diff --git a/src/hdf5_interface.h b/src/hdf5_interface.h index ca5e27e7e8..6759ffc64a 100644 --- a/src/hdf5_interface.h +++ b/src/hdf5_interface.h @@ -15,12 +15,13 @@ hid_t create_group(hid_t parent_id, const char* name); hid_t create_group(hid_t parent_id, const std::string& name); void close_dataset(hid_t dataset_id); void close_group(hid_t group_id); +extern "C" int dataset_ndims(hid_t dset); extern "C" hid_t file_open(const char* filename, char mode, bool parallel); hid_t file_open(const std::string& filename, char mode, bool parallel); extern "C" void file_close(hid_t file_id); extern "C" void get_shape(hid_t obj_if, hsize_t* dims); extern "C" void get_shape_attr(hid_t obj_if, const char* name, hsize_t* dims); -bool object_exists(hid_t object_id, const char* name); +extern "C" bool object_exists(hid_t object_id, const char* name); hid_t open_dataset(hid_t group_id, const char* name); hid_t open_group(hid_t group_id, const char* name); bool using_mpio_device(hid_t obj_id); From 05fcd993c27137e182479ab754e0a025e610086e Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Thu, 19 Apr 2018 07:47:23 -0500 Subject: [PATCH 34/77] Convert HDF5 read_complex to C++ --- src/hdf5_interface.F90 | 96 ++++++++---------------------------------- src/hdf5_interface.cpp | 23 +++++++++- src/hdf5_interface.h | 3 ++ 3 files changed, 43 insertions(+), 79 deletions(-) diff --git a/src/hdf5_interface.F90 b/src/hdf5_interface.F90 index 56da0def1f..b0b3d1006a 100644 --- a/src/hdf5_interface.F90 +++ b/src/hdf5_interface.F90 @@ -161,6 +161,15 @@ module hdf5_interface logical(C_BOOL), intent(in) :: indep end subroutine read_llong_c + subroutine read_complex_c(obj_id, name, buffer, indep) & + bind(C, name='read_complex') + import HID_T, C_PTR, C_DOUBLE_COMPLEX, C_BOOL + integer(HID_T), value :: obj_id + type(C_PTR), value :: name + complex(C_DOUBLE_COMPLEX), intent(in) :: buffer(*) + logical(C_BOOL), intent(in) :: indep + end subroutine read_complex_c + subroutine write_attr_double_c(obj_id, ndim, dims, name, buffer) & bind(C, name='write_attr_double') import HID_T, HSIZE_T, C_INT, C_DOUBLE, C_CHAR @@ -1527,94 +1536,25 @@ contains !=============================================================================== subroutine read_complex_2D(buffer, obj_id, name, indep) - complex(8), target, intent(inout) :: buffer(:,:) + complex(C_DOUBLE_COMPLEX), target, intent(inout) :: buffer(:,:) integer(HID_T), intent(in) :: obj_id character(*), optional, intent(in) :: name logical, optional, intent(in) :: indep ! independent I/O - integer :: hdf5_err - integer(HID_T) :: dset_id - integer(HSIZE_T) :: dims(2) + logical(C_BOOL) :: indep_ + character(kind=C_CHAR), target, allocatable :: name_(:) + + indep_ = .false. + if (present(indep)) indep_ = indep ! If 'name' argument is passed, obj_id is interpreted to be a group and ! 'name' is the name of the dataset we should read from if (present(name)) then - call h5dopen_f(obj_id, trim(name), dset_id, hdf5_err) + name_ = to_c_string(name) + call read_complex_c(obj_id, c_loc(name_), buffer, indep_) else - dset_id = obj_id + call read_complex_c(obj_id, C_NULL_PTR, buffer, indep_) end if - - dims(:) = shape(buffer) - - if (present(indep)) then - call read_complex_2D_explicit(dset_id, dims, buffer, indep) - else - call read_complex_2D_explicit(dset_id, dims, buffer) - end if - - if (present(name)) call h5dclose_f(dset_id, hdf5_err) end subroutine read_complex_2D - subroutine read_complex_2D_explicit(dset_id, dims, buffer, indep) - integer(HID_T), intent(in) :: dset_id - integer(HSIZE_T), intent(in) :: dims(2) - complex(8), target, intent(inout) :: buffer(dims(1), dims(2)) - logical, optional, intent(in) :: indep ! independent I/O - - real(8), target :: buffer_r(dims(1), dims(2)) - real(8), target :: buffer_i(dims(1), dims(2)) - - integer(HSIZE_T) :: i, j - - integer :: hdf5_err - integer :: data_xfer_mode -#ifdef PHDF5 - integer(HID_T) :: plist ! property list -#endif - type(c_ptr) :: f_ptr_r, f_ptr_i - - ! Components needed for complex type support - integer(HID_T) :: dtype_real - integer(HID_T) :: dtype_imag - integer(SIZE_T) :: size_double - - ! Create the complex type - call h5tget_size_f(H5T_NATIVE_DOUBLE, size_double, hdf5_err) - - ! Insert the 'r' and 'i' identifiers - call h5tcreate_f(H5T_COMPOUND_F, size_double, dtype_real, hdf5_err) - call h5tcreate_f(H5T_COMPOUND_F, size_double, dtype_imag, hdf5_err) - call h5tinsert_f(dtype_real, "r", 0_SIZE_T, H5T_NATIVE_DOUBLE, hdf5_err) - call h5tinsert_f(dtype_imag, "i", 0_SIZE_T, H5T_NATIVE_DOUBLE, hdf5_err) - - ! Set up collective vs. independent I/O - data_xfer_mode = H5FD_MPIO_COLLECTIVE_F - if (present(indep)) then - if (indep) data_xfer_mode = H5FD_MPIO_INDEPENDENT_F - end if - - f_ptr_r = c_loc(buffer_r) - f_ptr_i = c_loc(buffer_i) - - if (using_mpio_device(dset_id)) then -#ifdef PHDF5 - call h5pcreate_f(H5P_DATASET_XFER_F, plist, hdf5_err) - call h5pset_dxpl_mpio_f(plist, data_xfer_mode, hdf5_err) - call h5dread_f(dset_id, dtype_real, f_ptr_r, hdf5_err, xfer_prp=plist) - call h5dread_f(dset_id, dtype_imag, f_ptr_i, hdf5_err, xfer_prp=plist) - call h5pclose_f(plist, hdf5_err) -#endif - else - call h5dread_f(dset_id, dtype_real, f_ptr_r, hdf5_err) - call h5dread_f(dset_id, dtype_imag, f_ptr_i, hdf5_err) - end if - - ! Reconstitute the complex numbers - do i = 1, dims(1) - do j = 1, dims(2) - buffer(i, j) = cmplx(buffer_r(i,j), buffer_i(i,j), kind=8) - end do - end do - end subroutine read_complex_2D_explicit - end module hdf5_interface diff --git a/src/hdf5_interface.cpp b/src/hdf5_interface.cpp index 8fef1bd951..c75ec31aa2 100644 --- a/src/hdf5_interface.cpp +++ b/src/hdf5_interface.cpp @@ -269,6 +269,27 @@ read_llong(hid_t obj_id, const char* name, long long* buffer, bool indep) } +void +read_complex(hid_t obj_id, const char* name, double _Complex* buffer, bool indep) +{ + // Create compound datatype for complex numbers + struct complex_t { + double re; + double im; + }; + complex_t tmp; + hid_t complex_id = H5Tcreate(H5T_COMPOUND, sizeof tmp); + H5Tinsert(complex_id, "r", HOFFSET(complex_t, re), H5T_NATIVE_DOUBLE); + H5Tinsert(complex_id, "i", HOFFSET(complex_t, im), H5T_NATIVE_DOUBLE); + + // Read data + read_dataset(obj_id, name, complex_id, buffer, indep); + + // Free resources + H5Tclose(complex_id); +} + + void write_attr(hid_t obj_id, int ndim, const hsize_t* dims, const char* name, hid_t mem_type_id, const void* buffer) @@ -412,4 +433,4 @@ write_string(hid_t group_id, char const* name, const std::string& buffer, bool i write_string(group_id, 0, nullptr, buffer.length(), name, buffer.c_str(), indep); } -} +} // namespace openmc diff --git a/src/hdf5_interface.h b/src/hdf5_interface.h index 6759ffc64a..785548e89c 100644 --- a/src/hdf5_interface.h +++ b/src/hdf5_interface.h @@ -7,6 +7,7 @@ #include #include #include +#include namespace openmc { @@ -57,6 +58,8 @@ extern "C" void read_int(hid_t obj_id, const char* name, int* buffer, bool indep); extern "C" void read_llong(hid_t obj_id, const char* name, long long* buffer, bool indep); +extern "C" void read_complex(hid_t obj_id, const char* name, + double _Complex* buffer, bool indep); void write_attr(hid_t obj_id, int ndim, const hsize_t* dims, const char* name, hid_t mem_type_id, const void* buffer); From 66bc225fa3b83bb0aa8ff60067cc9461d549fa52 Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Thu, 19 Apr 2018 10:17:48 -0500 Subject: [PATCH 35/77] Convert open/close_dataset/group --- src/hdf5_interface.F90 | 90 +++++++++++++++++++++--------------------- src/hdf5_interface.h | 10 ++--- 2 files changed, 50 insertions(+), 50 deletions(-) diff --git a/src/hdf5_interface.F90 b/src/hdf5_interface.F90 index b0b3d1006a..73b052e747 100644 --- a/src/hdf5_interface.F90 +++ b/src/hdf5_interface.F90 @@ -422,18 +422,17 @@ contains character(*), intent(in) :: name ! name of group integer(HID_T) :: newgroup_id - logical :: exists ! does the group exist - integer :: hdf5_err ! HDF5 error code + interface + function open_group_c(group_id, name) result(newgroup_id) & + bind(C, name='open_group') + import HID_T, C_CHAR + integer(HID_T), value :: group_id + character(kind=C_CHAR), intent(in) :: name(*) + integer(HID_T) :: newgroup_id + end function open_group_c + end interface - ! Check if group exists - exists = object_exists(group_id, name) - - ! open group if it exists - if (exists) then - call h5gopen_f(group_id, trim(name), newgroup_id, hdf5_err) - else - call fatal_error("The group '" // trim(name) // "' does not exist.") - end if + newgroup_id = open_group_c(group_id, to_c_string(name)) end function open_group !=============================================================================== @@ -445,18 +444,17 @@ contains character(*), intent(in) :: name ! name of group integer(HID_T) :: newgroup_id - integer :: hdf5_err ! HDF5 error code - logical :: exists ! does the group exist + interface + function create_group_c(group_id, name) result(newgroup_id) & + bind(C, name='create_group') + import HID_T, C_CHAR + integer(HID_T), value :: group_id + character(kind=C_CHAR), intent(in) :: name(*) + integer(HID_T) :: newgroup_id + end function create_group_c + end interface - ! Check if group exists - exists = object_exists(group_id, name) - - ! create group - if (exists) then - call fatal_error("The group '" // trim(name) // "' already exists.") - else - call h5gcreate_f(group_id, trim(name), newgroup_id, hdf5_err) - end if + newgroup_id = create_group_c(group_id, to_c_string(name)) end function create_group !=============================================================================== @@ -465,13 +463,14 @@ contains subroutine close_group(group_id) integer(HID_T), intent(inout) :: group_id + interface + subroutine close_group_c(group_id) bind(C, name='close_group') + import HID_T + integer(HID_T), value :: group_id + end subroutine close_group_c + end interface - integer :: hdf5_err ! HDF5 error code - - call h5gclose_f(group_id, hdf5_err) - if (hdf5_err < 0) then - call fatal_error("Unable to close HDF5 group.") - end if + call close_group_c(group_id) end subroutine close_group !=============================================================================== @@ -483,33 +482,34 @@ contains character(*), intent(in) :: name ! name of dataset integer(HID_T) :: dataset_id - logical :: exists ! does the dataset exist - integer :: hdf5_err ! HDF5 error code + interface + function open_dataset_c(group_id, name) result(dset_id) & + bind(C, name='open_dataset') + import HID_T, C_CHAR + integer(HID_T), value :: group_id + character(kind=C_CHAR), intent(in) :: name(*) + integer(HID_T) :: dset_id + end function open_dataset_c + end interface - ! Check if group exists - exists = object_exists(group_id, name) - - ! open group if it exists - if (exists) then - call h5dopen_f(group_id, trim(name), dataset_id, hdf5_err) - else - call fatal_error("The dataset '" // trim(name) // "' does not exist.") - end if + dataset_id = open_dataset_c(group_id, to_c_string(name)) end function open_dataset !=============================================================================== -! CLOSE_GROUP closes HDF5 temp_group +! CLOSE_DATASET closes an HDF5 dataset !=============================================================================== subroutine close_dataset(dataset_id) integer(HID_T), intent(inout) :: dataset_id - integer :: hdf5_err ! HDF5 error code + interface + subroutine close_dataset_c(dset_id) bind(C, name='close_dataset') + import HID_T + integer(HID_T), value :: dset_id + end subroutine close_dataset_c + end interface - call h5dclose_f(dataset_id, hdf5_err) - if (hdf5_err < 0) then - call fatal_error("Unable to close HDF5 dataset.") - end if + call close_dataset_c(dataset_id) end subroutine close_dataset !=============================================================================== diff --git a/src/hdf5_interface.h b/src/hdf5_interface.h index 785548e89c..69cd7adaac 100644 --- a/src/hdf5_interface.h +++ b/src/hdf5_interface.h @@ -12,10 +12,10 @@ namespace openmc { -hid_t create_group(hid_t parent_id, const char* name); +extern "C" hid_t create_group(hid_t parent_id, const char* name); hid_t create_group(hid_t parent_id, const std::string& name); -void close_dataset(hid_t dataset_id); -void close_group(hid_t group_id); +extern "C" void close_dataset(hid_t dataset_id); +extern "C" void close_group(hid_t group_id); extern "C" int dataset_ndims(hid_t dset); extern "C" hid_t file_open(const char* filename, char mode, bool parallel); hid_t file_open(const std::string& filename, char mode, bool parallel); @@ -23,8 +23,8 @@ extern "C" void file_close(hid_t file_id); extern "C" void get_shape(hid_t obj_if, hsize_t* dims); extern "C" void get_shape_attr(hid_t obj_if, const char* name, hsize_t* dims); extern "C" bool object_exists(hid_t object_id, const char* name); -hid_t open_dataset(hid_t group_id, const char* name); -hid_t open_group(hid_t group_id, const char* name); +extern "C" hid_t open_dataset(hid_t group_id, const char* name); +extern "C" hid_t open_group(hid_t group_id, const char* name); bool using_mpio_device(hid_t obj_id); From b8635f1c2ba4157d4a323845802b7bb8793f54a1 Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Thu, 19 Apr 2018 10:59:33 -0500 Subject: [PATCH 36/77] Convert HDF5 read_string to C++ --- src/hdf5_interface.F90 | 89 +++++++++++++++++------------------------- src/hdf5_interface.cpp | 27 ++++++++++++- src/hdf5_interface.h | 3 ++ 3 files changed, 64 insertions(+), 55 deletions(-) diff --git a/src/hdf5_interface.F90 b/src/hdf5_interface.F90 index 73b052e747..a0148cfd2d 100644 --- a/src/hdf5_interface.F90 +++ b/src/hdf5_interface.F90 @@ -100,6 +100,12 @@ module hdf5_interface public :: get_name interface + function dataset_typesize(dset) result(sz) bind(C) + import HID_T, SIZE_T + integer(HID_T), value :: dset + integer(SIZE_T) :: sz + end function dataset_typesize + subroutine file_close(file_id) bind(C) import HID_T integer(HID_T), value :: file_id @@ -123,7 +129,7 @@ module hdf5_interface import HID_T, C_DOUBLE, C_BOOL, C_PTR integer(HID_T), value :: obj_id type(C_PTR), value :: name - real(C_DOUBLE), intent(in) :: buffer(*) + real(C_DOUBLE), intent(out) :: buffer(*) logical(C_BOOL), intent(in) :: indep end subroutine read_double_c @@ -132,7 +138,7 @@ module hdf5_interface import HID_T, C_CHAR, C_INT integer(HID_T), value :: obj_id character(kind=C_CHAR), intent(in) :: name(*) - integer(C_INT), intent(in) :: buffer(*) + integer(C_INT), intent(out) :: buffer(*) end subroutine read_attr_int_c subroutine read_attr_double_c(obj_id, name, buffer) & @@ -140,7 +146,7 @@ module hdf5_interface import HID_T, C_CHAR, C_DOUBLE integer(HID_T), value :: obj_id character(kind=C_CHAR), intent(in) :: name(*) - real(C_DOUBLE), intent(in) :: buffer(*) + real(C_DOUBLE), intent(out) :: buffer(*) end subroutine read_attr_double_c subroutine read_int_c(obj_id, name, buffer, indep) & @@ -148,7 +154,7 @@ module hdf5_interface import HID_T, C_INT, C_BOOL, C_PTR integer(HID_T), value :: obj_id type(C_PTR), value :: name - integer(C_INT), intent(in) :: buffer(*) + integer(C_INT), intent(out) :: buffer(*) logical(C_BOOL), intent(in) :: indep end subroutine read_int_c @@ -157,16 +163,26 @@ module hdf5_interface import HID_T, C_INT, C_BOOL, C_PTR, C_LONG_LONG integer(HID_T), value :: obj_id type(C_PTR), value :: name - integer(C_LONG_LONG), intent(in) :: buffer(*) + integer(C_LONG_LONG), intent(out) :: buffer(*) logical(C_BOOL), intent(in) :: indep end subroutine read_llong_c + subroutine read_string_c(obj_id, name, slen, buffer, indep) & + bind(C, name='read_string') + import HID_T, C_PTR, C_SIZE_T, C_CHAR, C_BOOL + integer(HID_T), value :: obj_id + type(C_PTR), value :: name + integer(C_SIZE_T), value :: slen + character(kind=C_CHAR), intent(out) :: buffer(*) + logical(C_BOOL), intent(in) :: indep + end subroutine read_string_c + subroutine read_complex_c(obj_id, name, buffer, indep) & bind(C, name='read_complex') import HID_T, C_PTR, C_DOUBLE_COMPLEX, C_BOOL integer(HID_T), value :: obj_id type(C_PTR), value :: name - complex(C_DOUBLE_COMPLEX), intent(in) :: buffer(*) + complex(C_DOUBLE_COMPLEX), intent(out) :: buffer(*) logical(C_BOOL), intent(in) :: indep end subroutine read_complex_c @@ -1019,67 +1035,32 @@ contains character(*), optional, intent(in) :: name logical, optional, intent(in) :: indep ! independent I/O - integer :: hdf5_err - integer :: data_xfer_mode -#ifdef PHDF5 - integer(HID_T) :: plist ! property list -#endif integer(HID_T) :: dset_id - integer(HID_T) :: filetype - integer(HID_T) :: memtype integer(SIZE_T) :: i, n - character(kind=C_CHAR), allocatable, target :: temp_buffer(:) - type(c_ptr) :: f_ptr + logical(C_BOOL) :: indep_ + character(kind=C_CHAR), allocatable, target :: buffer_(:) if (present(name)) then - call h5dopen_f(obj_id, trim(name), dset_id, hdf5_err) + dset_id = open_dataset(obj_id, name) else dset_id = obj_id end if - ! Set up collective vs. independent I/O - data_xfer_mode = H5FD_MPIO_COLLECTIVE_F - if (present(indep)) then - if (indep) data_xfer_mode = H5FD_MPIO_INDEPENDENT_F - end if + ! Allocate a C char array to get string + n = dataset_typesize(dset_id) + allocate(buffer_(n)) - ! Make sure buffer is large enough - call h5dget_type_f(dset_id, filetype, hdf5_err) - call h5tget_size_f(filetype, n, hdf5_err) - if (n > len(buffer)) then - call fatal_error("Character buffer is not long enough to & - &read HDF5 string.") - end if - - ! Get datatype in memory based on Fortran character - call h5tcopy_f(H5T_C_S1, memtype, hdf5_err) - call h5tset_size_f(memtype, n + 1, hdf5_err) - - ! Get pointer to start of string - allocate(temp_buffer(n)) - f_ptr = c_loc(temp_buffer(1)) - - if (using_mpio_device(dset_id)) then -#ifdef PHDF5 - call h5pcreate_f(H5P_DATASET_XFER_F, plist, hdf5_err) - call h5pset_dxpl_mpio_f(plist, data_xfer_mode, hdf5_err) - call h5dread_f(dset_id, memtype, f_ptr, hdf5_err, xfer_prp=plist) - call h5pclose_f(plist, hdf5_err) -#endif - else - call h5dread_f(dset_id, memtype, f_ptr, hdf5_err) - end if + indep_ = .false. + if (present(indep)) indep_ = indep + call read_string_c(dset_id, C_NULL_PTR, n, buffer_, indep_) buffer = '' do i = 1, n - if (temp_buffer(i) == C_NULL_CHAR) cycle - buffer(i:i) = temp_buffer(i) + if (buffer_(i) == C_NULL_CHAR) cycle + buffer(i:i) = buffer_(i) end do - if (present(name)) call h5dclose_f(dset_id, hdf5_err) - - call h5tclose_f(filetype, hdf5_err) - call h5tclose_f(memtype, hdf5_err) + call close_dataset(dset_id) end subroutine read_string !=============================================================================== @@ -1343,7 +1324,7 @@ contains allocate(buffer(dims(2), dims(1))) end if - call read_attr_int_C(obj_id, to_c_string(name), buffer) + call read_attr_int_c(obj_id, to_c_string(name), buffer) end subroutine read_attribute_integer_2D subroutine read_attribute_string(buffer, obj_id, name) diff --git a/src/hdf5_interface.cpp b/src/hdf5_interface.cpp index c75ec31aa2..bf410923b6 100644 --- a/src/hdf5_interface.cpp +++ b/src/hdf5_interface.cpp @@ -101,6 +101,16 @@ dataset_ndims(hid_t dset) } +size_t +dataset_typesize(hid_t dset) +{ + hid_t filetype = H5Dget_type(dset); + size_t n = H5Tget_size(filetype); + H5Tclose(filetype); + return n; +} + + hid_t file_open(const char* filename, char mode, bool parallel) { @@ -225,7 +235,7 @@ read_dataset(hid_t obj_id, const char* name, hid_t mem_type_id, void* buffer, bool indep) { hid_t dset = obj_id; - if (name) dset = H5Dopen(obj_id, name, H5P_DEFAULT); + if (name) dset = open_dataset(obj_id, name); if (using_mpio_device(dset)) { #ifdef PHDF5 @@ -269,6 +279,21 @@ read_llong(hid_t obj_id, const char* name, long long* buffer, bool indep) } +void +read_string(hid_t obj_id, const char* name, size_t slen, char* buffer, bool indep) +{ + // Create datatype for a string + hid_t datatype = H5Tcopy(H5T_C_S1); + H5Tset_size(datatype, slen + 1); + + // Read data into buffer + read_dataset(obj_id, name, datatype, buffer, indep); + + // Free resources + H5Tclose(datatype); +} + + void read_complex(hid_t obj_id, const char* name, double _Complex* buffer, bool indep) { diff --git a/src/hdf5_interface.h b/src/hdf5_interface.h index 69cd7adaac..fdaf9ac8fc 100644 --- a/src/hdf5_interface.h +++ b/src/hdf5_interface.h @@ -17,6 +17,7 @@ hid_t create_group(hid_t parent_id, const std::string& name); extern "C" void close_dataset(hid_t dataset_id); extern "C" void close_group(hid_t group_id); extern "C" int dataset_ndims(hid_t dset); +extern "C" size_t dataset_typesize(hid_t dset); extern "C" hid_t file_open(const char* filename, char mode, bool parallel); hid_t file_open(const std::string& filename, char mode, bool parallel); extern "C" void file_close(hid_t file_id); @@ -58,6 +59,8 @@ extern "C" void read_int(hid_t obj_id, const char* name, int* buffer, bool indep); extern "C" void read_llong(hid_t obj_id, const char* name, long long* buffer, bool indep); +extern "C" void read_string(hid_t obj_id, const char* name, size_t slen, + char* buffer, bool indep); extern "C" void read_complex(hid_t obj_id, const char* name, double _Complex* buffer, bool indep); From 1cb46effda75c250c58da506b3b58582e7c8e540 Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Thu, 19 Apr 2018 11:07:27 -0500 Subject: [PATCH 37/77] Convert HDF5 attribute_exists to C++ --- src/hdf5_interface.F90 | 16 +++++++++++----- src/hdf5_interface.cpp | 8 ++++++++ src/hdf5_interface.h | 1 + 3 files changed, 20 insertions(+), 5 deletions(-) diff --git a/src/hdf5_interface.F90 b/src/hdf5_interface.F90 index a0148cfd2d..eee5397671 100644 --- a/src/hdf5_interface.F90 +++ b/src/hdf5_interface.F90 @@ -332,7 +332,7 @@ contains end subroutine get_groups !=============================================================================== -! CHECK_ATTRIBUTE Checks to see if an attribute exists in the object +! ATTRIBUTE_EXISTS checks to see if an attribute exists in the object !=============================================================================== function attribute_exists(object_id, name) result(exists) @@ -340,11 +340,17 @@ contains character(*), intent(in) :: name ! name of group logical :: exists - integer :: hdf5_err ! HDF5 error code - - ! Check if attribute exists - call h5aexists_by_name_f(object_id, '.', trim(name), exists, hdf5_err) + interface + function attribute_exists_c(obj_id, name) result(exists) & + bind(C, name='attribute_exists') + import HID_T, C_CHAR, C_BOOL + integer(HID_T), value :: obj_id + character(kind=C_CHAR), intent(in) :: name(*) + logical(C_BOOL) :: exists + end function attribute_exists_c + end interface + exists = attribute_exists_c(object_id, to_c_string(name)) end function attribute_exists !=============================================================================== diff --git a/src/hdf5_interface.cpp b/src/hdf5_interface.cpp index bf410923b6..aa44e7c972 100644 --- a/src/hdf5_interface.cpp +++ b/src/hdf5_interface.cpp @@ -11,6 +11,14 @@ namespace openmc { +bool +attribute_exists(hid_t obj_id, const char* name) +{ + htri_t out = H5Aexists_by_name(obj_id, ".", name, H5P_DEFAULT); + return out > 0; +} + + bool using_mpio_device(hid_t obj_id) { diff --git a/src/hdf5_interface.h b/src/hdf5_interface.h index fdaf9ac8fc..2e470dbc7d 100644 --- a/src/hdf5_interface.h +++ b/src/hdf5_interface.h @@ -12,6 +12,7 @@ namespace openmc { +extern "C" bool attribute_exists(hid_t obj_id, const char* name); extern "C" hid_t create_group(hid_t parent_id, const char* name); hid_t create_group(hid_t parent_id, const std::string& name); extern "C" void close_dataset(hid_t dataset_id); From 95b05ef02de570432101daa48a884ec70346c358 Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Thu, 19 Apr 2018 11:33:24 -0500 Subject: [PATCH 38/77] Convert HDF5 read_string_1D to C++ --- src/hdf5_interface.F90 | 96 +++++++++++------------------------------- 1 file changed, 24 insertions(+), 72 deletions(-) diff --git a/src/hdf5_interface.F90 b/src/hdf5_interface.F90 index eee5397671..1cf2522598 100644 --- a/src/hdf5_interface.F90 +++ b/src/hdf5_interface.F90 @@ -1111,87 +1111,39 @@ contains character(*), optional, intent(in) :: name logical, optional, intent(in) :: indep ! independent I/O - integer :: hdf5_err - integer(HID_T) :: dset_id - integer(HSIZE_T) :: dims(1) + integer(HID_T) :: dset_id + integer(SIZE_T) :: i, j, k, n, m + logical(C_BOOL) :: indep_ + character(kind=C_CHAR), allocatable, target :: buffer_(:) - ! If 'name' argument is passed, obj_id is interpreted to be a group and - ! 'name' is the name of the dataset we should read from if (present(name)) then - call h5dopen_f(obj_id, trim(name), dset_id, hdf5_err) + dset_id = open_dataset(obj_id, name) else dset_id = obj_id end if - dims(:) = shape(buffer) + ! Allocate a C char array to get strings + n = dataset_typesize(dset_id) + m = size(buffer) + allocate(buffer_(n*m)) - if (present(indep)) then - call read_string_1D_explicit(dset_id, dims, buffer, indep) - else - call read_string_1D_explicit(dset_id, dims, buffer) - end if + indep_ = .false. + if (present(indep)) indep_ = indep + call read_string_c(dset_id, C_NULL_PTR, n, buffer_, indep_) + + ! Convert null-terminated C strings into Fortran strings + do i = 1, m + buffer(i) = '' + do j = 1, n + k = (i-1)*n + j + if (buffer_(k) == C_NULL_CHAR) exit + buffer(i)(j:j) = buffer_(k) + end do + end do + + call close_dataset(dset_id) end subroutine read_string_1D - subroutine read_string_1D_explicit(dset_id, dims, buffer, indep) - integer(HID_T), intent(in) :: dset_id - integer(HSIZE_T), intent(in) :: dims(1) - character(*), target, intent(inout) :: buffer(dims(1)) - logical, optional, intent(in) :: indep ! independent I/O - - integer :: hdf5_err - integer :: data_xfer_mode -#ifdef PHDF5 - integer(HID_T) :: plist ! property list -#endif - integer(HID_T) :: space_id - integer(HID_T) :: filetype - integer(HID_T) :: memtype - integer(SIZE_T) :: size - integer(SIZE_T) :: n - type(c_ptr) :: f_ptr - - ! Set up collective vs. independent I/O - data_xfer_mode = H5FD_MPIO_COLLECTIVE_F - if (present(indep)) then - if (indep) data_xfer_mode = H5FD_MPIO_INDEPENDENT_F - end if - - ! Get dataset and dataspace - call h5dget_space_f(dset_id, space_id, hdf5_err) - - ! Make sure buffer is large enough - call h5dget_type_f(dset_id, filetype, hdf5_err) - call h5tget_size_f(filetype, size, hdf5_err) - if (size > len(buffer(1)) + 1) then - call fatal_error("Character buffer is not long enough to & - &read HDF5 string array.") - end if - - ! Get datatype in memory based on Fortran character - n = len(buffer(1)) - call h5tcopy_f(H5T_FORTRAN_S1, memtype, hdf5_err) - call h5tset_size_f(memtype, n, hdf5_err) - - ! Get pointer to start of string - f_ptr = c_loc(buffer(1)(1:1)) - - if (using_mpio_device(dset_id)) then -#ifdef PHDF5 - call h5pcreate_f(H5P_DATASET_XFER_F, plist, hdf5_err) - call h5pset_dxpl_mpio_f(plist, data_xfer_mode, hdf5_err) - call h5dread_f(dset_id, memtype, f_ptr, hdf5_err, mem_space_id=space_id, & - xfer_prp=plist) - call h5pclose_f(plist, hdf5_err) -#endif - else - call h5dread_f(dset_id, memtype, f_ptr, hdf5_err, mem_space_id=space_id) - end if - - call h5sclose_f(space_id, hdf5_err) - call h5tclose_f(filetype, hdf5_err) - call h5tclose_f(memtype, hdf5_err) - end subroutine read_string_1D_explicit - !=============================================================================== ! WRITE_ATTRIBUTE_STRING !=============================================================================== From c50c6f070007f0a6cbdcd3a7d76e0d1f5d950add Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Thu, 19 Apr 2018 12:21:46 -0500 Subject: [PATCH 39/77] Convert HDF5 read_attribute_string/logical to C++ --- src/hdf5_interface.F90 | 147 ++++++++++++++--------------------------- src/hdf5_interface.cpp | 27 ++++++++ src/hdf5_interface.h | 3 + 3 files changed, 81 insertions(+), 96 deletions(-) diff --git a/src/hdf5_interface.F90 b/src/hdf5_interface.F90 index 1cf2522598..6f4eabad88 100644 --- a/src/hdf5_interface.F90 +++ b/src/hdf5_interface.F90 @@ -100,6 +100,13 @@ module hdf5_interface public :: get_name interface + function attribute_typesize(obj_id, name) result(sz) bind(C) + import HID_T, C_CHAR, SIZE_T + integer(HID_T), value :: obj_id + character(kind=C_CHAR), intent(in) :: name(*) + integer(SIZE_T) :: sz + end function attribute_typesize + function dataset_typesize(dset) result(sz) bind(C) import HID_T, SIZE_T integer(HID_T), value :: dset @@ -149,6 +156,15 @@ module hdf5_interface real(C_DOUBLE), intent(out) :: buffer(*) end subroutine read_attr_double_c + subroutine read_attr_string_c(obj_id, name, slen, buffer) & + bind(C, name='read_attr_string') + import HID_T, C_CHAR, C_SIZE_T + integer(HID_T), value :: obj_id + character(kind=C_CHAR), intent(in) :: name(*) + integer(C_SIZE_T), value :: slen + character(kind=C_CHAR), intent(out) :: buffer(*) + end subroutine read_attr_string_c + subroutine read_int_c(obj_id, name, buffer, indep) & bind(C, name='read_int') import HID_T, C_INT, C_BOOL, C_PTR @@ -1290,44 +1306,22 @@ contains integer(HID_T), intent(in) :: obj_id character(*), intent(in) :: name ! name for data - integer :: hdf5_err - integer(HID_T) :: attr_id ! data set handle - integer(HID_T) :: filetype - integer(HID_T) :: memtype - integer(SIZE_T) :: i - integer(SIZE_T) :: size - character(kind=C_CHAR), allocatable, target :: temp_buffer(:) - type(c_ptr) :: f_ptr + integer(C_SIZE_T) :: i, n + character(kind=C_CHAR), allocatable, target :: buffer_(:) - ! Get dataset and dataspace - call h5aopen_f(obj_id, trim(name), attr_id, hdf5_err) + ! Allocate a C char array to get string + n = attribute_typesize(obj_id, to_c_string(name)) + allocate(buffer_(n)) - ! Make sure buffer is large enough - call h5aget_type_f(attr_id, filetype, hdf5_err) - call h5tget_size_f(filetype, size, hdf5_err) - allocate(temp_buffer(size)) - if (size > len(buffer)) then - call fatal_error("Character buffer is not long enough to & - &read HDF5 string.") - end if + ! Read attribute + call read_attr_string_c(obj_id, to_c_string(name), n, buffer_) - ! Get datatype in memory based on Fortran character - call h5tcopy_f(H5T_C_S1, memtype, hdf5_err) - call h5tset_size_f(memtype, size + 1, hdf5_err) - - ! Get pointer to start of string - f_ptr = c_loc(temp_buffer(1)) - - call h5aread_f(attr_id, memtype, f_ptr, hdf5_err) + ! Copy back to Fortran string buffer = '' - do i = 1, size - if (temp_buffer(i) == C_NULL_CHAR) cycle - buffer(i:i) = temp_buffer(i) + do i = 1, n + if (buffer_(i) == C_NULL_CHAR) cycle + buffer(i:i) = buffer_(i) end do - - call h5aclose_f(attr_id, hdf5_err) - call h5tclose_f(filetype, hdf5_err) - call h5tclose_f(memtype, hdf5_err) end subroutine read_attribute_string subroutine read_attribute_string_1D(buffer, obj_id, name) @@ -1335,82 +1329,43 @@ contains integer(HID_T), intent(in) :: obj_id character(*), intent(in) :: name - integer :: hdf5_err - integer(HID_T) :: space_id - integer(HID_T) :: attr_id + integer(C_SIZE_T) :: i, j, k, n, m integer(HSIZE_T) :: dims(1) - integer(HSIZE_T) :: maxdims(1) + character(kind=C_CHAR), allocatable, target :: buffer_(:) - call h5aopen_f(obj_id, trim(name), attr_id, hdf5_err) - - if (allocated(buffer)) then - dims(:) = shape(buffer) - else - call h5aget_space_f(attr_id, space_id, hdf5_err) - call h5sget_simple_extent_dims_f(space_id, dims, maxdims, hdf5_err) + if (.not. allocated(buffer)) then + call get_shape_attr(obj_id, to_c_string(name), dims) allocate(buffer(dims(1))) - call h5sclose_f(space_id, hdf5_err) end if - call read_attribute_string_1D_explicit(attr_id, dims, buffer) - call h5aclose_f(attr_id, hdf5_err) + ! Allocate a C char array to get strings + n = attribute_typesize(obj_id, to_c_string(name)) + m = size(buffer) + allocate(buffer_(n*m)) + + ! Read attribute + call read_attr_string_c(obj_id, to_c_string(name), n, buffer_) + + ! Convert null-terminated C strings into Fortran strings + do i = 1, m + buffer(i) = '' + do j = 1, n + k = (i-1)*n + j + if (buffer_(k) == C_NULL_CHAR) exit + buffer(i)(j:j) = buffer_(k) + end do + end do end subroutine read_attribute_string_1D - subroutine read_attribute_string_1D_explicit(attr_id, dims, buffer) - integer(HID_T), intent(in) :: attr_id - integer(HSIZE_T), intent(in) :: dims(1) - character(*), target, intent(inout) :: buffer(dims(1)) - - integer :: hdf5_err - integer(HID_T) :: filetype - integer(HID_T) :: memtype - integer(SIZE_T) :: size - integer(SIZE_T) :: n - type(c_ptr) :: f_ptr - - ! Make sure buffer is large enough - call h5aget_type_f(attr_id, filetype, hdf5_err) - call h5tget_size_f(filetype, size, hdf5_err) - if (size > len(buffer(1)) + 1) then - call fatal_error("Character buffer is not long enough to & - &read HDF5 string array.") - end if - - ! Get datatype in memory based on Fortran character - n = len(buffer(1)) - call h5tcopy_f(H5T_FORTRAN_S1, memtype, hdf5_err) - call h5tset_size_f(memtype, n, hdf5_err) - - ! Get pointer to start of string - f_ptr = c_loc(buffer(1)(1:1)) - - call h5aread_f(attr_id, memtype, f_ptr, hdf5_err) - - call h5tclose_f(filetype, hdf5_err) - call h5tclose_f(memtype, hdf5_err) - end subroutine read_attribute_string_1D_explicit - subroutine read_attribute_logical(buffer, obj_id, name) logical, intent(inout), target :: buffer integer(HID_T), intent(in) :: obj_id character(*), intent(in) :: name - integer, target :: int_buffer - integer :: hdf5_err - integer(HID_T) :: attr_id - type(c_ptr) :: f_ptr + integer :: tmp - call h5aopen_f(obj_id, trim(name), attr_id, hdf5_err) - f_ptr = c_loc(int_buffer) - call h5aread_f(attr_id, H5T_NATIVE_INTEGER, f_ptr, hdf5_err) - call h5aclose_f(attr_id, hdf5_err) - - ! Convert to Fortran logical - if (int_buffer == 0) then - buffer = .false. - else - buffer = .true. - end if + call read_attribute_integer(tmp, obj_id, name) + buffer = (tmp /= 0) end subroutine read_attribute_logical subroutine get_shape(obj_id, dims) diff --git a/src/hdf5_interface.cpp b/src/hdf5_interface.cpp index aa44e7c972..935ef084ad 100644 --- a/src/hdf5_interface.cpp +++ b/src/hdf5_interface.cpp @@ -19,6 +19,18 @@ attribute_exists(hid_t obj_id, const char* name) } +size_t +attribute_typesize(hid_t obj_id, const char* name) +{ + hid_t attr = H5Aopen(obj_id, name, H5P_DEFAULT); + hid_t filetype = H5Aget_type(attr); + size_t n = H5Tget_size(filetype); + H5Tclose(filetype); + H5Aclose(attr); + return n; +} + + bool using_mpio_device(hid_t obj_id) { @@ -238,6 +250,21 @@ read_attr_int(hid_t obj_id, const char* name, int* buffer) } +void +read_attr_string(hid_t obj_id, const char* name, size_t slen, char* buffer) +{ + // Create datatype for a string + hid_t datatype = H5Tcopy(H5T_C_S1); + H5Tset_size(datatype, slen + 1); + + // Read data into buffer + read_attr(obj_id, name, datatype, buffer); + + // Free resources + H5Tclose(datatype); +} + + void read_dataset(hid_t obj_id, const char* name, hid_t mem_type_id, void* buffer, bool indep) diff --git a/src/hdf5_interface.h b/src/hdf5_interface.h index 2e470dbc7d..9ea170c6cc 100644 --- a/src/hdf5_interface.h +++ b/src/hdf5_interface.h @@ -13,6 +13,7 @@ namespace openmc { extern "C" bool attribute_exists(hid_t obj_id, const char* name); +extern "C" size_t attribute_typesize(hid_t obj_id, const char* name); extern "C" hid_t create_group(hid_t parent_id, const char* name); hid_t create_group(hid_t parent_id, const std::string& name); extern "C" void close_dataset(hid_t dataset_id); @@ -51,6 +52,8 @@ void read_attr(hid_t obj_id, const char* name, hid_t mem_type_id, const void* buffer); extern "C" void read_attr_double(hid_t obj_id, const char* name, double* buffer); extern "C" void read_attr_int(hid_t obj_id, const char* name, int* buffer); +extern "C" void read_attr_string(hid_t obj_id, const char* name, size_t slen, + char* buffer); void read_dataset(hid_t obj_id, const char* name, hid_t mem_type_id, void* buffer, bool indep); From cfea8aa32471c00ca629d35fa65cbd7c6a38fce5 Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Thu, 19 Apr 2018 12:26:32 -0500 Subject: [PATCH 40/77] Remove using_mpio_device on Fortran side --- src/hdf5_interface.F90 | 28 ---------------------------- 1 file changed, 28 deletions(-) diff --git a/src/hdf5_interface.F90 b/src/hdf5_interface.F90 index 6f4eabad88..77628d742b 100644 --- a/src/hdf5_interface.F90 +++ b/src/hdf5_interface.F90 @@ -1396,34 +1396,6 @@ contains ndims = dataset_ndims(obj_id) end subroutine get_ndims - function using_mpio_device(obj_id) result(mpio) - integer(HID_T), intent(in) :: obj_id - logical :: mpio - - integer :: hdf5_err - integer(HID_T) :: driver - integer(HID_T) :: file_id - integer(HID_T) :: fapl_id - - ! Determine file that this object is part of - call h5iget_file_id_f(obj_id, file_id, hdf5_err) - - ! Get file access property list - call h5fget_access_plist_f(file_id, fapl_id, hdf5_err) - - ! Get low-level driver identifier - call h5pget_driver_f(fapl_id, driver, hdf5_err) - - ! Close file access property list access - call h5pclose_f(fapl_id, hdf5_err) - - ! Close file access -- note that this only decreases the reference count so - ! that the file is not actually closed - call h5fclose_f(file_id, hdf5_err) - - mpio = (driver == H5FD_MPIO_F) - end function using_mpio_device - !=============================================================================== ! READ_COMPLEX_2D reads double precision complex 2-D array data as output by ! the h5py HDF5 python module. From 012c8c9232fe3a53588aee0c0f3f9591f314a726 Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Thu, 19 Apr 2018 12:35:14 -0500 Subject: [PATCH 41/77] Use C_SIZE_T consistently --- src/hdf5_interface.F90 | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/hdf5_interface.F90 b/src/hdf5_interface.F90 index 77628d742b..da6ebd09d3 100644 --- a/src/hdf5_interface.F90 +++ b/src/hdf5_interface.F90 @@ -101,16 +101,16 @@ module hdf5_interface interface function attribute_typesize(obj_id, name) result(sz) bind(C) - import HID_T, C_CHAR, SIZE_T + import HID_T, C_CHAR, C_SIZE_T integer(HID_T), value :: obj_id character(kind=C_CHAR), intent(in) :: name(*) - integer(SIZE_T) :: sz + integer(C_SIZE_T) :: sz end function attribute_typesize function dataset_typesize(dset) result(sz) bind(C) - import HID_T, SIZE_T + import HID_T, C_SIZE_T integer(HID_T), value :: dset - integer(SIZE_T) :: sz + integer(C_SIZE_T) :: sz end function dataset_typesize subroutine file_close(file_id) bind(C) @@ -1058,7 +1058,7 @@ contains logical, optional, intent(in) :: indep ! independent I/O integer(HID_T) :: dset_id - integer(SIZE_T) :: i, n + integer(C_SIZE_T) :: i, n logical(C_BOOL) :: indep_ character(kind=C_CHAR), allocatable, target :: buffer_(:) @@ -1128,7 +1128,7 @@ contains logical, optional, intent(in) :: indep ! independent I/O integer(HID_T) :: dset_id - integer(SIZE_T) :: i, j, k, n, m + integer(C_SIZE_T) :: i, j, k, n, m logical(C_BOOL) :: indep_ character(kind=C_CHAR), allocatable, target :: buffer_(:) From f78e6e0fc3bd4e4c61f4b0a8b9b4d28220357c7c Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Thu, 19 Apr 2018 13:00:02 -0500 Subject: [PATCH 42/77] Make HDF5 kind type parameters available from hdf5_interface --- src/angle_distribution.F90 | 4 +--- src/angleenergy_header.F90 | 2 +- src/endf_header.F90 | 2 -- src/energy_distribution.F90 | 2 -- src/hdf5_interface.F90 | 1 + src/mesh_header.F90 | 2 -- src/mgxs_header.F90 | 2 -- src/multipole_header.F90 | 2 -- src/nuclide_header.F90 | 2 -- src/particle_header.F90 | 2 -- src/particle_restart.F90 | 4 +--- src/product_header.F90 | 4 +--- src/reaction_header.F90 | 6 +----- src/sab_header.F90 | 5 +---- src/secondary_correlated.F90 | 5 +---- src/secondary_kalbach.F90 | 5 +---- src/secondary_nbody.F90 | 4 +--- src/secondary_uncorrelated.F90 | 4 +--- src/source.F90 | 3 +-- src/summary.F90 | 2 -- src/surface_header.F90 | 5 ++--- src/tallies/tally_filter.F90 | 2 -- src/tallies/tally_filter_azimuthal.F90 | 2 -- src/tallies/tally_filter_cell.F90 | 2 -- src/tallies/tally_filter_cellborn.F90 | 2 -- src/tallies/tally_filter_cellfrom.F90 | 2 -- src/tallies/tally_filter_delayedgroup.F90 | 2 -- src/tallies/tally_filter_distribcell.F90 | 2 -- src/tallies/tally_filter_energy.F90 | 2 -- src/tallies/tally_filter_energyfunc.F90 | 2 -- src/tallies/tally_filter_header.F90 | 3 +-- src/tallies/tally_filter_legendre.F90 | 2 -- src/tallies/tally_filter_material.F90 | 2 -- src/tallies/tally_filter_mesh.F90 | 2 -- src/tallies/tally_filter_meshsurface.F90 | 2 -- src/tallies/tally_filter_mu.F90 | 2 -- src/tallies/tally_filter_polar.F90 | 2 -- src/tallies/tally_filter_sph_harm.F90 | 2 -- src/tallies/tally_filter_sptl_legendre.F90 | 2 -- src/tallies/tally_filter_surface.F90 | 2 -- src/tallies/tally_filter_universe.F90 | 2 -- src/tallies/tally_filter_zernike.F90 | 2 -- src/track_output.F90 | 2 -- src/urr_header.F90 | 3 +-- src/volume_calc.F90 | 3 +-- 45 files changed, 17 insertions(+), 102 deletions(-) diff --git a/src/angle_distribution.F90 b/src/angle_distribution.F90 index 5d16f74242..a1f20e7799 100644 --- a/src/angle_distribution.F90 +++ b/src/angle_distribution.F90 @@ -1,12 +1,10 @@ module angle_distribution - use hdf5, only: HID_T, HSIZE_T - use algorithm, only: binary_search use constants, only: ZERO, ONE, HISTOGRAM, LINEAR_LINEAR use distribution_univariate, only: DistributionContainer, Tabular use hdf5_interface, only: read_attribute, get_shape, read_dataset, & - open_dataset, close_dataset + open_dataset, close_dataset, HID_T, HSIZE_T use random_lcg, only: prn implicit none diff --git a/src/angleenergy_header.F90 b/src/angleenergy_header.F90 index 60d5443c46..9fda5109ec 100644 --- a/src/angleenergy_header.F90 +++ b/src/angleenergy_header.F90 @@ -1,6 +1,6 @@ module angleenergy_header - use hdf5, only: HID_T + use hdf5_interface, only: HID_T !=============================================================================== ! ANGLEENERGY (abstract) defines a correlated or uncorrelated angle-energy diff --git a/src/endf_header.F90 b/src/endf_header.F90 index e9e45ab751..9443efe2be 100644 --- a/src/endf_header.F90 +++ b/src/endf_header.F90 @@ -1,7 +1,5 @@ module endf_header - use hdf5, only: HID_T, HSIZE_T - use algorithm, only: binary_search use constants, only: ZERO, HISTOGRAM, LINEAR_LINEAR, LINEAR_LOG, & LOG_LINEAR, LOG_LOG diff --git a/src/energy_distribution.F90 b/src/energy_distribution.F90 index 770da617cc..a9578e5d88 100644 --- a/src/energy_distribution.F90 +++ b/src/energy_distribution.F90 @@ -1,7 +1,5 @@ module energy_distribution - use hdf5 - use algorithm, only: binary_search use constants, only: ZERO, ONE, HALF, TWO, PI, HISTOGRAM, LINEAR_LINEAR use endf_header, only: Tabulated1D diff --git a/src/hdf5_interface.F90 b/src/hdf5_interface.F90 index da6ebd09d3..5320ec9f53 100644 --- a/src/hdf5_interface.F90 +++ b/src/hdf5_interface.F90 @@ -98,6 +98,7 @@ module hdf5_interface public :: get_groups public :: get_datasets public :: get_name + public :: HID_T, HSIZE_T, SIZE_T interface function attribute_typesize(obj_id, name) result(sz) bind(C) diff --git a/src/mesh_header.F90 b/src/mesh_header.F90 index fc13a868e5..fb22d2ad31 100644 --- a/src/mesh_header.F90 +++ b/src/mesh_header.F90 @@ -2,8 +2,6 @@ module mesh_header use, intrinsic :: ISO_C_BINDING - use hdf5 - use constants use dict_header, only: DictIntInt use error diff --git a/src/mgxs_header.F90 b/src/mgxs_header.F90 index 6eabefae3c..e599a89ff3 100644 --- a/src/mgxs_header.F90 +++ b/src/mgxs_header.F90 @@ -3,8 +3,6 @@ module mgxs_header use, intrinsic :: ISO_FORTRAN_ENV use, intrinsic :: ISO_C_BINDING - use hdf5, only: HID_T, HSIZE_T, SIZE_T - use algorithm, only: find, sort use constants, only: MAX_WORD_LEN, ZERO, ONE, TWO, PI use error, only: fatal_error diff --git a/src/multipole_header.F90 b/src/multipole_header.F90 index 7fb438bce1..f2d0c91062 100644 --- a/src/multipole_header.F90 +++ b/src/multipole_header.F90 @@ -1,7 +1,5 @@ module multipole_header - use hdf5 - use constants use dict_header, only: DictIntInt use error, only: fatal_error diff --git a/src/nuclide_header.F90 b/src/nuclide_header.F90 index 76fc26a748..a063bb90b4 100644 --- a/src/nuclide_header.F90 +++ b/src/nuclide_header.F90 @@ -3,8 +3,6 @@ module nuclide_header use, intrinsic :: ISO_FORTRAN_ENV use, intrinsic :: ISO_C_BINDING - use hdf5, only: HID_T, HSIZE_T, SIZE_T - use algorithm, only: sort, find, binary_search use constants use dict_header, only: DictIntInt, DictCharInt diff --git a/src/particle_header.F90 b/src/particle_header.F90 index 02fb55405a..cdb97dec8d 100644 --- a/src/particle_header.F90 +++ b/src/particle_header.F90 @@ -1,7 +1,5 @@ module particle_header - use hdf5, only: HID_T - use bank_header, only: Bank, source_bank use constants use error, only: fatal_error, warning diff --git a/src/particle_restart.F90 b/src/particle_restart.F90 index fc8a05277c..c3d25151b6 100644 --- a/src/particle_restart.F90 +++ b/src/particle_restart.F90 @@ -5,7 +5,7 @@ module particle_restart use bank_header, only: Bank use constants use error, only: write_message - use hdf5_interface, only: file_open, file_close, read_dataset + use hdf5_interface, only: file_open, file_close, read_dataset, HID_T use mgxs_header, only: energy_bin_avg use nuclide_header, only: micro_xs, n_nuclides use output, only: print_particle @@ -16,8 +16,6 @@ module particle_restart use tally_header, only: n_tallies use tracking, only: transport - use hdf5, only: HID_T - implicit none private public :: openmc_particle_restart diff --git a/src/product_header.F90 b/src/product_header.F90 index a69929473d..a5e23f4b6c 100644 --- a/src/product_header.F90 +++ b/src/product_header.F90 @@ -1,13 +1,11 @@ module product_header - use hdf5, only: HID_T - use angleenergy_header, only: AngleEnergyContainer use constants, only: ZERO, MAX_WORD_LEN, EMISSION_PROMPT, EMISSION_DELAYED, & EMISSION_TOTAL, NEUTRON, PHOTON use endf_header, only: Tabulated1D, Function1D, Polynomial use hdf5_interface, only: read_attribute, open_group, close_group, & - open_dataset, close_dataset, read_dataset + open_dataset, close_dataset, read_dataset, HID_T use random_lcg, only: prn use secondary_correlated, only: CorrelatedAngleEnergy use secondary_kalbach, only: KalbachMann diff --git a/src/reaction_header.F90 b/src/reaction_header.F90 index 12b3888c4b..48973336bf 100644 --- a/src/reaction_header.F90 +++ b/src/reaction_header.F90 @@ -1,11 +1,7 @@ module reaction_header - use hdf5, only: HID_T, HSIZE_T, SIZE_T, h5gget_info_f, h5lget_name_by_idx_f, & - H5_INDEX_NAME_F, H5_ITER_INC_F - use constants, only: MAX_WORD_LEN - use hdf5_interface, only: read_attribute, open_group, close_group, & - open_dataset, read_dataset, close_dataset, get_shape, get_groups + use hdf5_interface use product_header, only: ReactionProduct use stl_vector, only: VectorInt use string, only: to_str, starts_with diff --git a/src/sab_header.F90 b/src/sab_header.F90 index eca8e555a1..7ac14ef00e 100644 --- a/src/sab_header.F90 +++ b/src/sab_header.F90 @@ -8,10 +8,7 @@ module sab_header use dict_header, only: DictIntInt, DictCharInt use distribution_univariate, only: Tabular use error, only: warning, fatal_error - use hdf5, only: HID_T, HSIZE_T, SIZE_T - use hdf5_interface, only: read_attribute, get_shape, open_group, close_group, & - open_dataset, read_dataset, close_dataset, get_datasets, object_exists, & - get_name + use hdf5_interface use random_lcg, only: prn use secondary_correlated, only: CorrelatedAngleEnergy use settings diff --git a/src/secondary_correlated.F90 b/src/secondary_correlated.F90 index a0e203f33d..6f5e6cabf7 100644 --- a/src/secondary_correlated.F90 +++ b/src/secondary_correlated.F90 @@ -1,13 +1,10 @@ module secondary_correlated - use hdf5, only: HID_T, HSIZE_T - use algorithm, only: binary_search use angleenergy_header, only: AngleEnergy use constants, only: ZERO, ONE, HALF, TWO, HISTOGRAM, LINEAR_LINEAR use distribution_univariate, only: DistributionContainer, Tabular - use hdf5_interface, only: get_shape, read_attribute, open_dataset, & - read_dataset, close_dataset + use hdf5_interface use random_lcg, only: prn !=============================================================================== diff --git a/src/secondary_kalbach.F90 b/src/secondary_kalbach.F90 index f963cff3ff..3315174e1d 100644 --- a/src/secondary_kalbach.F90 +++ b/src/secondary_kalbach.F90 @@ -1,12 +1,9 @@ module secondary_kalbach - use hdf5, only: HID_T, HSIZE_T - use algorithm, only: binary_search use angleenergy_header, only: AngleEnergy use constants, only: ZERO, HALF, ONE, TWO, HISTOGRAM, LINEAR_LINEAR - use hdf5_interface, only: read_attribute, read_dataset, open_dataset, & - close_dataset, get_shape + use hdf5_interface use random_lcg, only: prn !=============================================================================== diff --git a/src/secondary_nbody.F90 b/src/secondary_nbody.F90 index 14ae949a9e..aee4b1ff78 100644 --- a/src/secondary_nbody.F90 +++ b/src/secondary_nbody.F90 @@ -1,10 +1,8 @@ module secondary_nbody - use hdf5, only: HID_T - use angleenergy_header, only: AngleEnergy use constants, only: ONE, TWO, PI - use hdf5_interface, only: read_attribute + use hdf5_interface, only: read_attribute, HID_T use math, only: maxwell_spectrum use random_lcg, only: prn diff --git a/src/secondary_uncorrelated.F90 b/src/secondary_uncorrelated.F90 index 40aa827da6..e559c1e5ae 100644 --- a/src/secondary_uncorrelated.F90 +++ b/src/secondary_uncorrelated.F90 @@ -1,7 +1,5 @@ module secondary_uncorrelated - use hdf5, only: HID_T - use angle_distribution, only: AngleDistribution use angleenergy_header, only: AngleEnergy use constants, only: ONE, TWO, MAX_WORD_LEN @@ -9,7 +7,7 @@ module secondary_uncorrelated ContinuousTabular, MaxwellEnergy, Evaporation, WattEnergy, DiscretePhoton use error, only: warning use hdf5_interface, only: read_attribute, open_group, close_group, & - object_exists + object_exists, HID_T use random_lcg, only: prn !=============================================================================== diff --git a/src/source.F90 b/src/source.F90 index 9e3a0831de..8e142fcfaa 100644 --- a/src/source.F90 +++ b/src/source.F90 @@ -1,6 +1,5 @@ module source - use hdf5, only: HID_T #ifdef OPENMC_MPI use message_passing #endif @@ -12,7 +11,7 @@ module source use distribution_multivariate, only: SpatialBox use error, only: fatal_error use geometry, only: find_cell - use hdf5_interface, only: file_open, file_close, read_dataset + use hdf5_interface, only: file_open, file_close, read_dataset, HID_T use math use message_passing, only: rank use mgxs_header, only: rev_energy_bins, num_energy_groups diff --git a/src/summary.F90 b/src/summary.F90 index 9f27694d1b..6f8333b2cf 100644 --- a/src/summary.F90 +++ b/src/summary.F90 @@ -1,7 +1,5 @@ module summary - use hdf5 - use constants use endf, only: reaction_name use error, only: write_message diff --git a/src/surface_header.F90 b/src/surface_header.F90 index 9ed89a14e9..ab6babb5cb 100644 --- a/src/surface_header.F90 +++ b/src/surface_header.F90 @@ -1,9 +1,9 @@ module surface_header use, intrinsic :: ISO_C_BINDING - use hdf5 use dict_header, only: DictIntInt + use hdf5_interface implicit none @@ -71,8 +71,7 @@ module surface_header subroutine surface_to_hdf5_c(surf_ptr, group) & bind(C, name='surface_to_hdf5') - use ISO_C_BINDING - use hdf5 + import C_PTR, HID_T implicit none type(C_PTR), intent(in), value :: surf_ptr integer(HID_T), intent(in), value :: group diff --git a/src/tallies/tally_filter.F90 b/src/tallies/tally_filter.F90 index e484ac2315..4b589cedbf 100644 --- a/src/tallies/tally_filter.F90 +++ b/src/tallies/tally_filter.F90 @@ -2,8 +2,6 @@ module tally_filter use, intrinsic :: ISO_C_BINDING - use hdf5, only: HID_T - use error use string, only: to_f_string use tally_filter_header diff --git a/src/tallies/tally_filter_azimuthal.F90 b/src/tallies/tally_filter_azimuthal.F90 index 272d111d14..fc7f15a17a 100644 --- a/src/tallies/tally_filter_azimuthal.F90 +++ b/src/tallies/tally_filter_azimuthal.F90 @@ -2,8 +2,6 @@ module tally_filter_azimuthal use, intrinsic :: ISO_C_BINDING - use hdf5 - use algorithm, only: binary_search use constants use error, only: fatal_error diff --git a/src/tallies/tally_filter_cell.F90 b/src/tallies/tally_filter_cell.F90 index 8d2b93d282..00ab8fa15b 100644 --- a/src/tallies/tally_filter_cell.F90 +++ b/src/tallies/tally_filter_cell.F90 @@ -2,8 +2,6 @@ module tally_filter_cell use, intrinsic :: ISO_C_BINDING - use hdf5 - use constants, only: ONE, MAX_LINE_LEN use dict_header, only: EMPTY use error, only: fatal_error diff --git a/src/tallies/tally_filter_cellborn.F90 b/src/tallies/tally_filter_cellborn.F90 index 450858b6b8..0d7461ef82 100644 --- a/src/tallies/tally_filter_cellborn.F90 +++ b/src/tallies/tally_filter_cellborn.F90 @@ -2,8 +2,6 @@ module tally_filter_cellborn use, intrinsic :: ISO_C_BINDING - use hdf5 - use constants, only: ONE, MAX_LINE_LEN use dict_header, only: EMPTY use error, only: fatal_error diff --git a/src/tallies/tally_filter_cellfrom.F90 b/src/tallies/tally_filter_cellfrom.F90 index 16cb294d56..2c54021226 100644 --- a/src/tallies/tally_filter_cellfrom.F90 +++ b/src/tallies/tally_filter_cellfrom.F90 @@ -2,8 +2,6 @@ module tally_filter_cellfrom use, intrinsic :: ISO_C_BINDING - use hdf5 - use constants, only: ONE, MAX_LINE_LEN use dict_header, only: EMPTY use error, only: fatal_error diff --git a/src/tallies/tally_filter_delayedgroup.F90 b/src/tallies/tally_filter_delayedgroup.F90 index 32010e8157..1a662005bc 100644 --- a/src/tallies/tally_filter_delayedgroup.F90 +++ b/src/tallies/tally_filter_delayedgroup.F90 @@ -2,8 +2,6 @@ module tally_filter_delayedgroup use, intrinsic :: ISO_C_BINDING - use hdf5 - use constants, only: ONE, MAX_LINE_LEN, MAX_DELAYED_GROUPS use error, only: fatal_error use hdf5_interface diff --git a/src/tallies/tally_filter_distribcell.F90 b/src/tallies/tally_filter_distribcell.F90 index 3cb34efe4c..6c42161ca7 100644 --- a/src/tallies/tally_filter_distribcell.F90 +++ b/src/tallies/tally_filter_distribcell.F90 @@ -2,8 +2,6 @@ module tally_filter_distribcell use, intrinsic :: ISO_C_BINDING - use hdf5, only: HID_T - use constants use dict_header, only: EMPTY use error diff --git a/src/tallies/tally_filter_energy.F90 b/src/tallies/tally_filter_energy.F90 index d186fa62a8..93da69edda 100644 --- a/src/tallies/tally_filter_energy.F90 +++ b/src/tallies/tally_filter_energy.F90 @@ -2,8 +2,6 @@ module tally_filter_energy use, intrinsic :: ISO_C_BINDING - use hdf5, only: HID_T - use algorithm, only: binary_search use constants use error diff --git a/src/tallies/tally_filter_energyfunc.F90 b/src/tallies/tally_filter_energyfunc.F90 index efaabae2ee..1402707b4d 100644 --- a/src/tallies/tally_filter_energyfunc.F90 +++ b/src/tallies/tally_filter_energyfunc.F90 @@ -2,8 +2,6 @@ module tally_filter_energyfunc use, intrinsic :: ISO_C_BINDING - use hdf5 - use algorithm, only: binary_search use constants use error, only: fatal_error diff --git a/src/tallies/tally_filter_header.F90 b/src/tallies/tally_filter_header.F90 index 93d050b1af..e57423ddfa 100644 --- a/src/tallies/tally_filter_header.F90 +++ b/src/tallies/tally_filter_header.F90 @@ -5,13 +5,12 @@ module tally_filter_header use constants, only: MAX_LINE_LEN use dict_header, only: DictIntInt use error + use hdf5_interface, only: HID_T use particle_header, only: Particle use stl_vector, only: VectorInt, VectorReal use string, only: to_str use xml_interface, only: XMLNode - use hdf5 - implicit none private public :: free_memory_tally_filter diff --git a/src/tallies/tally_filter_legendre.F90 b/src/tallies/tally_filter_legendre.F90 index 9545b86926..b4ee7b06b1 100644 --- a/src/tallies/tally_filter_legendre.F90 +++ b/src/tallies/tally_filter_legendre.F90 @@ -2,8 +2,6 @@ module tally_filter_legendre use, intrinsic :: ISO_C_BINDING - use hdf5, only: HID_T - use constants use error use hdf5_interface diff --git a/src/tallies/tally_filter_material.F90 b/src/tallies/tally_filter_material.F90 index 3b9f843f84..443dc62855 100644 --- a/src/tallies/tally_filter_material.F90 +++ b/src/tallies/tally_filter_material.F90 @@ -2,8 +2,6 @@ module tally_filter_material use, intrinsic :: ISO_C_BINDING - use hdf5, only: HID_T - use constants use dict_header, only: DictIntInt, EMPTY use error diff --git a/src/tallies/tally_filter_mesh.F90 b/src/tallies/tally_filter_mesh.F90 index d2acdc4c8a..486569da63 100644 --- a/src/tallies/tally_filter_mesh.F90 +++ b/src/tallies/tally_filter_mesh.F90 @@ -2,8 +2,6 @@ module tally_filter_mesh use, intrinsic :: ISO_C_BINDING - use hdf5 - use constants use dict_header, only: EMPTY use error diff --git a/src/tallies/tally_filter_meshsurface.F90 b/src/tallies/tally_filter_meshsurface.F90 index d90b63664e..801d4252ca 100644 --- a/src/tallies/tally_filter_meshsurface.F90 +++ b/src/tallies/tally_filter_meshsurface.F90 @@ -2,8 +2,6 @@ module tally_filter_meshsurface use, intrinsic :: ISO_C_BINDING - use hdf5 - use constants use dict_header, only: EMPTY use error diff --git a/src/tallies/tally_filter_mu.F90 b/src/tallies/tally_filter_mu.F90 index c949289b66..7f8bde9238 100644 --- a/src/tallies/tally_filter_mu.F90 +++ b/src/tallies/tally_filter_mu.F90 @@ -2,8 +2,6 @@ module tally_filter_mu use, intrinsic :: ISO_C_BINDING - use hdf5 - use algorithm, only: binary_search use constants, only: ONE, TWO, MAX_LINE_LEN, NO_BIN_FOUND use error, only: fatal_error diff --git a/src/tallies/tally_filter_polar.F90 b/src/tallies/tally_filter_polar.F90 index 89815c1028..7cbb55f8b4 100644 --- a/src/tallies/tally_filter_polar.F90 +++ b/src/tallies/tally_filter_polar.F90 @@ -2,8 +2,6 @@ module tally_filter_polar use, intrinsic :: ISO_C_BINDING - use hdf5 - use algorithm, only: binary_search use constants use error, only: fatal_error diff --git a/src/tallies/tally_filter_sph_harm.F90 b/src/tallies/tally_filter_sph_harm.F90 index 5c47c2c71f..bc95baaa3c 100644 --- a/src/tallies/tally_filter_sph_harm.F90 +++ b/src/tallies/tally_filter_sph_harm.F90 @@ -2,8 +2,6 @@ module tally_filter_sph_harm use, intrinsic :: ISO_C_BINDING - use hdf5, only: HID_T - use constants use error use hdf5_interface diff --git a/src/tallies/tally_filter_sptl_legendre.F90 b/src/tallies/tally_filter_sptl_legendre.F90 index d6594d05a9..83db9a864e 100644 --- a/src/tallies/tally_filter_sptl_legendre.F90 +++ b/src/tallies/tally_filter_sptl_legendre.F90 @@ -2,8 +2,6 @@ module tally_filter_sptl_legendre use, intrinsic :: ISO_C_BINDING - use hdf5, only: HID_T - use constants use error use hdf5_interface diff --git a/src/tallies/tally_filter_surface.F90 b/src/tallies/tally_filter_surface.F90 index df3bf36031..ec642bc8de 100644 --- a/src/tallies/tally_filter_surface.F90 +++ b/src/tallies/tally_filter_surface.F90 @@ -2,8 +2,6 @@ module tally_filter_surface use, intrinsic :: ISO_C_BINDING - use hdf5 - use constants, only: ONE, MAX_LINE_LEN use dict_header, only: EMPTY use error, only: fatal_error diff --git a/src/tallies/tally_filter_universe.F90 b/src/tallies/tally_filter_universe.F90 index 742152232d..0dc5aefe14 100644 --- a/src/tallies/tally_filter_universe.F90 +++ b/src/tallies/tally_filter_universe.F90 @@ -2,8 +2,6 @@ module tally_filter_universe use, intrinsic :: ISO_C_BINDING - use hdf5 - use constants, only: ONE, MAX_LINE_LEN use dict_header, only: EMPTY use error, only: fatal_error diff --git a/src/tallies/tally_filter_zernike.F90 b/src/tallies/tally_filter_zernike.F90 index e96a53a7f9..fa205b1808 100644 --- a/src/tallies/tally_filter_zernike.F90 +++ b/src/tallies/tally_filter_zernike.F90 @@ -2,8 +2,6 @@ module tally_filter_zernike use, intrinsic :: ISO_C_BINDING - use hdf5, only: HID_T - use constants use error use hdf5_interface diff --git a/src/track_output.F90 b/src/track_output.F90 index 350e687b1c..95af9e6b0f 100644 --- a/src/track_output.F90 +++ b/src/track_output.F90 @@ -5,8 +5,6 @@ module track_output - use hdf5 - use constants use hdf5_interface use particle_header, only: Particle diff --git a/src/urr_header.F90 b/src/urr_header.F90 index cc41d43ccc..0ec9e89deb 100644 --- a/src/urr_header.F90 +++ b/src/urr_header.F90 @@ -1,8 +1,7 @@ module urr_header - use hdf5, only: HID_T, HSIZE_T use hdf5_interface, only: read_attribute, open_dataset, read_dataset, & - close_dataset, get_shape + close_dataset, get_shape, HID_T, HSIZE_T implicit none diff --git a/src/volume_calc.F90 b/src/volume_calc.F90 index ac813a94af..fa770c1f37 100644 --- a/src/volume_calc.F90 +++ b/src/volume_calc.F90 @@ -2,7 +2,6 @@ module volume_calc use, intrinsic :: ISO_C_BINDING - use hdf5, only: HID_T #ifdef _OPENMP use omp_lib #endif @@ -12,7 +11,7 @@ module volume_calc use geometry, only: find_cell use geometry_header, only: universes, cells use hdf5_interface, only: file_open, file_close, write_attribute, & - create_group, close_group, write_dataset + create_group, close_group, write_dataset, HID_T use output, only: header, time_stamp use material_header, only: materials use message_passing From 4fdfd51ab9bb6ad79aadf64d9f3f5e9f4da70cdb Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Thu, 19 Apr 2018 14:44:10 -0500 Subject: [PATCH 43/77] Convert HDF5 read/write_tally_results (and fix attribute bug) --- src/hdf5_interface.F90 | 4 +- src/hdf5_interface.cpp | 47 +++++++++++++++++++- src/hdf5_interface.h | 7 +++ src/tallies/tally_header.F90 | 84 +++++++++++++----------------------- 4 files changed, 84 insertions(+), 58 deletions(-) diff --git a/src/hdf5_interface.F90 b/src/hdf5_interface.F90 index 5320ec9f53..752ce062dc 100644 --- a/src/hdf5_interface.F90 +++ b/src/hdf5_interface.F90 @@ -1342,7 +1342,7 @@ contains ! Allocate a C char array to get strings n = attribute_typesize(obj_id, to_c_string(name)) m = size(buffer) - allocate(buffer_(n*m)) + allocate(buffer_((n+1)*m)) ! Read attribute call read_attr_string_c(obj_id, to_c_string(name), n, buffer_) @@ -1351,7 +1351,7 @@ contains do i = 1, m buffer(i) = '' do j = 1, n - k = (i-1)*n + j + k = (i-1)*(n+1) + j if (buffer_(k) == C_NULL_CHAR) exit buffer(i)(j:j) = buffer_(k) end do diff --git a/src/hdf5_interface.cpp b/src/hdf5_interface.cpp index 935ef084ad..ddc2dcdfc1 100644 --- a/src/hdf5_interface.cpp +++ b/src/hdf5_interface.cpp @@ -350,6 +350,26 @@ read_complex(hid_t obj_id, const char* name, double _Complex* buffer, bool indep } +void +read_tally_results(hid_t group_id, hsize_t n_filter, hsize_t n_score, double* results) +{ + // Create dataspace for hyperslab in memory + hsize_t dims[] {n_filter, n_score, 3}; + hsize_t start[] {0, 0, 1}; + hsize_t count[] {n_filter, n_score, 2}; + hid_t memspace = H5Screate_simple(3, dims, nullptr); + H5Sselect_hyperslab(memspace, H5S_SELECT_SET, start, nullptr, count, nullptr); + + // Create and write dataset + hid_t dset = H5Dopen(group_id, "results", H5P_DEFAULT); + H5Dread(dset, H5T_NATIVE_DOUBLE, memspace, H5S_ALL, H5P_DEFAULT, results); + + // Free resources + H5Dclose(dset); + H5Sclose(memspace); +} + + void write_attr(hid_t obj_id, int ndim, const hsize_t* dims, const char* name, hid_t mem_type_id, const void* buffer) @@ -488,9 +508,34 @@ write_string(hid_t group_id, int ndim, const hsize_t* dims, size_t slen, void -write_string(hid_t group_id, char const* name, const std::string& buffer, bool indep) +write_string(hid_t group_id, const char* name, const std::string& buffer, bool indep) { write_string(group_id, 0, nullptr, buffer.length(), name, buffer.c_str(), indep); } + +void +write_tally_results(hid_t group_id, hsize_t n_filter, hsize_t n_score, const double* results) +{ + // Set dimensions of sum/sum_sq hyperslab to store + hsize_t count[] {n_filter, n_score, 2}; + hid_t dspace = H5Screate_simple(3, count, nullptr); + + // Set dimensions of results array + hsize_t dims[] {n_filter, n_score, 3}; + hsize_t start[] {0, 0, 1}; + hid_t memspace = H5Screate_simple(3, dims, nullptr); + H5Sselect_hyperslab(memspace, H5S_SELECT_SET, start, nullptr, count, nullptr); + + // Create and write dataset + hid_t dset = H5Dcreate(group_id, "results", H5T_NATIVE_DOUBLE, dspace, + H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT); + H5Dwrite(dset, H5T_NATIVE_DOUBLE, memspace, H5S_ALL, H5P_DEFAULT, results); + + // Free resources + H5Dclose(dset); + H5Sclose(memspace); + H5Sclose(dspace); +} + } // namespace openmc diff --git a/src/hdf5_interface.h b/src/hdf5_interface.h index 9ea170c6cc..57f56f5c20 100644 --- a/src/hdf5_interface.h +++ b/src/hdf5_interface.h @@ -68,6 +68,9 @@ extern "C" void read_string(hid_t obj_id, const char* name, size_t slen, extern "C" void read_complex(hid_t obj_id, const char* name, double _Complex* buffer, bool indep); +extern "C" void read_tally_results(hid_t group_id, hsize_t n_filter, + hsize_t n_score, double* results); + void write_attr(hid_t obj_id, int ndim, const hsize_t* dims, const char* name, hid_t mem_type_id, const void* buffer); extern "C" void write_attr_double(hid_t obj_id, int ndim, const hsize_t* dims, @@ -90,5 +93,9 @@ extern "C" void write_string(hid_t group_id, int ndim, const hsize_t* dims, size const char* name, char const* buffer, bool indep); void write_string(hid_t group_id, const char* name, const std::string& buffer, bool indep); + +extern "C" void write_tally_results(hid_t group_id, hsize_t n_filter, hsize_t n_score, + const double* results); + } // namespace openmc #endif //HDF5_INTERFACE_H diff --git a/src/tallies/tally_header.F90 b/src/tallies/tally_header.F90 index 413464b7b5..cbfa4f048d 100644 --- a/src/tallies/tally_header.F90 +++ b/src/tallies/tally_header.F90 @@ -2,11 +2,10 @@ module tally_header use, intrinsic :: ISO_C_BINDING - use hdf5 - use constants use error use dict_header, only: DictIntInt + use hdf5_interface, only: HID_T, HSIZE_T use message_passing, only: n_procs use nuclide_header, only: nuclide_dict use settings, only: reduce_tallies, run_mode @@ -200,67 +199,42 @@ contains class(TallyObject), intent(in) :: this integer(HID_T), intent(in) :: group_id - integer :: hdf5_err - integer(HID_T) :: dset, dspace - integer(HID_T) :: memspace - integer(HSIZE_T) :: dims(3) - integer(HSIZE_T) :: dims_slab(3) - integer(HSIZE_T) :: offset(3) = [1,0,0] + integer(HSIZE_T) :: n_filter, n_score + interface + subroutine write_tally_results(group_id, n_filter, n_score, results) & + bind(C) + import HID_T, HSIZE_T, C_DOUBLE + integer(HID_T), value :: group_id + integer(HSIZE_T), value :: n_filter + integer(HSIZE_T), value :: n_score + real(C_DOUBLE), intent(in) :: results(*) + end subroutine write_tally_results + end interface - ! Create file dataspace - dims_slab(:) = shape(this % results) - dims_slab(1) = 2 - call h5screate_simple_f(3, dims_slab, dspace, hdf5_err) - - ! Create memory dataspace that contains only SUM and SUM_SQ values - dims(:) = shape(this % results) - call h5screate_simple_f(3, dims, memspace, hdf5_err) - call h5sselect_hyperslab_f(memspace, H5S_SELECT_SET_F, offset, dims_slab, & - hdf5_err) - - ! Create and write to dataset - call h5dcreate_f(group_id, "results", H5T_NATIVE_DOUBLE, dspace, dset, & - hdf5_err) - call h5dwrite_f(dset, H5T_NATIVE_DOUBLE, this % results, dims_slab, & - hdf5_err, mem_space_id=memspace) - - ! Close identifiers - call h5dclose_f(dset, hdf5_err) - call h5sclose_f(memspace, hdf5_err) - call h5sclose_f(dspace, hdf5_err) + n_filter = size(this % results, 3) + n_score = size(this % results, 2) + call write_tally_results(group_id, n_filter, n_score, this % results) end subroutine tally_write_results_hdf5 subroutine tally_read_results_hdf5(this, group_id) class(TallyObject), intent(inout) :: this integer(HID_T), intent(in) :: group_id - integer :: hdf5_err - integer(HID_T) :: dset, dspace - integer(HID_T) :: memspace - integer(HSIZE_T) :: dims(3) - integer(HSIZE_T) :: dims_slab(3) - integer(HSIZE_T) :: offset(3) = [1,0,0] + integer(HSIZE_T) :: n_filter, n_score + interface + subroutine read_tally_results(group_id, n_filter, n_score, results) & + bind(C) + import HID_T, HSIZE_T, C_DOUBLE + integer(HID_T), value :: group_id + integer(HSIZE_T), value :: n_filter + integer(HSIZE_T), value :: n_score + real(C_DOUBLE), intent(out) :: results(*) + end subroutine read_tally_results + end interface - ! Create file dataspace - dims_slab(:) = shape(this % results) - dims_slab(1) = 2 - call h5screate_simple_f(3, dims_slab, dspace, hdf5_err) - - ! Create memory dataspace that contains only SUM and SUM_SQ values - dims(:) = shape(this % results) - call h5screate_simple_f(3, dims, memspace, hdf5_err) - call h5sselect_hyperslab_f(memspace, H5S_SELECT_SET_F, offset, dims_slab, & - hdf5_err) - - ! Create and write to dataset - call h5dopen_f(group_id, "results", dset, hdf5_err) - call h5dread_f(dset, H5T_NATIVE_DOUBLE, this % results, dims_slab, & - hdf5_err, mem_space_id=memspace) - - ! Close identifiers - call h5dclose_f(dset, hdf5_err) - call h5sclose_f(memspace, hdf5_err) - call h5sclose_f(dspace, hdf5_err) + n_filter = size(this % results, 3) + n_score = size(this % results, 2) + call read_tally_results(group_id, n_filter, n_score, this % results) end subroutine tally_read_results_hdf5 !=============================================================================== From 64fa01f5375eb464e06ad8a548b3eeeeef94f8c3 Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Thu, 19 Apr 2018 15:51:40 -0500 Subject: [PATCH 44/77] Fix use of auto for transfer list --- src/hdf5_interface.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/hdf5_interface.cpp b/src/hdf5_interface.cpp index ddc2dcdfc1..5549ac7d81 100644 --- a/src/hdf5_interface.cpp +++ b/src/hdf5_interface.cpp @@ -275,7 +275,7 @@ read_dataset(hid_t obj_id, const char* name, hid_t mem_type_id, if (using_mpio_device(dset)) { #ifdef PHDF5 // Set up collective vs independent I/O - auto data_xfer_mode {indep ? H5FD_MPIO_INDEPENDENT : H5FD_MPIO_COLLECTIVE}; + auto data_xfer_mode = indep ? H5FD_MPIO_INDEPENDENT : H5FD_MPIO_COLLECTIVE; // Create dataset transfer property list hid_t plist = H5Pcreate(H5P_DATASET_XFER); From 9b8cb2e0f132d63e1f557e3ad1ff7fa537d4f9c7 Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Fri, 20 Apr 2018 06:38:16 -0500 Subject: [PATCH 45/77] Have openmc_init take a MPI_Comm* --- CMakeLists.txt | 1 + include/openmc.h | 12 +++++++++++- openmc/capi/core.py | 16 +++++++--------- src/api.F90 | 4 ++-- src/hdf5_interface.cpp | 15 ++++++++++----- src/initialize.F90 | 6 ++++-- src/initialize.cpp | 20 ++++++++++++++++++++ src/main.cpp | 14 ++++++-------- 8 files changed, 61 insertions(+), 27 deletions(-) create mode 100644 src/initialize.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index ff7a3334be..ab52510499 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -434,6 +434,7 @@ set(LIBOPENMC_FORTRAN_SRC ) set(LIBOPENMC_CXX_SRC src/error.h + src/initialize.cpp src/hdf5_interface.h src/hdf5_interface.cpp src/random_lcg.cpp diff --git a/include/openmc.h b/include/openmc.h index 1945453452..85cb09a918 100644 --- a/include/openmc.h +++ b/include/openmc.h @@ -4,6 +4,10 @@ #include #include +#ifdef OPENMC_MPI +#include "mpi.h" +#endif + #ifdef __cplusplus extern "C" { #endif @@ -46,7 +50,8 @@ extern "C" { int64_t openmc_get_seed(); int openmc_get_tally_index(int32_t id, int32_t* index); void openmc_hard_reset(); - void openmc_init(const int* intracomm); + int openmc_init(const void* intracomm); + int openmc_init_f(const int* intracomm); int openmc_legendre_filter_get_order(int32_t index, int* order); int openmc_legendre_filter_set_order(int32_t index, int order); int openmc_load_nuclide(char name[]); @@ -145,6 +150,11 @@ extern "C" { extern bool openmc_simulation_initialized; extern int openmc_verbosity; +#ifdef OPENMC_MPI + // MPI variables + extern MPI_Comm openmc_intracomm; +#endif + // Run modes constexpr int RUN_MODE_FIXEDSOURCE {1}; constexpr int RUN_MODE_EIGENVALUE {2}; diff --git a/openmc/capi/core.py b/openmc/capi/core.py index d356905036..a278e69d5b 100644 --- a/openmc/capi/core.py +++ b/openmc/capi/core.py @@ -1,6 +1,6 @@ from contextlib import contextmanager from ctypes import (CDLL, c_int, c_int32, c_int64, c_double, c_char_p, - POINTER, Structure) + POINTER, Structure, c_void_p) from warnings import warn import numpy as np @@ -27,7 +27,7 @@ _dll.openmc_find.argtypes = [POINTER(c_double*3), c_int, POINTER(c_int32), _dll.openmc_find.restype = c_int _dll.openmc_find.errcheck = _error_handler _dll.openmc_hard_reset.restype = None -_dll.openmc_init.argtypes = [POINTER(c_int)] +_dll.openmc_init.argtypes = [c_void_p] _dll.openmc_init.restype = None _dll.openmc_get_keff.argtypes = [POINTER(c_double*2)] _dll.openmc_get_keff.restype = c_int @@ -116,13 +116,11 @@ def init(intracomm=None): """ if intracomm is not None: - # If an mpi4py communicator was passed, convert it to an integer to - # be passed to openmc_init - try: - intracomm = intracomm.py2f() - except AttributeError: - pass - _dll.openmc_init(c_int(intracomm)) + # If an mpi4py communicator was passed, convert it to void* to be passed + # to openmc_init + from mpi4py import MPI + address = MPI._addressof(intracomm) + _dll.openmc_init(c_void_p(address)) else: _dll.openmc_init(None) diff --git a/src/api.F90 b/src/api.F90 index d7f3ed0235..03ea9bff06 100644 --- a/src/api.F90 +++ b/src/api.F90 @@ -15,7 +15,7 @@ module openmc_api use mesh_header use message_passing use nuclide_header - use initialize, only: openmc_init + use initialize, only: openmc_init_f use particle_header, only: Particle use plot, only: openmc_plot_geometry use random_lcg, only: openmc_get_seed, openmc_set_seed @@ -64,7 +64,7 @@ module openmc_api public :: openmc_get_tally_index public :: openmc_global_tallies public :: openmc_hard_reset - public :: openmc_init + public :: openmc_init_f public :: openmc_load_nuclide public :: openmc_material_add_nuclide public :: openmc_material_get_id diff --git a/src/hdf5_interface.cpp b/src/hdf5_interface.cpp index 5549ac7d81..b31bf8c1ac 100644 --- a/src/hdf5_interface.cpp +++ b/src/hdf5_interface.cpp @@ -1,14 +1,19 @@ #include "hdf5_interface.h" -#include "error.h" - -#include "hdf5.h" -#include "hdf5_hl.h" #include #include #include #include +#include "hdf5.h" +#include "hdf5_hl.h" +#ifdef OPENMC_MPI +#include "mpi.h" +#include "openmc.h" +#endif +#include "error.h" + + namespace openmc { bool @@ -158,7 +163,7 @@ file_open(const char* filename, char mode, bool parallel) if (parallel) { // Setup file access property list with parallel I/O access plist = H5Pcreate(H5P_FILE_ACCESS); - H5Pset_fapl_mpio(plist, mpi_intracomm, MPI_INFO_NULL); + H5Pset_fapl_mpio(plist, openmc_intracomm, MPI_INFO_NULL); } #endif diff --git a/src/initialize.F90 b/src/initialize.F90 index 7b699b9cb7..773c6dbf0e 100644 --- a/src/initialize.F90 +++ b/src/initialize.F90 @@ -41,8 +41,9 @@ contains ! setting up timers, etc. !=============================================================================== - subroutine openmc_init(intracomm) bind(C) + function openmc_init_f(intracomm) result(err) bind(C) integer, intent(in), optional :: intracomm ! MPI intracommunicator + integer(C_INT) :: err #ifdef _OPENMP character(MAX_WORD_LEN) :: envvar @@ -105,7 +106,8 @@ contains ! Stop initialization timer call time_initialize%stop() - end subroutine openmc_init + err = 0 + end function openmc_init_f #ifdef OPENMC_MPI !=============================================================================== diff --git a/src/initialize.cpp b/src/initialize.cpp new file mode 100644 index 0000000000..029a4155d8 --- /dev/null +++ b/src/initialize.cpp @@ -0,0 +1,20 @@ +#include "openmc.h" + +#ifdef OPENMC_MPI +MPI_Comm openmc_intracomm; +#endif + + +int +openmc_init(const void* intracomm) +{ +#ifdef OPENMC_MPI + openmc_intracomm = *static_cast(intracomm); + + MPI_Fint fcomm = MPI_Comm_c2f(openmc_intracomm); + openmc_init_f(&fcomm); +#else + openmc_init_f(nullptr); +#endif + return 0; +} diff --git a/src/main.cpp b/src/main.cpp index 7b2ccb5c3e..2814b538f7 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,17 +1,15 @@ #include "openmc.h" -#ifdef MPI -#include -#else -#define MPI_COMM_WORLD nullptr -#endif - - int main(int argc, char** argv) { int err; // Initialize run -- when run with MPI, pass communicator - openmc_init(MPI_COMM_WORLD); +#ifdef OPENMC_MPI + MPI_Comm world {MPI_COMM_WORLD}; + openmc_init(&world); +#else + openmc_init(nullptr); +#endif // start problem based on mode switch (openmc_run_mode) { From 25b1001558092e487a17e67fcaaacec214022127 Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Fri, 20 Apr 2018 07:02:59 -0500 Subject: [PATCH 46/77] Move mpi-related definitions into message_passing.h --- CMakeLists.txt | 1 + include/openmc.h | 8 -------- src/hdf5_interface.cpp | 4 ++-- src/initialize.cpp | 8 +++----- src/message_passing.cpp | 15 +++++++++++++++ src/message_passing.h | 18 ++++++++++++++++++ 6 files changed, 39 insertions(+), 15 deletions(-) create mode 100644 src/message_passing.cpp create mode 100644 src/message_passing.h diff --git a/CMakeLists.txt b/CMakeLists.txt index ab52510499..8c67728340 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -437,6 +437,7 @@ set(LIBOPENMC_CXX_SRC src/initialize.cpp src/hdf5_interface.h src/hdf5_interface.cpp + src/message_passing.cpp src/random_lcg.cpp src/random_lcg.h src/simulation.cpp diff --git a/include/openmc.h b/include/openmc.h index 85cb09a918..1788fb8cca 100644 --- a/include/openmc.h +++ b/include/openmc.h @@ -4,9 +4,6 @@ #include #include -#ifdef OPENMC_MPI -#include "mpi.h" -#endif #ifdef __cplusplus extern "C" { @@ -150,11 +147,6 @@ extern "C" { extern bool openmc_simulation_initialized; extern int openmc_verbosity; -#ifdef OPENMC_MPI - // MPI variables - extern MPI_Comm openmc_intracomm; -#endif - // Run modes constexpr int RUN_MODE_FIXEDSOURCE {1}; constexpr int RUN_MODE_EIGENVALUE {2}; diff --git a/src/hdf5_interface.cpp b/src/hdf5_interface.cpp index b31bf8c1ac..cbbd7d7c3e 100644 --- a/src/hdf5_interface.cpp +++ b/src/hdf5_interface.cpp @@ -9,7 +9,7 @@ #include "hdf5_hl.h" #ifdef OPENMC_MPI #include "mpi.h" -#include "openmc.h" +#include "message_passing.h" #endif #include "error.h" @@ -163,7 +163,7 @@ file_open(const char* filename, char mode, bool parallel) if (parallel) { // Setup file access property list with parallel I/O access plist = H5Pcreate(H5P_FILE_ACCESS); - H5Pset_fapl_mpio(plist, openmc_intracomm, MPI_INFO_NULL); + H5Pset_fapl_mpio(plist, openmc::mpi::intracomm, MPI_INFO_NULL); } #endif diff --git a/src/initialize.cpp b/src/initialize.cpp index 029a4155d8..4f3261dad7 100644 --- a/src/initialize.cpp +++ b/src/initialize.cpp @@ -1,17 +1,15 @@ #include "openmc.h" -#ifdef OPENMC_MPI -MPI_Comm openmc_intracomm; -#endif +#include "message_passing.h" int openmc_init(const void* intracomm) { #ifdef OPENMC_MPI - openmc_intracomm = *static_cast(intracomm); + openmc::mpi::intracomm = *static_cast(intracomm); - MPI_Fint fcomm = MPI_Comm_c2f(openmc_intracomm); + MPI_Fint fcomm = MPI_Comm_c2f(openmc::mpi::intracomm); openmc_init_f(&fcomm); #else openmc_init_f(nullptr); diff --git a/src/message_passing.cpp b/src/message_passing.cpp new file mode 100644 index 0000000000..3ab96ffd87 --- /dev/null +++ b/src/message_passing.cpp @@ -0,0 +1,15 @@ +#include "message_passing.h" + +namespace openmc { +namespace mpi { + +int rank; +int n_procs; + +#ifdef OPENMC_MPI +MPI_Comm intracomm; +MPI_Datatype bank; +#endif + +} // namespace mpi +} // namespace openmc diff --git a/src/message_passing.h b/src/message_passing.h new file mode 100644 index 0000000000..fea092c618 --- /dev/null +++ b/src/message_passing.h @@ -0,0 +1,18 @@ +#ifndef MESSAGE_PASSING_H +#define MESSAGE_PASSING_H + +namespace openmc { +namespace mpi { + + extern int rank; + extern int n_procs; + +#ifdef OPENMC_MPI + extern MPI_Datatype bank; + extern MPI_Comm intracomm; +#endif + +} // namespace mpi +} // namespace openmc + +#endif // MESSAGE_PASSING_H From 0ee5ec4ecbb634f08c008a08cdcd60617f584c9f Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Fri, 20 Apr 2018 07:25:35 -0500 Subject: [PATCH 47/77] Make sure headers only contain declarations and inline funcs --- CMakeLists.txt | 9 ++----- src/hdf5_interface.cpp | 2 +- src/surface.cpp | 49 ++++++++++++++++++++++++++++++++++++ src/surface.h | 56 +++++++++++------------------------------- src/xml_interface.cpp | 40 ++++++++++++++++++++++++++++++ src/xml_interface.h | 32 ++---------------------- 6 files changed, 109 insertions(+), 79 deletions(-) create mode 100644 src/xml_interface.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 8c67728340..455556f015 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -433,19 +433,14 @@ set(LIBOPENMC_FORTRAN_SRC src/tallies/trigger_header.F90 ) set(LIBOPENMC_CXX_SRC - src/error.h src/initialize.cpp - src/hdf5_interface.h src/hdf5_interface.cpp src/message_passing.cpp src/random_lcg.cpp - src/random_lcg.h src/simulation.cpp src/surface.cpp - src/surface.h - src/xml_interface.h - src/pugixml/pugixml.cpp - src/pugixml/pugixml.hpp) + src/xml_interface.cpp + src/pugixml/pugixml.cpp) add_library(libopenmc SHARED ${LIBOPENMC_FORTRAN_SRC} ${LIBOPENMC_CXX_SRC}) set_target_properties(libopenmc PROPERTIES OUTPUT_NAME openmc) add_executable(${program} src/main.cpp) diff --git a/src/hdf5_interface.cpp b/src/hdf5_interface.cpp index cbbd7d7c3e..1502ec2e12 100644 --- a/src/hdf5_interface.cpp +++ b/src/hdf5_interface.cpp @@ -2,8 +2,8 @@ #include #include -#include #include +#include #include "hdf5.h" #include "hdf5_hl.h" diff --git a/src/surface.cpp b/src/surface.cpp index 9db9db3fa5..2c3279604a 100644 --- a/src/surface.cpp +++ b/src/surface.cpp @@ -11,6 +11,12 @@ namespace openmc { +//============================================================================== +// Global variables +//============================================================================== + +int32_t n_surfaces; + //============================================================================== // Helper functions for reading the "coeffs" node of an XML surface element //============================================================================== @@ -1232,4 +1238,47 @@ read_surfaces(pugi::xml_node *node) } } +//============================================================================== +// Fortran compatibility functions +//============================================================================== + +extern "C" Surface* surface_pointer(int surf_ind) {return surfaces_c[surf_ind];} + +extern "C" int surface_id(Surface *surf) {return surf->id;} + +extern "C" int surface_bc(Surface *surf) {return surf->bc;} + +extern "C" bool surface_sense(Surface *surf, double xyz[3], double uvw[3]) +{return surf->sense(xyz, uvw);} + +extern "C" void surface_reflect(Surface *surf, double xyz[3], double uvw[3]) +{surf->reflect(xyz, uvw);} + +extern "C" double +surface_distance(Surface *surf, double xyz[3], double uvw[3], bool coincident) +{return surf->distance(xyz, uvw, coincident);} + +extern "C" void surface_normal(Surface *surf, double xyz[3], double uvw[3]) +{return surf->normal(xyz, uvw);} + +extern "C" void surface_to_hdf5(Surface *surf, hid_t group) +{surf->to_hdf5(group);} + +extern "C" int surface_i_periodic(PeriodicSurface *surf) +{return surf->i_periodic;} + +extern "C" bool +surface_periodic(PeriodicSurface *surf, PeriodicSurface *other, double xyz[3], + double uvw[3]) +{return surf->periodic_translate(other, xyz, uvw);} + +extern "C" void free_memory_surfaces_c() +{ + for (int i = 0; i < n_surfaces; i++) {delete surfaces_c[i];} + delete surfaces_c; + surfaces_c = nullptr; + n_surfaces = 0; + surface_dict.clear(); +} + } // namespace openmc diff --git a/src/surface.h b/src/surface.h index 627a8fbae2..15ac0d5bdd 100644 --- a/src/surface.h +++ b/src/surface.h @@ -25,15 +25,14 @@ extern "C" const int BC_PERIODIC {3}; //============================================================================== extern "C" double FP_COINCIDENT; -constexpr double INFTY{std::numeric_limits::max()}; +constexpr double INFTY {std::numeric_limits::max()}; constexpr int C_NONE {-1}; //============================================================================== // Global variables //============================================================================== -// Braces force n_surfaces to be defined here, not just declared. -extern "C" {int32_t n_surfaces {0};} +extern "C" int32_t n_surfaces; class Surface; Surface **surfaces_c; @@ -384,44 +383,19 @@ public: // Fortran compatibility functions //============================================================================== -extern "C" Surface* surface_pointer(int surf_ind) {return surfaces_c[surf_ind];} - -extern "C" int surface_id(Surface *surf) {return surf->id;} - -extern "C" int surface_bc(Surface *surf) {return surf->bc;} - -extern "C" bool surface_sense(Surface *surf, double xyz[3], double uvw[3]) -{return surf->sense(xyz, uvw);} - -extern "C" void surface_reflect(Surface *surf, double xyz[3], double uvw[3]) -{surf->reflect(xyz, uvw);} - -extern "C" double -surface_distance(Surface *surf, double xyz[3], double uvw[3], bool coincident) -{return surf->distance(xyz, uvw, coincident);} - -extern "C" void surface_normal(Surface *surf, double xyz[3], double uvw[3]) -{return surf->normal(xyz, uvw);} - -extern "C" void surface_to_hdf5(Surface *surf, hid_t group) -{surf->to_hdf5(group);} - -extern "C" int surface_i_periodic(PeriodicSurface *surf) -{return surf->i_periodic;} - -extern "C" bool -surface_periodic(PeriodicSurface *surf, PeriodicSurface *other, double xyz[3], - double uvw[3]) -{return surf->periodic_translate(other, xyz, uvw);} - -extern "C" void free_memory_surfaces_c() -{ - for (int i = 0; i < n_surfaces; i++) {delete surfaces_c[i];} - delete surfaces_c; - surfaces_c = nullptr; - n_surfaces = 0; - surface_dict.clear(); -} +extern "C" Surface* surface_pointer(int surf_ind); +extern "C" int surface_id(Surface *surf); +extern "C" int surface_bc(Surface *surf); +extern "C" bool surface_sense(Surface *surf, double xyz[3], double uvw[3]); +extern "C" void surface_reflect(Surface *surf, double xyz[3], double uvw[3]); +extern "C" double surface_distance(Surface *surf, double xyz[3], double uvw[3], + bool coincident); +extern "C" void surface_normal(Surface *surf, double xyz[3], double uvw[3]); +extern "C" void surface_to_hdf5(Surface *surf, hid_t group); +extern "C" int surface_i_periodic(PeriodicSurface *surf); +extern "C" bool surface_periodic(PeriodicSurface *surf, PeriodicSurface *other, + double xyz[3], double uvw[3]); +extern "C" void free_memory_surfaces_c(); } // namespace openmc #endif // SURFACE_H diff --git a/src/xml_interface.cpp b/src/xml_interface.cpp new file mode 100644 index 0000000000..aea1c2c17b --- /dev/null +++ b/src/xml_interface.cpp @@ -0,0 +1,40 @@ +#include "xml_interface.h" + +#include // for std::transform +#include +#include + +#include "pugixml/pugixml.hpp" +#include "error.h" + + +namespace openmc { + +std::string +get_node_value(pugi::xml_node node, const char *name) +{ + // Search for either an attribute or child tag and get the data as a char*. + const pugi::char_t *value_char; + if (node.attribute(name)) { + value_char = node.attribute(name).value(); + } else if (node.child(name)) { + value_char = node.child_value(name); + } else { + std::stringstream err_msg; + err_msg << "Node \"" << name << "\" is not a member of the \"" + << node.name() << "\" XML node"; + fatal_error(err_msg); + } + + // Convert to lowercase string. + std::string value(value_char); + std::transform(value.begin(), value.end(), value.begin(), ::tolower); + + // Remove whitespace. + value.erase(0, value.find_first_not_of(" \t\r\n")); + value.erase(value.find_last_not_of(" \t\r\n") + 1); + + return value; +} + +} // namespace openmc diff --git a/src/xml_interface.h b/src/xml_interface.h index 778497562b..52aa6003f4 100644 --- a/src/xml_interface.h +++ b/src/xml_interface.h @@ -1,8 +1,6 @@ #ifndef XML_INTERFACE_H #define XML_INTERFACE_H -#include // for std::transform -#include #include #include "pugixml/pugixml.hpp" @@ -10,39 +8,13 @@ namespace openmc { -bool +inline bool check_for_node(pugi::xml_node node, const char *name) { return node.attribute(name) || node.child(name); } - -std::string -get_node_value(pugi::xml_node node, const char *name) -{ - // Search for either an attribute or child tag and get the data as a char*. - const pugi::char_t *value_char; - if (node.attribute(name)) { - value_char = node.attribute(name).value(); - } else if (node.child(name)) { - value_char = node.child_value(name); - } else { - std::stringstream err_msg; - err_msg << "Node \"" << name << "\" is not a member of the \"" - << node.name() << "\" XML node"; - fatal_error(err_msg); - } - - // Convert to lowercase string. - std::string value(value_char); - std::transform(value.begin(), value.end(), value.begin(), ::tolower); - - // Remove whitespace. - value.erase(0, value.find_first_not_of(" \t\r\n")); - value.erase(value.find_last_not_of(" \t\r\n") + 1); - - return value; -} +std::string get_node_value(pugi::xml_node node, const char *name); } // namespace openmc #endif // XML_INTERFACE_H From 44ff22dc148ecf64e8e61cf589f9abcb89e84bd9 Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Fri, 20 Apr 2018 11:03:40 -0500 Subject: [PATCH 48/77] Convert write_source_bank to C++, move some MPI initialization over too --- CMakeLists.txt | 1 + include/openmc.h | 7 +- openmc/capi/core.py | 14 ++-- src/initialize.F90 | 16 ----- src/initialize.cpp | 42 +++++++++++- src/message_passing.F90 | 6 +- src/simulation_header.F90 | 4 +- src/source.F90 | 2 +- src/state_point.F90 | 135 ++++---------------------------------- src/state_point.cpp | 112 +++++++++++++++++++++++++++++++ src/state_point.h | 15 +++++ 11 files changed, 200 insertions(+), 154 deletions(-) create mode 100644 src/state_point.cpp create mode 100644 src/state_point.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 455556f015..9b750a6dd3 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -438,6 +438,7 @@ set(LIBOPENMC_CXX_SRC src/message_passing.cpp src/random_lcg.cpp src/simulation.cpp + src/state_point.cpp src/surface.cpp src/xml_interface.cpp src/pugixml/pugixml.cpp) diff --git a/include/openmc.h b/include/openmc.h index 1788fb8cca..7f2bbf46c7 100644 --- a/include/openmc.h +++ b/include/openmc.h @@ -127,7 +127,6 @@ extern "C" { extern char openmc_err_msg[256]; extern double openmc_keff; extern double openmc_keff_std; - extern bool openmc_master; extern int32_t n_batches; extern int32_t n_cells; extern int32_t n_filters; @@ -147,6 +146,12 @@ extern "C" { extern bool openmc_simulation_initialized; extern int openmc_verbosity; + // Variables that are shared by necessity (can be removed later) + extern bool openmc_master; + extern int openmc_n_procs; + extern int openmc_rank; + extern int64_t openmc_work; + // Run modes constexpr int RUN_MODE_FIXEDSOURCE {1}; constexpr int RUN_MODE_EIGENVALUE {2}; diff --git a/openmc/capi/core.py b/openmc/capi/core.py index a278e69d5b..57e2e88ebd 100644 --- a/openmc/capi/core.py +++ b/openmc/capi/core.py @@ -118,11 +118,15 @@ def init(intracomm=None): if intracomm is not None: # If an mpi4py communicator was passed, convert it to void* to be passed # to openmc_init - from mpi4py import MPI - address = MPI._addressof(intracomm) - _dll.openmc_init(c_void_p(address)) - else: - _dll.openmc_init(None) + try: + from mpi4py import MPI + except ImportError: + intracomm = None + else: + address = MPI._addressof(intracomm) + intracomm = c_void_p(address) + + _dll.openmc_init(intracomm) def iter_batches(): diff --git a/src/initialize.F90 b/src/initialize.F90 index 773c6dbf0e..7b8f37dee6 100644 --- a/src/initialize.F90 +++ b/src/initialize.F90 @@ -131,27 +131,11 @@ contains integer :: bank_types(5) ! Datatypes #endif integer(MPI_ADDRESS_KIND) :: bank_disp(5) ! Displacements - logical :: init_called type(Bank) :: b ! Indicate that MPI is turned on mpi_enabled = .true. - - ! Initialize MPI - call MPI_INITIALIZED(init_called, mpi_err) - if (.not. init_called) call MPI_INIT(mpi_err) - - ! Determine number of processors and rank of each processor mpi_intracomm = intracomm - call MPI_COMM_SIZE(mpi_intracomm, n_procs, mpi_err) - call MPI_COMM_RANK(mpi_intracomm, rank, mpi_err) - - ! Determine master - if (rank == 0) then - master = .true. - else - master = .false. - end if ! ========================================================================== ! CREATE MPI_BANK TYPE diff --git a/src/initialize.cpp b/src/initialize.cpp index 4f3261dad7..d32a6c97f3 100644 --- a/src/initialize.cpp +++ b/src/initialize.cpp @@ -3,12 +3,14 @@ #include "message_passing.h" -int -openmc_init(const void* intracomm) +int openmc_init(const void* intracomm) { #ifdef OPENMC_MPI - openmc::mpi::intracomm = *static_cast(intracomm); + // Initialize MPI for C++ + MPI_Comm intracomm = *static_cast(intracomm); + initialize_mpi(intracomm); + // Continue with rest of initialization MPI_Fint fcomm = MPI_Comm_c2f(openmc::mpi::intracomm); openmc_init_f(&fcomm); #else @@ -16,3 +18,37 @@ openmc_init(const void* intracomm) #endif return 0; } + + +#ifdef OPENMC_MPI +void initialize_mpi(MPI_Comm intracomm) +{ + openmc::mpi::intracomm = intracomm; + + // Initialize MPI + int flag; + if (!MPI_Initialized(&flag)) MPI_Init(nullptr, nullptr); + + // Determine number of processes and rank for each + MPI_Comm_size(intracomm, openmc::mpi::n_procs); + MPI_Comm_rank(intracomm, openmc::mpi::rank); + + // Set variable for Fortran side + openmc_n_procs = openmc::mpi::n_procs; + openmc_rank = openmc::mpi::rank; + openmc_master = (openmc::mpi::rank == 0); + + // Create bank datatype + Bank b; + MPI_Aint disp[5]; + disp[0] = &b.wgt - &b; + disp[1] = &b.xyz - &b; + disp[2] = &b.uvw - &b; + disp[3] = &b.E - &b; + disp[4] = &b.delayed_group - &b; + int blocks[] {1, 3, 3, 1, 1}; + MPI_Datatype types[] {MPI_DOUBLE, MPI_DOUBLE, MPI_DOUBLE, MPI_DOUBLE, MPI_INT}; + MPI_Type_create_struct(5, blocks, disp, types, &openmc::mpi::bank); + MPI_Type_commit(&openmc::mpi::bank); +} +#endif diff --git a/src/message_passing.F90 b/src/message_passing.F90 index f9a16ee759..6ade0895a9 100644 --- a/src/message_passing.F90 +++ b/src/message_passing.F90 @@ -14,9 +14,9 @@ module message_passing ! mpi_enabled flag are for when MPI is not being used at all, i.e. a serial ! run. In this case, these variables are still used at times. - integer :: n_procs = 1 ! number of processes - integer :: rank = 0 ! rank of process - logical(C_BOOL), bind(C, name='openmc_master') :: master = .true. ! master process? + integer(C_INT), bind(C, name='openmc_n_procs') :: n_procs = 1 ! number of processes + integer(C_INT), bind(C, name='openmc_rank') :: rank = 0 ! rank of process + logical(C_BOOL), bind(C, name='openmc_master') :: master = .true. ! master process? logical :: mpi_enabled = .false. ! is MPI in use and initialized? #ifdef OPENMC_MPIF08 type(MPI_Datatype) :: MPI_BANK ! MPI datatype for fission bank diff --git a/src/simulation_header.F90 b/src/simulation_header.F90 index 67bf3062bd..a214f4410b 100644 --- a/src/simulation_header.F90 +++ b/src/simulation_header.F90 @@ -32,8 +32,8 @@ module simulation_header logical :: satisfy_triggers = .false. ! whether triggers are satisfied - integer(8) :: work ! number of particles per processor - integer(8), allocatable :: work_index(:) ! starting index in source bank for each process + integer(C_INT64_T), bind(C, name='openmc_work') :: work ! number of particles per processor + integer(C_INT64_T), allocatable :: work_index(:) ! starting index in source bank for each process integer(8) :: current_work ! index in source bank of current history simulated ! ============================================================================ diff --git a/src/source.F90 b/src/source.F90 index 8e142fcfaa..59a117465c 100644 --- a/src/source.F90 +++ b/src/source.F90 @@ -88,7 +88,7 @@ contains call write_message('Writing out initial source...', 5) filename = trim(path_output) // 'initial_source.h5' file_id = file_open(filename, 'w', parallel=.true.) - call write_source_bank(file_id) + call write_source_bank(file_id, work_index, source_bank) call file_close(file_id) end if diff --git a/src/state_point.F90 b/src/state_point.F90 index 62240f110a..181ab968b9 100644 --- a/src/state_point.F90 +++ b/src/state_point.F90 @@ -15,6 +15,7 @@ module state_point use hdf5 + use bank_header, only: Bank use cmfd_header use constants use eigenvalue, only: openmc_get_keff @@ -37,6 +38,15 @@ module state_point implicit none + interface + subroutine write_source_bank(group_id, work_index, bank_) bind(C) + import HID_T, C_INT64_T, Bank + integer(HID_T), value :: group_id + integer(C_INT64_T), intent(in) :: work_index(*) + type(Bank), intent(in) :: bank_(*) + end subroutine write_source_bank + end interface + contains !=============================================================================== @@ -489,7 +499,7 @@ contains end if end if - call write_source_bank(file_id) + call write_source_bank(file_id, work_index, source_bank) if (master .or. parallel) call file_close(file_id) end if @@ -502,7 +512,7 @@ contains call write_dataset(file_id, "filetype", 'source') end if - call write_source_bank(file_id) + call write_source_bank(file_id, work_index, source_bank) if (master .or. parallel) call file_close(file_id) end if @@ -831,132 +841,11 @@ contains end subroutine load_state_point -!=============================================================================== -! WRITE_SOURCE_BANK writes OpenMC source_bank data -!=============================================================================== - - subroutine write_source_bank(group_id) - use bank_header, only: Bank - - integer(HID_T), intent(in) :: group_id - - integer :: hdf5_err - integer(HID_T) :: dset ! data set handle - integer(HID_T) :: dspace ! data or file space handle - integer(HID_T) :: memspace ! memory space handle - integer(HSIZE_T) :: offset(1) ! source data offset - integer(HSIZE_T) :: dims(1) - type(c_ptr) :: f_ptr -#ifdef PHDF5 - integer(HID_T) :: plist ! property list -#else - integer :: i -#ifdef OPENMC_MPI - integer :: mpi_err ! MPI error code - type(Bank), allocatable, target :: temp_source(:) -#endif -#endif - -#ifdef PHDF5 - ! Set size of total dataspace for all procs and rank - dims(1) = n_particles - call h5screate_simple_f(1, dims, dspace, hdf5_err) - call h5dcreate_f(group_id, "source_bank", hdf5_bank_t, dspace, dset, hdf5_err) - - ! Create another data space but for each proc individually - dims(1) = work - call h5screate_simple_f(1, dims, memspace, hdf5_err) - - ! Select hyperslab for this dataspace - offset(1) = work_index(rank) - call h5sselect_hyperslab_f(dspace, H5S_SELECT_SET_F, offset, dims, hdf5_err) - - ! Set up the property list for parallel writing - call h5pcreate_f(H5P_DATASET_XFER_F, plist, hdf5_err) - call h5pset_dxpl_mpio_f(plist, H5FD_MPIO_COLLECTIVE_F, hdf5_err) - - ! Set up pointer to data - f_ptr = c_loc(source_bank) - - ! Write data to file in parallel - call h5dwrite_f(dset, hdf5_bank_t, f_ptr, hdf5_err, & - file_space_id=dspace, mem_space_id=memspace, & - xfer_prp=plist) - - ! Close all ids - call h5sclose_f(dspace, hdf5_err) - call h5sclose_f(memspace, hdf5_err) - call h5dclose_f(dset, hdf5_err) - call h5pclose_f(plist, hdf5_err) - -#else - - if (master) then - ! Create dataset big enough to hold all source sites - dims(1) = n_particles - call h5screate_simple_f(1, dims, dspace, hdf5_err) - call h5dcreate_f(group_id, "source_bank", hdf5_bank_t, & - dspace, dset, hdf5_err) - - ! Save source bank sites since the souce_bank array is overwritten below -#ifdef OPENMC_MPI - allocate(temp_source(work)) - temp_source(:) = source_bank(:) -#endif - - do i = 0, n_procs - 1 - ! Create memory space - dims(1) = work_index(i+1) - work_index(i) - call h5screate_simple_f(1, dims, memspace, hdf5_err) - -#ifdef OPENMC_MPI - ! Receive source sites from other processes - if (i > 0) then - call MPI_RECV(source_bank, int(dims(1)), MPI_BANK, i, i, & - mpi_intracomm, MPI_STATUS_IGNORE, mpi_err) - end if -#endif - - ! Select hyperslab for this dataspace - call h5dget_space_f(dset, dspace, hdf5_err) - offset(1) = work_index(i) - call h5sselect_hyperslab_f(dspace, H5S_SELECT_SET_F, offset, dims, hdf5_err) - - ! Set up pointer to data and write data to hyperslab - f_ptr = c_loc(source_bank) - call h5dwrite_f(dset, hdf5_bank_t, f_ptr, hdf5_err, & - file_space_id=dspace, mem_space_id=memspace) - - call h5sclose_f(memspace, hdf5_err) - call h5sclose_f(dspace, hdf5_err) - end do - - ! Close all ids - call h5dclose_f(dset, hdf5_err) - - ! Restore state of source bank -#ifdef OPENMC_MPI - source_bank(:) = temp_source(:) - deallocate(temp_source) -#endif - else -#ifdef OPENMC_MPI - call MPI_SEND(source_bank, int(work), MPI_BANK, 0, rank, & - mpi_intracomm, mpi_err) -#endif - end if - -#endif - - end subroutine write_source_bank - !=============================================================================== ! READ_SOURCE_BANK reads OpenMC source_bank data !=============================================================================== subroutine read_source_bank(group_id) - use bank_header, only: Bank - integer(HID_T), intent(in) :: group_id integer :: hdf5_err diff --git a/src/state_point.cpp b/src/state_point.cpp new file mode 100644 index 0000000000..20338c4be5 --- /dev/null +++ b/src/state_point.cpp @@ -0,0 +1,112 @@ +#include "state_point.h" + +#include +#include + +#include "mpi.h" +#include "message_passing.h" +#include "openmc.h" + +namespace openmc { + +void +write_source_bank(hid_t group_id, int64_t* work_index, const Bank* source_bank) +{ + // Create type for array of 3 reals + hsize_t dims[] {3}; + hid_t triplet = H5Tarray_create(H5T_NATIVE_DOUBLE, 1, dims); + + // Create bank datatype + hid_t banktype = H5Tcreate(H5T_COMPOUND, sizeof(struct Bank)); + H5Tinsert(banktype, "wgt", HOFFSET(Bank, wgt), H5T_NATIVE_DOUBLE); + H5Tinsert(banktype, "xyz", HOFFSET(Bank, xyz), triplet); + H5Tinsert(banktype, "uvw", HOFFSET(Bank, uvw), triplet); + H5Tinsert(banktype, "E", HOFFSET(Bank, E), H5T_NATIVE_DOUBLE); + H5Tinsert(banktype, "delayed_group", HOFFSET(Bank, delayed_group), H5T_NATIVE_INT); + +#ifdef PHDF5 + // Set size of total dataspace for all procs and rank + dims[0] = n_particles; + hid_t dspace = H5Screate_simple(1, dims, H5P_DEFAULT); + hid_t dset = H5Dcreate(group_id, "source_bank", banktype, dspace, + H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT); + + // Create another data space but for each proc individually + hsize_t count[] {openmc_work}; + hid_t memspace = H5Screate_simple(1, count, H5P_DEFAULT); + + // Select hyperslab for this dataspace + hsize_t start[] {work_index[openmc::mpi::rank]}; + H5Sselect_hyperslab(dspace, H5S_SELECT_SET, start, nullptr, count, nullptr); + + // Set up the property list for parallel writing + hid_t plist = H5Pcreate(H5P_DATASET_XFER); + H5Pset_dxpl_mpio_f(plist, H5FD_MPIO_COLLECTIVE); + + // Write data to file in parallel + H5Dwrite(dset, banktype, memspace, dspace, memspace, plist, source_bank); + + // Free resources + H5Sclose(dspace); + h5sclose(memspace); + H5Dclose(dset); + H5Pclose(plist); + +#else + + if (openmc_master) { + // Create dataset big enough to hold all source sites + hsize_t dims[] {static_cast(n_particles)}; + hid_t dspace = H5Screate_simple(1, dims, H5P_DEFAULT); + hid_t dset = H5Dcreate(group_id, "source_bank", banktype, dspace, + H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT); + + // Save source bank sites since the souce_bank array is overwritten below +#ifdef OPENMC_MPI + std::vector temp_source {source_bank, source_bank + openmc_work}; +#endif + + for (int i = 0; i < openmc::mpi::n_procs; ++i) { + // Create memory space + hsize_t count[] {static_cast(work_index[i+1] - work_index[i])}; + hid_t memspace = H5Screate_simple(1, count, H5P_DEFAULT); + +#ifdef OPENMC_MPI + // Receive source sites from other processes + if (i > 0) + MPI_Recv(source_bank, count[0], openmc::mpi::bank, i, i, + openmc::mpi::intracomm, MPI_STATUS_IGNORE); +#endif + + // Select hyperslab for this dataspace + dspace = H5Dget_space(dset); + hsize_t start[] {static_cast(work_index[i])}; + H5Sselect_hyperslab(dspace, H5S_SELECT_SET, start, nullptr, count, nullptr); + + // Write data to hyperslab + H5Dwrite(dset, banktype, memspace, dspace, H5P_DEFAULT, source_bank); + + H5Sclose(memspace); + H5Sclose(dspace); + } + + // Close all ids + H5Dclose(dset); + +#ifdef OPENMC_MPI + // Restore state of source bank + std::copy(temp_source.begin(), temp_source.end(), source_bank); +#endif + } else { +#ifdef OPENMC_MPI + MPI_Send(source_bank, openmc_work, openmc::mpi::bank, 0, openmc::mpi::rank, + openmc::mpi::mpi_intracomm); +#endif + } +#endif + + H5Tclose(banktype); + H5Tclose(triplet); +} + +} // namespace openmc diff --git a/src/state_point.h b/src/state_point.h new file mode 100644 index 0000000000..f0dafdb809 --- /dev/null +++ b/src/state_point.h @@ -0,0 +1,15 @@ +#ifndef STATE_POINT_H +#define STATE_POINT_H + +#include + +#include "hdf5.h" +#include "openmc.h" + +namespace openmc { + +extern "C" void write_source_bank(hid_t group_id, int64_t* work_index, + const struct Bank* bank); + +} // namespace openmc +#endif // STATE_POINT_H From 65095096f9ad72981f1be9c6ad9d89e55e77ea12 Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Fri, 20 Apr 2018 13:53:53 -0500 Subject: [PATCH 49/77] Convert read_source_bank to C++ and fix a bunch of bugs --- src/hdf5_interface.F90 | 18 +++++------ src/hdf5_interface.cpp | 7 +++- src/initialize.cpp | 40 +++++++++++++++-------- src/initialize.h | 14 ++++++++ src/main.cpp | 4 +++ src/message_passing.h | 2 ++ src/mgxs_data.F90 | 4 +++ src/mgxs_header.F90 | 20 ++++++++++++ src/source.F90 | 2 +- src/state_point.F90 | 73 +++++------------------------------------- src/state_point.cpp | 71 ++++++++++++++++++++++++++++++++++------ src/state_point.h | 4 ++- 12 files changed, 159 insertions(+), 100 deletions(-) create mode 100644 src/initialize.h diff --git a/src/hdf5_interface.F90 b/src/hdf5_interface.F90 index 752ce062dc..d76f7b6b71 100644 --- a/src/hdf5_interface.F90 +++ b/src/hdf5_interface.F90 @@ -138,7 +138,7 @@ module hdf5_interface integer(HID_T), value :: obj_id type(C_PTR), value :: name real(C_DOUBLE), intent(out) :: buffer(*) - logical(C_BOOL), intent(in) :: indep + logical(C_BOOL), value :: indep end subroutine read_double_c subroutine read_attr_int_c(obj_id, name, buffer) & @@ -172,7 +172,7 @@ module hdf5_interface integer(HID_T), value :: obj_id type(C_PTR), value :: name integer(C_INT), intent(out) :: buffer(*) - logical(C_BOOL), intent(in) :: indep + logical(C_BOOL), value :: indep end subroutine read_int_c subroutine read_llong_c(obj_id, name, buffer, indep) & @@ -181,7 +181,7 @@ module hdf5_interface integer(HID_T), value :: obj_id type(C_PTR), value :: name integer(C_LONG_LONG), intent(out) :: buffer(*) - logical(C_BOOL), intent(in) :: indep + logical(C_BOOL), value :: indep end subroutine read_llong_c subroutine read_string_c(obj_id, name, slen, buffer, indep) & @@ -191,7 +191,7 @@ module hdf5_interface type(C_PTR), value :: name integer(C_SIZE_T), value :: slen character(kind=C_CHAR), intent(out) :: buffer(*) - logical(C_BOOL), intent(in) :: indep + logical(C_BOOL), value :: indep end subroutine read_string_c subroutine read_complex_c(obj_id, name, buffer, indep) & @@ -200,7 +200,7 @@ module hdf5_interface integer(HID_T), value :: obj_id type(C_PTR), value :: name complex(C_DOUBLE_COMPLEX), intent(out) :: buffer(*) - logical(C_BOOL), intent(in) :: indep + logical(C_BOOL), value :: indep end subroutine read_complex_c subroutine write_attr_double_c(obj_id, ndim, dims, name, buffer) & @@ -239,7 +239,7 @@ module hdf5_interface integer(HSIZE_T), intent(in) :: dims(*) character(kind=C_CHAR), intent(in) :: name(*) real(C_DOUBLE), intent(in) :: buffer(*) - logical(C_BOOL), intent(in) :: indep + logical(C_BOOL), value :: indep end subroutine write_double_c subroutine write_int_c(group_id, ndim, dims, name, buffer, indep) & @@ -250,7 +250,7 @@ module hdf5_interface integer(HSIZE_T), intent(in) :: dims(*) character(kind=C_CHAR), intent(in) :: name(*) integer(C_INT), intent(in) :: buffer(*) - logical(C_BOOL), intent(in) :: indep + logical(C_BOOL), value :: indep end subroutine write_int_c subroutine write_llong_c(group_id, ndim, dims, name, buffer, indep) & @@ -261,7 +261,7 @@ module hdf5_interface integer(HSIZE_T), intent(in) :: dims(*) character(kind=C_CHAR), intent(in) :: name(*) integer(C_LONG_LONG), intent(in) :: buffer(*) - logical(C_BOOL), intent(in) :: indep + logical(C_BOOL), value :: indep end subroutine write_llong_c subroutine write_string_c(group_id, ndim, dims, slen, name, buffer, indep) & @@ -273,7 +273,7 @@ module hdf5_interface integer(C_SIZE_T), value :: slen character(kind=C_CHAR), intent(in) :: name(*) character(kind=C_CHAR), intent(in) :: buffer(*) - logical(C_BOOL), intent(in) :: indep + logical(C_BOOL), value :: indep end subroutine write_string_c end interface diff --git a/src/hdf5_interface.cpp b/src/hdf5_interface.cpp index 1502ec2e12..d81c5b34a8 100644 --- a/src/hdf5_interface.cpp +++ b/src/hdf5_interface.cpp @@ -174,6 +174,11 @@ file_open(const char* filename, char mode, bool parallel) } else { file_id = H5Fopen(filename, flags, plist); } + if (file_id < 0) { + std::stringstream msg; + msg << "Failed to open HDF5 file with mode '" << mode << "': " << filename; + fatal_error(msg); + } #ifdef PHDF5 // Close the property list @@ -451,7 +456,7 @@ write_dataset(hid_t group_id, int ndim, const hsize_t* dims, const char* name, if (using_mpio_device(group_id)) { #ifdef PHDF5 // Set up collective vs independent I/O - auto data_xfer_mode {indep ? H5FD_MPIO_INDEPENDENT : H5FD_MPIO_COLLECTIVE}; + auto data_xfer_mode = indep ? H5FD_MPIO_INDEPENDENT : H5FD_MPIO_COLLECTIVE; // Create dataset transfer property list hid_t plist = H5Pcreate(H5P_DATASET_XFER); diff --git a/src/initialize.cpp b/src/initialize.cpp index d32a6c97f3..23025feb23 100644 --- a/src/initialize.cpp +++ b/src/initialize.cpp @@ -1,17 +1,27 @@ -#include "openmc.h" +#include "initialize.h" + +#include #include "message_passing.h" +#include "openmc.h" int openmc_init(const void* intracomm) { #ifdef OPENMC_MPI + // Check if intracomm was passed + MPI_Comm comm; + if (intracomm) { + comm = *static_cast(intracomm); + } else { + comm = MPI_COMM_WORLD; + } + // Initialize MPI for C++ - MPI_Comm intracomm = *static_cast(intracomm); - initialize_mpi(intracomm); + openmc::initialize_mpi(comm); // Continue with rest of initialization - MPI_Fint fcomm = MPI_Comm_c2f(openmc::mpi::intracomm); + MPI_Fint fcomm = MPI_Comm_c2f(comm); openmc_init_f(&fcomm); #else openmc_init_f(nullptr); @@ -19,6 +29,7 @@ int openmc_init(const void* intracomm) return 0; } +namespace openmc { #ifdef OPENMC_MPI void initialize_mpi(MPI_Comm intracomm) @@ -30,8 +41,8 @@ void initialize_mpi(MPI_Comm intracomm) if (!MPI_Initialized(&flag)) MPI_Init(nullptr, nullptr); // Determine number of processes and rank for each - MPI_Comm_size(intracomm, openmc::mpi::n_procs); - MPI_Comm_rank(intracomm, openmc::mpi::rank); + MPI_Comm_size(intracomm, &openmc::mpi::n_procs); + MPI_Comm_rank(intracomm, &openmc::mpi::rank); // Set variable for Fortran side openmc_n_procs = openmc::mpi::n_procs; @@ -40,15 +51,18 @@ void initialize_mpi(MPI_Comm intracomm) // Create bank datatype Bank b; - MPI_Aint disp[5]; - disp[0] = &b.wgt - &b; - disp[1] = &b.xyz - &b; - disp[2] = &b.uvw - &b; - disp[3] = &b.E - &b; - disp[4] = &b.delayed_group - &b; + MPI_Aint disp[] { + offsetof(Bank, wgt), + offsetof(Bank, xyz), + offsetof(Bank, uvw), + offsetof(Bank, E), + offsetof(Bank, delayed_group) + }; int blocks[] {1, 3, 3, 1, 1}; MPI_Datatype types[] {MPI_DOUBLE, MPI_DOUBLE, MPI_DOUBLE, MPI_DOUBLE, MPI_INT}; MPI_Type_create_struct(5, blocks, disp, types, &openmc::mpi::bank); MPI_Type_commit(&openmc::mpi::bank); } -#endif + +#endif // OPENMC_MPI +} // namespace openmc diff --git a/src/initialize.h b/src/initialize.h new file mode 100644 index 0000000000..430987038d --- /dev/null +++ b/src/initialize.h @@ -0,0 +1,14 @@ +#ifndef INITIALIZE_H +#define INITIALIZE_H + +#include "mpi.h" + +namespace openmc { + +#ifdef OPENMC_MPI + void initialize_mpi(MPI_Comm intracomm); +#endif + +} + +#endif // INITIALIZE_H diff --git a/src/main.cpp b/src/main.cpp index 2814b538f7..1dd20ebe04 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,5 +1,9 @@ +#ifdef OPENMC_MPI +#include "mpi.h" +#endif #include "openmc.h" + int main(int argc, char** argv) { int err; diff --git a/src/message_passing.h b/src/message_passing.h index fea092c618..67353e23a1 100644 --- a/src/message_passing.h +++ b/src/message_passing.h @@ -1,6 +1,8 @@ #ifndef MESSAGE_PASSING_H #define MESSAGE_PASSING_H +#include "mpi.h" + namespace openmc { namespace mpi { diff --git a/src/mgxs_data.F90 b/src/mgxs_data.F90 index 1b14e6e9f0..e0631d16c5 100644 --- a/src/mgxs_data.F90 +++ b/src/mgxs_data.F90 @@ -132,6 +132,8 @@ contains ! Add name to dictionary call already_read % add(name) + call close_group(xsdata_group) + end if end do NUCLIDE_LOOP end do MATERIAL_LOOP @@ -159,6 +161,8 @@ contains end do NUCLIDE_LOOP2 end do MATERIAL_LOOP3 + call file_close(file_id) + end subroutine read_mgxs !=============================================================================== diff --git a/src/mgxs_header.F90 b/src/mgxs_header.F90 index e599a89ff3..76042703af 100644 --- a/src/mgxs_header.F90 +++ b/src/mgxs_header.F90 @@ -549,6 +549,8 @@ contains else call fatal_error("beta must be provided as a 1D or 2D array") end if + + call close_dataset(xsdata) else temp_beta = ZERO end if @@ -679,6 +681,8 @@ contains call fatal_error("nu-fission must be provided as a 1D or 2D & &array") end if + + call close_dataset(xsdata) end if ! If chi-prompt provided, set chi-prompt @@ -782,6 +786,8 @@ contains call fatal_error("chi-delayed must be provided as a 1D or 2D & &array") end if + + call close_dataset(xsdata) end if ! If prompt-nu-fission present, set prompt-nu-fission @@ -838,6 +844,8 @@ contains call fatal_error("prompt-nu-fission must be provided as a 1D & &or 2D array") end if + + call close_dataset(xsdata) end if ! If delayed-nu-fission provided, set delayed-nu-fission. If @@ -963,6 +971,8 @@ contains call fatal_error("delayed-nu-fission must be provided as a & &1D, 2D, or 3D array") end if + + call close_dataset(xsdata) end if ! Deallocate temporary beta array @@ -1346,6 +1356,8 @@ contains else call fatal_error("beta must be provided as a 3D or 4D array") end if + + call close_dataset(xsdata) else temp_beta = ZERO end if @@ -1517,6 +1529,8 @@ contains call fatal_error("nu-fission must be provided as a 3D or & &4D array") end if + + call close_dataset(xsdata) end if ! If chi-prompt provided, set chi-prompt @@ -1651,6 +1665,8 @@ contains call fatal_error("chi-delayed must be provided as a 3D or 4D & &array") end if + + call close_dataset(xsdata) end if ! If prompt-nu-fission present, set prompt-nu-fission @@ -1720,6 +1736,8 @@ contains call fatal_error("prompt-nu-fission must be provided as a 3D & &or 4D array") end if + + call close_dataset(xsdata) end if ! If delayed-nu-fission provided, set delayed-nu-fission. If @@ -1868,6 +1886,8 @@ contains call fatal_error("delayed-nu-fission must be provided as a & &3D, 4D, or 5D array") end if + + call close_dataset(xsdata) end if ! Deallocate temporary beta array diff --git a/src/source.F90 b/src/source.F90 index 59a117465c..b02430823b 100644 --- a/src/source.F90 +++ b/src/source.F90 @@ -63,7 +63,7 @@ contains end if ! Read in the source bank - call read_source_bank(file_id) + call read_source_bank(file_id, work_index, source_bank) ! Close file call file_close(file_id) diff --git a/src/state_point.F90 b/src/state_point.F90 index 181ab968b9..5b1c4d462a 100644 --- a/src/state_point.F90 +++ b/src/state_point.F90 @@ -13,8 +13,6 @@ module state_point use, intrinsic :: ISO_C_BINDING - use hdf5 - use bank_header, only: Bank use cmfd_header use constants @@ -45,6 +43,13 @@ module state_point integer(C_INT64_T), intent(in) :: work_index(*) type(Bank), intent(in) :: bank_(*) end subroutine write_source_bank + + subroutine read_source_bank(group_id, work_index, bank_) bind(C) + import HID_T, C_INT64_T, Bank + integer(HID_T), value :: group_id + integer(C_INT64_T), intent(in) :: work_index(*) + type(Bank), intent(out) :: bank_(*) + end subroutine read_source_bank end interface contains @@ -832,7 +837,7 @@ contains end if ! Write out source - call read_source_bank(file_id) + call read_source_bank(file_id, work_index, source_bank) end if @@ -841,66 +846,4 @@ contains end subroutine load_state_point -!=============================================================================== -! READ_SOURCE_BANK reads OpenMC source_bank data -!=============================================================================== - - subroutine read_source_bank(group_id) - integer(HID_T), intent(in) :: group_id - - integer :: hdf5_err - integer(HID_T) :: dset ! data set handle - integer(HID_T) :: dspace ! data space handle - integer(HID_T) :: memspace ! memory space handle - integer(HSIZE_T) :: dims(1) ! dimensions on one processor - integer(HSIZE_T) :: dims_all(1) ! overall dimensions - integer(HSIZE_T) :: maxdims(1) ! maximum dimensions - integer(HSIZE_T) :: offset(1) ! offset of data - type(c_ptr) :: f_ptr -#ifdef PHDF5 - integer(HID_T) :: plist ! property list -#endif - - ! Open the dataset - call h5dopen_f(group_id, "source_bank", dset, hdf5_err) - - ! Create another data space but for each proc individually - dims(1) = work - call h5screate_simple_f(1, dims, memspace, hdf5_err) - - ! Make sure source bank is big enough - call h5dget_space_f(dset, dspace, hdf5_err) - call h5sget_simple_extent_dims_f(dspace, dims_all, maxdims, hdf5_err) - if (size(source_bank, KIND=HSIZE_T) > dims_all(1)) then - call fatal_error("Number of source sites in source file is less than & - &number of source particles per generation.") - end if - - ! Select hyperslab for each process - offset(1) = work_index(rank) - call h5sselect_hyperslab_f(dspace, H5S_SELECT_SET_F, offset, dims, hdf5_err) - - ! Set up pointer to data - f_ptr = c_loc(source_bank) - -#ifdef PHDF5 - ! Read data in parallel - call h5pcreate_f(H5P_DATASET_XFER_F, plist, hdf5_err) - call h5pset_dxpl_mpio_f(plist, H5FD_MPIO_COLLECTIVE_F, hdf5_err) - call h5dread_f(dset, hdf5_bank_t, f_ptr, hdf5_err, & - file_space_id=dspace, mem_space_id=memspace, & - xfer_prp=plist) - call h5pclose_f(plist, hdf5_err) -#else - call h5dread_f(dset, hdf5_bank_t, f_ptr, hdf5_err, & - file_space_id=dspace, mem_space_id=memspace) -#endif - - ! Close all ids - call h5sclose_f(dspace, hdf5_err) - call h5sclose_f(memspace, hdf5_err) - call h5dclose_f(dset, hdf5_err) - - end subroutine read_source_bank - end module state_point diff --git a/src/state_point.cpp b/src/state_point.cpp index 20338c4be5..cc6aa2a41d 100644 --- a/src/state_point.cpp +++ b/src/state_point.cpp @@ -4,14 +4,14 @@ #include #include "mpi.h" +#include "error.h" #include "message_passing.h" #include "openmc.h" namespace openmc { -void -write_source_bank(hid_t group_id, int64_t* work_index, const Bank* source_bank) -{ + +hid_t h5banktype() { // Create type for array of 3 reals hsize_t dims[] {3}; hid_t triplet = H5Tarray_create(H5T_NATIVE_DOUBLE, 1, dims); @@ -24,31 +24,41 @@ write_source_bank(hid_t group_id, int64_t* work_index, const Bank* source_bank) H5Tinsert(banktype, "E", HOFFSET(Bank, E), H5T_NATIVE_DOUBLE); H5Tinsert(banktype, "delayed_group", HOFFSET(Bank, delayed_group), H5T_NATIVE_INT); + H5Tclose(triplet); + return banktype; +} + + +void +write_source_bank(hid_t group_id, int64_t* work_index, const Bank* source_bank) +{ + hid_t banktype = h5banktype(); + #ifdef PHDF5 // Set size of total dataspace for all procs and rank - dims[0] = n_particles; + hsize_t dims[] {static_cast(n_particles)}; hid_t dspace = H5Screate_simple(1, dims, H5P_DEFAULT); hid_t dset = H5Dcreate(group_id, "source_bank", banktype, dspace, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT); // Create another data space but for each proc individually - hsize_t count[] {openmc_work}; + hsize_t count[] {static_cast(openmc_work)}; hid_t memspace = H5Screate_simple(1, count, H5P_DEFAULT); // Select hyperslab for this dataspace - hsize_t start[] {work_index[openmc::mpi::rank]}; + hsize_t start[] {static_cast(work_index[openmc::mpi::rank])}; H5Sselect_hyperslab(dspace, H5S_SELECT_SET, start, nullptr, count, nullptr); // Set up the property list for parallel writing hid_t plist = H5Pcreate(H5P_DATASET_XFER); - H5Pset_dxpl_mpio_f(plist, H5FD_MPIO_COLLECTIVE); + H5Pset_dxpl_mpio(plist, H5FD_MPIO_COLLECTIVE); // Write data to file in parallel - H5Dwrite(dset, banktype, memspace, dspace, memspace, plist, source_bank); + H5Dwrite(dset, banktype, memspace, dspace, plist, source_bank); // Free resources H5Sclose(dspace); - h5sclose(memspace); + H5Sclose(memspace); H5Dclose(dset); H5Pclose(plist); @@ -106,7 +116,48 @@ write_source_bank(hid_t group_id, int64_t* work_index, const Bank* source_bank) #endif H5Tclose(banktype); - H5Tclose(triplet); +} + + +void read_source_bank(hid_t group_id, int64_t* work_index, struct Bank* source_bank) +{ + hid_t banktype = h5banktype(); + + // Open the dataset + hid_t dset = H5Dopen(group_id, "source_bank", H5P_DEFAULT); + + // Create another data space but for each proc individually + hsize_t dims[] {static_cast(openmc_work)}; + hid_t memspace = H5Screate_simple(1, dims, H5P_DEFAULT); + + // Make sure source bank is big enough + hid_t dspace = H5Dget_space(dset); + hsize_t dims_all[1]; + H5Sget_simple_extent_dims(dspace, dims_all, nullptr); + if (work_index[openmc::mpi::n_procs] > dims_all[0]) { + fatal_error("Number of source sites in source file is less " + "than number of source particles per generation."); + } + + // Select hyperslab for each process + hsize_t start[] {static_cast(work_index[openmc::mpi::rank])}; + H5Sselect_hyperslab(dspace, H5S_SELECT_SET, start, nullptr, dims, nullptr); + +#ifdef PHDF5 + // Read data in parallel + hid_t plist = H5Pcreate(H5P_DATASET_XFER); + H5Pset_dxpl_mpio(plist, H5FD_MPIO_COLLECTIVE); + H5Dread(dset, banktype, memspace, dspace, plist, source_bank); + H5Pclose(plist); +#else + H5Dread(dset, banktype, memspace, dspace, H5P_DEFAULT, source_bank); +#endif + + // Close all ids + H5Sclose(dspace); + H5Sclose(memspace); + H5Dclose(dset); + H5Tclose(banktype); } } // namespace openmc diff --git a/src/state_point.h b/src/state_point.h index f0dafdb809..34186d0d97 100644 --- a/src/state_point.h +++ b/src/state_point.h @@ -9,7 +9,9 @@ namespace openmc { extern "C" void write_source_bank(hid_t group_id, int64_t* work_index, - const struct Bank* bank); + const struct Bank* source_bank); +extern "C" void read_source_bank(hid_t group_id, int64_t* work_index, + struct Bank* source_bank); } // namespace openmc #endif // STATE_POINT_H From 73b50e1e173ffca3a528774923627052149e7d5f Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Fri, 20 Apr 2018 14:02:48 -0500 Subject: [PATCH 50/77] Make sure statepoint context manager closes linked summary --- openmc/statepoint.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/openmc/statepoint.py b/openmc/statepoint.py index eb011d8742..3b878e9a37 100644 --- a/openmc/statepoint.py +++ b/openmc/statepoint.py @@ -150,6 +150,8 @@ class StatePoint(object): def __exit__(self, *exc): self._f.close() + if self._summary is not None: + self._summary._f.close() @property def cmfd_on(self): From d8c30b7f6211bf613bf81eb98052e0b78d06de6f Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Fri, 20 Apr 2018 14:07:14 -0500 Subject: [PATCH 51/77] Get rid of most of hdf5_initialize (no longer needed) --- src/api.F90 | 5 +---- src/hdf5_interface.F90 | 3 --- src/initialize.F90 | 44 ++++-------------------------------------- 3 files changed, 5 insertions(+), 47 deletions(-) diff --git a/src/api.F90 b/src/api.F90 index 03ea9bff06..32077c5657 100644 --- a/src/api.F90 +++ b/src/api.F90 @@ -2,7 +2,7 @@ module openmc_api use, intrinsic :: ISO_C_BINDING - use hdf5, only: HID_T, h5tclose_f, h5close_f + use hdf5, only: h5close_f use bank_header, only: openmc_source_bank use constants, only: K_BOLTZMANN @@ -169,9 +169,6 @@ contains ! Deallocate arrays call free_memory() - ! Release compound datatypes - call h5tclose_f(hdf5_bank_t, err) - ! Close FORTRAN interface. call h5close_f(err) diff --git a/src/hdf5_interface.F90 b/src/hdf5_interface.F90 index d76f7b6b71..70b624b4fe 100644 --- a/src/hdf5_interface.F90 +++ b/src/hdf5_interface.F90 @@ -24,9 +24,6 @@ module hdf5_interface implicit none private - integer(HID_T), public :: hdf5_bank_t ! Compound type for Bank - integer(HID_T), public :: hdf5_integer8_t ! type for integer(8) - interface write_dataset module procedure write_double_0D module procedure write_double_1D diff --git a/src/initialize.F90 b/src/initialize.F90 index 7b8f37dee6..7a43c9381d 100644 --- a/src/initialize.F90 +++ b/src/initialize.F90 @@ -13,8 +13,7 @@ module initialize use error, only: fatal_error, warning, write_message use geometry_header, only: Cell, Universe, Lattice, RectLattice, HexLattice,& root_universe - use hdf5_interface, only: file_open, read_attribute, file_close, & - hdf5_bank_t, hdf5_integer8_t + use hdf5_interface, only: file_open, read_attribute, file_close use input_xml, only: read_input_xml use material_header, only: Material use message_passing @@ -45,6 +44,7 @@ contains integer, intent(in), optional :: intracomm ! MPI intracommunicator integer(C_INT) :: err + integer :: hdf5_err #ifdef _OPENMP character(MAX_WORD_LEN) :: envvar #endif @@ -87,8 +87,8 @@ contains end if #endif - ! Initialize HDF5 interface - call hdf5_initialize() + ! Initialize HDF5 Fortran interface. + call h5open_f(hdf5_err) ! Read command line arguments call read_command_line() @@ -160,42 +160,6 @@ contains end subroutine initialize_mpi #endif -!=============================================================================== -! HDF5_INITIALIZE -!=============================================================================== - - subroutine hdf5_initialize() - - type(Bank), target :: tmpb(2) ! temporary Bank - integer :: hdf5_err - integer(HID_T) :: coordinates_t ! HDF5 type for 3 reals - integer(HSIZE_T) :: dims(1) = (/3/) ! size of coordinates - - ! Initialize FORTRAN interface. - call h5open_f(hdf5_err) - - ! Create compound type for xyz and uvw - call h5tarray_create_f(H5T_NATIVE_DOUBLE, 1, dims, coordinates_t, hdf5_err) - - ! Create the compound datatype for Bank - call h5tcreate_f(H5T_COMPOUND_F, h5offsetof(c_loc(tmpb(1)), & - c_loc(tmpb(2))), hdf5_bank_t, hdf5_err) - call h5tinsert_f(hdf5_bank_t, "wgt", h5offsetof(c_loc(tmpb(1)), & - c_loc(tmpb(1)%wgt)), H5T_NATIVE_DOUBLE, hdf5_err) - call h5tinsert_f(hdf5_bank_t, "xyz", h5offsetof(c_loc(tmpb(1)), & - c_loc(tmpb(1)%xyz)), coordinates_t, hdf5_err) - call h5tinsert_f(hdf5_bank_t, "uvw", h5offsetof(c_loc(tmpb(1)), & - c_loc(tmpb(1)%uvw)), coordinates_t, hdf5_err) - call h5tinsert_f(hdf5_bank_t, "E", h5offsetof(c_loc(tmpb(1)), & - c_loc(tmpb(1)%E)), H5T_NATIVE_DOUBLE, hdf5_err) - call h5tinsert_f(hdf5_bank_t, "delayed_group", h5offsetof(c_loc(tmpb(1)), & - c_loc(tmpb(1)%delayed_group)), H5T_NATIVE_INTEGER, hdf5_err) - - ! Determine type for integer(8) - hdf5_integer8_t = h5kind_to_type(8, H5_INTEGER_KIND) - - end subroutine hdf5_initialize - !=============================================================================== ! READ_COMMAND_LINE reads all parameters from the command line !=============================================================================== From 3290c410a8df12e76c7852644dda4e73be7907f6 Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Fri, 20 Apr 2018 14:55:06 -0500 Subject: [PATCH 52/77] Fix bugs for MPI/non-PHDF5 runs --- src/initialize.h | 2 ++ src/message_passing.h | 2 ++ src/state_point.cpp | 10 ++++++---- src/state_point.h | 4 ++-- 4 files changed, 12 insertions(+), 6 deletions(-) diff --git a/src/initialize.h b/src/initialize.h index 430987038d..d2c4df5d79 100644 --- a/src/initialize.h +++ b/src/initialize.h @@ -1,7 +1,9 @@ #ifndef INITIALIZE_H #define INITIALIZE_H +#ifdef OPENMC_MPI #include "mpi.h" +#endif namespace openmc { diff --git a/src/message_passing.h b/src/message_passing.h index 67353e23a1..14cf3a7cb0 100644 --- a/src/message_passing.h +++ b/src/message_passing.h @@ -1,7 +1,9 @@ #ifndef MESSAGE_PASSING_H #define MESSAGE_PASSING_H +#ifdef OPENMC_MPI #include "mpi.h" +#endif namespace openmc { namespace mpi { diff --git a/src/state_point.cpp b/src/state_point.cpp index cc6aa2a41d..2ea9d1c43c 100644 --- a/src/state_point.cpp +++ b/src/state_point.cpp @@ -3,7 +3,9 @@ #include #include +#ifdef OPENMC_MPI #include "mpi.h" +#endif #include "error.h" #include "message_passing.h" #include "openmc.h" @@ -30,7 +32,7 @@ hid_t h5banktype() { void -write_source_bank(hid_t group_id, int64_t* work_index, const Bank* source_bank) +write_source_bank(hid_t group_id, int64_t* work_index, Bank* source_bank) { hid_t banktype = h5banktype(); @@ -73,7 +75,7 @@ write_source_bank(hid_t group_id, int64_t* work_index, const Bank* source_bank) // Save source bank sites since the souce_bank array is overwritten below #ifdef OPENMC_MPI - std::vector temp_source {source_bank, source_bank + openmc_work}; + std::vector temp_source {source_bank, source_bank + openmc_work}; #endif for (int i = 0; i < openmc::mpi::n_procs; ++i) { @@ -110,7 +112,7 @@ write_source_bank(hid_t group_id, int64_t* work_index, const Bank* source_bank) } else { #ifdef OPENMC_MPI MPI_Send(source_bank, openmc_work, openmc::mpi::bank, 0, openmc::mpi::rank, - openmc::mpi::mpi_intracomm); + openmc::mpi::intracomm); #endif } #endif @@ -119,7 +121,7 @@ write_source_bank(hid_t group_id, int64_t* work_index, const Bank* source_bank) } -void read_source_bank(hid_t group_id, int64_t* work_index, struct Bank* source_bank) +void read_source_bank(hid_t group_id, int64_t* work_index, Bank* source_bank) { hid_t banktype = h5banktype(); diff --git a/src/state_point.h b/src/state_point.h index 34186d0d97..459df1a675 100644 --- a/src/state_point.h +++ b/src/state_point.h @@ -9,9 +9,9 @@ namespace openmc { extern "C" void write_source_bank(hid_t group_id, int64_t* work_index, - const struct Bank* source_bank); + Bank* source_bank); extern "C" void read_source_bank(hid_t group_id, int64_t* work_index, - struct Bank* source_bank); + Bank* source_bank); } // namespace openmc #endif // STATE_POINT_H From 70173aa25c1de99b8e5127003a1e1fcb7007099d Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Tue, 24 Apr 2018 06:42:43 -0500 Subject: [PATCH 53/77] Install openmc.h header properly --- CMakeLists.txt | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 9b750a6dd3..ed9021cf48 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -443,7 +443,9 @@ set(LIBOPENMC_CXX_SRC src/xml_interface.cpp src/pugixml/pugixml.cpp) add_library(libopenmc SHARED ${LIBOPENMC_FORTRAN_SRC} ${LIBOPENMC_CXX_SRC}) -set_target_properties(libopenmc PROPERTIES OUTPUT_NAME openmc) +set_target_properties(libopenmc PROPERTIES + OUTPUT_NAME openmc + PUBLIC_HEADER include/openmc.h) add_executable(${program} src/main.cpp) #=============================================================================== @@ -501,7 +503,9 @@ add_custom_command(TARGET libopenmc POST_BUILD install(TARGETS ${program} libopenmc RUNTIME DESTINATION bin LIBRARY DESTINATION lib - ARCHIVE DESTINATION lib) + ARCHIVE DESTINATION lib + PUBLIC_HEADER DESTINATION include + ) install(DIRECTORY src/relaxng DESTINATION share/openmc) install(FILES man/man1/openmc.1 DESTINATION share/man/man1) install(FILES LICENSE DESTINATION "share/doc/${program}" RENAME copyright) From 1a77f8afee8f671cf51a4b6f81681f2c66845ba5 Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Tue, 24 Apr 2018 15:25:58 -0500 Subject: [PATCH 54/77] Add C++ routines for HDF5 get_groups, get_datasets, get_name --- src/hdf5_interface.F90 | 123 ++++++++++++++++++---------------- src/hdf5_interface.cpp | 147 +++++++++++++++++++++++++++++++++++------ src/hdf5_interface.h | 9 ++- 3 files changed, 201 insertions(+), 78 deletions(-) diff --git a/src/hdf5_interface.F90 b/src/hdf5_interface.F90 index 70b624b4fe..077807c04f 100644 --- a/src/hdf5_interface.F90 +++ b/src/hdf5_interface.F90 @@ -13,13 +13,12 @@ module hdf5_interface use, intrinsic :: ISO_C_BINDING use hdf5 - use h5lt use error, only: fatal_error #ifdef PHDF5 use message_passing, only: mpi_intracomm, MPI_INFO_NULL #endif - use string, only: to_c_string + use string, only: to_c_string, to_f_string implicit none private @@ -316,31 +315,37 @@ contains integer(HID_T), intent(in) :: object_id character(len=150), allocatable, intent(out) :: names(:) - integer :: n_members, i, group_count, type - integer :: hdf5_err - character(len=150) :: name + integer :: i + integer(C_INT) :: n + character(len=150,kind=C_CHAR), target, allocatable :: names_(:) + type(C_PTR), allocatable :: name_ptrs(:) - ! Get number of members in this location - call h5gn_members_f(object_id, './', n_members, hdf5_err) + interface + function get_num_groups(group_id) result(n) bind(C) + import HID_T, C_INT + integer(HID_T), value :: group_id + integer(C_INT) :: n + end function get_num_groups + subroutine get_groups_c(group_id, name) bind(C, name='get_groups') + import HID_T, C_PTR + integer(HID_T), value :: group_id + type(C_PTR) :: name(*) + end subroutine get_groups_c + end interface - ! Get the number of groups - group_count = 0 - do i = 0, n_members - 1 - call h5gget_obj_info_idx_f(object_id, "./", i, name, type, hdf5_err) - if (type == H5G_GROUP_F) then - group_count = group_count + 1 - end if + ! Determine number of groups and allocate + n = get_num_groups(object_id) + allocate(names(n), names_(n), name_ptrs(n)) + + ! Set C pointers to beginning of each string + do i = 1, size(names) + name_ptrs(i) = c_loc(names_(i)) end do - ! Now we can allocate the storage for the ids - allocate(names(group_count)) - group_count = 0 - do i = 0, n_members - 1 - call h5gget_obj_info_idx_f(object_id, "./", i, name, type, hdf5_err) - if (type == H5G_GROUP_F) then - group_count = group_count + 1 - names(group_count) = trim(name) - end if + ! Get names of groups and copy to Fortran strings + call get_groups_c(object_id, name_ptrs) + do i = 1, size(names) + names(i) = to_f_string(names_(i)) end do end subroutine get_groups @@ -398,32 +403,37 @@ contains integer(HID_T), intent(in) :: object_id character(len=150), allocatable, intent(out) :: names(:) - integer :: n_members, i, dset_count, type - integer :: hdf5_err - character(len=150) :: name + integer :: i + integer(C_INT) :: n + character(len=150,kind=C_CHAR), target, allocatable :: names_(:) + type(C_PTR), allocatable :: name_ptrs(:) + interface + function get_num_datasets(group_id) result(n) bind(C) + import HID_T, C_INT + integer(HID_T), value :: group_id + integer(C_INT) :: n + end function get_num_datasets + subroutine get_datasets_c(group_id, name) bind(C, name='get_datasets') + import HID_T, C_PTR + integer(HID_T), value :: group_id + type(C_PTR) :: name(*) + end subroutine get_datasets_c + end interface - ! Get number of members in this location - call h5gn_members_f(object_id, './', n_members, hdf5_err) + ! Determine number of datasets and allocate + n = get_num_datasets(object_id) + allocate(names(n), names_(n), name_ptrs(n)) - ! Get the number of datasets - dset_count = 0 - do i = 0, n_members - 1 - call h5gget_obj_info_idx_f(object_id, "./", i, name, type, hdf5_err) - if (type == H5G_DATASET_F ) then - dset_count = dset_count + 1 - end if + ! Set C pointers to beginning of each string + do i = 1, size(names) + name_ptrs(i) = c_loc(names_(i)) end do - ! Now we can allocate the storage for the ids - allocate(names(dset_count)) - dset_count = 0 - do i = 0, n_members - 1 - call h5gget_obj_info_idx_f(object_id, "./", i, name, type, hdf5_err) - if (type == H5G_DATASET_F ) then - dset_count = dset_count + 1 - names(dset_count) = trim(name) - end if + ! Get names of datasets and copy to Fortran strings + call get_datasets_c(object_id, name_ptrs) + do i = 1, size(names) + names(i) = to_f_string(names_(i)) end do end subroutine get_datasets @@ -432,21 +442,22 @@ contains ! GET_NAME Obtains the name of the current group in group_id !=============================================================================== - function get_name(group_id, name_len_) result(name) - integer(HID_T), intent(in) :: group_id + function get_name(object_id, name_len_) result(name) + integer(HID_T), intent(in) :: object_id integer(SIZE_T), optional, intent(in) :: name_len_ - character(len=150) :: name ! name of group - integer(SIZE_T) :: name_len, name_file_len - integer :: hdf5_err ! HDF5 error code + character(150) :: name ! name of object + character(kind=C_CHAR) :: name_(150) + interface + subroutine get_name_c(obj_id, name) bind(C, name='get_name') + import HID_T, C_CHAR + integer(HID_T), value :: obj_id + character(kind=C_CHAR), intent(out) :: name(*) + end subroutine get_name_c + end interface - if (present(name_len_)) then - name_len = name_len_ - else - name_len = 150 - end if - - call h5iget_name_f(group_id, name, name_len, name_file_len, hdf5_err) + call get_name_c(object_id, name_) + name = to_f_string(name_) end function get_name !=============================================================================== diff --git a/src/hdf5_interface.cpp b/src/hdf5_interface.cpp index d81c5b34a8..e4db2ee58a 100644 --- a/src/hdf5_interface.cpp +++ b/src/hdf5_interface.cpp @@ -36,26 +36,6 @@ attribute_typesize(hid_t obj_id, const char* name) } -bool -using_mpio_device(hid_t obj_id) -{ - // Determine file that this object is part of - hid_t file_id = H5Iget_file_id(obj_id); - - // Get file access property list - hid_t fapl_id = H5Fget_access_plist(file_id); - - // Get low-level driver identifier - hid_t driver = H5Pget_driver(fapl_id); - - // Free resources - H5Pclose(fapl_id); - H5Fclose(file_id); - - return driver == H5FD_MPIO; -} - - void get_shape(hid_t obj_id, hsize_t* dims) { @@ -199,6 +179,113 @@ void file_close(hid_t file_id) H5Fclose(file_id); } + +void +get_name(hid_t obj_id, char* name) +{ + size_t size = 1 + H5Iget_name(obj_id, nullptr, 0); + H5Iget_name(obj_id, name, size); +} + + +int get_num_datasets(hid_t group_id) +{ + // Determine number of links in the group + H5G_info_t info; + H5Gget_info(group_id, &info); + + // Iterate over links to get number of groups + H5O_info_t oinfo; + int ndatasets = 0; + for (hsize_t i = 0; i < info.nlinks; ++i) { + // Determine type of object (and skip non-group) + H5Oget_info_by_idx(group_id, ".", H5_INDEX_NAME, H5_ITER_INC, i, &oinfo, + H5P_DEFAULT); + if (oinfo.type == H5O_TYPE_DATASET) ndatasets += 1; + } + + return ndatasets; +} + + +int get_num_groups(hid_t group_id) +{ + // Determine number of links in the group + H5G_info_t info; + H5Gget_info(group_id, &info); + + // Iterate over links to get number of groups + H5O_info_t oinfo; + int ngroups = 0; + for (hsize_t i = 0; i < info.nlinks; ++i) { + // Determine type of object (and skip non-group) + H5Oget_info_by_idx(group_id, ".", H5_INDEX_NAME, H5_ITER_INC, i, &oinfo, + H5P_DEFAULT); + if (oinfo.type == H5O_TYPE_GROUP) ngroups += 1; + } + + return ngroups; +} + + +void +get_datasets(hid_t group_id, char* name[]) +{ + // Determine number of links in the group + H5G_info_t info; + H5Gget_info(group_id, &info); + + // Iterate over links to get names + H5O_info_t oinfo; + hsize_t count = 0; + size_t size; + for (hsize_t i = 0; i < info.nlinks; ++i) { + // Determine type of object (and skip non-group) + H5Oget_info_by_idx(group_id, ".", H5_INDEX_NAME, H5_ITER_INC, i, &oinfo, + H5P_DEFAULT); + if (oinfo.type != H5O_TYPE_DATASET) continue; + + // Get size of name + size = 1 + H5Lget_name_by_idx(group_id, ".", H5_INDEX_NAME, H5_ITER_INC, + i, nullptr, 0, H5P_DEFAULT); + + // Read name + H5Lget_name_by_idx(group_id, ".", H5_INDEX_NAME, H5_ITER_INC, i, + name[count], size, H5P_DEFAULT); + count += 1; + } +} + + +void +get_groups(hid_t group_id, char* name[]) +{ + // Determine number of links in the group + H5G_info_t info; + H5Gget_info(group_id, &info); + + // Iterate over links to get names + H5O_info_t oinfo; + hsize_t count = 0; + size_t size; + for (hsize_t i = 0; i < info.nlinks; ++i) { + // Determine type of object (and skip non-group) + H5Oget_info_by_idx(group_id, ".", H5_INDEX_NAME, H5_ITER_INC, i, &oinfo, + H5P_DEFAULT); + if (oinfo.type != H5O_TYPE_GROUP) continue; + + // Get size of name + size = 1 + H5Lget_name_by_idx(group_id, ".", H5_INDEX_NAME, H5_ITER_INC, + i, nullptr, 0, H5P_DEFAULT); + + // Read name + H5Lget_name_by_idx(group_id, ".", H5_INDEX_NAME, H5_ITER_INC, i, + name[count], size, H5P_DEFAULT); + count += 1; + } +} + + bool object_exists(hid_t object_id, const char* name) { @@ -548,4 +635,24 @@ write_tally_results(hid_t group_id, hsize_t n_filter, hsize_t n_score, const dou H5Sclose(dspace); } + +bool +using_mpio_device(hid_t obj_id) +{ + // Determine file that this object is part of + hid_t file_id = H5Iget_file_id(obj_id); + + // Get file access property list + hid_t fapl_id = H5Fget_access_plist(file_id); + + // Get low-level driver identifier + hid_t driver = H5Pget_driver(fapl_id); + + // Free resources + H5Pclose(fapl_id); + H5Fclose(file_id); + + return driver == H5FD_MPIO; +} + } // namespace openmc diff --git a/src/hdf5_interface.h b/src/hdf5_interface.h index 57f56f5c20..9a8b3c569d 100644 --- a/src/hdf5_interface.h +++ b/src/hdf5_interface.h @@ -23,8 +23,13 @@ extern "C" size_t dataset_typesize(hid_t dset); extern "C" hid_t file_open(const char* filename, char mode, bool parallel); hid_t file_open(const std::string& filename, char mode, bool parallel); extern "C" void file_close(hid_t file_id); -extern "C" void get_shape(hid_t obj_if, hsize_t* dims); -extern "C" void get_shape_attr(hid_t obj_if, const char* name, hsize_t* dims); +extern "C" void get_name(hid_t obj_id, char* name); +extern "C" int get_num_datasets(hid_t group_id); +extern "C" int get_num_groups(hid_t group_id); +extern "C" void get_datasets(hid_t group_id, char* name[]); +extern "C" void get_groups(hid_t group_id, char* name[]); +extern "C" void get_shape(hid_t obj_id, hsize_t* dims); +extern "C" void get_shape_attr(hid_t obj_id, const char* name, hsize_t* dims); extern "C" bool object_exists(hid_t object_id, const char* name); extern "C" hid_t open_dataset(hid_t group_id, const char* name); extern "C" hid_t open_group(hid_t group_id, const char* name); From 279562c32afed79f4b45eefdd69b3d67a8dc372d Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Tue, 24 Apr 2018 15:45:21 -0500 Subject: [PATCH 55/77] Make sure rank/nprocs is set for serial runs --- src/message_passing.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/message_passing.cpp b/src/message_passing.cpp index 3ab96ffd87..2ff3952d73 100644 --- a/src/message_passing.cpp +++ b/src/message_passing.cpp @@ -3,8 +3,8 @@ namespace openmc { namespace mpi { -int rank; -int n_procs; +int rank {0}; +int n_procs {1}; #ifdef OPENMC_MPI MPI_Comm intracomm; From 3acec3c093bf0bb4c90b6de1963ad4e4d1d61d46 Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Tue, 24 Apr 2018 22:42:04 -0500 Subject: [PATCH 56/77] Call HDF5 routines from C++ side for voxel plots --- CMakeLists.txt | 1 + src/plot.F90 | 62 +++++++++++++++++++++++++++----------------------- src/plot.cpp | 42 ++++++++++++++++++++++++++++++++++ src/plot.h | 15 ++++++++++++ 4 files changed, 91 insertions(+), 29 deletions(-) create mode 100644 src/plot.cpp create mode 100644 src/plot.h diff --git a/CMakeLists.txt b/CMakeLists.txt index ed9021cf48..5c6636cbce 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -436,6 +436,7 @@ set(LIBOPENMC_CXX_SRC src/initialize.cpp src/hdf5_interface.cpp src/message_passing.cpp + src/plot.cpp src/random_lcg.cpp src/simulation.cpp src/state_point.cpp diff --git a/src/plot.F90 b/src/plot.F90 index 92b8f350df..c2ffa2d39c 100644 --- a/src/plot.F90 +++ b/src/plot.F90 @@ -2,8 +2,6 @@ module plot use, intrinsic :: ISO_C_BINDING - use hdf5 - use constants use error, only: fatal_error, write_message use geometry, only: find_cell, check_cell_overlap @@ -340,23 +338,46 @@ contains subroutine create_voxel(pl) type(ObjectPlot), intent(in) :: pl - integer :: x, y, z ! voxel location indices + integer(C_INT) :: x, y, z ! voxel location indices integer :: rgb(3) ! colors (red, green, blue) from 0-255 integer :: id ! id of cell or material - integer :: hdf5_err - integer, target :: data(pl%pixels(3),pl%pixels(2)) + integer(C_INT), target :: data(pl%pixels(3),pl%pixels(2)) integer(HID_T) :: file_id integer(HID_T) :: dspace integer(HID_T) :: memspace integer(HID_T) :: dset integer(HSIZE_T) :: dims(3) - integer(HSIZE_T) :: dims_slab(3) - integer(HSIZE_T) :: offset(3) real(8) :: vox(3) ! x, y, and z voxel widths real(8) :: ll(3) ! lower left starting point for each sweep direction type(Particle) :: p type(ProgressBar) :: progress - type(c_ptr) :: f_ptr + + interface + subroutine voxel_init(file_id, dims, dspace, dset, memspace) bind(C) + import HID_T, HSIZE_T + integer(HID_T), value :: file_id + integer(HSIZE_T), intent(in) :: dims(*) + integer(HID_T), intent(out) :: dspace + integer(HID_T), intent(out) :: dset + integer(HID_T), intent(out) :: memspace + end subroutine voxel_init + + subroutine voxel_write_slice(x, dspace, dset, memspace, buf) bind(C) + import C_INT, HID_T, C_PTR + integer(C_INT), value :: x + integer(HID_T), value :: dspace + integer(HID_T), value :: dset + integer(HID_T), value :: memspace + type(C_PTR), value :: buf + end subroutine voxel_write_slice + + subroutine voxel_finalize(dspace, dset, memspace) bind(C) + import HID_T + integer(HID_T), value :: dspace + integer(HID_T), value :: dset + integer(HID_T), value :: memspace + end subroutine voxel_finalize + end interface ! compute voxel widths in each direction vox = pl % width/dble(pl % pixels) @@ -390,20 +411,8 @@ contains ! Create dataset for voxel data -- note that the dimensions are reversed ! since we want the order in the file to be z, y, x - dims(:) = [pl%pixels(3), pl%pixels(2), pl%pixels(1)] - call h5screate_simple_f(3, dims, dspace, hdf5_err) - call h5dcreate_f(file_id, "data", H5T_NATIVE_INTEGER, dspace, dset, hdf5_err) - - ! Create another dataspace for 2D array in memory - dims_slab(1) = pl%pixels(3) - dims_slab(2) = pl%pixels(2) - dims_slab(3) = 1 - call h5screate_simple_f(2, dims_slab(1:2), memspace, hdf5_err) - - ! Initialize offset and get pointer to data - offset(:) = 0 - call h5sselect_hyperslab_f(dspace, H5S_SELECT_SET_F, offset, dims_slab, hdf5_err) - f_ptr = c_loc(data) + dims(:) = pl % pixels + call voxel_init(file_id, dims, dspace, dset, memspace) ! move to center of voxels ll = ll + vox / TWO @@ -433,15 +442,10 @@ contains p % coord(1) % xyz(3) = ll(3) ! Write to HDF5 dataset - offset(3) = x - 1 - call h5soffset_simple_f(dspace, offset, hdf5_err) - call h5dwrite_f(dset, H5T_NATIVE_INTEGER, f_ptr, hdf5_err, & - mem_space_id=memspace, file_space_id=dspace) + call voxel_write_slice(x, dspace, dset, memspace, c_loc(data)) end do - call h5dclose_f(dset, hdf5_err) - call h5sclose_f(dspace, hdf5_err) - call h5sclose_f(memspace, hdf5_err) + call voxel_finalize(dspace, dset, memspace) call file_close(file_id) end subroutine create_voxel diff --git a/src/plot.cpp b/src/plot.cpp new file mode 100644 index 0000000000..0dca6d08cd --- /dev/null +++ b/src/plot.cpp @@ -0,0 +1,42 @@ +#include "plot.h" + +namespace openmc { + +void +voxel_init(hid_t file_id, const hsize_t* dims, hid_t* dspace, hid_t* dset, + hid_t* memspace) +{ + // Create dataspace/dataset for voxel data + *dspace = H5Screate_simple(3, dims, nullptr); + *dset = H5Dcreate(file_id, "data", H5T_NATIVE_INT, *dspace, H5P_DEFAULT, + H5P_DEFAULT, H5P_DEFAULT); + + // Create dataspace for a slice of the voxel + hsize_t dims_slice[2] {dims[1], dims[2]}; + *memspace = H5Screate_simple(2, dims_slice, nullptr); + + // Select hyperslab in dataspace + hsize_t start[3] {0, 0, 0}; + hsize_t count[3] {1, dims[1], dims[2]}; + H5Sselect_hyperslab(*dspace, H5S_SELECT_SET, start, nullptr, count, nullptr); +} + + +void +voxel_write_slice(int x, hid_t dspace, hid_t dset, hid_t memspace, void* buf) +{ + hssize_t offset[3] {x - 1, 0, 0}; + H5Soffset_simple(dspace, offset); + H5Dwrite(dset, H5T_NATIVE_INT, memspace, dspace, H5P_DEFAULT, buf); +} + + +void +voxel_finalize(hid_t dspace, hid_t dset, hid_t memspace) +{ + H5Dclose(dset); + H5Sclose(dspace); + H5Sclose(memspace); +} + +} // namespace openmc diff --git a/src/plot.h b/src/plot.h new file mode 100644 index 0000000000..75406b9ace --- /dev/null +++ b/src/plot.h @@ -0,0 +1,15 @@ +#ifndef PLOT_H +#define PLOT_H + +#include "hdf5.h" + +namespace openmc { + +extern "C" void voxel_init(hid_t file_id, const hsize_t* dims, hid_t* dspace, + hid_t* dset, hid_t* memspace); +extern "C" void voxel_write_slice(int x, hid_t dspace, hid_t dset, + hid_t memspace, void* buf); +extern "C" void voxel_finalize(hid_t dspace, hid_t dset, hid_t memspace); + +} // namespace openmc +#endif // PLOT_H From 36dc4a59b14d6d3b0450d53d434b73d5adf64ea2 Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Tue, 24 Apr 2018 23:03:21 -0500 Subject: [PATCH 57/77] Remove remaining dependencies on Fortran HDF5 interface --- CMakeLists.txt | 2 +- src/api.F90 | 5 ----- src/hdf5_interface.F90 | 11 +++++------ src/initialize.F90 | 6 +----- src/mgxs_header.F90 | 4 +--- src/nuclide_header.F90 | 4 +--- src/sab_header.F90 | 4 +--- 7 files changed, 10 insertions(+), 26 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 5c6636cbce..ed72434d80 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -70,7 +70,7 @@ if(NOT DEFINED HDF5_PREFER_PARALLEL) endif() endif() -find_package(HDF5 COMPONENTS Fortran_HL) +find_package(HDF5 COMPONENTS HL) if(NOT HDF5_FOUND) message(FATAL_ERROR "Could not find HDF5") endif() diff --git a/src/api.F90 b/src/api.F90 index 32077c5657..d00d166c42 100644 --- a/src/api.F90 +++ b/src/api.F90 @@ -2,8 +2,6 @@ module openmc_api use, intrinsic :: ISO_C_BINDING - use hdf5, only: h5close_f - use bank_header, only: openmc_source_bank use constants, only: K_BOLTZMANN use eigenvalue, only: k_sum, openmc_get_keff @@ -169,9 +167,6 @@ contains ! Deallocate arrays call free_memory() - ! Close FORTRAN interface. - call h5close_f(err) - #ifdef OPENMC_MPI ! Free all MPI types call MPI_TYPE_FREE(MPI_BANK, err) diff --git a/src/hdf5_interface.F90 b/src/hdf5_interface.F90 index 077807c04f..57138c377a 100644 --- a/src/hdf5_interface.F90 +++ b/src/hdf5_interface.F90 @@ -12,8 +12,6 @@ module hdf5_interface use, intrinsic :: ISO_C_BINDING - use hdf5 - use error, only: fatal_error #ifdef PHDF5 use message_passing, only: mpi_intracomm, MPI_INFO_NULL @@ -94,7 +92,9 @@ module hdf5_interface public :: get_groups public :: get_datasets public :: get_name - public :: HID_T, HSIZE_T, SIZE_T + + integer, public, parameter :: HID_T = C_INT64_T + integer, public, parameter :: HSIZE_T = C_LONG_LONG interface function attribute_typesize(obj_id, name) result(sz) bind(C) @@ -442,9 +442,8 @@ contains ! GET_NAME Obtains the name of the current group in group_id !=============================================================================== - function get_name(object_id, name_len_) result(name) - integer(HID_T), intent(in) :: object_id - integer(SIZE_T), optional, intent(in) :: name_len_ + function get_name(object_id) result(name) + integer(HID_T), intent(in) :: object_id character(150) :: name ! name of object character(kind=C_CHAR) :: name_(150) diff --git a/src/initialize.F90 b/src/initialize.F90 index 7a43c9381d..8d136cf242 100644 --- a/src/initialize.F90 +++ b/src/initialize.F90 @@ -2,7 +2,6 @@ module initialize use, intrinsic :: ISO_C_BINDING, only: c_loc - use hdf5 #ifdef _OPENMP use omp_lib #endif @@ -13,7 +12,7 @@ module initialize use error, only: fatal_error, warning, write_message use geometry_header, only: Cell, Universe, Lattice, RectLattice, HexLattice,& root_universe - use hdf5_interface, only: file_open, read_attribute, file_close + use hdf5_interface, only: file_open, read_attribute, file_close, HID_T use input_xml, only: read_input_xml use material_header, only: Material use message_passing @@ -87,9 +86,6 @@ contains end if #endif - ! Initialize HDF5 Fortran interface. - call h5open_f(hdf5_err) - ! Read command line arguments call read_command_line() diff --git a/src/mgxs_header.F90 b/src/mgxs_header.F90 index 76042703af..3bb74d5f79 100644 --- a/src/mgxs_header.F90 +++ b/src/mgxs_header.F90 @@ -246,7 +246,6 @@ contains type(VectorInt), intent(out) :: temps_to_read ! Temperatures to read integer, intent(out) :: order_dim ! Scattering data order size - integer(SIZE_T) :: name_len integer(HID_T) :: kT_group character(MAX_WORD_LEN), allocatable :: dset_names(:) real(8), allocatable :: temps_available(:) ! temperatures available @@ -257,8 +256,7 @@ contains integer :: ipol, iazi ! Get name of dataset from group - name_len = len(this % name) - this % name = get_name(xs_id, name_len) + this % name = get_name(xs_id) ! Get rid of leading '/' this % name = trim(this % name(2:)) diff --git a/src/nuclide_header.F90 b/src/nuclide_header.F90 index a063bb90b4..ebabe5cdbc 100644 --- a/src/nuclide_header.F90 +++ b/src/nuclide_header.F90 @@ -290,7 +290,6 @@ contains integer(HID_T) :: total_nu integer(HID_T) :: fer_group ! fission_energy_release group integer(HID_T) :: fer_dset - integer(SIZE_T) :: name_len integer(HSIZE_T) :: j integer(HSIZE_T) :: dims(1) character(MAX_WORD_LEN) :: temp_str @@ -304,8 +303,7 @@ contains type(VectorInt) :: index_inelastic_scatter ! Get name of nuclide from group - name_len = len(this % name) - this % name = get_name(group_id, name_len) + this % name = get_name(group_id) ! Get rid of leading '/' this % name = trim(this % name(2:)) diff --git a/src/sab_header.F90 b/src/sab_header.F90 index 7ac14ef00e..615e7b281d 100644 --- a/src/sab_header.F90 +++ b/src/sab_header.F90 @@ -100,7 +100,6 @@ contains integer :: n_energy, n_energy_out, n_mu integer :: i_closest integer :: n_temperature - integer(SIZE_T) :: name_len integer(HID_T) :: T_group integer(HID_T) :: elastic_group integer(HID_T) :: inelastic_group @@ -120,8 +119,7 @@ contains type(VectorInt) :: temps_to_read ! Get name of table from group - name_len = len(this % name) - this % name = get_name(group_id, name_len) + this % name = get_name(group_id) ! Get rid of leading '/' this % name = trim(this % name(2:)) From da4999f1163b8b030dd08dc57d9ef2f9cb1133df Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Wed, 25 Apr 2018 12:51:45 -0500 Subject: [PATCH 58/77] Move reading command-line arguments to C++ side --- include/openmc.h | 6 +- openmc/capi/core.py | 4 +- src/api.F90 | 2 + src/hdf5_interface.F90 | 5 +- src/initialize.F90 | 200 +++++++------------------------------- src/initialize.cpp | 161 +++++++++++++++++++++++++++++- src/initialize.h | 6 +- src/main.cpp | 13 ++- src/output.F90 | 4 +- src/settings.F90 | 10 +- src/simulation_header.F90 | 2 +- 11 files changed, 229 insertions(+), 184 deletions(-) diff --git a/include/openmc.h b/include/openmc.h index 7f2bbf46c7..0556187419 100644 --- a/include/openmc.h +++ b/include/openmc.h @@ -47,7 +47,7 @@ extern "C" { int64_t openmc_get_seed(); int openmc_get_tally_index(int32_t id, int32_t* index); void openmc_hard_reset(); - int openmc_init(const void* intracomm); + int openmc_init(int argc, char* argv[], const void* intracomm); int openmc_init_f(const int* intracomm); int openmc_legendre_filter_get_order(int32_t index, int* order); int openmc_legendre_filter_set_order(int32_t index, int order); @@ -146,9 +146,11 @@ extern "C" { extern bool openmc_simulation_initialized; extern int openmc_verbosity; - // Variables that are shared by necessity (can be removed later) + // Variables that are shared by necessity (can be removed from public header + // later) extern bool openmc_master; extern int openmc_n_procs; + extern int openmc_n_threads; extern int openmc_rank; extern int64_t openmc_work; diff --git a/openmc/capi/core.py b/openmc/capi/core.py index 57e2e88ebd..1c2725382f 100644 --- a/openmc/capi/core.py +++ b/openmc/capi/core.py @@ -27,7 +27,7 @@ _dll.openmc_find.argtypes = [POINTER(c_double*3), c_int, POINTER(c_int32), _dll.openmc_find.restype = c_int _dll.openmc_find.errcheck = _error_handler _dll.openmc_hard_reset.restype = None -_dll.openmc_init.argtypes = [c_void_p] +_dll.openmc_init.argtypes = [c_int, POINTER(c_char_p), c_void_p] _dll.openmc_init.restype = None _dll.openmc_get_keff.argtypes = [POINTER(c_double*2)] _dll.openmc_get_keff.restype = c_int @@ -126,7 +126,7 @@ def init(intracomm=None): address = MPI._addressof(intracomm) intracomm = c_void_p(address) - _dll.openmc_init(intracomm) + _dll.openmc_init(0, None, intracomm) def iter_batches(): diff --git a/src/api.F90 b/src/api.F90 index d00d166c42..bf760770b5 100644 --- a/src/api.F90 +++ b/src/api.F90 @@ -104,7 +104,9 @@ contains subroutine openmc_finalize() bind(C) +#ifdef OPENMC_MPI integer :: err +#endif ! Clear results call openmc_reset() diff --git a/src/hdf5_interface.F90 b/src/hdf5_interface.F90 index 57138c377a..3fd5e860fd 100644 --- a/src/hdf5_interface.F90 +++ b/src/hdf5_interface.F90 @@ -1105,7 +1105,7 @@ contains integer :: i integer(HSIZE_T) :: dims(1) - integer(C_SIZE_T) :: m + integer(C_SIZE_T) :: m, n logical(C_BOOL) :: indep_ character(kind=C_CHAR), allocatable :: buffer_(:) @@ -1118,7 +1118,8 @@ contains m = maxval(len_trim(buffer)) + 1 allocate(buffer_(dims(1)*m)) do i = 0, dims(1) - 1 - buffer_(i*m+1 : (i+1)*m) = to_c_string(buffer(i+1)) + n = len_trim(buffer(i+1)) + 1 + buffer_(i*m+1 : i*m+n) = to_c_string(buffer(i+1)) end do call write_string_c(group_id, 1, dims, m, to_c_string(name), & diff --git a/src/initialize.F90 b/src/initialize.F90 index 8d136cf242..d5ce32b312 100644 --- a/src/initialize.F90 +++ b/src/initialize.F90 @@ -1,6 +1,6 @@ module initialize - use, intrinsic :: ISO_C_BINDING, only: c_loc + use, intrinsic :: ISO_C_BINDING #ifdef _OPENMP use omp_lib @@ -8,28 +8,20 @@ module initialize use bank_header, only: Bank use constants - use set_header, only: SetInt - use error, only: fatal_error, warning, write_message - use geometry_header, only: Cell, Universe, Lattice, RectLattice, HexLattice,& - root_universe - use hdf5_interface, only: file_open, read_attribute, file_close, HID_T use input_xml, only: read_input_xml - use material_header, only: Material use message_passing - use mgxs_data, only: read_mgxs, create_macro_xs - use output, only: print_version, print_usage use random_lcg, only: openmc_set_seed use settings -#ifdef _OPENMP - use simulation_header, only: n_threads -#endif - use string, only: to_str, starts_with, ends_with, str_to_int - use tally_header, only: TallyObject - use tally_filter + use string, only: ends_with, to_f_string use timer_header implicit none + type(C_PTR), bind(C) :: openmc_path_input + type(C_PTR), bind(C) :: openmc_path_statepoint + type(C_PTR), bind(C) :: openmc_path_sourcepoint + type(C_PTR), bind(C) :: openmc_path_particle_restart + contains !=============================================================================== @@ -43,7 +35,6 @@ contains integer, intent(in), optional :: intracomm ! MPI intracommunicator integer(C_INT) :: err - integer :: hdf5_err #ifdef _OPENMP character(MAX_WORD_LEN) :: envvar #endif @@ -161,162 +152,41 @@ contains !=============================================================================== subroutine read_command_line() + ! Arguments were already read on C++ side (initialize.cpp). Here we just + ! convert the C-style strings to Fortran style - integer :: i ! loop index - integer :: argc ! number of command line arguments - integer :: last_flag ! index of last flag - character(MAX_WORD_LEN) :: filetype - integer(HID_T) :: file_id - character(MAX_WORD_LEN), allocatable :: argv(:) ! command line arguments + character(kind=C_CHAR), pointer :: string(:) + interface + function is_null(ptr) result(x) bind(C) + import C_PTR, C_BOOL + type(C_PTR), value :: ptr + logical(C_BOOL) :: x + end function is_null + end interface - ! Check number of command line arguments and allocate argv - argc = COMMAND_ARGUMENT_COUNT() - - ! Allocate and retrieve command arguments - allocate(argv(argc)) - do i = 1, argc - call GET_COMMAND_ARGUMENT(i, argv(i)) - end do - - ! Process command arguments - last_flag = 0 - i = 1 - do while (i <= argc) - ! Check for flags - if (starts_with(argv(i), "-")) then - select case (argv(i)) - case ('-p', '-plot', '--plot') - run_mode = MODE_PLOTTING - check_overlaps = .true. - - case ('-n', '-particles', '--particles') - ! Read number of particles per cycle - i = i + 1 - n_particles = str_to_int(argv(i)) - - ! Check that number specified was valid - if (n_particles == ERROR_INT) then - call fatal_error("Must specify integer after " // trim(argv(i-1)) & - &// " command-line flag.") - end if - case ('-r', '-restart', '--restart') - ! Read path for state point/particle restart - i = i + 1 - - ! Check what type of file this is - file_id = file_open(argv(i), 'r', parallel=.true.) - call read_attribute(filetype, file_id, 'filetype') - call file_close(file_id) - - ! Set path and flag for type of run - select case (trim(filetype)) - case ('statepoint') - path_state_point = argv(i) - restart_run = .true. - case ('particle restart') - path_particle_restart = argv(i) - particle_restart_run = .true. - case default - call fatal_error("Unrecognized file after restart flag: " // filetype // ".") - end select - - ! If its a restart run check for additional source file - if (restart_run .and. i + 1 <= argc) then - - ! Increment arg - i = i + 1 - - ! Check if it has extension we can read - if (ends_with(argv(i), '.h5')) then - - ! Check file type is a source file - file_id = file_open(argv(i), 'r', parallel=.true.) - call read_attribute(filetype, file_id, 'filetype') - call file_close(file_id) - if (filetype /= 'source') then - call fatal_error("Second file after restart flag must be a & - &source file") - end if - - ! It is a source file - path_source_point = argv(i) - - else ! Different option is specified not a source file - - ! Source is in statepoint file - path_source_point = path_state_point - - ! Set argument back - i = i - 1 - - end if - - else ! No command line arg after statepoint - - ! Source is assumed to be in statepoint file - path_source_point = path_state_point - - end if - - case ('-g', '-geometry-debug', '--geometry-debug') - check_overlaps = .true. - - case ('-c', '--volume') - run_mode = MODE_VOLUME - - case ('-s', '--threads') - ! Read number of threads - i = i + 1 - -#ifdef _OPENMP - ! Read and set number of OpenMP threads - n_threads = int(str_to_int(argv(i)), 4) - if (n_threads < 1) then - call fatal_error("Invalid number of threads specified on command & - &line.") - end if - call omp_set_num_threads(n_threads) -#else - if (master) call warning("Ignoring number of threads specified on & - &command line.") -#endif - - case ('-?', '-h', '-help', '--help') - call print_usage() - stop - case ('-v', '-version', '--version') - call print_version() - stop - case ('-t', '-track', '--track') - write_all_tracks = .true. - case default - call fatal_error("Unknown command line option: " // argv(i)) - end select - - last_flag = i - end if - - ! Increment counter - i = i + 1 - end do - - ! Determine directory where XML input files are - if (argc > 0 .and. last_flag < argc) then - path_input = argv(last_flag + 1) + if (.not. is_null(openmc_path_input)) then + call c_f_pointer(openmc_path_input, string, [255]) + path_input = to_f_string(string) else path_input = '' end if - - ! Add slash at end of directory if it isn't there - if (.not. ends_with(path_input, "/") .and. len_trim(path_input) > 0) then - path_input = trim(path_input) // "/" + if (.not. is_null(openmc_path_statepoint)) then + call c_f_pointer(openmc_path_statepoint, string, [255]) + path_state_point = to_f_string(string) + end if + if (.not. is_null(openmc_path_sourcepoint)) then + call c_f_pointer(openmc_path_sourcepoint, string, [255]) + path_source_point = to_f_string(string) + end if + if (.not. is_null(openmc_path_particle_restart)) then + call c_f_pointer(openmc_path_particle_restart, string, [255]) + path_particle_restart = to_f_string(string) end if - ! Free memory from argv - deallocate(argv) - - ! TODO: Check that directory exists - + ! Add slash at end of directory if it isn't there + if (len_trim(path_input) > 0 .and. .not. ends_with(path_input, "/")) then + path_input = trim(path_input) // "/" + end if end subroutine read_command_line end module initialize diff --git a/src/initialize.cpp b/src/initialize.cpp index 23025feb23..d8045e4337 100644 --- a/src/initialize.cpp +++ b/src/initialize.cpp @@ -1,12 +1,38 @@ #include "initialize.h" #include +#include +#include +#include +#include +#include "error.h" +#include "hdf5_interface.h" #include "message_passing.h" #include "openmc.h" +#ifdef _OPENMP +#include "omp.h" +#endif + +// data/functions from Fortran side +extern "C" bool openmc_check_overlaps; +extern "C" bool openmc_write_all_tracks; +extern "C" bool openmc_particle_restart_run; +extern "C" bool openmc_restart_run; +extern "C" void print_usage(); +extern "C" void print_version(); -int openmc_init(const void* intracomm) +// Paths to various files +extern "C" { + char* openmc_path_input; + char* openmc_path_statepoint; + char* openmc_path_sourcepoint; + char* openmc_path_particle_restart; + bool is_null(void* ptr) {return !ptr;} +} + +int openmc_init(int argc, char* argv[], const void* intracomm) { #ifdef OPENMC_MPI // Check if intracomm was passed @@ -19,13 +45,20 @@ int openmc_init(const void* intracomm) // Initialize MPI for C++ openmc::initialize_mpi(comm); +#endif + + // Parse command-line arguments + int err = openmc::parse_command_line(argc, argv); + if (err) return err; // Continue with rest of initialization +#ifdef OPENMC_MPI MPI_Fint fcomm = MPI_Comm_c2f(comm); openmc_init_f(&fcomm); #else openmc_init_f(nullptr); #endif + return 0; } @@ -63,6 +96,130 @@ void initialize_mpi(MPI_Comm intracomm) MPI_Type_create_struct(5, blocks, disp, types, &openmc::mpi::bank); MPI_Type_commit(&openmc::mpi::bank); } - #endif // OPENMC_MPI + + +inline bool ends_with(std::string const& value, std::string const& ending) +{ + if (ending.size() > value.size()) return false; + return std::equal(ending.rbegin(), ending.rend(), value.rbegin()); +} + + +int +parse_command_line(int argc, char* argv[]) +{ + char buffer[256]; // buffer for reading attribute + int last_flag = 0; + for (int i=1; i < argc; ++i) { + std::string arg {argv[i]}; + if (arg[0] == '-') { + if (arg == "-p" || arg == "--plot") { + openmc_run_mode = RUN_MODE_PLOTTING; + openmc_check_overlaps = true; + + } else if (arg == "-n" || arg == "--particles") { + i += 1; + n_particles = std::stoll(argv[i]); + + } else if (arg == "-r" || arg == "--restart") { + i += 1; + + // Check what type of file this is + hid_t file_id = file_open(argv[i], 'r', true); + size_t len = attribute_typesize(file_id, "filetype"); + read_attr_string(file_id, "filetype", len, buffer); + file_close(file_id); + std::string filetype {buffer}; + + // Set path and flag for type of run + if (filetype == "statepoint") { + openmc_path_statepoint = argv[i]; + openmc_restart_run = true; + } else if (filetype == "particle restart") { + openmc_path_particle_restart = argv[i]; + openmc_particle_restart_run = true; + } else { + std::stringstream msg; + msg << "Unrecognized file after restart flag: " << filetype << "."; + strcpy(openmc_err_msg, msg.str().c_str()); + return OPENMC_E_INVALID_ARGUMENT; + } + + // If its a restart run check for additional source file + if (openmc_restart_run && i + 1 < argc) { + // Check if it has extension we can read + if (ends_with(argv[i+1], ".h5")) { + + // Check file type is a source file + file_id = file_open(argv[i+1], 'r', true); + len = attribute_typesize(file_id, "filetype"); + read_attr_string(file_id, "filetype", len, buffer); + file_close(file_id); + if (filetype != "source") { + std::string msg {"Second file after restart flag must be a source file"}; + strcpy(openmc_err_msg, msg.c_str()); + return OPENMC_E_INVALID_ARGUMENT; + } + + // It is a source file + openmc_path_sourcepoint = argv[i+1]; + i += 1; + + } else { + // Source is in statepoint file + openmc_path_sourcepoint = openmc_path_statepoint; + } + + } else { + // Source is assumed to be in statepoint file + openmc_path_sourcepoint = openmc_path_statepoint; + } + + } else if (arg == "-g" || arg == "--geometry-debug") { + openmc_check_overlaps = true; + } else if (arg == "-c" || arg == "--volume") { + openmc_run_mode = RUN_MODE_VOLUME; + } else if (arg == "-s" || arg == "--threads") { + // Read number of threads + i += 1; + +#ifdef _OPENMP + // Read and set number of OpenMP threads + openmc_n_threads = std::stoi(argv[i]); + if (openmc_n_threads < 1) { + std::string msg {"Number of threads must be positive."}; + strcpy(openmc_err_msg, msg.c_str()); + return OPENMC_E_INVALID_ARGUMENT; + } + omp_set_num_threads(openmc_n_threads); +#endif + + } else if (arg == "-?" || arg == "-h" || arg == "--help") { + print_usage(); + return OPENMC_E_UNASSIGNED; + + } else if (arg == "-v" || arg == "--version") { + print_version(); + return OPENMC_E_UNASSIGNED; + + } else if (arg == "-t" || arg == "--track") { + openmc_write_all_tracks = true; + + } else { + std::cerr << "Unknown option: " << argv[i] << '\n'; + print_usage(); + return OPENMC_E_UNASSIGNED; + } + + last_flag = i; + } + } + + // Determine directory where XML input files are + if (argc > 1 && last_flag < argc) openmc_path_input = argv[last_flag + 1]; + + return 0; +} + } // namespace openmc diff --git a/src/initialize.h b/src/initialize.h index d2c4df5d79..14283fb5fc 100644 --- a/src/initialize.h +++ b/src/initialize.h @@ -5,10 +5,14 @@ #include "mpi.h" #endif +extern "C" void print_usage(); +extern "C" void print_version(); + namespace openmc { +int parse_command_line(int argc, char* argv[]); #ifdef OPENMC_MPI - void initialize_mpi(MPI_Comm intracomm); +void initialize_mpi(MPI_Comm intracomm); #endif } diff --git a/src/main.cpp b/src/main.cpp index 1dd20ebe04..5bf305093b 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,19 +1,26 @@ +#include "error.h" #ifdef OPENMC_MPI #include "mpi.h" #endif #include "openmc.h" -int main(int argc, char** argv) { +int main(int argc, char* argv[]) { int err; // Initialize run -- when run with MPI, pass communicator #ifdef OPENMC_MPI MPI_Comm world {MPI_COMM_WORLD}; - openmc_init(&world); + err = openmc_init(argc, argv, &world); #else - openmc_init(nullptr); + err = openmc_init(argc, argv, nullptr); #endif + if (err == -1) { + // This happens for the -h and -v flags + return 0; + } else if (err) { + openmc::fatal_error(openmc_err_msg); + } // start problem based on mode switch (openmc_run_mode) { diff --git a/src/output.F90 b/src/output.F90 index b6809ca82f..174292fb3b 100644 --- a/src/output.F90 +++ b/src/output.F90 @@ -162,7 +162,7 @@ contains ! information !=============================================================================== - subroutine print_version() + subroutine print_version() bind(C) if (master) then write(UNIT=OUTPUT_UNIT, FMT='(1X,A,1X,I1,".",I2,".",I1)') & @@ -182,7 +182,7 @@ contains ! PRINT_USAGE displays information about command line usage of OpenMC !=============================================================================== - subroutine print_usage() + subroutine print_usage() bind(C) if (master) then write(OUTPUT_UNIT,*) 'Usage: openmc [options] [directory]' diff --git a/src/settings.F90 b/src/settings.F90 index 4de72e8c4d..aef1c011be 100644 --- a/src/settings.F90 +++ b/src/settings.F90 @@ -78,13 +78,13 @@ module settings integer(C_INT), bind(C, name='openmc_run_mode') :: run_mode = NONE ! Restart run - logical :: restart_run = .false. + logical(C_BOOL), bind(C, name='openmc_restart_run') :: restart_run = .false. ! The verbosity controls how much information will be printed to the screen ! and in logs integer(C_INT), bind(C, name='openmc_verbosity') :: verbosity = 7 - logical :: check_overlaps = .false. + logical(C_BOOL), bind(C, name='openmc_check_overlaps') :: check_overlaps = .false. ! Trace for single particle integer :: trace_batch @@ -92,11 +92,13 @@ module settings integer(8) :: trace_particle ! Particle tracks - logical :: write_all_tracks = .false. + logical(C_BOOL), bind(C, name='openmc_write_all_tracks') :: & + write_all_tracks = .false. integer, allocatable :: track_identifiers(:,:) ! Particle restart run - logical :: particle_restart_run = .false. + logical(C_BOOL), bind(C, name='openmc_particle_restart_run') :: & + particle_restart_run = .false. ! Write out initial source logical :: write_initial_source = .false. diff --git a/src/simulation_header.F90 b/src/simulation_header.F90 index a214f4410b..8fe5e2da1f 100644 --- a/src/simulation_header.F90 +++ b/src/simulation_header.F90 @@ -58,7 +58,7 @@ module simulation_header ! PARALLEL PROCESSING VARIABLES #ifdef _OPENMP - integer :: n_threads = NONE ! number of OpenMP threads + integer(C_INT), bind(C, name='openmc_n_threads') :: n_threads = NONE ! number of OpenMP threads integer :: thread_id ! ID of a given thread #endif From 30944b554a5ecda6d7ec20fb221419a76c5bc618 Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Wed, 25 Apr 2018 14:46:27 -0500 Subject: [PATCH 59/77] Update docs, don't modify when .mod files are created --- CMakeLists.txt | 6 +----- docs/source/capi/index.rst | 6 ++++-- docs/source/usersguide/install.rst | 8 +------- src/math.F90 | 1 - 4 files changed, 6 insertions(+), 15 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index ed72434d80..3cfea2227f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -5,7 +5,6 @@ project(openmc Fortran C CXX) set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib) set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib) set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin) -set(CMAKE_Fortran_MODULE_DIRECTORY ${CMAKE_BINARY_DIR}/include) # Set module path set(CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake/Modules) @@ -456,10 +455,7 @@ add_executable(${program} src/main.cpp) set_property(TARGET ${program} libopenmc pugixml_fortran PROPERTY LINKER_LANGUAGE Fortran) -target_include_directories(libopenmc - PUBLIC include ${HDF5_INCLUDE_DIRS} - PRIVATE ${CMAKE_BINARY_DIR}/include - ) +target_include_directories(libopenmc PUBLIC include ${HDF5_INCLUDE_DIRS}) # The executable and the faddeeva package use only one language. They can be # set via target_compile_options which accepts a list. diff --git a/docs/source/capi/index.rst b/docs/source/capi/index.rst index 0e6a2536c6..fbc2830b56 100644 --- a/docs/source/capi/index.rst +++ b/docs/source/capi/index.rst @@ -270,13 +270,15 @@ Functions Reset tallies, timers, and pseudo-random number generator state -.. c:function:: void openmc_init(const int* intracomm) +.. c:function:: void openmc_init(int argc, char** argv, const void* intracomm) Initialize OpenMC + :param int argc: Number of command-line arguments (including command) + :param char** argv: Command-line arguments :param intracomm: MPI intracommunicator. If MPI is not being used, a null pointer should be passed. - :type intracomm: const int* + :type intracomm: const void* .. c:function:: int openmc_load_nuclide(char name[]) diff --git a/docs/source/usersguide/install.rst b/docs/source/usersguide/install.rst index b0618818e3..f5b277a840 100644 --- a/docs/source/usersguide/install.rst +++ b/docs/source/usersguide/install.rst @@ -141,16 +141,10 @@ Prerequisites recommend that your HDF5 installation be built with parallel I/O features. An example of configuring HDF5_ is listed below:: - FC=mpifort ./configure --enable-fortran --enable-parallel + FC=mpifort ./configure --enable-parallel You may omit ``--enable-parallel`` if you want to compile HDF5_ in serial. - .. important:: - - If you are building HDF5 version 1.8.x or earlier, you must include - ``--enable-fortran2003`` as well when configuring HDF5 or else OpenMC - will not be able to compile. - .. admonition:: Optional :class: note diff --git a/src/math.F90 b/src/math.F90 index ee8cd0530b..20bacf88cf 100644 --- a/src/math.F90 +++ b/src/math.F90 @@ -598,7 +598,6 @@ contains real(8) :: zn_mat(n+1, n+1) ! Matrix form of the coefficients which is ! easier to work with real(8) :: k1, k2, k3, k4 ! Variables for R_m_n calculation - real(8) :: sqrt_norm ! normalization for radial moments integer :: i,p,q ! Loop counters real(8), parameter :: SQRT_N_1(0:10) = [& From 0a8f5977edd4dcf5506e86731867f3226d32e500 Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Wed, 25 Apr 2018 15:07:40 -0500 Subject: [PATCH 60/77] Be more consistent with C API function return values --- docs/source/capi/index.rst | 52 ++++++++++++++++++++++++++++++-------- include/openmc.h | 17 ++++++------- openmc/capi/core.py | 27 +++++++++++++------- src/api.F90 | 27 +++++++++++--------- src/main.cpp | 4 +-- src/plot.F90 | 6 +++-- src/simulation.F90 | 18 +++++++++---- src/state_point.F90 | 7 ++--- src/volume_calc.F90 | 6 +++-- 9 files changed, 109 insertions(+), 55 deletions(-) diff --git a/docs/source/capi/index.rst b/docs/source/capi/index.rst index fbc2830b56..85509f6f43 100644 --- a/docs/source/capi/index.rst +++ b/docs/source/capi/index.rst @@ -46,10 +46,13 @@ Type Definitions Functions --------- -.. c:function:: void openmc_calculate_volumes() +.. c:function:: int openmc_calculate_volumes() Run a stochastic volume calculation + :return: Return status (negative if an error occurred) + :rtype: int + .. c:function:: int openmc_cell_get_fill(int32_t index, int* type, int32_t** indices, int32_t* n) Get the fill for a cell @@ -192,11 +195,14 @@ Functions :return: Return status (negative if an error occurred) :rtype: int -.. c:function:: void openmc_finalize() +.. c:function:: int openmc_finalize() Finalize a simulation -.. c:function:: void openmc_find(double* xyz, int rtype, int32_t* id, int32_t* instance) + :return: Return status (negative if an error occurs) + :rtype: int + +.. c:function:: int openmc_find(double* xyz, int rtype, int32_t* id, int32_t* instance) Determine the ID of the cell/material containing a given point @@ -207,6 +213,8 @@ Functions occurs, the ID is -1. :param int32_t* instance: If a cell is repeated in the geometry, the instance of the cell that was found and zero otherwise. + :return: Return status (negative if an error occurs) + :rtype: int .. c:function:: int openmc_get_cell_index(int32_t id, int32_t* index) @@ -266,11 +274,14 @@ Functions :return: Return status (negative if an error occurs) :rtype: int -.. c:function:: void openmc_hard_reset() +.. c:function:: int openmc_hard_reset() Reset tallies, timers, and pseudo-random number generator state -.. c:function:: void openmc_init(int argc, char** argv, const void* intracomm) + :return: Return status (negative if an error occurs) + :rtype: int + +.. c:function:: int openmc_init(int argc, char** argv, const void* intracomm) Initialize OpenMC @@ -279,6 +290,8 @@ Functions :param intracomm: MPI intracommunicator. If MPI is not being used, a null pointer should be passed. :type intracomm: const void* + :return: Return status (negative if an error occurs) + :rtype: int .. c:function:: int openmc_load_nuclide(char name[]) @@ -396,26 +409,41 @@ Functions :return: Return status (negative if an error occurs) :rtype: int -.. c:function:: void openmc_plot_geometry() +.. c:function:: int openmc_plot_geometry() Run plotting mode. -.. c:function:: void openmc_reset() + :return: Return status (negative if an error occurs) + :rtype: int + +.. c:function:: int openmc_reset() Resets all tally scores -.. c:function:: void openmc_run() + :return: Return status (negative if an error occurs) + :rtype: int + +.. c:function:: int openmc_run() Run a simulation -.. c:function:: void openmc_simulation_finalize() + :return: Return status (negative if an error occurs) + :rtype: int + +.. c:function:: int openmc_simulation_finalize() Finalize a simulation. -.. c:function:: void openmc_simulation_init() + :return: Return status (negative if an error occurs) + :rtype: int + +.. c:function:: int openmc_simulation_init() Initialize a simulation. Must be called after openmc_init(). + :return: Return status (negative if an error occurs) + :rtype: int + .. c:function:: int openmc_source_bank(struct Bank** ptr, int64_t* n) Return a pointer to the source bank array. @@ -435,13 +463,15 @@ Functions :return: Return status (negative if an error occurred) :rtype: int -.. c:function:: void openmc_statepoint_write(const char filename[]) +.. c:function:: int openmc_statepoint_write(const char filename[]) Write a statepoint file :param filename: Name of file to create. If a null pointer is passed, a filename is assigned automatically. :type filename: const char[] + :return: Return status (negative if an error occurs) + :rtype: int .. c:function:: int openmc_tally_get_id(int32_t index, int32_t* id) diff --git a/include/openmc.h b/include/openmc.h index 0556187419..38b7f21670 100644 --- a/include/openmc.h +++ b/include/openmc.h @@ -4,7 +4,6 @@ #include #include - #ifdef __cplusplus extern "C" { #endif @@ -17,7 +16,7 @@ extern "C" { int delayed_group; }; - void openmc_calculate_volumes(); + int openmc_calculate_volumes(); int openmc_cell_get_fill(int32_t index, int* type, int32_t** indices, int32_t* n); int openmc_cell_get_id(int32_t index, int32_t* id); int openmc_cell_set_fill(int32_t index, int type, int32_t n, const int32_t* indices); @@ -35,7 +34,7 @@ extern "C" { int openmc_filter_get_type(int32_t index, const char** type); int openmc_filter_set_id(int32_t index, int32_t id); int openmc_filter_set_type(int32_t index, const char* type); - void openmc_finalize(); + int openmc_finalize(); int openmc_find(double* xyz, int rtype, int32_t* id, int32_t* instance); int openmc_get_cell_index(int32_t id, int32_t* index); int openmc_get_filter_index(int32_t id, int32_t* index); @@ -46,7 +45,7 @@ extern "C" { int openmc_get_nuclide_index(const char name[], int* index); int64_t openmc_get_seed(); int openmc_get_tally_index(int32_t id, int32_t* index); - void openmc_hard_reset(); + int openmc_hard_reset(); int openmc_init(int argc, char* argv[], const void* intracomm); int openmc_init_f(const int* intracomm); int openmc_legendre_filter_get_order(int32_t index, int* order); @@ -73,12 +72,12 @@ extern "C" { int openmc_next_batch(int* status); int openmc_nuclide_name(int index, char** name); int openmc_particle_restart(); - void openmc_plot_geometry(); - void openmc_reset(); + int openmc_plot_geometry(); + int openmc_reset(); int openmc_run(); void openmc_set_seed(int64_t new_seed); - void openmc_simulation_finalize(); - void openmc_simulation_init(); + int openmc_simulation_finalize(); + int openmc_simulation_init(); int openmc_source_bank(struct Bank** ptr, int64_t* n); int openmc_source_set_strength(int32_t index, double strength); int openmc_spatial_legendre_filter_get_order(int32_t index, int* order); @@ -90,7 +89,7 @@ extern "C" { int openmc_sphharm_filter_get_cosine(int32_t index, char cosine[]); int openmc_sphharm_filter_set_order(int32_t index, int order); int openmc_sphharm_filter_set_cosine(int32_t index, const char cosine[]); - void openmc_statepoint_write(const char filename[]); + int openmc_statepoint_write(const char filename[]); int openmc_tally_get_active(int32_t index, bool* active); int openmc_tally_get_id(int32_t index, int32_t* id); int openmc_tally_get_filters(int32_t index, int32_t** indices, int* n); diff --git a/openmc/capi/core.py b/openmc/capi/core.py index 1c2725382f..273f0c0c7f 100644 --- a/openmc/capi/core.py +++ b/openmc/capi/core.py @@ -20,32 +20,41 @@ class _Bank(Structure): ('delayed_group', c_int)] -_dll.openmc_calculate_volumes.restype = None -_dll.openmc_finalize.restype = None +_dll.openmc_calculate_volumes.restype = c_int +_dll.openmc_calculate_volumes.errcheck = _error_handler +_dll.openmc_finalize.restype = c_int +_dll.openmc_finalize.errcheck = _error_handler _dll.openmc_find.argtypes = [POINTER(c_double*3), c_int, POINTER(c_int32), POINTER(c_int32)] _dll.openmc_find.restype = c_int _dll.openmc_find.errcheck = _error_handler -_dll.openmc_hard_reset.restype = None +_dll.openmc_hard_reset.restype = c_int +_dll.openmc_hard_reset.errcheck = _error_handler _dll.openmc_init.argtypes = [c_int, POINTER(c_char_p), c_void_p] -_dll.openmc_init.restype = None +_dll.openmc_init.restype = c_int +_dll.openmc_init.errcheck = _error_handler _dll.openmc_get_keff.argtypes = [POINTER(c_double*2)] _dll.openmc_get_keff.restype = c_int _dll.openmc_get_keff.errcheck = _error_handler _dll.openmc_next_batch.argtypes = [POINTER(c_int)] _dll.openmc_next_batch.restype = c_int _dll.openmc_next_batch.errcheck = _error_handler -_dll.openmc_plot_geometry.restype = None +_dll.openmc_plot_geometry.restype = c_int +_dll.openmc_plot_geometry.restype = _error_handler _dll.openmc_run.restype = c_int _dll.openmc_run.errcheck = _error_handler -_dll.openmc_reset.restype = None +_dll.openmc_reset.restype = c_int +_dll.openmc_reset.errcheck = _error_handler _dll.openmc_source_bank.argtypes = [POINTER(POINTER(_Bank)), POINTER(c_int64)] _dll.openmc_source_bank.restype = c_int _dll.openmc_source_bank.errcheck = _error_handler -_dll.openmc_simulation_init.restype = None -_dll.openmc_simulation_finalize.restype = None +_dll.openmc_simulation_init.restype = c_int +_dll.openmc_simulation_init.errcheck = _error_handler +_dll.openmc_simulation_finalize.restype = c_int +_dll.openmc_simulation_finalize.errcheck = _error_handler _dll.openmc_statepoint_write.argtypes = [POINTER(c_char_p)] -_dll.openmc_statepoint_write.restype = None +_dll.openmc_statepoint_write.restype = c_int +_dll.openmc_statepoint_write.errcheck = _error_handler def calculate_volumes(): diff --git a/src/api.F90 b/src/api.F90 index bf760770b5..49d86edb67 100644 --- a/src/api.F90 +++ b/src/api.F90 @@ -102,14 +102,11 @@ contains ! variables !=============================================================================== - subroutine openmc_finalize() bind(C) - -#ifdef OPENMC_MPI - integer :: err -#endif + function openmc_finalize() result(err) bind(C) + integer(C_INT) :: err ! Clear results - call openmc_reset() + err = openmc_reset() ! Reset global variables assume_separate = .false. @@ -169,12 +166,13 @@ contains ! Deallocate arrays call free_memory() + err = 0 #ifdef OPENMC_MPI ! Free all MPI types call MPI_TYPE_FREE(MPI_BANK, err) #endif - end subroutine openmc_finalize + end function openmc_finalize !=============================================================================== ! OPENMC_FIND determines the ID or a cell or material at a given point in space @@ -225,9 +223,11 @@ contains ! generator state !=============================================================================== - subroutine openmc_hard_reset() bind(C) + function openmc_hard_reset() result(err) bind(C) + integer(C_INT) :: err + ! Reset all tallies and timers - call openmc_reset() + err = openmc_reset() ! Reset total generations and keff guess keff = ONE @@ -235,13 +235,15 @@ contains ! Reset the random number generator state call openmc_set_seed(DEFAULT_SEED) - end subroutine openmc_hard_reset + end function openmc_hard_reset !=============================================================================== ! OPENMC_RESET resets tallies and timers !=============================================================================== - subroutine openmc_reset() bind(C) + function openmc_reset() result(err) bind(C) + integer(C_INT) :: err + integer :: i if (allocated(tallies)) then @@ -289,7 +291,8 @@ contains call time_transport % reset() call time_finalize % reset() - end subroutine openmc_reset + err = 0 + end function openmc_reset !=============================================================================== ! FREE_MEMORY deallocates and clears all global allocatable arrays in the diff --git a/src/main.cpp b/src/main.cpp index 5bf305093b..b9e475cd71 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -29,13 +29,13 @@ int main(int argc, char* argv[]) { err = openmc_run(); break; case RUN_MODE_PLOTTING: - openmc_plot_geometry(); + err = openmc_plot_geometry(); break; case RUN_MODE_PARTICLE: if (openmc_master) err = openmc_particle_restart(); break; case RUN_MODE_VOLUME: - openmc_calculate_volumes(); + err = openmc_calculate_volumes(); break; } diff --git a/src/plot.F90 b/src/plot.F90 index c2ffa2d39c..f17ac33511 100644 --- a/src/plot.F90 +++ b/src/plot.F90 @@ -30,7 +30,8 @@ contains ! RUN_PLOT controls the logic for making one or many plots !=============================================================================== - subroutine openmc_plot_geometry() bind(C) + function openmc_plot_geometry() result(err) bind(C) + integer(C_INT) :: err integer :: i ! loop index for plots @@ -50,7 +51,8 @@ contains end associate end do - end subroutine openmc_plot_geometry + err = 0 + end function openmc_plot_geometry !=============================================================================== ! POSITION_RGB computes the red/green/blue values for a given plot with the diff --git a/src/simulation.F90 b/src/simulation.F90 index e9729df038..4f6163429e 100644 --- a/src/simulation.F90 +++ b/src/simulation.F90 @@ -312,6 +312,7 @@ contains subroutine finalize_batch() + integer(C_INT) :: err #ifdef OPENMC_MPI integer :: mpi_err ! MPI error code #endif @@ -347,7 +348,7 @@ contains ! Write out state point if it's been specified for this batch if (statepoint_batch % contains(current_batch)) then - call openmc_statepoint_write() + err = openmc_statepoint_write() end if ! Write out source point if it's been specified for this batch @@ -396,9 +397,13 @@ contains ! INITIALIZE_SIMULATION !=============================================================================== - subroutine openmc_simulation_init() bind(C) + function openmc_simulation_init() result(err) bind(C) + integer(C_INT) :: err + integer :: i + err = 0 + ! Skip if simulation has already been initialized if (simulation_initialized) return @@ -456,14 +461,15 @@ contains ! Set flag indicating initialization is done simulation_initialized = .true. - end subroutine openmc_simulation_init + end function openmc_simulation_init !=============================================================================== ! FINALIZE_SIMULATION calculates tally statistics, writes tallies, and displays ! execution time and results !=============================================================================== - subroutine openmc_simulation_finalize() bind(C) + function openmc_simulation_finalize() result(err) bind(C) + integer(C_INT) :: err integer :: i ! loop index #ifdef OPENMC_MPI @@ -479,6 +485,8 @@ contains #endif #endif + err = 0 + ! Skip if simulation was never run if (.not. simulation_initialized) return @@ -553,7 +561,7 @@ contains need_depletion_rx = .false. simulation_initialized = .false. - end subroutine openmc_simulation_finalize + end function openmc_simulation_finalize !=============================================================================== ! CALCULATE_WORK determines how many particles each processor should simulate diff --git a/src/state_point.F90 b/src/state_point.F90 index 5b1c4d462a..005b549c30 100644 --- a/src/state_point.F90 +++ b/src/state_point.F90 @@ -58,8 +58,9 @@ contains ! OPENMC_STATEPOINT_WRITE writes an HDF5 statepoint file to disk !=============================================================================== - subroutine openmc_statepoint_write(filename) bind(C) + function openmc_statepoint_write(filename) result(err) bind(C) type(C_PTR), intent(in), optional :: filename + integer(C_INT) :: err integer :: i, j, k integer :: i_xs @@ -70,12 +71,12 @@ contains integer(HID_T) :: cmfd_group, tallies_group, tally_group, meshes_group, & filters_group, filter_group, derivs_group, & deriv_group, runtime_group - integer(C_INT) :: err real(C_DOUBLE) :: k_combined(2) character(MAX_WORD_LEN), allocatable :: str_array(:) character(C_CHAR), pointer :: string(:) character(len=:, kind=C_CHAR), allocatable :: filename_ + err = 0 if (present(filename)) then call c_f_pointer(filename, string, [MAX_FILE_LEN]) filename_ = to_f_string(string) @@ -458,7 +459,7 @@ contains call file_close(file_id) end if - end subroutine openmc_statepoint_write + end function openmc_statepoint_write !=============================================================================== ! WRITE_SOURCE_POINT diff --git a/src/volume_calc.F90 b/src/volume_calc.F90 index fa770c1f37..8264797a7a 100644 --- a/src/volume_calc.F90 +++ b/src/volume_calc.F90 @@ -36,9 +36,10 @@ contains ! the user has specified and writes results to HDF5 files !=============================================================================== - subroutine openmc_calculate_volumes() bind(C) + function openmc_calculate_volumes() result(err) bind(C) integer :: i, j integer :: n + integer(C_INT) :: err real(8), allocatable :: volume(:,:) ! volume mean/stdev in each domain character(10) :: domain_type character(MAX_FILE_LEN) :: filename ! filename for HDF5 file @@ -99,7 +100,8 @@ contains call write_message("Elapsed time: " // trim(to_str(time_volume % & get_value())) // " s", 6) end if - end subroutine openmc_calculate_volumes + err = 0 + end function openmc_calculate_volumes !=============================================================================== ! GET_VOLUME stochastically determines the volume of a set of domains along with From 9e29b8e202348bc24f20e1ae3f98ad584c6db0ab Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Wed, 25 Apr 2018 15:18:12 -0500 Subject: [PATCH 61/77] Support using statepoint as a source file --- docs/source/io_formats/source.rst | 16 ++++++++-------- src/source.F90 | 6 +++--- src/state_point.F90 | 6 +----- 3 files changed, 12 insertions(+), 16 deletions(-) diff --git a/docs/source/io_formats/source.rst b/docs/source/io_formats/source.rst index a0a62afca0..cff77d2fa5 100644 --- a/docs/source/io_formats/source.rst +++ b/docs/source/io_formats/source.rst @@ -8,13 +8,13 @@ Normally, source data is stored in a state point file. However, it is possible to request that the source be written separately, in which case the format used is that documented here. -**/filetype** (*char[]*) +**/** - String indicating the type of file. +:Attributes: - **filetype** (*char[]*) -- String indicating the type of file. -**/source_bank** (Compound type) - - Source bank information for each particle. The compound type has fields - ``wgt``, ``xyz``, ``uvw``, ``E``, and ``delayed_group``, which - represent the weight, position, direction, energy, energy group, and - delayed_group of the source particle, respectively. +:Datasets: + - **source_bank** (Compound type) -- Source bank information for each + particle. The compound type has fields ``wgt``, ``xyz``, ``uvw``, + ``E``, and ``delayed_group``, which represent the weight, position, + direction, energy, energy group, and delayed_group of the source + particle, respectively. diff --git a/src/source.F90 b/src/source.F90 index b02430823b..3683611315 100644 --- a/src/source.F90 +++ b/src/source.F90 @@ -11,7 +11,7 @@ module source use distribution_multivariate, only: SpatialBox use error, only: fatal_error use geometry, only: find_cell - use hdf5_interface, only: file_open, file_close, read_dataset, HID_T + use hdf5_interface use math use message_passing, only: rank use mgxs_header, only: rev_energy_bins, num_energy_groups @@ -54,10 +54,10 @@ contains file_id = file_open(path_source, 'r', parallel=.true.) ! Read the file type - call read_dataset(filetype, file_id, "filetype") + call read_attribute(filetype, file_id, "filetype") ! Check to make sure this is a source file - if (filetype /= 'source') then + if (filetype /= 'source' .and. filetype /= 'statepoint') then call fatal_error("Specified starting source file not a source file & &type.") end if diff --git a/src/state_point.F90 b/src/state_point.F90 index 005b549c30..cc7511dd61 100644 --- a/src/state_point.F90 +++ b/src/state_point.F90 @@ -515,7 +515,7 @@ contains call write_message("Creating source file " // trim(filename) // "...", 5) if (master .or. parallel) then file_id = file_open(filename, 'w', parallel=.true.) - call write_dataset(file_id, "filetype", 'source') + call write_attribute(file_id, "filetype", 'source') end if call write_source_bank(file_id, work_index, source_bank) @@ -831,10 +831,6 @@ contains ! Open source file file_id = file_open(path_source_point, 'r', parallel=.true.) - - ! Read file type - call read_dataset(int_array(1), file_id, "filetype") - end if ! Write out source From f528cbca97fc4450bce58cbb0f33a96accb98b41 Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Wed, 25 Apr 2018 16:12:23 -0500 Subject: [PATCH 62/77] Fix for source_file test, oops --- src/state_point.F90 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/state_point.F90 b/src/state_point.F90 index cc7511dd61..a6e44dfa17 100644 --- a/src/state_point.F90 +++ b/src/state_point.F90 @@ -493,7 +493,7 @@ contains ! Create separate source file if (master .or. parallel) then file_id = file_open(filename, 'w', parallel=.true.) - call write_dataset(file_id, "filetype", 'source') + call write_attribute(file_id, "filetype", 'source') end if else filename = trim(path_output) // 'statepoint.' // & From 8f77f7ba06a8ab93355178d4c38b9615ce0da7f3 Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Wed, 25 Apr 2018 22:26:15 -0500 Subject: [PATCH 63/77] Try not propagating error status from MPI_Finalize --- src/main.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main.cpp b/src/main.cpp index b9e475cd71..42593dc658 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -44,6 +44,6 @@ int main(int argc, char* argv[]) { // If MPI is in use and enabled, terminate it #ifdef MPI - err = MPI_Finalize(); + MPI_Finalize(); #endif } From ebe53476360a93f94a2afa6096829003e290c9b5 Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Thu, 26 Apr 2018 07:03:40 -0500 Subject: [PATCH 64/77] Fix MPI-related bugs --- CMakeLists.txt | 1 + src/api.F90 | 6 ++++++ src/finalize.cpp | 10 ++++++++++ src/finalize.h | 6 ++++++ src/hdf5_interface.F90 | 2 +- src/initialize.cpp | 3 ++- src/main.cpp | 6 ++++-- 7 files changed, 30 insertions(+), 4 deletions(-) create mode 100644 src/finalize.cpp create mode 100644 src/finalize.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 3cfea2227f..7ecd6e3211 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -433,6 +433,7 @@ set(LIBOPENMC_FORTRAN_SRC ) set(LIBOPENMC_CXX_SRC src/initialize.cpp + src/finalize.cpp src/hdf5_interface.cpp src/message_passing.cpp src/plot.cpp diff --git a/src/api.F90 b/src/api.F90 index 49d86edb67..bc0757be57 100644 --- a/src/api.F90 +++ b/src/api.F90 @@ -105,6 +105,11 @@ contains function openmc_finalize() result(err) bind(C) integer(C_INT) :: err + interface + subroutine openmc_free_bank() bind(C) + end subroutine openmc_free_bank + end interface + ! Clear results err = openmc_reset() @@ -170,6 +175,7 @@ contains #ifdef OPENMC_MPI ! Free all MPI types call MPI_TYPE_FREE(MPI_BANK, err) + call openmc_free_bank() #endif end function openmc_finalize diff --git a/src/finalize.cpp b/src/finalize.cpp new file mode 100644 index 0000000000..696a1e80e5 --- /dev/null +++ b/src/finalize.cpp @@ -0,0 +1,10 @@ +#include "finalize.h" + +#include "message_passing.h" + +void openmc_free_bank() +{ +#ifdef OPENMC_MPI + MPI_Type_free(&openmc::mpi::bank); +#endif +} diff --git a/src/finalize.h b/src/finalize.h new file mode 100644 index 0000000000..e606493ca1 --- /dev/null +++ b/src/finalize.h @@ -0,0 +1,6 @@ +#ifndef FINALIZE_H +#define FINALIZE_H + +extern "C" void openmc_free_bank(); + +#endif // FINALIZE_H diff --git a/src/hdf5_interface.F90 b/src/hdf5_interface.F90 index 3fd5e860fd..40f56d88ef 100644 --- a/src/hdf5_interface.F90 +++ b/src/hdf5_interface.F90 @@ -1103,7 +1103,7 @@ contains character(*), intent(in), target :: buffer(:) ! read data to here logical, intent(in), optional :: indep ! independent I/O - integer :: i + integer(HSIZE_T) :: i integer(HSIZE_T) :: dims(1) integer(C_SIZE_T) :: m, n logical(C_BOOL) :: indep_ diff --git a/src/initialize.cpp b/src/initialize.cpp index d8045e4337..c7c37e31db 100644 --- a/src/initialize.cpp +++ b/src/initialize.cpp @@ -71,7 +71,8 @@ void initialize_mpi(MPI_Comm intracomm) // Initialize MPI int flag; - if (!MPI_Initialized(&flag)) MPI_Init(nullptr, nullptr); + MPI_Initialized(&flag); + if (!flag) MPI_Init(nullptr, nullptr); // Determine number of processes and rank for each MPI_Comm_size(intracomm, &openmc::mpi::n_procs); diff --git a/src/main.cpp b/src/main.cpp index 42593dc658..6d0cf1f268 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -38,12 +38,14 @@ int main(int argc, char* argv[]) { err = openmc_calculate_volumes(); break; } + if (err) openmc::fatal_error(openmc_err_msg); // Finalize and free up memory - openmc_finalize(); + err = openmc_finalize(); + if (err) openmc::fatal_error(openmc_err_msg); // If MPI is in use and enabled, terminate it -#ifdef MPI +#ifdef OPENMC_MPI MPI_Finalize(); #endif } From 1d2ebb71f8789410052c10773d0011232aeaa706 Mon Sep 17 00:00:00 2001 From: Adam G Nelson Date: Fri, 27 Apr 2018 19:45:38 -0400 Subject: [PATCH 65/77] Implemented Expansion filters in to the MGXS classes and removed the old score-based expansions --- .gitignore | 5 +- docs/source/io_formats/statepoint.rst | 9 +- docs/source/io_formats/summary.rst | 16 +- docs/source/usersguide/tallies.rst | 63 +- examples/jupyter/mg-mode-part-ii.ipynb | 411 ++--- examples/jupyter/mg-mode-part-iii.ipynb | 309 ++-- examples/jupyter/mgxs-part-iii.ipynb | 919 +++++------ openmc/capi/tally.py | 8 +- openmc/filter.py | 4 +- openmc/filter_expansion.py | 7 + openmc/material.py | 20 +- openmc/mesh.py | 68 +- openmc/mgxs/library.py | 88 +- openmc/mgxs/mgxs.py | 379 ++--- openmc/plotter.py | 23 +- openmc/statepoint.py | 7 - openmc/summary.py | 27 +- openmc/tallies.py | 76 +- src/cmfd_data.F90 | 53 +- src/cmfd_input.F90 | 66 +- src/constants.F90 | 54 +- src/endf.F90 | 16 - src/input_xml.F90 | 240 +-- src/math.F90 | 1 - src/mgxs_header.F90 | 10 +- src/output.F90 | 71 +- src/state_point.F90 | 35 - src/summary.F90 | 156 +- src/tallies/tally.F90 | 205 +-- src/tallies/tally_header.F90 | 6 - src/tallies/trigger.F90 | 76 +- .../cmfd_feed/results_true.dat | 61 +- .../cmfd_nofeed/results_true.dat | 61 +- .../mgxs_library_ce_to_mg/inputs_true.dat | 55 +- .../mgxs_library_condense/inputs_true.dat | 814 +++++----- .../mgxs_library_condense/results_true.dat | 120 +- .../mgxs_library_distribcell/inputs_true.dat | 112 +- .../mgxs_library_distribcell/results_true.dat | 40 +- .../mgxs_library_hdf5/inputs_true.dat | 814 +++++----- .../mgxs_library_mesh/inputs_true.dat | 112 +- .../mgxs_library_mesh/results_true.dat | 144 +- .../mgxs_library_no_nuclides/inputs_true.dat | 814 +++++----- .../mgxs_library_no_nuclides/results_true.dat | 408 ++--- .../mgxs_library_nuclides/inputs_true.dat | 648 ++++---- .../mgxs_library_nuclides/results_true.dat | 2 +- .../sourcepoint_restart/results_true.dat | 1440 ----------------- .../sourcepoint_restart/tallies.xml | 2 +- .../statepoint_restart/results_true.dat | 1328 +++------------ .../statepoint_restart/tallies.xml | 2 +- .../regression_tests/tallies/inputs_true.dat | 68 +- .../regression_tests/tallies/results_true.dat | 2 +- tests/regression_tests/tallies/test.py | 105 +- tests/regression_tests/track_output/test.py | 2 +- 53 files changed, 3695 insertions(+), 6887 deletions(-) diff --git a/.gitignore b/.gitignore index 65c7285af1..0fc2c63bc0 100644 --- a/.gitignore +++ b/.gitignore @@ -99,4 +99,7 @@ examples/jupyter/plots .tox/ .python-version .coverage -htmlcov \ No newline at end of file +htmlcov + +# Test data +tests/xsdir diff --git a/docs/source/io_formats/statepoint.rst b/docs/source/io_formats/statepoint.rst index f0f2af59b2..38dae7dd7a 100644 --- a/docs/source/io_formats/statepoint.rst +++ b/docs/source/io_formats/statepoint.rst @@ -133,15 +133,8 @@ The current version of the statepoint file format is 17.0. - **derivative** (*int*) -- ID of the derivative applied to the tally. - **n_score_bins** (*int*) -- Number of scoring bins for a single - nuclide. In general, this can be greater than the number of - user-specified scores since each score might have multiple scoring - bins, e.g., scatter-PN. + nuclide. - **score_bins** (*char[][]*) -- Values of specified scores. - - **n_user_scores** (*int*) -- Number of scores without accounting - for those added by expansions, e.g. scatter-PN. - - **moment_orders** (*char[][]*) -- Tallying moment orders for - Legendre and spherical harmonic tally expansions (e.g., 'P2', - 'Y1,2', etc.). - **results** (*double[][][2]*) -- Accumulated sum and sum-of-squares for each bin of the i-th tally. The first dimension represents combinations of filter bins, the second dimensions represents diff --git a/docs/source/io_formats/summary.rst b/docs/source/io_formats/summary.rst index 049749b599..76c412b860 100644 --- a/docs/source/io_formats/summary.rst +++ b/docs/source/io_formats/summary.rst @@ -4,7 +4,7 @@ Summary File Format =================== -The current version of the summary file format is 5.0. +The current version of the summary file format is 6.0. **/** @@ -104,8 +104,13 @@ The current version of the summary file format is 5.0. - **atom_density** (*double[]*) -- Total atom density of the material in atom/b-cm. - **nuclides** (*char[][]*) -- Array of nuclides present in the - material, e.g., 'U235'. + material, e.g., 'U235'. This data set is only present if nuclides + are used. - **nuclide_densities** (*double[]*) -- Atom density of each nuclide. + This data set is only present if 'nuclides' data set is present. + - **macroscopics** (*char[][]*) -- Array of macroscopic data sets + present in the material. This dataset is only present if + macroscopic data sets are used in multi-group mode. - **sab_names** (*char[][]*) -- Names of S(:math:`\alpha,\beta`) tables assigned to the material. @@ -116,6 +121,13 @@ The current version of the summary file format is 5.0. :Datasets: - **names** (*char[][]*) -- Names of nuclides. - **awrs** (*float[]*) -- Atomic weight ratio of each nuclide. +**/macroscopics/** + +:Attributes: - **n_macroscopics** (*int*) -- Number of macroscopic data sets + in the problem. + +:Datasets: - **names** (*char[][]*) -- Names of the macroscopic data sets. + **/tallies/tally /** :Datasets: - **name** (*char[]*) -- Name of the tally. diff --git a/docs/source/usersguide/tallies.rst b/docs/source/usersguide/tallies.rst index e0f8ab1797..19691e32bf 100644 --- a/docs/source/usersguide/tallies.rst +++ b/docs/source/usersguide/tallies.rst @@ -21,7 +21,12 @@ region of phase space, as in: Thus, to specify a tally, we need to specify what regions of phase space should be included when deciding whether to score an event as well as what the scoring function (:math:`f` in the above equation) should be used. The regions of phase -space are called *filters* and the scoring functions are simply called *scores*. +space are generally called *filters* and the scoring functions are simply +called *scores*. + +The only cases when *filters* do not correspond directly with the regions of +phase space are when expansion functions are applied in the integrand, such as +for Legendre expansions of the scattering kernel. ------- Filters @@ -69,10 +74,9 @@ Scores ------ To specify the scoring functions, a list of strings needs to be given to the -:attr:`Tally.scores` attribute. You can score the flux ('flux'), a reaction rate -('total', 'fission', etc.), or even scattering moments (e.g., 'scatter-P3'). For -example, to tally the elastic scattering rate and the fission neutron -production, you'd assign:: +:attr:`Tally.scores` attribute. You can score the flux ('flux'), or a reaction +rate ('total', 'fission', etc.). For example, to tally the elastic scattering +rate and the fission neutron production, you'd assign:: tally.scores = ['elastic', 'nu-fission'] @@ -98,12 +102,6 @@ The following tables show all valid scores: +======================+===================================================+ |flux |Total flux. | +----------------------+---------------------------------------------------+ - |flux-YN |Spherical harmonic expansion of the direction of | - | |motion :math:`\left(\Omega\right)` of the total | - | |flux. This score will tally all of the harmonic | - | |moments of order 0 to N. N must be between 0 and | - | |10. | - +----------------------+---------------------------------------------------+ .. table:: **Reaction scores: units are reactions per source particle.** @@ -118,43 +116,10 @@ The following tables show all valid scores: +----------------------+---------------------------------------------------+ |fission |Total fission reaction rate. | +----------------------+---------------------------------------------------+ - |scatter |Total scattering rate. Can also be identified with | - | |the "scatter-0" response type. | - +----------------------+---------------------------------------------------+ - |scatter-N |Tally the N\ :sup:`th` \ scattering moment, where N| - | |is the Legendre expansion order of the change in | - | |particle angle :math:`\left(\mu\right)`. N must be | - | |between 0 and 10. As an example, tallying the 2\ | - | |:sup:`nd` \ scattering moment would be specified as| - | |``scatter-2``. | - +----------------------+---------------------------------------------------+ - |scatter-PN |Tally all of the scattering moments from order 0 to| - | |N, where N is the Legendre expansion order of the | - | |change in particle angle | - | |:math:`\left(\mu\right)`. That is, "scatter-P1" is | - | |equivalent to requesting tallies of "scatter-0" and| - | |"scatter-1". Like for "scatter-N", N must be | - | |between 0 and 10. As an example, tallying up to the| - | |2\ :sup:`nd` \ scattering moment would be specified| - | |as `` scatter-P2 ``. | - +----------------------+---------------------------------------------------+ - |scatter-YN |"scatter-YN" is similar to "scatter-PN" except an | - | |additional expansion is performed for the incoming | - | |particle direction :math:`\left(\Omega\right)` | - | |using the real spherical harmonics. This is useful| - | |for performing angular flux moment weighting of the| - | |scattering moments. Like "scatter-PN", "scatter-YN"| - | |will tally all of the moments from order 0 to N; N | - | |again must be between 0 and 10. | + |scatter |Total scattering rate. | +----------------------+---------------------------------------------------+ |total |Total reaction rate. | +----------------------+---------------------------------------------------+ - |total-YN |The total reaction rate expanded via spherical | - | |harmonics about the direction of motion of the | - | |neutron, :math:`\Omega`. This score will tally all | - | |of the harmonic moments of order 0 to N. N must be| - | |between 0 and 10. | - +----------------------+---------------------------------------------------+ |(n,2nd) |(n,2nd) reaction rate. | +----------------------+---------------------------------------------------+ |(n,2n) |(n,2n) reaction rate. | @@ -248,10 +213,10 @@ The following tables show all valid scores: +----------------------+---------------------------------------------------+ |nu-fission |Total production of neutrons due to fission. | +----------------------+---------------------------------------------------+ - |nu-scatter, |These scores are similar in functionality to their | - |nu-scatter-N, |``scatter*`` equivalents except the total | - |nu-scatter-PN, |production of neutrons due to scattering is scored | - |nu-scatter-YN |vice simply the scattering rate. This accounts for | + |nu-scatter, |This score is similar in functionality to the | + | |``scatter`` score except the total production of | + | |neutrons due to scattering is scored vice simply | + | |the scattering rate. This accounts for | | |multiplicity from (n,2n), (n,3n), and (n,4n) | | |reactions. | +----------------------+---------------------------------------------------+ diff --git a/examples/jupyter/mg-mode-part-ii.ipynb b/examples/jupyter/mg-mode-part-ii.ipynb index 7a2b029de0..6380c32b08 100644 --- a/examples/jupyter/mg-mode-part-ii.ipynb +++ b/examples/jupyter/mg-mode-part-ii.ipynb @@ -26,9 +26,7 @@ { "cell_type": "code", "execution_count": 1, - "metadata": { - "collapsed": false - }, + "metadata": {}, "outputs": [], "source": [ "import matplotlib.pyplot as plt\n", @@ -50,9 +48,7 @@ { "cell_type": "code", "execution_count": 2, - "metadata": { - "collapsed": false - }, + "metadata": {}, "outputs": [], "source": [ "# 1.6% enriched fuel\n", @@ -84,9 +80,7 @@ { "cell_type": "code", "execution_count": 3, - "metadata": { - "collapsed": true - }, + "metadata": {}, "outputs": [], "source": [ "# Instantiate a Materials object\n", @@ -106,9 +100,7 @@ { "cell_type": "code", "execution_count": 4, - "metadata": { - "collapsed": true - }, + "metadata": {}, "outputs": [], "source": [ "# Create cylinders for the fuel and clad\n", @@ -136,9 +128,7 @@ { "cell_type": "code", "execution_count": 5, - "metadata": { - "collapsed": false - }, + "metadata": {}, "outputs": [], "source": [ "# Create a Universe to encapsulate a fuel pin\n", @@ -173,9 +163,7 @@ { "cell_type": "code", "execution_count": 6, - "metadata": { - "collapsed": false - }, + "metadata": {}, "outputs": [], "source": [ "# Create a Universe to encapsulate a control rod guide tube\n", @@ -210,9 +198,7 @@ { "cell_type": "code", "execution_count": 7, - "metadata": { - "collapsed": false - }, + "metadata": {}, "outputs": [], "source": [ "# Create fuel assembly Lattice\n", @@ -231,9 +217,7 @@ { "cell_type": "code", "execution_count": 8, - "metadata": { - "collapsed": true - }, + "metadata": {}, "outputs": [], "source": [ "# Create array indices for guide tube locations in lattice\n", @@ -263,9 +247,7 @@ { "cell_type": "code", "execution_count": 9, - "metadata": { - "collapsed": false - }, + "metadata": {}, "outputs": [], "source": [ "# Create root Cell\n", @@ -290,15 +272,23 @@ { "cell_type": "code", "execution_count": 10, - "metadata": { - "collapsed": false - }, + "metadata": {}, "outputs": [ { "data": { - "image/png": "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\n", "text/plain": [ - "" + "" + ] + }, + "execution_count": 10, + "metadata": {}, + "output_type": "execute_result" + }, + { + "data": { + "image/png": "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\n", + "text/plain": [ + "" ] }, "metadata": {}, @@ -321,9 +311,7 @@ { "cell_type": "code", "execution_count": 11, - "metadata": { - "collapsed": false - }, + "metadata": {}, "outputs": [], "source": [ "# Create Geometry and set root universe\n", @@ -343,15 +331,13 @@ { "cell_type": "code", "execution_count": 12, - "metadata": { - "collapsed": true - }, + "metadata": {}, "outputs": [], "source": [ "# OpenMC simulation parameters\n", "batches = 600\n", "inactive = 50\n", - "particles = 2000\n", + "particles = 3000\n", "\n", "# Instantiate a Settings object\n", "settings_file = openmc.Settings()\n", @@ -383,9 +369,7 @@ { "cell_type": "code", "execution_count": 13, - "metadata": { - "collapsed": false - }, + "metadata": {}, "outputs": [], "source": [ "# Instantiate a 2-group EnergyGroups object\n", @@ -402,9 +386,7 @@ { "cell_type": "code", "execution_count": 14, - "metadata": { - "collapsed": true - }, + "metadata": {}, "outputs": [], "source": [ "# Initialize a 2-group MGXS Library for OpenMC\n", @@ -424,9 +406,7 @@ { "cell_type": "code", "execution_count": 15, - "metadata": { - "collapsed": true - }, + "metadata": {}, "outputs": [], "source": [ "# Specify multi-group cross section types to compute\n", @@ -446,9 +426,7 @@ { "cell_type": "code", "execution_count": 16, - "metadata": { - "collapsed": false - }, + "metadata": {}, "outputs": [], "source": [ "# Specify a \"cell\" domain type for the cross section tally filters\n", @@ -470,9 +448,7 @@ { "cell_type": "code", "execution_count": 17, - "metadata": { - "collapsed": false - }, + "metadata": {}, "outputs": [], "source": [ "# Do not compute cross sections on a nuclide-by-nuclide basis\n", @@ -489,9 +465,7 @@ { "cell_type": "code", "execution_count": 18, - "metadata": { - "collapsed": false - }, + "metadata": {}, "outputs": [ { "name": "stderr", @@ -519,9 +493,7 @@ { "cell_type": "code", "execution_count": 19, - "metadata": { - "collapsed": false - }, + "metadata": {}, "outputs": [], "source": [ "# Check the library - if no errors are raised, then the library is satisfactory.\n", @@ -538,9 +510,7 @@ { "cell_type": "code", "execution_count": 20, - "metadata": { - "collapsed": false - }, + "metadata": {}, "outputs": [], "source": [ "# Construct all tallies needed for the multi-group cross section library\n", @@ -559,9 +529,7 @@ { "cell_type": "code", "execution_count": 21, - "metadata": { - "collapsed": true - }, + "metadata": {}, "outputs": [], "source": [ "# Create a \"tallies.xml\" file for the MGXS Library\n", @@ -579,10 +547,21 @@ { "cell_type": "code", "execution_count": 22, - "metadata": { - "collapsed": true - }, - "outputs": [], + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "/home/nelsonag/git/openmc/openmc/mixin.py:71: IDWarning: Another Filter instance already exists with id=66.\n", + " warn(msg, IDWarning)\n", + "/home/nelsonag/git/openmc/openmc/mixin.py:71: IDWarning: Another Filter instance already exists with id=2.\n", + " warn(msg, IDWarning)\n", + "/home/nelsonag/git/openmc/openmc/mixin.py:71: IDWarning: Another Filter instance already exists with id=11.\n", + " warn(msg, IDWarning)\n" + ] + } + ], "source": [ "# Instantiate a tally Mesh\n", "mesh = openmc.Mesh()\n", @@ -618,9 +597,7 @@ { "cell_type": "code", "execution_count": 23, - "metadata": { - "collapsed": false - }, + "metadata": {}, "outputs": [ { "name": "stdout", @@ -652,11 +629,11 @@ " %%%%%%%%%%%\n", "\n", " | The OpenMC Monte Carlo Code\n", - " Copyright | 2011-2017 Massachusetts Institute of Technology\n", + " Copyright | 2011-2018 Massachusetts Institute of Technology\n", " License | http://openmc.readthedocs.io/en/latest/license.html\n", - " Version | 0.8.0\n", - " Git SHA1 | 4b01fd311461f1350989cb84ec18fe2cbaa8fa9f\n", - " Date/Time | 2017-03-10 17:30:51\n", + " Version | 0.10.0\n", + " Git SHA1 | 6c2d82a4d7dfe10312329d5969568fc03a698416\n", + " Date/Time | 2018-04-22 15:02:43\n", " OpenMP Threads | 8\n", "\n", "\n", @@ -665,23 +642,13 @@ "\n", " ============================> RESULTS <============================\n", "\n", - " k-effective (Collision) = 1.16584 +/- 0.00111\n", - " k-effective (Track-length) = 1.16532 +/- 0.00131\n", - " k-effective (Absorption) = 1.16513 +/- 0.00100\n", - " Combined k-effective = 1.16538 +/- 0.00086\n", + " k-effective (Collision) = 1.16513 +/- 0.00090\n", + " k-effective (Track-length) = 1.16337 +/- 0.00104\n", + " k-effective (Absorption) = 1.16479 +/- 0.00080\n", + " Combined k-effective = 1.16460 +/- 0.00068\n", " Leakage Fraction = 0.00000 +/- 0.00000\n", "\n" ] - }, - { - "data": { - "text/plain": [ - "0" - ] - }, - "execution_count": 23, - "metadata": {}, - "output_type": "execute_result" } ], "source": [ @@ -699,9 +666,7 @@ { "cell_type": "code", "execution_count": 24, - "metadata": { - "collapsed": false - }, + "metadata": {}, "outputs": [], "source": [ "# Move the statepoint File\n", @@ -724,9 +689,7 @@ { "cell_type": "code", "execution_count": 25, - "metadata": { - "collapsed": false - }, + "metadata": {}, "outputs": [], "source": [ "# Load the statepoint file\n", @@ -747,9 +710,7 @@ { "cell_type": "code", "execution_count": 26, - "metadata": { - "collapsed": false - }, + "metadata": {}, "outputs": [], "source": [ "# Initialize MGXS Library with OpenMC statepoint data\n", @@ -781,23 +742,8 @@ { "cell_type": "code", "execution_count": 27, - "metadata": { - "collapsed": false - }, - "outputs": [ - { - "name": "stderr", - "output_type": "stream", - "text": [ - "/home/nelsonag/git/openmc/openmc/tallies.py:1834: RuntimeWarning: invalid value encountered in true_divide\n", - " self_rel_err = data['self']['std. dev.'] / data['self']['mean']\n", - "/home/nelsonag/git/openmc/openmc/tallies.py:1835: RuntimeWarning: invalid value encountered in true_divide\n", - " other_rel_err = data['other']['std. dev.'] / data['other']['mean']\n", - "/home/nelsonag/git/openmc/openmc/tallies.py:1836: RuntimeWarning: invalid value encountered in true_divide\n", - " new_tally._mean = data['self']['mean'] / data['other']['mean']\n" - ] - } - ], + "metadata": {}, + "outputs": [], "source": [ "# Create a MGXS File which can then be written to disk\n", "mgxs_file = mgxs_lib.create_mg_library(xs_type='macro', xsdata_names=['fuel', 'zircaloy', 'water'])\n", @@ -820,24 +766,35 @@ { "cell_type": "code", "execution_count": 28, - "metadata": { - "collapsed": false - }, - "outputs": [], + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "/home/nelsonag/git/openmc/openmc/mixin.py:71: IDWarning: Another Material instance already exists with id=1.\n", + " warn(msg, IDWarning)\n", + "/home/nelsonag/git/openmc/openmc/mixin.py:71: IDWarning: Another Material instance already exists with id=2.\n", + " warn(msg, IDWarning)\n", + "/home/nelsonag/git/openmc/openmc/mixin.py:71: IDWarning: Another Material instance already exists with id=3.\n", + " warn(msg, IDWarning)\n" + ] + } + ], "source": [ "# Re-define our materials to use the multi-group macroscopic data\n", "# instead of the continuous-energy data.\n", "\n", "# 1.6% enriched fuel UO2\n", - "fuel_mg = openmc.Material(name='UO2')\n", + "fuel_mg = openmc.Material(name='UO2', material_id=1)\n", "fuel_mg.add_macroscopic('fuel')\n", "\n", "# cladding\n", - "zircaloy_mg = openmc.Material(name='Clad')\n", + "zircaloy_mg = openmc.Material(name='Clad', material_id=2)\n", "zircaloy_mg.add_macroscopic('zircaloy')\n", "\n", "# moderator\n", - "water_mg = openmc.Material(name='Water')\n", + "water_mg = openmc.Material(name='Water', material_id=3)\n", "water_mg.add_macroscopic('water')\n", "\n", "# Finally, instantiate our Materials object\n", @@ -868,9 +825,7 @@ { "cell_type": "code", "execution_count": 29, - "metadata": { - "collapsed": true - }, + "metadata": {}, "outputs": [], "source": [ "# Set the energy mode\n", @@ -890,9 +845,7 @@ { "cell_type": "code", "execution_count": 30, - "metadata": { - "collapsed": true - }, + "metadata": {}, "outputs": [], "source": [ "# Create a \"tallies.xml\" file for the MGXS Library\n", @@ -902,7 +855,7 @@ "mesh_tally = openmc.Tally(name='mesh tally')\n", "mesh_tally.filters = [openmc.MeshFilter(mesh)]\n", "mesh_tally.scores = ['fission']\n", - "tallies_file.add_tally(mesh_tally)\n", + "tallies_file.append(mesh_tally)\n", "\n", "# Export to \"tallies.xml\"\n", "tallies_file.export_to_xml()" @@ -919,15 +872,13 @@ { "cell_type": "code", "execution_count": 31, - "metadata": { - "collapsed": false - }, + "metadata": {}, "outputs": [ { "data": { - "image/png": "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\n", + "image/png": "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\n", "text/plain": [ - "" + "" ] }, "metadata": {}, @@ -935,9 +886,9 @@ }, { "data": { - "image/png": "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\nRU5ErkJggg==\n", + "image/png": "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\n", "text/plain": [ - "" + "" ] }, "metadata": {}, @@ -945,9 +896,9 @@ }, { "data": { - "image/png": "iVBORw0KGgoAAAANSUhEUgAAAY4AAAEaCAYAAAAG87ApAAAABHNCSVQICAgIfAhkiAAAAAlwSFlz\nAAALEgAACxIB0t1+/AAAIABJREFUeJzt3Xl8VNX9//HXJ3uAEJB9R42guCASEdQqdakraututS4U\nXGqtP21r7betbe23te23m7ZWccEdRdtawV3rWgEFUVwQQVxA9j0sCST5/P64NziJyWQmmckseT8f\n3kfmnrnL54RxPrn3nHuOuTsiIiKxykl1ACIiklmUOEREJC5KHCIiEhclDhERiYsSh4iIxEWJQ0RE\n4qLEIZJgZvZjM7s9Scf+lZmtMbMVyTi+SCyUOCRpzOwcM5ttZpvNbLmZPWlmh6Ywnv5m9o/wi3ej\nmb1jZhe08phjzWxpZJm7/9rdv92qYBs/1wDgamCYu/dOwPFuNbObI9bzzWxLE2WjYzjeXWb2q9bG\nJelPiUOSwsyuAv4M/BroBQwEbgZObmL7vDYI615gCTAI6AZ8C1jZBudNlEHAWndfFe+OTfx+XwYO\nj1gvBz4DDmtQBjAn3nPGq40+A5II7q5FS0IXoBTYDJweZZufA48A9wGbgG8DhQTJZlm4/BkoDLfv\nDkwHNgDrgFeAnPC9a4DPgQpgAXBkE+fcDOwfJabRwGvhOd4Gxka8twswOYxrPfAo0BHYBtSGx94M\n9A3rdl/EvicB74XHfRHYK+K9T4DvA/OAjcBDQFEjsR3V4Fx3xXjsa8JjVwF5DY7ZPzxe93D9h8B1\nwMcNyp6L2OdhYEUY68vA3mH5RGAHsD2Mb1pY3hf4B7A6PO4V0T4Dqf7saoltSXkAWrJvAY4Fqht+\nUTXY5ufhF80pBFe+xcAvgZlAT6BH+CV+fbj9b4BbgPxw+QpgwFCCq4i+4XaDgd2bOOdzwH+Bs4CB\nDd7rB6wFjg/jOTpc7xG+/3j4pd41PP/hYflYYGkjdbsvfD0E2BIeLz/8Il4EFITvfwK8Hn7B7gLM\nBy5pIv5654rx2G8BA4DiJo75MfD18PV04Ajg/gZlP4vY/iKghC+S/FsR790F/CpiPYfgSuVnQAGw\nG7AYOKapz0CqP7taYlt0q0qSoRuwxt2rm9luhrs/6u617r4N+CbwS3df5e6rgV8A54Xb7gD6AIPc\nfYe7v+LBt08NwZfYMDPLd/dP3P2jJs53OsGVyk+Bj83sLTM7MHzvXOAJd38ijOdZYDZwvJn1AY4j\n+EJfH57/pRh/F2cCj7v7s+6+A/g/giR5cMQ2N7r7MndfB0wD9k/wsZeEv9/GvAQcZmY5wCiCxP1K\nRNkh4TYAuPud7l7h7lUEX/zDzay0iWMfSJB4f+nu2919MXAbQeKu0/AzIBlAiUOSYS3QPYZ71ksa\nrPcFPo1Y/zQsA/g9wV/Tz5jZYjP7EYC7LwKuJPgSW2VmD5pZXxoRfun/yN33Jmh3eQt41MyMoP3g\ndDPbULcAhxIkqwHAOndfH0vlo9XJ3WvDeveL2Cayh9RWoFMCj93wd9zQywRtGvsCi919K/BqRFkx\nMAvAzHLN7AYz+8jMNhFc0UBwG7Exg4C+DX6nPyb43ccan6QhJQ5JhhlAJcEtiGgaDs28jODLps7A\nsIzwr9yr3X03YBxwlZkdGb73gLsfGu7rwG+bC9Dd1xD8hV53i2gJcK+7d4lYOrr7DeF7u5hZlxjq\n0FC9OoVJagBBm0xrxXLs5uJ7GRgOnEBwpQFBm8mAsOwNd68My88h6NxwFEE71uC6UzdxriXAxw1+\npyXufnwc8UkaUuKQhHP3jQT3tf9mZqeYWYewW+dxZva7KLtOAX5iZj3MrHt4jPsAzOxEMysLvxw3\nEdyiqjGzoWZ2hJkVEiSrbeF7X2JmvzWzfcwsz8xKgEuBRe6+NjzPODM7JvzLuijsatvf3ZcDTwI3\nm1nXsC51PY9WAt2i3K6ZCpxgZkeaWT5Bd9oqgvab1mr1scMrtpXA9wgTR3gLcFZY9nLE5iXh8dcC\nHQh6zEVaSdCOUed1YJOZXWNmxeHvdZ+I24OSoZQ4JCnc/Y/AVcBPCHrULAEuJ+iN1JRfEbQrzAPe\nAd4MywD2IGjc3kxwRXOzu79I0L5xA7CG4JZPT4LbIY3pAPyLoAfSYoK/1k8K411C8Nf0jyPi/QFf\n/D9yHkE7ywfAKoLbY7j7BwQJb3F4O6bebTJ3X0DQfnJTGOM4YJy7b4/ye4hJAo/9MkFnhP9GlL1C\n8LuMTBz3ENwa+xx4n6A9JNIdBG1NG8zsUXevCWPan6ARfg1wO8HVimQwC/64EBERiY2uOEREJC5K\nHCIiEhclDhERiYsSh4iIxEWJQ0RE4pJVo1Ga2ThgXElJyYQhQ4akOhwRkYwxZ86cNe7eI5Zts7I7\nbnl5uc+ePTvVYYiIZAwzm+Pu5c1vqVtVIiISp6xKHGY2zswmbdy4MdWhiIhkraxKHO4+zd0nlpZq\nRAMRkWTJqsQhIiLJl1WJQ7eqRESSL6sSh25ViYgkX1Yljjq1WdjFWEQkXWTlA4Cd+paxqXIHnYvy\nUx2SiEjWyaorjrpbVTtq4dzbZ7Fha6vnyhERkQayKnHUGdStAx8sr+Ds22axdnNVqsMREckqWZk4\nSoryuf38cj5es5mzJs1k1abKVIckIpI1sjJxABw2pAd3XTiKzzds48xJM1m2YVuqQxIRyQpZlTga\nPscxerdu3Dt+FGsqqjjj1hksWbc1xRGKiGS+rEocjT3HMXLQLtw/4SAqKqs549YZfLxmSwojFBHJ\nfFmVOJqyX/8uTJkwmqrqWs64dQYLV1akOiQRkYzVLhIHwLC+nXlo4mgAzpo0k/eXbUpxRCIimand\nJA6APXqVMPXiMRTk5XD2bTOZt3RDqkMSEck4WZU4YhnkcNfuHZl68RhKivL45m2zmPPp+jaMUEQk\n82VV4oh1kMMBu3Rg6sVj6F5SyHl3zGLm4rVtFKGISObLqsQRj75dinlo4mj6dinmgsmv88rC1akO\nSUQkI7TbxAHQs3MRD04czeBuHRl/92yen78y1SGJiKS9dp04ALp3KuTBiaMZ2quES+6bw1PvLk91\nSCIiaa3dJw6ALh0KuH/CQezbr5TvPDCXf7/1eapDEhFJW1mVOFozdWznonzuGX8Q5YO6cuVDb/Hw\n7CVJiFBEJPOZNzFbnpndGMP+m9z9J4kNqfXKy8t99uzZLdp32/YaJt47m1cWruF/v74P3zxoUIKj\nExFJP2Y2x93LY9k22hXHycCcZpZTWxdq+ikuyOW2b5VzxJ49+Z9/vcudr36c6pBERNJKtKlj/+Tu\nd0fb2cy6JjietFCUn8st547kiilz+eX096mqruXSsbunOiwRkbTQ5BWHu/+5uZ1j2SZTFeTl8Ndz\nRnDS8L789qkP+PNzH9LUbT0RkfYk2hUHAGa2K/BdYHDk9u5+UvLCSg95uTn86cz9KcjL4c/PLaSq\nupYfHjMUM0t1aCIiKdNs4gAeBe4ApgG1yQ0n/eTmGL87dT8K8nL4+4sfUbWjlp+euJeSh4i0W7Ek\njkp3j6WHVdbKyTH+95R9KMzL4c7/fkxVdQ3Xn7wPOTlKHiLS/sSSOP5iZtcBzwBVdYXu/mbSokpD\nZsbPThxGYV4ut7z0Edura7nh1P3IVfIQkXYmlsSxL3AecARf3KrycL1dMTOuOXYoRflBm8f2mlr+\ncPpw8nKz6jlKEZGoYkkcXwd2c/ftyQ6mtcxsHDCurKwsmefgyqOGUJCXw++eWsD26lr+ctYICvKU\nPESkfYjl2+5toEuyA0mEWOfjSITLxpbx0xOH8eS7K7j0vjlU7qhJ+jlFRNJBLFccvYAPzOwN6rdx\nZH133OaMP3RXCvNy+Mmj7zLhntlMOq+c4oLcVIclIpJUsSSO65IeRQY7d/QgCvJyuOYf87jwrte5\n4/wD6VgYy69VRCQzxfIN9xmw3N0rAcysmOAqREJnlA+gMC+Hq6a+zXl3zOKui0bRuSg/1WGJiCRF\nLG0cD1P/wb+asEwinLx/P/569gje+Xwj594+iw1b074vgYhIi8SSOPIie1SFrwuSF1LmOm7fPtxy\n7kg+WF7B2bfNYu3mquZ3EhHJMLEkjtVmtrMh3MxOBtYkL6TMduRevbj9/HI+XrOZsybNZNWmylSH\nJCKSULEkjkuBH5vZZ2b2GXANMDG5YWW2w4b0YPIFo/h8wzbOnDSTZRu2pTokEZGEaTJxmNkYMzN3\nX+Tuo4FhwN7ufrC7f9R2IWamMbt3497xo1hTUcUZt85gybqtqQ5JRCQhol1xnA/MMbMHzewCoJO7\nV7RNWNlh5KBduH/CQVRUVnPGrTP4eM2WVIckItJq0SZyusTdDwB+DnQF7jKzGWb2azM7zMz0pFsM\n9uvfhSkTRlNVXcsZt85g4UrlXhHJbM22cbj7B+7+J3c/lmBgw1eB04FZyQ4OwMx2M7M7zOyRtjhf\nMgzr25mHJo4G4KxJM3l/2aYURyQi0nJxjczn7tvc/QngWncvb+lJzexOM1tlZu82KD/WzBaY2SIz\n+1F4zsXuPr6l50oXe/QqYerFYyjIy+Hs22Yyb+mGVIckItIiLR3S9f1Wnvcu4NjIgvDW19+A4wga\n4s82s2GtPE9a2bV7R6ZePIaSojy+edss5ny6PtUhiYjErckhR8zsqqbeAjq15qTu/rKZDW5QPApY\n5O6Lw/M/CJxM65NUWhmwSwemXjyGc26byXl3zOLOCw5k9G7dUh2WiEjMol1x/JqgUbykwdKpmf1a\nqh+wJGJ9KdDPzLqZ2S3ACDO7tqmdzWyimc02s9mrV69OQniJ07dLMVMvHkPfLsVcMPl1XlmY3vGK\niESKNsjhm8Cj7j6n4Rtm9u0kxNLYHKzu7muBS5rb2d0nAZMAysvLPcGxJVzPzkU8OHE0594+i/F3\nz+bmcw7gqGEaO1JE0l+0K4cLgU+beK/FDeNRLAUGRKz3B5bFcwAzG2dmkzZu3JjQwJKle6dCHpw4\nmr16l3DxfXP491ufpzokEZFmRXuOY4G7NzomlbuvTEIsbwB7mNmuZlYAnAU8Fs8B2nIGwETp0qGA\n+yeMpnxQV6586C3undlUrhYRSQ/Rhhz5eXM7x7JNE/tNAWYAQ81sqZmNd/dq4HLgaWA+MNXd32vJ\n8TNNp8I87r5oFEcM7clPH32Xm19clOqQRESaZO6NNweY2VLgj9H2BSa4+57JCKwlzGwcMK6srGzC\nwoULUx1O3HbU1HL11Ld57O1lXDp2d354zFDMGmv6ERFJLDObE+vzedEax28j6EUVzW0xR9UG3H0a\nMK28vHxCqmNpifzcHP505v6UFOXx9xc/YtO2HVx/8j7k5Ch5iEj6aDJxuPsv2jIQCeTmGL86ZR86\nFeVx60uL2VxVzf+dPpz83GT0gBYRiV8sc45njIhbVakOpVXMjGuP24vS4nx+99QCtlRV89dzDqAo\nX+NKikjqZdWfsZnYqyqay8aWcf3Je/Pc/FVcOPkNNldVpzokEZHsShzZ6Lwxg/nTmcN5/ZN1fPP2\nWWzYur35nUREkqjZW1Vm1gOYAAyO3N7dL0peWC2TLbeqGvr6iP50LMjj8gfmcuatM7l3/Ch6di5K\ndVgi0k7FcsXxb6AUeA54PGJJO9l2qyrS1/buzeQLD2TJ+q2crqloRSSFYkkcHdz9Gnef6u7/qFuS\nHpl8ySFl3bn/2wexYesOTr9lBotWaTZBEWl7sSSO6WZ2fNIjkZiMGNiVByeOprrWOf2WGbyzNDPG\n5RKR7BFL4vgeQfKoNLOKcEnLuU8zbZDDltqrT2ceuWQMHQryOPu2mcxavDbVIYlIOxLLnOMl7p7j\n7kXh6xJ379wWwcUrm9s4GhrcvSOPXDqGXp0L+dadr/PCglWpDklE2omYuuOa2Ulm9n/hcmKyg5LY\n9CkNJoQq69mJCXfPZvq8uEahFxFpkWYTh5ndQHC76v1w+V5YJmmgW6dCpkwczYiBXfjulLnc/don\nqQ5JRLJcLFccxwNHu/ud7n4ncGxYJmmic1E+91x0EEft1YvrHnuP3zwxn9ratJ8EUUQyVKxPjneJ\neJ39DQgZqLggl1vOHcm5owdy68uLufKht6iqrkl1WCKShWIZ5PA3wFwze4FgDo7DgGuTGlULZeuT\n47HKzTGuP3kf+nXpwG+f+oBVFZXcel45pcX5qQ5NRLJIkxM51dvIrA9wIEHimOXuK5IdWGuUl5f7\n7NmzUx1GSv1r7lJ++Mg8duveickXHkjfLsWpDklE0lg8EzlFmzp2z/DnAUAfYCmwBOgblkka+/qI\n/tx14SiWbdjGN25+jQ9WpOWjNyKSgaJNHTvJ3SeGt6gacnc/IrmhtZyuOL4wf/kmLpz8Bluqqrn1\nvJEcXNY91SGJSBqK54qj2VtVZlbk7pXNlaUTJY76lm3YxgWTX+fjNVv4/WnDOWVEv1SHJCJpJiG3\nqiK8FmOZpKm+XYp5+JKDGTmoK1c+9BZ/fPZDddcVkRaL1sbR28xGAsVmNsLMDgiXsUCHNoswDu1l\nrKqWKC3O5+6LRnH6yP7c+PxCvvPAm2zdrhkFRSR+0do4zgcuAMqBNwh6VAFsAu5293+2RYAtoVtV\nTXN37nj1Y379xHz27N2Z288vV48rEUl4G8epmTb/hhJH8174YBVXTJlLYX4ut543kpGDuqY6JBFJ\noUS3cYw0s51PjptZVzP7VYujk7Tw1T178s/LDqZjYS5nT5rJA7M+I5ZnekREYkkcx7n7hroVd1+P\nxqrKCnv0KuHRyw5h9O7d+PG/3uH7D89j23YNUyIi0cWSOHLNrLBuxcyKgcIo20sG6dqxgMkXHMiV\nR+3BP+cu5es3/5eP12xJdVgiksZiSRz3Ac+b2Xgzuwh4Frg7uWFJW8rNMa48agh3XTiKFZsqOemm\nV3nyneWpDktE0lQsMwD+DvgVsBewN3B9WCZZ5vAhPXj8iq+wW89OXHr/m1zzyDy2VKnLrojUF+uw\n6vOBp9z9auAVMytJYkySQv26FPPIJWP4zld3Z+qcJZxw4yu8tWRD8zuKSLsRywyAE4BHgFvDon7A\no8kMSlIrPzeHHxyzJw9OGM326lpO/ftr/Pm5D9leXZvq0EQkDcRyxfEd4BCCB/9w94VAz2QG1VJ6\ncjyxDtqtG09eeRgn7teHPz+3kHE3vcqbn61PdVgikmKxJI4qd99et2JmeUBadvh392nuPrG0VJMU\nJkppcT5/OWsEt3+rnE2VOzj1769x3b/fZbPaPkTarVgSx0tm9mOCMauOBh4GpiU3LEk3Rw3rxbNX\nHc75YwZzz8xPOfIPL/Lw7CUaLFGkHYplyJEcYDzwNYLxqp4Gbvc0fsxYQ44k19zP1vPzae/z9pIN\nDOvTmZ+csJfm+RDJcAkdqyrioAUE3XE/d/dVrYgv6ZQ4kq+21pk2bxm/e2oBn2/Yxlf26M7lXy3j\noN26pTo0EWmBRE0de4uZ7R2+LgXeAu4B5prZ2QmJVDJWTo5x8v79eP7qw7n2uD2Zv3wTZ06ayem3\nvMaLC1Zp3CuRLBZtWPX33L0ucVwJjHX3U8ysN/Cku49owzjjUj641Gdfd2iqw2hXatxZXVHJsg2V\nbK+ppSg/l14lhXQvKSQ/J9bHhRJs39Og/MLUnFskw8RzxZEX5b3tEa/rGsVx9xVm1vge0m7lmtG7\nczE9S4pYu2U7KzdV8um6rXy2bitdOxbQrWMBXToUkNtWn50V7wQ/lThEEi5a4thgZicCnxM8xzEe\ndnbHTe+Zf7rvARc+nuoo2qUcoEe4fLBiE1Nmfcb0ectZu347xfm5jB3ag8OG9ODQsu4M2CWJE0lO\nPiF5xxZp56IljouBG4HewJXuviIsPxLQt7I0a8/enfnFyfvw0xOH8frH63j8neU8N38lT74bfJQG\n7FLMqMHdGD6glH37lbJXn84U5eemOGoRaU7MvaoyiXpVpS9356PVW/jvojW8umgNcz9bz5rNwV3R\nvBxjcPeO7Na9I7v26Mju3TsxsFsHencuondpUXxJpe6KQ1eeIjFJVBuHSMKZGWU9O1HWsxPnHzwY\nd2fFpkrmLd3IvKUbWLhyMx+v2cKLC1azvab+2Filxfn06lxIr85FdOlQQGlxHqXF+fWWDgV5FBfk\nMmx7NTkGa9dvpTg/l6Jwyc1R+5xIa6V94jCzjsDNBI31L7r7/SkOSRLIzOhTWkyf0mKO2bv3zvLq\nmlqWbajks3VbWbGpkpWbKlmxMfi5sqKKJeu2snHbDjZVVlPTyNPrDxYE45Wd9dsX6pXn5Rh5uUZe\nTk74M3idm2Pk51r4M1jPy80h14IYcwwMA2Pn65yc4KeF2xhgBjk7X4fvEZYZDbb9Yp/66xZRFnkO\ngPrvRZ6LhtsTcb7GyiPWaTT+6MfN2flesH1+rlGQlxMsubkRr4OfheF6UV4unYry6FSYR0Feinrc\nSaukJHGY2Z3AicAqd98novxY4C9ALsHT6TcA3wAecfdpZvYQoMTRDuTl5jCwWwcGdovegO7ubK6q\nZuO2HWzctoPKHTVs217LkGdKqHXnd6P3C8tq2Lq9hh01tVTXOtU1TnVt3esvympqnR01tcHPWqe2\n1nEcd6j1up/gXovXhGWAexBL3esvtvUwzi+2rXWH4L96+9Sdp+GxdpaH60Ss152nbvtmj1vvWB5x\nzNQoyMuhc5hE6pJJ1w4F9CgppEenwuBnSSE9S4oYsEsxXToUpC5Y2anZxGFm3wMmAxXA7cAI4Efu\n/kwrznsX8FeCBwrrzpML/I2g6+9S4A0zewzoD4R9K9GE2FKPmVFSlE9JUT79u0a88WrwBXNG+YDU\nBJaB3BtJSGGiCd7/cuKpdcJk5eyocbbX1LK9OmKpqaGqujZ4LyzbtqOGLVXVVFTuoKKqms2V1VRU\nVrM5LFu4ajOvfbSWjdt2fCnGzkV5DOrWkYHdOlDWoxN79enMsD6dGbBLMXpMoO3EcsVxkbv/xcyO\nIehleSFBImlx4nD3l81scIPiUcAid18MYGYPAicTJJH+BE+uR3vSfSIwEWDgwIEtDU2k3aq7pQWQ\nS+q/hKuqa1i7eTurK6pYsamSz9Zu5dN1W/h07VbeWbqRJ95ZvjOplRTmsVefzowc3JVRu+7CyEFd\n6VyUn9oKZLFYEkfdJ+h4YLK7v23JSe39gCUR60uBgwi6BP/VzE4gyqi87j4JmARBr6okxCcibagw\nL5e+XYrp26WY4Y28v3V7NQtWVDB/eQXzl2/inc83ctvLi/n7ix+RY1A+eBeO26c3x+7Tmz6l6f3o\nWaaJJXHMMbNngF2Ba8NpY5MxFVxjycjdfQvBVY6IyE4dCvIYMbArIwZ+cY9y6/Zq3vpsAzMWr+WZ\n91byi2nv84tp73NIWTfOHjWQrw3rrQb5BIglcYwH9gcWu/tWM9uF5HyRLwUib0j3B5bFcwAzGweM\nKysrS2RcIpIhOhTkcXBZdw4u687VXxvK4tWbmT5vOQ+9sYTLH5hLt44FnDayP2eNGsiu3TumOtyM\nFct8HIcAb7n7FjM7FzgA+Iu7f9qqEwdtHNPrelWFQ5l8SPBk+ufAG8A57v5evMfWA4CiBwAlUk2t\n88rC1Ux5/TOem7+KmlrnkLJufGdsGWN276aGdRI0rHqEvwNbzWw48EPgUyJ6Q7WEmU0BZgBDzWyp\nmY1392rgcoKJouYDU1uSNEREGsrNMcYO7cmt55Uz40dH8INjhrJw5WbOuX0Wp98yg9c/XpfqEDNK\nLFccb7r7AWb2M4JJnO6oK2ubEGMXcatqwsKFC1MdjqSSrjikGZU7apg6ewk3v/ARKzZVMm54X649\nbk/6dmldQ3rljhqWbdjGbj06JSjStpHoK44KM7sWOA94PHzeIi37ubn7NHefWFpamupQRCTNFeXn\n8q0xg3nh+2O54sg9eOa9FRz5h5e46fmFVO5o+SNjlz8wlyP+8FKrjpHuYkkcZwJVBM9zrCDoNvv7\npEYlItJGigtyueroITx31eGMHdqDPzz7IUf98SWeendFi2ayfG7+SgA+W7c10aGmjWZ7VYUTN90P\nHBjOz/G6u7eqjSNZ1KtK6lnxjublkJgNIGjQ3ThwB5+s3cK2qTV8UJzP7j06UZAbexfeBwvWAtDz\nHyVQnJ1DpDT72zCzM4DXgdOBM4BZZnZasgNrCd2qkp32PQ1675vqKCQDlRbns1//UgZ168Cmyh28\ns3QjG7Ztb37HBrZXJ+Nxt/QQS+P428DR7r4qXO8BPOfujT3MmRbUHVdEEmHBigouf+BNFq3ezKWH\n787/O3oI+VGuPrZX1zLkJ08C8P2vDeHyI/Zoq1BbLdGN4zl1SSO0Nsb92pyZjTOzSRs3bkx1KCKS\nBYb2LuGxyw/lzPIB3PziR5w1aSafb9jW5PZrt1TtfL1yU1WT22W6WBLAU2b2tJldYGYXEEwb+0Ry\nw2oZ3aoSkUQrLsjlhlP348azR7BgRQXH/+UVnnp3RaPbropIFis2VbZViG2u2cTh7j8AbgX2A4YD\nk9z9mmQHJiKSTk4a3pfp3z2Ugbt04JL75vCjf8xj6/bqetusqggSR9cO+azM4sQRtVdV+MzG0+5+\nFPDPtglJRCQ9De7ekX9cejB/eu5DbnnpI978bD1/P3cku4cP+y1cVQEEI/POW7ohlaEmVdQrDnev\nIRhuJCPu/aiNQ0SSrSAvh2uO3ZN7LzqINZu3c9JNr/LEO8sBmLdkI4O6dWDP3iWsrqiiuiY7e1bF\n0sZRCbxjZneY2Y11S7IDawm1cYhIWzl0j+48fsWhDOldwmX3v8kFk1/nhQWrGL1rN3p1LqLWYc3m\n+LvxZoJYhlV/PFxERCRCn9JiHpo4hr++sIiHZy9hzz6dueKoPXh/2SYgaCDvXVqU4igTr8nEET6v\n0cPd725Qvg+wMtmBiYhkgoK8HK46eghXHT1kZ9nWqqDR/MOVFew/oEuqQkuaaLeqbiKYY7yhfsBf\nkhOOiEjm271HJ7p1LOClD1c3uc1Nzy/kew/ObcOoEida4tjX3V9qWOjuTxN0zRURkUbk5Bgn79+P\np99d0WS33D88+yH/fmsZtbX1R+/YUVPLjjRvVI+WOKINnZ6Ww6qrV5WIpIvzDx4EwA1PfhB1u4YP\nCh5w/bNaqhXLAAASSklEQVSM+OWzSYsrEaIljoVmdnzDQjM7DlicvJBaTr2qRCRdDOrWkcvG7s6/\n5n6+s7tunc1VXzw4+MnaLQA7rzwqKqvrvZ+OovWq+n/A9HB03DlhWTkwBjgx2YGJiGS67xxRxiuL\n1nD11LfpU1rEiIFdAfg0TBbB662s2LiUq6a+zQfXH5uqUOPS5BWHu38I7Au8BAwOl5eA/cL3REQk\nisK8XG49byQ9OxfyrTte5+0lwdPkH6+pnzj+/Fww1fXqiswYGLG5J8er3H2yu18dLne6e/YOwCIi\nkmA9S4qYMmE0XTrmc+4ds5j72Xo+XFGBGfTrUsyna7dQE96m2rB1R4qjjU0sDwCKiEgr9O1SzJQJ\nozn7tpmcOWkmeTnG8P5d6Nohn0/XbqUgL/gbft3WzHjSPC3n1Wgp9aoSkXTVv2sHHr3sEI4e1ose\nJYX8zwl7MahbRz5du2Xn1LQbMiRxNHvFYWYdgW3uXhuu5wBF7p52M7G7+zRgWnl5+YRUxyIi0lC3\nToX87ZwDdq4vWFHBlu01LFkffJ2u35IZiSOWK47ngQ4R6x2A55ITjohI+3H0sF6YwdbtNQCsj2jj\nGPyj9B0iMJbEUeTum+tWwtcdomwvIiIx6NW5iK8N67VzveGtKndvuEtaiCVxbDGznddWZjYSaHrS\nXRERidn1J+/DBQcPJsfqX3EAO3tbRVqybivn3TGL/X/5DP/5IDXjzcbSq+pK4GEzWxau9wHOTF5I\nIiLtR8/ORfz8pL35aPXmL80auKPGycutv/1XfvfCztffvns2i39zQluEWU8sc46/AewJXApcBuzl\n7nOi7yUiIvE4bWR/Pllbv8/RL6e/n6JoomsycZjZEeHPbwDjgCHAHsC4sExERBLkxP36MqxP53pl\n/5q7NEXRRBftiuPw8Oe4RhaNVSUikkC5Ocafz9q/XlnljvQcXr3JNg53vy78eWHbhdM6ZjYOGFdW\nVpbqUERE4jakVwlH7tmT5z9YBYBZ/fcrd9TUW09Vn6tm2zjMrJuZ3Whmb5rZHDP7i5l1a4vg4qVh\n1UUk0932rfKdryOnnf18wzb2/OlT9bZNVW/dWLrjPgisBk4FTgtfP5TMoERE2qucHOPdXxzDKfv3\n5e0lG1iwogKATyJG1E21WBLHLu5+vbt/HC6/ArJv9nURkTTRqTCP68btTafCPH7/dPQZBFMhlsTx\ngpmdZWY54XIGkL7PwouIZIGuHQu46NBdeW7+Kpas21rvttQFBw8GYN9+pfz8sfeY/ck6Rv3vc202\n1lUsieNi4AFge7g8CFxlZhVmtimZwYmItGcn7NsHgBkfra1X3qe0iKG9Snjn843c9donnHbLDFZV\nVDFz8drGDpNwzT457u4lbRGIiIjUV9azEwV5OfzwH/Pqlffv2oE9enViwcqKlMQV00ROZnYScFi4\n+qK7T09eSCIiAmBm1DYyXtVefUpYvnEb0+ctr1feVp2sYumOewPwPeD9cPleWCYiIklWHSaOq48e\nsrNs1+4dGT7gy32UcuxLRUkRyxXH8cD+ERM53Q3MBX6UzMBERAQOLevOq4vW8O2v7Mag7h0pH9QV\nM6NjwZe/vi+5700APrkhuQMfxjrneBdgXfhaT9eJiLSRP5wxnI9Wb6a4IJeThvfdWd6xMDfKXskV\nS+L4DTDXzF4AjKCt49qkRiUiIkAw2VOvzkVfKu/eqTAF0QRiGVZ9CjAa+Ge4jHH3B5MdmIiINK1j\nYR6Xjt09JeeOpXH868BWd3/M3f8NVJrZKckPbef5dzOzO8zskbY6p4hIJrjm2D05du/eXypvrCdW\nIsXyAOB17r6xbsXdNwDXxXJwM7vTzFaZ2bsNyo81swVmtsjMojayu/tidx8fy/lERNqbY/bp9aWy\n5z9YxX8XrUnaOWNJHI1tE2uj+l3AsZEFZpYL/A04DhgGnG1mw8xsXzOb3mDpGeN5RETapZOG92O3\nHh3rlU24ZzbfvH0Ws5L0JHksiWO2mf3RzHYPbxv9CYhp6lh3f5kvemPVGQUsCq8k6oYwOdnd33H3\nExssq2KtiJlNNLPZZjZ79erVse4mIpLRcnOM/1w9ttH3VlZUJeWcsSSO7xKMUfUQ8DBQCXynFefs\nByyJWF8aljUqnA/kFmCEmTXZm8vdJ7l7ubuX9+jRoxXhiYhknhe/P/ZLZVdMmcvGbTsSfq5Yxqra\nQviwX3ibqWNY1lKNPdvYZEuOu68FLmnF+UREst7g7h0bLb/s/jnccf6BFOUn7rmPWHpVPWBmnc2s\nI/AesMDMftCKcy4FBkSs9weWteJ4O5nZODObtHHjxuY3FhHJMo9fceiXyv67aC2H3PAf3J2bnl/I\ne8ta//0Yy62qYe6+CTgFeAIYCJzXinO+AexhZruaWQFwFvBYK463k6aOFZH2bO++jX/3rd2ynW/d\n+Tp/ePZDTrjxVbyVc87GkjjyzSyfIHH82913EOMgjGY2BZgBDDWzpWY23t2rgcuBp4H5wFR3f69l\n4X/pfLriEJF27Z6LRnHCvn146sqv1Ct/ZeEX3XMn3DO7VcnDmtvZzK4ArgHeBk4guOK4z92/EnXH\nFCovL/fZs2enOgwRkZSp3FHDnj99Kuo244b35aazRwBgZnPcvTyWYzebOBrdySwvvHJIS0ocIiJQ\nXVOLmfHJ2i0c+YeXADijvD9TZy/duc3bP/sapR3yE5s4zKyU4EnxuomcXgJ+Gfk0ebpR4hARqe+/\ni9awYEUFFx26KzW1zi0vfcTvn14AwE9O2IsJh+0ec+KIpY3jTqACOCNcNgGTWxh7UqmNQ0SkcYeU\ndeeiQ3cFgocGLz38iwESf/X4/LiOFUvi2N3drwuf9F7s7r8AdovrLG1EvapERGKTk2N8cP2x/O7U\n/eLfN4ZttpnZzs7BZnYIsC3uM4mISFopys/ljAMH8MC3D4prv1gGK7wEuCds6wBYD5wfZ3xtwszG\nAePKyspSHYqISMYwi2+y8qhXHGaWAwx19+HAfsB+7j7C3ee1PMTk0a0qEZH45cSXN6InDnevJXhY\nD3ffFD5BLiIiWSShVxyhZ83s+2Y2wMx2qVtaFp6IiKSbOPNGTG0cF4U/I4dSd9KwZ5XaOERE4pfQ\nW1UA7r5rI0vaJQ1QG4eISMsk+FaVmX3HzLpErHc1s8taEJmIiKShhF9xABPcfUPdiruvBybEdxoR\nEUlXyWgcz7GIo4azABbEGZeIiKSpisr4ppeNJXE8DUw1syPN7AhgChB9rN4U0VhVIiLxG7VrfB1l\nYxkdNwe4GDiSoAXlGeB2d69pYYxJp9FxRUTiE8+w6s12xw0fAvx7uIiISDvXbOIwsz2A3wDDgKK6\n8nTtkisiIskVSxvHZIKrjWrgq8A9wL3JDEpERNJXLImj2N2fJ2gP+dTdfw4ckdywREQkXcUy5Ehl\n2EC+0MwuBz4HeiY3LBERSVexXHFcCXQArgBGAueRxvNxqDuuiEhyNdsdNxOpO66ISHwS0h3XzB6L\ntqO7nxRvYCIikvmitXGMAZYQPCk+i3iHTxQRkawULXH0Bo4GzgbOAR4Hprj7e20RmIiIpKcmG8fd\nvcbdn3L384HRwCLgRTP7bptFJyIiaSdqd1wzKwROILjqGAzcCPwz+WGJiEi6itY4fjewD/Ak8At3\nf7fNohIRkbQV7YrjPGALMAS4InJKDsDdvXOSYxMRkTTUZOJw91geDkwrZjYOGFdWVpbqUEREslbG\nJYdo3H2au08sLS1NdSgiIlkrqxKHiIgknxKHiIjERYlDRETiosQhIiJxUeIQEZG4KHGIiEhclDhE\nRCQuShwiIhIXJQ4REYmLEoeIiMRFiUNEROKS9onDzE4xs9vM7N9m9rVUxyMi0t4lNXGY2Z1mtsrM\n3m1QfqyZLTCzRWb2o2jHcPdH3X0CcAFwZhLDFRGRGESdATAB7gL+CtxTV2BmucDfCOYzXwq8YWaP\nAbnAbxrsf5G7rwpf/yTcT0REUiipicPdXzazwQ2KRwGL3H0xgJk9CJzs7r8BTmx4DAtmkLoBeNLd\n32zqXGY2EZgIMHDgwITELyIiX5aKNo5+wJKI9aVhWVO+CxwFnGZmlzS1kbtPcvdydy/v0aNHYiIV\nEZEvSfatqsZYI2Xe1MbufiNwY/LCERGReKTiimMpMCBivT+wLBEHNrNxZjZp48aNiTiciIg0IhWJ\n4w1gDzPb1cwKgLOAxxJxYE0dKyKSfMnujjsFmAEMNbOlZjbe3auBy4GngfnAVHd/L0Hn0xWHiEiS\nmXuTzQsZq7y83GfPnp3qMEREMoaZzXH38li2Tfsnx0VEJL2koldV0pjZOGAcUGlmCbn9lWa6A2tS\nHUSSZGvdVK/Mk611a65eg2I9UFbeqjKz2bFecmWSbK0XZG/dVK/Mk611S2S9dKtKRETiosQhIiJx\nydbEMSnVASRJttYLsrduqlfmyda6JaxeWdnGISIiyZOtVxwiIpIkShwiIhIXJQ4REYlLu0ocZjbW\nzF4xs1vMbGyq40kkM9srrNcjZnZpquNJFDPbzczuMLNHUh1LImRbfepk6+cPsvd7w8y+EtbpdjN7\nLZ59MyZxJGL+coJ5PzYDRQTDu6eFBM3NPt/dLwHOANLi4aUE1Wuxu49PbqStE089M6E+deKsV9p9\n/qKJ87OZlt8bjYnz3+yV8N9sOnB3XCdy94xYgMOAA4B3I8pygY+A3YAC4G1gGLBv+MuIXHoCOeF+\nvYD7U12nRNYt3Ock4DXgnFTXKZH1Cvd7JNX1SUQ9M6E+La1Xun3+ElW3dP3eSMS/Wfj+VKBzPOfJ\nmLGqPAHzl0dYDxQmI86WSFTd3P0x4DEzexx4IHkRxybB/2ZpK556Au+3bXQtF2+90u3zF02cn826\nf7O0+t5oTLz/ZmY2ENjo7pviOU/GJI4mNDZ/+UFNbWxm3wCOAboAf01uaK0Wb93GAt8g+GA/kdTI\nWifeenUD/hcYYWbXhgkmEzRazwyuT52m6jWWzPj8RdNU3TLpe6Mx0f6fGw9MjveAmZ444p2//J/A\nP5MXTkLFW7cXgReTFUwCxVuvtcAlyQsnaRqtZwbXp05T9XqRzPj8RdNU3TLpe6MxTf4/5+7XteSA\nGdM43oSkzV+eBrK1btlar4aytZ7ZWi/I3rolvF6ZnjiSNn95GsjWumVrvRrK1npma70ge+uW+Hql\nuhdAHL0FpgDLgR0EGXR8WH488CFBr4H/SXWcqlv216u91DNb65XNdWuremmQQxERiUum36oSEZE2\npsQhIiJxUeIQEZG4KHGIiEhclDhERCQuShwiIhIXJQ5p18ysxszeiliaG5q/TZjZJ2b2jpk1OUS5\nmV1gZlMalHU3s9VmVmhm95vZOjM7LfkRS3uS6WNVibTWNnffP5EHNLM8d69OwKG+6u5rorz/T+D/\nzKyDu28Ny04DHnP3KuCbZnZXAuIQqUdXHCKNCP/i/4WZvRn+5b9nWN4xnCznDTOba2Ynh+UXmNnD\nZjYNeMbMcszsZjN7z8ymm9kTZnaamR1pZv+KOM/RZtbsAHpmNtLMXjKzOWb2tJn18WAo7JeBcRGb\nnkXw9LBI0ihxSHtX3OBW1ZkR761x9wOAvwPfD8v+B/iPux8IfBX4vZl1DN8bA5zv7kcQDDE+mGCC\nqm+H7wH8B9jLzHqE6xfSzLDWZpYP3ASc5u4jgTsJhmaHIEmcFW7XFxgCvBDn70AkLrpVJe1dtFtV\ndVcCcwgSAcDXgJPMrC6RFAEDw9fPuvu68PWhwMPuXgusMLMXIBij28zuBc41s8kECeVbzcQ4FNgH\neNbMIJjRbXn43nTgZjPrTDBt6yPuXtNcpUVaQ4lDpGlV4c8avvh/xYBT3X1B5IZmdhCwJbIoynEn\nA9OASoLk0lx7iAHvufuYhm+4+zYzewr4OsGVx/9r5lgiraZbVSLxeRr4roV/+pvZiCa2exU4NWzr\n6AWMrXvD3ZcRzIfwE+CuGM65AOhhZmPCc+ab2d4R708BriKYE3tmXLURaQElDmnvGrZx3NDM9tcD\n+cA8M3s3XG/MPwiGtX4XuBWYBWyMeP9+YIl/MZ91k9x9O0Fvqd+a2dvAW8DBEZs8A/QFHnINdy1t\nQMOqiySJmXVy983hPOOvA4e4+4rwvb8Cc939jib2/QQob6Y7biwx3AVMd/dHWnMckUi64hBJnulm\n9hbwCnB9RNKYA+wH3Bdl39XA89EeAGyOmd0PHE7QliKSMLriEBGRuOiKQ0RE4qLEISIicVHiEBGR\nuChxiIhIXJQ4REQkLkocIiISl/8PMcPiun1YM38AAAAASUVORK5CYII=\n", + "image/png": "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\n", "text/plain": [ - "" + "" ] }, "metadata": {}, @@ -991,7 +942,6 @@ "cell_type": "code", "execution_count": 32, "metadata": { - "collapsed": false, "scrolled": true }, "outputs": [ @@ -1025,11 +975,11 @@ " %%%%%%%%%%%\n", "\n", " | The OpenMC Monte Carlo Code\n", - " Copyright | 2011-2017 Massachusetts Institute of Technology\n", + " Copyright | 2011-2018 Massachusetts Institute of Technology\n", " License | http://openmc.readthedocs.io/en/latest/license.html\n", - " Version | 0.8.0\n", - " Git SHA1 | 4b01fd311461f1350989cb84ec18fe2cbaa8fa9f\n", - " Date/Time | 2017-03-10 17:31:49\n", + " Version | 0.10.0\n", + " Git SHA1 | 6c2d82a4d7dfe10312329d5969568fc03a698416\n", + " Date/Time | 2018-04-22 15:04:03\n", " OpenMP Threads | 8\n", "\n", "\n", @@ -1038,23 +988,13 @@ "\n", " ============================> RESULTS <============================\n", "\n", - " k-effective (Collision) = 1.16235 +/- 0.00111\n", - " k-effective (Track-length) = 1.16345 +/- 0.00134\n", - " k-effective (Absorption) = 1.16397 +/- 0.00058\n", - " Combined k-effective = 1.16388 +/- 0.00058\n", + " k-effective (Collision) = 1.16541 +/- 0.00086\n", + " k-effective (Track-length) = 1.16590 +/- 0.00096\n", + " k-effective (Absorption) = 1.16469 +/- 0.00046\n", + " Combined k-effective = 1.16480 +/- 0.00045\n", " Leakage Fraction = 0.00000 +/- 0.00000\n", "\n" ] - }, - { - "data": { - "text/plain": [ - "0" - ] - }, - "execution_count": 32, - "metadata": {}, - "output_type": "execute_result" } ], "source": [ @@ -1075,9 +1015,7 @@ { "cell_type": "code", "execution_count": 33, - "metadata": { - "collapsed": false - }, + "metadata": {}, "outputs": [], "source": [ "# Move the StatePoint File\n", @@ -1108,9 +1046,7 @@ { "cell_type": "code", "execution_count": 34, - "metadata": { - "collapsed": false - }, + "metadata": {}, "outputs": [], "source": [ "ce_keff = sp.k_combined" @@ -1126,26 +1062,24 @@ { "cell_type": "code", "execution_count": 35, - "metadata": { - "collapsed": false - }, + "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ - "Continuous-Energy keff = 1.165379\n", - "Multi-Group keff = 1.163885\n", - "bias [pcm]: 149.4\n" + "Continuous-Energy keff = 1.164600+/-0.000677\n", + "Multi-Group keff = 1.164805+/-0.000448\n", + "bias [pcm]: -20.4\n" ] } ], "source": [ - "bias = 1.0E5 * (ce_keff[0] - mg_keff[0])\n", + "bias = 1.0E5 * (ce_keff - mg_keff)\n", "\n", - "print('Continuous-Energy keff = {0:1.6f}'.format(ce_keff[0]))\n", - "print('Multi-Group keff = {0:1.6f}'.format(mg_keff[0]))\n", - "print('bias [pcm]: {0:1.1f}'.format(bias))" + "print('Continuous-Energy keff = {0:1.6f}'.format(ce_keff))\n", + "print('Multi-Group keff = {0:1.6f}'.format(mg_keff))\n", + "print('bias [pcm]: {0:1.1f}'.format(bias.nominal_value))" ] }, { @@ -1174,9 +1108,7 @@ { "cell_type": "code", "execution_count": 36, - "metadata": { - "collapsed": false - }, + "metadata": {}, "outputs": [], "source": [ "# Get the OpenMC fission rate mesh tally data\n", @@ -1200,9 +1132,7 @@ { "cell_type": "code", "execution_count": 37, - "metadata": { - "collapsed": false - }, + "metadata": {}, "outputs": [], "source": [ "# Get the OpenMC fission rate mesh tally data\n", @@ -1226,14 +1156,12 @@ { "cell_type": "code", "execution_count": 38, - "metadata": { - "collapsed": false - }, + "metadata": {}, "outputs": [ { "data": { "text/plain": [ - "" + "" ] }, "execution_count": 38, @@ -1242,9 +1170,9 @@ }, { "data": { - "image/png": "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\n", + "image/png": "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\n", "text/plain": [ - "" + "" ] }, "metadata": {}, @@ -1304,9 +1232,7 @@ { "cell_type": "code", "execution_count": 39, - "metadata": { - "collapsed": true - }, + "metadata": {}, "outputs": [], "source": [ "# Set the maximum scattering order to 0 (i.e., isotropic scattering)\n", @@ -1326,9 +1252,7 @@ { "cell_type": "code", "execution_count": 40, - "metadata": { - "collapsed": false - }, + "metadata": {}, "outputs": [ { "name": "stdout", @@ -1360,11 +1284,11 @@ " %%%%%%%%%%%\n", "\n", " | The OpenMC Monte Carlo Code\n", - " Copyright | 2011-2017 Massachusetts Institute of Technology\n", + " Copyright | 2011-2018 Massachusetts Institute of Technology\n", " License | http://openmc.readthedocs.io/en/latest/license.html\n", - " Version | 0.8.0\n", - " Git SHA1 | 4b01fd311461f1350989cb84ec18fe2cbaa8fa9f\n", - " Date/Time | 2017-03-10 17:32:18\n", + " Version | 0.10.0\n", + " Git SHA1 | 6c2d82a4d7dfe10312329d5969568fc03a698416\n", + " Date/Time | 2018-04-22 15:04:39\n", " OpenMP Threads | 8\n", "\n", "\n", @@ -1373,23 +1297,13 @@ "\n", " ============================> RESULTS <============================\n", "\n", - " k-effective (Collision) = 1.16104 +/- 0.00109\n", - " k-effective (Track-length) = 1.16004 +/- 0.00125\n", - " k-effective (Absorption) = 1.16297 +/- 0.00061\n", - " Combined k-effective = 1.16273 +/- 0.00061\n", + " k-effective (Collision) = 1.16379 +/- 0.00090\n", + " k-effective (Track-length) = 1.16469 +/- 0.00101\n", + " k-effective (Absorption) = 1.16315 +/- 0.00052\n", + " Combined k-effective = 1.16335 +/- 0.00050\n", " Leakage Fraction = 0.00000 +/- 0.00000\n", "\n" ] - }, - { - "data": { - "text/plain": [ - "0" - ] - }, - "execution_count": 40, - "metadata": {}, - "output_type": "execute_result" } ], "source": [ @@ -1407,16 +1321,14 @@ { "cell_type": "code", "execution_count": 41, - "metadata": { - "collapsed": false - }, + "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ - "P3 bias [pcm]: 149.4\n", - "P0 bias [pcm]: 265.3\n" + "P3 bias [pcm]: -20.4\n", + "P0 bias [pcm]: 125.1\n" ] } ], @@ -1434,10 +1346,10 @@ "# Get keff\n", "mg_p0_keff = mgsp_p0.k_combined\n", "\n", - "bias_p0 = 1.0E5 * (ce_keff[0] - mg_p0_keff[0])\n", + "bias_p0 = 1.0E5 * (ce_keff - mg_p0_keff)\n", "\n", - "print('P3 bias [pcm]: {0:1.1f}'.format(bias))\n", - "print('P0 bias [pcm]: {0:1.1f}'.format(bias_p0))" + "print('P3 bias [pcm]: {0:1.1f}'.format(bias.nominal_value))\n", + "print('P0 bias [pcm]: {0:1.1f}'.format(bias_p0.nominal_value))" ] }, { @@ -1453,9 +1365,7 @@ { "cell_type": "code", "execution_count": 42, - "metadata": { - "collapsed": false - }, + "metadata": {}, "outputs": [], "source": [ "# Convert the zircaloy and fuel data to P0 scattering\n", @@ -1474,9 +1384,7 @@ { "cell_type": "code", "execution_count": 43, - "metadata": { - "collapsed": true - }, + "metadata": {}, "outputs": [], "source": [ "# Convert the formats as discussed\n", @@ -1501,9 +1409,7 @@ { "cell_type": "code", "execution_count": 44, - "metadata": { - "collapsed": false - }, + "metadata": {}, "outputs": [ { "name": "stdout", @@ -1535,11 +1441,11 @@ " %%%%%%%%%%%\n", "\n", " | The OpenMC Monte Carlo Code\n", - " Copyright | 2011-2017 Massachusetts Institute of Technology\n", + " Copyright | 2011-2018 Massachusetts Institute of Technology\n", " License | http://openmc.readthedocs.io/en/latest/license.html\n", - " Version | 0.8.0\n", - " Git SHA1 | 4b01fd311461f1350989cb84ec18fe2cbaa8fa9f\n", - " Date/Time | 2017-03-10 17:32:48\n", + " Version | 0.10.0\n", + " Git SHA1 | 6c2d82a4d7dfe10312329d5969568fc03a698416\n", + " Date/Time | 2018-04-22 15:05:16\n", " OpenMP Threads | 8\n", "\n", "\n", @@ -1548,23 +1454,13 @@ "\n", " ============================> RESULTS <============================\n", "\n", - " k-effective (Collision) = 1.16348 +/- 0.00117\n", - " k-effective (Track-length) = 1.16263 +/- 0.00133\n", - " k-effective (Absorption) = 1.16485 +/- 0.00063\n", - " Combined k-effective = 1.16459 +/- 0.00061\n", + " k-effective (Collision) = 1.16471 +/- 0.00093\n", + " k-effective (Track-length) = 1.16412 +/- 0.00106\n", + " k-effective (Absorption) = 1.16449 +/- 0.00050\n", + " Combined k-effective = 1.16441 +/- 0.00049\n", " Leakage Fraction = 0.00000 +/- 0.00000\n", "\n" ] - }, - { - "data": { - "text/plain": [ - "0" - ] - }, - "execution_count": 44, - "metadata": {}, - "output_type": "execute_result" } ], "source": [ @@ -1587,16 +1483,14 @@ { "cell_type": "code", "execution_count": 45, - "metadata": { - "collapsed": false - }, + "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ - "P3 bias [pcm]: 149.4\n", - "Mixed Scattering bias [pcm]: 79.0\n" + "P3 bias [pcm]: -20.4\n", + "Mixed Scattering bias [pcm]: 19.5\n" ] } ], @@ -1605,16 +1499,17 @@ "mgsp_mixed = openmc.StatePoint('./statepoint.' + str(batches) + '.h5')\n", "\n", "mg_mixed_keff = mgsp_mixed.k_combined\n", - "bias_mixed = 1.0E5 * (ce_keff[0] - mg_mixed_keff[0])\n", + "bias_mixed = 1.0E5 * (ce_keff - mg_mixed_keff)\n", "\n", - "print('P3 bias [pcm]: {0:1.1f}'.format(bias))\n", - "print('Mixed Scattering bias [pcm]: {0:1.1f}'.format(bias_mixed))" + "print('P3 bias [pcm]: {0:1.1f}'.format(bias.nominal_value))\n", + "print('Mixed Scattering bias [pcm]: {0:1.1f}'.format(bias_mixed.nominal_value))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ + "\n", "Our tests in this section showed the flexibility of data formatting within OpenMC's multi-group mode: every material can be represented with its own format with the approximations that make the most sense. Now, as you'll see above, the runtimes from our P3, P0, and mixed cases are not significantly different and therefore this might not be a useful strategy for multi-group Monte Carlo. However, this capability provides a useful benchmark for the accuracy hit one may expect due to these scattering approximations before implementing this generality in a deterministic solver where the runtime savings are more significant.\n", "\n", "**NOTE**: The biases obtained above with P3, P0, and mixed representations do not necessarily reflect the inherent accuracies of the options. These cases were *not* run with a sufficient number of histories to truly differentiate methods improvement from statistical noise." @@ -1623,9 +1518,9 @@ ], "metadata": { "kernelspec": { - "display_name": "Python 3", + "display_name": "openmc", "language": "python", - "name": "python3" + "name": "openmc" }, "language_info": { "codemirror_mode": { @@ -1637,9 +1532,9 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.6.0" + "version": "3.6.5" } }, "nbformat": 4, - "nbformat_minor": 0 + "nbformat_minor": 1 } diff --git a/examples/jupyter/mg-mode-part-iii.ipynb b/examples/jupyter/mg-mode-part-iii.ipynb index c36ecd54af..2f37070c14 100644 --- a/examples/jupyter/mg-mode-part-iii.ipynb +++ b/examples/jupyter/mg-mode-part-iii.ipynb @@ -23,9 +23,7 @@ { "cell_type": "code", "execution_count": 1, - "metadata": { - "collapsed": false - }, + "metadata": {}, "outputs": [], "source": [ "import os\n", @@ -48,9 +46,7 @@ { "cell_type": "code", "execution_count": 2, - "metadata": { - "collapsed": true - }, + "metadata": {}, "outputs": [], "source": [ "# Instantiate some elements\n", @@ -74,9 +70,7 @@ { "cell_type": "code", "execution_count": 3, - "metadata": { - "collapsed": false - }, + "metadata": {}, "outputs": [], "source": [ "materials = {}\n", @@ -127,9 +121,7 @@ { "cell_type": "code", "execution_count": 4, - "metadata": { - "collapsed": true - }, + "metadata": {}, "outputs": [], "source": [ "# Instantiate a Materials object\n", @@ -156,9 +148,7 @@ { "cell_type": "code", "execution_count": 5, - "metadata": { - "collapsed": false - }, + "metadata": {}, "outputs": [], "source": [ "# Set constants for the problem and assembly dimensions\n", @@ -207,9 +197,7 @@ { "cell_type": "code", "execution_count": 6, - "metadata": { - "collapsed": true - }, + "metadata": {}, "outputs": [], "source": [ "# Set regions for geometry building\n", @@ -253,9 +241,7 @@ { "cell_type": "code", "execution_count": 7, - "metadata": { - "collapsed": false - }, + "metadata": {}, "outputs": [], "source": [ "universes = {}\n", @@ -295,9 +281,7 @@ { "cell_type": "code", "execution_count": 8, - "metadata": { - "collapsed": true - }, + "metadata": {}, "outputs": [], "source": [ "# Create fuel assembly Lattice\n", @@ -336,9 +320,7 @@ { "cell_type": "code", "execution_count": 9, - "metadata": { - "collapsed": true - }, + "metadata": {}, "outputs": [], "source": [ "# The top portion of the blade, poisoned with B4C\n", @@ -372,9 +354,7 @@ { "cell_type": "code", "execution_count": 10, - "metadata": { - "collapsed": false - }, + "metadata": {}, "outputs": [], "source": [ "# Create root Universe\n", @@ -396,15 +376,23 @@ { "cell_type": "code", "execution_count": 11, - "metadata": { - "collapsed": false - }, + "metadata": {}, "outputs": [ { "data": { - "image/png": "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\n", "text/plain": [ - "" + "" + ] + }, + "execution_count": 11, + "metadata": {}, + "output_type": "execute_result" + }, + { + "data": { + "image/png": "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\n", + "text/plain": [ + "" ] }, "metadata": {}, @@ -435,9 +423,7 @@ { "cell_type": "code", "execution_count": 12, - "metadata": { - "collapsed": false - }, + "metadata": {}, "outputs": [], "source": [ "# Create Geometry and set root universe\n", @@ -459,9 +445,7 @@ { "cell_type": "code", "execution_count": 13, - "metadata": { - "collapsed": true - }, + "metadata": {}, "outputs": [], "source": [ "# OpenMC simulation parameters\n", @@ -498,9 +482,7 @@ { "cell_type": "code", "execution_count": 14, - "metadata": { - "collapsed": false - }, + "metadata": {}, "outputs": [], "source": [ "# Instantiate a 2-group EnergyGroups object\n", @@ -518,9 +500,7 @@ { "cell_type": "code", "execution_count": 15, - "metadata": { - "collapsed": true - }, + "metadata": {}, "outputs": [], "source": [ "# Initialize a 2-group Isotropic MGXS Library for OpenMC\n", @@ -541,9 +521,7 @@ { "cell_type": "code", "execution_count": 16, - "metadata": { - "collapsed": true - }, + "metadata": {}, "outputs": [], "source": [ "# Specify multi-group cross section types to compute\n", @@ -563,9 +541,7 @@ { "cell_type": "code", "execution_count": 17, - "metadata": { - "collapsed": false - }, + "metadata": {}, "outputs": [], "source": [ "# Instantiate a tally Mesh\n", @@ -598,9 +574,7 @@ { "cell_type": "code", "execution_count": 18, - "metadata": { - "collapsed": false - }, + "metadata": {}, "outputs": [], "source": [ "# Set the scattering format to histogram and then define the number of bins\n", @@ -630,9 +604,7 @@ { "cell_type": "code", "execution_count": 19, - "metadata": { - "collapsed": true - }, + "metadata": {}, "outputs": [], "source": [ "# Let's repeat all of the above for an angular MGXS library so we can gather\n", @@ -662,9 +634,7 @@ { "cell_type": "code", "execution_count": 20, - "metadata": { - "collapsed": false - }, + "metadata": {}, "outputs": [], "source": [ "# Check the libraries - if no errors are raised, then the library is satisfactory.\n", @@ -684,15 +654,13 @@ { "cell_type": "code", "execution_count": 21, - "metadata": { - "collapsed": false - }, + "metadata": {}, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ - "/home/romano/openmc/openmc/mgxs/mgxs.py:4106: UserWarning: The legendre order will be ignored since the scatter format is set to histogram\n", + "/home/nelsonag/git/openmc/openmc/mgxs/mgxs.py:4116: UserWarning: The legendre order will be ignored since the scatter format is set to histogram\n", " warnings.warn(msg)\n" ] } @@ -713,9 +681,7 @@ { "cell_type": "code", "execution_count": 22, - "metadata": { - "collapsed": true - }, + "metadata": {}, "outputs": [], "source": [ "# Create a \"tallies.xml\" file for the MGXS Library\n", @@ -734,27 +700,25 @@ { "cell_type": "code", "execution_count": 23, - "metadata": { - "collapsed": false - }, + "metadata": {}, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ - "/home/romano/openmc/openmc/mixin.py:61: IDWarning: Another MeshFilter instance already exists with id=1.\n", + "/home/nelsonag/git/openmc/openmc/mixin.py:71: IDWarning: Another Filter instance already exists with id=1.\n", " warn(msg, IDWarning)\n", - "/home/romano/openmc/openmc/mixin.py:61: IDWarning: Another EnergyFilter instance already exists with id=2.\n", + "/home/nelsonag/git/openmc/openmc/mixin.py:71: IDWarning: Another Filter instance already exists with id=2.\n", " warn(msg, IDWarning)\n", - "/home/romano/openmc/openmc/mixin.py:61: IDWarning: Another EnergyoutFilter instance already exists with id=11.\n", + "/home/nelsonag/git/openmc/openmc/mixin.py:71: IDWarning: Another Filter instance already exists with id=11.\n", " warn(msg, IDWarning)\n", - "/home/romano/openmc/openmc/mixin.py:61: IDWarning: Another PolarFilter instance already exists with id=21.\n", + "/home/nelsonag/git/openmc/openmc/mixin.py:71: IDWarning: Another Filter instance already exists with id=21.\n", " warn(msg, IDWarning)\n", - "/home/romano/openmc/openmc/mixin.py:61: IDWarning: Another AzimuthalFilter instance already exists with id=22.\n", + "/home/nelsonag/git/openmc/openmc/mixin.py:71: IDWarning: Another Filter instance already exists with id=22.\n", " warn(msg, IDWarning)\n", - "/home/romano/openmc/openmc/mixin.py:61: IDWarning: Another MuFilter instance already exists with id=12.\n", + "/home/nelsonag/git/openmc/openmc/mixin.py:71: IDWarning: Another Filter instance already exists with id=12.\n", " warn(msg, IDWarning)\n", - "/home/romano/openmc/openmc/mixin.py:61: IDWarning: Another EnergyFilter instance already exists with id=18.\n", + "/home/nelsonag/git/openmc/openmc/mixin.py:71: IDWarning: Another Filter instance already exists with id=18.\n", " warn(msg, IDWarning)\n" ] } @@ -787,9 +751,7 @@ { "cell_type": "code", "execution_count": 24, - "metadata": { - "collapsed": false - }, + "metadata": {}, "outputs": [ { "name": "stdout", @@ -821,12 +783,12 @@ " %%%%%%%%%%%\n", "\n", " | The OpenMC Monte Carlo Code\n", - " Copyright | 2011-2017 Massachusetts Institute of Technology\n", + " Copyright | 2011-2018 Massachusetts Institute of Technology\n", " License | http://openmc.readthedocs.io/en/latest/license.html\n", - " Version | 0.9.0\n", - " Git SHA1 | da61fb4a55e1feaa127799ad9293a766161fbb3e\n", - " Date/Time | 2017-12-11 16:57:27\n", - " OpenMP Threads | 4\n", + " Version | 0.10.0\n", + " Git SHA1 | 6c2d82a4d7dfe10312329d5969568fc03a698416\n", + " Date/Time | 2018-04-24 19:15:17\n", + " OpenMP Threads | 8\n", "\n", "\n", " ====================> K EIGENVALUE SIMULATION <====================\n", @@ -841,16 +803,6 @@ " Leakage Fraction = 0.00000 +/- 0.00000\n", "\n" ] - }, - { - "data": { - "text/plain": [ - "0" - ] - }, - "execution_count": 24, - "metadata": {}, - "output_type": "execute_result" } ], "source": [ @@ -868,9 +820,7 @@ { "cell_type": "code", "execution_count": 25, - "metadata": { - "collapsed": false - }, + "metadata": {}, "outputs": [], "source": [ "# Move the StatePoint File\n", @@ -893,9 +843,7 @@ { "cell_type": "code", "execution_count": 26, - "metadata": { - "collapsed": false - }, + "metadata": {}, "outputs": [], "source": [ "# Load the statepoint file, but not the summary file, as it is a different filename than expected.\n", @@ -912,9 +860,7 @@ { "cell_type": "code", "execution_count": 27, - "metadata": { - "collapsed": false - }, + "metadata": {}, "outputs": [], "source": [ "su = openmc.Summary(ce_sumfile)\n", @@ -931,9 +877,7 @@ { "cell_type": "code", "execution_count": 28, - "metadata": { - "collapsed": false - }, + "metadata": {}, "outputs": [], "source": [ "# Initialize MGXS Library with OpenMC statepoint data\n", @@ -970,21 +914,13 @@ { "cell_type": "code", "execution_count": 29, - "metadata": { - "collapsed": false - }, + "metadata": {}, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ - "/home/romano/openmc/openmc/tallies.py:1798: RuntimeWarning: invalid value encountered in true_divide\n", - " self_rel_err = data['self']['std. dev.'] / data['self']['mean']\n", - "/home/romano/openmc/openmc/tallies.py:1799: RuntimeWarning: invalid value encountered in true_divide\n", - " other_rel_err = data['other']['std. dev.'] / data['other']['mean']\n", - "/home/romano/openmc/openmc/tallies.py:1800: RuntimeWarning: invalid value encountered in true_divide\n", - " new_tally._mean = data['self']['mean'] / data['other']['mean']\n", - "/home/romano/openmc/openmc/mixin.py:61: IDWarning: Another Universe instance already exists with id=0.\n", + "/home/nelsonag/git/openmc/openmc/mixin.py:71: IDWarning: Another Universe instance already exists with id=0.\n", " warn(msg, IDWarning)\n" ] } @@ -1013,9 +949,7 @@ { "cell_type": "code", "execution_count": 30, - "metadata": { - "collapsed": true - }, + "metadata": {}, "outputs": [], "source": [ "# Set the energy mode\n", @@ -1035,16 +969,14 @@ { "cell_type": "code", "execution_count": 31, - "metadata": { - "collapsed": true - }, + "metadata": {}, "outputs": [], "source": [ "# Create a \"tallies.xml\" file for the MGXS Library\n", "tallies_file = openmc.Tallies()\n", "\n", "# Add our fission rate mesh tally\n", - "tallies_file.add_tally(tally)\n", + "tallies_file.append(tally)\n", "\n", "# Export to \"tallies.xml\"\n", "tallies_file.export_to_xml()" @@ -1060,15 +992,23 @@ { "cell_type": "code", "execution_count": 32, - "metadata": { - "collapsed": false - }, + "metadata": {}, "outputs": [ { "data": { - "image/png": "iVBORw0KGgoAAAANSUhEUgAAAP8AAAD8CAYAAAC4nHJkAAAABHNCSVQICAgIfAhkiAAAAAlwSFlz\nAAALEgAACxIB0t1+/AAAEGVJREFUeJzt3XuwVeV9xvHvA0JQVC6iqKCijdhQx6iDisYLKdagdSS2\npsVWxRhjTZRgx4xDYkZtppncNU1zUaKoSRiNGiTWS8RrndpIghTlpiLGCwgcExUiGbn++sdeZLaH\nfWCz17u2h7zPZ+bMWWfv9/zWj7XPw1p7nXXWq4jAzPLT4/1uwMzeHw6/WaYcfrNMOfxmmXL4zTLl\n8JtlyuE3y5TDb5Yph98sUztta4CkqcDpQEdEHFr3+ETgEmAjcF9EXLGtWj0G9IidhvQs0W5je0Xv\n5DUBdn1l3+Q1Nx3wSvKaANFnSCV1X/vt65XUHTF4WCV1n1/6WvKaww5+N3lNgIWLhqcvun4FseFt\nNTN0m+EHbgG+B/x48wOSPgqMAz4cEWsl7dXUyob0ZK/pezQzdLtMXDs0eU2AY//l6uQ1111/cfKa\nAOs+9OVK6k4676pK6j552fWV1D1x8uXJa9587/zkNQE+fMzU5DU3Lbmg6bHbPOyPiCeANzs9/Bng\naxGxthjTsT0Nmtn7r9X3/MOBEyTNkvTfko5K2ZSZVa+Zw/6uvm8gMAo4CrhD0kHR4E8EJV0EXATQ\nc1+fXzTrLlpN41JgetT8GtgEDGo0MCKmRMTIiBjZY4DDb9ZdtJrGGcBHASQNB3oDv0vVlJlVr5lf\n9d0GjAYGSVoKXA1MBaZKmg+sAyY0OuQ3s+5rm+GPiLO7eOqcxL2YWRv5TbhZphx+s0w5/GaZcvjN\nMuXwm2XK4TfLlMNvlimH3yxTDr9Zphx+s0w5/GaZcvjNMuXwm2Wq1Tv5tGTP1w7gsxO/nbzuHh+Y\nmbwmwMGj0t8R99KOVclrAvzbvbMrqXvK/f0qqXvyfx1fSd3n3+qTvOaNk8ckrwnw98svSV7z4fWv\nNj3We36zTDn8Zply+M0y5fCbZWqb4Zc0VVJHcb++zs9dLikkNbxzr5l1X83s+W8BxnZ+UNJ+wClA\n86cXzazbaHW6LoDrgCsA37XXbAfU0nt+SeOAZRHxTOJ+zKxNtvsiH0m7AF+kdsjfzPg/TdfVr8+e\n27s6M6tIK3v+vwAOBJ6R9DIwFJgjae9Gg+un6+rbe/fWOzWzpLZ7zx8R84C9Nn9d/AcwMiI8XZfZ\nDqSZX/XdBvwKOETSUkmfqr4tM6tamem6Nj8/LFk3ZtY2vsLPLFMOv1mmHH6zTDn8Zply+M0y5fCb\nZcrhN8uUw2+WKUW07y9yd+59aBw0+K7kddded3vymgAb7vtq8po3nHRD8poAB8+aXkndXm8Or6Tu\nsVcdXUndnm8OTF7zO492JK8JsGHuHclrTn78cZa89baaGes9v1mmHH6zTDn8Zply+M0y5fCbZcrh\nN8uUw2+WKYffLFMOv1mmWpquS9I3JT0n6VlJd0vqX22bZpZaq9N1PQQcGhGHAS8AX0jcl5lVrKXp\nuiJiZkRsKL58itq9+81sB5LiPf8FwANdPSnpIkmzJc3euOmtBKszsxRKhV/SlcAGYFpXY+pn7OnZ\nY0CZ1ZlZQts9Y89mks4HTgfGRDv/LtjMkmgp/JLGUpue+6SI+GPalsysHVqdrut7wG7AQ5LmSrq+\n4j7NLLFWp+u6qYJezKyNfIWfWaYcfrNMtXy2vxXDDnuBm3/zN8nrTvrcJ5PXBPjazNeT11z/s0HJ\nawJcdvlnK6m7YPT/VlL3qy//XSV17ztrXPKaH7twdPKaAItvW5S8Zp+PvNv0WO/5zTLl8JtlyuE3\ny5TDb5Yph98sUw6/WaYcfrNMOfxmmXL4zTLl8JtlyuE3y5TDb5Yph98sUw6/WaZanbFnoKSHJC0u\nPvu2vGY7mFZn7JkMPBIRBwOPFF+b2Q6kpRl7gHHArcXyrcDHE/dlZhVr9T3/4IhYXiyvAAYn6sfM\n2qT0Cb9iwo4uJ+2on67r7Tc2lV2dmSXSavhXStoHoPjc0dXA+um6+u/pXy6YdRetpvEeYEKxPAH4\nRZp2zKxdtK1p9ooZe0YDg4CVwNXADOAOYH/gFeAfIqLzScEt7LzXsDjoH79UsuUtTdz72uQ1AVYe\n9oHkNYd/bHbymgBPDu1bSd3n9j+pkronLK7mNFGf2dclr/noOZ9IXhNgNZ9PXnPe/Em8s2axmhnb\n6ow9AGO2qysz61b8JtwsUw6/WaYcfrNMOfxmmXL4zTLl8JtlyuE3y5TDb5Yph98sUw6/WaYcfrNM\nOfxmmXL4zTLl8JtlyuE3y5TDb5Yph98sUw6/WaZKhV/Sv0paIGm+pNsk9UnVmJlVq+XwSxoCfA4Y\nGRGHAj2B8akaM7NqbfMGnk18/86S1gO7AK9vbfCIta/y5JJLSq5yS9P6dzltQCkHPDc6ec3XD5+X\n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\niEeI+AAAAABJRU5ErkJggg==\n", "text/plain": [ - "" + "" + ] + }, + "execution_count": 32, + "metadata": {}, + "output_type": "execute_result" + }, + { + "data": { + "image/png": "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\n", + "text/plain": [ + "" ] }, "metadata": {}, @@ -1093,9 +1033,7 @@ { "cell_type": "code", "execution_count": 33, - "metadata": { - "collapsed": false - }, + "metadata": {}, "outputs": [ { "name": "stdout", @@ -1127,12 +1065,12 @@ " %%%%%%%%%%%\n", "\n", " | The OpenMC Monte Carlo Code\n", - " Copyright | 2011-2017 Massachusetts Institute of Technology\n", + " Copyright | 2011-2018 Massachusetts Institute of Technology\n", " License | http://openmc.readthedocs.io/en/latest/license.html\n", - " Version | 0.9.0\n", - " Git SHA1 | da61fb4a55e1feaa127799ad9293a766161fbb3e\n", - " Date/Time | 2017-12-11 17:00:35\n", - " OpenMP Threads | 4\n", + " Version | 0.10.0\n", + " Git SHA1 | 6c2d82a4d7dfe10312329d5969568fc03a698416\n", + " Date/Time | 2018-04-24 19:16:03\n", + " OpenMP Threads | 8\n", "\n", "\n", " ====================> K EIGENVALUE SIMULATION <====================\n", @@ -1147,16 +1085,6 @@ " Leakage Fraction = 0.00000 +/- 0.00000\n", "\n" ] - }, - { - "data": { - "text/plain": [ - "0" - ] - }, - "execution_count": 33, - "metadata": {}, - "output_type": "execute_result" } ], "source": [ @@ -1174,9 +1102,7 @@ { "cell_type": "code", "execution_count": 34, - "metadata": { - "collapsed": true - }, + "metadata": {}, "outputs": [], "source": [ "# Move the StatePoint File\n", @@ -1201,21 +1127,13 @@ { "cell_type": "code", "execution_count": 35, - "metadata": { - "collapsed": false - }, + "metadata": {}, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ - "/home/romano/openmc/openmc/tallies.py:1798: RuntimeWarning: invalid value encountered in true_divide\n", - " self_rel_err = data['self']['std. dev.'] / data['self']['mean']\n", - "/home/romano/openmc/openmc/tallies.py:1799: RuntimeWarning: invalid value encountered in true_divide\n", - " other_rel_err = data['other']['std. dev.'] / data['other']['mean']\n", - "/home/romano/openmc/openmc/tallies.py:1800: RuntimeWarning: invalid value encountered in true_divide\n", - " new_tally._mean = data['self']['mean'] / data['other']['mean']\n", - "/home/romano/openmc/openmc/mixin.py:61: IDWarning: Another Universe instance already exists with id=0.\n", + "/home/nelsonag/git/openmc/openmc/mixin.py:71: IDWarning: Another Universe instance already exists with id=0.\n", " warn(msg, IDWarning)\n" ] } @@ -1237,9 +1155,7 @@ { "cell_type": "code", "execution_count": 36, - "metadata": { - "collapsed": false - }, + "metadata": {}, "outputs": [ { "name": "stdout", @@ -1271,12 +1187,12 @@ " %%%%%%%%%%%\n", "\n", " | The OpenMC Monte Carlo Code\n", - " Copyright | 2011-2017 Massachusetts Institute of Technology\n", + " Copyright | 2011-2018 Massachusetts Institute of Technology\n", " License | http://openmc.readthedocs.io/en/latest/license.html\n", - " Version | 0.9.0\n", - " Git SHA1 | da61fb4a55e1feaa127799ad9293a766161fbb3e\n", - " Date/Time | 2017-12-11 17:00:59\n", - " OpenMP Threads | 4\n", + " Version | 0.10.0\n", + " Git SHA1 | 6c2d82a4d7dfe10312329d5969568fc03a698416\n", + " Date/Time | 2018-04-24 19:16:12\n", + " OpenMP Threads | 8\n", "\n", "\n", " ====================> K EIGENVALUE SIMULATION <====================\n", @@ -1291,16 +1207,6 @@ " Leakage Fraction = 0.00000 +/- 0.00000\n", "\n" ] - }, - { - "data": { - "text/plain": [ - "0" - ] - }, - "execution_count": 36, - "metadata": {}, - "output_type": "execute_result" } ], "source": [ @@ -1321,9 +1227,7 @@ { "cell_type": "code", "execution_count": 37, - "metadata": { - "collapsed": false - }, + "metadata": {}, "outputs": [], "source": [ "# Load the isotropic statepoint file\n", @@ -1346,9 +1250,7 @@ { "cell_type": "code", "execution_count": 38, - "metadata": { - "collapsed": false - }, + "metadata": {}, "outputs": [], "source": [ "ce_keff = sp.k_combined\n", @@ -1356,8 +1258,8 @@ "angle_mg_keff = angle_mgsp.k_combined\n", "\n", "# Find eigenvalue bias\n", - "iso_bias = 1.0E5 * (ce_keff[0] - iso_mg_keff[0])\n", - "angle_bias = 1.0E5 * (ce_keff[0] - angle_mg_keff[0])" + "iso_bias = 1.0E5 * (ce_keff - iso_mg_keff)\n", + "angle_bias = 1.0E5 * (ce_keff - angle_mg_keff)" ] }, { @@ -1370,9 +1272,7 @@ { "cell_type": "code", "execution_count": 39, - "metadata": { - "collapsed": false - }, + "metadata": {}, "outputs": [ { "name": "stdout", @@ -1384,8 +1284,8 @@ } ], "source": [ - "print('Isotropic to CE Bias [pcm]: {0:1.1f}'.format(iso_bias))\n", - "print('Angle to CE Bias [pcm]: {0:1.1f}'.format(angle_bias))" + "print('Isotropic to CE Bias [pcm]: {0:1.1f}'.format(iso_bias.nominal_value))\n", + "print('Angle to CE Bias [pcm]: {0:1.1f}'.format(angle_bias.nominal_value))" ] }, { @@ -1408,15 +1308,14 @@ "cell_type": "code", "execution_count": 40, "metadata": { - "collapsed": false, "scrolled": false }, "outputs": [ { "data": { - "image/png": "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\n", + "image/png": "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\n", "text/plain": [ - "" + "" ] }, "metadata": {}, @@ -1466,14 +1365,12 @@ { "cell_type": "code", "execution_count": 41, - "metadata": { - "collapsed": false - }, + "metadata": {}, "outputs": [ { "data": { "text/plain": [ - "" + "" ] }, "execution_count": 41, @@ -1482,9 +1379,9 @@ }, { "data": { - "image/png": "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\n", + "image/png": "iVBORw0KGgoAAAANSUhEUgAAAt0AAAFfCAYAAACSp3C8AAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEgAACxIB0t1+/AAAIABJREFUeJzt3Xm4JVV59/3vj4YGGaSBbhVoBg1OOKG2oNHHEIwKTqAxClEmB/SJxCFxQo0kJDjk9ZFoMJqOAqIIGhQlAUWjtEQjChhUEFFEkGaQSWYBgfv9o+p0733oPmcf2PvUGb6f66qr967xruruVfdetWqtVBWSJEmSRmedrgOQJEmS5jqTbkmSJGnETLolSZKkETPpliRJkkbMpFuSJEkaMZNuSZIkacRMutUnybZJbkmyoKPj/22Sz06w/BVJvj6dMUkaXJIDknyn6zimQ5IVSV7TdRxTkeSSJH8ywfKvJtl/OmOS5guT7mk0WWE34D5GWshX1a+rauOqunuKcR2QpJIcMW7+nu38Y6YaS5Lt223X7YnvuKp6ziTbLUvyn0l+m+SGJD9NcniSzaYagzSXteXJb5Os33UsAEl2TXJP+8P/liQrk3whyVO6jm2UBvmh0v5dVZInjJt/Ujt/1/tw3HtVclTVHlX16Qm2SZKDk/w4yW1Jrmpj23uqx5fmG5PuOaY3Qe3AL4GXjYthf+Dn0xVAkj8EVgDfBR5VVYuA3YG7gCesZZsur5nUiSTbA/8HKOBFnQbT74qq2hjYBHgq8DPgv5M8q9uwZoSfA/uNfUmyBfA04JppjOGjwJuBvwa2ALYG3kNTzt5Lm6Sba0iYdHcmyQ5Jvp3kxiTXJvl8z7I/THJWu+ysNpEkyeE0N8kj21qgI9v5leQNSX4B/GKifbTLViR5f5IfJLkpyVeSbN4u66tdTrJ5kqOTXNHWiH15gtO6CvgJ8NyxbYE/BE7uOfauSVaOuxZrewJwRvvnDe35Pm2AGqF/BI6uqvdX1W9gVe39oVW1oj3eAUm+m+SIJNcBf5tknSTvSXJpkquTHJtk00FibmuLTkzy+SQ3J/nh+NooaQbaDzgTOIbmx/EqSY5J8rEkp7T/pr+f5A96lj8nyYVt+fIvbVm2xidwSR6V5BtJrm+3edkgwVVjZVW9F/gk8MFB9tnG/ol2+c1tbNtNYduJzvvZSX7WnveRQMad66uSXNCWlaeNO24leX2SX6R5AvexNiF9NPAJ4GltOXfDBJflOODlWd38bx/gJODOcefwDz3f71V+tfN3B97V7u+WJD9q56/1aWqSRwB/AexdVd+oqt9V1d1V9Z2qOqBnvRVpni5+F7gNeFiSrZKc3F73i5K8dtCY2/L2kDRPLX/b3pM2mOA6STOSSXd3/h74OrAZsBT4Z1iVqJ5CU5uwBfBh4JQkW1TVu4H/Bg5um4Ac3LO/vYBdgB0n2kfP+vsBrwK2pKkF/uha4vwMsCHwGOBBwBFrWW/Msayuidkb+ApwxyTbrM0z2z8Xtef7vYlWTrIRTa3PFwfY9y7AxcCDgcOBA9rpj4GHARsDR04h1j2Bfwc2Bz4HfDnJelPYXppu+9EkcccBz03y4HHL9wb+jqaMuojm/wlJFgMnAofQlC8X0vy4vpf2/+Q3aP5PPKjd578k2XGKsX4JeFKSjQbc5ytoytjFwLntOQ4az0Tn/SWaWt3FNE/2nt5zrnvSJLEvAZbQlNXHjzuPFwBPAR4PvAx4blVdALwe+F5bzi2a4DpcAfwUGGtitx9NmTtlVfU14H3A59vjDlJRsBtwWVWdPcC6+wIH0TyxuBQ4AVgJbAW8FHhfkt2mEPIraCp0/gB4BM3fgzSrmHR35/fAdsBWVXV7VY3V3j4f+EVVfaaq7qqq42ker75wkv29v6qur6rfDbiPz1TVeVV1K/A3NM1C+l6eTLIlsAfw+qr6bVX9vqq+PUkcJwG7trXE9/mGcB9tRvNv+qqxGUn+sa1VujVJbyF9RVX9c3t9fkdToH+4qi6uqltoEoq9M3jTk3Oq6sSq+j3Nj5wNaB6NSzNOkmfQlD9fqKpzaBLIPx+32klV9YOquosmad2pnf884Pyq+lK77KP0/J8b5wXAJVV1dPt/7X9pfhT/2RRDvoKmVnnRgPs8parOqKo7gHfT1CJvM+C2k5332P/zfxp33q+nKYcvaLd9H7BTb2038IGquqGqfg2c3rPvqTgW2C/Jo2gqJCasjBiyxYz7u07T7v6GJLePO9djqur89lo8hOYHyjva+925NE8v9mNwR1bVZVV1Pc0PoX3u36lI08+kuztvp7mJ/CDJ+Ule1c7fiqZWoNelNO3mJnJZz+dB9nHZuGXr0RSovbYBrq+q305y7FXaBPYUmlqILarqu4NuO1VJ3pXVL1x9AvgtcA9N7f1YPG9va45OAnoT6Mv693ava3Zpu/742r+1WbW/qrqH1TU60ky0P/D1qrq2/f45xjUxoT+5uo3m6Q80/657/70Xzb/3NdkO2KVNym5om068AnhIVveUdEuSWyaJd2uatuc3TLTPnvV747sFuL6Ne5Btp3LeveXIdsBHevZ7PU0Z31vurm3fU/Elmhrng2meRI5Me28a+zv6P8B19JSvAFW1lObesT79zW3G35Our6qbe+YNcl/rNf6eZfmqWccXyDpSVVcBr4VVtU7/leQMmhqd7catvi3wtbFN17bLns+T7QOahLp32e+Ba8fNvwzYPMmiqpqoneF4xwLfonlEO96tNM1VAGhr15esZT9rO9dmYdX7aGqTVknyfZrHu6dPEuP4fY+/ZtvSNLv5DU3hPlnM2/QsX4emydAVk8QgTbskD6Bp2rAgyVgSuD6wKMkTqupHk+ziSpp/32P7S+/3cS4Dvl1Vz17L8kGTzhcDP6yqW5NMtk/o//+4MU2zrysGiGciV47bb7h3eXl4VR13H/Y9YVnXt2LVbUm+CvxfmqYW4/WVsfT/oJjScavqMb3fk1xN807RsgGamIy/J22eZJOexHtb4PIpxDz+nmX5qlnHmu6OJPmzJGM3qt/SFFD3AKcCj0jy50nWTfJyYEfgP9t1f0PT5ngik+0D4JVJdkyyIXAYcOL4bgKr6krgqzRtHjdLsl6SZzK5bwPPpm2nPs7PgQ2SPL9t8/wemhv+mlxDc00mO99ebwdeleSdSR4E0F7nh06y3fHAW5I8tL1Jj7V1vGvAmJ+c5CVtc5Q307RjP3MKcUvTZS/gbpoyYad2ejRNG+RBHvefAjwuyV7tv/c3sPbE7j9pyqJ92/JjvSRPSfPy4ITS2DrJocBraNpLD7rP5yV5RpKFNG27z6yqy+5PPO15P6bn//kbx533J4BDkjymjX/TJIM2o/kNsLSNdxDvAv6oqi5Zw7Jzac5/8yQPoSmPJjru9hmwd5GquhD4V+CENC+VPqCthFhjm/6e7S4D/gd4f5INkjweeDUw1l3hIDG/IcnSNO8svRv4/BrWkWY0k+7uPAX4fvtY9WTgTW174uto2h3+Nc2jvLcDL+h5DPwR4KVp3uBe48uPA+wDmseSx9A87tyA5gayJvvS1IL/DLiaiQvwseNXVX2zbXs3ftmNNG+/f5KmluNW1vJouqpuo2m79932ke2kbaTbtvG70byE+fP2Me/XaLoRXNOPgDFH0VyTM4BfAbcDfzmFmL8CvJzmB9S+wEvadp/STLM/TQ8/v66qq8YmmheHXzHZewxtOfJnND0FXUeTvJ/NGl6Ybms1n0PzcuIVNOXNB1n7D22Ardpy8RbgLOBxwK5V9fUp7PNzwKE0TTyeDLzyfsQz/rw/0J73w2m6Jh1bflK7rxOS3AScR/NOzCC+BZwPXJXk2slWrqoret4DGu8zwI+AS2he1p8oOf339s/rkvxwwFjfQNOO/8M013clzQ+blwO/nmC7fYDtaa77ScChVfVfU4j5c+2yi2neQfiHNawjzWhpmqVpPkmyAvhsVX2y61jmgiR/C+xQVa/sOhZpurW1pCuBV1TVZM26piOeY4CVVWXvFnNEkkuA1/Qk6dKsZE23JGlKkjw3yaI0I1m+i+YFOptTSdIETLolSVP1NJpH/NfSdEW6V9tzkSRpLWxeIkmSJI2YNd2SJEnSiJl0d6RnYIgFk6+91n3ckmQq3enNW0m2T1KT9cwwwfbvSuKLp9L9YLk3vSz3pJnFpHvEklyS5HfpGXktyVZtd10bj+8beyra7S8eZrxwr5ivSnJM23f1INver0J+kn2vSDPU8C1Jrk3ypTRD1Q/7OLsm6esSsKreV1WvGfaxpLnIcm+ocVnuSXOESff0eGF7oxibZsNIWi+sqo1pBs54InBIx/GMObiNawea0ew+1HE8ktbMcm94LPekOcCkuyPja0aSHJDk4iQ3J/lVkle083dI8u0kN7a1HJ/v2Ucl2aH9vGmSY5Nck+TSJO8ZG2Ws3fd3knyoHVTnV0kGGrShHTTjNJqb0Nhxn5/kf5PclOSytp/qMWe0f97Q1sw8rd3mVUkuaI9/WpLt2vlJckSSq9v9/STJYweI6wbgy+PiWifNSJS/THJdki+kGb3sXpIc2MZzc3vdX9fO34hmFM6temvokvxtks+263w1ycHj9vejJC9pPz8qyTeSXJ/kwiQvm+x8pPnAcs9yT5rPTLpngLbA+yiwR1VtQjOk7rnt4r+nGYVrM2Apax9V8Z+BTWmGTP8jmuGcD+xZvgtwIbCYZiS5TyXJALEtpRlV7aKe2be2+18EPB/4v0n2apeNDRO/qK3d+l6SPWn68n0JsIRmuOnj2/We027ziDb+l9GM9jZZXFu0++uN6y9phrj+I2ArmtEhP7aWXVxNM2rnA2mu0xFJnlRVt7bne8UENXTH04yuNhbLjsB2wCnt3+U3aEZPexDNyHf/0q4jqWW5Z7knzTtV5TTCiWZY21uAG9rpy+387YEC1gU2apf9KfCAcdsfCywHlq5h30XzuHEBcCewY8+y1wEr2s8HABf1LNuw3fYhk8R8c7veN2luJms7x38Cjhh/Xj3Lvwq8uuf7OsBtNAX2bsDPgacC60xyLVe0293YHuNcYNue5RcAz+r5viXNEPbrrimucfv+MvCm9vOuNCPa9S7/W5pRPAE2obkBb9d+Pxw4qv38cuC/x237rzRDHnf+79HJaTomyz3LPcs9J6d7T9Z0T4+9qmpRO+01fmE1tQwvB14PXJnklCSPahe/nWa0tx8kOT/Jq9aw/8XAesClPfMuBbbu+X5Vz/Fuaz9O9JLQXtXUPu0KPKo9BgBJdklyevtI98Y27sVr3g3Q3GQ+kuSGJDcA17fntHVVfQs4kqZm5uoky5M8cIJ9vbGqNgUez+pasN7jnNRznAuAu4EHj99Jkj2SnNk+Cr0BeN4k57BKVd0MnEJTmwNN7c9xPTHsMhZDu+9XAA8ZZN/SHGK5Z7lnuSf1MOmeIarqtKp6Nk0txc+Af2vnX1VVr62qrWhqcf5lrD1jj2tpaja265m3LXD5EOL6NnAM/S/ufA44GdimvRF8guZmAk2tyniXAa/ruQEvqqoHVNX/tMf4aFU9GdiR5nHr2waI6yfAPwAf63lcfBnNo+re42xQVX3XIc3Q1V9sz+nBVbUIOHWScxjveGCftu3mBsDpPTF8e1wMG1fV/x1gn9K8YrlnuSfNJybdM0CSByfZs20XdwfNI8572mV/1rYvhKatXo0tG1NN91tfAA5Pskn7ss5fAZ8dUoj/BDw7yRPa75sA11fV7Ul2Bv68Z91r2vh6+9H9BHBIkse057Rpkj9rPz+lrUFaj+bR5e3jz28Cn6apzXlRz3EO73lZaUnbrnK8hcD6bax3pXm56jk9y38DbJFk0wmOfSrNzf4w4PNVNRbzfwKPSLJvkvXa6SlJHj3gOUnzguWe5Z4035h0zwzr0NwsrqB5BPlHwFgNwVOA7ye5haaW5U215j5q/5Km8L4Y+A5NrcxRwwiuqq6haWP53nbWXwCHJbm5nfeFnnVvo2nr9932MeNTq+ok4IPACUluAs6jeWkHmhd6/o3mxnopzctE/9+Acd0JfAT4m3bWR2iu0dfb2M6keZFq/HY3A29s4/4tzc3z5J7lP6Op0bm4PYet1rCPO4AvAX9Cc6179/0cmkewV9A83v4gzc1O0mqWe5Z70rySqkGeKEmSJEmzS5KjaHrtubqq7tU1Z/suydHAk4B3V9WHepbtTvPDdgHwyar6QDv/ocAJwBbAOcC+7Q/iCVnTLUmSpLnqGGD3CZZfT/MUqG/QqSQLaF523oPm3Yt9errB/CBN70U70Dw5evUggZh0S5IkaU6qqjNoEuu1Lb+6qs6ieTG718403Y5e3NZinwDs2b7EvBtwYrvep2n6yp/UulMNXpIkSXPX7kld23UQAzoHzqd5GXnM8qpaPoRdb03TM8+YlTTvS2wB3FBVd/XM35oBmHRLkiRplWuBs7sOYkCB26tqWddxDMKkW/fS9hjw+LX0FiBJc47lnjTOOrOkBfI9g/a2OWWXA9v0fF/azrsOWJRk3ba2e2z+pGbJFZ3dklyS5E/ux/ZJ8sYk5yW5NcnKJP+e5HFDiG1Fktf0zmsHNZg1N572HG5PckvP9B9dxyXNZ5Z7o2W5p5FbZ53ZMY3OWcDDkzw0yUKaLjFPrqbbv9OBl7br7Q98ZZAdWtM9O3wEeD7wWuC7NF3XvLid95MO45pJDq6qT47yAD2/aiWNnuXe5Cz3NBrJ7KnpnkSS44FdgcVJVgKHAusBVNUnkjyEpjXNA4F7krwZ2LGqbkpyMHAaTflzVFWd3+72HTR98P8D8L/ApwYKpqqcRjgBn6EZaex3NCOuvb2d/yKaxv83ACuAR69l+4cDdwM7T3CMTWkGcbiGZqCF9wDrtMsOoBk04kM03dr8imbIYGgGc7ib5gWEW4Aj2/kF7NB+Poamy5xTgJuB7wN/0C7bvl133Z5YVgCvaT+v08ZyKXB1G+Om7bJdgZXjzuMS4E/azzu3/wluohkp7cMTnP+qY65h2a40Lzn8dRvDlcCBPcvXb6/Nr9vjfAJ4wLht30Ez2MNn2vlvb/dzBfCasetFM6DHb4AFPft/CfCjrv8dOjlN52S5Z7lnuTe7pycnVQsXzooJOLvr6zXoNDd+xsxgVbUvTcH2wmoeX/5jkkfQjPz1ZmAJzdC6/9E+vhjvWTSF9A8mOMw/09yAHkYzqtt+wIE9y3cBLgQWA/8IfCpJqurdwH/T1JZsXFUHr2X/ewN/B2wGXERz0xrEAe30x21sGwNHDrjtR4CPVNUDgT+gZ/S3++AhNNdna5q+ND+WZLN22QeARwA70dxAtmb1CHRj225OM/TxQW1H+X9FMyLbDjQ3KACq6XLoOvqHVt6X5qYrzRuWe5Z7WO7Nfl03G+m+ecnQza5o546XA6dU1Teq6vc0NQ4PAP5wDetuQVO7sEZt5+17A4dU1c1VdQnw/2gKvTGXVtW/VdXdNP1Jbgk8eArxnlRVP6jmEeNxNAX1IF5BU1NzcVXdAhwC7J1kkGZNvwd2SLK4qm6pqjMnWf+j7dDFY9Pfj9vXYVX1+6o6laZ265FtX5sHAW+pquurGcr4fTTXc8w9wKFVdUdV/Q54GXB0VZ1fzdDPfzsujk8DrwRIsjnwXHqGS5bmMcu9yVnuaWYYa14yG6ZZZHZFO3dsRfPoEYCquoemL8g19fN4Hc3NYm0W07RNurRn3qXj9nVVz7Fuaz9uPIV4r+r5fNsUtu07z/bzugx243s1TU3Mz5KcleQFAEk+0fPS0Lt61n9jVS3qmf6mZ9l11d8mcewclgAbAueM3bSAr7Xzx1xTVb39f25Ff7+dvZ8BPgu8MMlGNDeq/66qtSYP0jxiuTc5yz3NHF0n0ybduo9q3PcraB7bAc1b+jTd0qypy5lvAkuTrK0PymtpajS265m37Vr2NUhsU3Fr++eGPfMe0vO57zzbuO6iaf93a+92bc3VqkK/qn5RVfsAD6IZbvXEJBtV1evbR8IbV9X77kfs0Fy73wGP6blpbVpVvTfX8dfnSprugcb0didEVV0OfI+mTeO+NG1bpfnIcm91XJZ7mn26TqZNunUf/Yambd+YLwDPT/KsJOvRvOxyB/A/4zesql8A/wIcn2TXJAuTbJBk7yTvbB+dfgE4PMkmSbajaXv32fsY28Cq6hqam9wrkyxI8iqadohjjgfe0na3szHNI8zPt7UvPwc2SPL89hq8h+blHgCSvDLJkrY27IZ29lA742z3/W/AEUke1B536yTPnWCzLwAHJnl0kg2Bv1nDOsfSvHT0OOBLw4xZmkUs9yz3NFvZvGQkZle0s9f7gfe0j/LeWlUX0rR/+2eaWocX0rxwdOdatn8jzYs4H6MpiH9J03XWWJ+sf0lTg3IxzRv7nwOOGjC2jwAvTfLbJB+d8pk13Xm9jeZx8GPov4EeRVPjcQZN7wG3t7FSVTcCfwF8kuYGdivNG/NjdgfOTzNgxUeAvdu2hWtz5Lj+as8ZMP530LwkdWaSm4D/Ah65tpWr6qvAR2n66LwIGGtzeUfPaifR1HSd1PNYW5pvLPcs9yT1SNX9ecomzW9JHg2cB6zf234yyS+B11XVf3UWnCSNgOXe3Lds3XXr7E037TqMgeT6688ph4GX5qYkL6bp7mxDmnaX/zHuxvOnNG0iv9VNhJI0XJZ788wcGhxnJjHplqbudTSDZ9wNfJvmcTHQDM0M7Ajs27adlKS5wHJvvjHpHjqTbmmKqmr3CZbtOo2hSNK0sNybh0y6h86kW5IkSavZvGQkTLolSZLUz6R76EaSdCeLC7Yfxa4HttFGnR4egAc+sOsIGjPh/03SdQSw7gz4ibnFZjOkuePNN3d6+Euuvpprb7xxBvyrGJ7FG21U2y9a1G0Qv/99t8cH2GCDriNobLjh5OvMBxtPZRDOEZkJ/y4B7lxb75TT45Irr+TaG26YU+WepmZEacj2wNmj2fWAnvCETg8PwG67dR1BYybce2bCfXjzzbuOAPZ/6a2TrzQdTj+908Mve8tbOj3+KGy/aBFnv/713QZx5QwYeXvHHbuOoDETbgIzoLbh7qc9o+sQWHDVoAOFjtivf93p4Ze96lWdHn9KbF4yEjOg7k+SJEkzikn30Jl0S5IkqZ9J99CZdEuSJGk1m5eMhEm3JEmS+pl0D51XVJIkSRoxa7olSZK0ms1LRsKkW5IkSf1MuofOpFuSJEn9TLqHzqRbkiRJq9m8ZCRMuiVJktTPpHvoTLolSZK0mjXdIzHpFU3yyCTn9kw3JXnzdAQnSV2w3JMkDdukNd1VdSGwE0CSBcDlwEkjjkuSOmO5J2nes6Z76KbavORZwC+r6tJRBCNJM5DlnqT5x6R76KZ6RfcGjh9FIJI0Q1nuSZpfxtp0z4Zp0lPJUUmuTnLeWpYnyUeTXJTkx0me1M7/43HNDG9Psle77Jgkv+pZttMgl3Xgmu4kC4EXAYesZflBwEHNt20H3a0kzVhTKfe23XTTaYxMkkZs7tR0HwMcCRy7luV7AA9vp12AjwO7VNXprG5muDlwEfD1nu3eVlUnTiWQqTQv2QP4YVX9Zk0Lq2o5sLwJbllNJQhJmqEGLveWbb215Z6kuWEO9V5SVWck2X6CVfYEjq2qAs5MsijJllV1Zc86LwW+WlW33Z9YpnJF98FHrJLmF8s9SZrbtgYu6/m+sp3Xa03NDA9vm6MckWT9QQ40UNKdZCPg2cCXBllfkmY7yz1J81rXbbUHb9O9OMnZPdNBw7wMSbYEHgec1jP7EOBRwFOAzYF3DLKvgZqXVNWtwBZTC1OSZi/LPUnz2uxpXnJtVS27H9tfDmzT831pO2/My4CTqur3YzN6mp7ckeRo4K2DHMgRKSVJkrTaHGrTPYCTgYOTnEDzIuWN49pz78O4l+nH2nwnCbAXsMaeUcYz6ZYkSVK/OZJ0Jzke2JWmGcpK4FBgPYCq+gRwKvA8mt5JbgMO7Nl2e5pa8G+P2+1xSZYAAc4FXj9ILCbdkiRJWm0O1XRX1T6TLC/gDWtZdgn3fqmSqtrtvsRi0i1JkqR+cyTpnkm8opIkSdKIWdMtSZKkftZ0D51JtyRJklabQ226ZxKTbkmSJPUz6R46k25JkiStZk33SJh0S5IkqZ9J99CNJOneYAPYYYdR7Hlwu+/e7fEBdt216wgaT3xi1xFAVdcRwCYL7+g6BPifH3QdQWPTTbs9/oIF3R5/FKrgnnu6jeHFL+72+DBzbtRPelLXEXDlTRt1HQJb3vm7rkOAu+7qOoLGwx7W7fEXLuz2+OqcNd2SJElazeYlI2HSLUmSpH4m3UNn0i1JkqR+Jt1DZ9ItSZKk1WxeMhIm3ZIkSepn0j10Jt2SJElazZrukfCKSpIkSSNmTbckSZL6WdM9dCbdkiRJ6mfSPXQm3ZIkSVrNNt0jYdItSZKkfibdQ2fSLUmSpNWs6R4Jr6gkSZI0YgPVdCdZBHwSeCxQwKuq6nujDEySumS5J2les6Z76AZtXvIR4GtV9dIkC4ENRxiTJM0ElnuS5i+T7qGbNOlOsinwTOAAgKq6E7hztGFJUncs9yTNa7bpHolBarofClwDHJ3kCcA5wJuq6taRRiZJ3bHckzS/mXQP3SBXdF3gScDHq+qJwK3AO8evlOSgJGcnOfvuu68ZcpiSNK2mXO5dc9tt0x2jJI3GWE33bJhmkUGiXQmsrKrvt99PpLkZ9amq5VW1rKqWLViwZJgxStJ0m3K5t2RDm3xLmkO6TqbnY9JdVVcBlyV5ZDvrWcBPRxqVJHXIck+SNGyD9l7yl8Bx7Rv8FwMHji4kSZoRLPckzV+zrBZ5Nhgo6a6qc4FlI45FkmYMyz1J89Yc6r0kyVHAC4Crq+qxa1gemi5inwfcBhxQVT9sl90N/KRd9ddV9aJ2/kOBE4AtaF6037ft5WpCc+OKSpIkaXi6bqs9vDbdxwC7T7B8D+Dh7XQQ8PGeZb+rqp3a6UU98z8IHFFVOwC/BV490CUdZCVJkiTNE3Oo95KqOgO4foJV9gSOrcaZwKIkW6790iTAbjQv2AN8GthrkMs6aJtuSZIkzRdzpHnJALYGLuv5vrKddyWwQZKzgbuAD1TVl2malNxQVXeNW39SJt2SJEnqN3uS7sWr41y+AAAdNElEQVRtYjxmeVUtH9K+t6uqy5M8DPhWkp8AN97XnZl0S5Ikaba6tqruz0vvlwPb9Hxf2s6jqsb+vDjJCuCJwBdpmqCs29Z2r1p/MrPmZ4wkSZKmwRxq0z2Ak4H90ngqcGNVXZlksyTrN5cji4GnAz+tqgJOB17abr8/8JVBDmRNtyRJkvrNnuYlE0pyPLArTTOUlcChwHoAVfUJ4FSa7gIvoukycGxMhkcD/5rkHppK6g9U1dggae8ATkjyD8D/Ap8aJBaTbkmSJK02h/rprqp9JllewBvWMP9/gMetZZuLgZ2nGotJtyRJkvrNkaR7JjHpliRJUj+T7qHzikqSJEkjNpKa7vXWgyVLRrHnwT3+8d0eH+BHP+o6gsb/+dm/dR0CP3nqa7sOgccdfUjXIcD/+39dR9BYsaLb41d1e/xRWHddWLSo2xge9rBujw9cueEfdB0CAFsuP6LrEDj3UW/pOgS2vPPrXYfAeX+wZ9chAPDYu37ZbQD33NPt8adiDrXpnklsXiJJkqR+Jt1DZ9ItSZKk1azpHgmTbkmSJPUz6R46k25JkiT1M+keOpNuSZIkrWbzkpHwikqSJEkjZk23JEmS+lnTPXQm3ZIkSVrN5iUjYdItSZKkfibdQ2fSLUmSpH4m3UNn0i1JkqTVbF4yEl5RSZIkacQGqulOcglwM3A3cFdVLRtlUJLUNcs9SfOaNd1DN5XmJX9cVdeOLBJJmnks9yTNPzYvGQnbdEuSJKmfSffQDZp0F/D1JAX8a1UtH2FMkjQTWO5Jmp+s6R6JQZPuZ1TV5UkeBHwjyc+q6ozeFZIcBBwEsP762w45TEmadlMq97bdbLMuYpSk0TDpHrqBrmhVXd7+eTVwErDzGtZZXlXLqmrZwoVLhhulJE2zqZZ7SzbeeLpDlKTRWWed2THNIpNGm2SjJJuMfQaeA5w36sAkqSuWe5KkYRukecmDgZOSjK3/uar62kijkqRuWe5Jmr9s0z0SkybdVXUx8IRpiEWSZgTLPUnznkn30NlloCRJklazpnskTLolSZLUz6R76Ey6JUmS1M+ke+i8opIkSdKImXRLkiRptbE23bNhmvRUclSSq5OssdvXND6a5KIkP07ypHb+Tkm+l+T8dv7Le7Y5JsmvkpzbTjsNclltXiJJkqR+c6d5yTHAkcCxa1m+B/DwdtoF+Hj7523AflX1iyRbAeckOa2qbmi3e1tVnTiVQEy6JUmStNoc6r2kqs5Isv0Eq+wJHFtVBZyZZFGSLavq5z37uCLJ1cAS4Ia17Wgyc+OKSpIkaXi6bjYyfcPAbw1c1vN9ZTtvlSQ7AwuBX/bMPrxtdnJEkvUHOZA13ZIkSeo3e2q6Fyc5u+f78qpaPqydJ9kS+Aywf1Xd084+BLiKJhFfDrwDOGyyfZl0S5IkabXZ1bzk2qpadj+2vxzYpuf70nYeSR4InAK8u6rOHFuhqq5sP96R5GjgrYMcaNZcUUmSJGnITgb2a3sxeSpwY1VdmWQhcBJNe+++Fybb2m+SBNgLWGPPKOONpKZ7ww3hyU8exZ5nl4N3OavrEBpPeW3XEfC4rgMA7nj/h7sOgfUP2L/rEBpve1u3x193Dj5ku+02+OEPu43hZS/r9vjAll87uusQGm95S9cRsEfXAQBf+cqeXYfAnr+bGffC3z/yKZ0evxYO1Ox35pg9Nd0TSnI8sCtNM5SVwKHAegBV9QngVOB5wEU0PZYc2G76MuCZwBZJDmjnHVBV5wLHJVkCBDgXeP0gsczBO58kSZLus9nVvGRCVbXPJMsLeMMa5n8W+OxattntvsRi0i1JkqR+cyTpnklMuiVJktTPpHvoTLolSZK02hxqXjKTeEUlSZKkEbOmW5IkSf2s6R46k25JkiStZvOSkTDpliRJUj+T7qEz6ZYkSVI/k+6hM+mWJEnSajYvGQmTbkmSJPUz6R46r6gkSZI0YgPXdCdZAJwNXF5VLxhdSJI0M1juSZqXbF4yElNpXvIm4ALggSOKRZJmGss9SfOTSffQDXRFkywFng98crThSNLMYLknaV5bZ53ZMc0ig9Z0/xPwdmCTEcYiSTOJ5Z6k+cnmJSMxadKd5AXA1VV1TpJdJ1jvIOAggE022XZoAUrSdLsv5d62G200TdFJ0jQw6R66Qa7o04EXJbkEOAHYLclnx69UVcurallVLdtwwyVDDlOSptWUy70lG2ww3TFKkmaRSZPuqjqkqpZW1fbA3sC3quqVI49MkjpiuSdpXhtrXjIbplnEwXEkSZLUb5YltLPBlJLuqloBrBhJJJI0A1nuSZqXTLqHzppuSZIkrWbvJSNh0i1JkqR+Jt1DZ9ItSZKk1azpHgmvqCRJkjRi1nRLkiSpnzXdQ2fSLUmSpNVsXjISJt2SJEnqZ9I9dCbdkiRJ6mfSPXQm3ZIkSVrN5iUj4RWVJEnSnJTkqCRXJzlvLcuT5KNJLkry4yRP6lm2f5JftNP+PfOfnOQn7TYfTZJBYjHpliRJUr911pkd0+SOAXafYPkewMPb6SDg4wBJNgcOBXYBdgYOTbJZu83Hgdf2bDfR/lcZSfOS22+Hn/1sFHse3M47d3t8gO/c8ZSuQwDgGV0HoFWu+/Cnuw4BgC3u+k23Aaw7B1u2bbklvOc9nYZw6Z1bdnp8gJufcmDXIQDw2K4D0Cp/d+rMuBe+ZINuj3/77d0ef0rmUPOSqjojyfYTrLIncGxVFXBmkkVJtgR2Bb5RVdcDJPkGsHuSFcADq+rMdv6xwF7AVyeLZQ7e+SRJknS/zJGkewBbA5f1fF/Zzpto/so1zJ+USbckSZL6FAM1U54JFic5u+f78qpa3lk0EzDpliRJUp977uk6goFdW1XL7sf2lwPb9Hxf2s67nKaJSe/8Fe38pWtYf1Lz5tmBJEmSJlfVJN2zYRqCk4H92l5MngrcWFVXAqcBz0myWfsC5XOA09plNyV5attryX7AVwY5kDXdkiRJmpOSHE9TY704yUqaHknWA6iqTwCnAs8DLgJuAw5sl12f5O+Bs9pdHTb2UiXwFzS9ojyA5gXKSV+iBJNuSZIkjTOLmpdMqKr2mWR5AW9Yy7KjgKPWMP9s7kMnSSbdkiRJWmWseYmGy6RbkiRJfUy6h8+kW5IkSX1MuofPpFuSJEmr2LxkNOwyUJIkSRoxa7olSZLUx5ru4Zs06U6yAXAGsH67/olVdeioA5OkrljuSZrPbF4yGoPUdN8B7FZVtyRZD/hOkq9W1Zkjjk2SumK5J2leM+kevkmT7rbT8Fvar+u1U40yKEnqkuWepPnMmu7RGKhNd5IFwDnADsDHqur7I41KkjpmuSdpPjPpHr6Bku6quhvYKcki4KQkj62q83rXSXIQcBDAAx6w7dADlaTpNNVyb9uttuogSkkaDZPu4ZtSl4FVdQNwOrD7GpYtr6plVbVs4cIlw4pPkjo1aLm3ZPPNpz84SdKsMWnSnWRJW9NDkgcAzwZ+NurAJKkrlnuS5rOxNt2zYZpNBmlesiXw6bZ94zrAF6rqP0cbliR1ynJP0rw22xLa2WCQ3kt+DDxxGmKRpBnBck/SfGbvJaPhiJSSJEnqY9I9fCbdkiRJ6mPSPXxT6r1EkiRJ0tRZ0y1JkqRVbNM9GibdkiRJ6mPSPXwm3ZIkSVrFmu7RMOmWJElSH5Pu4TPpliRJUh+T7uEz6ZYkSdIqNi8ZDbsMlCRJkkbMmm5JkiT1saZ7+EaSdG+0Eey88yj2PLiHPKTb4wM8Y8U/dB0CAOc84D1dh8CTd7q76xBY/67buw6B9f/shV2H0PiP/+j2+AsWdHv8UVi4ELbfvtMQNr6p08MDsN3X/rXrEAD46mWv6zoENt646wjg6qu7jgAOfcE5XYcAwLevf3Knx7/rrk4PPyU2LxkNa7olSZLUx6R7+Ey6JUmS1Meke/h8kVKSJEmrjDUvmQ3TIJLsnuTCJBcleecalm+X5JtJfpxkRZKl7fw/TnJuz3R7kr3aZcck+VXPsp0mi8OabkmSJM1JSRYAHwOeDawEzkpyclX9tGe1DwHHVtWnk+wGvB/Yt6pOB3Zq97M5cBHw9Z7t3lZVJw4ai0m3JEmS+syh5iU7AxdV1cUASU4A9gR6k+4dgb9qP58OfHkN+3kp8NWquu2+BmLzEkmSJK0yy5qXLE5yds900LjT2Rq4rOf7ynZerx8BL2k/vxjYJMkW49bZGzh+3LzD2yYpRyRZf7Lrak23JEmS+syimu5rq2rZ/dzHW4EjkxwAnAFcDqzq6zjJlsDjgNN6tjkEuApYCCwH3gEcNtFBTLolSZLUZxYl3ZO5HNim5/vSdt4qVXUFbU13ko2BP62qG3pWeRlwUlX9vmebK9uPdyQ5miZxn5BJtyRJklaZY4PjnAU8PMlDaZLtvYE/710hyWLg+qq6h6YG+6hx+9innd+7zZZVdWWSAHsB500WiEm3JEmS+syVpLuq7kpyME3TkAXAUVV1fpLDgLOr6mRgV+D9SYqmeckbxrZPsj1NTfm3x+36uCRLgADnAq+fLBaTbkmSJM1ZVXUqcOq4ee/t+XwisMau/6rqEu794iVVtdtU4zDpliRJ0ipzrHnJjDFp0p1kG+BY4MFAAcur6iOjDkySumK5J2m+M+kevkFquu8C/rqqfphkE+CcJN8YN5KPJM0llnuS5jWT7uGbNOluu0S5sv18c5ILaNq2ePORNCdZ7kmaz2xeMhpTatPdvsH5ROD7owhGkmYayz1J85FJ9/ANPAx821n4F4E3V9VNa1h+0NgQnLfees0wY5SkTkyl3Lvm2munP0BJ0qwxUE13kvVobjzHVdWX1rROVS2nGQaTrbdeVkOLUJI6MNVyb9mTn2y5J2lOsHnJaAzSe0mATwEXVNWHRx+SJHXLck/SfGfSPXyD1HQ/HdgX+EmSc9t572o7GpekuchyT9K8ZtI9fIP0XvIdmiEuJWlesNyTNJ/ZvGQ0HJFSkiRJfUy6h8+kW5IkSatY0z0aA3cZKEmSJOm+saZbkiRJfazpHj6TbkmSJK1i85LRMOmWJElSH5Pu4TPpliRJUh+T7uEz6ZYkSdIqNi8ZDXsvkSRJkkbMmm5JkiT1saZ7+Ey6JUmStIrNS0bDpFuSJEl9TLqHbyRJ95ZL7uJv/uK6Uex6cAsXdnt84LLt39N1CAA8+Y0v7joEOPHEriOAl7yk6wjglFO6jqCxYkW3x7/55m6PPwq33ALf+U6nIWzxzGd2enyAX+z2uq5DAGCP7xzddQgcv8GBXYfAax/yH12HwOcvemHXIQDw9Kd3e/z11+/2+FNl0j181nRLkiRpFZuXjIZJtyRJkvqYdA+fXQZKkiRJI2ZNtyRJklaxeclomHRLkiSpj0n38Nm8RJIkSX3uuWd2TINIsnuSC5NclOSda1i+XZJvJvlxkhVJlvYsuzvJue10cs/8hyb5frvPzyeZtNs8k25JkiStMta8ZDZMk0myAPgYsAewI7BPkh3HrfYh4NiqejxwGPD+nmW/q6qd2ulFPfM/CBxRVTsAvwVePVksJt2SJEnq03UyPcSa7p2Bi6rq4qq6EzgB2HPcOjsC32o/n76G5X2SBNgNGBuE5NPAXpMFYtItSZKkuWpr4LKe7yvbeb1+BIyNoPdiYJMkW7TfN0hydpIzk4wl1lsAN1TVXRPs8158kVKSJEmrzLLeSxYnObvn+/KqWj7FfbwVODLJAcAZwOXA3e2y7arq8iQPA76V5CfAjfclUJNuSZIk9ZlFSfe1VbVsguWXA9v0fF/azlulqq6grelOsjHwp1V1Q7vs8vbPi5OsAJ4IfBFYlGTdtrb7XvtcE5uXSJIkqU/XbbWH2Kb7LODhbW8jC4G9gZN7V0iyOMlYTnwIcFQ7f7Mk64+tAzwd+GlVFU3b75e22+wPfGWyQCZNupMcleTqJOcNdGqSNMtZ7kmaz+ZS7yVtTfTBwGnABcAXqur8JIclGeuNZFfgwiQ/Bx4MHN7OfzRwdpIf0STZH6iqn7bL3gH8VZKLaNp4f2qyWAZpXnIMcCRw7ADrStJccAyWe5LmsVnUvGRSVXUqcOq4ee/t+Xwiq3si6V3nf4DHrWWfF9P0jDKwSZPuqjojyfZT2akkzWaWe5Lms1n2IuWsMbQ23UkOartUOfua664b1m4lacbqK/duvE8vs0uS5omh9V7Sds+yHGDZTjvVsPYrSTNVX7n3yEda7kmaM6zpHj67DJQkSVIfk+7hM+mWJEnSKrbpHo1Bugw8Hvge8MgkK5O8evRhSVJ3LPckzXdddwU4xH66Z4xBei/ZZzoCkaSZwnJP0nxmTfdoOCKlJEmSNGK26ZYkSVIfa7qHz6RbkiRJfUy6h8+kW5IkSavYpns0TLolSZLUx6R7+Ey6JUmStIo13aNh0i1JkqQ+Jt3DZ5eBkiRJ0ohZ0y1JkqQ+1nQPn0m3JEmSVrFN92iYdEuSJKmPSffwjSbpvuceuOWWkex6YIsXd3t8YJt1r+w6hMZ739t1BHDxxV1HwB0nn9Z1CKx/0zVdh9C47rpuj3/33d0efxTWXx8e9rBuY7j99m6PDzx88Z1dhwDAHX9+YNchsM/C6joELlv5wq5D4KkzJHlbutFvOz3+wgWzp9yzpns0rOmWJElSH5Pu4bP3EkmSJGnErOmWJElSH2u6h8+kW5IkSavYpns0TLolSZLUx6R7+Ey6JUmStIo13aNh0i1JkqQ+Jt3DZ9ItSZKkVazpHg27DJQkSZJGzJpuSZIk9bGme/is6ZYkSVKfe+6ZHdMgkuye5MIkFyV55xqWb5fkm0l+nGRFkqXt/J2SfC/J+e2yl/dsc0ySXyU5t512miwOa7olSZK0ylxq051kAfAx4NnASuCsJCdX1U97VvsQcGxVfTrJbsD7gX2B24D9quoXSbYCzklyWlXd0G73tqo6cdBYBqrpnuwXgiTNNZZ7kuazrmuwh1jTvTNwUVVdXFV3AicAe45bZ0fgW+3n08eWV9XPq+oX7ecrgKuBJff1mk6adPf8QtijDWqfJDve1wNK0kxnuSdpPhur6Z4N0wC2Bi7r+b6yndfrR8BL2s8vBjZJskXvCkl2BhYCv+yZfXjb7OSIJOtPFsggNd2D/EKQpLnEck/SvNZ1Mj2FpHtxkrN7poPuw+m+FfijJP8L/BFwOXD32MIkWwKfAQ6sqrFU/xDgUcBTgM2Bd0x2kEHadK/pF8Iu41dqT/IggG23Hv8DQpJmFcs9SZodrq2qZRMsvxzYpuf70nbeKm3TkZcAJNkY+NOxdttJHgicAry7qs7s2ebK9uMdSY6mSdwnNLTeS6pqeVUtq6plSzbffFi7laQZy3JP0lzVdQ32EJuXnAU8PMlDkywE9gZO7l0hyeIkYznxIcBR7fyFwEk0L1meOG6bLds/A+wFnDdZIIPUdE/6C0GS5hjLPUnz1lzqvaSq7kpyMHAasAA4qqrOT3IYcHZVnQzsCrw/SQFnAG9oN38Z8ExgiyQHtPMOqKpzgeOSLAECnAu8frJYBkm6V/1CoLnp7A38+UBnKkmzk+WepHltriTdAFV1KnDquHnv7fl8InCvrv+q6rPAZ9eyz92mGsekSffafiFM9UCSNFtY7kmaz+ZSTfdMMtDgOGv6hSBJc5nlnqT5zKR7+BwGXpIkSRoxh4GXJElSH2u6h8+kW5IkSavYpns0TLolSZLUx6R7+Ey6JUmStIo13aNh0i1JkqQ+Jt3DZ9ItSZKkPibdw2eXgZIkSdKIWdMtSZKkVWzTPRom3ZIkSepj0j18Jt2SJElaxZru0UhVDX+nyTXApfdjF4uBa4cUjjHcfzMhDmOYWzFsV1VLhhHMTGG5N1QzIQ5jMIZhxzBryr31119WW211dtdhDOSSS3JOVS3rOo5BjKSm+/7+o0pydtcX0BhmVhzGYAwzneXe3IrDGIxhpsUw3azpHj57L5EkSZJGzDbdkiRJWsU23aMxU5Pu5V0HgDH0mglxGEPDGOaumXBdZ0IMMDPiMIaGMTRmQgzTyqR7+EbyIqUkSZJmp/XWW1aLF8+OFymvumqev0gpSZKk2cua7uGbcS9SJtk9yYVJLkryzg6Of1SSq5OcN93H7olhmySnJ/lpkvOTvKmDGDZI8oMkP2pj+LvpjqEnlgVJ/jfJf3Z0/EuS/CTJuUk6++mfZFGSE5P8LMkFSZ42zcd/ZHsNxqabkrx5OmOYqyz3LPfWEEun5V4bQ+dln+Ved+65Z3ZMs8mMal6SZAHwc+DZwErgLGCfqvrpNMbwTOAW4Niqeux0HXdcDFsCW1bVD5NsApwD7DXN1yHARlV1S5L1gO8Ab6qqM6crhp5Y/gpYBjywql7QwfEvAZZVVaf9xCb5NPDfVfXJJAuBDavqho5iWQBcDuxSVfenb+p5z3JvVQyWe/2xdFrutTFcQsdln+VeN9Zdd1ltuunsaF5y/fWzp3nJTKvp3hm4qKourqo7gROAPaczgKo6A7h+Oo+5hhiurKoftp9vBi4Atp7mGKqqbmm/rtdO0/4LLclS4PnAJ6f72DNJkk2BZwKfAqiqO7u68bSeBfxyrt94ponlHpZ7vSz3GpZ7mmtmWtK9NXBZz/eVTHOhO9Mk2R54IvD9Do69IMm5wNXAN6pq2mMA/gl4O9DlQ6QCvp7knCQHdRTDQ4FrgKPbR86fTLJRR7EA7A0c3+Hx5xLLvXEs92ZEuQfdl32Wex3qutnIXGxeMtOSbvVIsjHwReDNVXXTdB+/qu6uqp2ApcDOSab1sXOSFwBXV9U503ncNXhGVT0J2AN4Q/sofrqtCzwJ+HhVPRG4FZj2tr8A7SPeFwH/3sXxNbdZ7s2Ycg+6L/ss9zoy1k/3bJhmk5mWdF8ObNPzfWk7b95p2xN+ETiuqr7UZSzt47zTgd2n+dBPB17Utis8AdgtyWenOQaq6vL2z6uBk2iaA0y3lcDKnlq3E2luRl3YA/hhVf2mo+PPNZZ7Lcs9YIaUezAjyj7LvQ51nUybdI/eWcDDkzy0/VW5N3ByxzFNu/Zlnk8BF1TVhzuKYUmSRe3nB9C85PWz6Yyhqg6pqqVVtT3Nv4VvVdUrpzOGJBu1L3XRPtZ8DjDtPTxU1VXAZUke2c56FjBtL5iNsw/z6BHrNLDcw3JvzEwo92BmlH2We93qOpmei0n3jOqnu6ruSnIwcBqwADiqqs6fzhiSHA/sCixOshI4tKo+NZ0x0NR07Av8pG1bCPCuqjp1GmPYEvh0+7b2OsAXqqqzrqs69GDgpCYfYF3gc1X1tY5i+UvguDYxuxg4cLoDaG++zwZeN93Hnqss91ax3JtZZkrZZ7nXAYeBH40Z1WWgJEmSurXOOstq/fVnR5eBt99ul4GSJEmapbpuNjLM5iWZZACyJNsl+WaSHydZ0XbbObZs/yS/aKf9e+Y/Oc3gURcl+WjbRG5CJt2SJElaZS71XtI2F/sYzcuwOwL7JNlx3Gofohkc7PHAYcD72203Bw4FdqF5kfjQJJu123wceC3w8Haa9KVrk25JkiT16TqZHmJN9yADkO0IfKv9fHrP8ufS9Nd/fVX9FvgGsHs7gu4Dq+rMatppHwvsNVkgM+pFSkmSJHVvDr1IuaYByHYZt86PgJcAHwFeDGySZIu1bLt1O61cw/wJmXRLkiSpxzmnQRZ3HcWANkjS+9bn8qpaPsV9vBU4MskBwBk0YyXcPaT4VjHpliRJ0ipVNd2DQo3SpAOQVdUVNDXdY6Pi/mlV3ZDkcpruVHu3XdFuv3Tc/EkHNbNNtyRJkuaqSQcgS7I4yVhOfAhwVPv5NOA5STZrX6B8DnBaVV0J3JTkqW2vJfsBX5ksEJNuSZIkzUlVdRcwNgDZBTSDXp2f5LAkL2pX2xW4MMnPaQaGOrzd9nrg72kS97OAw9p5AH8BfBK4CPgl8NXJYnFwHEmSJGnErOmWJEmSRsykW5IkSRoxk25JkiRpxEy6JUmSpBEz6ZYkSZJGzKRbkiRJGjGTbkmSJGnETLolSZKkEfv/AaNFf9tV0ZDyAAAAAElFTkSuQmCC\n", "text/plain": [ - "" + "" ] }, "metadata": {}, @@ -1520,9 +1417,9 @@ ], "metadata": { "kernelspec": { - "display_name": "Python 3", + "display_name": "openmc", "language": "python", - "name": "python3" + "name": "openmc" }, "language_info": { "codemirror_mode": { @@ -1534,9 +1431,9 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.6.0" + "version": "3.6.5" } }, "nbformat": 4, - "nbformat_minor": 0 + "nbformat_minor": 1 } diff --git a/examples/jupyter/mgxs-part-iii.ipynb b/examples/jupyter/mgxs-part-iii.ipynb index 450276c89f..4171486a81 100644 --- a/examples/jupyter/mgxs-part-iii.ipynb +++ b/examples/jupyter/mgxs-part-iii.ipynb @@ -24,17 +24,15 @@ { "cell_type": "code", "execution_count": 1, - "metadata": { - "collapsed": false - }, + "metadata": {}, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ - "/home/wbinventor/miniconda3/lib/python3.5/site-packages/matplotlib/__init__.py:1350: UserWarning: This call to matplotlib.use() has no effect\n", - "because the backend has already been chosen;\n", - "matplotlib.use() must be called *before* pylab, matplotlib.pyplot,\n", + "/home/nelsonag/python/openmc/lib/python3.6/site-packages/matplotlib/__init__.py:1405: UserWarning: \n", + "This call to matplotlib.use() has no effect because the backend has already\n", + "been chosen; matplotlib.use() must be called *before* pylab, matplotlib.pyplot,\n", "or matplotlib.backends is imported for the first time.\n", "\n", " warnings.warn(_use_error_msg)\n" @@ -68,10 +66,8 @@ }, { "cell_type": "code", - "execution_count": 3, - "metadata": { - "collapsed": true - }, + "execution_count": 2, + "metadata": {}, "outputs": [], "source": [ "# 1.6 enriched fuel\n", @@ -103,10 +99,8 @@ }, { "cell_type": "code", - "execution_count": 4, - "metadata": { - "collapsed": true - }, + "execution_count": 3, + "metadata": {}, "outputs": [], "source": [ "# Instantiate a Materials object\n", @@ -125,10 +119,8 @@ }, { "cell_type": "code", - "execution_count": 5, - "metadata": { - "collapsed": true - }, + "execution_count": 4, + "metadata": {}, "outputs": [], "source": [ "# Create cylinders for the fuel and clad\n", @@ -153,10 +145,8 @@ }, { "cell_type": "code", - "execution_count": 6, - "metadata": { - "collapsed": true - }, + "execution_count": 5, + "metadata": {}, "outputs": [], "source": [ "# Create a Universe to encapsulate a fuel pin\n", @@ -190,10 +180,8 @@ }, { "cell_type": "code", - "execution_count": 7, - "metadata": { - "collapsed": true - }, + "execution_count": 6, + "metadata": {}, "outputs": [], "source": [ "# Create a Universe to encapsulate a control rod guide tube\n", @@ -227,10 +215,8 @@ }, { "cell_type": "code", - "execution_count": 8, - "metadata": { - "collapsed": true - }, + "execution_count": 7, + "metadata": {}, "outputs": [], "source": [ "# Create fuel assembly Lattice\n", @@ -248,10 +234,8 @@ }, { "cell_type": "code", - "execution_count": 9, - "metadata": { - "collapsed": true - }, + "execution_count": 8, + "metadata": {}, "outputs": [], "source": [ "# Create array indices for guide tube locations in lattice\n", @@ -280,10 +264,8 @@ }, { "cell_type": "code", - "execution_count": 10, - "metadata": { - "collapsed": true - }, + "execution_count": 9, + "metadata": {}, "outputs": [], "source": [ "# Create root Cell\n", @@ -307,10 +289,8 @@ }, { "cell_type": "code", - "execution_count": 11, - "metadata": { - "collapsed": true - }, + "execution_count": 10, + "metadata": {}, "outputs": [], "source": [ "# Create Geometry and set root Universe\n", @@ -319,10 +299,8 @@ }, { "cell_type": "code", - "execution_count": 12, - "metadata": { - "collapsed": true - }, + "execution_count": 11, + "metadata": {}, "outputs": [], "source": [ "# Export to \"geometry.xml\"\n", @@ -338,16 +316,14 @@ }, { "cell_type": "code", - "execution_count": 13, - "metadata": { - "collapsed": false - }, + "execution_count": 12, + "metadata": {}, "outputs": [], "source": [ "# OpenMC simulation parameters\n", "batches = 50\n", "inactive = 10\n", - "particles = 2500\n", + "particles = 10000\n", "\n", "# Instantiate a Settings object\n", "settings_file = openmc.Settings()\n", @@ -374,10 +350,8 @@ }, { "cell_type": "code", - "execution_count": 14, - "metadata": { - "collapsed": true - }, + "execution_count": 13, + "metadata": {}, "outputs": [], "source": [ "# Instantiate a Plot\n", @@ -402,22 +376,9 @@ }, { "cell_type": "code", - "execution_count": 15, - "metadata": { - "collapsed": false - }, - "outputs": [ - { - "data": { - "text/plain": [ - "0" - ] - }, - "execution_count": 15, - "metadata": {}, - "output_type": "execute_result" - } - ], + "execution_count": 14, + "metadata": {}, + "outputs": [], "source": [ "# Run openmc in plotting mode\n", "openmc.plot_geometry(output=False)" @@ -425,19 +386,17 @@ }, { "cell_type": "code", - "execution_count": 16, - "metadata": { - "collapsed": false - }, + "execution_count": 15, + "metadata": {}, "outputs": [ { "data": { - "image/png": "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\n", + "image/png": "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\n", "text/plain": [ "" ] }, - "execution_count": 16, + "execution_count": 15, "metadata": {}, "output_type": "execute_result" } @@ -473,10 +432,8 @@ }, { "cell_type": "code", - "execution_count": 17, - "metadata": { - "collapsed": false - }, + "execution_count": 16, + "metadata": {}, "outputs": [], "source": [ "# Instantiate a 2-group EnergyGroups object\n", @@ -493,10 +450,8 @@ }, { "cell_type": "code", - "execution_count": 18, - "metadata": { - "collapsed": false - }, + "execution_count": 17, + "metadata": {}, "outputs": [], "source": [ "# Initialize a 2-group MGXS Library for OpenMOC\n", @@ -526,21 +481,19 @@ "* `ChiDelayed` (`\"chi-delayed\"`)\n", "* `Beta` (`\"beta\"`)\n", "\n", - "In this case, let's create the multi-group cross sections needed to run an OpenMOC simulation to verify the accuracy of our cross sections. In particular, we will define `\"transport\"`, `\"nu-fission\"`, `'\"fission\"`, `\"nu-scatter matrix\"` and `\"chi\"` cross sections for our `Library`.\n", + "In this case, let's create the multi-group cross sections needed to run an OpenMOC simulation to verify the accuracy of our cross sections. In particular, we will define `\"nu-transport\"`, `\"nu-fission\"`, `'\"fission\"`, `\"nu-scatter matrix\"` and `\"chi\"` cross sections for our `Library`.\n", "\n", "**Note**: A variety of different approximate transport-corrected total multi-group cross sections (and corresponding scattering matrices) can be found in the literature. At the present time, the `openmc.mgxs` module only supports the `\"P0\"` transport correction. This correction can be turned on and off through the boolean `Library.correction` property which may take values of `\"P0\"` (default) or `None`." ] }, { "cell_type": "code", - "execution_count": 19, - "metadata": { - "collapsed": false - }, + "execution_count": 18, + "metadata": {}, "outputs": [], "source": [ "# Specify multi-group cross section types to compute\n", - "mgxs_lib.mgxs_types = ['transport', 'nu-fission', 'fission', 'nu-scatter matrix', 'chi']" + "mgxs_lib.mgxs_types = ['nu-transport', 'nu-fission', 'fission', 'nu-scatter matrix', 'chi']" ] }, { @@ -554,10 +507,8 @@ }, { "cell_type": "code", - "execution_count": 20, - "metadata": { - "collapsed": true - }, + "execution_count": 19, + "metadata": {}, "outputs": [], "source": [ "# Specify a \"cell\" domain type for the cross section tally filters\n", @@ -576,10 +527,8 @@ }, { "cell_type": "code", - "execution_count": 21, - "metadata": { - "collapsed": true - }, + "execution_count": 20, + "metadata": {}, "outputs": [], "source": [ "# Compute cross sections on a nuclide-by-nuclide basis\n", @@ -595,10 +544,8 @@ }, { "cell_type": "code", - "execution_count": 22, - "metadata": { - "collapsed": true - }, + "execution_count": 21, + "metadata": {}, "outputs": [], "source": [ "# Construct all tallies needed for the multi-group cross section library\n", @@ -616,10 +563,8 @@ }, { "cell_type": "code", - "execution_count": 23, - "metadata": { - "collapsed": true - }, + "execution_count": 22, + "metadata": {}, "outputs": [], "source": [ "# Create a \"tallies.xml\" file for the MGXS Library\n", @@ -636,10 +581,8 @@ }, { "cell_type": "code", - "execution_count": 24, - "metadata": { - "collapsed": false - }, + "execution_count": 23, + "metadata": {}, "outputs": [], "source": [ "# Instantiate a tally Mesh\n", @@ -663,11 +606,32 @@ }, { "cell_type": "code", - "execution_count": 25, - "metadata": { - "collapsed": true - }, - "outputs": [], + "execution_count": 24, + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "/home/nelsonag/git/openmc/openmc/mixin.py:71: IDWarning: Another Filter instance already exists with id=126.\n", + " warn(msg, IDWarning)\n", + "/home/nelsonag/git/openmc/openmc/mixin.py:71: IDWarning: Another Filter instance already exists with id=21.\n", + " warn(msg, IDWarning)\n", + "/home/nelsonag/git/openmc/openmc/mixin.py:71: IDWarning: Another Filter instance already exists with id=2.\n", + " warn(msg, IDWarning)\n", + "/home/nelsonag/git/openmc/openmc/mixin.py:71: IDWarning: Another Filter instance already exists with id=3.\n", + " warn(msg, IDWarning)\n", + "/home/nelsonag/git/openmc/openmc/mixin.py:71: IDWarning: Another Filter instance already exists with id=4.\n", + " warn(msg, IDWarning)\n", + "/home/nelsonag/git/openmc/openmc/mixin.py:71: IDWarning: Another Filter instance already exists with id=96.\n", + " warn(msg, IDWarning)\n", + "/home/nelsonag/git/openmc/openmc/mixin.py:71: IDWarning: Another Filter instance already exists with id=15.\n", + " warn(msg, IDWarning)\n", + "/home/nelsonag/git/openmc/openmc/mixin.py:71: IDWarning: Another Filter instance already exists with id=114.\n", + " warn(msg, IDWarning)\n" + ] + } + ], "source": [ "# Export all tallies to a \"tallies.xml\" file\n", "tallies_file.export_to_xml()" @@ -675,10 +639,8 @@ }, { "cell_type": "code", - "execution_count": 26, - "metadata": { - "collapsed": false - }, + "execution_count": 25, + "metadata": {}, "outputs": [ { "name": "stdout", @@ -710,137 +672,111 @@ " %%%%%%%%%%%\n", "\n", " | The OpenMC Monte Carlo Code\n", - " Copyright | 2011-2017 Massachusetts Institute of Technology\n", + " Copyright | 2011-2018 Massachusetts Institute of Technology\n", " License | http://openmc.readthedocs.io/en/latest/license.html\n", - " Version | 0.8.0\n", - " Git SHA1 | 647bf77a57a3cc5cce24b39cb192e1b99f52e499\n", - " Date/Time | 2017-02-27 14:21:38\n", - " OpenMP Threads | 4\n", - "\n", - " ===========================================================================\n", - " ========================> INITIALIZATION <=========================\n", - " ===========================================================================\n", + " Version | 0.10.0\n", + " Git SHA1 | 6c2d82a4d7dfe10312329d5969568fc03a698416\n", + " Date/Time | 2018-04-24 19:20:48\n", + " OpenMP Threads | 8\n", "\n", " Reading settings XML file...\n", - " Reading geometry XML file...\n", - " Reading materials XML file...\n", " Reading cross sections XML file...\n", - " Reading U235 from\n", - " /home/wbinventor/Documents/NSE-CRPG-Codes/openmc/data/nndc_hdf5/U235.h5\n", - " Reading U238 from\n", - " /home/wbinventor/Documents/NSE-CRPG-Codes/openmc/data/nndc_hdf5/U238.h5\n", - " Reading O16 from\n", - " /home/wbinventor/Documents/NSE-CRPG-Codes/openmc/data/nndc_hdf5/O16.h5\n", - " Reading H1 from\n", - " /home/wbinventor/Documents/NSE-CRPG-Codes/openmc/data/nndc_hdf5/H1.h5\n", - " Reading B10 from\n", - " /home/wbinventor/Documents/NSE-CRPG-Codes/openmc/data/nndc_hdf5/B10.h5\n", - " Reading Zr90 from\n", - " /home/wbinventor/Documents/NSE-CRPG-Codes/openmc/data/nndc_hdf5/Zr90.h5\n", + " Reading materials XML file...\n", + " Reading geometry XML file...\n", + " Building neighboring cells lists for each surface...\n", + " Reading U235 from /opt/xsdata/nndc/U235.h5\n", + " Reading U238 from /opt/xsdata/nndc/U238.h5\n", + " Reading O16 from /opt/xsdata/nndc/O16.h5\n", + " Reading H1 from /opt/xsdata/nndc/H1.h5\n", + " Reading B10 from /opt/xsdata/nndc/B10.h5\n", + " Reading Zr90 from /opt/xsdata/nndc/Zr90.h5\n", " Maximum neutron transport energy: 2.00000E+07 eV for U235\n", " Reading tallies XML file...\n", - " Building neighboring cells lists for each surface...\n", + " Writing summary.h5 file...\n", " Initializing source particles...\n", "\n", - " ===========================================================================\n", " ====================> K EIGENVALUE SIMULATION <====================\n", - " ===========================================================================\n", "\n", " Bat./Gen. k Average k \n", " ========= ======== ==================== \n", - " 1/1 1.03852 \n", - " 2/1 0.99743 \n", - " 3/1 1.02987 \n", - " 4/1 1.04397 \n", - " 5/1 1.06262 \n", - " 6/1 1.06657 \n", - " 7/1 0.98574 \n", - " 8/1 1.04364 \n", - " 9/1 1.01253 \n", - " 10/1 1.02094 \n", - " 11/1 0.99586 \n", - " 12/1 1.00508 1.00047 +/- 0.00461\n", - " 13/1 1.05292 1.01795 +/- 0.01769\n", - " 14/1 1.04732 1.02530 +/- 0.01450\n", - " 15/1 1.04886 1.03001 +/- 0.01218\n", - " 16/1 1.00948 1.02659 +/- 0.01052\n", - " 17/1 1.02684 1.02662 +/- 0.00889\n", - " 18/1 0.97234 1.01984 +/- 0.01026\n", - " 19/1 0.99754 1.01736 +/- 0.00938\n", - " 20/1 0.98964 1.01459 +/- 0.00884\n", - " 21/1 1.04140 1.01703 +/- 0.00836\n", - " 22/1 1.03854 1.01882 +/- 0.00784\n", - " 23/1 1.05917 1.02192 +/- 0.00785\n", - " 24/1 1.02413 1.02208 +/- 0.00727\n", - " 25/1 1.03113 1.02268 +/- 0.00679\n", - " 26/1 1.05113 1.02446 +/- 0.00660\n", - " 27/1 1.03252 1.02494 +/- 0.00622\n", - " 28/1 1.05196 1.02644 +/- 0.00605\n", - " 29/1 0.99663 1.02487 +/- 0.00593\n", - " 30/1 1.01820 1.02454 +/- 0.00564\n", - " 31/1 1.02753 1.02468 +/- 0.00537\n", - " 32/1 1.02162 1.02454 +/- 0.00512\n", - " 33/1 1.04083 1.02525 +/- 0.00494\n", - " 34/1 1.03335 1.02558 +/- 0.00474\n", - " 35/1 1.01304 1.02508 +/- 0.00458\n", - " 36/1 0.99299 1.02385 +/- 0.00457\n", - " 37/1 1.04936 1.02479 +/- 0.00450\n", - " 38/1 1.02856 1.02493 +/- 0.00433\n", - " 39/1 1.03706 1.02535 +/- 0.00420\n", - " 40/1 1.08118 1.02721 +/- 0.00447\n", - " 41/1 1.00149 1.02638 +/- 0.00440\n", - " 42/1 1.00233 1.02563 +/- 0.00433\n", - " 43/1 1.03023 1.02577 +/- 0.00419\n", - " 44/1 1.03230 1.02596 +/- 0.00407\n", - " 45/1 0.98123 1.02468 +/- 0.00416\n", - " 46/1 1.02126 1.02458 +/- 0.00404\n", - " 47/1 0.99772 1.02386 +/- 0.00400\n", - " 48/1 1.02773 1.02396 +/- 0.00389\n", - " 49/1 1.01690 1.02378 +/- 0.00379\n", - " 50/1 1.02890 1.02391 +/- 0.00370\n", + " 1/1 1.03784 \n", + " 2/1 1.02297 \n", + " 3/1 1.02244 \n", + " 4/1 1.02344 \n", + " 5/1 1.02057 \n", + " 6/1 1.04077 \n", + " 7/1 1.00795 \n", + " 8/1 1.02418 \n", + " 9/1 1.02241 \n", + " 10/1 1.03731 \n", + " 11/1 1.01477 \n", + " 12/1 1.05315 1.03396 +/- 0.01919\n", + " 13/1 1.02824 1.03205 +/- 0.01124\n", + " 14/1 1.02858 1.03118 +/- 0.00800\n", + " 15/1 1.02176 1.02930 +/- 0.00647\n", + " 16/1 1.06046 1.03449 +/- 0.00741\n", + " 17/1 1.02066 1.03252 +/- 0.00657\n", + " 18/1 1.03088 1.03231 +/- 0.00569\n", + " 19/1 1.02021 1.03097 +/- 0.00520\n", + " 20/1 1.02717 1.03059 +/- 0.00466\n", + " 21/1 1.03455 1.03095 +/- 0.00423\n", + " 22/1 1.02917 1.03080 +/- 0.00387\n", + " 23/1 1.02800 1.03058 +/- 0.00356\n", + " 24/1 1.02935 1.03050 +/- 0.00330\n", + " 25/1 1.01612 1.02954 +/- 0.00322\n", + " 26/1 1.00549 1.02803 +/- 0.00336\n", + " 27/1 1.02824 1.02805 +/- 0.00316\n", + " 28/1 1.01487 1.02731 +/- 0.00307\n", + " 29/1 1.05544 1.02879 +/- 0.00326\n", + " 30/1 1.00467 1.02759 +/- 0.00332\n", + " 31/1 1.03942 1.02815 +/- 0.00321\n", + " 32/1 1.02587 1.02805 +/- 0.00306\n", + " 33/1 1.02938 1.02811 +/- 0.00292\n", + " 34/1 1.02838 1.02812 +/- 0.00280\n", + " 35/1 1.00052 1.02701 +/- 0.00290\n", + " 36/1 1.01722 1.02664 +/- 0.00281\n", + " 37/1 1.01881 1.02635 +/- 0.00272\n", + " 38/1 1.03928 1.02681 +/- 0.00266\n", + " 39/1 1.03802 1.02720 +/- 0.00260\n", + " 40/1 1.00710 1.02653 +/- 0.00260\n", + " 41/1 1.02558 1.02650 +/- 0.00251\n", + " 42/1 1.03499 1.02676 +/- 0.00245\n", + " 43/1 1.01128 1.02629 +/- 0.00242\n", + " 44/1 1.00442 1.02565 +/- 0.00243\n", + " 45/1 1.03444 1.02590 +/- 0.00238\n", + " 46/1 1.01799 1.02568 +/- 0.00232\n", + " 47/1 1.00814 1.02521 +/- 0.00231\n", + " 48/1 1.00500 1.02467 +/- 0.00231\n", + " 49/1 1.01960 1.02454 +/- 0.00225\n", + " 50/1 1.02431 1.02454 +/- 0.00219\n", " Creating state point statepoint.50.h5...\n", "\n", - " ===========================================================================\n", - " ======================> SIMULATION FINISHED <======================\n", - " ===========================================================================\n", - "\n", - "\n", " =======================> TIMING STATISTICS <=======================\n", "\n", - " Total time for initialization = 3.4887E-01 seconds\n", - " Reading cross sections = 2.1990E-01 seconds\n", - " Total time in simulation = 3.2195E+01 seconds\n", - " Time in transport only = 3.1778E+01 seconds\n", - " Time in inactive batches = 1.9903E+00 seconds\n", - " Time in active batches = 3.0205E+01 seconds\n", - " Time synchronizing fission bank = 5.9614E-03 seconds\n", - " Sampling source sites = 4.8344E-03 seconds\n", - " SEND/RECV source sites = 1.0392E-03 seconds\n", - " Time accumulating tallies = 1.5849E-03 seconds\n", - " Total time for finalization = 3.9664E-05 seconds\n", - " Total time elapsed = 3.2560E+01 seconds\n", - " Calculation Rate (inactive) = 12561.1 neutrons/second\n", - " Calculation Rate (active) = 3310.69 neutrons/second\n", + " Total time for initialization = 2.8179E-01 seconds\n", + " Reading cross sections = 2.5741E-01 seconds\n", + " Total time in simulation = 2.5787E+01 seconds\n", + " Time in transport only = 2.5724E+01 seconds\n", + " Time in inactive batches = 1.7591E+00 seconds\n", + " Time in active batches = 2.4028E+01 seconds\n", + " Time synchronizing fission bank = 1.3217E-02 seconds\n", + " Sampling source sites = 1.0464E-02 seconds\n", + " SEND/RECV source sites = 2.6486E-03 seconds\n", + " Time accumulating tallies = 2.7351E-04 seconds\n", + " Total time for finalization = 5.5454E-05 seconds\n", + " Total time elapsed = 2.6109E+01 seconds\n", + " Calculation Rate (inactive) = 56847.1 neutrons/second\n", + " Calculation Rate (active) = 16647.3 neutrons/second\n", "\n", " ============================> RESULTS <============================\n", "\n", - " k-effective (Collision) = 1.02621 +/- 0.00393\n", - " k-effective (Track-length) = 1.02391 +/- 0.00370\n", - " k-effective (Absorption) = 1.02077 +/- 0.00423\n", - " Combined k-effective = 1.02331 +/- 0.00353\n", + " k-effective (Collision) = 1.02204 +/- 0.00176\n", + " k-effective (Track-length) = 1.02454 +/- 0.00219\n", + " k-effective (Absorption) = 1.02370 +/- 0.00186\n", + " Combined k-effective = 1.02329 +/- 0.00157\n", " Leakage Fraction = 0.00000 +/- 0.00000\n", "\n" ] - }, - { - "data": { - "text/plain": [ - "0" - ] - }, - "execution_count": 26, - "metadata": {}, - "output_type": "execute_result" } ], "source": [ @@ -864,10 +800,8 @@ }, { "cell_type": "code", - "execution_count": 27, - "metadata": { - "collapsed": false - }, + "execution_count": 26, + "metadata": {}, "outputs": [], "source": [ "# Load the last statepoint file\n", @@ -883,10 +817,8 @@ }, { "cell_type": "code", - "execution_count": 28, - "metadata": { - "collapsed": false - }, + "execution_count": 27, + "metadata": {}, "outputs": [], "source": [ "# Initialize MGXS Library with OpenMC statepoint data\n", @@ -918,10 +850,8 @@ }, { "cell_type": "code", - "execution_count": 29, - "metadata": { - "collapsed": false - }, + "execution_count": 28, + "metadata": {}, "outputs": [], "source": [ "# Retrieve the NuFissionXS object for the fuel cell from the library\n", @@ -938,23 +868,26 @@ }, { "cell_type": "code", - "execution_count": 30, - "metadata": { - "collapsed": false - }, + "execution_count": 29, + "metadata": {}, "outputs": [ - { - "name": "stderr", - "output_type": "stream", - "text": [ - "/home/wbinventor/Documents/NSE-CRPG-Codes/openmc/openmc/tallies.py:1835: RuntimeWarning: invalid value encountered in true_divide\n", - " self_rel_err = data['self']['std. dev.'] / data['self']['mean']\n" - ] - }, { "data": { "text/html": [ "
\n", + "\n", "\n", " \n", " \n", @@ -969,23 +902,23 @@ " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", - " \n", - " \n", + " \n", + " \n", " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", - " \n", - " \n", + " \n", + " \n", " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", @@ -993,23 +926,23 @@ " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", - " \n", - " \n", + " \n", + " \n", " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", - " \n", - " \n", + " \n", + " \n", " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", @@ -1020,16 +953,16 @@ "" ], "text/plain": [ - " cell group in nuclide mean std. dev.\n", - "3 10000 1 U235 8.096764e-03 3.130177e-05\n", - "4 10000 1 U238 7.364515e-03 4.510564e-05\n", - "5 10000 1 O16 0.000000e+00 0.000000e+00\n", - "0 10000 2 U235 3.611153e-01 2.048312e-03\n", - "1 10000 2 U238 6.735070e-07 3.780177e-09\n", - "2 10000 2 O16 0.000000e+00 0.000000e+00" + " cell group in nuclide mean std. dev.\n", + "3 1 1 U235 8.093482e-03 1.597406e-05\n", + "4 1 1 U238 7.347745e-03 2.082526e-05\n", + "5 1 1 O16 0.000000e+00 0.000000e+00\n", + "0 1 2 U235 3.615911e-01 1.206052e-03\n", + "1 1 2 U238 6.743056e-07 2.229534e-09\n", + "2 1 2 O16 0.000000e+00 0.000000e+00" ] }, - "execution_count": 30, + "execution_count": 29, "metadata": {}, "output_type": "execute_result" } @@ -1048,10 +981,8 @@ }, { "cell_type": "code", - "execution_count": 31, - "metadata": { - "collapsed": false - }, + "execution_count": 30, + "metadata": {}, "outputs": [ { "name": "stdout", @@ -1060,16 +991,16 @@ "Multi-Group XS\n", "\tReaction Type =\tnu-fission\n", "\tDomain Type =\tcell\n", - "\tDomain ID =\t10000\n", + "\tDomain ID =\t1\n", "\tNuclide =\tU235\n", "\tCross Sections [cm^-1]:\n", - " Group 1 [0.625 - 20000000.0eV]:\t8.10e-03 +/- 3.87e-01%\n", - " Group 2 [0.0 - 0.625 eV]:\t3.61e-01 +/- 5.67e-01%\n", + " Group 1 [0.625 - 20000000.0eV]:\t8.09e-03 +/- 1.97e-01%\n", + " Group 2 [0.0 - 0.625 eV]:\t3.62e-01 +/- 3.34e-01%\n", "\n", "\tNuclide =\tU238\n", "\tCross Sections [cm^-1]:\n", - " Group 1 [0.625 - 20000000.0eV]:\t7.36e-03 +/- 6.12e-01%\n", - " Group 2 [0.0 - 0.625 eV]:\t6.74e-07 +/- 5.61e-01%\n", + " Group 1 [0.625 - 20000000.0eV]:\t7.35e-03 +/- 2.83e-01%\n", + " Group 2 [0.0 - 0.625 eV]:\t6.74e-07 +/- 3.31e-01%\n", "\n", "\tNuclide =\tO16\n", "\tCross Sections [cm^-1]:\n", @@ -1084,7 +1015,7 @@ "name": "stderr", "output_type": "stream", "text": [ - "/home/wbinventor/Documents/NSE-CRPG-Codes/openmc/openmc/tallies.py:1506: RuntimeWarning: invalid value encountered in true_divide\n", + "/home/nelsonag/git/openmc/openmc/tallies.py:1269: RuntimeWarning: invalid value encountered in true_divide\n", " data = self.std_dev[indices] / self.mean[indices]\n" ] } @@ -1102,24 +1033,9 @@ }, { "cell_type": "code", - "execution_count": 32, - "metadata": { - "collapsed": false - }, - "outputs": [ - { - "name": "stderr", - "output_type": "stream", - "text": [ - "/home/wbinventor/Documents/NSE-CRPG-Codes/openmc/openmc/tallies.py:1835: RuntimeWarning: invalid value encountered in true_divide\n", - " self_rel_err = data['self']['std. dev.'] / data['self']['mean']\n", - "/home/wbinventor/Documents/NSE-CRPG-Codes/openmc/openmc/tallies.py:1836: RuntimeWarning: invalid value encountered in true_divide\n", - " other_rel_err = data['other']['std. dev.'] / data['other']['mean']\n", - "/home/wbinventor/Documents/NSE-CRPG-Codes/openmc/openmc/tallies.py:1837: RuntimeWarning: invalid value encountered in true_divide\n", - " new_tally._mean = data['self']['mean'] / data['other']['mean']\n" - ] - } - ], + "execution_count": 31, + "metadata": {}, + "outputs": [], "source": [ "# Store the cross section data in an \"mgxs/mgxs.h5\" HDF5 binary file\n", "mgxs_lib.build_hdf5_store(filename='mgxs.h5', directory='mgxs')" @@ -1134,10 +1050,8 @@ }, { "cell_type": "code", - "execution_count": 33, - "metadata": { - "collapsed": true - }, + "execution_count": 32, + "metadata": {}, "outputs": [], "source": [ "# Store a Library and its MGXS objects in a pickled binary file \"mgxs/mgxs.pkl\"\n", @@ -1146,10 +1060,8 @@ }, { "cell_type": "code", - "execution_count": 34, - "metadata": { - "collapsed": true - }, + "execution_count": 33, + "metadata": {}, "outputs": [], "source": [ "# Instantiate a new MGXS Library from the pickled binary file \"mgxs/mgxs.pkl\"\n", @@ -1165,10 +1077,8 @@ }, { "cell_type": "code", - "execution_count": 35, - "metadata": { - "collapsed": false - }, + "execution_count": 34, + "metadata": {}, "outputs": [], "source": [ "# Create a 1-group structure\n", @@ -1180,23 +1090,26 @@ }, { "cell_type": "code", - "execution_count": 36, - "metadata": { - "collapsed": false - }, + "execution_count": 35, + "metadata": {}, "outputs": [ - { - "name": "stderr", - "output_type": "stream", - "text": [ - "/home/wbinventor/Documents/NSE-CRPG-Codes/openmc/openmc/tallies.py:1835: RuntimeWarning: invalid value encountered in true_divide\n", - " self_rel_err = data['self']['std. dev.'] / data['self']['mean']\n" - ] - }, { "data": { "text/html": [ "
\n", + "\n", "
31000011U2358.096764e-033.130177e-058.093482e-031.597406e-05
41000011U2387.364515e-034.510564e-057.347745e-032.082526e-05
51000011O160.000000e+00
01000012U2353.611153e-012.048312e-033.615911e-011.206052e-03
11000012U2386.735070e-073.780177e-096.743056e-072.229534e-09
21000012O160.000000e+00
\n", " \n", " \n", @@ -1211,23 +1124,23 @@ " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", - " \n", - " \n", + " \n", + " \n", " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", - " \n", - " \n", + " \n", + " \n", " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", @@ -1238,13 +1151,13 @@ "" ], "text/plain": [ - " cell group in nuclide mean std. dev.\n", - "0 10000 1 U235 0.074393 0.000308\n", - "1 10000 1 U238 0.005982 0.000036\n", - "2 10000 1 O16 0.000000 0.000000" + " cell group in nuclide mean std. dev.\n", + "0 1 1 U235 0.074672 0.000179\n", + "1 1 1 U238 0.005964 0.000017\n", + "2 1 1 O16 0.000000 0.000000" ] }, - "execution_count": 36, + "execution_count": 35, "metadata": {}, "output_type": "execute_result" } @@ -1273,10 +1186,8 @@ }, { "cell_type": "code", - "execution_count": 37, - "metadata": { - "collapsed": false - }, + "execution_count": 36, + "metadata": {}, "outputs": [], "source": [ "# Create an OpenMOC Geometry from the OpenMC Geometry\n", @@ -1292,24 +1203,9 @@ }, { "cell_type": "code", - "execution_count": 38, - "metadata": { - "collapsed": false - }, - "outputs": [ - { - "name": "stderr", - "output_type": "stream", - "text": [ - "/home/wbinventor/Documents/NSE-CRPG-Codes/openmc/openmc/tallies.py:1835: RuntimeWarning: invalid value encountered in true_divide\n", - " self_rel_err = data['self']['std. dev.'] / data['self']['mean']\n", - "/home/wbinventor/Documents/NSE-CRPG-Codes/openmc/openmc/tallies.py:1836: RuntimeWarning: invalid value encountered in true_divide\n", - " other_rel_err = data['other']['std. dev.'] / data['other']['mean']\n", - "/home/wbinventor/Documents/NSE-CRPG-Codes/openmc/openmc/tallies.py:1837: RuntimeWarning: invalid value encountered in true_divide\n", - " new_tally._mean = data['self']['mean'] / data['other']['mean']\n" - ] - } - ], + "execution_count": 37, + "metadata": {}, + "outputs": [], "source": [ "# Load the library into the OpenMOC geometry\n", "materials = load_openmc_mgxs_lib(mgxs_lib, openmoc_geometry)" @@ -1324,9 +1220,8 @@ }, { "cell_type": "code", - "execution_count": 39, + "execution_count": 38, "metadata": { - "collapsed": false, "scrolled": true }, "outputs": [ @@ -1336,131 +1231,131 @@ "text": [ "[ NORMAL ] Importing ray tracing data from file...\n", "[ NORMAL ] Computing the eigenvalue...\n", - "[ NORMAL ] Iteration 0:\tk_eff = 0.823793\tres = 0.000E+00\n", - "[ NORMAL ] Iteration 1:\tk_eff = 0.780554\tres = 1.938E-01\n", - "[ NORMAL ] Iteration 2:\tk_eff = 0.739678\tres = 6.539E-02\n", - "[ NORMAL ] Iteration 3:\tk_eff = 0.711003\tres = 5.285E-02\n", - "[ NORMAL ] Iteration 4:\tk_eff = 0.689738\tres = 3.931E-02\n", - "[ NORMAL ] Iteration 5:\tk_eff = 0.675038\tres = 3.014E-02\n", - "[ NORMAL ] Iteration 6:\tk_eff = 0.665753\tres = 2.147E-02\n", - "[ NORMAL ] Iteration 7:\tk_eff = 0.661013\tres = 1.389E-02\n", - "[ NORMAL ] Iteration 8:\tk_eff = 0.660052\tres = 7.293E-03\n", - "[ NORMAL ] Iteration 9:\tk_eff = 0.662216\tres = 2.057E-03\n", - "[ NORMAL ] Iteration 10:\tk_eff = 0.666942\tres = 3.576E-03\n", - "[ NORMAL ] Iteration 11:\tk_eff = 0.673743\tres = 7.278E-03\n", - "[ NORMAL ] Iteration 12:\tk_eff = 0.682202\tres = 1.030E-02\n", - "[ NORMAL ] Iteration 13:\tk_eff = 0.691961\tres = 1.264E-02\n", - "[ NORMAL ] Iteration 14:\tk_eff = 0.702715\tres = 1.438E-02\n", - "[ NORMAL ] Iteration 15:\tk_eff = 0.714203\tres = 1.561E-02\n", - "[ NORMAL ] Iteration 16:\tk_eff = 0.726205\tres = 1.641E-02\n", - "[ NORMAL ] Iteration 17:\tk_eff = 0.738532\tres = 1.686E-02\n", - "[ NORMAL ] Iteration 18:\tk_eff = 0.751030\tres = 1.703E-02\n", - "[ NORMAL ] Iteration 19:\tk_eff = 0.763567\tres = 1.697E-02\n", - "[ NORMAL ] Iteration 20:\tk_eff = 0.776034\tres = 1.674E-02\n", - "[ NORMAL ] Iteration 21:\tk_eff = 0.788344\tres = 1.637E-02\n", - "[ NORMAL ] Iteration 22:\tk_eff = 0.800423\tres = 1.591E-02\n", - "[ NORMAL ] Iteration 23:\tk_eff = 0.812215\tres = 1.536E-02\n", - "[ NORMAL ] Iteration 24:\tk_eff = 0.823673\tres = 1.477E-02\n", - "[ NORMAL ] Iteration 25:\tk_eff = 0.834764\tres = 1.415E-02\n", - "[ NORMAL ] Iteration 26:\tk_eff = 0.845462\tres = 1.350E-02\n", - "[ NORMAL ] Iteration 27:\tk_eff = 0.855748\tres = 1.285E-02\n", - "[ NORMAL ] Iteration 28:\tk_eff = 0.865611\tres = 1.220E-02\n", - "[ NORMAL ] Iteration 29:\tk_eff = 0.875045\tres = 1.156E-02\n", - "[ NORMAL ] Iteration 30:\tk_eff = 0.884048\tres = 1.093E-02\n", - "[ NORMAL ] Iteration 31:\tk_eff = 0.892623\tres = 1.032E-02\n", - "[ NORMAL ] Iteration 32:\tk_eff = 0.900775\tres = 9.727E-03\n", - "[ NORMAL ] Iteration 33:\tk_eff = 0.908511\tres = 9.158E-03\n", - "[ NORMAL ] Iteration 34:\tk_eff = 0.915841\tres = 8.613E-03\n", - "[ NORMAL ] Iteration 35:\tk_eff = 0.922778\tres = 8.092E-03\n", - "[ NORMAL ] Iteration 36:\tk_eff = 0.929332\tres = 7.596E-03\n", - "[ NORMAL ] Iteration 37:\tk_eff = 0.935519\tres = 7.124E-03\n", - "[ NORMAL ] Iteration 38:\tk_eff = 0.941351\tres = 6.676E-03\n", - "[ NORMAL ] Iteration 39:\tk_eff = 0.946843\tres = 6.253E-03\n", - "[ NORMAL ] Iteration 40:\tk_eff = 0.952011\tres = 5.852E-03\n", - "[ NORMAL ] Iteration 41:\tk_eff = 0.956869\tres = 5.474E-03\n", - "[ NORMAL ] Iteration 42:\tk_eff = 0.961431\tres = 5.118E-03\n", - "[ NORMAL ] Iteration 43:\tk_eff = 0.965712\tres = 4.783E-03\n", - "[ NORMAL ] Iteration 44:\tk_eff = 0.969727\tres = 4.467E-03\n", - "[ NORMAL ] Iteration 45:\tk_eff = 0.973489\tres = 4.170E-03\n", - "[ NORMAL ] Iteration 46:\tk_eff = 0.977013\tres = 3.892E-03\n", - "[ NORMAL ] Iteration 47:\tk_eff = 0.980310\tres = 3.631E-03\n", - "[ NORMAL ] Iteration 48:\tk_eff = 0.983394\tres = 3.386E-03\n", - "[ NORMAL ] Iteration 49:\tk_eff = 0.986277\tres = 3.156E-03\n", - "[ NORMAL ] Iteration 50:\tk_eff = 0.988971\tres = 2.942E-03\n", - "[ NORMAL ] Iteration 51:\tk_eff = 0.991487\tres = 2.740E-03\n", - "[ NORMAL ] Iteration 52:\tk_eff = 0.993835\tres = 2.552E-03\n", - "[ NORMAL ] Iteration 53:\tk_eff = 0.996026\tres = 2.376E-03\n", - "[ NORMAL ] Iteration 54:\tk_eff = 0.998069\tres = 2.212E-03\n", - "[ NORMAL ] Iteration 55:\tk_eff = 0.999974\tres = 2.059E-03\n", - "[ NORMAL ] Iteration 56:\tk_eff = 1.001749\tres = 1.915E-03\n", - "[ NORMAL ] Iteration 57:\tk_eff = 1.003403\tres = 1.782E-03\n", - "[ NORMAL ] Iteration 58:\tk_eff = 1.004943\tres = 1.657E-03\n", - "[ NORMAL ] Iteration 59:\tk_eff = 1.006377\tres = 1.540E-03\n", - "[ NORMAL ] Iteration 60:\tk_eff = 1.007711\tres = 1.432E-03\n", - "[ NORMAL ] Iteration 61:\tk_eff = 1.008952\tres = 1.331E-03\n", - "[ NORMAL ] Iteration 62:\tk_eff = 1.010107\tres = 1.237E-03\n", - "[ NORMAL ] Iteration 63:\tk_eff = 1.011181\tres = 1.149E-03\n", - "[ NORMAL ] Iteration 64:\tk_eff = 1.012179\tres = 1.067E-03\n", - "[ NORMAL ] Iteration 65:\tk_eff = 1.013107\tres = 9.909E-04\n", - "[ NORMAL ] Iteration 66:\tk_eff = 1.013969\tres = 9.201E-04\n", - "[ NORMAL ] Iteration 67:\tk_eff = 1.014769\tres = 8.542E-04\n", - "[ NORMAL ] Iteration 68:\tk_eff = 1.015513\tres = 7.929E-04\n", - "[ NORMAL ] Iteration 69:\tk_eff = 1.016204\tres = 7.358E-04\n", - "[ NORMAL ] Iteration 70:\tk_eff = 1.016845\tres = 6.828E-04\n", - "[ NORMAL ] Iteration 71:\tk_eff = 1.017440\tres = 6.335E-04\n", - "[ NORMAL ] Iteration 72:\tk_eff = 1.017993\tres = 5.877E-04\n", - "[ NORMAL ] Iteration 73:\tk_eff = 1.018505\tres = 5.451E-04\n", - "[ NORMAL ] Iteration 74:\tk_eff = 1.018980\tres = 5.056E-04\n", - "[ NORMAL ] Iteration 75:\tk_eff = 1.019422\tres = 4.688E-04\n", - "[ NORMAL ] Iteration 76:\tk_eff = 1.019831\tres = 4.347E-04\n", - "[ NORMAL ] Iteration 77:\tk_eff = 1.020210\tres = 4.030E-04\n", - "[ NORMAL ] Iteration 78:\tk_eff = 1.020562\tres = 3.736E-04\n", - "[ NORMAL ] Iteration 79:\tk_eff = 1.020888\tres = 3.463E-04\n", - "[ NORMAL ] Iteration 80:\tk_eff = 1.021190\tres = 3.209E-04\n", - "[ NORMAL ] Iteration 81:\tk_eff = 1.021471\tres = 2.974E-04\n", - "[ NORMAL ] Iteration 82:\tk_eff = 1.021730\tres = 2.756E-04\n", - "[ NORMAL ] Iteration 83:\tk_eff = 1.021971\tres = 2.553E-04\n", - "[ NORMAL ] Iteration 84:\tk_eff = 1.022194\tres = 2.365E-04\n", - "[ NORMAL ] Iteration 85:\tk_eff = 1.022400\tres = 2.191E-04\n", - "[ NORMAL ] Iteration 86:\tk_eff = 1.022592\tres = 2.030E-04\n", - "[ NORMAL ] Iteration 87:\tk_eff = 1.022769\tres = 1.880E-04\n", - "[ NORMAL ] Iteration 88:\tk_eff = 1.022933\tres = 1.741E-04\n", - "[ NORMAL ] Iteration 89:\tk_eff = 1.023085\tres = 1.612E-04\n", - "[ NORMAL ] Iteration 90:\tk_eff = 1.023226\tres = 1.493E-04\n", - "[ NORMAL ] Iteration 91:\tk_eff = 1.023356\tres = 1.382E-04\n", - "[ NORMAL ] Iteration 92:\tk_eff = 1.023477\tres = 1.279E-04\n", - "[ NORMAL ] Iteration 93:\tk_eff = 1.023588\tres = 1.184E-04\n", - "[ NORMAL ] Iteration 94:\tk_eff = 1.023692\tres = 1.097E-04\n", - "[ NORMAL ] Iteration 95:\tk_eff = 1.023788\tres = 1.015E-04\n", - "[ NORMAL ] Iteration 96:\tk_eff = 1.023876\tres = 9.392E-05\n", - "[ NORMAL ] Iteration 97:\tk_eff = 1.023958\tres = 8.694E-05\n", - "[ NORMAL ] Iteration 98:\tk_eff = 1.024034\tres = 8.045E-05\n", - "[ NORMAL ] Iteration 99:\tk_eff = 1.024104\tres = 7.446E-05\n", - "[ NORMAL ] Iteration 100:\tk_eff = 1.024169\tres = 6.890E-05\n", - "[ NORMAL ] Iteration 101:\tk_eff = 1.024229\tres = 6.374E-05\n", - "[ NORMAL ] Iteration 102:\tk_eff = 1.024285\tres = 5.897E-05\n", - "[ NORMAL ] Iteration 103:\tk_eff = 1.024336\tres = 5.457E-05\n", - "[ NORMAL ] Iteration 104:\tk_eff = 1.024384\tres = 5.049E-05\n", - "[ NORMAL ] Iteration 105:\tk_eff = 1.024428\tres = 4.672E-05\n", - "[ NORMAL ] Iteration 106:\tk_eff = 1.024469\tres = 4.321E-05\n", - "[ NORMAL ] Iteration 107:\tk_eff = 1.024506\tres = 3.994E-05\n", - "[ NORMAL ] Iteration 108:\tk_eff = 1.024541\tres = 3.696E-05\n", - "[ NORMAL ] Iteration 109:\tk_eff = 1.024574\tres = 3.418E-05\n", - "[ NORMAL ] Iteration 110:\tk_eff = 1.024603\tres = 3.164E-05\n", - "[ NORMAL ] Iteration 111:\tk_eff = 1.024631\tres = 2.925E-05\n", - "[ NORMAL ] Iteration 112:\tk_eff = 1.024657\tres = 2.705E-05\n", - "[ NORMAL ] Iteration 113:\tk_eff = 1.024680\tres = 2.501E-05\n", - "[ NORMAL ] Iteration 114:\tk_eff = 1.024702\tres = 2.313E-05\n", - "[ NORMAL ] Iteration 115:\tk_eff = 1.024722\tres = 2.140E-05\n", - "[ NORMAL ] Iteration 116:\tk_eff = 1.024741\tres = 1.981E-05\n", - "[ NORMAL ] Iteration 117:\tk_eff = 1.024758\tres = 1.827E-05\n", - "[ NORMAL ] Iteration 118:\tk_eff = 1.024774\tres = 1.690E-05\n", - "[ NORMAL ] Iteration 119:\tk_eff = 1.024789\tres = 1.564E-05\n", - "[ NORMAL ] Iteration 120:\tk_eff = 1.024802\tres = 1.445E-05\n", - "[ NORMAL ] Iteration 121:\tk_eff = 1.024815\tres = 1.338E-05\n", - "[ NORMAL ] Iteration 122:\tk_eff = 1.024827\tres = 1.236E-05\n", - "[ NORMAL ] Iteration 123:\tk_eff = 1.024837\tres = 1.142E-05\n", - "[ NORMAL ] Iteration 124:\tk_eff = 1.024847\tres = 1.057E-05\n" + "[ NORMAL ] Iteration 0:\tk_eff = 0.823436\tres = 0.000E+00\n", + "[ NORMAL ] Iteration 1:\tk_eff = 0.780042\tres = 1.941E-01\n", + "[ NORMAL ] Iteration 2:\tk_eff = 0.739063\tres = 6.559E-02\n", + "[ NORMAL ] Iteration 3:\tk_eff = 0.710328\tres = 5.301E-02\n", + "[ NORMAL ] Iteration 4:\tk_eff = 0.689038\tres = 3.942E-02\n", + "[ NORMAL ] Iteration 5:\tk_eff = 0.674339\tres = 3.021E-02\n", + "[ NORMAL ] Iteration 6:\tk_eff = 0.665075\tres = 2.149E-02\n", + "[ NORMAL ] Iteration 7:\tk_eff = 0.660373\tres = 1.387E-02\n", + "[ NORMAL ] Iteration 8:\tk_eff = 0.659460\tres = 7.242E-03\n", + "[ NORMAL ] Iteration 9:\tk_eff = 0.661679\tres = 1.995E-03\n", + "[ NORMAL ] Iteration 10:\tk_eff = 0.666463\tres = 3.649E-03\n", + "[ NORMAL ] Iteration 11:\tk_eff = 0.673324\tres = 7.367E-03\n", + "[ NORMAL ] Iteration 12:\tk_eff = 0.681842\tres = 1.039E-02\n", + "[ NORMAL ] Iteration 13:\tk_eff = 0.691660\tres = 1.273E-02\n", + "[ NORMAL ] Iteration 14:\tk_eff = 0.702469\tres = 1.447E-02\n", + "[ NORMAL ] Iteration 15:\tk_eff = 0.714008\tres = 1.569E-02\n", + "[ NORMAL ] Iteration 16:\tk_eff = 0.726057\tres = 1.649E-02\n", + "[ NORMAL ] Iteration 17:\tk_eff = 0.738428\tres = 1.693E-02\n", + "[ NORMAL ] Iteration 18:\tk_eff = 0.750965\tres = 1.709E-02\n", + "[ NORMAL ] Iteration 19:\tk_eff = 0.763536\tres = 1.703E-02\n", + "[ NORMAL ] Iteration 20:\tk_eff = 0.776034\tres = 1.679E-02\n", + "[ NORMAL ] Iteration 21:\tk_eff = 0.788369\tres = 1.641E-02\n", + "[ NORMAL ] Iteration 22:\tk_eff = 0.800470\tres = 1.594E-02\n", + "[ NORMAL ] Iteration 23:\tk_eff = 0.812280\tres = 1.539E-02\n", + "[ NORMAL ] Iteration 24:\tk_eff = 0.823753\tres = 1.479E-02\n", + "[ NORMAL ] Iteration 25:\tk_eff = 0.834854\tres = 1.416E-02\n", + "[ NORMAL ] Iteration 26:\tk_eff = 0.845560\tres = 1.351E-02\n", + "[ NORMAL ] Iteration 27:\tk_eff = 0.855851\tres = 1.286E-02\n", + "[ NORMAL ] Iteration 28:\tk_eff = 0.865717\tres = 1.220E-02\n", + "[ NORMAL ] Iteration 29:\tk_eff = 0.875152\tres = 1.156E-02\n", + "[ NORMAL ] Iteration 30:\tk_eff = 0.884153\tres = 1.093E-02\n", + "[ NORMAL ] Iteration 31:\tk_eff = 0.892725\tres = 1.031E-02\n", + "[ NORMAL ] Iteration 32:\tk_eff = 0.900872\tres = 9.722E-03\n", + "[ NORMAL ] Iteration 33:\tk_eff = 0.908602\tres = 9.152E-03\n", + "[ NORMAL ] Iteration 34:\tk_eff = 0.915926\tres = 8.605E-03\n", + "[ NORMAL ] Iteration 35:\tk_eff = 0.922853\tres = 8.083E-03\n", + "[ NORMAL ] Iteration 36:\tk_eff = 0.929399\tres = 7.586E-03\n", + "[ NORMAL ] Iteration 37:\tk_eff = 0.935576\tres = 7.114E-03\n", + "[ NORMAL ] Iteration 38:\tk_eff = 0.941398\tres = 6.666E-03\n", + "[ NORMAL ] Iteration 39:\tk_eff = 0.946880\tres = 6.242E-03\n", + "[ NORMAL ] Iteration 40:\tk_eff = 0.952037\tres = 5.841E-03\n", + "[ NORMAL ] Iteration 41:\tk_eff = 0.956883\tres = 5.463E-03\n", + "[ NORMAL ] Iteration 42:\tk_eff = 0.961434\tres = 5.107E-03\n", + "[ NORMAL ] Iteration 43:\tk_eff = 0.965705\tres = 4.771E-03\n", + "[ NORMAL ] Iteration 44:\tk_eff = 0.969708\tres = 4.456E-03\n", + "[ NORMAL ] Iteration 45:\tk_eff = 0.973460\tres = 4.159E-03\n", + "[ NORMAL ] Iteration 46:\tk_eff = 0.976972\tres = 3.881E-03\n", + "[ NORMAL ] Iteration 47:\tk_eff = 0.980259\tres = 3.620E-03\n", + "[ NORMAL ] Iteration 48:\tk_eff = 0.983333\tres = 3.375E-03\n", + "[ NORMAL ] Iteration 49:\tk_eff = 0.986206\tres = 3.146E-03\n", + "[ NORMAL ] Iteration 50:\tk_eff = 0.988890\tres = 2.932E-03\n", + "[ NORMAL ] Iteration 51:\tk_eff = 0.991396\tres = 2.731E-03\n", + "[ NORMAL ] Iteration 52:\tk_eff = 0.993735\tres = 2.543E-03\n", + "[ NORMAL ] Iteration 53:\tk_eff = 0.995917\tres = 2.368E-03\n", + "[ NORMAL ] Iteration 54:\tk_eff = 0.997952\tres = 2.204E-03\n", + "[ NORMAL ] Iteration 55:\tk_eff = 0.999848\tres = 2.050E-03\n", + "[ NORMAL ] Iteration 56:\tk_eff = 1.001616\tres = 1.907E-03\n", + "[ NORMAL ] Iteration 57:\tk_eff = 1.003262\tres = 1.774E-03\n", + "[ NORMAL ] Iteration 58:\tk_eff = 1.004795\tres = 1.650E-03\n", + "[ NORMAL ] Iteration 59:\tk_eff = 1.006222\tres = 1.534E-03\n", + "[ NORMAL ] Iteration 60:\tk_eff = 1.007550\tres = 1.425E-03\n", + "[ NORMAL ] Iteration 61:\tk_eff = 1.008785\tres = 1.325E-03\n", + "[ NORMAL ] Iteration 62:\tk_eff = 1.009934\tres = 1.231E-03\n", + "[ NORMAL ] Iteration 63:\tk_eff = 1.011002\tres = 1.143E-03\n", + "[ NORMAL ] Iteration 64:\tk_eff = 1.011995\tres = 1.062E-03\n", + "[ NORMAL ] Iteration 65:\tk_eff = 1.012918\tres = 9.859E-04\n", + "[ NORMAL ] Iteration 66:\tk_eff = 1.013775\tres = 9.153E-04\n", + "[ NORMAL ] Iteration 67:\tk_eff = 1.014571\tres = 8.497E-04\n", + "[ NORMAL ] Iteration 68:\tk_eff = 1.015311\tres = 7.886E-04\n", + "[ NORMAL ] Iteration 69:\tk_eff = 1.015997\tres = 7.318E-04\n", + "[ NORMAL ] Iteration 70:\tk_eff = 1.016635\tres = 6.790E-04\n", + "[ NORMAL ] Iteration 71:\tk_eff = 1.017226\tres = 6.300E-04\n", + "[ NORMAL ] Iteration 72:\tk_eff = 1.017775\tres = 5.844E-04\n", + "[ NORMAL ] Iteration 73:\tk_eff = 1.018285\tres = 5.420E-04\n", + "[ NORMAL ] Iteration 74:\tk_eff = 1.018757\tres = 5.026E-04\n", + "[ NORMAL ] Iteration 75:\tk_eff = 1.019195\tres = 4.660E-04\n", + "[ NORMAL ] Iteration 76:\tk_eff = 1.019602\tres = 4.321E-04\n", + "[ NORMAL ] Iteration 77:\tk_eff = 1.019979\tres = 4.005E-04\n", + "[ NORMAL ] Iteration 78:\tk_eff = 1.020328\tres = 3.713E-04\n", + "[ NORMAL ] Iteration 79:\tk_eff = 1.020652\tres = 3.441E-04\n", + "[ NORMAL ] Iteration 80:\tk_eff = 1.020952\tres = 3.189E-04\n", + "[ NORMAL ] Iteration 81:\tk_eff = 1.021230\tres = 2.955E-04\n", + "[ NORMAL ] Iteration 82:\tk_eff = 1.021488\tres = 2.738E-04\n", + "[ NORMAL ] Iteration 83:\tk_eff = 1.021727\tres = 2.536E-04\n", + "[ NORMAL ] Iteration 84:\tk_eff = 1.021948\tres = 2.350E-04\n", + "[ NORMAL ] Iteration 85:\tk_eff = 1.022153\tres = 2.177E-04\n", + "[ NORMAL ] Iteration 86:\tk_eff = 1.022344\tres = 2.016E-04\n", + "[ NORMAL ] Iteration 87:\tk_eff = 1.022520\tres = 1.867E-04\n", + "[ NORMAL ] Iteration 88:\tk_eff = 1.022683\tres = 1.729E-04\n", + "[ NORMAL ] Iteration 89:\tk_eff = 1.022833\tres = 1.601E-04\n", + "[ NORMAL ] Iteration 90:\tk_eff = 1.022973\tres = 1.482E-04\n", + "[ NORMAL ] Iteration 91:\tk_eff = 1.023102\tres = 1.372E-04\n", + "[ NORMAL ] Iteration 92:\tk_eff = 1.023222\tres = 1.271E-04\n", + "[ NORMAL ] Iteration 93:\tk_eff = 1.023333\tres = 1.176E-04\n", + "[ NORMAL ] Iteration 94:\tk_eff = 1.023436\tres = 1.089E-04\n", + "[ NORMAL ] Iteration 95:\tk_eff = 1.023531\tres = 1.008E-04\n", + "[ NORMAL ] Iteration 96:\tk_eff = 1.023619\tres = 9.327E-05\n", + "[ NORMAL ] Iteration 97:\tk_eff = 1.023700\tres = 8.632E-05\n", + "[ NORMAL ] Iteration 98:\tk_eff = 1.023775\tres = 7.988E-05\n", + "[ NORMAL ] Iteration 99:\tk_eff = 1.023845\tres = 7.391E-05\n", + "[ NORMAL ] Iteration 100:\tk_eff = 1.023910\tres = 6.838E-05\n", + "[ NORMAL ] Iteration 101:\tk_eff = 1.023969\tres = 6.329E-05\n", + "[ NORMAL ] Iteration 102:\tk_eff = 1.024024\tres = 5.855E-05\n", + "[ NORMAL ] Iteration 103:\tk_eff = 1.024076\tres = 5.415E-05\n", + "[ NORMAL ] Iteration 104:\tk_eff = 1.024123\tres = 5.011E-05\n", + "[ NORMAL ] Iteration 105:\tk_eff = 1.024166\tres = 4.634E-05\n", + "[ NORMAL ] Iteration 106:\tk_eff = 1.024207\tres = 4.290E-05\n", + "[ NORMAL ] Iteration 107:\tk_eff = 1.024244\tres = 3.966E-05\n", + "[ NORMAL ] Iteration 108:\tk_eff = 1.024279\tres = 3.669E-05\n", + "[ NORMAL ] Iteration 109:\tk_eff = 1.024311\tres = 3.392E-05\n", + "[ NORMAL ] Iteration 110:\tk_eff = 1.024341\tres = 3.137E-05\n", + "[ NORMAL ] Iteration 111:\tk_eff = 1.024368\tres = 2.904E-05\n", + "[ NORMAL ] Iteration 112:\tk_eff = 1.024393\tres = 2.686E-05\n", + "[ NORMAL ] Iteration 113:\tk_eff = 1.024417\tres = 2.481E-05\n", + "[ NORMAL ] Iteration 114:\tk_eff = 1.024438\tres = 2.296E-05\n", + "[ NORMAL ] Iteration 115:\tk_eff = 1.024458\tres = 2.121E-05\n", + "[ NORMAL ] Iteration 116:\tk_eff = 1.024477\tres = 1.961E-05\n", + "[ NORMAL ] Iteration 117:\tk_eff = 1.024494\tres = 1.815E-05\n", + "[ NORMAL ] Iteration 118:\tk_eff = 1.024510\tres = 1.679E-05\n", + "[ NORMAL ] Iteration 119:\tk_eff = 1.024524\tres = 1.551E-05\n", + "[ NORMAL ] Iteration 120:\tk_eff = 1.024538\tres = 1.435E-05\n", + "[ NORMAL ] Iteration 121:\tk_eff = 1.024550\tres = 1.326E-05\n", + "[ NORMAL ] Iteration 122:\tk_eff = 1.024561\tres = 1.226E-05\n", + "[ NORMAL ] Iteration 123:\tk_eff = 1.024572\tres = 1.133E-05\n", + "[ NORMAL ] Iteration 124:\tk_eff = 1.024582\tres = 1.047E-05\n" ] } ], @@ -1483,25 +1378,23 @@ }, { "cell_type": "code", - "execution_count": 40, - "metadata": { - "collapsed": false - }, + "execution_count": 39, + "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ - "openmc keff = 1.023307\n", - "openmoc keff = 1.024847\n", - "bias [pcm]: 154.0\n" + "openmc keff = 1.023293\n", + "openmoc keff = 1.024582\n", + "bias [pcm]: 128.8\n" ] } ], "source": [ "# Print report of keff and bias with OpenMC\n", "openmoc_keff = solver.getKeff()\n", - "openmc_keff = sp.k_combined[0]\n", + "openmc_keff = sp.k_combined.nominal_value\n", "bias = (openmoc_keff - openmc_keff) * 1e5\n", "\n", "print('openmc keff = {0:1.6f}'.format(openmc_keff))\n", @@ -1536,10 +1429,8 @@ }, { "cell_type": "code", - "execution_count": 41, - "metadata": { - "collapsed": false - }, + "execution_count": 40, + "metadata": {}, "outputs": [], "source": [ "# Get the OpenMC fission rate mesh tally data\n", @@ -1562,10 +1453,8 @@ }, { "cell_type": "code", - "execution_count": 42, - "metadata": { - "collapsed": false - }, + "execution_count": 41, + "metadata": {}, "outputs": [], "source": [ "# Create OpenMOC Mesh on which to tally fission rates\n", @@ -1594,26 +1483,24 @@ }, { "cell_type": "code", - "execution_count": 43, - "metadata": { - "collapsed": false - }, + "execution_count": 42, + "metadata": {}, "outputs": [ { "data": { "text/plain": [ - "" + "" ] }, - "execution_count": 43, + "execution_count": 42, "metadata": {}, "output_type": "execute_result" }, { "data": { - "image/png": "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\nAAAAAElFTkSuQmCC\n", + "image/png": "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\n", "text/plain": [ - "" + "" ] }, "metadata": {}, @@ -1640,9 +1527,9 @@ "metadata": { "anaconda-cloud": {}, "kernelspec": { - "display_name": "Python 3", + "display_name": "openmc", "language": "python", - "name": "python3" + "name": "openmc" }, "language_info": { "codemirror_mode": { @@ -1654,9 +1541,9 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.6.0" + "version": "3.6.5" } }, "nbformat": 4, - "nbformat_minor": 0 + "nbformat_minor": 1 } diff --git a/openmc/capi/tally.py b/openmc/capi/tally.py index a10fae47a3..d4d70af718 100644 --- a/openmc/capi/tally.py +++ b/openmc/capi/tally.py @@ -73,10 +73,10 @@ _dll.openmc_tally_set_type.errcheck = _error_handler _SCORES = { -1: 'flux', -2: 'total', -3: 'scatter', -4: 'nu-scatter', - -9: 'absorption', -10: 'fission', -11: 'nu-fission', -12: 'kappa-fission', - -13: 'current', -18: 'events', -19: 'delayed-nu-fission', - -20: 'prompt-nu-fission', -21: 'inverse-velocity', -22: 'fission-q-prompt', - -23: 'fission-q-recoverable', -24: 'decay-rate' + -5: 'absorption', -6: 'fission', -7: 'nu-fission', -8: 'kappa-fission', + -9: 'current', -10: 'events', -11: 'delayed-nu-fission', + -12: 'prompt-nu-fission', -13: 'inverse-velocity', -14: 'fission-q-prompt', + -15: 'fission-q-recoverable', -16: 'decay-rate' } diff --git a/openmc/filter.py b/openmc/filter.py index 2bab17dbb6..3180989eb7 100644 --- a/openmc/filter.py +++ b/openmc/filter.py @@ -104,10 +104,8 @@ class Filter(IDManagerMixin, metaclass=FilterMeta): return False elif len(self.bins) != len(other.bins): return False - elif not np.allclose(self.bins, other.bins): - return False else: - return True + return np.allclose(self.bins, other.bins) def __ne__(self, other): return not self == other diff --git a/openmc/filter_expansion.py b/openmc/filter_expansion.py index 872eaac9f5..ffac647c96 100644 --- a/openmc/filter_expansion.py +++ b/openmc/filter_expansion.py @@ -10,10 +10,17 @@ from . import Filter class ExpansionFilter(Filter): """Abstract filter class for functional expansions.""" + def __init__(self, order, filter_id=None): self.order = order self.id = filter_id + def __eq__(self, other): + if type(self) is not type(other): + return False + else: + return self.bins == other.bins + @property def order(self): return self._order diff --git a/openmc/material.py b/openmc/material.py index 6bfe58f4ac..cfa3eba3c3 100644 --- a/openmc/material.py +++ b/openmc/material.py @@ -278,8 +278,8 @@ class Material(IDManagerMixin): name = group['name'].value.decode() if 'name' in group else '' density = group['atom_density'].value - nuc_densities = group['nuclide_densities'][...] - nuclides = group['nuclides'].value + if 'nuclide_densities' in group: + nuc_densities = group['nuclide_densities'][...] # Create the Material material = cls(mat_id, name) @@ -295,10 +295,18 @@ class Material(IDManagerMixin): # Set the Material's density to atom/b-cm as used by OpenMC material.set_density(density=density, units='atom/b-cm') - # Add all nuclides to the Material - for fullname, density in zip(nuclides, nuc_densities): - name = fullname.decode().strip() - material.add_nuclide(name, percent=density, percent_type='ao') + if 'nuclides' in group: + nuclides = group['nuclides'].value + # Add all nuclides to the Material + for fullname, density in zip(nuclides, nuc_densities): + name = fullname.decode().strip() + material.add_nuclide(name, percent=density, percent_type='ao') + if 'macroscopics' in group: + macroscopics = group['macroscopics'].value + # Add all macroscopics to the Material + for fullname in macroscopics: + name = fullname.decode().strip() + material.add_macroscopic(name) return material diff --git a/openmc/mesh.py b/openmc/mesh.py index aed7a46d8c..c9c76552bc 100644 --- a/openmc/mesh.py +++ b/openmc/mesh.py @@ -182,41 +182,6 @@ class Mesh(IDManagerMixin): return mesh - def cell_generator(self): - """Generator function to traverse through every [i,j,k] index of the - mesh - - For example the following code: - - .. code-block:: python - - for mesh_index in mymesh.cell_generator(): - print(mesh_index) - - will produce the following output for a 3-D 2x2x2 mesh in mymesh:: - - [1, 1, 1] - [2, 1, 1] - [1, 2, 1] - [2, 2, 1] - ... - - - """ - - if len(self.dimension) == 1: - for x in range(self.dimension[0]): - yield [x + 1, 1, 1] - elif len(self.dimension) == 2: - for y in range(self.dimension[1]): - for x in range(self.dimension[0]): - yield [x + 1, y + 1, 1] - else: - for z in range(self.dimension[2]): - for y in range(self.dimension[1]): - for x in range(self.dimension[0]): - yield [x + 1, y + 1, z + 1] - def to_xml_element(self): """Return XML representation of the mesh @@ -280,12 +245,14 @@ class Mesh(IDManagerMixin): cv.check_value('bc', entry, ['transmission', 'vacuum', 'reflective', 'periodic']) + n_dim = len(self.dimension) + # Build the cell which will contain the lattice xplanes = [openmc.XPlane(x0=self.lower_left[0], boundary_type=bc[0]), openmc.XPlane(x0=self.upper_right[0], boundary_type=bc[1])] - if len(self.dimension) == 1: + if n_dim == 1: yplanes = [openmc.YPlane(y0=-1e10, boundary_type='reflective'), openmc.YPlane(y0=1e10, boundary_type='reflective')] else: @@ -294,7 +261,7 @@ class Mesh(IDManagerMixin): openmc.YPlane(y0=self.upper_right[1], boundary_type=bc[3])] - if len(self.dimension) <= 2: + if n_dim <= 2: # Would prefer to have the z ranges be the max supported float, but # these values are apparently different between python and Fortran. # Choosing a safe and sane default. @@ -314,12 +281,12 @@ class Mesh(IDManagerMixin): (+yplanes[0] & -yplanes[1]) & (+zplanes[0] & -zplanes[1])) - # Build the universes which will be used for each of the [i,j,k] + # Build the universes which will be used for each of the (i,j,k) # locations within the mesh. # We will concurrently build cells to assign to these universes cells = [] universes = [] - for [i, j, k] in self.cell_generator(): + for index in self.indices: cells.append(openmc.Cell()) universes.append(openmc.Universe()) universes[-1].add_cell(cells[-1]) @@ -329,7 +296,24 @@ class Mesh(IDManagerMixin): # Assign the universe and rotate to match the indexing expected for # the lattice - lattice.universes = np.rot90(np.reshape(universes, self.dimension)) + if n_dim == 1: + universe_array = np.array([universes]) + elif n_dim == 2: + universe_array = np.empty(self.dimension, dtype=openmc.Universe) + i = 0 + for y in range(self.dimension[1] - 1, -1, -1): + for x in range(self.dimension[0]): + universe_array[y][x] = universes[i] + i += 1 + else: + universe_array = np.empty(self.dimension, dtype=openmc.Universe) + i = 0 + for z in range(self.dimension[2]): + for y in range(self.dimension[1] - 1, -1, -1): + for x in range(self.dimension[0]): + universe_array[z][y][x] = universes[i] + i += 1 + lattice.universes = universe_array if self.width is not None: lattice.pitch = self.width @@ -337,9 +321,9 @@ class Mesh(IDManagerMixin): dx = ((self.upper_right[0] - self.lower_left[0]) / self.dimension[0]) - if len(self.dimension) == 1: + if n_dim == 1: lattice.pitch = [dx] - elif len(self.dimension) == 2: + elif n_dim == 2: dy = ((self.upper_right[1] - self.lower_left[1]) / self.dimension[1]) lattice.pitch = [dx, dy] diff --git a/openmc/mgxs/library.py b/openmc/mgxs/library.py index ed8e3f076c..7b75d90fff 100644 --- a/openmc/mgxs/library.py +++ b/openmc/mgxs/library.py @@ -1220,9 +1220,8 @@ class Library(object): xs_type = 'macro' # Initialize file - mgxs_file = openmc.MGXSLibrary(self.energy_groups, - num_delayed_groups=\ - self.num_delayed_groups) + mgxs_file = openmc.MGXSLibrary( + self.energy_groups, num_delayed_groups=self.num_delayed_groups) if self.domain_type == 'mesh': # Create the xsdata objects and add to the mgxs_file @@ -1231,7 +1230,7 @@ class Library(object): if self.by_nuclide: raise NotImplementedError("Mesh domains do not currently " "support nuclidic tallies") - for subdomain in domain.cell_generator(): + for subdomain in domain.indices: # Build & add metadata to XSdata object if xsdata_names is None: xsdata_name = 'set' + str(i + 1) @@ -1346,7 +1345,7 @@ class Library(object): geometry.root_universe = root materials = openmc.Materials() - for i, subdomain in enumerate(self.domains[0].cell_generator()): + for i, subdomain in enumerate(self.domains[0].indices): xsdata = mgxs_file.xsdatas[i] # Build the macroscopic and assign it to the cell of @@ -1401,24 +1400,16 @@ class Library(object): The rules to check include: - - Either total or transport should be present. + - Either total or transport must be present. - Both can be available if one wants, but we should use whatever corresponds to Library.correction (if P0: transport) - - Absorption and total (or transport) are required. + - Absorption is required. - A nu-fission cross section and chi values are not required as a fixed source problem could be the target. - Fission and kappa-fission are not required as they are only needed to support tallies the user may wish to request. - - A nu-scatter matrix is required. - - - Having a multiplicity matrix is preferred. - - Having both nu-scatter (of any order) and scatter - (at least isotropic) matrices is the second choice. - - If only nu-scatter, need total (not transport), to - be used in adjusting absorption - (i.e., reduced_abs = tot - nuscatt) See also -------- @@ -1428,36 +1419,51 @@ class Library(object): """ error_flag = False + + # if correction is 'P0', then transport must be provided + # otherwise total must be provided + if self.correction == 'P0': + if ('transport' not in self.mgxs_types and + 'nu-transport' not in self.mgxs_types): + error_flag = True + warn('If the "correction" parameter is "P0", then a ' + '"transport" or "nu-transport" MGXS type is required.') + else: + if 'total' not in self.mgxs_types: + error_flag = True + warn('If the "correction" parameter is None, then a ' + '"total" MGXS type is required.') + + # Check consistency of "nu-transport" and "nu-scatter" + if 'nu-transport' in self.mgxs_types: + if not ('nu-scatter matrix' in self.mgxs_types or + 'consistent nu-scatter matrix' in self.mgxs_types): + error_flag = True + warn('If a "nu-transport" MGXS type is used then a ' + '"nu-scatter matrix" or "consistent nu-scatter matrix" ' + 'must also be used.') + elif 'transport' in self.mgxs_types: + if not ('scatter matrix' in self.mgxs_types or + 'consistent scatter matrix' in self.mgxs_types): + error_flag = True + warn('If a "transport" MGXS type is used then a ' + '"scatter matrix" or "consistent scatter matrix" ' + 'must also be used.') + + # Make sure there is some kind of a scattering matrix data + if 'nu-scatter matrix' not in self.mgxs_types and \ + 'consistent nu-scatter matrix' not in self.mgxs_types and \ + 'scatter matrix' not in self.mgxs_types and \ + 'consistent scatter matrix' not in self.mgxs_types: + error_flag = True + warn('A "nu-scatter matrix", "consistent nu-scatter matrix", ' + '"scatter matrix", or "consistent scatter matrix" MGXS ' + 'type is required.') + # Ensure absorption is present if 'absorption' not in self.mgxs_types: error_flag = True warn('An "absorption" MGXS type is required but not provided.') - # Ensure nu-scattering matrix is required - if 'nu-scatter matrix' not in self.mgxs_types and \ - 'consistent nu-scatter matrix' not in self.mgxs_types: - error_flag = True - warn('A "nu-scatter matrix" MGXS type is required but not provided.') - else: - # Ok, now see the status of scatter and/or multiplicity - if 'scatter matrix' not in self.mgxs_types or \ - 'consistent scatter matrix' not in self.mgxs_types and \ - 'multiplicity matrix' not in self.mgxs_types: - # We dont have data needed for multiplicity matrix, therefore - # we need total, and not transport. - if 'total' not in self.mgxs_types: - error_flag = True - warn('A "total" MGXS type is required if a ' - 'scattering matrix is not provided.') - # Total or transport can be present, but if using - # self.correction=="P0", then we should use transport. - if self.correction == "P0" and 'nu-transport' not in self.mgxs_types: - error_flag = True - warn('A "nu-transport" MGXS type is required since a "P0" ' - 'correction is applied, but a "nu-transport" MGXS is ' - 'not provided.') - elif self.correction is None and 'total' not in self.mgxs_types: - error_flag = True - warn('A "total" MGXS type is required, but not provided.') if error_flag: raise ValueError('Invalid MGXS configuration encountered.') diff --git a/openmc/mgxs/mgxs.py b/openmc/mgxs/mgxs.py index 5bc00cbc95..81b4420d9c 100644 --- a/openmc/mgxs/mgxs.py +++ b/openmc/mgxs/mgxs.py @@ -1923,6 +1923,10 @@ class MGXS(metaclass=ABCMeta): if 'group out' in df: df = df[df['group out'].isin(groups)] + # Add the Legendre bin to the column if it exists + if 'legendre' in df: + columns += ['legendre'] + # If user requested micro cross sections, divide out the atom densities if xs_type == 'micro': if self.by_nuclide: @@ -2717,9 +2721,9 @@ class TransportXS(MGXS): @property def scores(self): if not self.nu: - return ['flux', 'total', 'flux', 'scatter-1'] + return ['flux', 'total', 'flux', 'scatter'] else: - return ['flux', 'total', 'flux', 'nu-scatter-1'] + return ['flux', 'total', 'flux', 'nu-scatter'] @property def tally_keys(self): @@ -2730,8 +2734,9 @@ class TransportXS(MGXS): group_edges = self.energy_groups.group_edges energy_filter = openmc.EnergyFilter(group_edges) energyout_filter = openmc.EnergyoutFilter(group_edges) + p1_filter = openmc.LegendreFilter(1) filters = [[energy_filter], [energy_filter], - [energy_filter], [energyout_filter]] + [energy_filter], [energyout_filter, p1_filter]] return self._add_angle_filters(filters) @@ -2739,12 +2744,18 @@ class TransportXS(MGXS): def rxn_rate_tally(self): if self._rxn_rate_tally is None: # Switch EnergyoutFilter to EnergyFilter. - old_filt = self.tallies['scatter-1'].filters[-1] + p1_tally = self.tallies['scatter-1'] + old_filt = p1_tally.filters[-2] new_filt = openmc.EnergyFilter(old_filt.values) - self.tallies['scatter-1'].filters[-1] = new_filt + p1_tally.filters[-2] = new_filt - self._rxn_rate_tally = \ - self.tallies['total'] - self.tallies['scatter-1'] + # Slice Legendre expansion filter and change name of score + p1_tally = p1_tally.get_slice(filters=[openmc.LegendreFilter], + filter_bins=[('P1',)], + squeeze=True) + p1_tally.scores = ['scatter-1'] + + self._rxn_rate_tally = self.tallies['total'] - p1_tally self._rxn_rate_tally.sparse = self.sparse return self._rxn_rate_tally @@ -2758,15 +2769,22 @@ class TransportXS(MGXS): raise ValueError(msg) # Switch EnergyoutFilter to EnergyFilter. - old_filt = self.tallies['scatter-1'].filters[-1] + p1_tally = self.tallies['scatter-1'] + old_filt = p1_tally.filters[-2] new_filt = openmc.EnergyFilter(old_filt.values) - self.tallies['scatter-1'].filters[-1] = new_filt + p1_tally.filters[-2] = new_filt + + # Slice Legendre expansion filter and change name of score + p1_tally = p1_tally.get_slice(filters=[openmc.LegendreFilter], + filter_bins=[('P1',)], + squeeze=True) + p1_tally.scores = ['scatter-1'] # Compute total cross section total_xs = self.tallies['total'] / self.tallies['flux (tracklength)'] # Compute transport correction term - trans_corr = self.tallies['scatter-1'] / self.tallies['flux (analog)'] + trans_corr = p1_tally / self.tallies['flux (analog)'] # Compute the transport-corrected total cross section self._xs_tally = total_xs - trans_corr @@ -3510,6 +3528,7 @@ class ScatterXS(MGXS): self._estimator = 'analog' self._valid_estimators = ['analog'] + class ScatterMatrixXS(MatrixMGXS): r"""A scattering matrix multi-group cross section with the cosine of the change-in-angle represented as one or more Legendre moments or a histogram. @@ -3598,10 +3617,10 @@ class ScatterMatrixXS(MatrixMGXS): name : str, optional Name of the multi-group cross section. Used as a label to identify tallies in OpenMC 'tallies.xml' file. - num_polar : Integral, optional + num_polar : int, optional Number of equi-width polar angle bins for angle discretization; defaults to one bin - num_azimuthal : Integral, optional + num_azimuthal : int, optional Number of equi-width azimuthal angle bins for angle discretization; defaults to one bin nu : bool @@ -3647,9 +3666,9 @@ class ScatterMatrixXS(MatrixMGXS): Domain type for spatial homogenization energy_groups : openmc.mgxs.EnergyGroups Energy group structure for energy condensation - num_polar : Integral + num_polar : int Number of equi-width polar angle bins for angle discretization - num_azimuthal : Integral + num_azimuthal : int Number of equi-width azimuthal angle bins for angle discretization tally_trigger : openmc.Trigger An (optional) tally precision trigger given to each tally used to @@ -3767,38 +3786,25 @@ class ScatterMatrixXS(MatrixMGXS): def scores(self): if self.formulation == 'simple': - scores = ['flux'] - - if self.scatter_format == 'legendre': - if self.legendre_order == 0: - scores.append('{}-0'.format(self.rxn_type)) - if self.correction: - scores.append('{}-1'.format(self.rxn_type)) - else: - scores.append('{}-P{}'.format(self.rxn_type, self.legendre_order)) - elif self.scatter_format == 'histogram': - scores += [self.rxn_type] + scores = ['flux', self.rxn_type] else: # Add scores for groupwise scattering cross section scores = ['flux', 'scatter'] # Add scores for group-to-group scattering probability matrix - if self.scatter_format == 'legendre': - if self.legendre_order == 0: - scores.append('scatter-0') - else: - scores.append('scatter-P{}'.format(self.legendre_order)) - elif self.scatter_format == 'histogram': - scores.append('scatter-0') + # these scores also contain the angular information, whether it be + # Legendre expansion or histogram bins + scores.append('scatter') - # Add scores for multiplicity matrix + # Add scores for multiplicity matrix; scatter info for the + # denominator will come from the previous score if self.nu: - scores.extend(['nu-scatter-0', 'scatter-0']) + scores.append('nu-scatter') # Add scores for transport correction if self.correction == 'P0' and self.legendre_order == 0: - scores.extend(['{}-1'.format(self.rxn_type), 'flux']) + scores.extend([self.rxn_type, 'flux']) return scores @@ -3811,15 +3817,15 @@ class ScatterMatrixXS(MatrixMGXS): tally_keys = ['flux (tracklength)', 'scatter'] # Add keys for group-to-group scattering probability matrix - tally_keys.append('scatter-P{}'.format(self.legendre_order)) + tally_keys.append('scatter matrix') # Add keys for multiplicity matrix if self.nu: - tally_keys.extend(['nu-scatter-0', 'scatter-0']) + tally_keys.extend(['nu-scatter']) # Add keys for transport correction if self.correction == 'P0' and self.legendre_order == 0: - tally_keys.extend(['{}-1'.format(self.rxn_type), 'flux (analog)']) + tally_keys.extend(['correction', 'flux (analog)']) return tally_keys @@ -3836,7 +3842,7 @@ class ScatterMatrixXS(MatrixMGXS): # Add estimators for multiplicity matrix if self.nu: - estimators.extend(['analog', 'analog']) + estimators.extend(['analog']) # Add estimators for transport correction if self.correction == 'P0' and self.legendre_order == 0: @@ -3853,13 +3859,15 @@ class ScatterMatrixXS(MatrixMGXS): if self.scatter_format == 'legendre': if self.correction == 'P0' and self.legendre_order == 0: - filters = [[energy], [energy, energyout], [energyout]] + angle_filter = openmc.LegendreFilter(order=1) else: - filters = [[energy], [energy, energyout]] + angle_filter = \ + openmc.LegendreFilter(order=self.legendre_order) elif self.scatter_format == 'histogram': bins = np.linspace(-1., 1., num=self.histogram_bins + 1, endpoint=True) - filters = [[energy], [energy, energyout, openmc.MuFilter(bins)]] + angle_filter = openmc.MuFilter(bins) + filters = [[energy], [energy, energyout, angle_filter]] else: group_edges = self.energy_groups.group_edges @@ -3871,19 +3879,21 @@ class ScatterMatrixXS(MatrixMGXS): # Group-to-group scattering probability matrix if self.scatter_format == 'legendre': - filters.append([energy, energyout]) + angle_filter = openmc.LegendreFilter(order=self.legendre_order) elif self.scatter_format == 'histogram': bins = np.linspace(-1., 1., num=self.histogram_bins + 1, endpoint=True) - filters.append([energy, energyout, openmc.MuFilter(bins)]) + angle_filter = openmc.MuFilter(bins) + filters.append([energy, energyout, angle_filter]) # Multiplicity matrix if self.nu: - filters.extend([[energy, energyout], [energy, energyout]]) + filters.extend([[energy, energyout]]) # Add filters for transport correction if self.correction == 'P0' and self.legendre_order == 0: - filters.extend([[energyout], [energy]]) + filters.extend([[energyout, openmc.LegendreFilter(1)], + [energy]]) return self._add_angle_filters(filters) @@ -3894,27 +3904,39 @@ class ScatterMatrixXS(MatrixMGXS): if self.formulation == 'simple': if self.scatter_format == 'legendre': - # If using P0 correction subtract scatter-1 from the diagonal + # If using P0 correction subtract P2 scatter from the diag. if self.correction == 'P0' and self.legendre_order == 0: - scatter_p0 = self.tallies['{}-0'.format(self.rxn_type)] - scatter_p1 = self.tallies['{}-1'.format(self.rxn_type)] - energy_filter = scatter_p0.find_filter(openmc.EnergyFilter) + scatter_p0 = self.tallies[self.rxn_type].get_slice( + filters=[openmc.LegendreFilter], + filter_bins=[('P0',)]) + scatter_p1 = self.tallies[self.rxn_type].get_slice( + filters=[openmc.LegendreFilter], + filter_bins=[('P1',)]) - # Transform scatter-p1 tally into an energyin/out matrix + # Set the Legendre order of these tallies to be 0 + # so they can be subtracted + legendre = openmc.LegendreFilter(order=0) + scatter_p0.filters[-1] = legendre + scatter_p1.filters[-1] = legendre + + scatter_p1 = scatter_p1.summation( + filter_type=openmc.EnergyFilter, + remove_filter=True) + + energy_filter = \ + scatter_p0.find_filter(openmc.EnergyFilter) + + # Transform scatter-p1 into an energyin/out matrix # to match scattering matrix shape for tally arithmetic energy_filter = copy.deepcopy(energy_filter) - scatter_p1 = scatter_p1.diagonalize_filter(energy_filter) + scatter_p1 = \ + scatter_p1.diagonalize_filter(energy_filter) + self._rxn_rate_tally = scatter_p0 - scatter_p1 - # Extract scattering moment reaction rate Tally - elif self.legendre_order == 0: - tally_key = '{}-{}'.format(self.rxn_type, - self.legendre_order) - self._rxn_rate_tally = self.tallies[tally_key] + # Otherwise, extract scattering moment reaction rate Tally else: - tally_key = '{}-P{}'.format(self.rxn_type, - self.legendre_order) - self._rxn_rate_tally = self.tallies[tally_key] + self._rxn_rate_tally = self.tallies[self.rxn_type] elif self.scatter_format == 'histogram': # Extract scattering rate distribution tally self._rxn_rate_tally = self.tallies[self.rxn_type] @@ -3941,35 +3963,24 @@ class ScatterMatrixXS(MatrixMGXS): self._xs_tally = MGXS.xs_tally.fget(self) else: - # Compute scattering probability matrix - energyout_bins = [self.energy_groups.get_group_bounds(i) - for i in range(self.num_groups, 0, -1)] - tally_key = 'scatter-P{}'.format(self.legendre_order) + # Compute scattering probability matrixS + tally_key = 'scatter matrix' # Compute normalization factor summed across outgoing energies - norm = self.tallies[tally_key].get_slice(scores=['scatter-0']) - norm = norm.summation( - filter_type=openmc.EnergyoutFilter, filter_bins=energyout_bins) - - # Remove the AggregateFilter summed across energyout bins - norm._filters = norm._filters[:2] + if self.scatter_format == 'legendre': + norm = self.tallies[tally_key].get_slice( + scores=['scatter'], + filters=[openmc.LegendreFilter], + filter_bins=[('P0',)], squeeze=True) # Compute normalization factor summed across outgoing mu bins - if self.scatter_format == 'histogram': - - # (Re-)append the MuFilter which was removed above - mu_bins = np.linspace( - -1., 1., num=self.histogram_bins + 1, endpoint=True) - norm._filters.append(openmc.MuFilter(mu_bins)) - - # Sum across all mu bins - mu_bins = [(mu_bins[i], mu_bins[i+1]) for - i in range(self.histogram_bins)] + elif self.scatter_format == 'histogram': + norm = self.tallies[tally_key].get_slice( + scores=['scatter']) norm = norm.summation( - filter_type=openmc.MuFilter, filter_bins=mu_bins) - - # Remove the AggregateFilter summed across mu bins - norm._filters = norm._filters[:2] + filter_type=openmc.MuFilter, remove_filter=True) + norm = norm.summation(filter_type=openmc.EnergyoutFilter, + remove_filter=True) # Compute groupwise scattering cross section self._xs_tally = self.tallies['scatter'] * \ @@ -3981,15 +3992,36 @@ class ScatterMatrixXS(MatrixMGXS): # Multiply by the multiplicity matrix if self.nu: - numer = self.tallies['nu-scatter-0'] - denom = self.tallies['scatter-0'] + numer = self.tallies['nu-scatter'] + # Get the denominator + if self.scatter_format == 'legendre': + denom = self.tallies[tally_key].get_slice( + scores=['scatter'], + filters=[openmc.LegendreFilter], + filter_bins=[('P0',)], squeeze=True) + + # Compute normalization factor summed across mu bins + elif self.scatter_format == 'histogram': + denom = self.tallies[tally_key].get_slice( + scores=['scatter']) + + # Sum across all mu bins + denom = denom.summation( + filter_type=openmc.MuFilter, remove_filter=True) + self._xs_tally *= (numer / denom) # If using P0 correction subtract scatter-1 from the diagonal if self.correction == 'P0' and self.legendre_order == 0: - scatter_p1 = self.tallies['{}-1'.format(self.rxn_type)] + scatter_p1 = self.tallies['correction'].get_slice( + filters=[openmc.LegendreFilter], filter_bins=[('P1',)]) flux = self.tallies['flux (analog)'] + # Set the Legendre order of the P1 tally to be 0 + # so it can be subtracted + legendre = openmc.LegendreFilter(order=0) + scatter_p1.filters[-1] = legendre + # Transform scatter-p1 tally into an energyin/out matrix # to match scattering matrix shape for tally arithmetic energy_filter = flux.find_filter(openmc.EnergyFilter) @@ -4005,6 +4037,20 @@ class ScatterMatrixXS(MatrixMGXS): self._compute_xs() + # Force the angle filter to be the last filter + if self.scatter_format == 'histogram': + angle_filter = self._xs_tally.find_filter(openmc.MuFilter) + else: + angle_filter = \ + self._xs_tally.find_filter(openmc.LegendreFilter) + angle_filter_index = self._xs_tally.filters.index(angle_filter) + # If the angle filter index is not last, then make it last + if angle_filter_index != len(self._xs_tally.filters) - 1: + energyout_filter = \ + self._xs_tally.find_filter(openmc.EnergyoutFilter) + self._xs_tally._swap_filters(energyout_filter, + angle_filter) + return self._xs_tally @nu.setter @@ -4125,16 +4171,6 @@ class ScatterMatrixXS(MatrixMGXS): self._rxn_rate_tally = None self._loaded_sp = False - if self.scatter_format == 'legendre': - # Expand scores to match the format in the statepoint - # e.g., "scatter-P2" -> "scatter-0", "scatter-1", "scatter-2" - for tally_key, tally in self.tallies.items(): - if 'scatter-P' in tally.scores[0]: - score_prefix = tally.scores[0].split('P')[0] - self.tallies[tally_key].scores = \ - [score_prefix + '{}'.format(i) - for i in range(self.legendre_order + 1)] - super().load_from_statepoint(statepoint) def get_slice(self, nuclides=[], in_groups=[], out_groups=[], @@ -4187,12 +4223,11 @@ class ScatterMatrixXS(MatrixMGXS): slice_xs.legendre_order = legendre_order # Slice the scattering tally - tally_key = '{}-P{}'.format(self.rxn_type, self.legendre_order) - expand_scores = \ - [self.rxn_type + '-{}'.format(i) - for i in range(self.legendre_order + 1)] - slice_xs.tallies[tally_key] = \ - slice_xs.tallies[tally_key].get_slice(scores=expand_scores) + filter_bins = [tuple(['P{}'.format(i) + for i in range(self.legendre_order + 1)])] + slice_xs.tallies[self.rxn_type] = \ + slice_xs.tallies[self.rxn_type].get_slice( + filters=[openmc.LegendreFilter], filter_bins=filter_bins) # Slice outgoing energy groups if needed if len(out_groups) != 0: @@ -4206,7 +4241,8 @@ class ScatterMatrixXS(MatrixMGXS): for tally_type, tally in slice_xs.tallies.items(): if tally.contains_filter(openmc.EnergyoutFilter): tally_slice = tally.get_slice( - filters=[openmc.EnergyoutFilter], filter_bins=filter_bins) + filters=[openmc.EnergyoutFilter], + filter_bins=filter_bins) slice_xs.tallies[tally_type] = tally_slice slice_xs.sparse = self.sparse @@ -4317,14 +4353,19 @@ class ScatterMatrixXS(MatrixMGXS): filter_bins.append((self.energy_groups.get_group_bounds(group),)) # Construct CrossScore for requested scattering moment - if moment != 'all' and self.scatter_format == 'legendre': - cv.check_type('moment', moment, Integral) - cv.check_greater_than('moment', moment, 0, equality=True) - cv.check_less_than( - 'moment', moment, self.legendre_order, equality=True) - scores = [self.xs_tally.scores[moment]] + if self.scatter_format == 'legendre': + if moment != 'all': + cv.check_type('moment', moment, Integral) + cv.check_greater_than('moment', moment, 0, equality=True) + cv.check_less_than( + 'moment', moment, self.legendre_order, equality=True) + filters.append(openmc.LegendreFilter) + filter_bins.append(('P{}'.format(moment),)) + num_angle_bins = 1 + else: + num_angle_bins = self.legendre_order + 1 else: - scores = [] + num_angle_bins = self.histogram_bins # Construct a collection of the nuclides to retrieve from the xs tally if self.by_nuclide: @@ -4336,6 +4377,7 @@ class ScatterMatrixXS(MatrixMGXS): query_nuclides = ['total'] # Use tally summation if user requested the sum for all nuclides + scores = self.xs_tally.scores if nuclides == 'sum' or nuclides == ['sum']: xs_tally = self.xs_tally.summation(nuclides=query_nuclides) xs = xs_tally.get_values(scores=scores, filters=filters, @@ -4367,24 +4409,15 @@ class ScatterMatrixXS(MatrixMGXS): else: num_out_groups = len(out_groups) - if self.scatter_format == 'histogram': - num_mu_bins = self.histogram_bins - else: - num_mu_bins = 1 - # Reshape tally data array with separate axes for domain and energy # Accomodate the polar and azimuthal bins if needed - num_subdomains = int(xs.shape[0] / (num_mu_bins * num_in_groups * + num_subdomains = int(xs.shape[0] / (num_angle_bins * num_in_groups * num_out_groups * self.num_polar * self.num_azimuthal)) if self.num_polar > 1 or self.num_azimuthal > 1: - if self.scatter_format == 'histogram': - new_shape = (self.num_polar, self.num_azimuthal, - num_subdomains, num_in_groups, num_out_groups, - num_mu_bins) - else: - new_shape = (self.num_polar, self.num_azimuthal, - num_subdomains, num_in_groups, num_out_groups) + new_shape = (self.num_polar, self.num_azimuthal, + num_subdomains, num_in_groups, num_out_groups, + num_angle_bins) new_shape += xs.shape[1:] xs = np.reshape(xs, new_shape) @@ -4397,11 +4430,9 @@ class ScatterMatrixXS(MatrixMGXS): if order_groups == 'increasing': xs = xs[:, :, :, ::-1, ::-1, ...] else: - if self.scatter_format == 'histogram': - new_shape = (num_subdomains, num_in_groups, num_out_groups, - num_mu_bins) - else: - new_shape = (num_subdomains, num_in_groups, num_out_groups) + new_shape = (num_subdomains, num_in_groups, num_out_groups, + num_angle_bins) + new_shape += xs.shape[1:] xs = np.reshape(xs, new_shape) @@ -4416,88 +4447,12 @@ class ScatterMatrixXS(MatrixMGXS): if squeeze: # We want to squeeze out everything but the angles, in_groups, - # out_groups, and, if needed, num_mu_bins dimension. These must + # out_groups, and, if needed, num_angle_bins dimension. These must # not be squeezed so 1-group, 1-angle problems have the correct # shape. xs = self._squeeze_xs(xs) return xs - def get_pandas_dataframe(self, groups='all', nuclides='all', moment='all', - xs_type='macro', paths=True): - """Build a Pandas DataFrame for the MGXS data. - - This method leverages :meth:`openmc.Tally.get_pandas_dataframe`, but - renames the columns with terminology appropriate for cross section data. - - Parameters - ---------- - groups : Iterable of Integral or 'all' - Energy groups of interest. Defaults to 'all'. - nuclides : Iterable of str or 'all' or 'sum' - The nuclides of the cross-sections to include in the dataframe. This - may be a list of nuclide name strings (e.g., ['U235', 'U238']). - The special string 'all' will include the cross sections for all - nuclides in the spatial domain. The special string 'sum' will - include the cross sections summed over all nuclides. Defaults - to 'all'. - moment : int or 'all' - The scattering matrix moment to return. All moments will be - returned if the moment is 'all' (default); otherwise, a specific - moment will be returned. - xs_type: {'macro', 'micro'} - Return macro or micro cross section in units of cm^-1 or barns. - Defaults to 'macro'. - paths : bool, optional - Construct columns for distribcell tally filters (default is True). - The geometric information in the Summary object is embedded into a - Multi-index column with a geometric "path" to each distribcell - instance. - - Returns - ------- - pandas.DataFrame - A Pandas DataFrame for the cross section data. - - Raises - ------ - ValueError - When this method is called before the multi-group cross section is - computed from tally data. - - """ - - df = super().get_pandas_dataframe(groups, nuclides, xs_type, paths) - - if self.scatter_format == 'legendre': - # Add a moment column to dataframe - if self.legendre_order > 0: - # Insert a column corresponding to the Legendre moments - moments = ['P{}'.format(i) - for i in range(self.legendre_order + 1)] - moments = np.tile(moments, int(df.shape[0] / len(moments))) - df['moment'] = moments - - # Place the moment column before the mean column - columns = df.columns.tolist() - mean_index \ - = [i for i, s in enumerate(columns) if 'mean' in s][0] - if self.domain_type == 'mesh': - df = df[columns[:mean_index] + [('moment', '')] + - columns[mean_index:-1]] - else: - df = df[columns[:mean_index] + ['moment'] + - columns[mean_index:-1]] - - # Select rows corresponding to requested scattering moment - if moment != 'all': - cv.check_type('moment', moment, Integral) - cv.check_greater_than('moment', moment, 0, equality=True) - cv.check_less_than( - 'moment', moment, self.legendre_order, equality=True) - df = df[df['moment'] == 'P{}'.format(moment)] - - return df - def print_xs(self, subdomains='all', nuclides='all', xs_type='macro', moment=0): """Prints a string representation for the multi-group cross section. @@ -4511,8 +4466,9 @@ class ScatterMatrixXS(MatrixMGXS): The nuclides of the cross-sections to include in the report. This may be a list of nuclide name strings (e.g., ['U235', 'U238']). The special string 'all' will report the cross sections for all - nuclides in the spatial domain. The special string 'sum' will report - the cross sections summed over all nuclides. Defaults to 'all'. + nuclides in the spatial domain. The special string 'sum' will + report the cross sections summed over all nuclides. Defaults to + 'all'. xs_type: {'macro', 'micro'} Return the macro or micro cross section in units of cm^-1 or barns. Defaults to 'macro'. @@ -4986,14 +4942,9 @@ class ScatterProbabilityMatrix(MatrixMGXS): def xs_tally(self): if self._xs_tally is None: - energyout_bins = [self.energy_groups.get_group_bounds(i) - for i in range(self.num_groups, 0, -1)] norm = self.rxn_rate_tally.get_slice(scores=[self.rxn_type]) norm = norm.summation( - filter_type=openmc.EnergyoutFilter, filter_bins=energyout_bins) - - # Remove the AggregateFilter summed across energyout bins - norm._filters = norm._filters[:2] + filter_type=openmc.EnergyoutFilter, remove_filter=True) # Compute the group-to-group probabilities self._xs_tally = self.tallies[self.rxn_type] / norm diff --git a/openmc/plotter.py b/openmc/plotter.py index 191b50c563..597a87750b 100644 --- a/openmc/plotter.py +++ b/openmc/plotter.py @@ -170,13 +170,13 @@ def plot_xs(this, types, divisor_types=None, temperature=294., data_type=None, data = data_new else: # Calculate for MG cross sections - E, data = calculate_mgxs(this, types, orders, temperature, + E, data = calculate_mgxs(this, data_type, types, orders, temperature, mg_cross_sections, ce_cross_sections, enrichment) if divisor_types: cv.check_length('divisor types', divisor_types, len(types)) - Ediv, data_div = calculate_mgxs(this, divisor_types, + Ediv, data_div = calculate_mgxs(this, data_type, divisor_types, divisor_orders, temperature, mg_cross_sections, ce_cross_sections, enrichment) @@ -243,7 +243,7 @@ def calculate_cexs(this, data_type, types, temperature=294., sab_name=None, Parameters ---------- - this : str or openmc.Material + this : {str, openmc.Nuclide, openmc.Element, openmc.Material} Object to source data from data_type : {'nuclide', 'element', material'} Type of object to plot @@ -280,7 +280,11 @@ def calculate_cexs(this, data_type, types, temperature=294., sab_name=None, cv.check_type('enrichment', enrichment, Real) if data_type == 'nuclide': - energy_grid, xs = _calculate_cexs_nuclide(this, types, temperature, + if isinstance(this, str): + nuc = openmc.Nuclide(this) + else: + nuc = this + energy_grid, xs = _calculate_cexs_nuclide(nuc, types, temperature, sab_name, cross_sections) # Convert xs (Iterable of Callable) to a grid of cross section values # calculated on @ the points in energy_grid for consistency with the @@ -289,10 +293,15 @@ def calculate_cexs(this, data_type, types, temperature=294., sab_name=None, for line in range(len(types)): data[line, :] = xs[line](energy_grid) elif data_type == 'element': - energy_grid, data = _calculate_cexs_elem_mat(this, types, temperature, + if isinstance(this, str): + elem = openmc.Element(this) + else: + elem = this + energy_grid, data = _calculate_cexs_elem_mat(elem, types, temperature, cross_sections, sab_name, enrichment) elif data_type == 'material': + cv.check_type('this', this, openmc.Material) energy_grid, data = _calculate_cexs_elem_mat(this, types, temperature, cross_sections) else: @@ -518,10 +527,8 @@ def _calculate_cexs_elem_mat(this, types, temperature=294., T = this.temperature else: T = temperature - data_type = 'material' else: T = temperature - data_type = 'element' # Load the library library = openmc.data.DataLibrary.from_xml(cross_sections) @@ -571,7 +578,7 @@ def _calculate_cexs_elem_mat(this, types, temperature=294., name = nuclide[0] nuc = nuclide[1] sab_tab = sabs[name] - temp_E, temp_xs = calculate_cexs(nuc, data_type, types, T, sab_tab, + temp_E, temp_xs = calculate_cexs(nuc, 'nuclide', types, T, sab_tab, cross_sections) E.append(temp_E) # Since the energy grids are different, store the cross sections as diff --git a/openmc/statepoint.py b/openmc/statepoint.py index eb011d8742..9c8eb709fa 100644 --- a/openmc/statepoint.py +++ b/openmc/statepoint.py @@ -405,17 +405,10 @@ class StatePoint(object): scores = group['score_bins'].value n_score_bins = group['n_score_bins'].value - # Read scattering moment order strings (e.g., P3, Y1,2, etc.) - moments = group['moment_orders'].value - # Add the scores to the Tally for j, score in enumerate(scores): score = score.decode() - # If this is a moment, use generic moment order - pattern = r'-n$|-pn$|-yn$' - score = re.sub(pattern, '-' + moments[j].decode(), score) - tally.scores.append(score) # Add Tally to the global dictionary of all Tallies diff --git a/openmc/summary.py b/openmc/summary.py index aa98025c08..10898290a3 100644 --- a/openmc/summary.py +++ b/openmc/summary.py @@ -9,7 +9,7 @@ import openmc import openmc.checkvalue as cv from openmc.region import Region -_VERSION_SUMMARY = 5 +_VERSION_SUMMARY = 6 class Summary(object): @@ -26,6 +26,8 @@ class Summary(object): nuclides : dict Dictionary whose keys are nuclide names and values are atomic weight ratios. + macroscopics : list + Names of macroscopic data sets version: tuple of int Version of OpenMC @@ -44,13 +46,15 @@ class Summary(object): self._fast_materials = {} self._fast_surfaces = {} self._fast_cells = {} - self._fast_universes = {} + self._fast_universes = {} self._fast_lattices = {} self._materials = openmc.Materials() self._nuclides = {} + self._macroscopics = [] self._read_nuclides() + self._read_macroscopics() with warnings.catch_warnings(): warnings.simplefilter("ignore", openmc.IDWarning) self._read_geometry() @@ -71,15 +75,26 @@ class Summary(object): def nuclides(self): return self._nuclides + @property + def macroscopics(self): + return self._macroscopics + @property def version(self): return tuple(self._f.attrs['openmc_version']) def _read_nuclides(self): - names = self._f['nuclides/names'].value - awrs = self._f['nuclides/awrs'].value - for name, awr in zip(names, awrs): - self._nuclides[name.decode()] = awr + if 'nuclides/names' in self._f: + names = self._f['nuclides/names'].value + awrs = self._f['nuclides/awrs'].value + for name, awr in zip(names, awrs): + self._nuclides[name.decode()] = awr + + def _read_macroscopics(self): + if 'macroscopics/names' in self._f: + names = self._f['macroscopics/names'].value + for name in names: + self._macroscopics = name.decode() def _read_geometry(self): # Read in and initialize the Materials and Geometry diff --git a/openmc/tallies.py b/openmc/tallies.py index 50398b786e..1ac89129a9 100644 --- a/openmc/tallies.py +++ b/openmc/tallies.py @@ -65,9 +65,7 @@ class Tally(IDManagerMixin): triggers : list of openmc.Trigger List of tally triggers num_scores : int - Total number of scores, accounting for the fact that a single - user-specified score, e.g. scatter-P3 or flux-Y2,2, might have multiple - bins + Total number of scores num_filter_bins : int Total number of filter bins accounting for all filters num_bins : int @@ -388,6 +386,14 @@ class Tally(IDManagerMixin): # If score is a string, strip whitespace if isinstance(score, str): + # Check to see if scores are deprecated before storing + for deprecated in ['scatter-', 'nu-scatter-', 'scatter-p', + 'nu-scatter-p', 'scatter-y', 'nu-scatter-y', + 'flux-y', 'total-y']: + if score.startswith(deprecated): + msg = score.strip() + ' is deprecated and should no ' \ + 'longer be used.' + raise ValueError(msg) scores[i] = score.strip() self._scores = cv.CheckedList(_SCORE_CLASSES, 'tally scores', scores) @@ -827,51 +833,8 @@ class Tally(IDManagerMixin): # Sparsify merged tally if both tallies are sparse merged_tally.sparse = self.sparse and other.sparse - # Consolidate scatter and flux Legendre moment scores - merged_tally._consolidate_moment_scores() - return merged_tally - def _consolidate_moment_scores(self): - """Remove redundant scattering and flux moment scores from a Tally.""" - - # Define regex for scatter, nu-scatter and flux moment scores - regex = [(r'^((?!nu-)scatter-\d)', r'^((?!nu-)scatter-(P|p)\d)'), - (r'nu-scatter-\d', r'nu-scatter-(P|p)\d'), - (r'flux-\d', r'flux-(P|p)\d')] - - # Find all non-scattering and non-flux moment scores - scores = [x for x in self.scores if - re.search(r'^((?!scatter-).)*$', x)] - scores = [x for x in scores if - re.search(r'^((?!flux-).)*$', x)] - - for regex_n, regex_pn in regex: - - # Use regex to find score-(P)n scores - score_n = [x for x in self.scores if re.search(regex_n, x)] - score_pn = [x for x in self.scores if re.search(regex_pn, x)] - - # Consolidate moment scores - if len(score_pn) > 0: - - # Only keep the highest score-PN score - high_pn = sorted([x.lower() for x in score_pn])[-1] - pn = int(high_pn.split('-')[-1].replace('p', '')) - - # Only keep the score-N scores with N > PN - score_n = sorted([x.lower() for x in score_n]) - score_n = [x for x in score_n if (int(x.split('-')[1]) > pn)] - - # Append highest score-PN and any higher score-N scores - scores.extend([high_pn] + score_n) - else: - scores.extend(score_n) - - # Override Tally's scores with consolidated list of scores - self.scores = scores - - def to_xml_element(self): """Return XML representation of the tally @@ -1180,7 +1143,7 @@ class Tally(IDManagerMixin): # Determine the score indices from any of the requested scores if nuclides: - nuclide_indices = np.zeros(len(nuclides), dtype=np.int) + nuclide_indices = np.zeros(len(nuclides), dtype=int) for i, nuclide in enumerate(nuclides): nuclide_indices[i] = self.get_nuclide_index(nuclide) @@ -1219,7 +1182,7 @@ class Tally(IDManagerMixin): # Determine the score indices from any of the requested scores if scores: - score_indices = np.zeros(len(scores), dtype=np.int) + score_indices = np.zeros(len(scores), dtype=int) for i, score in enumerate(scores): score_indices[i] = self.get_score_index(score) @@ -1491,11 +1454,8 @@ class Tally(IDManagerMixin): data = self.get_values(value=value) # Build a new array shape with one dimension per filter - new_shape = () - for self_filter in self.filters: - new_shape += (self_filter.num_bins, ) - new_shape += (self.num_nuclides,) - new_shape += (self.num_scores,) + new_shape = tuple(f.num_bins for f in self.filters) + new_shape += (self.num_nuclides, self.num_scores) # Reshape the data with one dimension for each filter data = np.reshape(data, new_shape) @@ -2772,7 +2732,7 @@ class Tally(IDManagerMixin): # Sum across the bins in the user-specified filter for i, self_filter in enumerate(self.filters): - if isinstance(self_filter, filter_type): + if type(self_filter) == filter_type: shape = mean.shape mean = np.take(mean, indices=bin_indices, axis=i) std_dev = np.take(std_dev, indices=bin_indices, axis=i) @@ -3012,7 +2972,7 @@ class Tally(IDManagerMixin): The data in the derived tally arrays is "diagonalized" along the bins in the new filter. This functionality is used by the openmc.mgxs module; to transport-correct scattering matrices by subtracting a 'scatter-P1' - reaction rate tally with an energy filter from an 'scatter' reaction + reaction rate tally with an energy filter from a 'scatter' reaction rate tally with both energy and energyout filters. Parameters @@ -3031,7 +2991,7 @@ class Tally(IDManagerMixin): if new_filter in self.filters: msg = 'Unable to diagonalize Tally ID="{0}" which already ' \ - 'contains a "{1}" filter'.format(self.id, new_filter.type) + 'contains a "{1}" filter'.format(self.id, type(new_filter)) raise ValueError(msg) # Add the new filter to a copy of this Tally @@ -3042,8 +3002,8 @@ class Tally(IDManagerMixin): # by which the "base" indices should be repeated to account for all # other filter bins in the diagonalized tally indices = np.arange(0, new_filter.num_bins**2, new_filter.num_bins+1) - diag_factor = int(self.num_filter_bins / new_filter.num_bins) - diag_indices = np.zeros(self.num_filter_bins, dtype=np.int) + diag_factor = self.num_filter_bins // new_filter.num_bins + diag_indices = np.zeros(self.num_filter_bins, dtype=int) # Determine the filter indices along the new "diagonal" for i in range(diag_factor): diff --git a/src/cmfd_data.F90 b/src/cmfd_data.F90 index 3152f1eb2b..ce4825426b 100644 --- a/src/cmfd_data.F90 +++ b/src/cmfd_data.F90 @@ -76,6 +76,7 @@ contains integer :: i_filter_mesh ! index for mesh filter integer :: i_filter_ein ! index for incoming energy filter integer :: i_filter_eout ! index for outgoing energy filter + integer :: i_filter_legendre ! index for Legendre filter integer :: i_mesh ! flattend index for mesh logical :: energy_filters! energy filters present real(8) :: flux ! temp variable for flux @@ -116,8 +117,11 @@ contains if (ital < 3) then i_filter_mesh = t % filter(t % find_filter(FILTER_MESH)) - else + else if (ital == 3) then i_filter_mesh = t % filter(t % find_filter(FILTER_MESHSURFACE)) + else if (ital == 4) then + i_filter_mesh = t % filter(t % find_filter(FILTER_MESH)) + i_filter_legendre = t % filter(t % find_filter(FILTER_LEGENDRE)) end if ! Check for energy filters @@ -187,13 +191,6 @@ contains ! Get total rr and convert to total xs cmfd % totalxs(h,i,j,k) = t % results(RESULT_SUM,2,score_index) / flux - ! Get p1 scatter rr and convert to p1 scatter xs - cmfd % p1scattxs(h,i,j,k) = t % results(RESULT_SUM,3,score_index) / flux - - ! Calculate diffusion coefficient - cmfd % diffcof(h,i,j,k) = ONE/(3.0_8*(cmfd % totalxs(h,i,j,k) - & - cmfd % p1scattxs(h,i,j,k))) - else if (ital == 2) then ! Begin loop to get energy out tallies @@ -301,6 +298,46 @@ contains score_index + IN_TOP) cmfd % current(12,h,i,j,k) = t % results(RESULT_SUM, 1, & score_index + OUT_TOP) + + else if (ital == 4) then + + ! Reset all bins to 1 + do l = 1, size(t % filter) + call filter_matches(t % filter(l)) % bins % clear() + call filter_matches(t % filter(l)) % bins % push_back(1) + end do + + ! Set ijk as mesh indices + ijk = (/ i, j, k /) + + ! Get bin number for mesh indices + filter_matches(i_filter_mesh) % bins % data(1) = & + m % get_bin_from_indices(ijk) + + ! Apply energy in filter + if (energy_filters) then + filter_matches(i_filter_ein) % bins % data(1) = ng - h + 1 + end if + + ! Apply Legendre filter + filter_matches(i_filter_legendre) % bins % data(1) = 2 + + ! Calculate score index from bins + score_index = 1 + do l = 1, size(t % filter) + score_index = score_index + (filter_matches(t % filter(l)) & + % bins % data(1) - 1) * t % stride(l) + end do + + ! Get p1 scatter rr and convert to p1 scatter xs + cmfd % p1scattxs(h,i,j,k) = & + t % results(RESULT_SUM,1,score_index) / & + cmfd % flux(h,i,j,k) + + ! Calculate diffusion coefficient + cmfd % diffcof(h,i,j,k) = & + ONE/(3.0_8*(cmfd % totalxs(h,i,j,k) - & + cmfd % p1scattxs(h,i,j,k))) end if TALLY end do OUTGROUP diff --git a/src/cmfd_input.F90 b/src/cmfd_input.F90 index 40b4abf572..549cff4191 100644 --- a/src/cmfd_input.F90 +++ b/src/cmfd_input.F90 @@ -373,7 +373,7 @@ contains ! Determine number of filters energy_filters = check_for_node(node_mesh, "energy") - n = merge(4, 2, energy_filters) + n = merge(5, 3, energy_filters) ! Extend filters array so we can add CMFD filters err = openmc_extend_filters(n, i_filt_start, i_filt_end) @@ -414,6 +414,12 @@ contains err = openmc_filter_set_id(i_filt, filt_id) err = openmc_meshsurface_filter_set_mesh(i_filt, i_start) + ! Add in legendre filter for the P1 tally + i_filt = i_filt + 1 + err = openmc_filter_set_type(i_filt, C_CHAR_'legendre' // C_NULL_CHAR) + call openmc_get_filter_next_id(filt_id) + err = openmc_filter_set_id(i_filt, filt_id) + err = openmc_legendre_filter_set_order(i_filt, 1) ! Initialize filters do i = i_filt_start, i_filt_end @@ -421,7 +427,7 @@ contains end do ! Allocate tallies - err = openmc_extend_tallies(3, i_start, i_end) + err = openmc_extend_tallies(4, i_start, i_end) cmfd_tallies => tallies(i_start:i_end) ! Begin loop around tallies @@ -455,7 +461,7 @@ contains if (i == 1) then ! Set name - t % name = "CMFD flux, total, scatter-1" + t % name = "CMFD flux, total" ! Set tally estimator to analog t % estimator = ESTIMATOR_ANALOG @@ -473,19 +479,12 @@ contains deallocate(filter_indices) ! Allocate scoring bins - allocate(t % score_bins(3)) - t % n_score_bins = 3 - t % n_user_score_bins = 3 - - ! Allocate scattering order data - allocate(t % moment_order(3)) - t % moment_order = 0 + allocate(t % score_bins(2)) + t % n_score_bins = 2 ! Set macro_bins t % score_bins(1) = SCORE_FLUX t % score_bins(2) = SCORE_TOTAL - t % score_bins(3) = SCORE_SCATTER_N - t % moment_order(3) = 1 else if (i == 2) then @@ -517,11 +516,6 @@ contains ! Allocate macro reactions allocate(t % score_bins(2)) t % n_score_bins = 2 - t % n_user_score_bins = 2 - - ! Allocate scattering order data - allocate(t % moment_order(2)) - t % moment_order = 0 ! Set macro_bins t % score_bins(1) = SCORE_NU_SCATTER @@ -537,7 +531,7 @@ contains ! Allocate and set filters allocate(filter_indices(n_filter)) - filter_indices(1) = i_filt_end + filter_indices(1) = i_filt_end - 1 if (energy_filters) then filter_indices(2) = i_filt_start + 1 end if @@ -547,15 +541,41 @@ contains ! Allocate macro reactions allocate(t % score_bins(1)) t % n_score_bins = 1 - t % n_user_score_bins = 1 - - ! Allocate scattering order data - allocate(t % moment_order(1)) - t % moment_order = 0 ! Set macro bins t % score_bins(1) = SCORE_CURRENT t % type = TALLY_MESH_SURFACE + + else if (i == 4) then + ! Set name + t % name = "CMFD P1 scatter" + + ! Set tally estimator to analog + t % estimator = ESTIMATOR_ANALOG + + ! Set tally type to volume + t % type = TALLY_VOLUME + + ! Allocate and set filters + n_filter = 2 + if (energy_filters) then + n_filter = n_filter + 1 + end if + allocate(filter_indices(n_filter)) + filter_indices(1) = i_filt_start + filter_indices(2) = i_filt_end + if (energy_filters) then + filter_indices(3) = i_filt_start + 1 + end if + err = openmc_tally_set_filters(i_start + i - 1, n_filter, filter_indices) + deallocate(filter_indices) + + ! Allocate scoring bins + allocate(t % score_bins(1)) + t % n_score_bins = 1 + + ! Set macro_bins + t % score_bins(1) = SCORE_SCATTER end if ! Make CMFD tallies active from the start diff --git a/src/constants.F90 b/src/constants.F90 index b335b78c86..d1893bf9e1 100644 --- a/src/constants.F90 +++ b/src/constants.F90 @@ -21,7 +21,7 @@ module constants integer, parameter :: VERSION_STATEPOINT(2) = [17, 0] integer, parameter :: VERSION_PARTICLE_RESTART(2) = [2, 0] integer, parameter :: VERSION_TRACK(2) = [2, 0] - integer, parameter :: VERSION_SUMMARY(2) = [5, 0] + integer, parameter :: VERSION_SUMMARY(2) = [6, 0] integer, parameter :: VERSION_VOLUME(2) = [1, 0] integer, parameter :: VERSION_VOXEL(2) = [1, 0] integer, parameter :: VERSION_MGXS_LIBRARY(2) = [1, 0] @@ -232,6 +232,10 @@ module constants MGXS_ISOTROPIC = 1, & ! Isotropically Weighted Data MGXS_ANGLE = 2 ! Data by Angular Bins + ! Flag to denote this was a macroscopic data object + real(8), parameter :: & + MACROSCOPIC_AWR = -TWO + ! Fission neutron emission (nu) type integer, parameter :: & NU_NONE = 0, & ! No nu values (non-fissionable) @@ -310,50 +314,28 @@ module constants ! Tally score type -- if you change these, make sure you also update the ! _SCORES dictionary in openmc/capi/tally.py - integer, parameter :: N_SCORE_TYPES = 24 + integer, parameter :: N_SCORE_TYPES = 16 integer, parameter :: & SCORE_FLUX = -1, & ! flux SCORE_TOTAL = -2, & ! total reaction rate SCORE_SCATTER = -3, & ! scattering rate SCORE_NU_SCATTER = -4, & ! scattering production rate - SCORE_SCATTER_N = -5, & ! arbitrary scattering moment - SCORE_SCATTER_PN = -6, & ! system for scoring 0th through nth moment - SCORE_NU_SCATTER_N = -7, & ! arbitrary nu-scattering moment - SCORE_NU_SCATTER_PN = -8, & ! system for scoring 0th through nth nu-scatter moment - SCORE_ABSORPTION = -9, & ! absorption rate - SCORE_FISSION = -10, & ! fission rate - SCORE_NU_FISSION = -11, & ! neutron production rate - SCORE_KAPPA_FISSION = -12, & ! fission energy production rate - SCORE_CURRENT = -13, & ! current - SCORE_FLUX_YN = -14, & ! angular moment of flux - SCORE_TOTAL_YN = -15, & ! angular moment of total reaction rate - SCORE_SCATTER_YN = -16, & ! angular flux-weighted scattering moment (0:N) - SCORE_NU_SCATTER_YN = -17, & ! angular flux-weighted nu-scattering moment (0:N) - SCORE_EVENTS = -18, & ! number of events - SCORE_DELAYED_NU_FISSION = -19, & ! delayed neutron production rate - SCORE_PROMPT_NU_FISSION = -20, & ! prompt neutron production rate - SCORE_INVERSE_VELOCITY = -21, & ! flux-weighted inverse velocity - SCORE_FISS_Q_PROMPT = -22, & ! prompt fission Q-value - SCORE_FISS_Q_RECOV = -23, & ! recoverable fission Q-value - SCORE_DECAY_RATE = -24 ! delayed neutron precursor decay rate + SCORE_ABSORPTION = -5, & ! absorption rate + SCORE_FISSION = -6, & ! fission rate + SCORE_NU_FISSION = -7, & ! neutron production rate + SCORE_KAPPA_FISSION = -8, & ! fission energy production rate + SCORE_CURRENT = -9, & ! current + SCORE_EVENTS = -10, & ! number of events + SCORE_DELAYED_NU_FISSION = -11, & ! delayed neutron production rate + SCORE_PROMPT_NU_FISSION = -12, & ! prompt neutron production rate + SCORE_INVERSE_VELOCITY = -13, & ! flux-weighted inverse velocity + SCORE_FISS_Q_PROMPT = -14, & ! prompt fission Q-value + SCORE_FISS_Q_RECOV = -15, & ! recoverable fission Q-value + SCORE_DECAY_RATE = -16 ! delayed neutron precursor decay rate ! Maximum scattering order supported integer, parameter :: MAX_ANG_ORDER = 10 - ! Names of *-PN & *-YN scores (MOMENT_STRS) and *-N moment scores - character(*), parameter :: & - MOMENT_STRS(6) = (/ "scatter-p ", & - "nu-scatter-p", & - "flux-y ", & - "total-y ", & - "scatter-y ", & - "nu-scatter-y"/), & - MOMENT_N_STRS(2) = (/ "scatter- ", & - "nu-scatter- "/) - - ! Location in MOMENT_STRS where the YN data begins - integer, parameter :: YN_LOC = 3 - ! Tally map bin finding integer, parameter :: NO_BIN_FOUND = -1 diff --git a/src/endf.F90 b/src/endf.F90 index 0ba2db388b..9934d9a7cf 100644 --- a/src/endf.F90 +++ b/src/endf.F90 @@ -26,14 +26,6 @@ contains string = "scatter" case (SCORE_NU_SCATTER) string = "nu-scatter" - case (SCORE_SCATTER_N) - string = "scatter-n" - case (SCORE_SCATTER_PN) - string = "scatter-pn" - case (SCORE_NU_SCATTER_N) - string = "nu-scatter-n" - case (SCORE_NU_SCATTER_PN) - string = "nu-scatter-pn" case (SCORE_ABSORPTION) string = "absorption" case (SCORE_FISSION) @@ -50,14 +42,6 @@ contains string = "kappa-fission" case (SCORE_CURRENT) string = "current" - case (SCORE_FLUX_YN) - string = "flux-yn" - case (SCORE_TOTAL_YN) - string = "total-yn" - case (SCORE_SCATTER_YN) - string = "scatter-yn" - case (SCORE_NU_SCATTER_YN) - string = "nu-scatter-yn" case (SCORE_EVENTS) string = "events" case (SCORE_INVERSE_VELOCITY) diff --git a/src/input_xml.F90 b/src/input_xml.F90 index 63e5cd7a49..f8cf50dd3c 100644 --- a/src/input_xml.F90 +++ b/src/input_xml.F90 @@ -2194,26 +2194,20 @@ contains integer :: i ! loop over user-specified tallies integer :: j ! loop over words integer :: k ! another loop index - integer :: l ! another loop index integer :: filter_id ! user-specified identifier for filter integer :: i_filt ! index in filters array integer :: i_elem ! index of entry in dictionary integer :: n ! size of arrays in mesh specification integer :: n_words ! number of words read integer :: n_filter ! number of filters - integer :: n_new ! number of new scores to add based on Yn/Pn tally - integer :: n_scores ! number of tot scores after adjusting for Yn/Pn tally - integer :: n_bins ! total new bins for this score + integer :: n_scores ! number of scores integer :: n_user_trig ! number of user-specified tally triggers integer :: trig_ind ! index of triggers array for each tally integer :: user_trig_ind ! index of user-specified triggers for each tally integer :: i_start, i_end integer(C_INT) :: err real(8) :: threshold ! trigger convergence threshold - integer :: n_order ! moment order requested - integer :: n_order_pos ! oosition of Scattering order in score name string integer :: MT ! user-specified MT for score - integer :: imomstr ! Index of MOMENT_STRS & MOMENT_N_STRS logical :: file_exists ! does tallies.xml file exist? integer, allocatable :: temp_filter(:) ! temporary filter indices character(MAX_LINE_LEN) :: filename @@ -2541,107 +2535,22 @@ contains allocate(sarray(n_words)) call get_node_array(node_tal, "scores", sarray) - ! Before we can allocate storage for scores, we must determine the - ! number of additional scores required due to the moment scores - ! (i.e., scatter-p#, flux-y#) - n_new = 0 + ! Append the score to the list of possible trigger scores do j = 1, n_words sarray(j) = to_lower(sarray(j)) - ! Find if scores(j) is of the form 'moment-p' or 'moment-y' present in - ! MOMENT_STRS(:) - ! If so, check the order, store if OK, then reset the number to 'n' score_name = trim(sarray(j)) - ! Append the score to the list of possible trigger scores if (trigger_on) call trigger_scores % set(trim(score_name), j) - do imomstr = 1, size(MOMENT_STRS) - if (starts_with(score_name,trim(MOMENT_STRS(imomstr)))) then - n_order_pos = scan(score_name,'0123456789') - n_order = int(str_to_int( & - score_name(n_order_pos:(len_trim(score_name)))),4) - if (n_order > MAX_ANG_ORDER) then - ! User requested too many orders; throw a warning and set to the - ! maximum order. - ! The above scheme will essentially take the absolute value - if (master) call warning("Invalid scattering order of " & - // trim(to_str(n_order)) // " requested. Setting to the & - &maximum permissible value, " & - // trim(to_str(MAX_ANG_ORDER))) - n_order = MAX_ANG_ORDER - sarray(j) = trim(MOMENT_STRS(imomstr)) & - // trim(to_str(MAX_ANG_ORDER)) - end if - ! Find total number of bins for this case - if (imomstr >= YN_LOC) then - n_bins = (n_order + 1)**2 - else - n_bins = n_order + 1 - end if - ! We subtract one since n_words already included - n_new = n_new + n_bins - 1 - exit - end if - end do end do - n_scores = n_words + n_new + n_scores = n_words ! Allocate score storage accordingly allocate(t % score_bins(n_scores)) - allocate(t % moment_order(n_scores)) - t % moment_order = 0 - j = 0 - do l = 1, n_words - j = j + 1 - ! Get the input string in scores(l) but if score is one of the moment - ! scores then strip off the n and store it as an integer to be used - ! later. Then perform the select case on this modified (number - ! removed) string - n_order = -1 - score_name = sarray(l) - do imomstr = 1, size(MOMENT_STRS) - if (starts_with(score_name,trim(MOMENT_STRS(imomstr)))) then - n_order_pos = scan(score_name,'0123456789') - n_order = int(str_to_int( & - score_name(n_order_pos:(len_trim(score_name)))),4) - if (n_order > MAX_ANG_ORDER) then - ! User requested too many orders; throw a warning and set to the - ! maximum order. - ! The above scheme will essentially take the absolute value - n_order = MAX_ANG_ORDER - end if - score_name = trim(MOMENT_STRS(imomstr)) // "n" - ! Find total number of bins for this case - if (imomstr >= YN_LOC) then - n_bins = (n_order + 1)**2 - else - n_bins = n_order + 1 - end if - exit - end if - end do - ! Now check the Moment_N_Strs, but only if we werent successful above - if (imomstr > size(MOMENT_STRS)) then - do imomstr = 1, size(MOMENT_N_STRS) - if (starts_with(score_name,trim(MOMENT_N_STRS(imomstr)))) then - n_order_pos = scan(score_name,'0123456789') - n_order = int(str_to_int( & - score_name(n_order_pos:(len_trim(score_name)))),4) - if (n_order > MAX_ANG_ORDER) then - ! User requested too many orders; throw a warning and set to the - ! maximum order. - ! The above scheme will essentially take the absolute value - if (master) call warning("Invalid scattering order of " & - // trim(to_str(n_order)) // " requested. Setting to & - &the maximum permissible value, " & - // trim(to_str(MAX_ANG_ORDER))) - n_order = MAX_ANG_ORDER - end if - score_name = trim(MOMENT_N_STRS(imomstr)) // "n" - exit - end if - end do - end if + + ! Check the validity of the scores and their filters + do j = 1, n_scores + score_name = sarray(j) ! Check if delayed group filter is used with any score besides ! delayed-nu-fission or decay-rate @@ -2652,23 +2561,6 @@ contains &delayedgroup filter.") end if - ! Check to see if the mu filter is applied and if that makes sense. - if ((.not. starts_with(score_name,'scatter')) .and. & - (.not. starts_with(score_name,'nu-scatter'))) then - if (t % find_filter(FILTER_MU) > 0) then - call fatal_error("Cannot tally " // trim(score_name) //" with a & - &change of angle (mu) filter.") - end if - ! Also check to see if this is a legendre expansion or not. - ! If so, we can accept this score and filter combo for p0, but not - ! elsewhere. - else if (n_order > 0) then - if (t % find_filter(FILTER_MU) > 0) then - call fatal_error("Cannot tally " // trim(score_name) //" with a & - &change of angle (mu) filter unless order is 0.") - end if - end if - select case (trim(score_name)) case ('flux') ! Prohibit user from tallying flux for an individual nuclide @@ -2683,22 +2575,6 @@ contains &filter.") end if - case ('flux-yn') - ! Prohibit user from tallying flux for an individual nuclide - if (.not. (t % n_nuclide_bins == 1 .and. & - t % nuclide_bins(1) == -1)) then - call fatal_error("Cannot tally flux for an individual nuclide.") - end if - - if (t % find_filter(FILTER_ENERGYOUT) > 0) then - call fatal_error("Cannot tally flux with an outgoing energy & - &filter.") - end if - - t % score_bins(j : j + n_bins - 1) = SCORE_FLUX_YN - t % moment_order(j : j + n_bins - 1) = n_order - j = j + n_bins - 1 - case ('total', '(n,total)') t % score_bins(j) = SCORE_TOTAL if (t % find_filter(FILTER_ENERGYOUT) > 0) then @@ -2706,18 +2582,13 @@ contains &outgoing energy filter.") end if - case ('total-yn') - if (t % find_filter(FILTER_ENERGYOUT) > 0) then - call fatal_error("Cannot tally total reaction rate with an & - &outgoing energy filter.") - end if - - t % score_bins(j : j + n_bins - 1) = SCORE_TOTAL_YN - t % moment_order(j : j + n_bins - 1) = n_order - j = j + n_bins - 1 - case ('scatter') t % score_bins(j) = SCORE_SCATTER + if (t % find_filter(FILTER_ENERGYOUT) > 0 .or. & + t % find_filter(FILTER_LEGENDRE) > 0) then + ! Set tally estimator to analog + t % estimator = ESTIMATOR_ANALOG + end if case ('nu-scatter') t % score_bins(j) = SCORE_NU_SCATTER @@ -2727,53 +2598,14 @@ contains ! necessary) if (run_CE) then t % estimator = ESTIMATOR_ANALOG + else + if (t % find_filter(FILTER_ENERGYOUT) > 0 .or. & + t % find_filter(FILTER_LEGENDRE) > 0) then + ! Set tally estimator to analog + t % estimator = ESTIMATOR_ANALOG + end if end if - case ('scatter-n') - t % score_bins(j) = SCORE_SCATTER_N - t % moment_order(j) = n_order - t % estimator = ESTIMATOR_ANALOG - - case ('nu-scatter-n') - t % score_bins(j) = SCORE_NU_SCATTER_N - t % moment_order(j) = n_order - t % estimator = ESTIMATOR_ANALOG - - case ('scatter-pn') - t % estimator = ESTIMATOR_ANALOG - ! Setup P0:Pn - t % score_bins(j : j + n_bins - 1) = SCORE_SCATTER_PN - t % moment_order(j : j + n_bins - 1) = n_order - j = j + n_bins - 1 - - case ('nu-scatter-pn') - t % estimator = ESTIMATOR_ANALOG - ! Setup P0:Pn - t % score_bins(j : j + n_bins - 1) = SCORE_NU_SCATTER_PN - t % moment_order(j : j + n_bins - 1) = n_order - j = j + n_bins - 1 - - case ('scatter-yn') - t % estimator = ESTIMATOR_ANALOG - ! Setup P0:Pn - t % score_bins(j : j + n_bins - 1) = SCORE_SCATTER_YN - t % moment_order(j : j + n_bins - 1) = n_order - j = j + n_bins - 1 - - case ('nu-scatter-yn') - t % estimator = ESTIMATOR_ANALOG - ! Setup P0:Pn - t % score_bins(j : j + n_bins - 1) = SCORE_NU_SCATTER_YN - t % moment_order(j : j + n_bins - 1) = n_order - j = j + n_bins - 1 - - case('transport') - call fatal_error("Transport score no longer supported for tallies, & - &please remove") - - case ('n1n') - call fatal_error("n1n score no longer supported for tallies, & - &please remove") case ('n2n', '(n,2n)') t % score_bins(j) = N_2N t % depletion_rx = .true. @@ -2937,6 +2769,14 @@ contains t % score_bins(j) = N_DA case default + ! First look for deprecated scores + if (starts_with(trim(score_name), 'scatter-') .or. & + starts_with(trim(score_name), 'nu-scatter-') .or. & + starts_with(trim(score_name), 'total-y') .or. & + starts_with(trim(score_name), 'flux-y')) then + call fatal_error(trim(score_name) // " is no longer available.") + end if + ! Assume that user has specified an MT number MT = int(str_to_int(score_name)) @@ -2945,14 +2785,12 @@ contains if (MT > 1) then t % score_bins(j) = MT else - call fatal_error("Invalid MT on : " & - // trim(sarray(l))) + call fatal_error("Invalid MT on : " // trim(score_name)) end if else ! Specified score was not an integer - call fatal_error("Unknown scoring function: " & - // trim(sarray(l))) + call fatal_error("Unknown scoring function: " // trim(score_name)) end if end select @@ -2967,35 +2805,19 @@ contains end do t % n_score_bins = n_scores - t % n_user_score_bins = n_words ! Deallocate temporary string array of scores deallocate(sarray) ! Check that no duplicate scores exist - j = 1 - do while (j < n_scores) - ! Determine number of bins for scores with expansions - n_order = t % moment_order(j) - select case (t % score_bins(j)) - case (SCORE_SCATTER_PN, SCORE_NU_SCATTER_PN) - n_bins = n_order + 1 - case (SCORE_FLUX_YN, SCORE_TOTAL_YN, SCORE_SCATTER_YN, & - SCORE_NU_SCATTER_YN) - n_bins = (n_order + 1)**2 - case default - n_bins = 1 - end select - - do k = j + n_bins, n_scores - if (t % score_bins(j) == t % score_bins(k) .and. & - t % moment_order(j) == t % moment_order(k)) then + do j = 1, n_scores - 1 + do k = j + 1, n_scores + if (t % score_bins(j) == t % score_bins(k)) then call fatal_error("Duplicate score of type '" // trim(& reaction_name(t % score_bins(j))) // "' found in tally " & // trim(to_str(t % id))) end if end do - j = j + n_bins end do else call fatal_error("No specified on tally " & diff --git a/src/math.F90 b/src/math.F90 index ee8cd0530b..20bacf88cf 100644 --- a/src/math.F90 +++ b/src/math.F90 @@ -598,7 +598,6 @@ contains real(8) :: zn_mat(n+1, n+1) ! Matrix form of the coefficients which is ! easier to work with real(8) :: k1, k2, k3, k4 ! Variables for R_m_n calculation - real(8) :: sqrt_norm ! normalization for radial moments integer :: i,p,q ! Loop counters real(8), parameter :: SQRT_N_1(0:10) = [& diff --git a/src/mgxs_header.F90 b/src/mgxs_header.F90 index 6eabefae3c..fd6074c428 100644 --- a/src/mgxs_header.F90 +++ b/src/mgxs_header.F90 @@ -6,7 +6,7 @@ module mgxs_header use hdf5, only: HID_T, HSIZE_T, SIZE_T use algorithm, only: find, sort - use constants, only: MAX_WORD_LEN, ZERO, ONE, TWO, PI + use constants, only: MAX_WORD_LEN, ZERO, ONE, TWO, PI, MACROSCOPIC_AWR use error, only: fatal_error use hdf5_interface use material_header, only: material @@ -268,7 +268,7 @@ contains if (attribute_exists(xs_id, "atomic_weight_ratio")) then call read_attribute(this % awr, xs_id, "atomic_weight_ratio") else - this % awr = -ONE + this % awr = MACROSCOPIC_AWR end if ! Determine temperatures available @@ -396,9 +396,9 @@ contains ! Store the dimensionality of the data in order_dim. ! For Legendre data, we usually refer to it as Pn where n is the order. - ! However Pn has n+1 sets of points (since you need to - ! the count the P0 moment). Adjust for that. Histogram and Tabular - ! formats dont need this adjustment. + ! However Pn has n+1 sets of points (since you need to count the P0 + ! moment). Adjust for that. Histogram and Tabular formats dont need this + ! adjustment. if (this % scatter_format == ANGLE_LEGENDRE) then order_dim = order_dim + 1 else diff --git a/src/output.F90 b/src/output.F90 index b6809ca82f..f9e770f514 100644 --- a/src/output.F90 +++ b/src/output.F90 @@ -665,14 +665,11 @@ contains integer :: j ! level in tally hierarchy integer :: k ! loop index for scoring bins integer :: n ! loop index for nuclides - integer :: l ! loop index for user scores integer :: h ! loop index for tally filters integer :: indent ! number of spaces to preceed output integer :: filter_index ! index in results array for filters integer :: score_index ! scoring bin index integer :: i_nuclide ! index in nuclides array - integer :: n_order ! loop index for moment orders - integer :: nm_order ! loop index for Ynm moment orders integer :: unit_tally ! tallies.out file unit integer :: nr ! number of realizations real(8) :: t_value ! t-values for confidence intervals @@ -699,14 +696,6 @@ contains score_names(abs(SCORE_NU_FISSION)) = "Nu-Fission Rate" score_names(abs(SCORE_KAPPA_FISSION)) = "Kappa-Fission Rate" score_names(abs(SCORE_EVENTS)) = "Events" - score_names(abs(SCORE_FLUX_YN)) = "Flux Moment" - score_names(abs(SCORE_TOTAL_YN)) = "Total Reaction Rate Moment" - score_names(abs(SCORE_SCATTER_N)) = "Scattering Rate Moment" - score_names(abs(SCORE_SCATTER_PN)) = "Scattering Rate Moment" - score_names(abs(SCORE_SCATTER_YN)) = "Scattering Rate Moment" - score_names(abs(SCORE_NU_SCATTER_N)) = "Scattering Prod. Rate Moment" - score_names(abs(SCORE_NU_SCATTER_PN)) = "Scattering Prod. Rate Moment" - score_names(abs(SCORE_NU_SCATTER_YN)) = "Scattering Prod. Rate Moment" score_names(abs(SCORE_DECAY_RATE)) = "Decay Rate" score_names(abs(SCORE_DELAYED_NU_FISSION)) = "Delayed-Nu-Fission Rate" score_names(abs(SCORE_PROMPT_NU_FISSION)) = "Prompt-Nu-Fission Rate" @@ -860,60 +849,20 @@ contains end if indent = indent + 2 - k = 0 - do l = 1, t % n_user_score_bins - k = k + 1 + do k = 1, t % n_score_bins score_index = score_index + 1 associate(r => t % results(RESULT_SUM:RESULT_SUM_SQ, :, :)) - select case(t % score_bins(k)) - case (SCORE_SCATTER_N, SCORE_NU_SCATTER_N) - score_name = 'P' // trim(to_str(t % moment_order(k))) // " " // & - score_names(abs(t % score_bins(k))) - x(:) = mean_stdev(r(:, score_index, filter_index), nr) - write(UNIT=unit_tally, FMT='(1X,2A,1X,A,"+/- ",A)') & - repeat(" ", indent), score_name, to_str(x(1)), & - trim(to_str(t_value * x(2))) - case (SCORE_SCATTER_PN, SCORE_NU_SCATTER_PN) - score_index = score_index - 1 - do n_order = 0, t % moment_order(k) - score_index = score_index + 1 - score_name = 'P' // trim(to_str(n_order)) // " " //& - score_names(abs(t % score_bins(k))) - x(:) = mean_stdev(r(:, score_index, filter_index), nr) - write(UNIT=unit_tally, FMT='(1X,2A,1X,A,"+/- ",A)') & - repeat(" ", indent), score_name, & - to_str(x(1)), trim(to_str(t_value * x(2))) - end do - k = k + t % moment_order(k) - case (SCORE_SCATTER_YN, SCORE_NU_SCATTER_YN, SCORE_FLUX_YN, & - SCORE_TOTAL_YN) - score_index = score_index - 1 - do n_order = 0, t % moment_order(k) - do nm_order = -n_order, n_order - score_index = score_index + 1 - score_name = 'Y' // trim(to_str(n_order)) // ',' // & - trim(to_str(nm_order)) // " " & - // score_names(abs(t % score_bins(k))) - x(:) = mean_stdev(r(:, score_index, filter_index), nr) - write(UNIT=unit_tally, FMT='(1X,2A,1X,A,"+/- ",A)') & - repeat(" ", indent), score_name, & - to_str(x(1)), trim(to_str(t_value * x(2))) - end do - end do - k = k + (t % moment_order(k) + 1)**2 - 1 - case default - if (t % score_bins(k) > 0) then - score_name = reaction_name(t % score_bins(k)) - else - score_name = score_names(abs(t % score_bins(k))) - end if - x(:) = mean_stdev(r(:, score_index, filter_index), nr) - write(UNIT=unit_tally, FMT='(1X,2A,1X,A,"+/- ",A)') & - repeat(" ", indent), score_name, & - to_str(x(1)), trim(to_str(t_value * x(2))) - end select + if (t % score_bins(k) > 0) then + score_name = reaction_name(t % score_bins(k)) + else + score_name = score_names(abs(t % score_bins(k))) + end if + x(:) = mean_stdev(r(:, score_index, filter_index), nr) + write(UNIT=unit_tally, FMT='(1X,2A,1X,A,"+/- ",A)') & + repeat(" ", indent), score_name, & + to_str(x(1)), trim(to_str(t_value * x(2))) end associate end do indent = indent - 2 diff --git a/src/state_point.F90 b/src/state_point.F90 index 980a7333cd..a7ae24ddab 100644 --- a/src/state_point.F90 +++ b/src/state_point.F90 @@ -48,8 +48,6 @@ contains integer :: i, j, k integer :: i_xs - integer :: n_order ! loop index for moment orders - integer :: nm_order ! loop index for Ynm moment orders integer, allocatable :: id_array(:) integer(HID_T) :: file_id integer(HID_T) :: cmfd_group, tallies_group, tally_group, meshes_group, & @@ -320,42 +318,9 @@ contains str_array(j) = reaction_name(tally % score_bins(j)) end do call write_dataset(tally_group, "score_bins", str_array) - call write_dataset(tally_group, "n_user_score_bins", & - tally % n_user_score_bins) deallocate(str_array) - ! Write explicit moment order strings for each score bin - k = 1 - allocate(str_array(tally % n_score_bins)) - MOMENT_LOOP: do j = 1, tally % n_user_score_bins - select case(tally % score_bins(k)) - case (SCORE_SCATTER_N, SCORE_NU_SCATTER_N) - str_array(k) = trim(to_str(tally % moment_order(k))) - k = k + 1 - case (SCORE_SCATTER_PN, SCORE_NU_SCATTER_PN) - do n_order = 0, tally % moment_order(k) - str_array(k) = trim(to_str(n_order)) - k = k + 1 - end do - case (SCORE_SCATTER_YN, SCORE_NU_SCATTER_YN, SCORE_FLUX_YN, & - SCORE_TOTAL_YN) - do n_order = 0, tally % moment_order(k) - do nm_order = -n_order, n_order - str_array(k) = 'Y' // trim(to_str(n_order)) // ',' // & - trim(to_str(nm_order)) - k = k + 1 - end do - end do - case default - str_array(k) = '' - k = k + 1 - end select - end do MOMENT_LOOP - - call write_dataset(tally_group, "moment_orders", str_array) - deallocate(str_array) - call close_group(tally_group) end associate end do TALLY_METADATA diff --git a/src/summary.F90 b/src/summary.F90 index 3aeb42178b..409c4de1f5 100644 --- a/src/summary.F90 +++ b/src/summary.F90 @@ -77,34 +77,81 @@ contains subroutine write_nuclides(file_id) integer(HID_T), intent(in) :: file_id integer(HID_T) :: nuclide_group + integer(HID_T) :: macro_group integer :: i - character(12), allocatable :: nucnames(:) + character(12), allocatable :: nuc_names(:) + character(12), allocatable :: macro_names(:) real(8), allocatable :: awrs(:) + integer :: num_nuclides + integer :: num_macros + integer :: j + integer :: k - ! Write useful data from nuclide objects - nuclide_group = create_group(file_id, "nuclides") - call write_attribute(nuclide_group, "n_nuclides", n_nuclides) + ! Find how many of these nuclides are macroscopic objects + if (run_CE) then + ! Then none are macroscopic + num_nuclides = n_nuclides + num_macros = 0 + else + num_nuclides = 0 + num_macros = 0 + do i = 1, n_nuclides + if (nuclides_MG(i) % obj % awr /= MACROSCOPIC_AWR) then + num_nuclides = num_nuclides + 1 + else + num_macros = num_macros + 1 + end if + end do + end if - ! Build array of nuclide names and awrs - allocate(nucnames(n_nuclides)) - allocate(awrs(n_nuclides)) + ! Build array of nuclide names and awrs while only sorting nuclides from + ! macroscopics + if (num_nuclides > 0) then + allocate(nuc_names(num_nuclides)) + allocate(awrs(num_nuclides)) + end if + if (num_macros > 0) then + allocate(macro_names(num_macros)) + end if + + j = 1 + k = 1 do i = 1, n_nuclides if (run_CE) then - nucnames(i) = nuclides(i) % name + nuc_names(i) = nuclides(i) % name awrs(i) = nuclides(i) % awr else - nucnames(i) = nuclides_MG(i) % obj % name - awrs(i) = nuclides_MG(i) % obj % awr + if (nuclides_MG(i) % obj % awr /= MACROSCOPIC_AWR) then + nuc_names(j) = nuclides_MG(i) % obj % name + awrs(j) = nuclides_MG(i) % obj % awr + j = j + 1 + else + macro_names(k) = nuclides_MG(i) % obj % name + k = k + 1 + end if end if end do + nuclide_group = create_group(file_id, "nuclides") + call write_attribute(nuclide_group, "n_nuclides", num_nuclides) + macro_group = create_group(file_id, "macroscopics") + call write_attribute(macro_group, "n_macroscopics", num_macros) ! Write nuclide names and awrs - call write_dataset(nuclide_group, "names", nucnames) - call write_dataset(nuclide_group, "awrs", awrs) - + if (num_nuclides > 0) then + ! Write useful data from nuclide objects + call write_dataset(nuclide_group, "names", nuc_names) + call write_dataset(nuclide_group, "awrs", awrs) + end if + if (num_macros > 0) then + ! Write useful data from macroscopic objects + call write_dataset(macro_group, "names", macro_names) + end if call close_group(nuclide_group) + call close_group(macro_group) - deallocate(nucnames, awrs) + + if (allocated(nuc_names)) deallocate(nuc_names, awrs) + if (allocated(macro_names)) deallocate(macro_names) end subroutine write_nuclides @@ -371,7 +418,13 @@ contains integer :: i integer :: j - character(20), allocatable :: nucnames(:) + integer :: k + integer :: n + character(20), allocatable :: nuc_names(:) + character(20), allocatable :: macro_names(:) + real(8), allocatable :: nuc_densities(:) + integer :: num_nuclides + integer :: num_macros integer(HID_T) :: materials_group integer(HID_T) :: material_group type(Material), pointer :: m @@ -399,24 +452,69 @@ contains ! Write atom density with units call write_dataset(material_group, "atom_density", m % density) - ! Copy ZAID for each nuclide to temporary array - allocate(nucnames(m%n_nuclides)) - do j = 1, m%n_nuclides - if (run_CE) then - nucnames(j) = nuclides(m%nuclide(j))%name - else - nucnames(j) = nuclides_MG(m%nuclide(j))%obj%name + if (run_CE) then + num_nuclides = m % n_nuclides + num_macros = 0 + else + ! Find the number of macroscopic and nuclide data in this material + num_nuclides = 0 + num_macros = 0 + k = 1 + n = 1 + do j = 1, m % n_nuclides + if (nuclides_MG(m % nuclide(j)) % obj % awr /= MACROSCOPIC_AWR) then + num_nuclides = num_nuclides + 1 + else + num_macros = num_macros + 1 + end if + end do + end if + + ! Copy ZAID or macro name for each nuclide to temporary array + if (num_nuclides > 0) then + allocate(nuc_names(num_nuclides)) + allocate(nuc_densities(num_nuclides)) + end if + if (run_CE) then + do j = 1, m % n_nuclides + nuc_names(j) = nuclides(m%nuclide(j))%name + nuc_densities(j) = m % atom_density(j) + end do + else + if (num_macros > 0) then + allocate(macro_names(num_macros)) end if - end do + + k = 1 + n = 1 + do j = 1, m % n_nuclides + if (nuclides_MG(m % nuclide(j)) % obj % awr /= MACROSCOPIC_AWR) then + nuc_names(k) = nuclides_MG(m % nuclide(j)) % obj % name + nuc_densities(k) = m % atom_density(j) + k = k + 1 + else + macro_names(n) = nuclides_MG(m % nuclide(j)) % obj % name + n = n + 1 + end if + end do + end if ! Write temporary array to 'nuclides' - call write_dataset(material_group, "nuclides", nucnames) + if (num_nuclides > 0) then + call write_dataset(material_group, "nuclides", nuc_names) + ! Deallocate temporary array + deallocate(nuc_names) + ! Write atom densities + call write_dataset(material_group, "nuclide_densities", nuc_densities) + deallocate(nuc_densities) + end if - ! Deallocate temporary array - deallocate(nucnames) - - ! Write atom densities - call write_dataset(material_group, "nuclide_densities", m%atom_density) + ! Write temporary array to 'macroscopics' + if (num_macros > 0) then + call write_dataset(material_group, "macroscopics", macro_names) + ! Deallocate temporary array + deallocate(macro_names) + end if if (m%n_sab > 0) then call write_dataset(material_group, "sab_names", m%sab_names) diff --git a/src/tallies/tally.F90 b/src/tallies/tally.F90 index f4d12be7e1..483246b362 100644 --- a/src/tallies/tally.F90 +++ b/src/tallies/tally.F90 @@ -84,7 +84,6 @@ contains integer :: i ! loop index for scoring bins integer :: l ! loop index for nuclides in material integer :: m ! loop index for reactions - integer :: q ! loop index for scoring bins integer :: i_temp ! temperature index integer :: i_nuc ! index in nuclides array (from material) integer :: i_energy ! index in nuclide energy grid @@ -104,9 +103,7 @@ contains ! Pre-collision energy of particle E = p % last_E - i = 0 - SCORE_LOOP: do q = 1, t % n_user_score_bins - i = i + 1 + SCORE_LOOP: do i = 1, t % n_score_bins ! determine what type of score bin score_bin = t % score_bins(i) @@ -120,7 +117,7 @@ contains select case(score_bin) - case (SCORE_FLUX, SCORE_FLUX_YN) + case (SCORE_FLUX) if (t % estimator == ESTIMATOR_ANALOG) then ! All events score to a flux bin. We actually use a collision ! estimator in place of an analog one since there is no way to count @@ -140,7 +137,7 @@ contains end if - case (SCORE_TOTAL, SCORE_TOTAL_YN) + case (SCORE_TOTAL) if (t % estimator == ESTIMATOR_ANALOG) then ! All events will score to the total reaction rate. We can just ! use the weight of the particle entering the collision as the @@ -187,7 +184,7 @@ contains end if - case (SCORE_SCATTER, SCORE_SCATTER_N) + case (SCORE_SCATTER) if (t % estimator == ESTIMATOR_ANALOG) then ! Skip any event where the particle didn't scatter if (p % event /= EVENT_SCATTER) cycle SCORE_LOOP @@ -197,7 +194,6 @@ contains score = p % last_wgt * flux else - ! Note SCORE_SCATTER_N not available for tracklength/collision. if (i_nuclide > 0) then score = (micro_xs(i_nuclide) % total & - micro_xs(i_nuclide) % absorption) * atom_density * flux @@ -207,33 +203,7 @@ contains end if - case (SCORE_SCATTER_PN) - ! Only analog estimators are available. - ! Skip any event where the particle didn't scatter - if (p % event /= EVENT_SCATTER) then - i = i + t % moment_order(i) - cycle SCORE_LOOP - end if - ! Since only scattering events make it here, again we can use - ! the weight entering the collision as the estimator for the - ! reaction rate - score = p % last_wgt * flux - - - case (SCORE_SCATTER_YN) - ! Only analog estimators are available. - ! Skip any event where the particle didn't scatter - if (p % event /= EVENT_SCATTER) then - i = i + (t % moment_order(i) + 1)**2 - 1 - cycle SCORE_LOOP - end if - ! Since only scattering events make it here, again we can use - ! the weight entering the collision as the estimator for the - ! reaction rate - score = p % last_wgt * flux - - - case (SCORE_NU_SCATTER, SCORE_NU_SCATTER_N) + case (SCORE_NU_SCATTER) ! Only analog estimators are available. ! Skip any event where the particle didn't scatter if (p % event /= EVENT_SCATTER) cycle SCORE_LOOP @@ -256,58 +226,6 @@ contains end if - case (SCORE_NU_SCATTER_PN) - ! Only analog estimators are available. - ! Skip any event where the particle didn't scatter - if (p % event /= EVENT_SCATTER) then - i = i + t % moment_order(i) - cycle SCORE_LOOP - end if - ! For scattering production, we need to use the pre-collision - ! weight times the yield as the estimate for the number of - ! neutrons exiting a reaction with neutrons in the exit channel - if (p % event_MT == ELASTIC .or. p % event_MT == N_LEVEL .or. & - (p % event_MT >= N_N1 .and. p % event_MT <= N_NC)) then - ! Don't waste time on very common reactions we know have - ! multiplicities of one. - score = p % last_wgt * flux - else - m = nuclides(p % event_nuclide) % reaction_index(p % event_MT) - - ! Get yield and apply to score - associate (rxn => nuclides(p % event_nuclide) % reactions(m)) - score = p % last_wgt * flux & - * rxn % products(1) % yield % evaluate(E) - end associate - end if - - - case (SCORE_NU_SCATTER_YN) - ! Only analog estimators are available. - ! Skip any event where the particle didn't scatter - if (p % event /= EVENT_SCATTER) then - i = i + (t % moment_order(i) + 1)**2 - 1 - cycle SCORE_LOOP - end if - ! For scattering production, we need to use the pre-collision - ! weight times the yield as the estimate for the number of - ! neutrons exiting a reaction with neutrons in the exit channel - if (p % event_MT == ELASTIC .or. p % event_MT == N_LEVEL .or. & - (p % event_MT >= N_N1 .and. p % event_MT <= N_NC)) then - ! Don't waste time on very common reactions we know have - ! multiplicities of one. - score = p % last_wgt * flux - else - m = nuclides(p % event_nuclide) % reaction_index(p % event_MT) - - ! Get yield and apply to score - associate (rxn => nuclides(p%event_nuclide)%reactions(m)) - score = p % last_wgt * flux & - * rxn % products(1) % yield % evaluate(E) - end associate - end if - - case (SCORE_ABSORPTION) if (t % estimator == ESTIMATOR_ANALOG) then if (survival_biasing) then @@ -1359,7 +1277,7 @@ contains end if i = 0 - SCORE_LOOP: do q = 1, t % n_user_score_bins + SCORE_LOOP: do q = 1, t % n_score_bins i = i + 1 ! determine what type of score bin @@ -1374,7 +1292,7 @@ contains select case(score_bin) - case (SCORE_FLUX, SCORE_FLUX_YN) + case (SCORE_FLUX) if (t % estimator == ESTIMATOR_ANALOG) then ! All events score to a flux bin. We actually use a collision ! estimator in place of an analog one since there is no way to count @@ -1395,7 +1313,7 @@ contains end if - case (SCORE_TOTAL, SCORE_TOTAL_YN) + case (SCORE_TOTAL) if (t % estimator == ESTIMATOR_ANALOG) then ! All events will score to the total reaction rate. We can just ! use the weight of the particle entering the collision as the @@ -1456,15 +1374,10 @@ contains end if - case (SCORE_SCATTER, SCORE_SCATTER_N, SCORE_SCATTER_PN, SCORE_SCATTER_YN) + case (SCORE_SCATTER) if (t % estimator == ESTIMATOR_ANALOG) then ! Skip any event where the particle didn't scatter if (p % event /= EVENT_SCATTER) then - if (score_bin == SCORE_SCATTER_PN) then - i = i + t % moment_order(i) - else if (score_bin == SCORE_SCATTER_YN) then - i = i + (t % moment_order(i) + 1)**2 - 1 - end if cycle SCORE_LOOP end if @@ -1485,7 +1398,6 @@ contains end if else - ! Note SCORE_SCATTER_*N not available for tracklength/collision. if (i_nuclide > 0) then score = atom_density * flux * & nucxs % get_xs('scatter/mult', p_g, UVW=p_uvw) @@ -1498,16 +1410,10 @@ contains end if - case (SCORE_NU_SCATTER, SCORE_NU_SCATTER_N, SCORE_NU_SCATTER_PN, & - SCORE_NU_SCATTER_YN) + case (SCORE_NU_SCATTER) if (t % estimator == ESTIMATOR_ANALOG) then ! Skip any event where the particle didn't scatter if (p % event /= EVENT_SCATTER) then - if (score_bin == SCORE_NU_SCATTER_PN) then - i = i + t % moment_order(i) - else if (score_bin == SCORE_NU_SCATTER_YN) then - i = i + (t % moment_order(i) + 1)**2 - 1 - end if cycle SCORE_LOOP end if @@ -1528,7 +1434,6 @@ contains end if else - ! Note SCORE_NU_SCATTER_*N not available for tracklength/collision. if (i_nuclide > 0) then score = nucxs % get_xs('scatter', p_g, UVW=p_uvw) * & atom_density * flux @@ -2101,98 +2006,10 @@ contains real(8), intent(inout) :: score ! data to score integer, intent(inout) :: i ! Working index - integer :: num_nm ! Number of N,M orders in harmonic - integer :: n ! Moment loop index - real(8) :: uvw(3) - - select case(score_bin) - case (SCORE_SCATTER_N, SCORE_NU_SCATTER_N) - ! Find the scattering order for a singly requested moment, and - ! store its moment contribution. - if (t % moment_order(i) == 1) then - score = score * p % mu ! avoid function call overhead - else - score = score * calc_pn(t % moment_order(i), p % mu) - endif !$omp atomic t % results(RESULT_VALUE, score_index, filter_index) = & t % results(RESULT_VALUE, score_index, filter_index) + score - - case(SCORE_SCATTER_YN, SCORE_NU_SCATTER_YN) - score_index = score_index - 1 - num_nm = 1 - ! Find the order for a collection of requested moments - ! and store the moment contribution of each - do n = 0, t % moment_order(i) - ! determine scoring bin index - score_index = score_index + num_nm - ! Update number of total n,m bins for this n (m = [-n: n]) - num_nm = 2 * n + 1 - - ! multiply score by the angular flux moments and store -!$omp critical (score_general_scatt_yn) - t % results(RESULT_VALUE, score_index: score_index + num_nm - 1, & - filter_index) = t % results(RESULT_VALUE, & - score_index: score_index + num_nm - 1, filter_index) & - + score * calc_pn(n, p % mu) * calc_rn(n, p % last_uvw) -!$omp end critical (score_general_scatt_yn) - end do - i = i + (t % moment_order(i) + 1)**2 - 1 - - - case(SCORE_FLUX_YN, SCORE_TOTAL_YN) - score_index = score_index - 1 - num_nm = 1 - if (t % estimator == ESTIMATOR_ANALOG .or. & - t % estimator == ESTIMATOR_COLLISION) then - uvw = p % last_uvw - else if (t % estimator == ESTIMATOR_TRACKLENGTH) then - uvw = p % coord(1) % uvw - end if - ! Find the order for a collection of requested moments - ! and store the moment contribution of each - do n = 0, t % moment_order(i) - ! determine scoring bin index - score_index = score_index + num_nm - ! Update number of total n,m bins for this n (m = [-n: n]) - num_nm = 2 * n + 1 - - ! multiply score by the angular flux moments and store -!$omp critical (score_general_flux_tot_yn) - t % results(RESULT_VALUE, score_index: score_index + num_nm - 1, & - filter_index) = t % results(RESULT_VALUE, & - score_index: score_index + num_nm - 1, filter_index) & - + score * calc_rn(n, uvw) -!$omp end critical (score_general_flux_tot_yn) - end do - i = i + (t % moment_order(i) + 1)**2 - 1 - - - case (SCORE_SCATTER_PN, SCORE_NU_SCATTER_PN) - score_index = score_index - 1 - ! Find the scattering order for a collection of requested moments - ! and store the moment contribution of each - do n = 0, t % moment_order(i) - ! determine scoring bin index - score_index = score_index + 1 - - ! get the score and tally it -!$omp atomic - t % results(RESULT_VALUE, score_index, filter_index) = & - t % results(RESULT_VALUE, score_index, filter_index) & - + score * calc_pn(n, p % mu) - end do - i = i + t % moment_order(i) - - - case default -!$omp atomic - t % results(RESULT_VALUE, score_index, filter_index) = & - t % results(RESULT_VALUE, score_index, filter_index) + score - - end select - end subroutine expand_and_score !=============================================================================== @@ -3134,7 +2951,7 @@ contains ! Currently only one score type k = 0 - SCORE_LOOP: do q = 1, t % n_user_score_bins + SCORE_LOOP: do q = 1, t % n_score_bins k = k + 1 ! determine what type of score bin diff --git a/src/tallies/tally_header.F90 b/src/tallies/tally_header.F90 index 413464b7b5..2d285706f8 100644 --- a/src/tallies/tally_header.F90 +++ b/src/tallies/tally_header.F90 @@ -74,13 +74,8 @@ module tally_header logical :: all_nuclides = .false. ! Values to score, e.g. flux, absorption, etc. - ! scat_order is the scattering order for each score. - ! It is to be 0 if the scattering order is 0, or if the score is not a - ! scattering response. integer :: n_score_bins = 0 integer, allocatable :: score_bins(:) - integer, allocatable :: moment_order(:) - integer :: n_user_score_bins = 0 ! Results for each bin -- the first dimension of the array is for scores ! (e.g. flux, total reaction rate, fission reaction rate, etc.) and the @@ -795,7 +790,6 @@ contains associate (t => tallies(index) % obj) if (allocated(t % score_bins)) deallocate(t % score_bins) allocate(t % score_bins(n)) - t % n_user_score_bins = n t % n_score_bins = n do i = 1, n diff --git a/src/tallies/trigger.F90 b/src/tallies/trigger.F90 index 7dcb3d71eb..2cb3bf8194 100644 --- a/src/tallies/trigger.F90 +++ b/src/tallies/trigger.F90 @@ -104,8 +104,6 @@ contains integer :: s ! loop index for triggers integer :: filter_index ! index in results array for filters integer :: score_index ! scoring bin index - integer :: n_order ! loop index for moment orders - integer :: nm_order ! loop index for Ynm moment orders integer(C_INT) :: err real(8) :: uncertainty ! trigger uncertainty real(8) :: std_dev = ZERO ! trigger standard deviation @@ -187,70 +185,18 @@ contains ! Initialize score bin index NUCLIDE_LOOP: do n = 1, t % n_nuclide_bins - select case(t % score_bins(trigger % score_index)) + call get_trigger_uncertainty(std_dev, rel_err, & + score_index, filter_index, t) - case (SCORE_SCATTER_PN, SCORE_NU_SCATTER_PN) - - score_index = score_index - 1 - - do n_order = 0, t % moment_order(trigger % score_index) - score_index = score_index + 1 - - call get_trigger_uncertainty(std_dev, rel_err, & - score_index, filter_index, t) - - if (trigger % variance < variance) then - trigger % variance = std_dev ** 2 - end if - if (trigger % std_dev < std_dev) then - trigger % std_dev = std_dev - end if - if (trigger % rel_err < rel_err) then - trigger % rel_err = rel_err - end if - - end do - - case (SCORE_SCATTER_YN, SCORE_NU_SCATTER_YN, SCORE_FLUX_YN, & - SCORE_TOTAL_YN) - - score_index = score_index - 1 - - do n_order = 0, t % moment_order(trigger % score_index) - do nm_order = -n_order, n_order - score_index = score_index + 1 - - call get_trigger_uncertainty(std_dev, rel_err, & - score_index, filter_index, t) - - if (trigger % variance < variance) then - trigger % variance = std_dev ** 2 - end if - if (trigger % std_dev < std_dev) then - trigger % std_dev = std_dev - end if - if (trigger % rel_err < rel_err) then - trigger % rel_err = rel_err - end if - - end do - end do - - case default - call get_trigger_uncertainty(std_dev, rel_err, & - score_index, filter_index, t) - - if (trigger % variance < variance) then - trigger % variance = std_dev ** 2 - end if - if (trigger % std_dev < std_dev) then - trigger % std_dev = std_dev - end if - if (trigger % rel_err < rel_err) then - trigger % rel_err = rel_err - end if - - end select + if (trigger % variance < variance) then + trigger % variance = std_dev ** 2 + end if + if (trigger % std_dev < std_dev) then + trigger % std_dev = std_dev + end if + if (trigger % rel_err < rel_err) then + trigger % rel_err = rel_err + end if select case (t % triggers(s) % type) case(VARIANCE) diff --git a/tests/regression_tests/cmfd_feed/results_true.dat b/tests/regression_tests/cmfd_feed/results_true.dat index 5e6750fe6b..aba219ba83 100644 --- a/tests/regression_tests/cmfd_feed/results_true.dat +++ b/tests/regression_tests/cmfd_feed/results_true.dat @@ -26,62 +26,42 @@ tally 2: 2.667071E+01 1.600292E+01 1.293670E+01 -2.252427E+00 -2.605738E-01 4.268506E+01 9.161216E+01 3.022909E+01 4.598915E+01 -3.873926E+00 -7.615035E-01 5.680399E+01 1.623879E+02 4.033805E+01 8.196263E+01 -5.280610E+00 -1.414008E+00 6.814742E+01 2.331778E+02 4.851618E+01 1.182330E+02 -6.261805E+00 -1.983205E+00 7.392923E+01 2.740255E+02 5.253586E+01 1.384152E+02 -6.733810E+00 -2.278242E+00 7.332860E+01 2.698608E+02 5.227405E+01 1.371810E+02 -6.714658E+00 -2.273652E+00 6.830172E+01 2.340687E+02 4.867159E+01 1.188724E+02 -6.215002E+00 -1.956978E+00 5.885634E+01 1.736180E+02 4.170434E+01 8.719622E+01 -5.253064E+00 -1.396224E+00 4.371848E+01 9.592893E+01 3.106403E+01 4.844308E+01 -3.818076E+00 -7.509442E-01 2.338413E+01 2.752467E+01 1.636713E+01 1.347770E+01 -2.219928E+00 -2.515492E-01 tally 3: 1.538752E+01 1.196478E+01 @@ -364,6 +344,47 @@ tally 4: 0.000000E+00 0.000000E+00 0.000000E+00 +tally 5: +1.538652E+01 +1.196332E+01 +2.252427E+00 +2.605738E-01 +2.911344E+01 +4.267319E+01 +3.873926E+00 +7.615035E-01 +3.884516E+01 +7.604619E+01 +5.280610E+00 +1.414008E+00 +4.672391E+01 +1.096625E+02 +6.261805E+00 +1.983205E+00 +5.058447E+01 +1.283588E+02 +6.733810E+00 +2.278242E+00 +5.033589E+01 +1.271898E+02 +6.714658E+00 +2.273652E+00 +4.687563E+01 +1.102719E+02 +6.215002E+00 +1.956978E+00 +4.013134E+01 +8.075062E+01 +5.253064E+00 +1.396224E+00 +2.996497E+01 +4.508840E+01 +3.818076E+00 +7.509442E-01 +1.574994E+01 +1.248291E+01 +2.219928E+00 +2.515492E-01 cmfd indices 1.000000E+01 1.000000E+00 diff --git a/tests/regression_tests/cmfd_nofeed/results_true.dat b/tests/regression_tests/cmfd_nofeed/results_true.dat index f00966cf8f..1636af364e 100644 --- a/tests/regression_tests/cmfd_nofeed/results_true.dat +++ b/tests/regression_tests/cmfd_nofeed/results_true.dat @@ -26,62 +26,42 @@ tally 2: 2.726751E+01 1.624000E+01 1.334217E+01 -2.239367E+00 -2.607315E-01 4.184801E+01 8.813954E+01 2.955600E+01 4.401685E+01 -3.937924E+00 -7.877545E-01 5.620224E+01 1.589242E+02 3.981400E+01 7.983679E+01 -5.183337E+00 -1.367303E+00 6.834724E+01 2.342245E+02 4.869600E+01 1.189597E+02 -6.288549E+00 -1.997858E+00 7.481522E+01 2.802998E+02 5.346500E+01 1.431835E+02 -6.691123E+00 -2.252645E+00 7.381412E+01 2.733775E+02 5.269700E+01 1.393729E+02 -6.846095E+00 -2.360683E+00 6.907776E+01 2.396752E+02 4.918500E+01 1.215909E+02 -6.400076E+00 -2.073871E+00 5.783261E+01 1.680814E+02 4.107800E+01 8.480751E+01 -5.269220E+00 -1.404986E+00 4.120212E+01 8.516647E+01 2.930300E+01 4.310295E+01 -3.730803E+00 -7.015777E-01 2.228419E+01 2.504034E+01 1.554100E+01 1.217931E+01 -2.126451E+00 -2.315275E-01 tally 3: 1.561100E+01 1.233967E+01 @@ -364,6 +344,47 @@ tally 4: 0.000000E+00 0.000000E+00 0.000000E+00 +tally 5: +1.560800E+01 +1.233482E+01 +2.239367E+00 +2.607315E-01 +2.847600E+01 +4.087518E+01 +3.937924E+00 +7.877545E-01 +3.833600E+01 +7.405661E+01 +5.183337E+00 +1.367303E+00 +4.686600E+01 +1.101919E+02 +6.288549E+00 +1.997858E+00 +5.154500E+01 +1.331141E+02 +6.691123E+00 +2.252645E+00 +5.067000E+01 +1.288871E+02 +6.846095E+00 +2.360683E+00 +4.737700E+01 +1.128379E+02 +6.400076E+00 +2.073871E+00 +3.952800E+01 +7.854943E+01 +5.269220E+00 +1.404986E+00 +2.818600E+01 +3.989536E+01 +3.730803E+00 +7.015777E-01 +1.497300E+01 +1.131008E+01 +2.126451E+00 +2.315275E-01 cmfd indices 1.000000E+01 1.000000E+00 diff --git a/tests/regression_tests/mgxs_library_ce_to_mg/inputs_true.dat b/tests/regression_tests/mgxs_library_ce_to_mg/inputs_true.dat index 70996fe378..bc5c4b2d46 100644 --- a/tests/regression_tests/mgxs_library_ce_to_mg/inputs_true.dat +++ b/tests/regression_tests/mgxs_library_ce_to_mg/inputs_true.dat @@ -59,10 +59,13 @@ 0.0 0.625 20000000.0 - + + 3 + + 2 - + 3 @@ -108,9 +111,9 @@ analog - 1 2 7 + 1 2 7 11 total - nu-scatter-P3 + nu-scatter analog @@ -126,121 +129,121 @@ analog - 14 2 + 15 2 total flux tracklength - 14 2 + 15 2 total total tracklength - 14 2 + 15 2 total flux tracklength - 14 2 + 15 2 total absorption tracklength - 14 2 + 15 2 total flux analog - 14 2 7 + 15 2 7 total nu-fission analog - 14 2 + 15 2 total flux analog - 14 2 7 + 15 2 7 11 total - nu-scatter-P3 + nu-scatter analog - 14 2 7 + 15 2 7 total nu-scatter analog - 14 2 7 + 15 2 7 total scatter analog - 27 2 + 29 2 total flux tracklength - 27 2 + 29 2 total total tracklength - 27 2 + 29 2 total flux tracklength - 27 2 + 29 2 total absorption tracklength - 27 2 + 29 2 total flux analog - 27 2 7 + 29 2 7 total nu-fission analog - 27 2 + 29 2 total flux analog - 27 2 7 + 29 2 7 11 total - nu-scatter-P3 + nu-scatter analog - 27 2 7 + 29 2 7 total nu-scatter analog - 27 2 7 + 29 2 7 total scatter analog diff --git a/tests/regression_tests/mgxs_library_condense/inputs_true.dat b/tests/regression_tests/mgxs_library_condense/inputs_true.dat index ef6c4c5206..5aedd383d0 100644 --- a/tests/regression_tests/mgxs_library_condense/inputs_true.dat +++ b/tests/regression_tests/mgxs_library_condense/inputs_true.dat @@ -59,16 +59,22 @@ 0.0 0.625 20000000.0 - + + 1 + + + 3 + + 0.0 20000000.0 - + 1 2 3 4 5 6 - + 2 - + 3 @@ -102,9 +108,9 @@ analog - 1 5 + 1 5 6 total - scatter-1 + scatter analog @@ -126,9 +132,9 @@ analog - 1 5 + 1 5 6 total - nu-scatter-1 + nu-scatter analog @@ -228,9 +234,9 @@ analog - 1 2 5 + 1 2 5 28 total - scatter-P3 + scatter analog @@ -240,9 +246,9 @@ analog - 1 2 5 + 1 2 5 28 total - nu-scatter-P3 + nu-scatter analog @@ -288,9 +294,9 @@ tracklength - 1 2 5 + 1 2 5 28 total - scatter-P3 + scatter analog @@ -306,883 +312,865 @@ tracklength - 1 2 5 + 1 2 5 28 total - scatter-P3 + scatter analog 1 2 5 total - nu-scatter-0 + nu-scatter analog - 1 2 5 + 1 52 total - scatter-0 + nu-fission analog - 1 46 + 1 5 total nu-fission analog - 1 5 + 1 52 total - nu-fission + prompt-nu-fission analog - 1 46 + 1 5 total prompt-nu-fission analog - 1 5 + 1 2 total - prompt-nu-fission - analog + flux + tracklength 1 2 total - flux + inverse-velocity tracklength 1 2 total - inverse-velocity + flux tracklength 1 2 total - flux + prompt-nu-fission tracklength - 1 2 - total - prompt-nu-fission - tracklength - - 1 2 total flux analog - + 1 2 5 total prompt-nu-fission analog - + 1 2 total flux tracklength - - 1 59 2 + + 1 65 2 total delayed-nu-fission tracklength + + 1 65 52 + total + delayed-nu-fission + analog + - 1 59 46 + 1 65 5 total delayed-nu-fission analog - 1 59 5 - total - delayed-nu-fission - analog - - 1 2 total nu-fission tracklength + + 1 65 2 + total + delayed-nu-fission + tracklength + - 1 59 2 + 1 65 2 total delayed-nu-fission tracklength - 1 59 2 - total - delayed-nu-fission - tracklength - - - 1 59 2 + 1 65 2 total decay-rate tracklength - + 1 2 total flux analog - - 1 59 2 5 + + 1 65 2 5 total delayed-nu-fission analog - - 74 2 + + 80 2 total flux tracklength + + 80 2 + total + total + tracklength + - 74 2 + 80 2 total - total + flux tracklength - 74 2 + 80 2 total - flux + total tracklength - 74 2 - total - total - tracklength - - - 74 2 + 80 2 total flux analog + + 80 5 6 + total + scatter + analog + - 74 5 - total - scatter-1 - analog - - - 74 2 + 80 2 total flux tracklength - - 74 2 + + 80 2 total total tracklength - - 74 2 + + 80 2 total flux analog + + 80 5 6 + total + nu-scatter + analog + - 74 5 - total - nu-scatter-1 - analog - - - 74 2 + 80 2 total flux tracklength + + 80 2 + total + absorption + tracklength + - 74 2 + 80 2 total - absorption + flux tracklength - 74 2 - total - flux - tracklength - - - 74 2 + 80 2 total absorption tracklength - - 74 2 + + 80 2 total fission tracklength + + 80 2 + total + flux + tracklength + - 74 2 - total - flux - tracklength - - - 74 2 + 80 2 total fission tracklength - - 74 2 + + 80 2 total flux tracklength - - 74 2 + + 80 2 total nu-fission tracklength - - 74 2 + + 80 2 total flux tracklength - - 74 2 + + 80 2 total kappa-fission tracklength - - 74 2 + + 80 2 total flux tracklength + + 80 2 + total + scatter + tracklength + - 74 2 - total - scatter - tracklength - - - 74 2 + 80 2 total flux analog + + 80 2 + total + nu-scatter + analog + - 74 2 + 80 2 total - nu-scatter + flux analog - 74 2 + 80 2 5 28 total - flux + scatter analog - 74 2 5 - total - scatter-P3 - analog - - - 74 2 + 80 2 total flux analog - - 74 2 5 - total - nu-scatter-P3 - analog - - - 74 2 5 + + 80 2 5 28 total nu-scatter analog - - 74 2 5 + + 80 2 5 + total + nu-scatter + analog + + + 80 2 5 total scatter analog + + 80 2 + total + flux + analog + - 74 2 + 80 2 5 total - flux + nu-fission analog - 74 2 5 + 80 2 5 total - nu-fission + scatter analog - 74 2 5 - total - scatter - analog - - - 74 2 + 80 2 total flux tracklength + + 80 2 + total + scatter + tracklength + - 74 2 + 80 2 5 28 total scatter - tracklength - - - 74 2 5 - total - scatter-P3 analog - - 74 2 + + 80 2 total flux tracklength - - 74 2 + + 80 2 total scatter tracklength - - 74 2 5 + + 80 2 5 28 total - scatter-P3 + scatter + analog + + + 80 2 5 + total + nu-scatter analog - 74 2 5 + 80 52 total - nu-scatter-0 + nu-fission analog - 74 2 5 + 80 5 total - scatter-0 + nu-fission analog - 74 46 + 80 52 total - nu-fission + prompt-nu-fission analog - 74 5 + 80 5 total - nu-fission + prompt-nu-fission analog - 74 46 + 80 2 total - prompt-nu-fission - analog + flux + tracklength - 74 5 + 80 2 total - prompt-nu-fission - analog + inverse-velocity + tracklength - 74 2 + 80 2 total flux tracklength - 74 2 + 80 2 total - inverse-velocity + prompt-nu-fission tracklength - 74 2 + 80 2 total flux - tracklength + analog - 74 2 + 80 2 5 total prompt-nu-fission - tracklength + analog - 74 2 + 80 2 total flux - analog + tracklength - 74 2 5 + 80 65 2 total - prompt-nu-fission - analog + delayed-nu-fission + tracklength - 74 2 + 80 65 52 total - flux - tracklength + delayed-nu-fission + analog - 74 59 2 + 80 65 5 total delayed-nu-fission - tracklength + analog - 74 59 46 - total - delayed-nu-fission - analog - - - 74 59 5 - total - delayed-nu-fission - analog - - - 74 2 + 80 2 total nu-fission tracklength + + 80 65 2 + total + delayed-nu-fission + tracklength + + + 80 65 2 + total + delayed-nu-fission + tracklength + - 74 59 2 - total - delayed-nu-fission - tracklength - - - 74 59 2 - total - delayed-nu-fission - tracklength - - - 74 59 2 + 80 65 2 total decay-rate tracklength - - 74 2 + + 80 2 total flux analog - - 74 59 2 5 + + 80 65 2 5 total delayed-nu-fission analog + + 159 2 + total + flux + tracklength + + + 159 2 + total + total + tracklength + - 147 2 + 159 2 total flux tracklength - 147 2 + 159 2 total total tracklength - 147 2 + 159 2 total flux - tracklength + analog - 147 2 + 159 5 6 total - total - tracklength + scatter + analog - 147 2 - total - flux - analog - - - 147 5 - total - scatter-1 - analog - - - 147 2 + 159 2 total flux tracklength - - 147 2 + + 159 2 total total tracklength - - 147 2 + + 159 2 total flux analog - - 147 5 + + 159 5 6 total - nu-scatter-1 + nu-scatter analog + + 159 2 + total + flux + tracklength + + + 159 2 + total + absorption + tracklength + - 147 2 + 159 2 total flux tracklength - 147 2 + 159 2 total absorption tracklength - 147 2 + 159 2 + total + fission + tracklength + + + 159 2 total flux tracklength - - 147 2 - total - absorption - tracklength - - 147 2 + 159 2 total fission tracklength - 147 2 + 159 2 total flux tracklength - 147 2 + 159 2 total - fission + nu-fission tracklength - 147 2 + 159 2 total flux tracklength - 147 2 + 159 2 total - nu-fission + kappa-fission tracklength - 147 2 + 159 2 total flux tracklength - 147 2 - total - kappa-fission - tracklength - - - 147 2 - total - flux - tracklength - - - 147 2 + 159 2 total scatter tracklength + + 159 2 + total + flux + analog + + + 159 2 + total + nu-scatter + analog + - 147 2 + 159 2 total flux analog - 147 2 + 159 2 5 28 total - nu-scatter + scatter analog - 147 2 + 159 2 total flux analog - 147 2 5 - total - scatter-P3 - analog - - - 147 2 - total - flux - analog - - - 147 2 5 - total - nu-scatter-P3 - analog - - - 147 2 5 + 159 2 5 28 total nu-scatter analog - - 147 2 5 + + 159 2 5 + total + nu-scatter + analog + + + 159 2 5 total scatter analog + + 159 2 + total + flux + analog + + + 159 2 5 + total + nu-fission + analog + - 147 2 + 159 2 5 total - flux + scatter analog - 147 2 5 - total - nu-fission - analog - - - 147 2 5 - total - scatter - analog - - - 147 2 + 159 2 total flux tracklength - - 147 2 + + 159 2 total scatter tracklength + + 159 2 5 28 + total + scatter + analog + + + 159 2 + total + flux + tracklength + - 147 2 5 - total - scatter-P3 - analog - - - 147 2 - total - flux - tracklength - - - 147 2 + 159 2 total scatter tracklength - - 147 2 5 + + 159 2 5 28 total - scatter-P3 + scatter + analog + + + 159 2 5 + total + nu-scatter + analog + + + 159 52 + total + nu-fission analog - 147 2 5 + 159 5 total - nu-scatter-0 + nu-fission analog - 147 2 5 + 159 52 total - scatter-0 + prompt-nu-fission analog - 147 46 + 159 5 total - nu-fission + prompt-nu-fission analog - 147 5 - total - nu-fission - analog - - - 147 46 - total - prompt-nu-fission - analog - - - 147 5 - total - prompt-nu-fission - analog - - - 147 2 + 159 2 total flux tracklength - - 147 2 + + 159 2 total inverse-velocity tracklength - - 147 2 + + 159 2 total flux tracklength - - 147 2 + + 159 2 total prompt-nu-fission tracklength + + 159 2 + total + flux + analog + + + 159 2 5 + total + prompt-nu-fission + analog + + + 159 2 + total + flux + tracklength + - 147 2 + 159 65 2 total - flux - analog + delayed-nu-fission + tracklength - 147 2 5 + 159 65 52 total - prompt-nu-fission + delayed-nu-fission analog - 147 2 + 159 65 5 total - flux - tracklength + delayed-nu-fission + analog - 147 59 2 - total - delayed-nu-fission - tracklength - - - 147 59 46 - total - delayed-nu-fission - analog - - - 147 59 5 - total - delayed-nu-fission - analog - - - 147 2 + 159 2 total nu-fission tracklength - - 147 59 2 + + 159 65 2 total delayed-nu-fission tracklength - - 147 59 2 + + 159 65 2 total delayed-nu-fission tracklength - - 147 59 2 + + 159 65 2 total decay-rate tracklength - - 147 2 + + 159 2 total flux analog - - 147 59 2 5 + + 159 65 2 5 total delayed-nu-fission analog diff --git a/tests/regression_tests/mgxs_library_condense/results_true.dat b/tests/regression_tests/mgxs_library_condense/results_true.dat index 0c9adedb1f..32d3d2e1a5 100644 --- a/tests/regression_tests/mgxs_library_condense/results_true.dat +++ b/tests/regression_tests/mgxs_library_condense/results_true.dat @@ -18,32 +18,32 @@ 0 1 1 total 0.388721 0.01783 material group in nuclide mean std. dev. 0 1 1 total 0.389304 0.023076 - material group in group out nuclide moment mean std. dev. -0 1 1 1 total P0 0.389304 0.023146 -1 1 1 1 total P1 0.046224 0.005907 -2 1 1 1 total P2 0.017984 0.002883 -3 1 1 1 total P3 0.006628 0.002457 - material group in group out nuclide moment mean std. dev. -0 1 1 1 total P0 0.389304 0.023146 -1 1 1 1 total P1 0.046224 0.005907 -2 1 1 1 total P2 0.017984 0.002883 -3 1 1 1 total P3 0.006628 0.002457 + material group in group out legendre nuclide mean std. dev. +0 1 1 1 P0 total 0.389304 0.023146 +1 1 1 1 P1 total 0.046224 0.005907 +2 1 1 1 P2 total 0.017984 0.002883 +3 1 1 1 P3 total 0.006628 0.002457 + material group in group out legendre nuclide mean std. dev. +0 1 1 1 P0 total 0.389304 0.023146 +1 1 1 1 P1 total 0.046224 0.005907 +2 1 1 1 P2 total 0.017984 0.002883 +3 1 1 1 P3 total 0.006628 0.002457 material group in group out nuclide mean std. dev. 0 1 1 1 total 1.0 0.066111 material group in group out nuclide mean std. dev. 0 1 1 1 total 0.085835 0.005592 material group in group out nuclide mean std. dev. 0 1 1 1 total 1.0 0.066111 - material group in group out nuclide moment mean std. dev. -0 1 1 1 total P0 0.388721 0.031279 -1 1 1 1 total P1 0.046155 0.006407 -2 1 1 1 total P2 0.017957 0.003039 -3 1 1 1 total P3 0.006618 0.002480 - material group in group out nuclide moment mean std. dev. -0 1 1 1 total P0 0.388721 0.040482 -1 1 1 1 total P1 0.046155 0.007097 -2 1 1 1 total P2 0.017957 0.003262 -3 1 1 1 total P3 0.006618 0.002518 + material group in group out legendre nuclide mean std. dev. +0 1 1 1 P0 total 0.388721 0.031279 +1 1 1 1 P1 total 0.046155 0.006407 +2 1 1 1 P2 total 0.017957 0.003039 +3 1 1 1 P3 total 0.006618 0.002480 + material group in group out legendre nuclide mean std. dev. +0 1 1 1 P0 total 0.388721 0.040482 +1 1 1 1 P1 total 0.046155 0.007097 +2 1 1 1 P2 total 0.017957 0.003262 +3 1 1 1 P3 total 0.006618 0.002518 material group out nuclide mean std. dev. 0 1 1 total 1.0 0.046071 material group out nuclide mean std. dev. @@ -109,32 +109,32 @@ 0 2 1 total 0.309384 0.013551 material group in nuclide mean std. dev. 0 2 1 total 0.307987 0.029308 - material group in group out nuclide moment mean std. dev. -0 2 1 1 total P0 0.307987 0.029308 -1 2 1 1 total P1 0.030617 0.007464 -2 2 1 1 total P2 0.018911 0.004323 -3 2 1 1 total P3 0.006235 0.003338 - material group in group out nuclide moment mean std. dev. -0 2 1 1 total P0 0.307987 0.029308 -1 2 1 1 total P1 0.030617 0.007464 -2 2 1 1 total P2 0.018911 0.004323 -3 2 1 1 total P3 0.006235 0.003338 + material group in group out legendre nuclide mean std. dev. +0 2 1 1 P0 total 0.307987 0.029308 +1 2 1 1 P1 total 0.030617 0.007464 +2 2 1 1 P2 total 0.018911 0.004323 +3 2 1 1 P3 total 0.006235 0.003338 + material group in group out legendre nuclide mean std. dev. +0 2 1 1 P0 total 0.307987 0.029308 +1 2 1 1 P1 total 0.030617 0.007464 +2 2 1 1 P2 total 0.018911 0.004323 +3 2 1 1 P3 total 0.006235 0.003338 material group in group out nuclide mean std. dev. 0 2 1 1 total 1.0 0.095039 material group in group out nuclide mean std. dev. 0 2 1 1 total 0.0 0.0 material group in group out nuclide mean std. dev. 0 2 1 1 total 1.0 0.095039 - material group in group out nuclide moment mean std. dev. -0 2 1 1 total P0 0.309384 0.032376 -1 2 1 1 total P1 0.030756 0.007617 -2 2 1 1 total P2 0.018997 0.004420 -3 2 1 1 total P3 0.006263 0.003364 - material group in group out nuclide moment mean std. dev. -0 2 1 1 total P0 0.309384 0.043735 -1 2 1 1 total P1 0.030756 0.008159 -2 2 1 1 total P2 0.018997 0.004775 -3 2 1 1 total P3 0.006263 0.003417 + material group in group out legendre nuclide mean std. dev. +0 2 1 1 P0 total 0.309384 0.032376 +1 2 1 1 P1 total 0.030756 0.007617 +2 2 1 1 P2 total 0.018997 0.004420 +3 2 1 1 P3 total 0.006263 0.003364 + material group in group out legendre nuclide mean std. dev. +0 2 1 1 P0 total 0.309384 0.043735 +1 2 1 1 P1 total 0.030756 0.008159 +2 2 1 1 P2 total 0.018997 0.004775 +3 2 1 1 P3 total 0.006263 0.003417 material group out nuclide mean std. dev. 0 2 1 total 0.0 0.0 material group out nuclide mean std. dev. @@ -200,32 +200,32 @@ 0 3 1 total 0.898938 0.043493 material group in nuclide mean std. dev. 0 3 1 total 0.903415 0.043959 - material group in group out nuclide moment mean std. dev. -0 3 1 1 total P0 0.903415 0.043586 -1 3 1 1 total P1 0.410417 0.015877 -2 3 1 1 total P2 0.143301 0.007187 -3 3 1 1 total P3 0.008739 0.003571 - material group in group out nuclide moment mean std. dev. -0 3 1 1 total P0 0.903415 0.043586 -1 3 1 1 total P1 0.410417 0.015877 -2 3 1 1 total P2 0.143301 0.007187 -3 3 1 1 total P3 0.008739 0.003571 + material group in group out legendre nuclide mean std. dev. +0 3 1 1 P0 total 0.903415 0.043586 +1 3 1 1 P1 total 0.410417 0.015877 +2 3 1 1 P2 total 0.143301 0.007187 +3 3 1 1 P3 total 0.008739 0.003571 + material group in group out legendre nuclide mean std. dev. +0 3 1 1 P0 total 0.903415 0.043586 +1 3 1 1 P1 total 0.410417 0.015877 +2 3 1 1 P2 total 0.143301 0.007187 +3 3 1 1 P3 total 0.008739 0.003571 material group in group out nuclide mean std. dev. 0 3 1 1 total 1.0 0.056867 material group in group out nuclide mean std. dev. 0 3 1 1 total 0.0 0.0 material group in group out nuclide mean std. dev. 0 3 1 1 total 1.0 0.056867 - material group in group out nuclide moment mean std. dev. -0 3 1 1 total P0 0.898938 0.067118 -1 3 1 1 total P1 0.408384 0.028127 -2 3 1 1 total P2 0.142591 0.010824 -3 3 1 1 total P3 0.008696 0.003588 - material group in group out nuclide moment mean std. dev. -0 3 1 1 total P0 0.898938 0.084369 -1 3 1 1 total P1 0.408384 0.036475 -2 3 1 1 total P2 0.142591 0.013525 -3 3 1 1 total P3 0.008696 0.003622 + material group in group out legendre nuclide mean std. dev. +0 3 1 1 P0 total 0.898938 0.067118 +1 3 1 1 P1 total 0.408384 0.028127 +2 3 1 1 P2 total 0.142591 0.010824 +3 3 1 1 P3 total 0.008696 0.003588 + material group in group out legendre nuclide mean std. dev. +0 3 1 1 P0 total 0.898938 0.084369 +1 3 1 1 P1 total 0.408384 0.036475 +2 3 1 1 P2 total 0.142591 0.013525 +3 3 1 1 P3 total 0.008696 0.003622 material group out nuclide mean std. dev. 0 3 1 total 0.0 0.0 material group out nuclide mean std. dev. diff --git a/tests/regression_tests/mgxs_library_distribcell/inputs_true.dat b/tests/regression_tests/mgxs_library_distribcell/inputs_true.dat index ba7dc05ff7..f6748d1508 100644 --- a/tests/regression_tests/mgxs_library_distribcell/inputs_true.dat +++ b/tests/regression_tests/mgxs_library_distribcell/inputs_true.dat @@ -86,7 +86,13 @@ 0.0 20000000.0 - + + 1 + + + 3 + + 1 2 3 4 5 6 @@ -120,9 +126,9 @@ analog - 1 5 + 1 5 6 total - scatter-1 + scatter analog @@ -144,9 +150,9 @@ analog - 1 5 + 1 5 6 total - nu-scatter-1 + nu-scatter analog @@ -246,9 +252,9 @@ analog - 1 2 5 + 1 2 5 28 total - scatter-P3 + scatter analog @@ -258,9 +264,9 @@ analog - 1 2 5 + 1 2 5 28 total - nu-scatter-P3 + nu-scatter analog @@ -306,9 +312,9 @@ tracklength - 1 2 5 + 1 2 5 28 total - scatter-P3 + scatter analog @@ -324,139 +330,133 @@ tracklength - 1 2 5 + 1 2 5 28 total - scatter-P3 + scatter analog 1 2 5 total - nu-scatter-0 + nu-scatter analog - 1 2 5 + 1 2 total - scatter-0 + nu-fission analog - 1 2 + 1 5 total nu-fission analog - 1 5 + 1 2 total - nu-fission + prompt-nu-fission analog - 1 2 + 1 5 total prompt-nu-fission analog - 1 5 - total - prompt-nu-fission - analog - - 1 2 total flux tracklength - + 1 2 total inverse-velocity tracklength - + 1 2 total flux tracklength + + 1 2 + total + prompt-nu-fission + tracklength + - 1 2 - total - prompt-nu-fission - tracklength - - 1 2 total flux analog - + 1 2 5 total prompt-nu-fission analog - + 1 2 total flux tracklength - - 1 59 2 + + 1 65 2 total delayed-nu-fission tracklength + + 1 65 2 + total + delayed-nu-fission + analog + - 1 59 2 + 1 65 5 total delayed-nu-fission analog - 1 59 5 - total - delayed-nu-fission - analog - - 1 2 total nu-fission tracklength + + 1 65 2 + total + delayed-nu-fission + tracklength + - 1 59 2 + 1 65 2 total delayed-nu-fission tracklength - 1 59 2 - total - delayed-nu-fission - tracklength - - - 1 59 2 + 1 65 2 total decay-rate tracklength - + 1 2 total flux analog - - 1 59 2 5 + + 1 65 2 5 total delayed-nu-fission analog diff --git a/tests/regression_tests/mgxs_library_distribcell/results_true.dat b/tests/regression_tests/mgxs_library_distribcell/results_true.dat index e9277c9758..d5496362c9 100644 --- a/tests/regression_tests/mgxs_library_distribcell/results_true.dat +++ b/tests/regression_tests/mgxs_library_distribcell/results_true.dat @@ -18,32 +18,32 @@ 0 ((0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13... 1 total 0.390797 0.008717 sum(distribcell) group in nuclide mean std. dev. 0 ((0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13... 1 total 0.387332 0.014241 - sum(distribcell) group in group out nuclide moment mean std. dev. -0 ((0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13... 1 1 total P0 0.387009 0.014230 -1 ((0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13... 1 1 total P1 0.047179 0.004923 -2 ((0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13... 1 1 total P2 0.015713 0.003654 -3 ((0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13... 1 1 total P3 0.005378 0.003137 - sum(distribcell) group in group out nuclide moment mean std. dev. -0 ((0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13... 1 1 total P0 0.387332 0.014241 -1 ((0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13... 1 1 total P1 0.047187 0.004933 -2 ((0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13... 1 1 total P2 0.015727 0.003654 -3 ((0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13... 1 1 total P3 0.005387 0.003141 + sum(distribcell) group in group out legendre nuclide mean std. dev. +0 ((0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13... 1 1 P0 total 0.387009 0.014230 +1 ((0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13... 1 1 P1 total 0.047179 0.004923 +2 ((0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13... 1 1 P2 total 0.015713 0.003654 +3 ((0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13... 1 1 P3 total 0.005378 0.003137 + sum(distribcell) group in group out legendre nuclide mean std. dev. +0 ((0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13... 1 1 P0 total 0.387332 0.014241 +1 ((0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13... 1 1 P1 total 0.047187 0.004933 +2 ((0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13... 1 1 P2 total 0.015727 0.003654 +3 ((0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13... 1 1 P3 total 0.005387 0.003141 sum(distribcell) group in group out nuclide mean std. dev. 0 ((0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13... 1 1 total 1.000834 0.037242 sum(distribcell) group in group out nuclide mean std. dev. 0 ((0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13... 1 1 total 0.094516 0.0059 sum(distribcell) group in group out nuclide mean std. dev. 0 ((0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13... 1 1 total 1.0 0.037213 - sum(distribcell) group in group out nuclide moment mean std. dev. -0 ((0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13... 1 1 total P0 0.390797 0.016955 -1 ((0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13... 1 1 total P1 0.047641 0.005091 -2 ((0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13... 1 1 total P2 0.015866 0.003708 -3 ((0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13... 1 1 total P3 0.005430 0.003170 - sum(distribcell) group in group out nuclide moment mean std. dev. -0 ((0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13... 1 1 total P0 0.391123 0.022356 -1 ((0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13... 1 1 total P1 0.047680 0.005395 -2 ((0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13... 1 1 total P2 0.015880 0.003758 -3 ((0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13... 1 1 total P3 0.005435 0.003179 + sum(distribcell) group in group out legendre nuclide mean std. dev. +0 ((0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13... 1 1 P0 total 0.390797 0.016955 +1 ((0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13... 1 1 P1 total 0.047641 0.005091 +2 ((0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13... 1 1 P2 total 0.015866 0.003708 +3 ((0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13... 1 1 P3 total 0.005430 0.003170 + sum(distribcell) group in group out legendre nuclide mean std. dev. +0 ((0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13... 1 1 P0 total 0.391123 0.022356 +1 ((0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13... 1 1 P1 total 0.047680 0.005395 +2 ((0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13... 1 1 P2 total 0.015880 0.003758 +3 ((0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13... 1 1 P3 total 0.005435 0.003179 sum(distribcell) group out nuclide mean std. dev. 0 ((0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13... 1 total 1.0 0.080455 sum(distribcell) group out nuclide mean std. dev. diff --git a/tests/regression_tests/mgxs_library_hdf5/inputs_true.dat b/tests/regression_tests/mgxs_library_hdf5/inputs_true.dat index ef6c4c5206..5aedd383d0 100644 --- a/tests/regression_tests/mgxs_library_hdf5/inputs_true.dat +++ b/tests/regression_tests/mgxs_library_hdf5/inputs_true.dat @@ -59,16 +59,22 @@ 0.0 0.625 20000000.0 - + + 1 + + + 3 + + 0.0 20000000.0 - + 1 2 3 4 5 6 - + 2 - + 3 @@ -102,9 +108,9 @@ analog - 1 5 + 1 5 6 total - scatter-1 + scatter analog @@ -126,9 +132,9 @@ analog - 1 5 + 1 5 6 total - nu-scatter-1 + nu-scatter analog @@ -228,9 +234,9 @@ analog - 1 2 5 + 1 2 5 28 total - scatter-P3 + scatter analog @@ -240,9 +246,9 @@ analog - 1 2 5 + 1 2 5 28 total - nu-scatter-P3 + nu-scatter analog @@ -288,9 +294,9 @@ tracklength - 1 2 5 + 1 2 5 28 total - scatter-P3 + scatter analog @@ -306,883 +312,865 @@ tracklength - 1 2 5 + 1 2 5 28 total - scatter-P3 + scatter analog 1 2 5 total - nu-scatter-0 + nu-scatter analog - 1 2 5 + 1 52 total - scatter-0 + nu-fission analog - 1 46 + 1 5 total nu-fission analog - 1 5 + 1 52 total - nu-fission + prompt-nu-fission analog - 1 46 + 1 5 total prompt-nu-fission analog - 1 5 + 1 2 total - prompt-nu-fission - analog + flux + tracklength 1 2 total - flux + inverse-velocity tracklength 1 2 total - inverse-velocity + flux tracklength 1 2 total - flux + prompt-nu-fission tracklength - 1 2 - total - prompt-nu-fission - tracklength - - 1 2 total flux analog - + 1 2 5 total prompt-nu-fission analog - + 1 2 total flux tracklength - - 1 59 2 + + 1 65 2 total delayed-nu-fission tracklength + + 1 65 52 + total + delayed-nu-fission + analog + - 1 59 46 + 1 65 5 total delayed-nu-fission analog - 1 59 5 - total - delayed-nu-fission - analog - - 1 2 total nu-fission tracklength + + 1 65 2 + total + delayed-nu-fission + tracklength + - 1 59 2 + 1 65 2 total delayed-nu-fission tracklength - 1 59 2 - total - delayed-nu-fission - tracklength - - - 1 59 2 + 1 65 2 total decay-rate tracklength - + 1 2 total flux analog - - 1 59 2 5 + + 1 65 2 5 total delayed-nu-fission analog - - 74 2 + + 80 2 total flux tracklength + + 80 2 + total + total + tracklength + - 74 2 + 80 2 total - total + flux tracklength - 74 2 + 80 2 total - flux + total tracklength - 74 2 - total - total - tracklength - - - 74 2 + 80 2 total flux analog + + 80 5 6 + total + scatter + analog + - 74 5 - total - scatter-1 - analog - - - 74 2 + 80 2 total flux tracklength - - 74 2 + + 80 2 total total tracklength - - 74 2 + + 80 2 total flux analog + + 80 5 6 + total + nu-scatter + analog + - 74 5 - total - nu-scatter-1 - analog - - - 74 2 + 80 2 total flux tracklength + + 80 2 + total + absorption + tracklength + - 74 2 + 80 2 total - absorption + flux tracklength - 74 2 - total - flux - tracklength - - - 74 2 + 80 2 total absorption tracklength - - 74 2 + + 80 2 total fission tracklength + + 80 2 + total + flux + tracklength + - 74 2 - total - flux - tracklength - - - 74 2 + 80 2 total fission tracklength - - 74 2 + + 80 2 total flux tracklength - - 74 2 + + 80 2 total nu-fission tracklength - - 74 2 + + 80 2 total flux tracklength - - 74 2 + + 80 2 total kappa-fission tracklength - - 74 2 + + 80 2 total flux tracklength + + 80 2 + total + scatter + tracklength + - 74 2 - total - scatter - tracklength - - - 74 2 + 80 2 total flux analog + + 80 2 + total + nu-scatter + analog + - 74 2 + 80 2 total - nu-scatter + flux analog - 74 2 + 80 2 5 28 total - flux + scatter analog - 74 2 5 - total - scatter-P3 - analog - - - 74 2 + 80 2 total flux analog - - 74 2 5 - total - nu-scatter-P3 - analog - - - 74 2 5 + + 80 2 5 28 total nu-scatter analog - - 74 2 5 + + 80 2 5 + total + nu-scatter + analog + + + 80 2 5 total scatter analog + + 80 2 + total + flux + analog + - 74 2 + 80 2 5 total - flux + nu-fission analog - 74 2 5 + 80 2 5 total - nu-fission + scatter analog - 74 2 5 - total - scatter - analog - - - 74 2 + 80 2 total flux tracklength + + 80 2 + total + scatter + tracklength + - 74 2 + 80 2 5 28 total scatter - tracklength - - - 74 2 5 - total - scatter-P3 analog - - 74 2 + + 80 2 total flux tracklength - - 74 2 + + 80 2 total scatter tracklength - - 74 2 5 + + 80 2 5 28 total - scatter-P3 + scatter + analog + + + 80 2 5 + total + nu-scatter analog - 74 2 5 + 80 52 total - nu-scatter-0 + nu-fission analog - 74 2 5 + 80 5 total - scatter-0 + nu-fission analog - 74 46 + 80 52 total - nu-fission + prompt-nu-fission analog - 74 5 + 80 5 total - nu-fission + prompt-nu-fission analog - 74 46 + 80 2 total - prompt-nu-fission - analog + flux + tracklength - 74 5 + 80 2 total - prompt-nu-fission - analog + inverse-velocity + tracklength - 74 2 + 80 2 total flux tracklength - 74 2 + 80 2 total - inverse-velocity + prompt-nu-fission tracklength - 74 2 + 80 2 total flux - tracklength + analog - 74 2 + 80 2 5 total prompt-nu-fission - tracklength + analog - 74 2 + 80 2 total flux - analog + tracklength - 74 2 5 + 80 65 2 total - prompt-nu-fission - analog + delayed-nu-fission + tracklength - 74 2 + 80 65 52 total - flux - tracklength + delayed-nu-fission + analog - 74 59 2 + 80 65 5 total delayed-nu-fission - tracklength + analog - 74 59 46 - total - delayed-nu-fission - analog - - - 74 59 5 - total - delayed-nu-fission - analog - - - 74 2 + 80 2 total nu-fission tracklength + + 80 65 2 + total + delayed-nu-fission + tracklength + + + 80 65 2 + total + delayed-nu-fission + tracklength + - 74 59 2 - total - delayed-nu-fission - tracklength - - - 74 59 2 - total - delayed-nu-fission - tracklength - - - 74 59 2 + 80 65 2 total decay-rate tracklength - - 74 2 + + 80 2 total flux analog - - 74 59 2 5 + + 80 65 2 5 total delayed-nu-fission analog + + 159 2 + total + flux + tracklength + + + 159 2 + total + total + tracklength + - 147 2 + 159 2 total flux tracklength - 147 2 + 159 2 total total tracklength - 147 2 + 159 2 total flux - tracklength + analog - 147 2 + 159 5 6 total - total - tracklength + scatter + analog - 147 2 - total - flux - analog - - - 147 5 - total - scatter-1 - analog - - - 147 2 + 159 2 total flux tracklength - - 147 2 + + 159 2 total total tracklength - - 147 2 + + 159 2 total flux analog - - 147 5 + + 159 5 6 total - nu-scatter-1 + nu-scatter analog + + 159 2 + total + flux + tracklength + + + 159 2 + total + absorption + tracklength + - 147 2 + 159 2 total flux tracklength - 147 2 + 159 2 total absorption tracklength - 147 2 + 159 2 + total + fission + tracklength + + + 159 2 total flux tracklength - - 147 2 - total - absorption - tracklength - - 147 2 + 159 2 total fission tracklength - 147 2 + 159 2 total flux tracklength - 147 2 + 159 2 total - fission + nu-fission tracklength - 147 2 + 159 2 total flux tracklength - 147 2 + 159 2 total - nu-fission + kappa-fission tracklength - 147 2 + 159 2 total flux tracklength - 147 2 - total - kappa-fission - tracklength - - - 147 2 - total - flux - tracklength - - - 147 2 + 159 2 total scatter tracklength + + 159 2 + total + flux + analog + + + 159 2 + total + nu-scatter + analog + - 147 2 + 159 2 total flux analog - 147 2 + 159 2 5 28 total - nu-scatter + scatter analog - 147 2 + 159 2 total flux analog - 147 2 5 - total - scatter-P3 - analog - - - 147 2 - total - flux - analog - - - 147 2 5 - total - nu-scatter-P3 - analog - - - 147 2 5 + 159 2 5 28 total nu-scatter analog - - 147 2 5 + + 159 2 5 + total + nu-scatter + analog + + + 159 2 5 total scatter analog + + 159 2 + total + flux + analog + + + 159 2 5 + total + nu-fission + analog + - 147 2 + 159 2 5 total - flux + scatter analog - 147 2 5 - total - nu-fission - analog - - - 147 2 5 - total - scatter - analog - - - 147 2 + 159 2 total flux tracklength - - 147 2 + + 159 2 total scatter tracklength + + 159 2 5 28 + total + scatter + analog + + + 159 2 + total + flux + tracklength + - 147 2 5 - total - scatter-P3 - analog - - - 147 2 - total - flux - tracklength - - - 147 2 + 159 2 total scatter tracklength - - 147 2 5 + + 159 2 5 28 total - scatter-P3 + scatter + analog + + + 159 2 5 + total + nu-scatter + analog + + + 159 52 + total + nu-fission analog - 147 2 5 + 159 5 total - nu-scatter-0 + nu-fission analog - 147 2 5 + 159 52 total - scatter-0 + prompt-nu-fission analog - 147 46 + 159 5 total - nu-fission + prompt-nu-fission analog - 147 5 - total - nu-fission - analog - - - 147 46 - total - prompt-nu-fission - analog - - - 147 5 - total - prompt-nu-fission - analog - - - 147 2 + 159 2 total flux tracklength - - 147 2 + + 159 2 total inverse-velocity tracklength - - 147 2 + + 159 2 total flux tracklength - - 147 2 + + 159 2 total prompt-nu-fission tracklength + + 159 2 + total + flux + analog + + + 159 2 5 + total + prompt-nu-fission + analog + + + 159 2 + total + flux + tracklength + - 147 2 + 159 65 2 total - flux - analog + delayed-nu-fission + tracklength - 147 2 5 + 159 65 52 total - prompt-nu-fission + delayed-nu-fission analog - 147 2 + 159 65 5 total - flux - tracklength + delayed-nu-fission + analog - 147 59 2 - total - delayed-nu-fission - tracklength - - - 147 59 46 - total - delayed-nu-fission - analog - - - 147 59 5 - total - delayed-nu-fission - analog - - - 147 2 + 159 2 total nu-fission tracklength - - 147 59 2 + + 159 65 2 total delayed-nu-fission tracklength - - 147 59 2 + + 159 65 2 total delayed-nu-fission tracklength - - 147 59 2 + + 159 65 2 total decay-rate tracklength - - 147 2 + + 159 2 total flux analog - - 147 59 2 5 + + 159 65 2 5 total delayed-nu-fission analog diff --git a/tests/regression_tests/mgxs_library_mesh/inputs_true.dat b/tests/regression_tests/mgxs_library_mesh/inputs_true.dat index aa2c904b19..299da0713c 100644 --- a/tests/regression_tests/mgxs_library_mesh/inputs_true.dat +++ b/tests/regression_tests/mgxs_library_mesh/inputs_true.dat @@ -323,7 +323,13 @@ 0.0 20000000.0 - + + 1 + + + 3 + + 1 2 3 4 5 6 @@ -357,9 +363,9 @@ analog - 1 5 + 1 5 6 total - scatter-1 + scatter analog @@ -381,9 +387,9 @@ analog - 1 5 + 1 5 6 total - nu-scatter-1 + nu-scatter analog @@ -483,9 +489,9 @@ analog - 1 2 5 + 1 2 5 28 total - scatter-P3 + scatter analog @@ -495,9 +501,9 @@ analog - 1 2 5 + 1 2 5 28 total - nu-scatter-P3 + nu-scatter analog @@ -543,9 +549,9 @@ tracklength - 1 2 5 + 1 2 5 28 total - scatter-P3 + scatter analog @@ -561,139 +567,133 @@ tracklength - 1 2 5 + 1 2 5 28 total - scatter-P3 + scatter analog 1 2 5 total - nu-scatter-0 + nu-scatter analog - 1 2 5 + 1 2 total - scatter-0 + nu-fission analog - 1 2 + 1 5 total nu-fission analog - 1 5 + 1 2 total - nu-fission + prompt-nu-fission analog - 1 2 + 1 5 total prompt-nu-fission analog - 1 5 - total - prompt-nu-fission - analog - - 1 2 total flux tracklength - + 1 2 total inverse-velocity tracklength - + 1 2 total flux tracklength + + 1 2 + total + prompt-nu-fission + tracklength + - 1 2 - total - prompt-nu-fission - tracklength - - 1 2 total flux analog - + 1 2 5 total prompt-nu-fission analog - + 1 2 total flux tracklength - - 1 59 2 + + 1 65 2 total delayed-nu-fission tracklength + + 1 65 2 + total + delayed-nu-fission + analog + - 1 59 2 + 1 65 5 total delayed-nu-fission analog - 1 59 5 - total - delayed-nu-fission - analog - - 1 2 total nu-fission tracklength + + 1 65 2 + total + delayed-nu-fission + tracklength + - 1 59 2 + 1 65 2 total delayed-nu-fission tracklength - 1 59 2 - total - delayed-nu-fission - tracklength - - - 1 59 2 + 1 65 2 total decay-rate tracklength - + 1 2 total flux analog - - 1 59 2 5 + + 1 65 2 5 total delayed-nu-fission analog diff --git a/tests/regression_tests/mgxs_library_mesh/results_true.dat b/tests/regression_tests/mgxs_library_mesh/results_true.dat index 4b9303fbf3..27c1ffdc97 100644 --- a/tests/regression_tests/mgxs_library_mesh/results_true.dat +++ b/tests/regression_tests/mgxs_library_mesh/results_true.dat @@ -58,42 +58,42 @@ 2 1 2 1 1 total 0.628158 0.064356 1 2 1 1 1 total 0.640809 0.158369 3 2 2 1 1 total 0.645171 0.080467 - mesh 1 group in group out nuclide moment mean std. dev. - x y z -0 1 1 1 1 1 total P0 0.763779 0.070696 -1 1 1 1 1 1 total P1 0.288556 0.024446 -2 1 1 1 1 1 total P2 0.082441 0.011443 -3 1 1 1 1 1 total P3 -0.005627 0.012638 -8 1 2 1 1 1 total P0 0.628158 0.064356 -9 1 2 1 1 1 total P1 0.245583 0.022676 -10 1 2 1 1 1 total P2 0.086370 0.007833 -11 1 2 1 1 1 total P3 0.019590 0.005345 -4 2 1 1 1 1 total P0 0.640809 0.158369 -5 2 1 1 1 1 total P1 0.273553 0.066437 -6 2 1 1 1 1 total P2 0.108446 0.024435 -7 2 1 1 1 1 total P3 0.012229 0.003785 -12 2 2 1 1 1 total P0 0.645171 0.080467 -13 2 2 1 1 1 total P1 0.252215 0.032154 -14 2 2 1 1 1 total P2 0.089251 0.009734 -15 2 2 1 1 1 total P3 0.004748 0.002987 - mesh 1 group in group out nuclide moment mean std. dev. - x y z -0 1 1 1 1 1 total P0 0.763779 0.070696 -1 1 1 1 1 1 total P1 0.288556 0.024446 -2 1 1 1 1 1 total P2 0.082441 0.011443 -3 1 1 1 1 1 total P3 -0.005627 0.012638 -8 1 2 1 1 1 total P0 0.628158 0.064356 -9 1 2 1 1 1 total P1 0.245583 0.022676 -10 1 2 1 1 1 total P2 0.086370 0.007833 -11 1 2 1 1 1 total P3 0.019590 0.005345 -4 2 1 1 1 1 total P0 0.640809 0.158369 -5 2 1 1 1 1 total P1 0.273553 0.066437 -6 2 1 1 1 1 total P2 0.108446 0.024435 -7 2 1 1 1 1 total P3 0.012229 0.003785 -12 2 2 1 1 1 total P0 0.645171 0.080467 -13 2 2 1 1 1 total P1 0.252215 0.032154 -14 2 2 1 1 1 total P2 0.089251 0.009734 -15 2 2 1 1 1 total P3 0.004748 0.002987 + mesh 1 group in group out legendre nuclide mean std. dev. + x y z +0 1 1 1 1 1 P0 total 0.763779 0.070696 +1 1 1 1 1 1 P1 total 0.288556 0.024446 +2 1 1 1 1 1 P2 total 0.082441 0.011443 +3 1 1 1 1 1 P3 total -0.005627 0.012638 +8 1 2 1 1 1 P0 total 0.628158 0.064356 +9 1 2 1 1 1 P1 total 0.245583 0.022676 +10 1 2 1 1 1 P2 total 0.086370 0.007833 +11 1 2 1 1 1 P3 total 0.019590 0.005345 +4 2 1 1 1 1 P0 total 0.640809 0.158369 +5 2 1 1 1 1 P1 total 0.273553 0.066437 +6 2 1 1 1 1 P2 total 0.108446 0.024435 +7 2 1 1 1 1 P3 total 0.012229 0.003785 +12 2 2 1 1 1 P0 total 0.645171 0.080467 +13 2 2 1 1 1 P1 total 0.252215 0.032154 +14 2 2 1 1 1 P2 total 0.089251 0.009734 +15 2 2 1 1 1 P3 total 0.004748 0.002987 + mesh 1 group in group out legendre nuclide mean std. dev. + x y z +0 1 1 1 1 1 P0 total 0.763779 0.070696 +1 1 1 1 1 1 P1 total 0.288556 0.024446 +2 1 1 1 1 1 P2 total 0.082441 0.011443 +3 1 1 1 1 1 P3 total -0.005627 0.012638 +8 1 2 1 1 1 P0 total 0.628158 0.064356 +9 1 2 1 1 1 P1 total 0.245583 0.022676 +10 1 2 1 1 1 P2 total 0.086370 0.007833 +11 1 2 1 1 1 P3 total 0.019590 0.005345 +4 2 1 1 1 1 P0 total 0.640809 0.158369 +5 2 1 1 1 1 P1 total 0.273553 0.066437 +6 2 1 1 1 1 P2 total 0.108446 0.024435 +7 2 1 1 1 1 P3 total 0.012229 0.003785 +12 2 2 1 1 1 P0 total 0.645171 0.080467 +13 2 2 1 1 1 P1 total 0.252215 0.032154 +14 2 2 1 1 1 P2 total 0.089251 0.009734 +15 2 2 1 1 1 P3 total 0.004748 0.002987 mesh 1 group in group out nuclide mean std. dev. x y z 0 1 1 1 1 1 total 1.0 0.108337 @@ -112,42 +112,42 @@ 2 1 2 1 1 1 total 1.0 0.113128 1 2 1 1 1 1 total 1.0 0.238517 3 2 2 1 1 1 total 1.0 0.132597 - mesh 1 group in group out nuclide moment mean std. dev. - x y z -0 1 1 1 1 1 total P0 0.735256 0.113047 -1 1 1 1 1 1 total P1 0.277780 0.041434 -2 1 1 1 1 1 total P2 0.079362 0.014706 -3 1 1 1 1 1 total P3 -0.005417 0.012184 -8 1 2 1 1 1 total P0 0.624575 0.110512 -9 1 2 1 1 1 total P1 0.244182 0.041824 -10 1 2 1 1 1 total P2 0.085877 0.014634 -11 1 2 1 1 1 total P3 0.019478 0.006012 -4 2 1 1 1 1 total P0 0.633925 0.212349 -5 2 1 1 1 1 total P1 0.270615 0.089799 -6 2 1 1 1 1 total P2 0.107281 0.034246 -7 2 1 1 1 1 total P3 0.012098 0.004637 -12 2 2 1 1 1 total P0 0.655214 0.126119 -13 2 2 1 1 1 total P1 0.256141 0.049765 -14 2 2 1 1 1 total P2 0.090641 0.016563 -15 2 2 1 1 1 total P3 0.004822 0.003115 - mesh 1 group in group out nuclide moment mean std. dev. - x y z -0 1 1 1 1 1 total P0 0.735256 0.138292 -1 1 1 1 1 1 total P1 0.277780 0.051210 -2 1 1 1 1 1 total P2 0.079362 0.017035 -3 1 1 1 1 1 total P3 -0.005417 0.012198 -8 1 2 1 1 1 total P0 0.624575 0.131169 -9 1 2 1 1 1 total P1 0.244182 0.050123 -10 1 2 1 1 1 total P2 0.085877 0.017565 -11 1 2 1 1 1 total P3 0.019478 0.006403 -4 2 1 1 1 1 total P0 0.633925 0.260681 -5 2 1 1 1 1 total P1 0.270615 0.110590 -6 2 1 1 1 1 total P2 0.107281 0.042750 -7 2 1 1 1 1 total P3 0.012098 0.005462 -12 2 2 1 1 1 total P0 0.655214 0.153147 -13 2 2 1 1 1 total P1 0.256141 0.060250 -14 2 2 1 1 1 total P2 0.090641 0.020464 -15 2 2 1 1 1 total P3 0.004822 0.003180 + mesh 1 group in group out legendre nuclide mean std. dev. + x y z +0 1 1 1 1 1 P0 total 0.735256 0.113047 +1 1 1 1 1 1 P1 total 0.277780 0.041434 +2 1 1 1 1 1 P2 total 0.079362 0.014706 +3 1 1 1 1 1 P3 total -0.005417 0.012184 +8 1 2 1 1 1 P0 total 0.624575 0.110512 +9 1 2 1 1 1 P1 total 0.244182 0.041824 +10 1 2 1 1 1 P2 total 0.085877 0.014634 +11 1 2 1 1 1 P3 total 0.019478 0.006012 +4 2 1 1 1 1 P0 total 0.633925 0.212349 +5 2 1 1 1 1 P1 total 0.270615 0.089799 +6 2 1 1 1 1 P2 total 0.107281 0.034246 +7 2 1 1 1 1 P3 total 0.012098 0.004637 +12 2 2 1 1 1 P0 total 0.655214 0.126119 +13 2 2 1 1 1 P1 total 0.256141 0.049765 +14 2 2 1 1 1 P2 total 0.090641 0.016563 +15 2 2 1 1 1 P3 total 0.004822 0.003115 + mesh 1 group in group out legendre nuclide mean std. dev. + x y z +0 1 1 1 1 1 P0 total 0.735256 0.138292 +1 1 1 1 1 1 P1 total 0.277780 0.051210 +2 1 1 1 1 1 P2 total 0.079362 0.017035 +3 1 1 1 1 1 P3 total -0.005417 0.012198 +8 1 2 1 1 1 P0 total 0.624575 0.131169 +9 1 2 1 1 1 P1 total 0.244182 0.050123 +10 1 2 1 1 1 P2 total 0.085877 0.017565 +11 1 2 1 1 1 P3 total 0.019478 0.006403 +4 2 1 1 1 1 P0 total 0.633925 0.260681 +5 2 1 1 1 1 P1 total 0.270615 0.110590 +6 2 1 1 1 1 P2 total 0.107281 0.042750 +7 2 1 1 1 1 P3 total 0.012098 0.005462 +12 2 2 1 1 1 P0 total 0.655214 0.153147 +13 2 2 1 1 1 P1 total 0.256141 0.060250 +14 2 2 1 1 1 P2 total 0.090641 0.020464 +15 2 2 1 1 1 P3 total 0.004822 0.003180 mesh 1 group out nuclide mean std. dev. x y z 0 1 1 1 1 total 1.0 0.300047 diff --git a/tests/regression_tests/mgxs_library_no_nuclides/inputs_true.dat b/tests/regression_tests/mgxs_library_no_nuclides/inputs_true.dat index ef6c4c5206..5aedd383d0 100644 --- a/tests/regression_tests/mgxs_library_no_nuclides/inputs_true.dat +++ b/tests/regression_tests/mgxs_library_no_nuclides/inputs_true.dat @@ -59,16 +59,22 @@ 0.0 0.625 20000000.0 - + + 1 + + + 3 + + 0.0 20000000.0 - + 1 2 3 4 5 6 - + 2 - + 3 @@ -102,9 +108,9 @@ analog - 1 5 + 1 5 6 total - scatter-1 + scatter analog @@ -126,9 +132,9 @@ analog - 1 5 + 1 5 6 total - nu-scatter-1 + nu-scatter analog @@ -228,9 +234,9 @@ analog - 1 2 5 + 1 2 5 28 total - scatter-P3 + scatter analog @@ -240,9 +246,9 @@ analog - 1 2 5 + 1 2 5 28 total - nu-scatter-P3 + nu-scatter analog @@ -288,9 +294,9 @@ tracklength - 1 2 5 + 1 2 5 28 total - scatter-P3 + scatter analog @@ -306,883 +312,865 @@ tracklength - 1 2 5 + 1 2 5 28 total - scatter-P3 + scatter analog 1 2 5 total - nu-scatter-0 + nu-scatter analog - 1 2 5 + 1 52 total - scatter-0 + nu-fission analog - 1 46 + 1 5 total nu-fission analog - 1 5 + 1 52 total - nu-fission + prompt-nu-fission analog - 1 46 + 1 5 total prompt-nu-fission analog - 1 5 + 1 2 total - prompt-nu-fission - analog + flux + tracklength 1 2 total - flux + inverse-velocity tracklength 1 2 total - inverse-velocity + flux tracklength 1 2 total - flux + prompt-nu-fission tracklength - 1 2 - total - prompt-nu-fission - tracklength - - 1 2 total flux analog - + 1 2 5 total prompt-nu-fission analog - + 1 2 total flux tracklength - - 1 59 2 + + 1 65 2 total delayed-nu-fission tracklength + + 1 65 52 + total + delayed-nu-fission + analog + - 1 59 46 + 1 65 5 total delayed-nu-fission analog - 1 59 5 - total - delayed-nu-fission - analog - - 1 2 total nu-fission tracklength + + 1 65 2 + total + delayed-nu-fission + tracklength + - 1 59 2 + 1 65 2 total delayed-nu-fission tracklength - 1 59 2 - total - delayed-nu-fission - tracklength - - - 1 59 2 + 1 65 2 total decay-rate tracklength - + 1 2 total flux analog - - 1 59 2 5 + + 1 65 2 5 total delayed-nu-fission analog - - 74 2 + + 80 2 total flux tracklength + + 80 2 + total + total + tracklength + - 74 2 + 80 2 total - total + flux tracklength - 74 2 + 80 2 total - flux + total tracklength - 74 2 - total - total - tracklength - - - 74 2 + 80 2 total flux analog + + 80 5 6 + total + scatter + analog + - 74 5 - total - scatter-1 - analog - - - 74 2 + 80 2 total flux tracklength - - 74 2 + + 80 2 total total tracklength - - 74 2 + + 80 2 total flux analog + + 80 5 6 + total + nu-scatter + analog + - 74 5 - total - nu-scatter-1 - analog - - - 74 2 + 80 2 total flux tracklength + + 80 2 + total + absorption + tracklength + - 74 2 + 80 2 total - absorption + flux tracklength - 74 2 - total - flux - tracklength - - - 74 2 + 80 2 total absorption tracklength - - 74 2 + + 80 2 total fission tracklength + + 80 2 + total + flux + tracklength + - 74 2 - total - flux - tracklength - - - 74 2 + 80 2 total fission tracklength - - 74 2 + + 80 2 total flux tracklength - - 74 2 + + 80 2 total nu-fission tracklength - - 74 2 + + 80 2 total flux tracklength - - 74 2 + + 80 2 total kappa-fission tracklength - - 74 2 + + 80 2 total flux tracklength + + 80 2 + total + scatter + tracklength + - 74 2 - total - scatter - tracklength - - - 74 2 + 80 2 total flux analog + + 80 2 + total + nu-scatter + analog + - 74 2 + 80 2 total - nu-scatter + flux analog - 74 2 + 80 2 5 28 total - flux + scatter analog - 74 2 5 - total - scatter-P3 - analog - - - 74 2 + 80 2 total flux analog - - 74 2 5 - total - nu-scatter-P3 - analog - - - 74 2 5 + + 80 2 5 28 total nu-scatter analog - - 74 2 5 + + 80 2 5 + total + nu-scatter + analog + + + 80 2 5 total scatter analog + + 80 2 + total + flux + analog + - 74 2 + 80 2 5 total - flux + nu-fission analog - 74 2 5 + 80 2 5 total - nu-fission + scatter analog - 74 2 5 - total - scatter - analog - - - 74 2 + 80 2 total flux tracklength + + 80 2 + total + scatter + tracklength + - 74 2 + 80 2 5 28 total scatter - tracklength - - - 74 2 5 - total - scatter-P3 analog - - 74 2 + + 80 2 total flux tracklength - - 74 2 + + 80 2 total scatter tracklength - - 74 2 5 + + 80 2 5 28 total - scatter-P3 + scatter + analog + + + 80 2 5 + total + nu-scatter analog - 74 2 5 + 80 52 total - nu-scatter-0 + nu-fission analog - 74 2 5 + 80 5 total - scatter-0 + nu-fission analog - 74 46 + 80 52 total - nu-fission + prompt-nu-fission analog - 74 5 + 80 5 total - nu-fission + prompt-nu-fission analog - 74 46 + 80 2 total - prompt-nu-fission - analog + flux + tracklength - 74 5 + 80 2 total - prompt-nu-fission - analog + inverse-velocity + tracklength - 74 2 + 80 2 total flux tracklength - 74 2 + 80 2 total - inverse-velocity + prompt-nu-fission tracklength - 74 2 + 80 2 total flux - tracklength + analog - 74 2 + 80 2 5 total prompt-nu-fission - tracklength + analog - 74 2 + 80 2 total flux - analog + tracklength - 74 2 5 + 80 65 2 total - prompt-nu-fission - analog + delayed-nu-fission + tracklength - 74 2 + 80 65 52 total - flux - tracklength + delayed-nu-fission + analog - 74 59 2 + 80 65 5 total delayed-nu-fission - tracklength + analog - 74 59 46 - total - delayed-nu-fission - analog - - - 74 59 5 - total - delayed-nu-fission - analog - - - 74 2 + 80 2 total nu-fission tracklength + + 80 65 2 + total + delayed-nu-fission + tracklength + + + 80 65 2 + total + delayed-nu-fission + tracklength + - 74 59 2 - total - delayed-nu-fission - tracklength - - - 74 59 2 - total - delayed-nu-fission - tracklength - - - 74 59 2 + 80 65 2 total decay-rate tracklength - - 74 2 + + 80 2 total flux analog - - 74 59 2 5 + + 80 65 2 5 total delayed-nu-fission analog + + 159 2 + total + flux + tracklength + + + 159 2 + total + total + tracklength + - 147 2 + 159 2 total flux tracklength - 147 2 + 159 2 total total tracklength - 147 2 + 159 2 total flux - tracklength + analog - 147 2 + 159 5 6 total - total - tracklength + scatter + analog - 147 2 - total - flux - analog - - - 147 5 - total - scatter-1 - analog - - - 147 2 + 159 2 total flux tracklength - - 147 2 + + 159 2 total total tracklength - - 147 2 + + 159 2 total flux analog - - 147 5 + + 159 5 6 total - nu-scatter-1 + nu-scatter analog + + 159 2 + total + flux + tracklength + + + 159 2 + total + absorption + tracklength + - 147 2 + 159 2 total flux tracklength - 147 2 + 159 2 total absorption tracklength - 147 2 + 159 2 + total + fission + tracklength + + + 159 2 total flux tracklength - - 147 2 - total - absorption - tracklength - - 147 2 + 159 2 total fission tracklength - 147 2 + 159 2 total flux tracklength - 147 2 + 159 2 total - fission + nu-fission tracklength - 147 2 + 159 2 total flux tracklength - 147 2 + 159 2 total - nu-fission + kappa-fission tracklength - 147 2 + 159 2 total flux tracklength - 147 2 - total - kappa-fission - tracklength - - - 147 2 - total - flux - tracklength - - - 147 2 + 159 2 total scatter tracklength + + 159 2 + total + flux + analog + + + 159 2 + total + nu-scatter + analog + - 147 2 + 159 2 total flux analog - 147 2 + 159 2 5 28 total - nu-scatter + scatter analog - 147 2 + 159 2 total flux analog - 147 2 5 - total - scatter-P3 - analog - - - 147 2 - total - flux - analog - - - 147 2 5 - total - nu-scatter-P3 - analog - - - 147 2 5 + 159 2 5 28 total nu-scatter analog - - 147 2 5 + + 159 2 5 + total + nu-scatter + analog + + + 159 2 5 total scatter analog + + 159 2 + total + flux + analog + + + 159 2 5 + total + nu-fission + analog + - 147 2 + 159 2 5 total - flux + scatter analog - 147 2 5 - total - nu-fission - analog - - - 147 2 5 - total - scatter - analog - - - 147 2 + 159 2 total flux tracklength - - 147 2 + + 159 2 total scatter tracklength + + 159 2 5 28 + total + scatter + analog + + + 159 2 + total + flux + tracklength + - 147 2 5 - total - scatter-P3 - analog - - - 147 2 - total - flux - tracklength - - - 147 2 + 159 2 total scatter tracklength - - 147 2 5 + + 159 2 5 28 total - scatter-P3 + scatter + analog + + + 159 2 5 + total + nu-scatter + analog + + + 159 52 + total + nu-fission analog - 147 2 5 + 159 5 total - nu-scatter-0 + nu-fission analog - 147 2 5 + 159 52 total - scatter-0 + prompt-nu-fission analog - 147 46 + 159 5 total - nu-fission + prompt-nu-fission analog - 147 5 - total - nu-fission - analog - - - 147 46 - total - prompt-nu-fission - analog - - - 147 5 - total - prompt-nu-fission - analog - - - 147 2 + 159 2 total flux tracklength - - 147 2 + + 159 2 total inverse-velocity tracklength - - 147 2 + + 159 2 total flux tracklength - - 147 2 + + 159 2 total prompt-nu-fission tracklength + + 159 2 + total + flux + analog + + + 159 2 5 + total + prompt-nu-fission + analog + + + 159 2 + total + flux + tracklength + - 147 2 + 159 65 2 total - flux - analog + delayed-nu-fission + tracklength - 147 2 5 + 159 65 52 total - prompt-nu-fission + delayed-nu-fission analog - 147 2 + 159 65 5 total - flux - tracklength + delayed-nu-fission + analog - 147 59 2 - total - delayed-nu-fission - tracklength - - - 147 59 46 - total - delayed-nu-fission - analog - - - 147 59 5 - total - delayed-nu-fission - analog - - - 147 2 + 159 2 total nu-fission tracklength - - 147 59 2 + + 159 65 2 total delayed-nu-fission tracklength - - 147 59 2 + + 159 65 2 total delayed-nu-fission tracklength - - 147 59 2 + + 159 65 2 total decay-rate tracklength - - 147 2 + + 159 2 total flux analog - - 147 59 2 5 + + 159 65 2 5 total delayed-nu-fission analog diff --git a/tests/regression_tests/mgxs_library_no_nuclides/results_true.dat b/tests/regression_tests/mgxs_library_no_nuclides/results_true.dat index 291c87dde9..d4c87378e8 100644 --- a/tests/regression_tests/mgxs_library_no_nuclides/results_true.dat +++ b/tests/regression_tests/mgxs_library_no_nuclides/results_true.dat @@ -28,40 +28,40 @@ material group in nuclide mean std. dev. 1 1 1 total 0.385188 0.026946 0 1 2 total 0.412389 0.015425 - material group in group out nuclide moment mean std. dev. -12 1 1 1 total P0 0.384199 0.027001 -13 1 1 1 total P1 0.051870 0.006983 -14 1 1 1 total P2 0.020069 0.002846 -15 1 1 1 total P3 0.009478 0.002234 -8 1 1 2 total P0 0.000989 0.000482 -9 1 1 2 total P1 -0.000207 0.000149 -10 1 1 2 total P2 -0.000103 0.000184 -11 1 1 2 total P3 0.000234 0.000128 -4 1 2 1 total P0 0.000925 0.000925 -5 1 2 1 total P1 -0.000768 0.000768 -6 1 2 1 total P2 0.000494 0.000494 -7 1 2 1 total P3 -0.000171 0.000172 -0 1 2 2 total P0 0.411465 0.015245 -1 1 2 2 total P1 0.016482 0.004502 -2 1 2 2 total P2 0.006371 0.010551 -3 1 2 2 total P3 -0.010499 0.010438 - material group in group out nuclide moment mean std. dev. -12 1 1 1 total P0 0.384199 0.027001 -13 1 1 1 total P1 0.051870 0.006983 -14 1 1 1 total P2 0.020069 0.002846 -15 1 1 1 total P3 0.009478 0.002234 -8 1 1 2 total P0 0.000989 0.000482 -9 1 1 2 total P1 -0.000207 0.000149 -10 1 1 2 total P2 -0.000103 0.000184 -11 1 1 2 total P3 0.000234 0.000128 -4 1 2 1 total P0 0.000925 0.000925 -5 1 2 1 total P1 -0.000768 0.000768 -6 1 2 1 total P2 0.000494 0.000494 -7 1 2 1 total P3 -0.000171 0.000172 -0 1 2 2 total P0 0.411465 0.015245 -1 1 2 2 total P1 0.016482 0.004502 -2 1 2 2 total P2 0.006371 0.010551 -3 1 2 2 total P3 -0.010499 0.010438 + material group in group out legendre nuclide mean std. dev. +12 1 1 1 P0 total 0.384199 0.027001 +13 1 1 1 P1 total 0.051870 0.006983 +14 1 1 1 P2 total 0.020069 0.002846 +15 1 1 1 P3 total 0.009478 0.002234 +8 1 1 2 P0 total 0.000989 0.000482 +9 1 1 2 P1 total -0.000207 0.000149 +10 1 1 2 P2 total -0.000103 0.000184 +11 1 1 2 P3 total 0.000234 0.000128 +4 1 2 1 P0 total 0.000925 0.000925 +5 1 2 1 P1 total -0.000768 0.000768 +6 1 2 1 P2 total 0.000494 0.000494 +7 1 2 1 P3 total -0.000171 0.000172 +0 1 2 2 P0 total 0.411465 0.015245 +1 1 2 2 P1 total 0.016482 0.004502 +2 1 2 2 P2 total 0.006371 0.010551 +3 1 2 2 P3 total -0.010499 0.010438 + material group in group out legendre nuclide mean std. dev. +12 1 1 1 P0 total 0.384199 0.027001 +13 1 1 1 P1 total 0.051870 0.006983 +14 1 1 1 P2 total 0.020069 0.002846 +15 1 1 1 P3 total 0.009478 0.002234 +8 1 1 2 P0 total 0.000989 0.000482 +9 1 1 2 P1 total -0.000207 0.000149 +10 1 1 2 P2 total -0.000103 0.000184 +11 1 1 2 P3 total 0.000234 0.000128 +4 1 2 1 P0 total 0.000925 0.000925 +5 1 2 1 P1 total -0.000768 0.000768 +6 1 2 1 P2 total 0.000494 0.000494 +7 1 2 1 P3 total -0.000171 0.000172 +0 1 2 2 P0 total 0.411465 0.015245 +1 1 2 2 P1 total 0.016482 0.004502 +2 1 2 2 P2 total 0.006371 0.010551 +3 1 2 2 P3 total -0.010499 0.010438 material group in group out nuclide mean std. dev. 3 1 1 1 total 1.0 0.078516 2 1 1 2 total 1.0 0.687184 @@ -77,40 +77,40 @@ 2 1 1 2 total 0.002567 0.001256 1 1 2 1 total 0.002242 0.002243 0 1 2 2 total 0.997758 0.041053 - material group in group out nuclide moment mean std. dev. -12 1 1 1 total P0 0.386423 0.036629 -13 1 1 1 total P1 0.052170 0.007767 -14 1 1 1 total P2 0.020185 0.003138 -15 1 1 1 total P3 0.009533 0.002327 -8 1 1 2 total P0 0.000995 0.000489 -9 1 1 2 total P1 -0.000208 0.000150 -10 1 1 2 total P2 -0.000104 0.000186 -11 1 1 2 total P3 0.000236 0.000130 -4 1 2 1 total P0 0.000887 0.000889 -5 1 2 1 total P1 -0.000737 0.000738 -6 1 2 1 total P2 0.000474 0.000475 -7 1 2 1 total P3 -0.000165 0.000165 -0 1 2 2 total P0 0.394772 0.029871 -1 1 2 2 total P1 0.015813 0.004443 -2 1 2 2 total P2 0.006113 0.010131 -3 1 2 2 total P3 -0.010073 0.010037 - material group in group out nuclide moment mean std. dev. -12 1 1 1 total P0 0.386423 0.047563 -13 1 1 1 total P1 0.052170 0.008781 -14 1 1 1 total P2 0.020185 0.003515 -15 1 1 1 total P3 0.009533 0.002444 -8 1 1 2 total P0 0.000995 0.000841 -9 1 1 2 total P1 -0.000208 0.000208 -10 1 1 2 total P2 -0.000104 0.000199 -11 1 1 2 total P3 0.000236 0.000208 -4 1 2 1 total P0 0.000887 0.001538 -5 1 2 1 total P1 -0.000737 0.001277 -6 1 2 1 total P2 0.000474 0.000821 -7 1 2 1 total P3 -0.000165 0.000285 -0 1 2 2 total P0 0.394772 0.033999 -1 1 2 2 total P1 0.015813 0.004491 -2 1 2 2 total P2 0.006113 0.010134 -3 1 2 2 total P3 -0.010073 0.010045 + material group in group out legendre nuclide mean std. dev. +12 1 1 1 P0 total 0.386423 0.036629 +13 1 1 1 P1 total 0.052170 0.007767 +14 1 1 1 P2 total 0.020185 0.003138 +15 1 1 1 P3 total 0.009533 0.002327 +8 1 1 2 P0 total 0.000995 0.000489 +9 1 1 2 P1 total -0.000208 0.000150 +10 1 1 2 P2 total -0.000104 0.000186 +11 1 1 2 P3 total 0.000236 0.000130 +4 1 2 1 P0 total 0.000887 0.000889 +5 1 2 1 P1 total -0.000737 0.000738 +6 1 2 1 P2 total 0.000474 0.000475 +7 1 2 1 P3 total -0.000165 0.000165 +0 1 2 2 P0 total 0.394772 0.029871 +1 1 2 2 P1 total 0.015813 0.004443 +2 1 2 2 P2 total 0.006113 0.010131 +3 1 2 2 P3 total -0.010073 0.010037 + material group in group out legendre nuclide mean std. dev. +12 1 1 1 P0 total 0.386423 0.047563 +13 1 1 1 P1 total 0.052170 0.008781 +14 1 1 1 P2 total 0.020185 0.003515 +15 1 1 1 P3 total 0.009533 0.002444 +8 1 1 2 P0 total 0.000995 0.000841 +9 1 1 2 P1 total -0.000208 0.000208 +10 1 1 2 P2 total -0.000104 0.000199 +11 1 1 2 P3 total 0.000236 0.000208 +4 1 2 1 P0 total 0.000887 0.001538 +5 1 2 1 P1 total -0.000737 0.001277 +6 1 2 1 P2 total 0.000474 0.000821 +7 1 2 1 P3 total -0.000165 0.000285 +0 1 2 2 P0 total 0.394772 0.033999 +1 1 2 2 P1 total 0.015813 0.004491 +2 1 2 2 P2 total 0.006113 0.010134 +3 1 2 2 P3 total -0.010073 0.010045 material group out nuclide mean std. dev. 1 1 1 total 1.0 0.046071 0 1 2 total 0.0 0.000000 @@ -235,40 +235,40 @@ material group in nuclide mean std. dev. 1 2 1 total 0.310121 0.033788 0 2 2 total 0.296264 0.043792 - material group in group out nuclide moment mean std. dev. -12 2 1 1 total P0 0.310121 0.033788 -13 2 1 1 total P1 0.038230 0.008484 -14 2 1 1 total P2 0.020745 0.004696 -15 2 1 1 total P3 0.007964 0.003732 -8 2 1 2 total P0 0.000000 0.000000 -9 2 1 2 total P1 0.000000 0.000000 -10 2 1 2 total P2 0.000000 0.000000 -11 2 1 2 total P3 0.000000 0.000000 -4 2 2 1 total P0 0.000000 0.000000 -5 2 2 1 total P1 0.000000 0.000000 -6 2 2 1 total P2 0.000000 0.000000 -7 2 2 1 total P3 0.000000 0.000000 -0 2 2 2 total P0 0.296264 0.043792 -1 2 2 2 total P1 -0.011214 0.016180 -2 2 2 2 total P2 0.008837 0.011504 -3 2 2 2 total P3 -0.003270 0.007329 - material group in group out nuclide moment mean std. dev. -12 2 1 1 total P0 0.310121 0.033788 -13 2 1 1 total P1 0.038230 0.008484 -14 2 1 1 total P2 0.020745 0.004696 -15 2 1 1 total P3 0.007964 0.003732 -8 2 1 2 total P0 0.000000 0.000000 -9 2 1 2 total P1 0.000000 0.000000 -10 2 1 2 total P2 0.000000 0.000000 -11 2 1 2 total P3 0.000000 0.000000 -4 2 2 1 total P0 0.000000 0.000000 -5 2 2 1 total P1 0.000000 0.000000 -6 2 2 1 total P2 0.000000 0.000000 -7 2 2 1 total P3 0.000000 0.000000 -0 2 2 2 total P0 0.296264 0.043792 -1 2 2 2 total P1 -0.011214 0.016180 -2 2 2 2 total P2 0.008837 0.011504 -3 2 2 2 total P3 -0.003270 0.007329 + material group in group out legendre nuclide mean std. dev. +12 2 1 1 P0 total 0.310121 0.033788 +13 2 1 1 P1 total 0.038230 0.008484 +14 2 1 1 P2 total 0.020745 0.004696 +15 2 1 1 P3 total 0.007964 0.003732 +8 2 1 2 P0 total 0.000000 0.000000 +9 2 1 2 P1 total 0.000000 0.000000 +10 2 1 2 P2 total 0.000000 0.000000 +11 2 1 2 P3 total 0.000000 0.000000 +4 2 2 1 P0 total 0.000000 0.000000 +5 2 2 1 P1 total 0.000000 0.000000 +6 2 2 1 P2 total 0.000000 0.000000 +7 2 2 1 P3 total 0.000000 0.000000 +0 2 2 2 P0 total 0.296264 0.043792 +1 2 2 2 P1 total -0.011214 0.016180 +2 2 2 2 P2 total 0.008837 0.011504 +3 2 2 2 P3 total -0.003270 0.007329 + material group in group out legendre nuclide mean std. dev. +12 2 1 1 P0 total 0.310121 0.033788 +13 2 1 1 P1 total 0.038230 0.008484 +14 2 1 1 P2 total 0.020745 0.004696 +15 2 1 1 P3 total 0.007964 0.003732 +8 2 1 2 P0 total 0.000000 0.000000 +9 2 1 2 P1 total 0.000000 0.000000 +10 2 1 2 P2 total 0.000000 0.000000 +11 2 1 2 P3 total 0.000000 0.000000 +4 2 2 1 P0 total 0.000000 0.000000 +5 2 2 1 P1 total 0.000000 0.000000 +6 2 2 1 P2 total 0.000000 0.000000 +7 2 2 1 P3 total 0.000000 0.000000 +0 2 2 2 P0 total 0.296264 0.043792 +1 2 2 2 P1 total -0.011214 0.016180 +2 2 2 2 P2 total 0.008837 0.011504 +3 2 2 2 P3 total -0.003270 0.007329 material group in group out nuclide mean std. dev. 3 2 1 1 total 1.0 0.108779 2 2 1 2 total 0.0 0.000000 @@ -284,40 +284,40 @@ 2 2 1 2 total 0.0 0.000000 1 2 2 1 total 0.0 0.000000 0 2 2 2 total 1.0 0.142427 - material group in group out nuclide moment mean std. dev. -12 2 1 1 total P0 0.312163 0.037253 -13 2 1 1 total P1 0.038481 0.008743 -14 2 1 1 total P2 0.020882 0.004835 -15 2 1 1 total P3 0.008017 0.003776 -8 2 1 2 total P0 0.000000 0.000000 -9 2 1 2 total P1 0.000000 0.000000 -10 2 1 2 total P2 0.000000 0.000000 -11 2 1 2 total P3 0.000000 0.000000 -4 2 2 1 total P0 0.000000 0.000000 -5 2 2 1 total P1 0.000000 0.000000 -6 2 2 1 total P2 0.000000 0.000000 -7 2 2 1 total P3 0.000000 0.000000 -0 2 2 2 total P0 0.295421 0.050236 -1 2 2 2 total P1 -0.011182 0.016162 -2 2 2 2 total P2 0.008811 0.011495 -3 2 2 2 total P3 -0.003261 0.007313 - material group in group out nuclide moment mean std. dev. -12 2 1 1 total P0 0.312163 0.050407 -13 2 1 1 total P1 0.038481 0.009693 -14 2 1 1 total P2 0.020882 0.005342 -15 2 1 1 total P3 0.008017 0.003876 -8 2 1 2 total P0 0.000000 0.000000 -9 2 1 2 total P1 0.000000 0.000000 -10 2 1 2 total P2 0.000000 0.000000 -11 2 1 2 total P3 0.000000 0.000000 -4 2 2 1 total P0 0.000000 0.000000 -5 2 2 1 total P1 0.000000 0.000000 -6 2 2 1 total P2 0.000000 0.000000 -7 2 2 1 total P3 0.000000 0.000000 -0 2 2 2 total P0 0.295421 0.065529 -1 2 2 2 total P1 -0.011182 0.016240 -2 2 2 2 total P2 0.008811 0.011563 -3 2 2 2 total P3 -0.003261 0.007328 + material group in group out legendre nuclide mean std. dev. +12 2 1 1 P0 total 0.312163 0.037253 +13 2 1 1 P1 total 0.038481 0.008743 +14 2 1 1 P2 total 0.020882 0.004835 +15 2 1 1 P3 total 0.008017 0.003776 +8 2 1 2 P0 total 0.000000 0.000000 +9 2 1 2 P1 total 0.000000 0.000000 +10 2 1 2 P2 total 0.000000 0.000000 +11 2 1 2 P3 total 0.000000 0.000000 +4 2 2 1 P0 total 0.000000 0.000000 +5 2 2 1 P1 total 0.000000 0.000000 +6 2 2 1 P2 total 0.000000 0.000000 +7 2 2 1 P3 total 0.000000 0.000000 +0 2 2 2 P0 total 0.295421 0.050236 +1 2 2 2 P1 total -0.011182 0.016162 +2 2 2 2 P2 total 0.008811 0.011495 +3 2 2 2 P3 total -0.003261 0.007313 + material group in group out legendre nuclide mean std. dev. +12 2 1 1 P0 total 0.312163 0.050407 +13 2 1 1 P1 total 0.038481 0.009693 +14 2 1 1 P2 total 0.020882 0.005342 +15 2 1 1 P3 total 0.008017 0.003876 +8 2 1 2 P0 total 0.000000 0.000000 +9 2 1 2 P1 total 0.000000 0.000000 +10 2 1 2 P2 total 0.000000 0.000000 +11 2 1 2 P3 total 0.000000 0.000000 +4 2 2 1 P0 total 0.000000 0.000000 +5 2 2 1 P1 total 0.000000 0.000000 +6 2 2 1 P2 total 0.000000 0.000000 +7 2 2 1 P3 total 0.000000 0.000000 +0 2 2 2 P0 total 0.295421 0.065529 +1 2 2 2 P1 total -0.011182 0.016240 +2 2 2 2 P2 total 0.008811 0.011563 +3 2 2 2 P3 total -0.003261 0.007328 material group out nuclide mean std. dev. 1 2 1 total 0.0 0.0 0 2 2 total 0.0 0.0 @@ -442,40 +442,40 @@ material group in nuclide mean std. dev. 1 3 1 total 0.671269 0.026186 0 3 2 total 2.035388 0.258060 - material group in group out nuclide moment mean std. dev. -12 3 1 1 total P0 0.639901 0.024709 -13 3 1 1 total P1 0.381167 0.016243 -14 3 1 1 total P2 0.152392 0.008156 -15 3 1 1 total P3 0.009148 0.003889 -8 3 1 2 total P0 0.031368 0.001728 -9 3 1 2 total P1 0.008758 0.000926 -10 3 1 2 total P2 -0.002568 0.001014 -11 3 1 2 total P3 -0.003785 0.000817 -4 3 2 1 total P0 0.000443 0.000445 -5 3 2 1 total P1 0.000400 0.000401 -6 3 2 1 total P2 0.000320 0.000321 -7 3 2 1 total P3 0.000214 0.000215 -0 3 2 2 total P0 2.034945 0.257800 -1 3 2 2 total P1 0.509940 0.051236 -2 3 2 2 total P2 0.111175 0.013020 -3 3 2 2 total P3 0.024988 0.008312 - material group in group out nuclide moment mean std. dev. -12 3 1 1 total P0 0.639901 0.024709 -13 3 1 1 total P1 0.381167 0.016243 -14 3 1 1 total P2 0.152392 0.008156 -15 3 1 1 total P3 0.009148 0.003889 -8 3 1 2 total P0 0.031368 0.001728 -9 3 1 2 total P1 0.008758 0.000926 -10 3 1 2 total P2 -0.002568 0.001014 -11 3 1 2 total P3 -0.003785 0.000817 -4 3 2 1 total P0 0.000443 0.000445 -5 3 2 1 total P1 0.000400 0.000401 -6 3 2 1 total P2 0.000320 0.000321 -7 3 2 1 total P3 0.000214 0.000215 -0 3 2 2 total P0 2.034945 0.257800 -1 3 2 2 total P1 0.509940 0.051236 -2 3 2 2 total P2 0.111175 0.013020 -3 3 2 2 total P3 0.024988 0.008312 + material group in group out legendre nuclide mean std. dev. +12 3 1 1 P0 total 0.639901 0.024709 +13 3 1 1 P1 total 0.381167 0.016243 +14 3 1 1 P2 total 0.152392 0.008156 +15 3 1 1 P3 total 0.009148 0.003889 +8 3 1 2 P0 total 0.031368 0.001728 +9 3 1 2 P1 total 0.008758 0.000926 +10 3 1 2 P2 total -0.002568 0.001014 +11 3 1 2 P3 total -0.003785 0.000817 +4 3 2 1 P0 total 0.000443 0.000445 +5 3 2 1 P1 total 0.000400 0.000401 +6 3 2 1 P2 total 0.000320 0.000321 +7 3 2 1 P3 total 0.000214 0.000215 +0 3 2 2 P0 total 2.034945 0.257800 +1 3 2 2 P1 total 0.509940 0.051236 +2 3 2 2 P2 total 0.111175 0.013020 +3 3 2 2 P3 total 0.024988 0.008312 + material group in group out legendre nuclide mean std. dev. +12 3 1 1 P0 total 0.639901 0.024709 +13 3 1 1 P1 total 0.381167 0.016243 +14 3 1 1 P2 total 0.152392 0.008156 +15 3 1 1 P3 total 0.009148 0.003889 +8 3 1 2 P0 total 0.031368 0.001728 +9 3 1 2 P1 total 0.008758 0.000926 +10 3 1 2 P2 total -0.002568 0.001014 +11 3 1 2 P3 total -0.003785 0.000817 +4 3 2 1 P0 total 0.000443 0.000445 +5 3 2 1 P1 total 0.000400 0.000401 +6 3 2 1 P2 total 0.000320 0.000321 +7 3 2 1 P3 total 0.000214 0.000215 +0 3 2 2 P0 total 2.034945 0.257800 +1 3 2 2 P1 total 0.509940 0.051236 +2 3 2 2 P2 total 0.111175 0.013020 +3 3 2 2 P3 total 0.024988 0.008312 material group in group out nuclide mean std. dev. 3 3 1 1 total 1.0 0.038609 2 3 1 2 total 1.0 0.067667 @@ -491,40 +491,40 @@ 2 3 1 2 total 0.046729 0.002547 1 3 2 1 total 0.000218 0.000219 0 3 2 2 total 0.999782 0.135885 - material group in group out nuclide moment mean std. dev. -12 3 1 1 total P0 0.632859 0.038142 -13 3 1 1 total P1 0.376973 0.023715 -14 3 1 1 total P2 0.150715 0.010664 -15 3 1 1 total P3 0.009047 0.003868 -8 3 1 2 total P0 0.031023 0.002232 -9 3 1 2 total P1 0.008661 0.000999 -10 3 1 2 total P2 -0.002540 0.001010 -11 3 1 2 total P3 -0.003743 0.000826 -4 3 2 1 total P0 0.000440 0.000445 -5 3 2 1 total P1 0.000397 0.000401 -6 3 2 1 total P2 0.000317 0.000321 -7 3 2 1 total P3 0.000212 0.000215 -0 3 2 2 total P0 2.020256 0.352194 -1 3 2 2 total P1 0.506260 0.079140 -2 3 2 2 total P2 0.110372 0.018488 -3 3 2 2 total P3 0.024808 0.008771 - material group in group out nuclide moment mean std. dev. -12 3 1 1 total P0 0.632859 0.045297 -13 3 1 1 total P1 0.376973 0.027825 -14 3 1 1 total P2 0.150715 0.012148 -15 3 1 1 total P3 0.009047 0.003884 -8 3 1 2 total P0 0.031023 0.003064 -9 3 1 2 total P1 0.008661 0.001159 -10 3 1 2 total P2 -0.002540 0.001024 -11 3 1 2 total P3 -0.003743 0.000864 -4 3 2 1 total P0 0.000440 0.000765 -5 3 2 1 total P1 0.000397 0.000690 -6 3 2 1 total P2 0.000317 0.000551 -7 3 2 1 total P3 0.000212 0.000369 -0 3 2 2 total P0 2.020256 0.446601 -1 3 2 2 total P1 0.506260 0.104875 -2 3 2 2 total P2 0.110372 0.023809 -3 3 2 2 total P3 0.024808 0.009397 + material group in group out legendre nuclide mean std. dev. +12 3 1 1 P0 total 0.632859 0.038142 +13 3 1 1 P1 total 0.376973 0.023715 +14 3 1 1 P2 total 0.150715 0.010664 +15 3 1 1 P3 total 0.009047 0.003868 +8 3 1 2 P0 total 0.031023 0.002232 +9 3 1 2 P1 total 0.008661 0.000999 +10 3 1 2 P2 total -0.002540 0.001010 +11 3 1 2 P3 total -0.003743 0.000826 +4 3 2 1 P0 total 0.000440 0.000445 +5 3 2 1 P1 total 0.000397 0.000401 +6 3 2 1 P2 total 0.000317 0.000321 +7 3 2 1 P3 total 0.000212 0.000215 +0 3 2 2 P0 total 2.020256 0.352194 +1 3 2 2 P1 total 0.506260 0.079140 +2 3 2 2 P2 total 0.110372 0.018488 +3 3 2 2 P3 total 0.024808 0.008771 + material group in group out legendre nuclide mean std. dev. +12 3 1 1 P0 total 0.632859 0.045297 +13 3 1 1 P1 total 0.376973 0.027825 +14 3 1 1 P2 total 0.150715 0.012148 +15 3 1 1 P3 total 0.009047 0.003884 +8 3 1 2 P0 total 0.031023 0.003064 +9 3 1 2 P1 total 0.008661 0.001159 +10 3 1 2 P2 total -0.002540 0.001024 +11 3 1 2 P3 total -0.003743 0.000864 +4 3 2 1 P0 total 0.000440 0.000765 +5 3 2 1 P1 total 0.000397 0.000690 +6 3 2 1 P2 total 0.000317 0.000551 +7 3 2 1 P3 total 0.000212 0.000369 +0 3 2 2 P0 total 2.020256 0.446601 +1 3 2 2 P1 total 0.506260 0.104875 +2 3 2 2 P2 total 0.110372 0.023809 +3 3 2 2 P3 total 0.024808 0.009397 material group out nuclide mean std. dev. 1 3 1 total 0.0 0.0 0 3 2 total 0.0 0.0 diff --git a/tests/regression_tests/mgxs_library_nuclides/inputs_true.dat b/tests/regression_tests/mgxs_library_nuclides/inputs_true.dat index b720bfcbba..f859d5f3ac 100644 --- a/tests/regression_tests/mgxs_library_nuclides/inputs_true.dat +++ b/tests/regression_tests/mgxs_library_nuclides/inputs_true.dat @@ -59,13 +59,19 @@ 0.0 0.625 20000000.0 - + + 1 + + + 3 + + 0.0 20000000.0 - + 2 - + 3 @@ -99,9 +105,9 @@ analog - 1 5 + 1 5 6 U234 U235 U238 O16 - scatter-1 + scatter analog @@ -123,9 +129,9 @@ analog - 1 5 + 1 5 6 U234 U235 U238 O16 - nu-scatter-1 + nu-scatter analog @@ -225,9 +231,9 @@ analog - 1 2 5 + 1 2 5 28 U234 U235 U238 O16 - scatter-P3 + scatter analog @@ -237,9 +243,9 @@ analog - 1 2 5 + 1 2 5 28 U234 U235 U238 O16 - nu-scatter-P3 + nu-scatter analog @@ -285,9 +291,9 @@ tracklength - 1 2 5 + 1 2 5 28 U234 U235 U238 O16 - scatter-P3 + scatter analog @@ -303,703 +309,685 @@ tracklength - 1 2 5 + 1 2 5 28 U234 U235 U238 O16 - scatter-P3 + scatter analog 1 2 5 U234 U235 U238 O16 - nu-scatter-0 + nu-scatter analog - 1 2 5 + 1 52 U234 U235 U238 O16 - scatter-0 + nu-fission analog - 1 46 + 1 5 U234 U235 U238 O16 nu-fission analog - 1 5 + 1 52 U234 U235 U238 O16 - nu-fission + prompt-nu-fission analog - 1 46 + 1 5 U234 U235 U238 O16 prompt-nu-fission analog - 1 5 - U234 U235 U238 O16 - prompt-nu-fission - analog - - 1 2 total flux tracklength - + 1 2 U234 U235 U238 O16 inverse-velocity tracklength - + 1 2 total flux tracklength - + 1 2 U234 U235 U238 O16 prompt-nu-fission tracklength - + 1 2 total flux analog - + 1 2 5 U234 U235 U238 O16 prompt-nu-fission analog - - 57 2 + + 63 2 total flux tracklength + + 63 2 + Zr90 Zr91 Zr92 Zr94 Zr96 + total + tracklength + - 57 2 - Zr90 Zr91 Zr92 Zr94 Zr96 - total + 63 2 + total + flux tracklength - 57 2 - total - flux + 63 2 + Zr90 Zr91 Zr92 Zr94 Zr96 + total tracklength - 57 2 - Zr90 Zr91 Zr92 Zr94 Zr96 - total - tracklength - - - 57 2 + 63 2 total flux analog + + 63 5 6 + Zr90 Zr91 Zr92 Zr94 Zr96 + scatter + analog + - 57 5 - Zr90 Zr91 Zr92 Zr94 Zr96 - scatter-1 - analog - - - 57 2 + 63 2 total flux tracklength - - 57 2 + + 63 2 Zr90 Zr91 Zr92 Zr94 Zr96 total tracklength - - 57 2 + + 63 2 total flux analog + + 63 5 6 + Zr90 Zr91 Zr92 Zr94 Zr96 + nu-scatter + analog + - 57 5 - Zr90 Zr91 Zr92 Zr94 Zr96 - nu-scatter-1 - analog - - - 57 2 + 63 2 total flux tracklength + + 63 2 + Zr90 Zr91 Zr92 Zr94 Zr96 + absorption + tracklength + - 57 2 - Zr90 Zr91 Zr92 Zr94 Zr96 - absorption + 63 2 + total + flux tracklength - 57 2 - total - flux - tracklength - - - 57 2 + 63 2 Zr90 Zr91 Zr92 Zr94 Zr96 absorption tracklength - - 57 2 + + 63 2 Zr90 Zr91 Zr92 Zr94 Zr96 fission tracklength + + 63 2 + total + flux + tracklength + - 57 2 - total - flux - tracklength - - - 57 2 + 63 2 Zr90 Zr91 Zr92 Zr94 Zr96 fission tracklength - - 57 2 + + 63 2 total flux tracklength - - 57 2 + + 63 2 Zr90 Zr91 Zr92 Zr94 Zr96 nu-fission tracklength - - 57 2 + + 63 2 total flux tracklength - - 57 2 + + 63 2 Zr90 Zr91 Zr92 Zr94 Zr96 kappa-fission tracklength - - 57 2 + + 63 2 total flux tracklength + + 63 2 + Zr90 Zr91 Zr92 Zr94 Zr96 + scatter + tracklength + - 57 2 - Zr90 Zr91 Zr92 Zr94 Zr96 - scatter - tracklength - - - 57 2 + 63 2 total flux analog + + 63 2 + Zr90 Zr91 Zr92 Zr94 Zr96 + nu-scatter + analog + - 57 2 - Zr90 Zr91 Zr92 Zr94 Zr96 - nu-scatter + 63 2 + total + flux analog - 57 2 - total - flux + 63 2 5 28 + Zr90 Zr91 Zr92 Zr94 Zr96 + scatter analog - 57 2 5 - Zr90 Zr91 Zr92 Zr94 Zr96 - scatter-P3 - analog - - - 57 2 + 63 2 total flux analog - - 57 2 5 - Zr90 Zr91 Zr92 Zr94 Zr96 - nu-scatter-P3 - analog - - - 57 2 5 + + 63 2 5 28 Zr90 Zr91 Zr92 Zr94 Zr96 nu-scatter analog - - 57 2 5 + + 63 2 5 + Zr90 Zr91 Zr92 Zr94 Zr96 + nu-scatter + analog + + + 63 2 5 Zr90 Zr91 Zr92 Zr94 Zr96 scatter analog + + 63 2 + total + flux + analog + - 57 2 - total - flux + 63 2 5 + Zr90 Zr91 Zr92 Zr94 Zr96 + nu-fission analog - 57 2 5 + 63 2 5 Zr90 Zr91 Zr92 Zr94 Zr96 - nu-fission + scatter analog - 57 2 5 - Zr90 Zr91 Zr92 Zr94 Zr96 - scatter - analog - - - 57 2 + 63 2 total flux tracklength + + 63 2 + Zr90 Zr91 Zr92 Zr94 Zr96 + scatter + tracklength + - 57 2 + 63 2 5 28 Zr90 Zr91 Zr92 Zr94 Zr96 scatter - tracklength - - - 57 2 5 - Zr90 Zr91 Zr92 Zr94 Zr96 - scatter-P3 analog - - 57 2 + + 63 2 total flux tracklength - - 57 2 + + 63 2 Zr90 Zr91 Zr92 Zr94 Zr96 scatter tracklength - - 57 2 5 + + 63 2 5 28 Zr90 Zr91 Zr92 Zr94 Zr96 - scatter-P3 + scatter + analog + + + 63 2 5 + Zr90 Zr91 Zr92 Zr94 Zr96 + nu-scatter analog - 57 2 5 + 63 52 Zr90 Zr91 Zr92 Zr94 Zr96 - nu-scatter-0 + nu-fission analog - 57 2 5 + 63 5 Zr90 Zr91 Zr92 Zr94 Zr96 - scatter-0 + nu-fission analog - 57 46 + 63 52 Zr90 Zr91 Zr92 Zr94 Zr96 - nu-fission + prompt-nu-fission analog - 57 5 + 63 5 Zr90 Zr91 Zr92 Zr94 Zr96 - nu-fission + prompt-nu-fission analog - 57 46 - Zr90 Zr91 Zr92 Zr94 Zr96 - prompt-nu-fission - analog + 63 2 + total + flux + tracklength - 57 5 + 63 2 Zr90 Zr91 Zr92 Zr94 Zr96 - prompt-nu-fission - analog + inverse-velocity + tracklength - 57 2 + 63 2 total flux tracklength - 57 2 + 63 2 Zr90 Zr91 Zr92 Zr94 Zr96 - inverse-velocity + prompt-nu-fission tracklength - 57 2 + 63 2 total flux - tracklength + analog - 57 2 + 63 2 5 Zr90 Zr91 Zr92 Zr94 Zr96 prompt-nu-fission - tracklength + analog - 57 2 + 125 2 total flux - analog + tracklength - 57 2 5 - Zr90 Zr91 Zr92 Zr94 Zr96 - prompt-nu-fission - analog + 125 2 + H1 O16 B10 B11 + total + tracklength - 113 2 + 125 2 total flux tracklength - 113 2 + 125 2 H1 O16 B10 B11 total tracklength - 113 2 + 125 2 total flux - tracklength + analog - 113 2 + 125 5 6 H1 O16 B10 B11 - total - tracklength + scatter + analog - 113 2 - total - flux - analog - - - 113 5 - H1 O16 B10 B11 - scatter-1 - analog - - - 113 2 + 125 2 total flux tracklength - - 113 2 + + 125 2 H1 O16 B10 B11 total tracklength - - 113 2 + + 125 2 total flux analog - - 113 5 + + 125 5 6 H1 O16 B10 B11 - nu-scatter-1 + nu-scatter analog + + 125 2 + total + flux + tracklength + + + 125 2 + H1 O16 B10 B11 + absorption + tracklength + - 113 2 + 125 2 total flux tracklength - 113 2 + 125 2 H1 O16 B10 B11 absorption tracklength - 113 2 + 125 2 + H1 O16 B10 B11 + fission + tracklength + + + 125 2 total flux tracklength - - 113 2 - H1 O16 B10 B11 - absorption - tracklength - - 113 2 + 125 2 H1 O16 B10 B11 fission tracklength - 113 2 + 125 2 total flux tracklength - 113 2 + 125 2 H1 O16 B10 B11 - fission + nu-fission tracklength - 113 2 + 125 2 total flux tracklength - 113 2 + 125 2 H1 O16 B10 B11 - nu-fission + kappa-fission tracklength - 113 2 + 125 2 total flux tracklength - 113 2 - H1 O16 B10 B11 - kappa-fission - tracklength - - - 113 2 - total - flux - tracklength - - - 113 2 + 125 2 H1 O16 B10 B11 scatter tracklength + + 125 2 + total + flux + analog + + + 125 2 + H1 O16 B10 B11 + nu-scatter + analog + - 113 2 + 125 2 total flux analog - 113 2 + 125 2 5 28 H1 O16 B10 B11 - nu-scatter + scatter analog - 113 2 + 125 2 total flux analog - 113 2 5 - H1 O16 B10 B11 - scatter-P3 - analog - - - 113 2 - total - flux - analog - - - 113 2 5 - H1 O16 B10 B11 - nu-scatter-P3 - analog - - - 113 2 5 + 125 2 5 28 H1 O16 B10 B11 nu-scatter analog - - 113 2 5 + + 125 2 5 + H1 O16 B10 B11 + nu-scatter + analog + + + 125 2 5 H1 O16 B10 B11 scatter analog + + 125 2 + total + flux + analog + + + 125 2 5 + H1 O16 B10 B11 + nu-fission + analog + - 113 2 - total - flux + 125 2 5 + H1 O16 B10 B11 + scatter analog - 113 2 5 - H1 O16 B10 B11 - nu-fission - analog - - - 113 2 5 - H1 O16 B10 B11 - scatter - analog - - - 113 2 + 125 2 total flux tracklength - - 113 2 + + 125 2 H1 O16 B10 B11 scatter tracklength + + 125 2 5 28 + H1 O16 B10 B11 + scatter + analog + + + 125 2 + total + flux + tracklength + - 113 2 5 - H1 O16 B10 B11 - scatter-P3 - analog - - - 113 2 - total - flux - tracklength - - - 113 2 + 125 2 H1 O16 B10 B11 scatter tracklength - - 113 2 5 + + 125 2 5 28 H1 O16 B10 B11 - scatter-P3 + scatter + analog + + + 125 2 5 + H1 O16 B10 B11 + nu-scatter + analog + + + 125 52 + H1 O16 B10 B11 + nu-fission analog - 113 2 5 + 125 5 H1 O16 B10 B11 - nu-scatter-0 + nu-fission analog - 113 2 5 + 125 52 H1 O16 B10 B11 - scatter-0 + prompt-nu-fission analog - 113 46 + 125 5 H1 O16 B10 B11 - nu-fission + prompt-nu-fission analog - 113 5 - H1 O16 B10 B11 - nu-fission - analog - - - 113 46 - H1 O16 B10 B11 - prompt-nu-fission - analog - - - 113 5 - H1 O16 B10 B11 - prompt-nu-fission - analog - - - 113 2 + 125 2 total flux tracklength - - 113 2 + + 125 2 H1 O16 B10 B11 inverse-velocity tracklength - - 113 2 + + 125 2 total flux tracklength - - 113 2 + + 125 2 H1 O16 B10 B11 prompt-nu-fission tracklength - - 113 2 + + 125 2 total flux analog - - 113 2 5 + + 125 2 5 H1 O16 B10 B11 prompt-nu-fission analog diff --git a/tests/regression_tests/mgxs_library_nuclides/results_true.dat b/tests/regression_tests/mgxs_library_nuclides/results_true.dat index a0315ebbc6..577694cfa5 100644 --- a/tests/regression_tests/mgxs_library_nuclides/results_true.dat +++ b/tests/regression_tests/mgxs_library_nuclides/results_true.dat @@ -1 +1 @@ -174d1593a15de41e2aba88cc4c48fc3a400314b400571a0328dfdf7482df111b3ac9701dbd196d06668b49d3acaa67d766702db0942c03140e9e004942f7bdfd \ No newline at end of file +0edd3036c0b5b1eebad90dc8fba25006f14745ceb51dd109e70d0c610d66071f32128facdbc6d4e5077534fe96fff9a8e0ddeefb4a18d6c578f8e805bab7aa22 \ No newline at end of file diff --git a/tests/regression_tests/sourcepoint_restart/results_true.dat b/tests/regression_tests/sourcepoint_restart/results_true.dat index f726da973c..e210748bf6 100644 --- a/tests/regression_tests/sourcepoint_restart/results_true.dat +++ b/tests/regression_tests/sourcepoint_restart/results_true.dat @@ -3,62 +3,26 @@ k-combined: tally 1: 1.100000E-02 3.700000E-05 -1.307570E-03 -2.851451E-06 -1.564980E-03 -2.368303E-06 -3.138136E-03 -5.769887E-06 7.719234E-03 2.632582E-05 0.000000E+00 0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 2.976389E-04 8.858890E-08 0.000000E+00 0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 8.816168E-04 7.772482E-07 1.000000E-03 1.000000E-06 -8.782909E-04 -7.713950E-07 -6.570925E-04 -4.317705E-07 -3.763366E-04 -1.416293E-07 0.000000E+00 0.000000E+00 2.100000E-02 1.150000E-04 -5.280651E-03 -1.222273E-05 -5.235520E-03 -1.202448E-05 -5.064093E-03 -1.787892E-05 1.071093E-02 2.748612E-05 0.000000E+00 0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 8.954045E-04 2.673851E-07 0.000000E+00 @@ -69,76 +33,28 @@ tally 1: 0.000000E+00 0.000000E+00 0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 3.100000E-02 2.130000E-04 -1.472240E-02 -5.500913E-05 -1.077445E-02 -2.987369E-05 -6.729425E-03 -1.249089E-05 1.363637E-02 4.345510E-05 0.000000E+00 0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 1.182717E-03 5.268980E-07 2.000000E-03 2.000000E-06 --1.367978E-03 -9.381191E-07 -4.071787E-04 -9.316064E-08 -4.394728E-04 -1.064342E-07 2.110880E-03 1.737594E-06 1.000000E-03 1.000000E-06 -9.347357E-04 -8.737309E-07 -8.105963E-04 -6.570664E-07 -6.396651E-04 -4.091714E-07 2.938723E-04 8.636091E-08 2.300000E-02 1.330000E-04 -1.081756E-02 -3.675127E-05 -2.530156E-03 -6.960955E-06 --1.930911E-03 -4.910249E-06 1.162826E-02 3.490280E-05 0.000000E+00 0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 8.957100E-04 4.402864E-07 0.000000E+00 @@ -149,36 +65,12 @@ tally 1: 0.000000E+00 0.000000E+00 0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 1.000000E-02 3.400000E-05 -4.086838E-03 -5.900874E-06 -1.812330E-03 -3.716159E-06 -2.138941E-03 -3.006748E-06 5.414128E-03 8.079333E-06 0.000000E+00 0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 3.079654E-04 9.484271E-08 0.000000E+00 @@ -189,36 +81,12 @@ tally 1: 0.000000E+00 0.000000E+00 0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 1.700000E-02 7.100000E-05 -5.492922E-03 -1.013834E-05 -5.773309E-04 -3.561549E-06 -2.550048E-03 -3.841061E-06 8.048522E-03 1.583843E-05 0.000000E+00 0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 5.915762E-04 1.749885E-07 0.000000E+00 @@ -229,156 +97,60 @@ tally 1: 0.000000E+00 0.000000E+00 0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 2.700000E-02 1.670000E-04 -1.789444E-02 -8.260005E-05 -1.049872E-02 -2.774537E-05 -5.665111E-03 -8.560197E-06 1.100708E-02 2.835295E-05 0.000000E+00 0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 3.079654E-04 9.484271E-08 1.000000E-03 1.000000E-06 --2.856031E-04 -8.156913E-08 --3.776463E-04 -1.426167E-07 -3.701637E-04 -1.370211E-07 1.203064E-03 7.240967E-07 1.000000E-03 1.000000E-06 -9.705482E-04 -9.419638E-07 -9.129457E-04 -8.334699E-07 -8.297310E-04 -6.884535E-07 0.000000E+00 0.000000E+00 4.400000E-02 4.320000E-04 -1.141886E-02 -4.208707E-05 -9.213446E-03 -2.259305E-05 -9.177440E-03 -2.088782E-05 2.116869E-02 9.629046E-05 0.000000E+00 0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 1.501009E-03 6.405021E-07 1.000000E-03 1.000000E-06 -5.882614E-04 -3.460515E-07 -1.907719E-05 -3.639390E-10 --3.734703E-04 -1.394801E-07 1.472277E-03 9.506217E-07 2.000000E-03 2.000000E-06 -1.830192E-03 -1.679505E-06 -1.519257E-03 -1.189525E-06 -1.118506E-03 -7.332971E-07 2.977039E-04 8.862762E-08 2.000000E-02 1.080000E-04 -8.640372E-03 -1.765553E-05 -5.688468E-03 -1.038555E-05 -2.447898E-03 -4.466055E-06 8.949667E-03 1.935056E-05 0.000000E+00 0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 2.977039E-04 8.862762E-08 1.000000E-03 1.000000E-06 --3.805163E-04 -1.447926E-07 --2.828111E-04 -7.998210E-08 -4.330345E-04 -1.875189E-07 2.121142E-03 1.958355E-06 1.000000E-03 1.000000E-06 -9.260022E-04 -8.574800E-07 -7.862200E-04 -6.181419E-07 -5.960676E-04 -3.552966E-07 2.938723E-04 8.636091E-08 1.000000E-02 3.400000E-05 -4.840884E-03 -1.080853E-05 -3.402096E-03 -4.113972E-06 -1.374077E-03 -2.333511E-06 4.754696E-03 7.172309E-06 0.000000E+00 0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 3.079654E-04 9.484271E-08 0.000000E+00 @@ -389,316 +161,124 @@ tally 1: 0.000000E+00 0.000000E+00 0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 1.300000E-02 3.700000E-05 -3.121167E-03 -2.465327E-06 -4.474559E-04 -1.522316E-06 -9.193982E-04 -3.247292E-06 5.365659E-03 6.567979E-06 0.000000E+00 0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 6.056043E-04 1.834316E-07 0.000000E+00 0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 2.977039E-04 8.862762E-08 1.000000E-03 1.000000E-06 -2.390376E-04 -5.713899E-08 --4.142915E-04 -1.716375E-07 --3.244105E-04 -1.052422E-07 0.000000E+00 0.000000E+00 2.900000E-02 2.230000E-04 -6.260565E-03 -1.544092E-05 -7.061757E-03 -2.562385E-05 -3.982541E-03 -7.962565E-06 1.486928E-02 5.763901E-05 0.000000E+00 0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 5.915762E-04 1.749885E-07 0.000000E+00 0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 5.954078E-04 3.545105E-07 1.000000E-03 1.000000E-06 -9.938157E-04 -9.876697E-07 -9.815046E-04 -9.633512E-07 -9.631807E-04 -9.277170E-07 0.000000E+00 0.000000E+00 2.900000E-02 1.990000E-04 -1.237546E-02 -3.198261E-05 -8.287792E-03 -2.747313E-05 -3.254969E-03 -8.653294E-06 1.189702E-02 3.303340E-05 0.000000E+00 0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 9.033082E-04 2.720592E-07 3.000000E-03 3.000000E-06 -3.649225E-04 -1.756075E-06 -1.134112E-03 -8.940601E-07 --9.392028E-04 -5.872882E-07 1.484187E-03 9.721092E-07 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 2.500000E-02 1.390000E-04 -1.511834E-02 -5.459835E-05 -7.753447E-03 -2.291820E-05 -6.142979E-03 -1.359405E-05 1.043467E-02 2.526768E-05 0.000000E+00 0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 5.912057E-04 1.747704E-07 1.000000E-03 1.000000E-06 --1.098110E-04 -1.205846E-08 --4.819123E-04 -2.322395E-07 -1.614061E-04 -2.605194E-08 8.813114E-04 4.316251E-07 0.000000E+00 0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 2.935668E-04 8.618147E-08 1.900000E-02 1.030000E-04 -1.035735E-02 -3.119381E-05 -6.483551E-03 -1.164471E-05 -3.924334E-03 -6.047577E-06 9.748672E-03 2.956633E-05 0.000000E+00 0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 3.079654E-04 9.484271E-08 0.000000E+00 0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 2.935668E-04 8.618147E-08 1.000000E-03 1.000000E-06 -8.623139E-04 -7.435852E-07 -6.153778E-04 -3.786899E-07 -3.095388E-04 -9.581428E-08 0.000000E+00 0.000000E+00 7.000000E-03 1.500000E-05 -3.445754E-03 -3.819507E-06 -2.124056E-03 -1.976201E-06 -1.542203E-03 -1.531669E-06 4.135720E-03 4.532611E-06 0.000000E+00 0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 5.874391E-04 1.725424E-07 0.000000E+00 0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 3.079654E-04 9.484271E-08 1.000000E-03 1.000000E-06 -9.451745E-04 -8.933548E-07 -8.400323E-04 -7.056542E-07 -6.931788E-04 -4.804969E-07 0.000000E+00 0.000000E+00 2.600000E-02 1.560000E-04 -6.314886E-03 -1.168542E-05 -6.676680E-04 -9.930437E-06 --2.103247E-04 -2.815945E-07 1.249410E-02 3.501589E-05 0.000000E+00 0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 6.159309E-04 3.793709E-07 0.000000E+00 0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 2.976389E-04 8.858890E-08 1.000000E-03 1.000000E-06 -9.514029E-04 -9.051675E-07 -8.577513E-04 -7.357373E-07 -7.258432E-04 -5.268483E-07 0.000000E+00 0.000000E+00 2.900000E-02 1.950000E-04 -8.928267E-03 -2.594547E-05 -4.752762E-03 -1.522378E-05 -5.376579E-03 -1.088620E-05 1.461148E-02 4.367385E-05 0.000000E+00 0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 5.912057E-04 1.747704E-07 0.000000E+00 @@ -709,66 +289,24 @@ tally 1: 0.000000E+00 0.000000E+00 0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 1.900000E-02 9.700000E-05 -1.046968E-02 -3.828445E-05 -6.704767E-03 -2.668260E-05 -2.659611E-03 -1.143518E-05 1.099391E-02 2.847330E-05 0.000000E+00 0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 2.935668E-04 8.618147E-08 0.000000E+00 0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 2.655539E-03 2.523801E-06 3.000000E-03 5.000000E-06 -2.960960E-03 -4.866206E-06 -2.884206E-03 -4.608867E-06 -2.772329E-03 -4.247272E-06 2.976389E-04 8.858890E-08 6.000000E-03 8.000000E-06 -2.104495E-03 -2.749678E-06 -8.451272E-04 -9.362821E-07 -5.355137E-04 -3.419837E-07 2.683856E-03 1.512640E-06 0.000000E+00 @@ -777,128 +315,50 @@ tally 1: 0.000000E+00 0.000000E+00 0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 2.976389E-04 8.858890E-08 1.000000E-03 1.000000E-06 -9.374310E-04 -8.787769E-07 -8.181653E-04 -6.693944E-07 -6.533352E-04 -4.268468E-07 2.976389E-04 8.858890E-08 1.200000E-02 4.600000E-05 -9.302157E-04 -3.853850E-06 -1.874541E-03 -3.092623E-06 --1.511552E-03 -4.053466E-06 5.941985E-03 9.853870E-06 0.000000E+00 0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 1.186548E-03 5.291647E-07 0.000000E+00 0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 2.935668E-04 8.618147E-08 1.000000E-03 1.000000E-06 -9.893707E-04 -9.788543E-07 -9.682814E-04 -9.375689E-07 -9.370683E-04 -8.780970E-07 0.000000E+00 0.000000E+00 2.300000E-02 1.230000E-04 -5.099566E-03 -9.143616E-06 -4.738751E-03 -7.819254E-06 -3.929250E-03 -6.884420E-06 1.015650E-02 2.236950E-05 0.000000E+00 0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 2.977039E-04 8.862762E-08 0.000000E+00 0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 5.912707E-04 1.748091E-07 2.000000E-03 2.000000E-06 -1.762035E-03 -1.552542E-06 -1.328812E-03 -8.839688E-07 -7.771806E-04 -3.049398E-07 0.000000E+00 0.000000E+00 3.100000E-02 2.250000E-04 -1.389831E-02 -5.927254E-05 -9.999959E-03 -3.379365E-05 -4.584291E-03 -1.665226E-05 1.729188E-02 6.078653E-05 0.000000E+00 0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 1.792523E-03 8.900697E-07 0.000000E+00 @@ -909,76 +369,28 @@ tally 1: 0.000000E+00 0.000000E+00 0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 1.700000E-02 7.100000E-05 -3.566805E-03 -2.049908E-05 -5.418617E-03 -7.496014E-06 -2.451897E-03 -2.115374E-06 7.760000E-03 1.634547E-05 0.000000E+00 0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 2.977039E-04 8.862762E-08 1.000000E-03 1.000000E-06 --7.119580E-04 -5.068842E-07 -2.603263E-04 -6.776977E-08 -1.657364E-04 -2.746855E-08 8.807004E-04 7.756332E-07 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 2.900000E-02 2.030000E-04 -6.527719E-03 -1.422798E-05 -1.560049E-03 -2.934829E-06 -1.548553E-03 -8.929308E-06 1.108618E-02 3.019577E-05 0.000000E+00 0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 1.174573E-03 8.619941E-07 0.000000E+00 @@ -989,76 +401,28 @@ tally 1: 0.000000E+00 0.000000E+00 0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 1.500000E-02 5.500000E-05 -2.209492E-03 -2.545503E-06 -5.991182E-03 -1.290780E-05 -1.772063E-03 -2.006265E-06 5.944486E-03 1.042417E-05 0.000000E+00 0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 3.079654E-04 9.484271E-08 0.000000E+00 0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 1.190621E-03 8.859277E-07 2.000000E-03 2.000000E-06 -1.908405E-03 -1.821879E-06 -1.732819E-03 -1.508498E-06 -1.487670E-03 -1.131430E-06 0.000000E+00 0.000000E+00 2.600000E-02 1.460000E-04 -7.818547E-03 -3.176773E-05 -5.200193E-03 -1.419001E-05 -3.947828E-03 -8.417104E-06 9.232713E-03 1.900222E-05 0.000000E+00 0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 1.186919E-03 5.294603E-07 0.000000E+00 @@ -1069,116 +433,44 @@ tally 1: 0.000000E+00 0.000000E+00 0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 3.600000E-02 2.740000E-04 -9.407788E-03 -2.403566E-05 -4.480017E-03 -6.102099E-06 -5.941113E-03 -1.265337E-05 1.462273E-02 4.551798E-05 0.000000E+00 0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 6.056694E-04 1.834703E-07 0.000000E+00 0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 8.807004E-04 7.756332E-07 1.000000E-03 1.000000E-06 -8.905295E-04 -7.930427E-07 -6.895641E-04 -4.754986E-07 -4.297756E-04 -1.847070E-07 0.000000E+00 0.000000E+00 1.200000E-02 3.000000E-05 -4.798420E-03 -7.171924E-06 -1.417651E-03 -4.997963E-06 -2.131704E-03 -3.253030E-06 7.754474E-03 1.333333E-05 0.000000E+00 0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 2.938723E-04 8.636091E-08 0.000000E+00 0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 1.484382E-03 1.504223E-06 3.000000E-03 5.000000E-06 -2.760812E-03 -4.139104E-06 -2.336063E-03 -2.844690E-06 -1.817042E-03 -1.656152E-06 0.000000E+00 0.000000E+00 1.900000E-02 9.900000E-05 -7.385212E-03 -2.033270E-05 -6.336514E-03 -2.028060E-05 -3.967026E-03 -1.027239E-05 1.066281E-02 2.937590E-05 0.000000E+00 0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 2.976389E-04 8.858890E-08 0.000000E+00 @@ -1189,26 +481,8 @@ tally 1: 0.000000E+00 0.000000E+00 0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 3.000000E-03 3.000000E-06 -1.134842E-03 -1.040850E-06 -6.127525E-05 -3.988312E-07 -4.938488E-05 -2.738492E-07 1.484493E-03 9.722886E-07 0.000000E+00 @@ -1223,122 +497,44 @@ tally 1: 0.000000E+00 0.000000E+00 0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 2.300000E-02 1.650000E-04 -9.507197E-03 -3.773476E-05 -6.295609E-03 -2.127696E-05 -6.339840E-03 -1.601206E-05 1.065253E-02 3.447907E-05 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 1.000000E-03 1.000000E-06 --1.117213E-04 -1.248165E-08 --4.812775E-04 -2.316281E-07 -1.640958E-04 -2.692743E-08 5.871336E-04 3.447259E-07 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 3.100000E-02 2.030000E-04 -1.194795E-02 -4.198084E-05 -8.484089E-03 -1.631808E-05 -5.880364E-03 -1.308096E-05 1.342551E-02 3.842917E-05 0.000000E+00 0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 5.915762E-04 1.749885E-07 1.000000E-03 1.000000E-06 --5.881991E-05 -3.459782E-09 --4.948103E-04 -2.448373E-07 -8.772111E-05 -7.694993E-09 5.871336E-04 3.447259E-07 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 1.900000E-02 8.700000E-05 -5.469796E-03 -1.029265E-05 -4.923561E-04 -2.403244E-06 -2.579361E-03 -5.814745E-06 8.693502E-03 1.682273E-05 0.000000E+00 0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 2.976389E-04 8.858890E-08 0.000000E+00 @@ -1349,26 +545,8 @@ tally 1: 0.000000E+00 0.000000E+00 0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 8.000000E-03 1.600000E-05 -5.411154E-03 -8.076329E-06 -3.145940E-03 -4.212660E-06 -2.637510E-03 -3.210372E-06 3.866943E-03 3.257876E-06 0.000000E+00 @@ -1377,48 +555,18 @@ tally 1: 0.000000E+00 0.000000E+00 0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 1.175489E-03 1.381775E-06 1.000000E-03 1.000000E-06 -7.809681E-04 -6.099112E-07 -4.148668E-04 -1.721145E-07 -1.935089E-05 -3.744570E-10 0.000000E+00 0.000000E+00 8.000000E-03 2.000000E-05 -3.721382E-03 -4.736982E-06 --1.037031E-04 -6.648392E-07 --5.996856E-04 -9.642316E-07 3.248622E-03 4.063213E-06 0.000000E+00 0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 2.938723E-04 8.636091E-08 0.000000E+00 @@ -1429,36 +577,12 @@ tally 1: 0.000000E+00 0.000000E+00 0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 2.800000E-02 1.780000E-04 -1.190615E-02 -4.434442E-05 -7.332993E-03 -2.337416E-05 -6.867008E-03 -1.321552E-05 1.283876E-02 3.527487E-05 0.000000E+00 0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 5.954078E-04 3.545105E-07 0.000000E+00 @@ -1469,66 +593,24 @@ tally 1: 0.000000E+00 0.000000E+00 0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 4.000000E-02 3.880000E-04 -6.620484E-03 -3.751545E-05 -9.255367E-03 -1.963463E-05 -7.761524E-03 -1.694944E-05 1.659048E-02 7.200873E-05 0.000000E+00 0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 2.976389E-04 8.858890E-08 1.000000E-03 1.000000E-06 --5.273064E-04 -2.780520E-07 --8.292201E-05 -6.876059E-09 -4.244131E-04 -1.801265E-07 8.891500E-04 4.407165E-07 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 1.200000E-02 3.400000E-05 -5.905081E-03 -1.535048E-05 -3.856089E-03 -8.589511E-06 -3.244585E-03 -5.882222E-06 5.074320E-03 5.793165E-06 0.000000E+00 @@ -1543,32 +625,8 @@ tally 1: 0.000000E+00 0.000000E+00 0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 4.000000E-03 8.000000E-06 -1.520286E-03 -4.076900E-06 -2.191143E-03 -3.717004E-06 -1.161623E-03 -3.726099E-06 3.570375E-03 5.251426E-06 0.000000E+00 @@ -1583,42 +641,12 @@ tally 1: 0.000000E+00 0.000000E+00 0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 4.000000E-03 4.000000E-06 -3.379122E-03 -2.880429E-06 -2.320644E-03 -1.498759E-06 -1.119131E-03 -6.212863E-07 1.494579E-03 6.241235E-07 0.000000E+00 0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 2.976389E-04 8.858890E-08 0.000000E+00 @@ -1629,76 +657,28 @@ tally 1: 0.000000E+00 0.000000E+00 0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 3.100000E-02 1.950000E-04 -1.338410E-02 -5.097757E-05 -6.794436E-03 -1.428226E-05 -3.939298E-03 -9.052046E-06 1.250316E-02 3.147175E-05 0.000000E+00 0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 5.953428E-04 1.772165E-07 1.000000E-03 1.000000E-06 --5.747626E-05 -3.303520E-09 --4.950447E-04 -2.450693E-07 -8.573970E-05 -7.351297E-09 5.954078E-04 3.545105E-07 1.000000E-03 1.000000E-06 -9.748367E-04 -9.503066E-07 -9.254598E-04 -8.564759E-07 -8.537292E-04 -7.288535E-07 0.000000E+00 0.000000E+00 2.600000E-02 1.800000E-04 -1.225587E-02 -3.757196E-05 -7.670283E-03 -2.316758E-05 -5.282346E-03 -1.407031E-05 1.162837E-02 3.241150E-05 0.000000E+00 0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 5.874391E-04 1.725424E-07 0.000000E+00 @@ -1709,66 +689,24 @@ tally 1: 0.000000E+00 0.000000E+00 0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 1.900000E-02 9.900000E-05 -7.244455E-03 -2.708286E-05 -4.601657E-03 -5.366244E-06 --1.675270E-03 -3.867377E-06 9.216754E-03 2.272207E-05 0.000000E+00 0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 3.079654E-04 9.484271E-08 0.000000E+00 0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 6.159309E-04 3.793709E-07 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 6.000000E-03 1.000000E-05 -1.316884E-03 -2.894217E-06 -2.095957E-03 -1.439521E-06 -1.013831E-04 -8.405300E-07 2.404012E-03 1.641294E-06 0.000000E+00 @@ -1799,66 +737,12 @@ tally 1: 0.000000E+00 0.000000E+00 0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 1.500000E-02 6.300000E-05 -5.790211E-03 -1.210465E-05 -8.591246E-04 -1.950998E-06 -1.987991E-03 -4.703397E-06 6.572185E-03 9.479065E-06 0.000000E+00 0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 5.954078E-04 3.545105E-07 0.000000E+00 @@ -1869,26 +753,8 @@ tally 1: 0.000000E+00 0.000000E+00 0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 1.900000E-02 1.030000E-04 -3.010784E-03 -6.984061E-06 -5.243839E-03 -8.093978E-06 --2.502286E-04 -2.564795E-06 7.760558E-03 1.654841E-05 0.000000E+00 @@ -1897,48 +763,18 @@ tally 1: 0.000000E+00 0.000000E+00 0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 2.935668E-04 8.618147E-08 1.000000E-03 1.000000E-06 -9.333938E-04 -8.712239E-07 -8.068359E-04 -6.509841E-07 -6.328968E-04 -4.005583E-07 0.000000E+00 0.000000E+00 1.800000E-02 1.220000E-04 -6.860987E-03 -2.966806E-05 -4.229750E-03 -1.617998E-05 -1.295452E-03 -8.613003E-07 7.815192E-03 2.039362E-05 0.000000E+00 0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 2.935668E-04 8.618147E-08 0.000000E+00 @@ -1965,50 +801,8 @@ tally 1: 0.000000E+00 0.000000E+00 0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 2.000000E-03 2.000000E-06 -1.502634E-03 -1.146555E-06 -7.198331E-04 -3.484978E-07 --3.426513E-05 -1.342349E-07 1.511030E-03 1.198310E-06 0.000000E+00 @@ -2023,32 +817,8 @@ tally 1: 0.000000E+00 0.000000E+00 0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 1.900000E-02 1.030000E-04 -3.892013E-03 -8.267134E-06 -3.385502E-03 -6.457947E-06 -4.380506E-03 -1.060881E-05 7.130794E-03 1.485134E-05 0.000000E+00 @@ -2057,78 +827,30 @@ tally 1: 0.000000E+00 0.000000E+00 0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 8.816168E-04 7.772482E-07 1.000000E-03 1.000000E-06 -9.951010E-04 -9.902260E-07 -9.853389E-04 -9.708928E-07 -9.707856E-04 -9.424246E-07 0.000000E+00 0.000000E+00 2.900000E-02 1.970000E-04 -4.944370E-03 -2.340271E-05 -3.891346E-03 -1.137205E-05 -5.738303E-03 -9.169816E-06 1.046961E-02 2.353870E-05 0.000000E+00 0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 6.056694E-04 1.834703E-07 0.000000E+00 0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 1.203064E-03 7.240967E-07 2.000000E-03 2.000000E-06 -1.696621E-03 -1.449397E-06 -1.174096E-03 -7.548933E-07 -5.719051E-04 -3.184788E-07 0.000000E+00 0.000000E+00 1.600000E-02 5.400000E-05 -7.937805E-03 -1.353584E-05 -4.065443E-03 -5.658333E-06 -3.432476E-03 -3.530320E-06 6.546902E-03 9.343143E-06 0.000000E+00 @@ -2143,32 +865,8 @@ tally 1: 0.000000E+00 0.000000E+00 0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 2.000000E-03 2.000000E-06 -1.447007E-04 -7.721849E-07 -1.582773E-04 -4.841114E-08 -1.981705E-04 -2.166687E-07 9.135698E-04 4.679598E-07 0.000000E+00 @@ -2199,176 +897,56 @@ tally 1: 0.000000E+00 0.000000E+00 0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 1.000000E-02 2.600000E-05 -5.875085E-04 -4.563904E-07 --9.207198E-05 -5.154496E-07 -3.674257E-05 -1.178281E-06 5.048984E-03 5.880389E-06 0.000000E+00 0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 3.079654E-04 9.484271E-08 0.000000E+00 0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 5.952777E-04 3.543556E-07 1.000000E-03 1.000000E-06 -9.362621E-04 -8.765867E-07 -8.148801E-04 -6.640295E-07 -6.473941E-04 -4.191191E-07 0.000000E+00 0.000000E+00 2.000000E-02 9.000000E-05 -5.358616E-03 -1.697599E-05 -3.060277E-03 -7.132281E-06 -2.485730E-03 -7.247489E-06 9.248312E-03 1.738407E-05 0.000000E+00 0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 8.991711E-04 2.696131E-07 0.000000E+00 0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 5.954078E-04 3.545105E-07 1.000000E-03 1.000000E-06 -9.816220E-04 -9.635817E-07 -9.453726E-04 -8.937294E-07 -8.922496E-04 -7.961093E-07 0.000000E+00 0.000000E+00 8.000000E-03 1.800000E-05 -4.925975E-03 -6.260377E-06 -3.176938E-03 -2.631319E-06 -2.008278E-03 -1.484516E-06 3.844641E-03 4.075868E-06 0.000000E+00 0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 2.977039E-04 8.862762E-08 0.000000E+00 0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 9.238963E-04 8.535844E-07 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 1.000000E-03 1.000000E-06 --3.865739E-04 -1.494394E-07 --2.758409E-04 -7.608820E-08 -4.354374E-04 -1.896058E-07 5.871336E-04 3.447259E-07 0.000000E+00 @@ -2383,24 +961,6 @@ tally 1: 0.000000E+00 0.000000E+00 0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 tally 2: 5.656886E-01 6.401440E-02 diff --git a/tests/regression_tests/sourcepoint_restart/tallies.xml b/tests/regression_tests/sourcepoint_restart/tallies.xml index db9b2ed75c..60bf6b268b 100644 --- a/tests/regression_tests/sourcepoint_restart/tallies.xml +++ b/tests/regression_tests/sourcepoint_restart/tallies.xml @@ -30,7 +30,7 @@ 1 2 3 - scatter-P3 nu-fission + scatter nu-fission diff --git a/tests/regression_tests/statepoint_restart/results_true.dat b/tests/regression_tests/statepoint_restart/results_true.dat index f726da973c..c35ff46b8d 100644 --- a/tests/regression_tests/statepoint_restart/results_true.dat +++ b/tests/regression_tests/statepoint_restart/results_true.dat @@ -3,62 +3,38 @@ k-combined: tally 1: 1.100000E-02 3.700000E-05 -1.307570E-03 -2.851451E-06 -1.564980E-03 -2.368303E-06 -3.138136E-03 -5.769887E-06 +1.100000E-02 +3.700000E-05 7.719234E-03 2.632582E-05 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 2.976389E-04 8.858890E-08 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 8.816168E-04 7.772482E-07 1.000000E-03 1.000000E-06 -8.782909E-04 -7.713950E-07 -6.570925E-04 -4.317705E-07 -3.763366E-04 -1.416293E-07 +1.000000E-03 +1.000000E-06 0.000000E+00 0.000000E+00 2.100000E-02 1.150000E-04 -5.280651E-03 -1.222273E-05 -5.235520E-03 -1.202448E-05 -5.064093E-03 -1.787892E-05 +2.100000E-02 +1.150000E-04 1.071093E-02 2.748612E-05 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 8.954045E-04 2.673851E-07 0.000000E+00 @@ -73,72 +49,40 @@ tally 1: 0.000000E+00 0.000000E+00 0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 3.100000E-02 2.130000E-04 -1.472240E-02 -5.500913E-05 -1.077445E-02 -2.987369E-05 -6.729425E-03 -1.249089E-05 +3.100000E-02 +2.130000E-04 1.363637E-02 4.345510E-05 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 1.182717E-03 5.268980E-07 2.000000E-03 2.000000E-06 --1.367978E-03 -9.381191E-07 -4.071787E-04 -9.316064E-08 -4.394728E-04 -1.064342E-07 +3.000000E-03 +5.000000E-06 2.110880E-03 1.737594E-06 1.000000E-03 1.000000E-06 -9.347357E-04 -8.737309E-07 -8.105963E-04 -6.570664E-07 -6.396651E-04 -4.091714E-07 +1.000000E-03 +1.000000E-06 2.938723E-04 8.636091E-08 2.300000E-02 1.330000E-04 -1.081756E-02 -3.675127E-05 -2.530156E-03 -6.960955E-06 --1.930911E-03 -4.910249E-06 +2.300000E-02 +1.330000E-04 1.162826E-02 3.490280E-05 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 8.957100E-04 4.402864E-07 0.000000E+00 @@ -153,32 +97,16 @@ tally 1: 0.000000E+00 0.000000E+00 0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 1.000000E-02 3.400000E-05 -4.086838E-03 -5.900874E-06 -1.812330E-03 -3.716159E-06 -2.138941E-03 -3.006748E-06 +1.000000E-02 +3.400000E-05 5.414128E-03 8.079333E-06 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 3.079654E-04 9.484271E-08 0.000000E+00 @@ -193,32 +121,16 @@ tally 1: 0.000000E+00 0.000000E+00 0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 1.700000E-02 7.100000E-05 -5.492922E-03 -1.013834E-05 -5.773309E-04 -3.561549E-06 -2.550048E-03 -3.841061E-06 +1.700000E-02 +7.100000E-05 8.048522E-03 1.583843E-05 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 5.915762E-04 1.749885E-07 0.000000E+00 @@ -233,152 +145,88 @@ tally 1: 0.000000E+00 0.000000E+00 0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 2.700000E-02 1.670000E-04 -1.789444E-02 -8.260005E-05 -1.049872E-02 -2.774537E-05 -5.665111E-03 -8.560197E-06 +2.700000E-02 +1.670000E-04 1.100708E-02 2.835295E-05 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 3.079654E-04 9.484271E-08 1.000000E-03 1.000000E-06 --2.856031E-04 -8.156913E-08 --3.776463E-04 -1.426167E-07 -3.701637E-04 -1.370211E-07 +1.000000E-03 +1.000000E-06 1.203064E-03 7.240967E-07 1.000000E-03 1.000000E-06 -9.705482E-04 -9.419638E-07 -9.129457E-04 -8.334699E-07 -8.297310E-04 -6.884535E-07 +1.000000E-03 +1.000000E-06 0.000000E+00 0.000000E+00 4.400000E-02 4.320000E-04 -1.141886E-02 -4.208707E-05 -9.213446E-03 -2.259305E-05 -9.177440E-03 -2.088782E-05 +4.400000E-02 +4.320000E-04 2.116869E-02 9.629046E-05 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 1.501009E-03 6.405021E-07 1.000000E-03 1.000000E-06 -5.882614E-04 -3.460515E-07 -1.907719E-05 -3.639390E-10 --3.734703E-04 -1.394801E-07 +1.000000E-03 +1.000000E-06 1.472277E-03 9.506217E-07 2.000000E-03 2.000000E-06 -1.830192E-03 -1.679505E-06 -1.519257E-03 -1.189525E-06 -1.118506E-03 -7.332971E-07 +2.000000E-03 +2.000000E-06 2.977039E-04 8.862762E-08 2.000000E-02 1.080000E-04 -8.640372E-03 -1.765553E-05 -5.688468E-03 -1.038555E-05 -2.447898E-03 -4.466055E-06 +2.000000E-02 +1.080000E-04 8.949667E-03 1.935056E-05 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 2.977039E-04 8.862762E-08 1.000000E-03 1.000000E-06 --3.805163E-04 -1.447926E-07 --2.828111E-04 -7.998210E-08 -4.330345E-04 -1.875189E-07 +1.000000E-03 +1.000000E-06 2.121142E-03 1.958355E-06 1.000000E-03 1.000000E-06 -9.260022E-04 -8.574800E-07 -7.862200E-04 -6.181419E-07 -5.960676E-04 -3.552966E-07 +1.000000E-03 +1.000000E-06 2.938723E-04 8.636091E-08 1.000000E-02 3.400000E-05 -4.840884E-03 -1.080853E-05 -3.402096E-03 -4.113972E-06 -1.374077E-03 -2.333511E-06 +1.000000E-02 +3.400000E-05 4.754696E-03 7.172309E-06 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 3.079654E-04 9.484271E-08 0.000000E+00 @@ -393,122 +241,70 @@ tally 1: 0.000000E+00 0.000000E+00 0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 1.300000E-02 3.700000E-05 -3.121167E-03 -2.465327E-06 -4.474559E-04 -1.522316E-06 -9.193982E-04 -3.247292E-06 +1.300000E-02 +3.700000E-05 5.365659E-03 6.567979E-06 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 6.056043E-04 1.834316E-07 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 2.977039E-04 8.862762E-08 1.000000E-03 1.000000E-06 -2.390376E-04 -5.713899E-08 --4.142915E-04 -1.716375E-07 --3.244105E-04 -1.052422E-07 +1.000000E-03 +1.000000E-06 0.000000E+00 0.000000E+00 2.900000E-02 2.230000E-04 -6.260565E-03 -1.544092E-05 -7.061757E-03 -2.562385E-05 -3.982541E-03 -7.962565E-06 +2.900000E-02 +2.230000E-04 1.486928E-02 5.763901E-05 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 5.915762E-04 1.749885E-07 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 5.954078E-04 3.545105E-07 1.000000E-03 1.000000E-06 -9.938157E-04 -9.876697E-07 -9.815046E-04 -9.633512E-07 -9.631807E-04 -9.277170E-07 +1.000000E-03 +1.000000E-06 0.000000E+00 0.000000E+00 2.900000E-02 1.990000E-04 -1.237546E-02 -3.198261E-05 -8.287792E-03 -2.747313E-05 -3.254969E-03 -8.653294E-06 +2.900000E-02 +1.990000E-04 1.189702E-02 3.303340E-05 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 9.033082E-04 2.720592E-07 3.000000E-03 3.000000E-06 -3.649225E-04 -1.756075E-06 -1.134112E-03 -8.940601E-07 --9.392028E-04 -5.872882E-07 +4.000000E-03 +6.000000E-06 1.484187E-03 9.721092E-07 0.000000E+00 @@ -517,188 +313,112 @@ tally 1: 0.000000E+00 0.000000E+00 0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 2.500000E-02 1.390000E-04 -1.511834E-02 -5.459835E-05 -7.753447E-03 -2.291820E-05 -6.142979E-03 -1.359405E-05 +2.500000E-02 +1.390000E-04 1.043467E-02 2.526768E-05 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 5.912057E-04 1.747704E-07 1.000000E-03 1.000000E-06 --1.098110E-04 -1.205846E-08 --4.819123E-04 -2.322395E-07 -1.614061E-04 -2.605194E-08 +1.000000E-03 +1.000000E-06 8.813114E-04 4.316251E-07 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 2.935668E-04 8.618147E-08 1.900000E-02 1.030000E-04 -1.035735E-02 -3.119381E-05 -6.483551E-03 -1.164471E-05 -3.924334E-03 -6.047577E-06 +1.900000E-02 +1.030000E-04 9.748672E-03 2.956633E-05 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 3.079654E-04 9.484271E-08 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 2.935668E-04 8.618147E-08 1.000000E-03 1.000000E-06 -8.623139E-04 -7.435852E-07 -6.153778E-04 -3.786899E-07 -3.095388E-04 -9.581428E-08 +1.000000E-03 +1.000000E-06 0.000000E+00 0.000000E+00 7.000000E-03 1.500000E-05 -3.445754E-03 -3.819507E-06 -2.124056E-03 -1.976201E-06 -1.542203E-03 -1.531669E-06 +7.000000E-03 +1.500000E-05 4.135720E-03 4.532611E-06 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 5.874391E-04 1.725424E-07 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 3.079654E-04 9.484271E-08 1.000000E-03 1.000000E-06 -9.451745E-04 -8.933548E-07 -8.400323E-04 -7.056542E-07 -6.931788E-04 -4.804969E-07 +1.000000E-03 +1.000000E-06 0.000000E+00 0.000000E+00 2.600000E-02 1.560000E-04 -6.314886E-03 -1.168542E-05 -6.676680E-04 -9.930437E-06 --2.103247E-04 -2.815945E-07 +2.600000E-02 +1.560000E-04 1.249410E-02 3.501589E-05 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 6.159309E-04 3.793709E-07 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 2.976389E-04 8.858890E-08 1.000000E-03 1.000000E-06 -9.514029E-04 -9.051675E-07 -8.577513E-04 -7.357373E-07 -7.258432E-04 -5.268483E-07 +1.000000E-03 +1.000000E-06 0.000000E+00 0.000000E+00 2.900000E-02 1.950000E-04 -8.928267E-03 -2.594547E-05 -4.752762E-03 -1.522378E-05 -5.376579E-03 -1.088620E-05 +2.900000E-02 +1.950000E-04 1.461148E-02 4.367385E-05 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 5.912057E-04 1.747704E-07 0.000000E+00 @@ -713,62 +433,34 @@ tally 1: 0.000000E+00 0.000000E+00 0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 1.900000E-02 9.700000E-05 -1.046968E-02 -3.828445E-05 -6.704767E-03 -2.668260E-05 -2.659611E-03 -1.143518E-05 +1.900000E-02 +9.700000E-05 1.099391E-02 2.847330E-05 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 2.935668E-04 8.618147E-08 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 2.655539E-03 2.523801E-06 3.000000E-03 5.000000E-06 -2.960960E-03 -4.866206E-06 -2.884206E-03 -4.608867E-06 -2.772329E-03 -4.247272E-06 +3.000000E-03 +5.000000E-06 2.976389E-04 8.858890E-08 6.000000E-03 8.000000E-06 -2.104495E-03 -2.749678E-06 -8.451272E-04 -9.362821E-07 -5.355137E-04 -3.419837E-07 +6.000000E-03 +8.000000E-06 2.683856E-03 1.512640E-06 0.000000E+00 @@ -781,124 +473,72 @@ tally 1: 0.000000E+00 0.000000E+00 0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 2.976389E-04 8.858890E-08 1.000000E-03 1.000000E-06 -9.374310E-04 -8.787769E-07 -8.181653E-04 -6.693944E-07 -6.533352E-04 -4.268468E-07 +1.000000E-03 +1.000000E-06 2.976389E-04 8.858890E-08 1.200000E-02 4.600000E-05 -9.302157E-04 -3.853850E-06 -1.874541E-03 -3.092623E-06 --1.511552E-03 -4.053466E-06 +1.200000E-02 +4.600000E-05 5.941985E-03 9.853870E-06 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 1.186548E-03 5.291647E-07 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 2.935668E-04 8.618147E-08 1.000000E-03 1.000000E-06 -9.893707E-04 -9.788543E-07 -9.682814E-04 -9.375689E-07 -9.370683E-04 -8.780970E-07 +1.000000E-03 +1.000000E-06 0.000000E+00 0.000000E+00 2.300000E-02 1.230000E-04 -5.099566E-03 -9.143616E-06 -4.738751E-03 -7.819254E-06 -3.929250E-03 -6.884420E-06 +2.300000E-02 +1.230000E-04 1.015650E-02 2.236950E-05 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 2.977039E-04 8.862762E-08 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 5.912707E-04 1.748091E-07 2.000000E-03 2.000000E-06 -1.762035E-03 -1.552542E-06 -1.328812E-03 -8.839688E-07 -7.771806E-04 -3.049398E-07 +2.000000E-03 +2.000000E-06 0.000000E+00 0.000000E+00 3.100000E-02 2.250000E-04 -1.389831E-02 -5.927254E-05 -9.999959E-03 -3.379365E-05 -4.584291E-03 -1.665226E-05 +3.100000E-02 +2.250000E-04 1.729188E-02 6.078653E-05 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 1.792523E-03 8.900697E-07 0.000000E+00 @@ -913,42 +553,22 @@ tally 1: 0.000000E+00 0.000000E+00 0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 1.700000E-02 7.100000E-05 -3.566805E-03 -2.049908E-05 -5.418617E-03 -7.496014E-06 -2.451897E-03 -2.115374E-06 +1.700000E-02 +7.100000E-05 7.760000E-03 1.634547E-05 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 2.977039E-04 8.862762E-08 1.000000E-03 1.000000E-06 --7.119580E-04 -5.068842E-07 -2.603263E-04 -6.776977E-08 -1.657364E-04 -2.746855E-08 +1.000000E-03 +1.000000E-06 8.807004E-04 7.756332E-07 0.000000E+00 @@ -957,28 +577,16 @@ tally 1: 0.000000E+00 0.000000E+00 0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 2.900000E-02 2.030000E-04 -6.527719E-03 -1.422798E-05 -1.560049E-03 -2.934829E-06 -1.548553E-03 -8.929308E-06 +2.900000E-02 +2.030000E-04 1.108618E-02 3.019577E-05 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 1.174573E-03 8.619941E-07 0.000000E+00 @@ -993,72 +601,40 @@ tally 1: 0.000000E+00 0.000000E+00 0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 1.500000E-02 5.500000E-05 -2.209492E-03 -2.545503E-06 -5.991182E-03 -1.290780E-05 -1.772063E-03 -2.006265E-06 +1.500000E-02 +5.500000E-05 5.944486E-03 1.042417E-05 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 3.079654E-04 9.484271E-08 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 1.190621E-03 8.859277E-07 2.000000E-03 2.000000E-06 -1.908405E-03 -1.821879E-06 -1.732819E-03 -1.508498E-06 -1.487670E-03 -1.131430E-06 +2.000000E-03 +2.000000E-06 0.000000E+00 0.000000E+00 2.600000E-02 1.460000E-04 -7.818547E-03 -3.176773E-05 -5.200193E-03 -1.419001E-05 -3.947828E-03 -8.417104E-06 +2.600000E-02 +1.460000E-04 9.232713E-03 1.900222E-05 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 1.186919E-03 5.294603E-07 0.000000E+00 @@ -1073,112 +649,64 @@ tally 1: 0.000000E+00 0.000000E+00 0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 3.600000E-02 2.740000E-04 -9.407788E-03 -2.403566E-05 -4.480017E-03 -6.102099E-06 -5.941113E-03 -1.265337E-05 +3.600000E-02 +2.740000E-04 1.462273E-02 4.551798E-05 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 6.056694E-04 1.834703E-07 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 8.807004E-04 7.756332E-07 1.000000E-03 1.000000E-06 -8.905295E-04 -7.930427E-07 -6.895641E-04 -4.754986E-07 -4.297756E-04 -1.847070E-07 +1.000000E-03 +1.000000E-06 0.000000E+00 0.000000E+00 1.200000E-02 3.000000E-05 -4.798420E-03 -7.171924E-06 -1.417651E-03 -4.997963E-06 -2.131704E-03 -3.253030E-06 +1.200000E-02 +3.000000E-05 7.754474E-03 1.333333E-05 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 2.938723E-04 8.636091E-08 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 1.484382E-03 1.504223E-06 3.000000E-03 5.000000E-06 -2.760812E-03 -4.139104E-06 -2.336063E-03 -2.844690E-06 -1.817042E-03 -1.656152E-06 +3.000000E-03 +5.000000E-06 0.000000E+00 0.000000E+00 1.900000E-02 9.900000E-05 -7.385212E-03 -2.033270E-05 -6.336514E-03 -2.028060E-05 -3.967026E-03 -1.027239E-05 +1.900000E-02 +9.900000E-05 1.066281E-02 2.937590E-05 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 2.976389E-04 8.858890E-08 0.000000E+00 @@ -1193,22 +721,10 @@ tally 1: 0.000000E+00 0.000000E+00 0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 3.000000E-03 3.000000E-06 -1.134842E-03 -1.040850E-06 -6.127525E-05 -3.988312E-07 -4.938488E-05 -2.738492E-07 +3.000000E-03 +3.000000E-06 1.484493E-03 9.722886E-07 0.000000E+00 @@ -1229,26 +745,10 @@ tally 1: 0.000000E+00 0.000000E+00 0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 2.300000E-02 1.650000E-04 -9.507197E-03 -3.773476E-05 -6.295609E-03 -2.127696E-05 -6.339840E-03 -1.601206E-05 +2.300000E-02 +1.650000E-04 1.065253E-02 3.447907E-05 0.000000E+00 @@ -1257,18 +757,10 @@ tally 1: 0.000000E+00 0.000000E+00 0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 1.000000E-03 1.000000E-06 --1.117213E-04 -1.248165E-08 --4.812775E-04 -2.316281E-07 -1.640958E-04 -2.692743E-08 +1.000000E-03 +1.000000E-06 5.871336E-04 3.447259E-07 0.000000E+00 @@ -1277,38 +769,22 @@ tally 1: 0.000000E+00 0.000000E+00 0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 3.100000E-02 2.030000E-04 -1.194795E-02 -4.198084E-05 -8.484089E-03 -1.631808E-05 -5.880364E-03 -1.308096E-05 +3.100000E-02 +2.030000E-04 1.342551E-02 3.842917E-05 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 5.915762E-04 1.749885E-07 1.000000E-03 1.000000E-06 --5.881991E-05 -3.459782E-09 --4.948103E-04 -2.448373E-07 -8.772111E-05 -7.694993E-09 +1.000000E-03 +1.000000E-06 5.871336E-04 3.447259E-07 0.000000E+00 @@ -1317,28 +793,16 @@ tally 1: 0.000000E+00 0.000000E+00 0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 1.900000E-02 8.700000E-05 -5.469796E-03 -1.029265E-05 -4.923561E-04 -2.403244E-06 -2.579361E-03 -5.814745E-06 +1.900000E-02 +8.700000E-05 8.693502E-03 1.682273E-05 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 2.976389E-04 8.858890E-08 0.000000E+00 @@ -1353,22 +817,10 @@ tally 1: 0.000000E+00 0.000000E+00 0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 8.000000E-03 1.600000E-05 -5.411154E-03 -8.076329E-06 -3.145940E-03 -4.212660E-06 -2.637510E-03 -3.210372E-06 +8.000000E-03 +1.600000E-05 3.866943E-03 3.257876E-06 0.000000E+00 @@ -1381,44 +833,24 @@ tally 1: 0.000000E+00 0.000000E+00 0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 1.175489E-03 1.381775E-06 1.000000E-03 1.000000E-06 -7.809681E-04 -6.099112E-07 -4.148668E-04 -1.721145E-07 -1.935089E-05 -3.744570E-10 +1.000000E-03 +1.000000E-06 0.000000E+00 0.000000E+00 8.000000E-03 2.000000E-05 -3.721382E-03 -4.736982E-06 --1.037031E-04 -6.648392E-07 --5.996856E-04 -9.642316E-07 +8.000000E-03 +2.000000E-05 3.248622E-03 4.063213E-06 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 2.938723E-04 8.636091E-08 0.000000E+00 @@ -1433,32 +865,16 @@ tally 1: 0.000000E+00 0.000000E+00 0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 2.800000E-02 1.780000E-04 -1.190615E-02 -4.434442E-05 -7.332993E-03 -2.337416E-05 -6.867008E-03 -1.321552E-05 +2.800000E-02 +1.780000E-04 1.283876E-02 3.527487E-05 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 5.954078E-04 3.545105E-07 0.000000E+00 @@ -1473,42 +889,22 @@ tally 1: 0.000000E+00 0.000000E+00 0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 4.000000E-02 3.880000E-04 -6.620484E-03 -3.751545E-05 -9.255367E-03 -1.963463E-05 -7.761524E-03 -1.694944E-05 +4.000000E-02 +3.880000E-04 1.659048E-02 7.200873E-05 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 2.976389E-04 8.858890E-08 1.000000E-03 1.000000E-06 --5.273064E-04 -2.780520E-07 --8.292201E-05 -6.876059E-09 -4.244131E-04 -1.801265E-07 +1.000000E-03 +1.000000E-06 8.891500E-04 4.407165E-07 0.000000E+00 @@ -1517,18 +913,10 @@ tally 1: 0.000000E+00 0.000000E+00 0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 1.200000E-02 3.400000E-05 -5.905081E-03 -1.535048E-05 -3.856089E-03 -8.589511E-06 -3.244585E-03 -5.882222E-06 +1.200000E-02 +3.400000E-05 5.074320E-03 5.793165E-06 0.000000E+00 @@ -1549,26 +937,10 @@ tally 1: 0.000000E+00 0.000000E+00 0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 4.000000E-03 8.000000E-06 -1.520286E-03 -4.076900E-06 -2.191143E-03 -3.717004E-06 -1.161623E-03 -3.726099E-06 +4.000000E-03 +8.000000E-06 3.570375E-03 5.251426E-06 0.000000E+00 @@ -1589,36 +961,16 @@ tally 1: 0.000000E+00 0.000000E+00 0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 4.000000E-03 4.000000E-06 -3.379122E-03 -2.880429E-06 -2.320644E-03 -1.498759E-06 -1.119131E-03 -6.212863E-07 +4.000000E-03 +4.000000E-06 1.494579E-03 6.241235E-07 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 2.976389E-04 8.858890E-08 0.000000E+00 @@ -1633,72 +985,40 @@ tally 1: 0.000000E+00 0.000000E+00 0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 3.100000E-02 1.950000E-04 -1.338410E-02 -5.097757E-05 -6.794436E-03 -1.428226E-05 -3.939298E-03 -9.052046E-06 +3.100000E-02 +1.950000E-04 1.250316E-02 3.147175E-05 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 5.953428E-04 1.772165E-07 1.000000E-03 1.000000E-06 --5.747626E-05 -3.303520E-09 --4.950447E-04 -2.450693E-07 -8.573970E-05 -7.351297E-09 +1.000000E-03 +1.000000E-06 5.954078E-04 3.545105E-07 1.000000E-03 1.000000E-06 -9.748367E-04 -9.503066E-07 -9.254598E-04 -8.564759E-07 -8.537292E-04 -7.288535E-07 +1.000000E-03 +1.000000E-06 0.000000E+00 0.000000E+00 2.600000E-02 1.800000E-04 -1.225587E-02 -3.757196E-05 -7.670283E-03 -2.316758E-05 -5.282346E-03 -1.407031E-05 +2.600000E-02 +1.800000E-04 1.162837E-02 3.241150E-05 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 5.874391E-04 1.725424E-07 0.000000E+00 @@ -1713,42 +1033,22 @@ tally 1: 0.000000E+00 0.000000E+00 0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 1.900000E-02 9.900000E-05 -7.244455E-03 -2.708286E-05 -4.601657E-03 -5.366244E-06 --1.675270E-03 -3.867377E-06 +1.900000E-02 +9.900000E-05 9.216754E-03 2.272207E-05 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 3.079654E-04 9.484271E-08 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 6.159309E-04 3.793709E-07 0.000000E+00 @@ -1757,18 +1057,10 @@ tally 1: 0.000000E+00 0.000000E+00 0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 6.000000E-03 1.000000E-05 -1.316884E-03 -2.894217E-06 -2.095957E-03 -1.439521E-06 -1.013831E-04 -8.405300E-07 +6.000000E-03 +1.000000E-05 2.404012E-03 1.641294E-06 0.000000E+00 @@ -1813,52 +1105,16 @@ tally 1: 0.000000E+00 0.000000E+00 0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 1.500000E-02 6.300000E-05 -5.790211E-03 -1.210465E-05 -8.591246E-04 -1.950998E-06 -1.987991E-03 -4.703397E-06 +1.500000E-02 +6.300000E-05 6.572185E-03 9.479065E-06 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 5.954078E-04 3.545105E-07 0.000000E+00 @@ -1873,22 +1129,10 @@ tally 1: 0.000000E+00 0.000000E+00 0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 1.900000E-02 1.030000E-04 -3.010784E-03 -6.984061E-06 -5.243839E-03 -8.093978E-06 --2.502286E-04 -2.564795E-06 +1.900000E-02 +1.030000E-04 7.760558E-03 1.654841E-05 0.000000E+00 @@ -1901,44 +1145,24 @@ tally 1: 0.000000E+00 0.000000E+00 0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 2.935668E-04 8.618147E-08 1.000000E-03 1.000000E-06 -9.333938E-04 -8.712239E-07 -8.068359E-04 -6.509841E-07 -6.328968E-04 -4.005583E-07 +1.000000E-03 +1.000000E-06 0.000000E+00 0.000000E+00 1.800000E-02 1.220000E-04 -6.860987E-03 -2.966806E-05 -4.229750E-03 -1.617998E-05 -1.295452E-03 -8.613003E-07 +1.800000E-02 +1.220000E-04 7.815192E-03 2.039362E-05 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 2.935668E-04 8.618147E-08 0.000000E+00 @@ -1977,38 +1201,10 @@ tally 1: 0.000000E+00 0.000000E+00 0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 2.000000E-03 2.000000E-06 -1.502634E-03 -1.146555E-06 -7.198331E-04 -3.484978E-07 --3.426513E-05 -1.342349E-07 +2.000000E-03 +2.000000E-06 1.511030E-03 1.198310E-06 0.000000E+00 @@ -2029,26 +1225,10 @@ tally 1: 0.000000E+00 0.000000E+00 0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 1.900000E-02 1.030000E-04 -3.892013E-03 -8.267134E-06 -3.385502E-03 -6.457947E-06 -4.380506E-03 -1.060881E-05 +1.900000E-02 +1.030000E-04 7.130794E-03 1.485134E-05 0.000000E+00 @@ -2061,74 +1241,42 @@ tally 1: 0.000000E+00 0.000000E+00 0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 8.816168E-04 7.772482E-07 1.000000E-03 1.000000E-06 -9.951010E-04 -9.902260E-07 -9.853389E-04 -9.708928E-07 -9.707856E-04 -9.424246E-07 +1.000000E-03 +1.000000E-06 0.000000E+00 0.000000E+00 2.900000E-02 1.970000E-04 -4.944370E-03 -2.340271E-05 -3.891346E-03 -1.137205E-05 -5.738303E-03 -9.169816E-06 +2.900000E-02 +1.970000E-04 1.046961E-02 2.353870E-05 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 6.056694E-04 1.834703E-07 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 1.203064E-03 7.240967E-07 2.000000E-03 2.000000E-06 -1.696621E-03 -1.449397E-06 -1.174096E-03 -7.548933E-07 -5.719051E-04 -3.184788E-07 +2.000000E-03 +2.000000E-06 0.000000E+00 0.000000E+00 1.600000E-02 5.400000E-05 -7.937805E-03 -1.353584E-05 -4.065443E-03 -5.658333E-06 -3.432476E-03 -3.530320E-06 +1.600000E-02 +5.400000E-05 6.546902E-03 9.343143E-06 0.000000E+00 @@ -2149,26 +1297,10 @@ tally 1: 0.000000E+00 0.000000E+00 0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 2.000000E-03 2.000000E-06 -1.447007E-04 -7.721849E-07 -1.582773E-04 -4.841114E-08 -1.981705E-04 -2.166687E-07 +2.000000E-03 +2.000000E-06 9.135698E-04 4.679598E-07 0.000000E+00 @@ -2213,142 +1345,70 @@ tally 1: 0.000000E+00 0.000000E+00 0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 1.000000E-02 2.600000E-05 -5.875085E-04 -4.563904E-07 --9.207198E-05 -5.154496E-07 -3.674257E-05 -1.178281E-06 +1.000000E-02 +2.600000E-05 5.048984E-03 5.880389E-06 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 3.079654E-04 9.484271E-08 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 5.952777E-04 3.543556E-07 1.000000E-03 1.000000E-06 -9.362621E-04 -8.765867E-07 -8.148801E-04 -6.640295E-07 -6.473941E-04 -4.191191E-07 +1.000000E-03 +1.000000E-06 0.000000E+00 0.000000E+00 2.000000E-02 9.000000E-05 -5.358616E-03 -1.697599E-05 -3.060277E-03 -7.132281E-06 -2.485730E-03 -7.247489E-06 +2.000000E-02 +9.000000E-05 9.248312E-03 1.738407E-05 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 8.991711E-04 2.696131E-07 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 5.954078E-04 3.545105E-07 1.000000E-03 1.000000E-06 -9.816220E-04 -9.635817E-07 -9.453726E-04 -8.937294E-07 -8.922496E-04 -7.961093E-07 +1.000000E-03 +1.000000E-06 0.000000E+00 0.000000E+00 8.000000E-03 1.800000E-05 -4.925975E-03 -6.260377E-06 -3.176938E-03 -2.631319E-06 -2.008278E-03 -1.484516E-06 +8.000000E-03 +1.800000E-05 3.844641E-03 4.075868E-06 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 2.977039E-04 8.862762E-08 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 9.238963E-04 8.535844E-07 0.000000E+00 @@ -2357,18 +1417,10 @@ tally 1: 0.000000E+00 0.000000E+00 0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 1.000000E-03 1.000000E-06 --3.865739E-04 -1.494394E-07 --2.758409E-04 -7.608820E-08 -4.354374E-04 -1.896058E-07 +1.000000E-03 +1.000000E-06 5.871336E-04 3.447259E-07 0.000000E+00 @@ -2389,18 +1441,6 @@ tally 1: 0.000000E+00 0.000000E+00 0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 tally 2: 5.656886E-01 6.401440E-02 diff --git a/tests/regression_tests/statepoint_restart/tallies.xml b/tests/regression_tests/statepoint_restart/tallies.xml index db9b2ed75c..c7dff36f0d 100644 --- a/tests/regression_tests/statepoint_restart/tallies.xml +++ b/tests/regression_tests/statepoint_restart/tallies.xml @@ -30,7 +30,7 @@ 1 2 3 - scatter-P3 nu-fission + scatter nu-scatter nu-fission diff --git a/tests/regression_tests/tallies/inputs_true.dat b/tests/regression_tests/tallies/inputs_true.dat index 2c33a8fa0d..6e7b5f3f02 100644 --- a/tests/regression_tests/tallies/inputs_true.dat +++ b/tests/regression_tests/tallies/inputs_true.dat @@ -341,13 +341,19 @@ 0.0 0.6283 1.2566 1.885 2.5132 3.14159 - + + 4 + + + 4 + + 1 2 3 4 6 8 - + 10 21 22 23 60 - + 21 22 23 27 28 29 60 @@ -414,80 +420,80 @@ 10 - total + scatter nu-scatter 11 - absorption delayed-nu-fission events fission inverse-velocity kappa-fission (n,2n) (n,n1) (n,gamma) nu-fission scatter elastic total prompt-nu-fission fission-q-prompt fission-q-recoverable - tracklength + scatter nu-scatter flux total 11 - absorption delayed-nu-fission events fission inverse-velocity kappa-fission (n,2n) (n,n1) (n,gamma) nu-fission scatter elastic total prompt-nu-fission fission-q-prompt fission-q-recoverable - analog + flux total 11 - absorption delayed-nu-fission events fission inverse-velocity kappa-fission (n,2n) (n,n1) (n,gamma) nu-fission scatter elastic total prompt-nu-fission fission-q-prompt fission-q-recoverable - collision + flux total 12 - flux + total - 12 - flux-y5 + 13 + absorption delayed-nu-fission events fission inverse-velocity kappa-fission (n,2n) (n,n1) (n,gamma) nu-fission scatter elastic total prompt-nu-fission fission-q-prompt fission-q-recoverable tracklength - 12 - flux-y5 + 13 + absorption delayed-nu-fission events fission inverse-velocity kappa-fission (n,2n) (n,n1) (n,gamma) nu-fission scatter elastic total prompt-nu-fission fission-q-prompt fission-q-recoverable analog - 12 - flux-y5 + 13 + absorption delayed-nu-fission events fission inverse-velocity kappa-fission (n,2n) (n,n1) (n,gamma) nu-fission scatter elastic total prompt-nu-fission fission-q-prompt fission-q-recoverable collision - 11 - scatter scatter-1 scatter-2 scatter-3 scatter-4 nu-scatter nu-scatter-1 nu-scatter-2 nu-scatter-3 nu-scatter-4 + 14 + flux + tracklength - 11 - scatter-p4 scatter-y4 nu-scatter-p4 nu-scatter-y3 + 14 + flux + analog - 11 - total + 14 + flux + collision - 11 + 13 U235 total - total-y4 + total tracklength - 11 + 13 U235 total - total-y4 + total analog - 11 + 13 U235 total - total-y4 + total collision - 11 + 13 all total tracklength - 11 + 13 all total collision diff --git a/tests/regression_tests/tallies/results_true.dat b/tests/regression_tests/tallies/results_true.dat index e9c0865fd5..b1cef30fef 100644 --- a/tests/regression_tests/tallies/results_true.dat +++ b/tests/regression_tests/tallies/results_true.dat @@ -1 +1 @@ -13014f42dea87bf6c1fc0d41361cdba8a7e32a8f809d348567dfce638c849f58a0c0f17065c199946db81a264ef72db850aea93b0e11adf4f70ec969e30529cd \ No newline at end of file +8cf1936c565c6a09bffe2f7a0623ded1405bae37c1de8159551e64b86ca4f6bce82890a630b9428bcf8353f6de8e5cfc1f1a4263fd51a1c6b5cddb0a9c2ff368 \ No newline at end of file diff --git a/tests/regression_tests/tallies/test.py b/tests/regression_tests/tallies/test.py index e3aebfd986..53ce60b628 100644 --- a/tests/regression_tests/tallies/test.py +++ b/tests/regression_tests/tallies/test.py @@ -1,5 +1,6 @@ from openmc.filter import * -from openmc import Mesh, Tally, Tallies +from openmc.filter_expansion import * +from openmc import Mesh, Tally from tests.testing_harness import HashedPyAPITestHarness @@ -17,53 +18,53 @@ def test_tallies(): azimuthal_bins = (-3.14159, -1.8850, -0.6283, 0.6283, 1.8850, 3.14159) azimuthal_filter = AzimuthalFilter(azimuthal_bins) - azimuthal_tally1 = Tally() + azimuthal_tally1 = Tally(tally_id=1) azimuthal_tally1.filters = [azimuthal_filter] azimuthal_tally1.scores = ['flux'] azimuthal_tally1.estimator = 'tracklength' - azimuthal_tally2 = Tally() + azimuthal_tally2 = Tally(tally_id=2) azimuthal_tally2.filters = [azimuthal_filter] azimuthal_tally2.scores = ['flux'] azimuthal_tally2.estimator = 'analog' mesh_2x2 = Mesh(mesh_id=1) - mesh_2x2.lower_left = [-182.07, -182.07] - mesh_2x2.upper_right = [182.07, 182.07] + mesh_2x2.lower_left = [-182.07, -182.07] + mesh_2x2.upper_right = [182.07, 182.07] mesh_2x2.dimension = [2, 2] mesh_filter = MeshFilter(mesh_2x2) - azimuthal_tally3 = Tally() + azimuthal_tally3 = Tally(tally_id=3) azimuthal_tally3.filters = [azimuthal_filter, mesh_filter] azimuthal_tally3.scores = ['flux'] azimuthal_tally3.estimator = 'tracklength' - cellborn_tally = Tally() + cellborn_tally = Tally(tally_id=4) cellborn_tally.filters = [ CellbornFilter((model.geometry.get_all_cells()[10], model.geometry.get_all_cells()[21], 22, 23))] # Test both Cell objects and ids cellborn_tally.scores = ['total'] - dg_tally = Tally() + dg_tally = Tally(tally_id=5) dg_tally.filters = [DelayedGroupFilter((1, 2, 3, 4, 5, 6))] dg_tally.scores = ['delayed-nu-fission'] four_groups = (0.0, 0.253, 1.0e3, 1.0e6, 20.0e6) energy_filter = EnergyFilter(four_groups) - energy_tally = Tally() + energy_tally = Tally(tally_id=6) energy_tally.filters = [energy_filter] energy_tally.scores = ['total'] energyout_filter = EnergyoutFilter(four_groups) - energyout_tally = Tally() + energyout_tally = Tally(tally_id=7) energyout_tally.filters = [energyout_filter] energyout_tally.scores = ['scatter'] - transfer_tally = Tally() + transfer_tally = Tally(tally_id=8) transfer_tally.filters = [energy_filter, energyout_filter] transfer_tally.scores = ['scatter', 'nu-fission'] - material_tally = Tally() + material_tally = Tally(tally_id=9) material_tally.filters = [ MaterialFilter((model.geometry.get_materials_by_name('UOX fuel')[0], model.geometry.get_materials_by_name('Zircaloy')[0], @@ -72,32 +73,56 @@ def test_tallies(): mu_bins = (-1.0, -0.5, 0.0, 0.5, 1.0) mu_filter = MuFilter(mu_bins) - mu_tally1 = Tally() + mu_tally1 = Tally(tally_id=10) mu_tally1.filters = [mu_filter] mu_tally1.scores = ['scatter', 'nu-scatter'] + print('mu_tally1', mu_tally1.id) - mu_tally2 = Tally() + mu_tally2 = Tally(tally_id=11) mu_tally2.filters = [mu_filter, mesh_filter] mu_tally2.scores = ['scatter', 'nu-scatter'] polar_bins = (0.0, 0.6283, 1.2566, 1.8850, 2.5132, 3.14159) polar_filter = PolarFilter(polar_bins) - polar_tally1 = Tally() + polar_tally1 = Tally(tally_id=12) polar_tally1.filters = [polar_filter] polar_tally1.scores = ['flux'] polar_tally1.estimator = 'tracklength' - polar_tally2 = Tally() + polar_tally2 = Tally(tally_id=13) polar_tally2.filters = [polar_filter] polar_tally2.scores = ['flux'] polar_tally2.estimator = 'analog' - polar_tally3 = Tally() + polar_tally3 = Tally(tally_id=14) polar_tally3.filters = [polar_filter, mesh_filter] polar_tally3.scores = ['flux'] polar_tally3.estimator = 'tracklength' - universe_tally = Tally() + legendre_filter = LegendreFilter(order=4) + legendre_tally = Tally(tally_id=15) + legendre_tally.filters = [legendre_filter] + legendre_tally.scores = ['scatter', 'nu-scatter'] + legendre_tally.estimatir = 'analog' + print('legendre_tally', mu_tally1.id) + + harmonics_filter = SphericalHarmonicsFilter(order=4) + harmonics_tally = Tally(tally_id=16) + harmonics_tally.filters = [harmonics_filter] + harmonics_tally.scores = ['scatter', 'nu-scatter', 'flux', 'total'] + harmonics_tally.estimatir = 'analog' + + harmonics_tally2 = Tally(tally_id=17) + harmonics_tally2.filters = [harmonics_filter] + harmonics_tally2.scores = ['flux', 'total'] + harmonics_tally2.estimatir = 'collision' + + harmonics_tally3 = Tally(tally_id=18) + harmonics_tally3.filters = [harmonics_filter] + harmonics_tally3.scores = ['flux', 'total'] + harmonics_tally3.estimatir = 'tracklength' + + universe_tally = Tally(tally_id=19) universe_tally.filters = [ UniverseFilter((model.geometry.get_all_universes()[1], model.geometry.get_all_universes()[2], @@ -107,7 +132,8 @@ def test_tallies(): cell_filter = CellFilter((model.geometry.get_all_cells()[10], model.geometry.get_all_cells()[21], 22, 23, 60)) # Test both Cell objects and ids - score_tallies = [Tally(), Tally(), Tally()] + score_tallies = [Tally(tally_id=20), Tally(tally_id=21), + Tally(tally_id=22)] for t in score_tallies: t.filters = [cell_filter] t.scores = ['absorption', 'delayed-nu-fission', 'events', 'fission', @@ -120,39 +146,24 @@ def test_tallies(): score_tallies[2].estimator = 'collision' cell_filter2 = CellFilter((21, 22, 23, 27, 28, 29, 60)) - flux_tallies = [Tally() for i in range(4)] + flux_tallies = [Tally(tally_id=23 + i) for i in range(3)] for t in flux_tallies: t.filters = [cell_filter2] - flux_tallies[0].scores = ['flux'] - for t in flux_tallies[1:]: - t.scores = ['flux-y5'] - flux_tallies[1].estimator = 'tracklength' - flux_tallies[2].estimator = 'analog' - flux_tallies[3].estimator = 'collision' + t.scores = ['flux'] + flux_tallies[0].estimator = 'tracklength' + flux_tallies[1].estimator = 'analog' + flux_tallies[2].estimator = 'collision' - scatter_tally1 = Tally() - scatter_tally1.filters = [cell_filter] - scatter_tally1.scores = ['scatter', 'scatter-1', 'scatter-2', 'scatter-3', - 'scatter-4', 'nu-scatter', 'nu-scatter-1', - 'nu-scatter-2', 'nu-scatter-3', 'nu-scatter-4'] - - scatter_tally2 = Tally() - scatter_tally2.filters = [cell_filter] - scatter_tally2.scores = ['scatter-p4', 'scatter-y4', 'nu-scatter-p4', - 'nu-scatter-y3'] - - total_tallies = [Tally() for i in range(4)] + total_tallies = [Tally(tally_id=26 + i) for i in range(3)] for t in total_tallies: t.filters = [cell_filter] - total_tallies[0].scores = ['total'] - for t in total_tallies[1:]: - t.scores = ['total-y4'] + t.scores = ['total'] t.nuclides = ['U235', 'total'] - total_tallies[1].estimator = 'tracklength' - total_tallies[2].estimator = 'analog' - total_tallies[3].estimator = 'collision' + total_tallies[0].estimator = 'tracklength' + total_tallies[1].estimator = 'analog' + total_tallies[2].estimator = 'collision' - all_nuclide_tallies = [Tally() for i in range(4)] + all_nuclide_tallies = [Tally(tally_id=29 + i) for i in range(4)] for t in all_nuclide_tallies: t.filters = [cell_filter] t.estimator = 'tracklength' @@ -167,10 +178,10 @@ def test_tallies(): azimuthal_tally1, azimuthal_tally2, azimuthal_tally3, cellborn_tally, dg_tally, energy_tally, energyout_tally, transfer_tally, material_tally, mu_tally1, mu_tally2, - polar_tally1, polar_tally2, polar_tally3, universe_tally] + polar_tally1, polar_tally2, polar_tally3, legendre_tally, + harmonics_tally, harmonics_tally2, harmonics_tally3, universe_tally] model.tallies += score_tallies model.tallies += flux_tallies - model.tallies += (scatter_tally1, scatter_tally2) model.tallies += total_tallies model.tallies += all_nuclide_tallies diff --git a/tests/regression_tests/track_output/test.py b/tests/regression_tests/track_output/test.py index 22eac03bfc..a5300a4aed 100644 --- a/tests/regression_tests/track_output/test.py +++ b/tests/regression_tests/track_output/test.py @@ -19,7 +19,7 @@ class TrackTestHarness(TestHarness): def _get_results(self): """Digest info in the statepoint and return as a string.""" # Run the track-to-vtk conversion script. - call(['../../scripts/openmc-track-to-vtk', '-o', 'poly'] + + call(['../../../scripts/openmc-track-to-vtk', '-o', 'poly'] + glob.glob('track_1_1_*.h5')) # Make sure the vtk file was created then return it's contents. From d4c4e612ea65e6de09ed276f66e990bdfb9a1dd6 Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Sun, 29 Apr 2018 19:09:22 -0500 Subject: [PATCH 66/77] Address @smharper comments on #996 --- src/error.F90 | 8 ++++++++ src/error.h | 18 +++++++++++++++--- src/hdf5_interface.cpp | 28 ++++++++++++++-------------- src/hdf5_interface.h | 27 +++++++++------------------ src/initialize.cpp | 7 +++++-- src/main.cpp | 28 ++++++++++++++-------------- 6 files changed, 65 insertions(+), 51 deletions(-) diff --git a/src/error.F90 b/src/error.F90 index f4fb34173c..d041051d29 100644 --- a/src/error.F90 +++ b/src/error.F90 @@ -111,6 +111,14 @@ contains end subroutine warning + subroutine warning_from_c(message, message_len) bind(C) + integer(C_INT), intent(in), value :: message_len + character(kind=C_CHAR), intent(in) :: message(message_len) + character(message_len+1) :: message_out + write(message_out, *) message + call warning(message_out) + end subroutine + !=============================================================================== ! FATAL_ERROR alerts the user that an error has been encountered and displays a ! message about the particular problem. Errors are considered 'fatal' and hence diff --git a/src/error.h b/src/error.h index 91c2727452..45d8bcdede 100644 --- a/src/error.h +++ b/src/error.h @@ -9,7 +9,8 @@ namespace openmc { -extern "C" void fatal_error_from_c(const char *message, int message_len); +extern "C" void fatal_error_from_c(const char* message, int message_len); +extern "C" void warning_from_c(const char* message, int message_len); inline @@ -27,8 +28,19 @@ void fatal_error(const std::string &message) inline void fatal_error(const std::stringstream &message) { - std::string out {message.str()}; - fatal_error_from_c(out.c_str(), out.length()); + fatal_error(message.str()); +} + +inline +void warning(const std::string& message) +{ + warning_from_c(message.c_str(), message.length()); +} + +inline +void warning(const std::stringstream& message) +{ + warning(message.str()); } } // namespace openmc diff --git a/src/hdf5_interface.cpp b/src/hdf5_interface.cpp index e4db2ee58a..8a8391bb54 100644 --- a/src/hdf5_interface.cpp +++ b/src/hdf5_interface.cpp @@ -122,20 +122,20 @@ file_open(const char* filename, char mode, bool parallel) bool create; unsigned int flags; switch (mode) { - case 'r': - case 'a': - create = false; - flags = (mode == 'r' ? H5F_ACC_RDONLY : H5F_ACC_RDWR); - break; - case 'w': - case 'x': - create = true; - flags = (mode == 'x' ? H5F_ACC_EXCL : H5F_ACC_TRUNC); - break; - default: - std::stringstream err_msg; - err_msg << "Invalid file mode: " << mode; - fatal_error(err_msg); + case 'r': + case 'a': + create = false; + flags = (mode == 'r' ? H5F_ACC_RDONLY : H5F_ACC_RDWR); + break; + case 'w': + case 'x': + create = true; + flags = (mode == 'x' ? H5F_ACC_EXCL : H5F_ACC_TRUNC); + break; + default: + std::stringstream err_msg; + err_msg << "Invalid file mode: " << mode; + fatal_error(err_msg); } hid_t plist = H5P_DEFAULT; diff --git a/src/hdf5_interface.h b/src/hdf5_interface.h index 9a8b3c569d..e38a31e997 100644 --- a/src/hdf5_interface.h +++ b/src/hdf5_interface.h @@ -35,24 +35,6 @@ extern "C" hid_t open_dataset(hid_t group_id, const char* name); extern "C" hid_t open_group(hid_t group_id, const char* name); bool using_mpio_device(hid_t obj_id); - -template void -write_double_1D(hid_t group_id, char const *name, - std::array &buffer) -{ - hsize_t dims[1]{array_len}; - hid_t dataspace = H5Screate_simple(1, dims, NULL); - - hid_t dataset = H5Dcreate(group_id, name, H5T_NATIVE_DOUBLE, dataspace, - H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT); - - H5Dwrite(dataset, H5T_NATIVE_DOUBLE, H5S_ALL, H5S_ALL, H5P_DEFAULT, - &buffer[0]); - - H5Sclose(dataspace); - H5Dclose(dataset); -} - void read_attr(hid_t obj_id, const char* name, hid_t mem_type_id, const void* buffer); extern "C" void read_attr_double(hid_t obj_id, const char* name, double* buffer); @@ -102,5 +84,14 @@ void write_string(hid_t group_id, const char* name, const std::string& buffer, b extern "C" void write_tally_results(hid_t group_id, hsize_t n_filter, hsize_t n_score, const double* results); +template void +write_double_1D(hid_t group_id, char const *name, + std::array &buffer) +{ + hsize_t dims[1] {array_len}; + write_dataset(group_id, 1, dims, name, H5T_NATIVE_DOUBLE, + buffer.data(), false); +} + } // namespace openmc #endif //HDF5_INTERFACE_H diff --git a/src/initialize.cpp b/src/initialize.cpp index c7c37e31db..728f43695b 100644 --- a/src/initialize.cpp +++ b/src/initialize.cpp @@ -102,8 +102,8 @@ void initialize_mpi(MPI_Comm intracomm) inline bool ends_with(std::string const& value, std::string const& ending) { - if (ending.size() > value.size()) return false; - return std::equal(ending.rbegin(), ending.rend(), value.rbegin()); + if (ending.size() > value.size()) return false; + return std::equal(ending.rbegin(), ending.rend(), value.rbegin()); } @@ -194,6 +194,9 @@ parse_command_line(int argc, char* argv[]) return OPENMC_E_INVALID_ARGUMENT; } omp_set_num_threads(openmc_n_threads); +#else + if (openmc_master) + warning("Ignoring number of threads specified on command line."); #endif } else if (arg == "-?" || arg == "-h" || arg == "--help") { diff --git a/src/main.cpp b/src/main.cpp index 6d0cf1f268..8d8f39e249 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -19,24 +19,24 @@ int main(int argc, char* argv[]) { // This happens for the -h and -v flags return 0; } else if (err) { - openmc::fatal_error(openmc_err_msg); + openmc::fatal_error(openmc_err_msg); } // start problem based on mode switch (openmc_run_mode) { - case RUN_MODE_FIXEDSOURCE: - case RUN_MODE_EIGENVALUE: - err = openmc_run(); - break; - case RUN_MODE_PLOTTING: - err = openmc_plot_geometry(); - break; - case RUN_MODE_PARTICLE: - if (openmc_master) err = openmc_particle_restart(); - break; - case RUN_MODE_VOLUME: - err = openmc_calculate_volumes(); - break; + case RUN_MODE_FIXEDSOURCE: + case RUN_MODE_EIGENVALUE: + err = openmc_run(); + break; + case RUN_MODE_PLOTTING: + err = openmc_plot_geometry(); + break; + case RUN_MODE_PARTICLE: + if (openmc_master) err = openmc_particle_restart(); + break; + case RUN_MODE_VOLUME: + err = openmc_calculate_volumes(); + break; } if (err) openmc::fatal_error(openmc_err_msg); From b61c67a12cd34f8f9a7c5641c73f98622a413ad4 Mon Sep 17 00:00:00 2001 From: Adam G Nelson Date: Tue, 1 May 2018 19:17:21 -0400 Subject: [PATCH 67/77] fixes per request of @paulromano: fixing test scratch files vice using .gitignore, minor typo in docs, and some otherwise small code cleanups --- .gitignore | 3 -- docs/source/usersguide/tallies.rst | 2 +- openmc/mgxs/mgxs.py | 2 +- openmc/tallies.py | 3 +- src/summary.F90 | 2 -- src/tallies/tally.F90 | 38 ++++++--------------- tests/regression_tests/tallies/test.py | 47 +++++++++++++------------- tests/unit_tests/test_data_neutron.py | 6 ++-- 8 files changed, 39 insertions(+), 64 deletions(-) diff --git a/.gitignore b/.gitignore index 0fc2c63bc0..ffdd58d335 100644 --- a/.gitignore +++ b/.gitignore @@ -100,6 +100,3 @@ examples/jupyter/plots .python-version .coverage htmlcov - -# Test data -tests/xsdir diff --git a/docs/source/usersguide/tallies.rst b/docs/source/usersguide/tallies.rst index 19691e32bf..bbec016423 100644 --- a/docs/source/usersguide/tallies.rst +++ b/docs/source/usersguide/tallies.rst @@ -24,7 +24,7 @@ function (:math:`f` in the above equation) should be used. The regions of phase space are generally called *filters* and the scoring functions are simply called *scores*. -The only cases when *filters* do not correspond directly with the regions of +The only cases when filters do not correspond directly with the regions of phase space are when expansion functions are applied in the integrand, such as for Legendre expansions of the scattering kernel. diff --git a/openmc/mgxs/mgxs.py b/openmc/mgxs/mgxs.py index 81b4420d9c..46f48fdfca 100644 --- a/openmc/mgxs/mgxs.py +++ b/openmc/mgxs/mgxs.py @@ -1925,7 +1925,7 @@ class MGXS(metaclass=ABCMeta): # Add the Legendre bin to the column if it exists if 'legendre' in df: - columns += ['legendre'] + columns.append('legendre') # If user requested micro cross sections, divide out the atom densities if xs_type == 'micro': diff --git a/openmc/tallies.py b/openmc/tallies.py index 1ac89129a9..a5341cbedd 100644 --- a/openmc/tallies.py +++ b/openmc/tallies.py @@ -391,8 +391,7 @@ class Tally(IDManagerMixin): 'nu-scatter-p', 'scatter-y', 'nu-scatter-y', 'flux-y', 'total-y']: if score.startswith(deprecated): - msg = score.strip() + ' is deprecated and should no ' \ - 'longer be used.' + msg = score.strip() + ' is no longer supported.' raise ValueError(msg) scores[i] = score.strip() diff --git a/src/summary.F90 b/src/summary.F90 index 409c4de1f5..a245648ef1 100644 --- a/src/summary.F90 +++ b/src/summary.F90 @@ -459,8 +459,6 @@ contains ! Find the number of macroscopic and nuclide data in this material num_nuclides = 0 num_macros = 0 - k = 1 - n = 1 do j = 1, m % n_nuclides if (nuclides_MG(m % nuclide(j)) % obj % awr /= MACROSCOPIC_AWR) then num_nuclides = num_nuclides + 1 diff --git a/src/tallies/tally.F90 b/src/tallies/tally.F90 index 483246b362..2e1d6184c3 100644 --- a/src/tallies/tally.F90 +++ b/src/tallies/tally.F90 @@ -1199,8 +1199,9 @@ contains !######################################################################### ! Expand score if necessary and add to tally results. - call expand_and_score(p, t, score_index, filter_index, score_bin, & - score, i) +!$omp atomic + t % results(RESULT_VALUE, score_index, filter_index) = & + t % results(RESULT_VALUE, score_index, filter_index) + score end do SCORE_LOOP end subroutine score_general_ce @@ -1982,36 +1983,15 @@ contains !######################################################################### ! Expand score if necessary and add to tally results. - call expand_and_score(p, t, score_index, filter_index, score_bin, & - score, i) +!$omp atomic + t % results(RESULT_VALUE, score_index, filter_index) = & + t % results(RESULT_VALUE, score_index, filter_index) + score end do SCORE_LOOP nullify(matxs, nucxs) end subroutine score_general_mg -!=============================================================================== -! EXPAND_AND_SCORE takes a previously determined score value and adjusts it -! if necessary (for functional expansion weighting), and then adds the resultant -! value to the tally results array. -!=============================================================================== - - subroutine expand_and_score(p, t, score_index, filter_index, score_bin, & - score, i) - type(Particle), intent(in) :: p - type(TallyObject), intent(inout) :: t - integer, intent(inout) :: score_index - integer, intent(in) :: filter_index ! for % results - integer, intent(in) :: score_bin ! score of concern - real(8), intent(inout) :: score ! data to score - integer, intent(inout) :: i ! Working index - -!$omp atomic - t % results(RESULT_VALUE, score_index, filter_index) = & - t % results(RESULT_VALUE, score_index, filter_index) + score - - end subroutine expand_and_score - !=============================================================================== ! SCORE_ALL_NUCLIDES tallies individual nuclide reaction rates specifically when ! the user requests all. @@ -2961,8 +2941,10 @@ contains score_index = q ! Expand score if necessary and add to tally results. - call expand_and_score(p, t, score_index, filter_index, score_bin, & - score, k) +!$omp atomic + t % results(RESULT_VALUE, score_index, filter_index) = & + t % results(RESULT_VALUE, score_index, filter_index) + score + end do SCORE_LOOP ! ====================================================================== diff --git a/tests/regression_tests/tallies/test.py b/tests/regression_tests/tallies/test.py index 53ce60b628..b86d71d006 100644 --- a/tests/regression_tests/tallies/test.py +++ b/tests/regression_tests/tallies/test.py @@ -18,12 +18,12 @@ def test_tallies(): azimuthal_bins = (-3.14159, -1.8850, -0.6283, 0.6283, 1.8850, 3.14159) azimuthal_filter = AzimuthalFilter(azimuthal_bins) - azimuthal_tally1 = Tally(tally_id=1) + azimuthal_tally1 = Tally() azimuthal_tally1.filters = [azimuthal_filter] azimuthal_tally1.scores = ['flux'] azimuthal_tally1.estimator = 'tracklength' - azimuthal_tally2 = Tally(tally_id=2) + azimuthal_tally2 = Tally() azimuthal_tally2.filters = [azimuthal_filter] azimuthal_tally2.scores = ['flux'] azimuthal_tally2.estimator = 'analog' @@ -33,38 +33,38 @@ def test_tallies(): mesh_2x2.upper_right = [182.07, 182.07] mesh_2x2.dimension = [2, 2] mesh_filter = MeshFilter(mesh_2x2) - azimuthal_tally3 = Tally(tally_id=3) + azimuthal_tally3 = Tally() azimuthal_tally3.filters = [azimuthal_filter, mesh_filter] azimuthal_tally3.scores = ['flux'] azimuthal_tally3.estimator = 'tracklength' - cellborn_tally = Tally(tally_id=4) + cellborn_tally = Tally() cellborn_tally.filters = [ CellbornFilter((model.geometry.get_all_cells()[10], model.geometry.get_all_cells()[21], 22, 23))] # Test both Cell objects and ids cellborn_tally.scores = ['total'] - dg_tally = Tally(tally_id=5) + dg_tally = Tally() dg_tally.filters = [DelayedGroupFilter((1, 2, 3, 4, 5, 6))] dg_tally.scores = ['delayed-nu-fission'] four_groups = (0.0, 0.253, 1.0e3, 1.0e6, 20.0e6) energy_filter = EnergyFilter(four_groups) - energy_tally = Tally(tally_id=6) + energy_tally = Tally() energy_tally.filters = [energy_filter] energy_tally.scores = ['total'] energyout_filter = EnergyoutFilter(four_groups) - energyout_tally = Tally(tally_id=7) + energyout_tally = Tally() energyout_tally.filters = [energyout_filter] energyout_tally.scores = ['scatter'] - transfer_tally = Tally(tally_id=8) + transfer_tally = Tally() transfer_tally.filters = [energy_filter, energyout_filter] transfer_tally.scores = ['scatter', 'nu-fission'] - material_tally = Tally(tally_id=9) + material_tally = Tally() material_tally.filters = [ MaterialFilter((model.geometry.get_materials_by_name('UOX fuel')[0], model.geometry.get_materials_by_name('Zircaloy')[0], @@ -73,56 +73,56 @@ def test_tallies(): mu_bins = (-1.0, -0.5, 0.0, 0.5, 1.0) mu_filter = MuFilter(mu_bins) - mu_tally1 = Tally(tally_id=10) + mu_tally1 = Tally() mu_tally1.filters = [mu_filter] mu_tally1.scores = ['scatter', 'nu-scatter'] print('mu_tally1', mu_tally1.id) - mu_tally2 = Tally(tally_id=11) + mu_tally2 = Tally() mu_tally2.filters = [mu_filter, mesh_filter] mu_tally2.scores = ['scatter', 'nu-scatter'] polar_bins = (0.0, 0.6283, 1.2566, 1.8850, 2.5132, 3.14159) polar_filter = PolarFilter(polar_bins) - polar_tally1 = Tally(tally_id=12) + polar_tally1 = Tally() polar_tally1.filters = [polar_filter] polar_tally1.scores = ['flux'] polar_tally1.estimator = 'tracklength' - polar_tally2 = Tally(tally_id=13) + polar_tally2 = Tally() polar_tally2.filters = [polar_filter] polar_tally2.scores = ['flux'] polar_tally2.estimator = 'analog' - polar_tally3 = Tally(tally_id=14) + polar_tally3 = Tally() polar_tally3.filters = [polar_filter, mesh_filter] polar_tally3.scores = ['flux'] polar_tally3.estimator = 'tracklength' legendre_filter = LegendreFilter(order=4) - legendre_tally = Tally(tally_id=15) + legendre_tally = Tally() legendre_tally.filters = [legendre_filter] legendre_tally.scores = ['scatter', 'nu-scatter'] legendre_tally.estimatir = 'analog' print('legendre_tally', mu_tally1.id) harmonics_filter = SphericalHarmonicsFilter(order=4) - harmonics_tally = Tally(tally_id=16) + harmonics_tally = Tally() harmonics_tally.filters = [harmonics_filter] harmonics_tally.scores = ['scatter', 'nu-scatter', 'flux', 'total'] harmonics_tally.estimatir = 'analog' - harmonics_tally2 = Tally(tally_id=17) + harmonics_tally2 = Tally() harmonics_tally2.filters = [harmonics_filter] harmonics_tally2.scores = ['flux', 'total'] harmonics_tally2.estimatir = 'collision' - harmonics_tally3 = Tally(tally_id=18) + harmonics_tally3 = Tally() harmonics_tally3.filters = [harmonics_filter] harmonics_tally3.scores = ['flux', 'total'] harmonics_tally3.estimatir = 'tracklength' - universe_tally = Tally(tally_id=19) + universe_tally = Tally() universe_tally.filters = [ UniverseFilter((model.geometry.get_all_universes()[1], model.geometry.get_all_universes()[2], @@ -132,8 +132,7 @@ def test_tallies(): cell_filter = CellFilter((model.geometry.get_all_cells()[10], model.geometry.get_all_cells()[21], 22, 23, 60)) # Test both Cell objects and ids - score_tallies = [Tally(tally_id=20), Tally(tally_id=21), - Tally(tally_id=22)] + score_tallies = [Tally(), Tally(), Tally()] for t in score_tallies: t.filters = [cell_filter] t.scores = ['absorption', 'delayed-nu-fission', 'events', 'fission', @@ -146,7 +145,7 @@ def test_tallies(): score_tallies[2].estimator = 'collision' cell_filter2 = CellFilter((21, 22, 23, 27, 28, 29, 60)) - flux_tallies = [Tally(tally_id=23 + i) for i in range(3)] + flux_tallies = [Tally() for i in range(3)] for t in flux_tallies: t.filters = [cell_filter2] t.scores = ['flux'] @@ -154,7 +153,7 @@ def test_tallies(): flux_tallies[1].estimator = 'analog' flux_tallies[2].estimator = 'collision' - total_tallies = [Tally(tally_id=26 + i) for i in range(3)] + total_tallies = [Tally() for i in range(3)] for t in total_tallies: t.filters = [cell_filter] t.scores = ['total'] @@ -163,7 +162,7 @@ def test_tallies(): total_tallies[1].estimator = 'analog' total_tallies[2].estimator = 'collision' - all_nuclide_tallies = [Tally(tally_id=29 + i) for i in range(4)] + all_nuclide_tallies = [Tally() for i in range(4)] for t in all_nuclide_tallies: t.filters = [cell_filter] t.estimator = 'tracklength' diff --git a/tests/unit_tests/test_data_neutron.py b/tests/unit_tests/test_data_neutron.py index 5713bfbc57..03746430d9 100644 --- a/tests/unit_tests/test_data_neutron.py +++ b/tests/unit_tests/test_data_neutron.py @@ -345,10 +345,10 @@ def test_nbody(tmpdir, h2): assert nbody1.q_value == nbody2.q_value -def test_ace_convert(tmpdir): +def test_ace_convert(run_in_tmpdir): filename = os.path.join(_ENDF_DATA, 'neutrons', 'n-001_H_001.endf') - ace_ascii = str(tmpdir.join('ace_ascii')) - ace_binary = str(tmpdir.join('ace_binary')) + ace_ascii = 'ace_ascii' + ace_binary = 'ace_binary' openmc.data.njoy.make_ace(filename, ace=ace_ascii) # Convert to binary From 2de47ec885a9a6946f90c19abc1343d0ef4c46f8 Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Tue, 1 May 2018 21:02:43 -0500 Subject: [PATCH 68/77] Fix calls to H5Screate_simple --- src/state_point.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/state_point.cpp b/src/state_point.cpp index 2ea9d1c43c..4e6b9a9f9f 100644 --- a/src/state_point.cpp +++ b/src/state_point.cpp @@ -39,13 +39,13 @@ write_source_bank(hid_t group_id, int64_t* work_index, Bank* source_bank) #ifdef PHDF5 // Set size of total dataspace for all procs and rank hsize_t dims[] {static_cast(n_particles)}; - hid_t dspace = H5Screate_simple(1, dims, H5P_DEFAULT); + hid_t dspace = H5Screate_simple(1, dims, nullptr); hid_t dset = H5Dcreate(group_id, "source_bank", banktype, dspace, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT); // Create another data space but for each proc individually hsize_t count[] {static_cast(openmc_work)}; - hid_t memspace = H5Screate_simple(1, count, H5P_DEFAULT); + hid_t memspace = H5Screate_simple(1, count, nullptr); // Select hyperslab for this dataspace hsize_t start[] {static_cast(work_index[openmc::mpi::rank])}; @@ -69,7 +69,7 @@ write_source_bank(hid_t group_id, int64_t* work_index, Bank* source_bank) if (openmc_master) { // Create dataset big enough to hold all source sites hsize_t dims[] {static_cast(n_particles)}; - hid_t dspace = H5Screate_simple(1, dims, H5P_DEFAULT); + hid_t dspace = H5Screate_simple(1, dims, nullptr); hid_t dset = H5Dcreate(group_id, "source_bank", banktype, dspace, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT); @@ -81,7 +81,7 @@ write_source_bank(hid_t group_id, int64_t* work_index, Bank* source_bank) for (int i = 0; i < openmc::mpi::n_procs; ++i) { // Create memory space hsize_t count[] {static_cast(work_index[i+1] - work_index[i])}; - hid_t memspace = H5Screate_simple(1, count, H5P_DEFAULT); + hid_t memspace = H5Screate_simple(1, count, nullptr); #ifdef OPENMC_MPI // Receive source sites from other processes @@ -130,7 +130,7 @@ void read_source_bank(hid_t group_id, int64_t* work_index, Bank* source_bank) // Create another data space but for each proc individually hsize_t dims[] {static_cast(openmc_work)}; - hid_t memspace = H5Screate_simple(1, dims, H5P_DEFAULT); + hid_t memspace = H5Screate_simple(1, dims, nullptr); // Make sure source bank is big enough hid_t dspace = H5Dget_space(dset); From 9d5275ca263117656290070647aa1b01eb73a297 Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Tue, 1 May 2018 22:22:18 -0500 Subject: [PATCH 69/77] Support passing command-line arguments in openmc.capi.init() --- openmc/capi/core.py | 24 +++++++++++++++++++----- 1 file changed, 19 insertions(+), 5 deletions(-) diff --git a/openmc/capi/core.py b/openmc/capi/core.py index 273f0c0c7f..ad78f06c3d 100644 --- a/openmc/capi/core.py +++ b/openmc/capi/core.py @@ -1,6 +1,6 @@ from contextlib import contextmanager -from ctypes import (CDLL, c_int, c_int32, c_int64, c_double, c_char_p, - POINTER, Structure, c_void_p) +from ctypes import (CDLL, c_int, c_int32, c_int64, c_double, c_char_p, c_char, + POINTER, Structure, c_void_p, create_string_buffer) from warnings import warn import numpy as np @@ -30,7 +30,7 @@ _dll.openmc_find.restype = c_int _dll.openmc_find.errcheck = _error_handler _dll.openmc_hard_reset.restype = c_int _dll.openmc_hard_reset.errcheck = _error_handler -_dll.openmc_init.argtypes = [c_int, POINTER(c_char_p), c_void_p] +_dll.openmc_init.argtypes = [c_int, POINTER(POINTER(c_char)), c_void_p] _dll.openmc_init.restype = c_int _dll.openmc_init.errcheck = _error_handler _dll.openmc_get_keff.argtypes = [POINTER(c_double*2)] @@ -115,15 +115,29 @@ def hard_reset(): _dll.openmc_hard_reset() -def init(intracomm=None): +def init(args=None, intracomm=None): """Initialize OpenMC Parameters ---------- + args : list of str + Command-line arguments intracomm : mpi4py.MPI.Intracomm or None MPI intracommunicator """ + if args is not None: + args = ['openmc'] + list(args) + argc = len(args) + + # Create the argv array. Note that it is actually expected to be of + # length argc + 1 with the final item being a null pointer. + argv = (POINTER(c_char) * (argc + 1))() + for i, arg in enumerate(args): + argv[i] = create_string_buffer(arg.encode()) + else: + argc = 0 + if intracomm is not None: # If an mpi4py communicator was passed, convert it to void* to be passed # to openmc_init @@ -135,7 +149,7 @@ def init(intracomm=None): address = MPI._addressof(intracomm) intracomm = c_void_p(address) - _dll.openmc_init(0, None, intracomm) + _dll.openmc_init(argc, argv, intracomm) def iter_batches(): From 6b1c0f907f991e84b497122448f342392f60b1b0 Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Wed, 2 May 2018 06:21:09 -0500 Subject: [PATCH 70/77] Fix openmc.capi.init() --- openmc/capi/core.py | 1 + openmc/deplete/operator.py | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/openmc/capi/core.py b/openmc/capi/core.py index ad78f06c3d..e044f95041 100644 --- a/openmc/capi/core.py +++ b/openmc/capi/core.py @@ -137,6 +137,7 @@ def init(args=None, intracomm=None): argv[i] = create_string_buffer(arg.encode()) else: argc = 0 + argv = None if intracomm is not None: # If an mpi4py communicator was passed, convert it to void* to be passed diff --git a/openmc/deplete/operator.py b/openmc/deplete/operator.py index a1d8ffb0b0..b40ff63447 100644 --- a/openmc/deplete/operator.py +++ b/openmc/deplete/operator.py @@ -268,7 +268,7 @@ class Operator(TransportOperator): # Initialize OpenMC library comm.barrier() - openmc.capi.init(comm) + openmc.capi.init(intracomm=comm) # Generate tallies in memory self._generate_tallies() From 3ab959cc3e9b9c9a3f90b6a96117fb1b032263a3 Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Wed, 2 May 2018 15:23:48 -0500 Subject: [PATCH 71/77] Fix bug when no outer lattice universe is defined --- src/geometry.F90 | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/geometry.F90 b/src/geometry.F90 index 0bacd7b5d1..e747b619ac 100644 --- a/src/geometry.F90 +++ b/src/geometry.F90 @@ -355,9 +355,10 @@ contains else ! Particle is outside the lattice. if (lat % outer == NO_OUTER_UNIVERSE) then - call p % mark_as_lost("Particle " // trim(to_str(p %id)) & + call warning("Particle " // trim(to_str(p %id)) & // " is outside lattice " // trim(to_str(lat % id)) & // " but the lattice has no defined outer universe.") + found = .false. return else p % coord(j + 1) % universe = lat % outer From 968c12deb515cecdf29aa0fa1de40d6f65dd4a06 Mon Sep 17 00:00:00 2001 From: Adam G Nelson Date: Sat, 5 May 2018 09:24:21 -0400 Subject: [PATCH 72/77] Fixed consistent scatter matrix filter ordering so tests come out consistently and added a mgxs_library_correction and mgxs_library_histogram test --- openmc/mgxs/mgxs.py | 10 + .../mgxs_library_correction/__init__.py | 0 .../mgxs_library_correction/inputs_true.dat | 392 +++++++++++++ .../mgxs_library_correction/results_true.dat | 60 ++ .../mgxs_library_correction/test.py | 63 ++ .../mgxs_library_histogram/__init__.py | 0 .../mgxs_library_histogram/inputs_true.dat | 287 ++++++++++ .../mgxs_library_histogram/results_true.dat | 540 ++++++++++++++++++ .../mgxs_library_histogram/test.py | 64 +++ 9 files changed, 1416 insertions(+) create mode 100644 tests/regression_tests/mgxs_library_correction/__init__.py create mode 100644 tests/regression_tests/mgxs_library_correction/inputs_true.dat create mode 100644 tests/regression_tests/mgxs_library_correction/results_true.dat create mode 100644 tests/regression_tests/mgxs_library_correction/test.py create mode 100644 tests/regression_tests/mgxs_library_histogram/__init__.py create mode 100644 tests/regression_tests/mgxs_library_histogram/inputs_true.dat create mode 100644 tests/regression_tests/mgxs_library_histogram/results_true.dat create mode 100644 tests/regression_tests/mgxs_library_histogram/test.py diff --git a/openmc/mgxs/mgxs.py b/openmc/mgxs/mgxs.py index 5bc00cbc95..1d8ace2824 100644 --- a/openmc/mgxs/mgxs.py +++ b/openmc/mgxs/mgxs.py @@ -4003,6 +4003,15 @@ class ScatterMatrixXS(MatrixMGXS): correction.nuclides = scatter_p1.nuclides self._xs_tally -= correction + # If the mu filter is before the group out filter swap them + if self.scatter_format == 'histogram': + tally = self._xs_tally + filt = tally.filters + eout_filter = tally.find_filter(openmc.EnergyoutFilter) + angle_filter = tally.find_filter(openmc.MuFilter) + if filt.index(eout_filter) > filt.index(angle_filter): + tally._swap_filters(eout_filter, angle_filter) + self._compute_xs() return self._xs_tally @@ -4466,6 +4475,7 @@ class ScatterMatrixXS(MatrixMGXS): """ + print(self.xs_tally.filters) df = super().get_pandas_dataframe(groups, nuclides, xs_type, paths) if self.scatter_format == 'legendre': diff --git a/tests/regression_tests/mgxs_library_correction/__init__.py b/tests/regression_tests/mgxs_library_correction/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/tests/regression_tests/mgxs_library_correction/inputs_true.dat b/tests/regression_tests/mgxs_library_correction/inputs_true.dat new file mode 100644 index 0000000000..d9793bc3ea --- /dev/null +++ b/tests/regression_tests/mgxs_library_correction/inputs_true.dat @@ -0,0 +1,392 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + eigenvalue + 100 + 10 + 5 + + + -0.63 -0.63 -1 0.63 0.63 1 + + + + + + + 1 + + + 0.0 0.625 20000000.0 + + + 0.0 0.625 20000000.0 + + + 2 + + + 3 + + + 1 2 + total + flux + analog + + + 1 2 3 + total + scatter-0 + analog + + + 1 3 + total + scatter-1 + analog + + + 1 2 + total + flux + analog + + + 1 2 3 + total + nu-scatter-0 + analog + + + 1 3 + total + nu-scatter-1 + analog + + + 1 2 + total + flux + tracklength + + + 1 2 + total + scatter + tracklength + + + 1 2 3 + total + scatter-0 + analog + + + 1 3 + total + scatter-1 + analog + + + 1 2 + total + flux + analog + + + 1 2 + total + flux + tracklength + + + 1 2 + total + scatter + tracklength + + + 1 2 3 + total + scatter-0 + analog + + + 1 2 3 + total + nu-scatter-0 + analog + + + 1 2 3 + total + scatter-0 + analog + + + 1 3 + total + nu-scatter-1 + analog + + + 1 2 + total + flux + analog + + + 13 2 + total + flux + analog + + + 13 2 3 + total + scatter-0 + analog + + + 13 3 + total + scatter-1 + analog + + + 13 2 + total + flux + analog + + + 13 2 3 + total + nu-scatter-0 + analog + + + 13 3 + total + nu-scatter-1 + analog + + + 13 2 + total + flux + tracklength + + + 13 2 + total + scatter + tracklength + + + 13 2 3 + total + scatter-0 + analog + + + 13 3 + total + scatter-1 + analog + + + 13 2 + total + flux + analog + + + 13 2 + total + flux + tracklength + + + 13 2 + total + scatter + tracklength + + + 13 2 3 + total + scatter-0 + analog + + + 13 2 3 + total + nu-scatter-0 + analog + + + 13 2 3 + total + scatter-0 + analog + + + 13 3 + total + nu-scatter-1 + analog + + + 13 2 + total + flux + analog + + + 25 2 + total + flux + analog + + + 25 2 3 + total + scatter-0 + analog + + + 25 3 + total + scatter-1 + analog + + + 25 2 + total + flux + analog + + + 25 2 3 + total + nu-scatter-0 + analog + + + 25 3 + total + nu-scatter-1 + analog + + + 25 2 + total + flux + tracklength + + + 25 2 + total + scatter + tracklength + + + 25 2 3 + total + scatter-0 + analog + + + 25 3 + total + scatter-1 + analog + + + 25 2 + total + flux + analog + + + 25 2 + total + flux + tracklength + + + 25 2 + total + scatter + tracklength + + + 25 2 3 + total + scatter-0 + analog + + + 25 2 3 + total + nu-scatter-0 + analog + + + 25 2 3 + total + scatter-0 + analog + + + 25 3 + total + nu-scatter-1 + analog + + + 25 2 + total + flux + analog + + diff --git a/tests/regression_tests/mgxs_library_correction/results_true.dat b/tests/regression_tests/mgxs_library_correction/results_true.dat new file mode 100644 index 0000000000..f7e288802c --- /dev/null +++ b/tests/regression_tests/mgxs_library_correction/results_true.dat @@ -0,0 +1,60 @@ + material group in group out nuclide mean std. dev. +3 1 1 1 total 0.332466 0.026533 +2 1 1 2 total 0.000989 0.000482 +1 1 2 1 total 0.000925 0.000925 +0 1 2 2 total 0.396146 0.015511 + material group in group out nuclide mean std. dev. +3 1 1 1 total 0.332466 0.026533 +2 1 1 2 total 0.000989 0.000482 +1 1 2 1 total 0.000925 0.000925 +0 1 2 2 total 0.396146 0.015511 + material group in group out nuclide mean std. dev. +3 1 1 1 total 0.334690 0.037288 +2 1 1 2 total 0.000995 0.000489 +1 1 2 1 total 0.000887 0.000889 +0 1 2 2 total 0.379453 0.030118 + material group in group out nuclide mean std. dev. +3 1 1 1 total 0.334690 0.048073 +2 1 1 2 total 0.000995 0.000841 +1 1 2 1 total 0.000887 0.001538 +0 1 2 2 total 0.379453 0.034216 + material group in group out nuclide mean std. dev. +3 2 1 1 total 0.271891 0.032748 +2 2 1 2 total 0.000000 0.000000 +1 2 2 1 total 0.000000 0.000000 +0 2 2 2 total 0.307478 0.047512 + material group in group out nuclide mean std. dev. +3 2 1 1 total 0.271891 0.032748 +2 2 1 2 total 0.000000 0.000000 +1 2 2 1 total 0.000000 0.000000 +0 2 2 2 total 0.307478 0.047512 + material group in group out nuclide mean std. dev. +3 2 1 1 total 0.273933 0.038207 +2 2 1 2 total 0.000000 0.000000 +1 2 2 1 total 0.000000 0.000000 +0 2 2 2 total 0.306635 0.052777 + material group in group out nuclide mean std. dev. +3 2 1 1 total 0.273933 0.051116 +2 2 1 2 total 0.000000 0.000000 +1 2 2 1 total 0.000000 0.000000 +0 2 2 2 total 0.306635 0.067497 + material group in group out nuclide mean std. dev. +3 3 1 1 total 0.258652 0.022623 +2 3 1 2 total 0.031368 0.001728 +1 3 2 1 total 0.000443 0.000445 +0 3 2 2 total 1.482300 0.232653 + material group in group out nuclide mean std. dev. +3 3 1 1 total 0.258652 0.022623 +2 3 1 2 total 0.031368 0.001728 +1 3 2 1 total 0.000443 0.000445 +0 3 2 2 total 1.482300 0.232653 + material group in group out nuclide mean std. dev. +3 3 1 1 total 0.251610 0.041472 +2 3 1 2 total 0.031023 0.002232 +1 3 2 1 total 0.000440 0.000445 +0 3 2 2 total 1.467612 0.356408 + material group in group out nuclide mean std. dev. +3 3 1 1 total 0.251610 0.048135 +2 3 1 2 total 0.031023 0.003064 +1 3 2 1 total 0.000440 0.000765 +0 3 2 2 total 1.467612 0.449931 diff --git a/tests/regression_tests/mgxs_library_correction/test.py b/tests/regression_tests/mgxs_library_correction/test.py new file mode 100644 index 0000000000..05eedfef82 --- /dev/null +++ b/tests/regression_tests/mgxs_library_correction/test.py @@ -0,0 +1,63 @@ +import hashlib + +import openmc +import openmc.mgxs +from openmc.examples import pwr_pin_cell + +from tests.testing_harness import PyAPITestHarness + + +class MGXSTestHarness(PyAPITestHarness): + def __init__(self, *args, **kwargs): + # Generate inputs using parent class routine + super().__init__(*args, **kwargs) + + # Initialize a two-group structure + energy_groups = openmc.mgxs.EnergyGroups(group_edges=[0, 0.625, 20.e6]) + + # Initialize MGXS Library for a few cross section types + self.mgxs_lib = openmc.mgxs.Library(self._model.geometry) + self.mgxs_lib.by_nuclide = False + + # Test all MGXS types + self.mgxs_lib.mgxs_types = ['scatter matrix', 'nu-scatter matrix', + 'consistent scatter matrix', + 'consistent nu-scatter matrix'] + self.mgxs_lib.energy_groups = energy_groups + self.mgxs_lib.correction = 'P0' + self.mgxs_lib.domain_type = 'material' + self.mgxs_lib.build_library() + + # Add tallies + self.mgxs_lib.add_to_tallies_file(self._model.tallies, merge=False) + + def _get_results(self, hash_output=False): + """Digest info in the statepoint and return as a string.""" + + # Read the statepoint file. + sp = openmc.StatePoint(self._sp_name) + + # Load the MGXS library from the statepoint + self.mgxs_lib.load_from_statepoint(sp) + + # Build a string from Pandas Dataframe for each MGXS + outstr = '' + for domain in self.mgxs_lib.domains: + for mgxs_type in self.mgxs_lib.mgxs_types: + mgxs = self.mgxs_lib.get_mgxs(domain, mgxs_type) + df = mgxs.get_pandas_dataframe() + outstr += df.to_string() + '\n' + + # Hash the results if necessary + if hash_output: + sha512 = hashlib.sha512() + sha512.update(outstr.encode('utf-8')) + outstr = sha512.hexdigest() + + return outstr + + +def test_mgxs_library_correction(): + model = pwr_pin_cell() + harness = MGXSTestHarness('statepoint.10.h5', model) + harness.main() diff --git a/tests/regression_tests/mgxs_library_histogram/__init__.py b/tests/regression_tests/mgxs_library_histogram/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/tests/regression_tests/mgxs_library_histogram/inputs_true.dat b/tests/regression_tests/mgxs_library_histogram/inputs_true.dat new file mode 100644 index 0000000000..29c46c9374 --- /dev/null +++ b/tests/regression_tests/mgxs_library_histogram/inputs_true.dat @@ -0,0 +1,287 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + eigenvalue + 100 + 10 + 5 + + + -0.63 -0.63 -1 0.63 0.63 1 + + + + + + + 1 + + + 0.0 0.625 20000000.0 + + + 0.0 0.625 20000000.0 + + + -1.0 -0.818181818182 -0.636363636364 -0.454545454545 -0.272727272727 -0.0909090909091 0.0909090909091 0.272727272727 0.454545454545 0.636363636364 0.818181818182 1.0 + + + 2 + + + 3 + + + 1 2 + total + flux + analog + + + 1 2 3 4 + total + scatter + analog + + + 1 2 + total + flux + analog + + + 1 2 3 4 + total + nu-scatter + analog + + + 1 2 + total + flux + tracklength + + + 1 2 + total + scatter + tracklength + + + 1 2 3 4 + total + scatter-0 + analog + + + 1 2 + total + flux + tracklength + + + 1 2 + total + scatter + tracklength + + + 1 2 3 4 + total + scatter-0 + analog + + + 1 2 3 + total + nu-scatter-0 + analog + + + 1 2 3 + total + scatter-0 + analog + + + 17 2 + total + flux + analog + + + 17 2 3 4 + total + scatter + analog + + + 17 2 + total + flux + analog + + + 17 2 3 4 + total + nu-scatter + analog + + + 17 2 + total + flux + tracklength + + + 17 2 + total + scatter + tracklength + + + 17 2 3 4 + total + scatter-0 + analog + + + 17 2 + total + flux + tracklength + + + 17 2 + total + scatter + tracklength + + + 17 2 3 4 + total + scatter-0 + analog + + + 17 2 3 + total + nu-scatter-0 + analog + + + 17 2 3 + total + scatter-0 + analog + + + 33 2 + total + flux + analog + + + 33 2 3 4 + total + scatter + analog + + + 33 2 + total + flux + analog + + + 33 2 3 4 + total + nu-scatter + analog + + + 33 2 + total + flux + tracklength + + + 33 2 + total + scatter + tracklength + + + 33 2 3 4 + total + scatter-0 + analog + + + 33 2 + total + flux + tracklength + + + 33 2 + total + scatter + tracklength + + + 33 2 3 4 + total + scatter-0 + analog + + + 33 2 3 + total + nu-scatter-0 + analog + + + 33 2 3 + total + scatter-0 + analog + + diff --git a/tests/regression_tests/mgxs_library_histogram/results_true.dat b/tests/regression_tests/mgxs_library_histogram/results_true.dat new file mode 100644 index 0000000000..116a1a9835 --- /dev/null +++ b/tests/regression_tests/mgxs_library_histogram/results_true.dat @@ -0,0 +1,540 @@ + material group in group out mu bin nuclide mean std. dev. +33 1 1 1 1 total 0.025383 0.001933 +34 1 1 1 2 total 0.027855 0.001701 +35 1 1 1 3 total 0.031646 0.002913 +36 1 1 1 4 total 0.028185 0.001430 +37 1 1 1 5 total 0.030162 0.002739 +38 1 1 1 6 total 0.029009 0.002713 +39 1 1 1 7 total 0.030492 0.002907 +40 1 1 1 8 total 0.035272 0.003860 +41 1 1 1 9 total 0.043678 0.006074 +42 1 1 1 10 total 0.044502 0.003030 +43 1 1 1 11 total 0.058017 0.004319 +22 1 1 2 1 total 0.000000 0.000000 +23 1 1 2 2 total 0.000165 0.000165 +24 1 1 2 3 total 0.000330 0.000202 +25 1 1 2 4 total 0.000165 0.000165 +26 1 1 2 5 total 0.000000 0.000000 +27 1 1 2 6 total 0.000165 0.000165 +28 1 1 2 7 total 0.000000 0.000000 +29 1 1 2 8 total 0.000000 0.000000 +30 1 1 2 9 total 0.000000 0.000000 +31 1 1 2 10 total 0.000165 0.000165 +32 1 1 2 11 total 0.000000 0.000000 +11 1 2 1 1 total 0.000925 0.000925 +12 1 2 1 2 total 0.000000 0.000000 +13 1 2 1 3 total 0.000000 0.000000 +14 1 2 1 4 total 0.000000 0.000000 +15 1 2 1 5 total 0.000000 0.000000 +16 1 2 1 6 total 0.000000 0.000000 +17 1 2 1 7 total 0.000000 0.000000 +18 1 2 1 8 total 0.000000 0.000000 +19 1 2 1 9 total 0.000000 0.000000 +20 1 2 1 10 total 0.000000 0.000000 +21 1 2 1 11 total 0.000000 0.000000 +0 1 2 2 1 total 0.037910 0.006498 +1 1 2 2 2 total 0.031438 0.002377 +2 1 2 2 3 total 0.036986 0.006429 +3 1 2 2 4 total 0.029588 0.005627 +4 1 2 2 5 total 0.036986 0.007359 +5 1 2 2 6 total 0.035136 0.004110 +6 1 2 2 7 total 0.037910 0.003188 +7 1 2 2 8 total 0.041609 0.004489 +8 1 2 2 9 total 0.040684 0.007710 +9 1 2 2 10 total 0.043458 0.004638 +10 1 2 2 11 total 0.039760 0.002920 + material group in group out mu bin nuclide mean std. dev. +33 1 1 1 1 total 0.025383 0.001933 +34 1 1 1 2 total 0.027855 0.001701 +35 1 1 1 3 total 0.031646 0.002913 +36 1 1 1 4 total 0.028185 0.001430 +37 1 1 1 5 total 0.030162 0.002739 +38 1 1 1 6 total 0.029009 0.002713 +39 1 1 1 7 total 0.030492 0.002907 +40 1 1 1 8 total 0.035272 0.003860 +41 1 1 1 9 total 0.043678 0.006074 +42 1 1 1 10 total 0.044502 0.003030 +43 1 1 1 11 total 0.058017 0.004319 +22 1 1 2 1 total 0.000000 0.000000 +23 1 1 2 2 total 0.000165 0.000165 +24 1 1 2 3 total 0.000330 0.000202 +25 1 1 2 4 total 0.000165 0.000165 +26 1 1 2 5 total 0.000000 0.000000 +27 1 1 2 6 total 0.000165 0.000165 +28 1 1 2 7 total 0.000000 0.000000 +29 1 1 2 8 total 0.000000 0.000000 +30 1 1 2 9 total 0.000000 0.000000 +31 1 1 2 10 total 0.000165 0.000165 +32 1 1 2 11 total 0.000000 0.000000 +11 1 2 1 1 total 0.000925 0.000925 +12 1 2 1 2 total 0.000000 0.000000 +13 1 2 1 3 total 0.000000 0.000000 +14 1 2 1 4 total 0.000000 0.000000 +15 1 2 1 5 total 0.000000 0.000000 +16 1 2 1 6 total 0.000000 0.000000 +17 1 2 1 7 total 0.000000 0.000000 +18 1 2 1 8 total 0.000000 0.000000 +19 1 2 1 9 total 0.000000 0.000000 +20 1 2 1 10 total 0.000000 0.000000 +21 1 2 1 11 total 0.000000 0.000000 +0 1 2 2 1 total 0.037910 0.006498 +1 1 2 2 2 total 0.031438 0.002377 +2 1 2 2 3 total 0.036986 0.006429 +3 1 2 2 4 total 0.029588 0.005627 +4 1 2 2 5 total 0.036986 0.007359 +5 1 2 2 6 total 0.035136 0.004110 +6 1 2 2 7 total 0.037910 0.003188 +7 1 2 2 8 total 0.041609 0.004489 +8 1 2 2 9 total 0.040684 0.007710 +9 1 2 2 10 total 0.043458 0.004638 +10 1 2 2 11 total 0.039760 0.002920 + material group in group out mu bin nuclide mean std. dev. +33 1 1 1 1 total 0.025529 0.002197 +34 1 1 1 2 total 0.028016 0.002047 +35 1 1 1 3 total 0.031829 0.003196 +36 1 1 1 4 total 0.028348 0.001833 +37 1 1 1 5 total 0.030337 0.003012 +38 1 1 1 6 total 0.029177 0.002969 +39 1 1 1 7 total 0.030668 0.003172 +40 1 1 1 8 total 0.035476 0.004135 +41 1 1 1 9 total 0.043931 0.006358 +42 1 1 1 10 total 0.044759 0.003536 +43 1 1 1 11 total 0.058353 0.004934 +22 1 1 2 1 total 0.000000 0.000000 +23 1 1 2 2 total 0.000166 0.000166 +24 1 1 2 3 total 0.000332 0.000204 +25 1 1 2 4 total 0.000166 0.000166 +26 1 1 2 5 total 0.000000 0.000000 +27 1 1 2 6 total 0.000166 0.000166 +28 1 1 2 7 total 0.000000 0.000000 +29 1 1 2 8 total 0.000000 0.000000 +30 1 1 2 9 total 0.000000 0.000000 +31 1 1 2 10 total 0.000166 0.000166 +32 1 1 2 11 total 0.000000 0.000000 +11 1 2 1 1 total 0.000887 0.000890 +12 1 2 1 2 total 0.000000 0.000000 +13 1 2 1 3 total 0.000000 0.000000 +14 1 2 1 4 total 0.000000 0.000000 +15 1 2 1 5 total 0.000000 0.000000 +16 1 2 1 6 total 0.000000 0.000000 +17 1 2 1 7 total 0.000000 0.000000 +18 1 2 1 8 total 0.000000 0.000000 +19 1 2 1 9 total 0.000000 0.000000 +20 1 2 1 10 total 0.000000 0.000000 +21 1 2 1 11 total 0.000000 0.000000 +0 1 2 2 1 total 0.036372 0.006773 +1 1 2 2 2 total 0.030162 0.003165 +2 1 2 2 3 total 0.035485 0.006687 +3 1 2 2 4 total 0.028388 0.005781 +4 1 2 2 5 total 0.035485 0.007518 +5 1 2 2 6 total 0.033711 0.004644 +6 1 2 2 7 total 0.036372 0.004045 +7 1 2 2 8 total 0.039921 0.005195 +8 1 2 2 9 total 0.039034 0.007923 +9 1 2 2 10 total 0.041695 0.005386 +10 1 2 2 11 total 0.038147 0.003944 + material group in group out mu bin nuclide mean std. dev. +33 1 1 1 1 total 0.025529 0.002974 +34 1 1 1 2 total 0.028016 0.003005 +35 1 1 1 3 total 0.031829 0.004057 +36 1 1 1 4 total 0.028348 0.002884 +37 1 1 1 5 total 0.030337 0.003840 +38 1 1 1 6 total 0.029177 0.003750 +39 1 1 1 7 total 0.030668 0.003982 +40 1 1 1 8 total 0.035476 0.004986 +41 1 1 1 9 total 0.043931 0.007233 +42 1 1 1 10 total 0.044759 0.004986 +43 1 1 1 11 total 0.058353 0.006733 +22 1 1 2 1 total 0.000000 0.000000 +23 1 1 2 2 total 0.000166 0.000201 +24 1 1 2 3 total 0.000332 0.000306 +25 1 1 2 4 total 0.000166 0.000201 +26 1 1 2 5 total 0.000000 0.000000 +27 1 1 2 6 total 0.000166 0.000201 +28 1 1 2 7 total 0.000000 0.000000 +29 1 1 2 8 total 0.000000 0.000000 +30 1 1 2 9 total 0.000000 0.000000 +31 1 1 2 10 total 0.000166 0.000201 +32 1 1 2 11 total 0.000000 0.000000 +11 1 2 1 1 total 0.000887 0.001538 +12 1 2 1 2 total 0.000000 0.000000 +13 1 2 1 3 total 0.000000 0.000000 +14 1 2 1 4 total 0.000000 0.000000 +15 1 2 1 5 total 0.000000 0.000000 +16 1 2 1 6 total 0.000000 0.000000 +17 1 2 1 7 total 0.000000 0.000000 +18 1 2 1 8 total 0.000000 0.000000 +19 1 2 1 9 total 0.000000 0.000000 +20 1 2 1 10 total 0.000000 0.000000 +21 1 2 1 11 total 0.000000 0.000000 +0 1 2 2 1 total 0.036372 0.006936 +1 1 2 2 2 total 0.030162 0.003400 +2 1 2 2 3 total 0.035485 0.006844 +3 1 2 2 4 total 0.028388 0.005898 +4 1 2 2 5 total 0.035485 0.007658 +5 1 2 2 6 total 0.033711 0.004847 +6 1 2 2 7 total 0.036372 0.004312 +7 1 2 2 8 total 0.039921 0.005448 +8 1 2 2 9 total 0.039034 0.008084 +9 1 2 2 10 total 0.041695 0.005652 +10 1 2 2 11 total 0.038147 0.004245 + material group in group out mu bin nuclide mean std. dev. +33 2 1 1 1 total 0.026289 0.004089 +34 2 1 1 2 total 0.018269 0.002939 +35 2 1 1 3 total 0.025398 0.002153 +36 2 1 1 4 total 0.024061 0.005097 +37 2 1 1 5 total 0.022279 0.003375 +38 2 1 1 6 total 0.027626 0.004817 +39 2 1 1 7 total 0.025843 0.003039 +40 2 1 1 8 total 0.026735 0.006742 +41 2 1 1 9 total 0.027626 0.005213 +42 2 1 1 10 total 0.036537 0.005920 +43 2 1 1 11 total 0.049459 0.004153 +22 2 1 2 1 total 0.000000 0.000000 +23 2 1 2 2 total 0.000000 0.000000 +24 2 1 2 3 total 0.000000 0.000000 +25 2 1 2 4 total 0.000000 0.000000 +26 2 1 2 5 total 0.000000 0.000000 +27 2 1 2 6 total 0.000000 0.000000 +28 2 1 2 7 total 0.000000 0.000000 +29 2 1 2 8 total 0.000000 0.000000 +30 2 1 2 9 total 0.000000 0.000000 +31 2 1 2 10 total 0.000000 0.000000 +32 2 1 2 11 total 0.000000 0.000000 +11 2 2 1 1 total 0.000000 0.000000 +12 2 2 1 2 total 0.000000 0.000000 +13 2 2 1 3 total 0.000000 0.000000 +14 2 2 1 4 total 0.000000 0.000000 +15 2 2 1 5 total 0.000000 0.000000 +16 2 2 1 6 total 0.000000 0.000000 +17 2 2 1 7 total 0.000000 0.000000 +18 2 2 1 8 total 0.000000 0.000000 +19 2 2 1 9 total 0.000000 0.000000 +20 2 2 1 10 total 0.000000 0.000000 +21 2 2 1 11 total 0.000000 0.000000 +0 2 2 2 1 total 0.024485 0.007210 +1 2 2 2 2 total 0.036727 0.005548 +2 2 2 2 3 total 0.041624 0.010918 +3 2 2 2 4 total 0.019588 0.008569 +4 2 2 2 5 total 0.022036 0.007526 +5 2 2 2 6 total 0.019588 0.011549 +6 2 2 2 7 total 0.022036 0.006454 +7 2 2 2 8 total 0.036727 0.010282 +8 2 2 2 9 total 0.022036 0.005164 +9 2 2 2 10 total 0.031830 0.011864 +10 2 2 2 11 total 0.019588 0.005336 + material group in group out mu bin nuclide mean std. dev. +33 2 1 1 1 total 0.026289 0.004089 +34 2 1 1 2 total 0.018269 0.002939 +35 2 1 1 3 total 0.025398 0.002153 +36 2 1 1 4 total 0.024061 0.005097 +37 2 1 1 5 total 0.022279 0.003375 +38 2 1 1 6 total 0.027626 0.004817 +39 2 1 1 7 total 0.025843 0.003039 +40 2 1 1 8 total 0.026735 0.006742 +41 2 1 1 9 total 0.027626 0.005213 +42 2 1 1 10 total 0.036537 0.005920 +43 2 1 1 11 total 0.049459 0.004153 +22 2 1 2 1 total 0.000000 0.000000 +23 2 1 2 2 total 0.000000 0.000000 +24 2 1 2 3 total 0.000000 0.000000 +25 2 1 2 4 total 0.000000 0.000000 +26 2 1 2 5 total 0.000000 0.000000 +27 2 1 2 6 total 0.000000 0.000000 +28 2 1 2 7 total 0.000000 0.000000 +29 2 1 2 8 total 0.000000 0.000000 +30 2 1 2 9 total 0.000000 0.000000 +31 2 1 2 10 total 0.000000 0.000000 +32 2 1 2 11 total 0.000000 0.000000 +11 2 2 1 1 total 0.000000 0.000000 +12 2 2 1 2 total 0.000000 0.000000 +13 2 2 1 3 total 0.000000 0.000000 +14 2 2 1 4 total 0.000000 0.000000 +15 2 2 1 5 total 0.000000 0.000000 +16 2 2 1 6 total 0.000000 0.000000 +17 2 2 1 7 total 0.000000 0.000000 +18 2 2 1 8 total 0.000000 0.000000 +19 2 2 1 9 total 0.000000 0.000000 +20 2 2 1 10 total 0.000000 0.000000 +21 2 2 1 11 total 0.000000 0.000000 +0 2 2 2 1 total 0.024485 0.007210 +1 2 2 2 2 total 0.036727 0.005548 +2 2 2 2 3 total 0.041624 0.010918 +3 2 2 2 4 total 0.019588 0.008569 +4 2 2 2 5 total 0.022036 0.007526 +5 2 2 2 6 total 0.019588 0.011549 +6 2 2 2 7 total 0.022036 0.006454 +7 2 2 2 8 total 0.036727 0.010282 +8 2 2 2 9 total 0.022036 0.005164 +9 2 2 2 10 total 0.031830 0.011864 +10 2 2 2 11 total 0.019588 0.005336 + material group in group out mu bin nuclide mean std. dev. +33 2 1 1 1 total 0.026462 0.003961 +34 2 1 1 2 total 0.018389 0.002854 +35 2 1 1 3 total 0.025565 0.001877 +36 2 1 1 4 total 0.024220 0.005027 +37 2 1 1 5 total 0.022425 0.003262 +38 2 1 1 6 total 0.027808 0.004704 +39 2 1 1 7 total 0.026014 0.002854 +40 2 1 1 8 total 0.026911 0.006690 +41 2 1 1 9 total 0.027808 0.005114 +42 2 1 1 10 total 0.036778 0.005752 +43 2 1 1 11 total 0.049785 0.003610 +22 2 1 2 1 total 0.000000 0.000000 +23 2 1 2 2 total 0.000000 0.000000 +24 2 1 2 3 total 0.000000 0.000000 +25 2 1 2 4 total 0.000000 0.000000 +26 2 1 2 5 total 0.000000 0.000000 +27 2 1 2 6 total 0.000000 0.000000 +28 2 1 2 7 total 0.000000 0.000000 +29 2 1 2 8 total 0.000000 0.000000 +30 2 1 2 9 total 0.000000 0.000000 +31 2 1 2 10 total 0.000000 0.000000 +32 2 1 2 11 total 0.000000 0.000000 +11 2 2 1 1 total 0.000000 0.000000 +12 2 2 1 2 total 0.000000 0.000000 +13 2 2 1 3 total 0.000000 0.000000 +14 2 2 1 4 total 0.000000 0.000000 +15 2 2 1 5 total 0.000000 0.000000 +16 2 2 1 6 total 0.000000 0.000000 +17 2 2 1 7 total 0.000000 0.000000 +18 2 2 1 8 total 0.000000 0.000000 +19 2 2 1 9 total 0.000000 0.000000 +20 2 2 1 10 total 0.000000 0.000000 +21 2 2 1 11 total 0.000000 0.000000 +0 2 2 2 1 total 0.024415 0.007393 +1 2 2 2 2 total 0.036622 0.006106 +2 2 2 2 3 total 0.041505 0.011274 +3 2 2 2 4 total 0.019532 0.008656 +4 2 2 2 5 total 0.021973 0.007663 +5 2 2 2 6 total 0.019532 0.011599 +6 2 2 2 7 total 0.021973 0.006620 +7 2 2 2 8 total 0.036622 0.010574 +8 2 2 2 9 total 0.021973 0.005378 +9 2 2 2 10 total 0.031739 0.012040 +10 2 2 2 11 total 0.019532 0.005496 + material group in group out mu bin nuclide mean std. dev. +33 2 1 1 1 total 0.026462 0.004896 +34 2 1 1 2 total 0.018389 0.003485 +35 2 1 1 3 total 0.025565 0.003355 +36 2 1 1 4 total 0.024220 0.005676 +37 2 1 1 5 total 0.022425 0.004073 +38 2 1 1 6 total 0.027808 0.005593 +39 2 1 1 7 total 0.026014 0.004019 +40 2 1 1 8 total 0.026911 0.007302 +41 2 1 1 9 total 0.027808 0.005941 +42 2 1 1 10 total 0.036778 0.007007 +43 2 1 1 11 total 0.049785 0.006508 +22 2 1 2 1 total 0.000000 0.000000 +23 2 1 2 2 total 0.000000 0.000000 +24 2 1 2 3 total 0.000000 0.000000 +25 2 1 2 4 total 0.000000 0.000000 +26 2 1 2 5 total 0.000000 0.000000 +27 2 1 2 6 total 0.000000 0.000000 +28 2 1 2 7 total 0.000000 0.000000 +29 2 1 2 8 total 0.000000 0.000000 +30 2 1 2 9 total 0.000000 0.000000 +31 2 1 2 10 total 0.000000 0.000000 +32 2 1 2 11 total 0.000000 0.000000 +11 2 2 1 1 total 0.000000 0.000000 +12 2 2 1 2 total 0.000000 0.000000 +13 2 2 1 3 total 0.000000 0.000000 +14 2 2 1 4 total 0.000000 0.000000 +15 2 2 1 5 total 0.000000 0.000000 +16 2 2 1 6 total 0.000000 0.000000 +17 2 2 1 7 total 0.000000 0.000000 +18 2 2 1 8 total 0.000000 0.000000 +19 2 2 1 9 total 0.000000 0.000000 +20 2 2 1 10 total 0.000000 0.000000 +21 2 2 1 11 total 0.000000 0.000000 +0 2 2 2 1 total 0.024415 0.008170 +1 2 2 2 2 total 0.036622 0.008031 +2 2 2 2 3 total 0.041505 0.012730 +3 2 2 2 4 total 0.019532 0.009092 +4 2 2 2 5 total 0.021973 0.008278 +5 2 2 2 6 total 0.019532 0.011928 +6 2 2 2 7 total 0.021973 0.007322 +7 2 2 2 8 total 0.036622 0.011790 +8 2 2 2 9 total 0.021973 0.006222 +9 2 2 2 10 total 0.031739 0.012861 +10 2 2 2 11 total 0.019532 0.006160 + material group in group out mu bin nuclide mean std. dev. +33 3 1 1 1 total 0.007001 0.000582 +34 3 1 1 2 total 0.007728 0.001008 +35 3 1 1 3 total 0.006819 0.001120 +36 3 1 1 4 total 0.006092 0.000787 +37 3 1 1 5 total 0.007183 0.000663 +38 3 1 1 6 total 0.011274 0.000704 +39 3 1 1 7 total 0.042642 0.002093 +40 3 1 1 8 total 0.074464 0.002664 +41 3 1 1 9 total 0.119015 0.006892 +42 3 1 1 10 total 0.153293 0.006049 +43 3 1 1 11 total 0.204390 0.010619 +22 3 1 2 1 total 0.000818 0.000302 +23 3 1 2 2 total 0.000818 0.000094 +24 3 1 2 3 total 0.001091 0.000234 +25 3 1 2 4 total 0.001091 0.000310 +26 3 1 2 5 total 0.002546 0.000607 +27 3 1 2 6 total 0.002364 0.000340 +28 3 1 2 7 total 0.004546 0.000835 +29 3 1 2 8 total 0.004819 0.000831 +30 3 1 2 9 total 0.006092 0.001113 +31 3 1 2 10 total 0.004546 0.000757 +32 3 1 2 11 total 0.002637 0.000371 +11 3 2 1 1 total 0.000000 0.000000 +12 3 2 1 2 total 0.000000 0.000000 +13 3 2 1 3 total 0.000000 0.000000 +14 3 2 1 4 total 0.000000 0.000000 +15 3 2 1 5 total 0.000000 0.000000 +16 3 2 1 6 total 0.000000 0.000000 +17 3 2 1 7 total 0.000000 0.000000 +18 3 2 1 8 total 0.000000 0.000000 +19 3 2 1 9 total 0.000000 0.000000 +20 3 2 1 10 total 0.000000 0.000000 +21 3 2 1 11 total 0.000443 0.000445 +0 3 2 2 1 total 0.088669 0.015373 +1 3 2 2 2 total 0.098422 0.016029 +2 3 2 2 3 total 0.126796 0.022922 +3 3 2 2 4 total 0.118373 0.018371 +4 3 2 2 5 total 0.131230 0.014538 +5 3 2 2 6 total 0.167584 0.027220 +6 3 2 2 7 total 0.180441 0.023605 +7 3 2 2 8 total 0.213691 0.028779 +8 3 2 2 9 total 0.236745 0.024777 +9 3 2 2 10 total 0.333394 0.041247 +10 3 2 2 11 total 0.339601 0.037814 + material group in group out mu bin nuclide mean std. dev. +33 3 1 1 1 total 0.007001 0.000582 +34 3 1 1 2 total 0.007728 0.001008 +35 3 1 1 3 total 0.006819 0.001120 +36 3 1 1 4 total 0.006092 0.000787 +37 3 1 1 5 total 0.007183 0.000663 +38 3 1 1 6 total 0.011274 0.000704 +39 3 1 1 7 total 0.042642 0.002093 +40 3 1 1 8 total 0.074464 0.002664 +41 3 1 1 9 total 0.119015 0.006892 +42 3 1 1 10 total 0.153293 0.006049 +43 3 1 1 11 total 0.204390 0.010619 +22 3 1 2 1 total 0.000818 0.000302 +23 3 1 2 2 total 0.000818 0.000094 +24 3 1 2 3 total 0.001091 0.000234 +25 3 1 2 4 total 0.001091 0.000310 +26 3 1 2 5 total 0.002546 0.000607 +27 3 1 2 6 total 0.002364 0.000340 +28 3 1 2 7 total 0.004546 0.000835 +29 3 1 2 8 total 0.004819 0.000831 +30 3 1 2 9 total 0.006092 0.001113 +31 3 1 2 10 total 0.004546 0.000757 +32 3 1 2 11 total 0.002637 0.000371 +11 3 2 1 1 total 0.000000 0.000000 +12 3 2 1 2 total 0.000000 0.000000 +13 3 2 1 3 total 0.000000 0.000000 +14 3 2 1 4 total 0.000000 0.000000 +15 3 2 1 5 total 0.000000 0.000000 +16 3 2 1 6 total 0.000000 0.000000 +17 3 2 1 7 total 0.000000 0.000000 +18 3 2 1 8 total 0.000000 0.000000 +19 3 2 1 9 total 0.000000 0.000000 +20 3 2 1 10 total 0.000000 0.000000 +21 3 2 1 11 total 0.000443 0.000445 +0 3 2 2 1 total 0.088669 0.015373 +1 3 2 2 2 total 0.098422 0.016029 +2 3 2 2 3 total 0.126796 0.022922 +3 3 2 2 4 total 0.118373 0.018371 +4 3 2 2 5 total 0.131230 0.014538 +5 3 2 2 6 total 0.167584 0.027220 +6 3 2 2 7 total 0.180441 0.023605 +7 3 2 2 8 total 0.213691 0.028779 +8 3 2 2 9 total 0.236745 0.024777 +9 3 2 2 10 total 0.333394 0.041247 +10 3 2 2 11 total 0.339601 0.037814 + material group in group out mu bin nuclide mean std. dev. +33 3 1 1 1 total 0.006924 0.000646 +34 3 1 1 2 total 0.007643 0.001048 +35 3 1 1 3 total 0.006744 0.001144 +36 3 1 1 4 total 0.006025 0.000819 +37 3 1 1 5 total 0.007104 0.000721 +38 3 1 1 6 total 0.011150 0.000841 +39 3 1 1 7 total 0.042173 0.002735 +40 3 1 1 8 total 0.073645 0.004084 +41 3 1 1 9 total 0.117706 0.008446 +42 3 1 1 10 total 0.151606 0.008778 +43 3 1 1 11 total 0.202141 0.013551 +22 3 1 2 1 total 0.000809 0.000301 +23 3 1 2 2 total 0.000809 0.000099 +24 3 1 2 3 total 0.001079 0.000236 +25 3 1 2 4 total 0.001079 0.000310 +26 3 1 2 5 total 0.002518 0.000610 +27 3 1 2 6 total 0.002338 0.000351 +28 3 1 2 7 total 0.004496 0.000848 +29 3 1 2 8 total 0.004766 0.000847 +30 3 1 2 9 total 0.006025 0.001130 +31 3 1 2 10 total 0.004496 0.000773 +32 3 1 2 11 total 0.002608 0.000383 +11 3 2 1 1 total 0.000000 0.000000 +12 3 2 1 2 total 0.000000 0.000000 +13 3 2 1 3 total 0.000000 0.000000 +14 3 2 1 4 total 0.000000 0.000000 +15 3 2 1 5 total 0.000000 0.000000 +16 3 2 1 6 total 0.000000 0.000000 +17 3 2 1 7 total 0.000000 0.000000 +18 3 2 1 8 total 0.000000 0.000000 +19 3 2 1 9 total 0.000000 0.000000 +20 3 2 1 10 total 0.000000 0.000000 +21 3 2 1 11 total 0.000440 0.000443 +0 3 2 2 1 total 0.088029 0.016753 +1 3 2 2 2 total 0.097712 0.017664 +2 3 2 2 3 total 0.125881 0.024808 +3 3 2 2 4 total 0.117518 0.020437 +4 3 2 2 5 total 0.130282 0.017687 +5 3 2 2 6 total 0.166374 0.030012 +6 3 2 2 7 total 0.179138 0.027327 +7 3 2 2 8 total 0.212149 0.033068 +8 3 2 2 9 total 0.235036 0.030744 +9 3 2 2 10 total 0.330988 0.048491 +10 3 2 2 11 total 0.337150 0.045927 + material group in group out mu bin nuclide mean std. dev. +33 3 1 1 1 total 0.006924 0.000699 +34 3 1 1 2 total 0.007643 0.001089 +35 3 1 1 3 total 0.006744 0.001173 +36 3 1 1 4 total 0.006025 0.000851 +37 3 1 1 5 total 0.007104 0.000772 +38 3 1 1 6 total 0.011150 0.000945 +39 3 1 1 7 total 0.042173 0.003183 +40 3 1 1 8 total 0.073645 0.004976 +41 3 1 1 9 total 0.117706 0.009591 +42 3 1 1 10 total 0.151606 0.010550 +43 3 1 1 11 total 0.202141 0.015638 +22 3 1 2 1 total 0.000809 0.000306 +23 3 1 2 2 total 0.000809 0.000113 +24 3 1 2 3 total 0.001079 0.000247 +25 3 1 2 4 total 0.001079 0.000318 +26 3 1 2 5 total 0.002518 0.000633 +27 3 1 2 6 total 0.002338 0.000385 +28 3 1 2 7 total 0.004496 0.000901 +29 3 1 2 8 total 0.004766 0.000906 +30 3 1 2 9 total 0.006025 0.001201 +31 3 1 2 10 total 0.004496 0.000830 +32 3 1 2 11 total 0.002608 0.000422 +11 3 2 1 1 total 0.000000 0.000000 +12 3 2 1 2 total 0.000000 0.000000 +13 3 2 1 3 total 0.000000 0.000000 +14 3 2 1 4 total 0.000000 0.000000 +15 3 2 1 5 total 0.000000 0.000000 +16 3 2 1 6 total 0.000000 0.000000 +17 3 2 1 7 total 0.000000 0.000000 +18 3 2 1 8 total 0.000000 0.000000 +19 3 2 1 9 total 0.000000 0.000000 +20 3 2 1 10 total 0.000000 0.000000 +21 3 2 1 11 total 0.000440 0.000764 +0 3 2 2 1 total 0.088029 0.020587 +1 3 2 2 2 total 0.097712 0.022100 +2 3 2 2 3 total 0.125881 0.030136 +3 3 2 2 4 total 0.117518 0.025939 +4 3 2 2 5 total 0.130282 0.025029 +5 3 2 2 6 total 0.166374 0.037579 +6 3 2 2 7 total 0.179138 0.036602 +7 3 2 2 8 total 0.212149 0.043875 +8 3 2 2 9 total 0.235036 0.044338 +9 3 2 2 10 total 0.330988 0.066148 +10 3 2 2 11 total 0.337150 0.064881 diff --git a/tests/regression_tests/mgxs_library_histogram/test.py b/tests/regression_tests/mgxs_library_histogram/test.py new file mode 100644 index 0000000000..b9905910ab --- /dev/null +++ b/tests/regression_tests/mgxs_library_histogram/test.py @@ -0,0 +1,64 @@ +import hashlib + +import openmc +import openmc.mgxs +from openmc.examples import pwr_pin_cell + +from tests.testing_harness import PyAPITestHarness + + +class MGXSTestHarness(PyAPITestHarness): + def __init__(self, *args, **kwargs): + # Generate inputs using parent class routine + super().__init__(*args, **kwargs) + + # Initialize a two-group structure + energy_groups = openmc.mgxs.EnergyGroups(group_edges=[0, 0.625, 20.e6]) + + # Initialize MGXS Library for a few cross section types + self.mgxs_lib = openmc.mgxs.Library(self._model.geometry) + self.mgxs_lib.by_nuclide = False + + # Test all MGXS types + self.mgxs_lib.mgxs_types = ['scatter matrix', 'nu-scatter matrix', + 'consistent scatter matrix', + 'consistent nu-scatter matrix'] + self.mgxs_lib.energy_groups = energy_groups + self.mgxs_lib.scatter_format = 'histogram' + self.mgxs_lib.histogram_bins = 11 + self.mgxs_lib.domain_type = 'material' + self.mgxs_lib.build_library() + + # Add tallies + self.mgxs_lib.add_to_tallies_file(self._model.tallies, merge=False) + + def _get_results(self, hash_output=False): + """Digest info in the statepoint and return as a string.""" + + # Read the statepoint file. + sp = openmc.StatePoint(self._sp_name) + + # Load the MGXS library from the statepoint + self.mgxs_lib.load_from_statepoint(sp) + + # Build a string from Pandas Dataframe for each MGXS + outstr = '' + for domain in self.mgxs_lib.domains: + for mgxs_type in self.mgxs_lib.mgxs_types: + mgxs = self.mgxs_lib.get_mgxs(domain, mgxs_type) + df = mgxs.get_pandas_dataframe() + outstr += df.to_string() + '\n' + + # Hash the results if necessary + if hash_output: + sha512 = hashlib.sha512() + sha512.update(outstr.encode('utf-8')) + outstr = sha512.hexdigest() + + return outstr + + +def test_mgxs_library_histogram(): + model = pwr_pin_cell() + harness = MGXSTestHarness('statepoint.10.h5', model) + harness.main() From 45d9234fdfab74e96f42fed27f7c045d9701e766 Mon Sep 17 00:00:00 2001 From: Adam G Nelson Date: Sat, 5 May 2018 11:15:11 -0400 Subject: [PATCH 73/77] Fixing df.drop call using newer pandas syntax instead of backwards-compatible syntax --- openmc/mgxs/mgxs.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openmc/mgxs/mgxs.py b/openmc/mgxs/mgxs.py index 560c6e9862..172d7ddb38 100644 --- a/openmc/mgxs/mgxs.py +++ b/openmc/mgxs/mgxs.py @@ -4505,7 +4505,7 @@ class ScatterMatrixXS(MatrixMGXS): # If the matrix is P0, remove the legendre column if self.scatter_format == 'legendre' and self.legendre_order == 0: - df = df.drop(columns=['legendre']) + df = df.drop(axis=1, labels=['legendre']) return df From 6d84ed8d5346eefb9b78fa358a806a1b1de77b0f Mon Sep 17 00:00:00 2001 From: Adam G Nelson Date: Sat, 5 May 2018 11:20:13 -0400 Subject: [PATCH 74/77] Resetting mgxs_library_histogram test results back to before the MGXS Api changes so I can more easily see progress --- .../mgxs_library_histogram/results_true.dat | 164 +++++++++--------- 1 file changed, 82 insertions(+), 82 deletions(-) diff --git a/tests/regression_tests/mgxs_library_histogram/results_true.dat b/tests/regression_tests/mgxs_library_histogram/results_true.dat index 20625efd06..116a1a9835 100644 --- a/tests/regression_tests/mgxs_library_histogram/results_true.dat +++ b/tests/regression_tests/mgxs_library_histogram/results_true.dat @@ -134,27 +134,27 @@ 9 1 2 2 10 total 0.041695 0.005386 10 1 2 2 11 total 0.038147 0.003944 material group in group out mu bin nuclide mean std. dev. -33 1 1 1 1 total 0.025529 0.002692 -34 1 1 1 2 total 0.028016 0.002666 -35 1 1 1 3 total 0.031829 0.003739 -36 1 1 1 4 total 0.028348 0.002519 -37 1 1 1 5 total 0.030337 0.003534 -38 1 1 1 6 total 0.029177 0.003461 -39 1 1 1 7 total 0.030668 0.003682 -40 1 1 1 8 total 0.035476 0.004666 -41 1 1 1 9 total 0.043931 0.006899 -42 1 1 1 10 total 0.044759 0.004466 -43 1 1 1 11 total 0.058353 0.006082 +33 1 1 1 1 total 0.025529 0.002974 +34 1 1 1 2 total 0.028016 0.003005 +35 1 1 1 3 total 0.031829 0.004057 +36 1 1 1 4 total 0.028348 0.002884 +37 1 1 1 5 total 0.030337 0.003840 +38 1 1 1 6 total 0.029177 0.003750 +39 1 1 1 7 total 0.030668 0.003982 +40 1 1 1 8 total 0.035476 0.004986 +41 1 1 1 9 total 0.043931 0.007233 +42 1 1 1 10 total 0.044759 0.004986 +43 1 1 1 11 total 0.058353 0.006733 22 1 1 2 1 total 0.000000 0.000000 -23 1 1 2 2 total 0.000166 0.000196 -24 1 1 2 3 total 0.000332 0.000290 -25 1 1 2 4 total 0.000166 0.000196 +23 1 1 2 2 total 0.000166 0.000201 +24 1 1 2 3 total 0.000332 0.000306 +25 1 1 2 4 total 0.000166 0.000201 26 1 1 2 5 total 0.000000 0.000000 -27 1 1 2 6 total 0.000166 0.000196 +27 1 1 2 6 total 0.000166 0.000201 28 1 1 2 7 total 0.000000 0.000000 29 1 1 2 8 total 0.000000 0.000000 30 1 1 2 9 total 0.000000 0.000000 -31 1 1 2 10 total 0.000166 0.000196 +31 1 1 2 10 total 0.000166 0.000201 32 1 1 2 11 total 0.000000 0.000000 11 1 2 1 1 total 0.000887 0.001538 12 1 2 1 2 total 0.000000 0.000000 @@ -167,17 +167,17 @@ 19 1 2 1 9 total 0.000000 0.000000 20 1 2 1 10 total 0.000000 0.000000 21 1 2 1 11 total 0.000000 0.000000 -0 1 2 2 1 total 0.036372 0.007026 -1 1 2 2 2 total 0.030162 0.003524 -2 1 2 2 3 total 0.035485 0.006931 -3 1 2 2 4 total 0.028388 0.005962 -4 1 2 2 5 total 0.035485 0.007736 -5 1 2 2 6 total 0.033711 0.004957 -6 1 2 2 7 total 0.036372 0.004455 -7 1 2 2 8 total 0.039921 0.005585 -8 1 2 2 9 total 0.039034 0.008173 -9 1 2 2 10 total 0.041695 0.005796 -10 1 2 2 11 total 0.038147 0.004404 +0 1 2 2 1 total 0.036372 0.006936 +1 1 2 2 2 total 0.030162 0.003400 +2 1 2 2 3 total 0.035485 0.006844 +3 1 2 2 4 total 0.028388 0.005898 +4 1 2 2 5 total 0.035485 0.007658 +5 1 2 2 6 total 0.033711 0.004847 +6 1 2 2 7 total 0.036372 0.004312 +7 1 2 2 8 total 0.039921 0.005448 +8 1 2 2 9 total 0.039034 0.008084 +9 1 2 2 10 total 0.041695 0.005652 +10 1 2 2 11 total 0.038147 0.004245 material group in group out mu bin nuclide mean std. dev. 33 2 1 1 1 total 0.026289 0.004089 34 2 1 1 2 total 0.018269 0.002939 @@ -314,17 +314,17 @@ 9 2 2 2 10 total 0.031739 0.012040 10 2 2 2 11 total 0.019532 0.005496 material group in group out mu bin nuclide mean std. dev. -33 2 1 1 1 total 0.026462 0.004589 -34 2 1 1 2 total 0.018389 0.003277 -35 2 1 1 3 total 0.025565 0.002922 -36 2 1 1 4 total 0.024220 0.005456 -37 2 1 1 5 total 0.022425 0.003808 -38 2 1 1 6 total 0.027808 0.005297 -39 2 1 1 7 total 0.026014 0.003652 -40 2 1 1 8 total 0.026911 0.007093 -41 2 1 1 9 total 0.027808 0.005664 -42 2 1 1 10 total 0.036778 0.006592 -43 2 1 1 11 total 0.049785 0.005660 +33 2 1 1 1 total 0.026462 0.004896 +34 2 1 1 2 total 0.018389 0.003485 +35 2 1 1 3 total 0.025565 0.003355 +36 2 1 1 4 total 0.024220 0.005676 +37 2 1 1 5 total 0.022425 0.004073 +38 2 1 1 6 total 0.027808 0.005593 +39 2 1 1 7 total 0.026014 0.004019 +40 2 1 1 8 total 0.026911 0.007302 +41 2 1 1 9 total 0.027808 0.005941 +42 2 1 1 10 total 0.036778 0.007007 +43 2 1 1 11 total 0.049785 0.006508 22 2 1 2 1 total 0.000000 0.000000 23 2 1 2 2 total 0.000000 0.000000 24 2 1 2 3 total 0.000000 0.000000 @@ -347,17 +347,17 @@ 19 2 2 1 9 total 0.000000 0.000000 20 2 2 1 10 total 0.000000 0.000000 21 2 2 1 11 total 0.000000 0.000000 -0 2 2 2 1 total 0.024415 0.008094 -1 2 2 2 2 total 0.036622 0.007855 -2 2 2 2 3 total 0.041505 0.012588 -3 2 2 2 4 total 0.019532 0.009048 -4 2 2 2 5 total 0.021973 0.008217 -5 2 2 2 6 total 0.019532 0.011894 -6 2 2 2 7 total 0.021973 0.007253 -7 2 2 2 8 total 0.036622 0.011671 -8 2 2 2 9 total 0.021973 0.006141 -9 2 2 2 10 total 0.031739 0.012779 -10 2 2 2 11 total 0.019532 0.006096 +0 2 2 2 1 total 0.024415 0.008170 +1 2 2 2 2 total 0.036622 0.008031 +2 2 2 2 3 total 0.041505 0.012730 +3 2 2 2 4 total 0.019532 0.009092 +4 2 2 2 5 total 0.021973 0.008278 +5 2 2 2 6 total 0.019532 0.011928 +6 2 2 2 7 total 0.021973 0.007322 +7 2 2 2 8 total 0.036622 0.011790 +8 2 2 2 9 total 0.021973 0.006222 +9 2 2 2 10 total 0.031739 0.012861 +10 2 2 2 11 total 0.019532 0.006160 material group in group out mu bin nuclide mean std. dev. 33 3 1 1 1 total 0.007001 0.000582 34 3 1 1 2 total 0.007728 0.001008 @@ -494,28 +494,28 @@ 9 3 2 2 10 total 0.330988 0.048491 10 3 2 2 11 total 0.337150 0.045927 material group in group out mu bin nuclide mean std. dev. -33 3 1 1 1 total 0.006924 0.000686 -34 3 1 1 2 total 0.007643 0.001078 -35 3 1 1 3 total 0.006744 0.001166 -36 3 1 1 4 total 0.006025 0.000843 -37 3 1 1 5 total 0.007104 0.000759 -38 3 1 1 6 total 0.011150 0.000920 -39 3 1 1 7 total 0.042173 0.003073 -40 3 1 1 8 total 0.073645 0.004762 -41 3 1 1 9 total 0.117706 0.009309 -42 3 1 1 10 total 0.151606 0.010122 -43 3 1 1 11 total 0.202141 0.015127 -22 3 1 2 1 total 0.000809 0.000308 -23 3 1 2 2 total 0.000809 0.000118 -24 3 1 2 3 total 0.001079 0.000251 -25 3 1 2 4 total 0.001079 0.000321 -26 3 1 2 5 total 0.002518 0.000642 -27 3 1 2 6 total 0.002338 0.000397 -28 3 1 2 7 total 0.004496 0.000920 -29 3 1 2 8 total 0.004766 0.000928 -30 3 1 2 9 total 0.006025 0.001227 -31 3 1 2 10 total 0.004496 0.000852 -32 3 1 2 11 total 0.002608 0.000436 +33 3 1 1 1 total 0.006924 0.000699 +34 3 1 1 2 total 0.007643 0.001089 +35 3 1 1 3 total 0.006744 0.001173 +36 3 1 1 4 total 0.006025 0.000851 +37 3 1 1 5 total 0.007104 0.000772 +38 3 1 1 6 total 0.011150 0.000945 +39 3 1 1 7 total 0.042173 0.003183 +40 3 1 1 8 total 0.073645 0.004976 +41 3 1 1 9 total 0.117706 0.009591 +42 3 1 1 10 total 0.151606 0.010550 +43 3 1 1 11 total 0.202141 0.015638 +22 3 1 2 1 total 0.000809 0.000306 +23 3 1 2 2 total 0.000809 0.000113 +24 3 1 2 3 total 0.001079 0.000247 +25 3 1 2 4 total 0.001079 0.000318 +26 3 1 2 5 total 0.002518 0.000633 +27 3 1 2 6 total 0.002338 0.000385 +28 3 1 2 7 total 0.004496 0.000901 +29 3 1 2 8 total 0.004766 0.000906 +30 3 1 2 9 total 0.006025 0.001201 +31 3 1 2 10 total 0.004496 0.000830 +32 3 1 2 11 total 0.002608 0.000422 11 3 2 1 1 total 0.000000 0.000000 12 3 2 1 2 total 0.000000 0.000000 13 3 2 1 3 total 0.000000 0.000000 @@ -527,14 +527,14 @@ 19 3 2 1 9 total 0.000000 0.000000 20 3 2 1 10 total 0.000000 0.000000 21 3 2 1 11 total 0.000440 0.000764 -0 3 2 2 1 total 0.088029 0.018984 -1 3 2 2 2 total 0.097712 0.020255 -2 3 2 2 3 total 0.125881 0.027901 -3 3 2 2 4 total 0.117518 0.023659 -4 3 2 2 5 total 0.130282 0.022078 -5 3 2 2 6 total 0.166374 0.034431 -6 3 2 2 7 total 0.179138 0.032816 -7 3 2 2 8 total 0.212149 0.039453 -8 3 2 2 9 total 0.235036 0.038904 -9 3 2 2 10 total 0.330988 0.058979 -10 3 2 2 11 total 0.337150 0.057260 +0 3 2 2 1 total 0.088029 0.020587 +1 3 2 2 2 total 0.097712 0.022100 +2 3 2 2 3 total 0.125881 0.030136 +3 3 2 2 4 total 0.117518 0.025939 +4 3 2 2 5 total 0.130282 0.025029 +5 3 2 2 6 total 0.166374 0.037579 +6 3 2 2 7 total 0.179138 0.036602 +7 3 2 2 8 total 0.212149 0.043875 +8 3 2 2 9 total 0.235036 0.044338 +9 3 2 2 10 total 0.330988 0.066148 +10 3 2 2 11 total 0.337150 0.064881 From 758f0b3087f1780387d707c2147a07d3d4aa6b03 Mon Sep 17 00:00:00 2001 From: Adam G Nelson Date: Sat, 5 May 2018 16:55:13 -0400 Subject: [PATCH 75/77] updating tests now that I know the std dev issue --- .../mgxs_library_correction/results_true.dat | 12 +- .../mgxs_library_histogram/results_true.dat | 164 +++++++++--------- 2 files changed, 88 insertions(+), 88 deletions(-) diff --git a/tests/regression_tests/mgxs_library_correction/results_true.dat b/tests/regression_tests/mgxs_library_correction/results_true.dat index f7e288802c..cc28320e25 100644 --- a/tests/regression_tests/mgxs_library_correction/results_true.dat +++ b/tests/regression_tests/mgxs_library_correction/results_true.dat @@ -2,12 +2,12 @@ 3 1 1 1 total 0.332466 0.026533 2 1 1 2 total 0.000989 0.000482 1 1 2 1 total 0.000925 0.000925 -0 1 2 2 total 0.396146 0.015511 +0 1 2 2 total 0.396146 0.015707 material group in group out nuclide mean std. dev. 3 1 1 1 total 0.332466 0.026533 2 1 1 2 total 0.000989 0.000482 1 1 2 1 total 0.000925 0.000925 -0 1 2 2 total 0.396146 0.015511 +0 1 2 2 total 0.396146 0.015707 material group in group out nuclide mean std. dev. 3 1 1 1 total 0.334690 0.037288 2 1 1 2 total 0.000995 0.000489 @@ -39,15 +39,15 @@ 1 2 2 1 total 0.000000 0.000000 0 2 2 2 total 0.306635 0.067497 material group in group out nuclide mean std. dev. -3 3 1 1 total 0.258652 0.022623 +3 3 1 1 total 0.258652 0.022596 2 3 1 2 total 0.031368 0.001728 1 3 2 1 total 0.000443 0.000445 -0 3 2 2 total 1.482300 0.232653 +0 3 2 2 total 1.482300 0.232582 material group in group out nuclide mean std. dev. -3 3 1 1 total 0.258652 0.022623 +3 3 1 1 total 0.258652 0.022596 2 3 1 2 total 0.031368 0.001728 1 3 2 1 total 0.000443 0.000445 -0 3 2 2 total 1.482300 0.232653 +0 3 2 2 total 1.482300 0.232582 material group in group out nuclide mean std. dev. 3 3 1 1 total 0.251610 0.041472 2 3 1 2 total 0.031023 0.002232 diff --git a/tests/regression_tests/mgxs_library_histogram/results_true.dat b/tests/regression_tests/mgxs_library_histogram/results_true.dat index 116a1a9835..20625efd06 100644 --- a/tests/regression_tests/mgxs_library_histogram/results_true.dat +++ b/tests/regression_tests/mgxs_library_histogram/results_true.dat @@ -134,27 +134,27 @@ 9 1 2 2 10 total 0.041695 0.005386 10 1 2 2 11 total 0.038147 0.003944 material group in group out mu bin nuclide mean std. dev. -33 1 1 1 1 total 0.025529 0.002974 -34 1 1 1 2 total 0.028016 0.003005 -35 1 1 1 3 total 0.031829 0.004057 -36 1 1 1 4 total 0.028348 0.002884 -37 1 1 1 5 total 0.030337 0.003840 -38 1 1 1 6 total 0.029177 0.003750 -39 1 1 1 7 total 0.030668 0.003982 -40 1 1 1 8 total 0.035476 0.004986 -41 1 1 1 9 total 0.043931 0.007233 -42 1 1 1 10 total 0.044759 0.004986 -43 1 1 1 11 total 0.058353 0.006733 +33 1 1 1 1 total 0.025529 0.002692 +34 1 1 1 2 total 0.028016 0.002666 +35 1 1 1 3 total 0.031829 0.003739 +36 1 1 1 4 total 0.028348 0.002519 +37 1 1 1 5 total 0.030337 0.003534 +38 1 1 1 6 total 0.029177 0.003461 +39 1 1 1 7 total 0.030668 0.003682 +40 1 1 1 8 total 0.035476 0.004666 +41 1 1 1 9 total 0.043931 0.006899 +42 1 1 1 10 total 0.044759 0.004466 +43 1 1 1 11 total 0.058353 0.006082 22 1 1 2 1 total 0.000000 0.000000 -23 1 1 2 2 total 0.000166 0.000201 -24 1 1 2 3 total 0.000332 0.000306 -25 1 1 2 4 total 0.000166 0.000201 +23 1 1 2 2 total 0.000166 0.000196 +24 1 1 2 3 total 0.000332 0.000290 +25 1 1 2 4 total 0.000166 0.000196 26 1 1 2 5 total 0.000000 0.000000 -27 1 1 2 6 total 0.000166 0.000201 +27 1 1 2 6 total 0.000166 0.000196 28 1 1 2 7 total 0.000000 0.000000 29 1 1 2 8 total 0.000000 0.000000 30 1 1 2 9 total 0.000000 0.000000 -31 1 1 2 10 total 0.000166 0.000201 +31 1 1 2 10 total 0.000166 0.000196 32 1 1 2 11 total 0.000000 0.000000 11 1 2 1 1 total 0.000887 0.001538 12 1 2 1 2 total 0.000000 0.000000 @@ -167,17 +167,17 @@ 19 1 2 1 9 total 0.000000 0.000000 20 1 2 1 10 total 0.000000 0.000000 21 1 2 1 11 total 0.000000 0.000000 -0 1 2 2 1 total 0.036372 0.006936 -1 1 2 2 2 total 0.030162 0.003400 -2 1 2 2 3 total 0.035485 0.006844 -3 1 2 2 4 total 0.028388 0.005898 -4 1 2 2 5 total 0.035485 0.007658 -5 1 2 2 6 total 0.033711 0.004847 -6 1 2 2 7 total 0.036372 0.004312 -7 1 2 2 8 total 0.039921 0.005448 -8 1 2 2 9 total 0.039034 0.008084 -9 1 2 2 10 total 0.041695 0.005652 -10 1 2 2 11 total 0.038147 0.004245 +0 1 2 2 1 total 0.036372 0.007026 +1 1 2 2 2 total 0.030162 0.003524 +2 1 2 2 3 total 0.035485 0.006931 +3 1 2 2 4 total 0.028388 0.005962 +4 1 2 2 5 total 0.035485 0.007736 +5 1 2 2 6 total 0.033711 0.004957 +6 1 2 2 7 total 0.036372 0.004455 +7 1 2 2 8 total 0.039921 0.005585 +8 1 2 2 9 total 0.039034 0.008173 +9 1 2 2 10 total 0.041695 0.005796 +10 1 2 2 11 total 0.038147 0.004404 material group in group out mu bin nuclide mean std. dev. 33 2 1 1 1 total 0.026289 0.004089 34 2 1 1 2 total 0.018269 0.002939 @@ -314,17 +314,17 @@ 9 2 2 2 10 total 0.031739 0.012040 10 2 2 2 11 total 0.019532 0.005496 material group in group out mu bin nuclide mean std. dev. -33 2 1 1 1 total 0.026462 0.004896 -34 2 1 1 2 total 0.018389 0.003485 -35 2 1 1 3 total 0.025565 0.003355 -36 2 1 1 4 total 0.024220 0.005676 -37 2 1 1 5 total 0.022425 0.004073 -38 2 1 1 6 total 0.027808 0.005593 -39 2 1 1 7 total 0.026014 0.004019 -40 2 1 1 8 total 0.026911 0.007302 -41 2 1 1 9 total 0.027808 0.005941 -42 2 1 1 10 total 0.036778 0.007007 -43 2 1 1 11 total 0.049785 0.006508 +33 2 1 1 1 total 0.026462 0.004589 +34 2 1 1 2 total 0.018389 0.003277 +35 2 1 1 3 total 0.025565 0.002922 +36 2 1 1 4 total 0.024220 0.005456 +37 2 1 1 5 total 0.022425 0.003808 +38 2 1 1 6 total 0.027808 0.005297 +39 2 1 1 7 total 0.026014 0.003652 +40 2 1 1 8 total 0.026911 0.007093 +41 2 1 1 9 total 0.027808 0.005664 +42 2 1 1 10 total 0.036778 0.006592 +43 2 1 1 11 total 0.049785 0.005660 22 2 1 2 1 total 0.000000 0.000000 23 2 1 2 2 total 0.000000 0.000000 24 2 1 2 3 total 0.000000 0.000000 @@ -347,17 +347,17 @@ 19 2 2 1 9 total 0.000000 0.000000 20 2 2 1 10 total 0.000000 0.000000 21 2 2 1 11 total 0.000000 0.000000 -0 2 2 2 1 total 0.024415 0.008170 -1 2 2 2 2 total 0.036622 0.008031 -2 2 2 2 3 total 0.041505 0.012730 -3 2 2 2 4 total 0.019532 0.009092 -4 2 2 2 5 total 0.021973 0.008278 -5 2 2 2 6 total 0.019532 0.011928 -6 2 2 2 7 total 0.021973 0.007322 -7 2 2 2 8 total 0.036622 0.011790 -8 2 2 2 9 total 0.021973 0.006222 -9 2 2 2 10 total 0.031739 0.012861 -10 2 2 2 11 total 0.019532 0.006160 +0 2 2 2 1 total 0.024415 0.008094 +1 2 2 2 2 total 0.036622 0.007855 +2 2 2 2 3 total 0.041505 0.012588 +3 2 2 2 4 total 0.019532 0.009048 +4 2 2 2 5 total 0.021973 0.008217 +5 2 2 2 6 total 0.019532 0.011894 +6 2 2 2 7 total 0.021973 0.007253 +7 2 2 2 8 total 0.036622 0.011671 +8 2 2 2 9 total 0.021973 0.006141 +9 2 2 2 10 total 0.031739 0.012779 +10 2 2 2 11 total 0.019532 0.006096 material group in group out mu bin nuclide mean std. dev. 33 3 1 1 1 total 0.007001 0.000582 34 3 1 1 2 total 0.007728 0.001008 @@ -494,28 +494,28 @@ 9 3 2 2 10 total 0.330988 0.048491 10 3 2 2 11 total 0.337150 0.045927 material group in group out mu bin nuclide mean std. dev. -33 3 1 1 1 total 0.006924 0.000699 -34 3 1 1 2 total 0.007643 0.001089 -35 3 1 1 3 total 0.006744 0.001173 -36 3 1 1 4 total 0.006025 0.000851 -37 3 1 1 5 total 0.007104 0.000772 -38 3 1 1 6 total 0.011150 0.000945 -39 3 1 1 7 total 0.042173 0.003183 -40 3 1 1 8 total 0.073645 0.004976 -41 3 1 1 9 total 0.117706 0.009591 -42 3 1 1 10 total 0.151606 0.010550 -43 3 1 1 11 total 0.202141 0.015638 -22 3 1 2 1 total 0.000809 0.000306 -23 3 1 2 2 total 0.000809 0.000113 -24 3 1 2 3 total 0.001079 0.000247 -25 3 1 2 4 total 0.001079 0.000318 -26 3 1 2 5 total 0.002518 0.000633 -27 3 1 2 6 total 0.002338 0.000385 -28 3 1 2 7 total 0.004496 0.000901 -29 3 1 2 8 total 0.004766 0.000906 -30 3 1 2 9 total 0.006025 0.001201 -31 3 1 2 10 total 0.004496 0.000830 -32 3 1 2 11 total 0.002608 0.000422 +33 3 1 1 1 total 0.006924 0.000686 +34 3 1 1 2 total 0.007643 0.001078 +35 3 1 1 3 total 0.006744 0.001166 +36 3 1 1 4 total 0.006025 0.000843 +37 3 1 1 5 total 0.007104 0.000759 +38 3 1 1 6 total 0.011150 0.000920 +39 3 1 1 7 total 0.042173 0.003073 +40 3 1 1 8 total 0.073645 0.004762 +41 3 1 1 9 total 0.117706 0.009309 +42 3 1 1 10 total 0.151606 0.010122 +43 3 1 1 11 total 0.202141 0.015127 +22 3 1 2 1 total 0.000809 0.000308 +23 3 1 2 2 total 0.000809 0.000118 +24 3 1 2 3 total 0.001079 0.000251 +25 3 1 2 4 total 0.001079 0.000321 +26 3 1 2 5 total 0.002518 0.000642 +27 3 1 2 6 total 0.002338 0.000397 +28 3 1 2 7 total 0.004496 0.000920 +29 3 1 2 8 total 0.004766 0.000928 +30 3 1 2 9 total 0.006025 0.001227 +31 3 1 2 10 total 0.004496 0.000852 +32 3 1 2 11 total 0.002608 0.000436 11 3 2 1 1 total 0.000000 0.000000 12 3 2 1 2 total 0.000000 0.000000 13 3 2 1 3 total 0.000000 0.000000 @@ -527,14 +527,14 @@ 19 3 2 1 9 total 0.000000 0.000000 20 3 2 1 10 total 0.000000 0.000000 21 3 2 1 11 total 0.000440 0.000764 -0 3 2 2 1 total 0.088029 0.020587 -1 3 2 2 2 total 0.097712 0.022100 -2 3 2 2 3 total 0.125881 0.030136 -3 3 2 2 4 total 0.117518 0.025939 -4 3 2 2 5 total 0.130282 0.025029 -5 3 2 2 6 total 0.166374 0.037579 -6 3 2 2 7 total 0.179138 0.036602 -7 3 2 2 8 total 0.212149 0.043875 -8 3 2 2 9 total 0.235036 0.044338 -9 3 2 2 10 total 0.330988 0.066148 -10 3 2 2 11 total 0.337150 0.064881 +0 3 2 2 1 total 0.088029 0.018984 +1 3 2 2 2 total 0.097712 0.020255 +2 3 2 2 3 total 0.125881 0.027901 +3 3 2 2 4 total 0.117518 0.023659 +4 3 2 2 5 total 0.130282 0.022078 +5 3 2 2 6 total 0.166374 0.034431 +6 3 2 2 7 total 0.179138 0.032816 +7 3 2 2 8 total 0.212149 0.039453 +8 3 2 2 9 total 0.235036 0.038904 +9 3 2 2 10 total 0.330988 0.058979 +10 3 2 2 11 total 0.337150 0.057260 From 382835960b6614e1f9e282fd900230171d1c6e7d Mon Sep 17 00:00:00 2001 From: Adam G Nelson Date: Tue, 8 May 2018 15:02:23 -0400 Subject: [PATCH 76/77] removed errant print statements in regression_tests/tallies/test.py --- tests/regression_tests/tallies/test.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/tests/regression_tests/tallies/test.py b/tests/regression_tests/tallies/test.py index b86d71d006..601b611f49 100644 --- a/tests/regression_tests/tallies/test.py +++ b/tests/regression_tests/tallies/test.py @@ -76,7 +76,6 @@ def test_tallies(): mu_tally1 = Tally() mu_tally1.filters = [mu_filter] mu_tally1.scores = ['scatter', 'nu-scatter'] - print('mu_tally1', mu_tally1.id) mu_tally2 = Tally() mu_tally2.filters = [mu_filter, mesh_filter] @@ -104,7 +103,6 @@ def test_tallies(): legendre_tally.filters = [legendre_filter] legendre_tally.scores = ['scatter', 'nu-scatter'] legendre_tally.estimatir = 'analog' - print('legendre_tally', mu_tally1.id) harmonics_filter = SphericalHarmonicsFilter(order=4) harmonics_tally = Tally() From 72d84bc286b946723e278fdcc6474d2e93c26a77 Mon Sep 17 00:00:00 2001 From: Alex Lindsay Date: Mon, 7 May 2018 14:42:09 -0600 Subject: [PATCH 77/77] Use consistent normalization for Zernikes. --- openmc/filter_expansion.py | 13 +++++++------ src/math.F90 | 12 +++--------- 2 files changed, 10 insertions(+), 15 deletions(-) diff --git a/openmc/filter_expansion.py b/openmc/filter_expansion.py index 872eaac9f5..b092410828 100644 --- a/openmc/filter_expansion.py +++ b/openmc/filter_expansion.py @@ -318,15 +318,15 @@ class ZernikeFilter(ExpansionFilter): This filter allows scores to be multiplied by Zernike polynomials of the particle's position normalized to a given unit circle, up to a - user-specified order. The Zernike polynomials follow the definition by `Noll - `_ and are defined as + user-specified order. The standard Zernike polynomials follow the definition by + Born and Wolf, *Principles of Optics* and are defined as .. math:: - Z_n^m(\rho, \theta) = \sqrt{2n + 2} R_n^m(\rho) \cos (m\theta), \quad m > 0 + Z_n^m(\rho, \theta) = R_n^m(\rho) \cos (m\theta), \quad m > 0 - Z_n^{m}(\rho, \theta) = \sqrt{2n + 2} R_n^{m}(\rho) \sin (m\theta), \quad m < 0 + Z_n^{m}(\rho, \theta) = R_n^{m}(\rho) \sin (m\theta), \quad m < 0 - Z_n^{m}(\rho, \theta) = \sqrt{n + 1} R_n^{m}(\rho), \quad m = 0 + Z_n^{m}(\rho, \theta) = R_n^{m}(\rho), \quad m = 0 where the radial polynomials are @@ -335,7 +335,8 @@ class ZernikeFilter(ExpansionFilter): \frac{n+m}{2} - k)! (\frac{n-m}{2} - k)!} \rho^{n-2k}. With this definition, the integral of :math:`(Z_n^m)^2` over the unit disk - is exactly :math:`\pi` for each polynomial. + is :math:`\frac{\epsilon_m\pi}{2n+2}` for each polynomial where :math:`\epsilon_m` is + 2 if :math:`m` equals 0 and 1 otherwise. Specifying a filter with order N tallies moments for all :math:`n` from 0 to N and each value of :math:`m`. The ordering of the Zernike polynomial diff --git a/src/math.F90 b/src/math.F90 index 20bacf88cf..c633131645 100644 --- a/src/math.F90 +++ b/src/math.F90 @@ -600,12 +600,6 @@ contains real(8) :: k1, k2, k3, k4 ! Variables for R_m_n calculation integer :: i,p,q ! Loop counters - real(8), parameter :: SQRT_N_1(0:10) = [& - sqrt(1.0_8), sqrt(2.0_8), sqrt(3.0_8), sqrt(4.0_8), & - sqrt(5.0_8), sqrt(6.0_8), sqrt(7.0_8), sqrt(8.0_8), & - sqrt(9.0_8), sqrt(10.0_8), sqrt(11.0_8)] - real(8), parameter :: SQRT_2N_2(0:10) = SQRT_N_1*sqrt(2.0_8) - ! n == radial degree ! m == azimuthal frequency @@ -669,11 +663,11 @@ contains do p = 0, n do q = -p, p, 2 if (q < 0) then - zn(i) = zn_mat(p+1, abs(q)+1) * sin_phi_vec(abs(q)) * SQRT_2N_2(p) + zn(i) = zn_mat(p+1, abs(q)+1) * sin_phi_vec(abs(q)) else if (q == 0) then - zn(i) = zn_mat(p+1, q+1) * SQRT_N_1(p) + zn(i) = zn_mat(p+1, q+1) else - zn(i) = zn_mat(p+1, q+1) * cos_phi_vec(abs(q)+1) * SQRT_2N_2(p) + zn(i) = zn_mat(p+1, q+1) * cos_phi_vec(abs(q)+1) end if i = i + 1 end do
01000011U2350.0743930.0003080.0746720.000179
11000011U2380.0059820.0000360.0059640.000017
21000011O160.000000