Merge pull request #154 from bhermanmit/master

Added Method for Tally statepoint binary extraction
This commit is contained in:
Paul Romano 2013-04-08 16:38:17 -07:00
commit b988630357
2 changed files with 262 additions and 198 deletions

View file

@ -1,206 +1,160 @@
#!/usr/bin/python
# Filename: eigenfunction_rms.py
import h5py
# import packages
import statepoint
import numpy as np
import cPickle
import matplotlib.pyplot as plt
import os
import sys
#
class EigenFunction:
#
'''Represents the reference eigenfunction'''
reference = 0.
#
def __init__(self,data):
#
'''Initializes the eigenfunction'''
self.function = 0.
self.data = data
self.meanfunction = 0.
#
def read_hdf5(self,h5_file,cycle):
#
'''Read data from HDF5 file'''
self.cycle = cycle
f = h5py.File(h5_file,'r')
group = '/cycle'+str(cycle)+'/'+self.data
dataset = f[group]
self.function = np.empty(dataset.shape,dataset.dtype)
dataset.read_direct(self.function)
self.function = self.function
self.iamref = 'F'
#
def set_reference(self):
#
'''Sets instance to be reference calc'''
self.iamref = 'T'
EigenFunction.reference = self.function
#
def compute_rms(self):
#
'''Computes RMS value'''
Np = self.function.size
Np = 41772
tmp = (self.meanfunction - EigenFunction.reference)**2
tmp2 = tmp.sum()
self.rms = np.sqrt((1.0/float(Np))*tmp2)
#
def read_runs(runpath,hdfile,cycle_start,cycle_end,run_start,run_end,data):
runlist = []
tmp = EigenFunction(data)
tmp.read_hdf5(runpath+str(run_start)+'/'+hdfile,cycle_start)
indices = tmp.function.shape # extent of all dimensions
i = cycle_start
while i <= cycle_end:
meantmp = EigenFunction(data) # init mean object
j = run_start
runs = np.zeros((run_end - run_start + 1,indices[0],indices[1],indices[2],indices[3])) # init runs array
while j <= run_end:
tmp.read_hdf5(runpath+str(j)+'/'+hdfile,i) # read hdf5 file
runs[j-run_start] = tmp.function # put function into runs
if i == cycle_start:
print runs[j-run_start,0,150,150,0]
j += 1
meantmp.meanfunction = np.average(runs, axis=0) # compute the mean
meantmp.function = runs
runlist.append(meantmp)
print 'Read in from path: '+runpath+' Cycle: '+str(i)
i += 1
return runlist
def create_reference(runpath,hdfile,cycle,run_start,run_end,data):
def main(tally_id, score_id, batch_start, batch_end, name):
# calculate reference solution
print 'Calculating Reference solution...'
tmp = EigenFunction(data)
tmp.read_hdf5(runpath+str(run_start)+'/'+hdfile,cycle) # load first eigenfunction
print 'Read in: '+runpath+str(1)+hdfile+' '+str(tmp.function[0,150,150,0])
indices = tmp.function.shape # extent of all dimensions
ref = np.zeros((run_end,indices[0],indices[1],indices[2],indices[3])) # initialize ref array
ref[0] = tmp.function # set the first run in ref
i = run_start + 1
while i <= run_end: # begin loop around all runs
tmp.read_hdf5(runpath+str(i)+'/'+hdfile,cycle)
print 'Read in: '+runpath+str(i)+hdfile+' '+str(tmp.function[0,150,150,0])
ref[i - run_start] = tmp.function
i += 1
meanref = np.average(ref, axis=0) # compute average of all runs
EigenFunction.reference = meanref # set to global space in EigenFunction instances
return meanref
# read in statepoint header data
sp = statepoint.StatePoint('statepoint.ref.binary')
def compute_rms(runlist):
# read in results
sp.read_results()
# calculate rms array
print 'Calculating rms...'
rms = np.zeros(len(runlist))
i = 0
while i < len(runlist):
runlist[i].compute_rms()
rms[i] = runlist[i].rms
i += 1
return rms
# extract reference mean
mean_ref = extract_mean(sp, tally_id, score_id)
def plot_rms(rms):
print 'Generating plot...'
ax = plt.subplot(111)
size = rms.shape[0]
x = np.linspace(1,size,size)*1e6
y = (rms[0]/x[0]**(-0.5))*x**(-0.5)
plt.loglog(x,rms*100,'b+')
plt.loglog(x,y*100,'g--')
ax.xaxis.grid(True,'minor')
ax.yaxis.grid(True,'minor')
ax.xaxis.grid(True,'major',linewidth=2)
ax.yaxis.grid(True,'major',linewidth=2)
plt.xlabel('# of Total Neutron Histories (active cycles)')
plt.ylabel('RMS Error [%]')
plt.legend(('1 million (10 runs)','Ideal Error 1 mil'))
return
# write gnuplot file
write_src_gnuplot('testsrc_pin','Pin mesh',mean_ref,np.size(mean_ref,0))
# preallocate arrays
hists = np.zeros(batch_end - batch_start + 1)
norms = np.zeros(batch_end - batch_start + 1)
i = batch_start
while i <= batch_end:
# process statepoint
sp = statepoint.StatePoint('statepoint.'+str(i)+'.binary')
sp.read_results()
# extract mean
mean = extract_mean(sp, tally_id, score_id)
# calculate L2 norm
norm = np.linalg.norm(mean - mean_ref)
# get history information
n_inactive = sp.n_inactive
current_batch = sp.current_batch
n_particles = sp.n_particles
gen_per_batch = sp.gen_per_batch
n_histories = (current_batch - n_inactive)*n_particles*gen_per_batch
# batch in vectors
hists[i - batch_start] = n_histories
norms[i - batch_start] = norm
# print
print 'Batch: '+str(i)+' Histories: '+str(n_histories)+' Norm: '+str(norm)
i += 1
# write out gnuplot file
write_norm_gnuplot(name,hists,norms,np.size(hists))
def extract_mean(sp, tally_id,score_id):
# extract results
results = sp.extract_results(tally_id,score_id)
# extract means and copy
mean = results['mean'].copy()
# reshape and integrate over energy
mean = mean.reshape(results['bin_max'],order='F')
mean = np.sum(mean,0)
mean = np.sum(mean,0)
mean = mean/mean.sum()*(mean > 1.e-8).sum()
return mean
def write_norm_gnuplot(path,xdat,ydat,size):
# Header String for GNUPLOT
headerstr = """#!/usr/bin/env gnuplot
set terminal pdf enhanced
set output '{output}'
set ylabel 'L-2 norm'
set xlabel 'Histories'
set log x
set log y
""".format(output=path+'.pdf')
# Write out the plot string
pltstr = "plot '-' using 1:2 with lines"
# Write out the data string
i = 0
datastr = ''
while i < size:
datastr = datastr + '{0} {1}\n'.format(xdat[i],ydat[i])
i += 1
# Concatenate all
outstr = headerstr + '\n' + pltstr + '\n' + datastr
# Write File
with open(path+".plot",'w') as f:
f.write(outstr)
# Run GNUPLOT
os.system('gnuplot ' + path+".plot")
def write_src_gnuplot(path,name,src,size):
# Header String for GNUPLOT
headerstr = """#!/usr/bin/env gnuplot
set terminal pdf enhanced
set output '{output}'
set palette defined (0 '#000090', 1 '#000fff', 2 '#0090ff', 3 '#0fffee', 4 '#90ff70', 5 '#ffee00', 6 '#ff7000', 7 '#ee0000', 8 '#7f0000')
set view map
set size ratio -1
set lmargin at screen 0.10
set rmargin at screen 0.90
set bmargin at screen 0.15
set tmargin at screen 0.90
unset xtics
unset ytics
set title '{title}'""".format(output=path+'.pdf',title=name)
# Write out the plot string
pltstr = "splot '-' matrix with image "
# Write out the data string
i = 0
datastr = ''
while i < size:
j = 0
while j < size:
datastr = datastr + '{0} '.format(src[i,j][0])
j += 1
datastr = datastr + '\n'
i += 1
# replace all nan with zero
datastr = datastr.replace('nan','0.0')
# Concatenate all
outstr = headerstr + '\n' + pltstr + '\n' + datastr
# Write File
with open(path+".plot",'w') as f:
f.write(outstr)
# Run GNUPLOT
os.system('gnuplot ' + path+".plot")
def plot_source(source):
plt.figure()
X = np.linspace(1,272,272)
Y = np.linspace(1,272,272)
Y,X = np.meshgrid(Y,X)
plt.contourf(X,Y,source[0,:,:,0],100)
plt.colorbar()
plt.xlabel('Mesh Cell in x-direction')
plt.ylabel('Mesh Cell in y-direction')
plt.title('OPR Converged Fission Source Distribution')
plt.show()
#
if __name__ == "__main__":
if sys.argv[1] == 'restart':
# load in data
print 'Loading input...'
filein = open('rms.out','r')
output = cPickle.load(filein)
filein.close()
rms = output['1milrms']
meanref = output['ref']
EigenFunction.reference = meanref
# plot rms
plot_rms(rms)
# plot mean source distribution
plot_source(meanref)
elif sys.argv[1] == 'interactive':
# load in data
print 'Loading input...'
filein = open('rms.out','r')
output = cPickle.load(filein)
filein.close()
rms = output['1milrms']
meanref = output['ref']
EigenFunction.reference = meanref
# pop an interactive python shell
from IPython import embed
embed()
else:
# calculate reference solution
runpath = '/media/Backup/opr_runs/64mil/run'
hdfile = 'output.h5'
cycle = 210
run_start = 1
run_end = 4
data = 'openmc_src'
meanref = create_reference(runpath,hdfile,cycle,run_start,run_end,data)
# calculate rms for 1 million case
runpath = '/media/Backup/opr_runs/1mil/run'
hdfile = 'output.h5'
cycle_start = 201
cycle_end = 840
run_start = 1
run_end = 10
data = 'openmc_src'
onemil = read_runs(runpath,hdfile,cycle_start,cycle_end,run_start,run_end,data)
# calculate rms array
rms = compute_rms(onemil)
# write out numpy array to binary file
print 'Writing output...'
output = {}
output.update({'1milrms':rms})
output.update({'ref':meanref})
fileout = open('rms.out','wb')
cPickle.dump(output,fileout)
fileout.close()
# plot rms
plot_rms(rms)
# plot mean source distribution
plot_source(meanref)
tally_id = int(sys.argv[1])
score_id = sys.argv[2]
batch_start = int(sys.argv[3])
batch_end = int(sys.argv[4])
name = sys.argv[5]
main(tally_id, score_id, batch_start, batch_end, name)

View file

@ -183,10 +183,11 @@ class StatePoint(object):
self.k_batch = self._get_double(self.current_batch, path='k_batch')
self.entropy = self._get_double(
self.current_batch*self.gen_per_batch, path='entropy')
self.k_col_abs = self._get_double(path='k_col_abs')[0]
self.k_col_tra = self._get_double(path='k_col_tra')[0]
self.k_abs_tra = self._get_double(path='k_abs_tra')[0]
self.k_combined = self._get_double(2, path='k_combined')
if self.revision >= 8:
self.k_col_abs = self._get_double(path='k_col_abs')[0]
self.k_col_tra = self._get_double(path='k_col_tra')[0]
self.k_abs_tra = self._get_double(path='k_abs_tra')[0]
self.k_combined = self._get_double(2, path='k_combined')
# Read number of meshes
n_meshes = self._get_int(path='tallies/n_meshes')[0]
@ -439,6 +440,115 @@ class StatePoint(object):
# has been called already.
return t.results[filter_index, score_index]
def extract_results(self, tally_id, score_str):
"""Returns a tally results dictionary given a tally_id and score string.
Parameters
----------
tally_id : int
Index for the tally in StatePoint.tallies list
score_str : string
Corresponds to the string entered for a score in tallies.xml.
For a flux score extraction it would be 'score'
"""
# get tally
try:
tally = self.tallies[tally_id-1]
except:
print 'Tally does not exist'
return
# get the score index if it is present
try:
idx = tally.scores.index(score_str)
except ValueError:
print 'Score does not exist'
print tally.scores
return
# create numpy array for mean and 95% CI
n_bins = len(tally.results)
n_filters = len(tally.filters)
n_scores = len(tally.scores)
meanv = np.zeros(n_bins)
unctv = np.zeros(n_bins)
filters = np.zeros((n_bins,n_filters))
filtmax = np.zeros(n_filters+1)
meshmax = np.zeros(4)
filtmax[0] = 1
meshmax[0] = 1
# get number of realizations
n = tally.n_realizations
# get t-value
t_value = scipy.stats.t.ppf(0.975, n - 1)
# calculate mean
meanv = tally.results[:,idx,0]
meanv = meanv / n
# calculate 95% two-sided CI
unctv = tally.results[:,idx,1]
unctv = t_value*np.sqrt((unctv/n - meanv*meanv)/(n-1))/meanv
# create output dictionary
data = {'mean':meanv,'CI95':unctv}
# get bounds of filter bins
for akey in tally.filters.keys():
idx = tally.filters.keys().index(akey)
filtmax[n_filters - idx] = tally.filters[akey].length
# compute bin info
for i in range(n_filters):
# compute indices for filter combination
filters[:,n_filters - i - 1] = np.floor((np.arange(n_bins) %
np.prod(filtmax[0:i+2]))/(np.prod(filtmax[0:i+1]))) + 1
# append in dictionary bin with filter
data.update({tally.filters.keys()[n_filters - i - 1]:
filters[:,n_filters - i - 1]})
# check for mesh
if tally.filters.keys()[n_filters - i - 1] == 'mesh':
dims = list(self.meshes[tally.filters['mesh'].bins[0] - 1].dimension)
dims.reverse()
dims = np.asarray(dims)
if score_str == 'current':
dims += 1
meshmax[1:4] = dims
mesh_bins = np.zeros((n_bins,3))
mesh_bins[:,2] = np.floor(((filters[:,n_filters - i - 1] - 1) %
np.prod(meshmax[0:2]))/(np.prod(meshmax[0:1]))) + 1
mesh_bins[:,1] = np.floor(((filters[:,n_filters - i - 1] - 1) %
np.prod(meshmax[0:3]))/(np.prod(meshmax[0:2]))) + 1
mesh_bins[:,0] = np.floor(((filters[:,n_filters - i - 1] - 1) %
np.prod(meshmax[0:4]))/(np.prod(meshmax[0:3]))) + 1
data.update({'mesh':zip(mesh_bins[:,0],mesh_bins[:,1],
mesh_bins[:,2])})
i += 1
# add in maximum bin filters and order
b = tally.filters.keys()
b.reverse()
filtmax = list(filtmax[1:])
try:
idx = b.index('mesh')
filtmax[idx] = np.max(mesh_bins[:,2])
filtmax.insert(idx,np.max(mesh_bins[:,1]))
filtmax.insert(idx,np.max(mesh_bins[:,0]))
except ValueError:
pass
data.update({'bin_order':b,'bin_max':filtmax})
return data
def _get_data(self, n, typeCode, size):
return list(struct.unpack('={0}{1}'.format(n,typeCode),
self._f.read(n*size)))