mit-crpg/openmc — pull request #309 by nelsonag (2014-08-25 19:23:24+00:00)
Title: Utilization of NDPP data for Tallying Estimators with increased efficiency

This pull request gives OpenMC the ability to read and utilize the data necessary to utilize what i'm calling the "improved method" of tallying data with outgoing energy or energy-angle distributions. Right now this only means the tallying of the scattering moment matrices and the fission energy spectra.
Before getting in to the code specifics, its probably useful to discuss (in a very condensed form) why this is needed and how well it works.

# The Method

So if you want to use monte carlo to tally MGXS libraries for a deterministic solver with all data produced to a certain uncertainty level, then most of the computation time will be spent waiting for the scattering moments. They are the last to "converge" because 1) the incoming and outgoing energy filters subdivide the region of phase space, decreasing the total number of tally hits per bin, 2) as the moment order increases, the legendre polynomial becomes more "oscillatory" increasing the apparent variance, and 3) these type of tallies are not conducive to track-length tallying since outgoing collision information is necessary.

To combat this, you would want to use a deterministic scoring technique: that is, given a collision the probability distribution for the outgoing energy and change in angle is provided in the ACE data; tally that complete PDF instead of an individual sampled outgoing point.
Now, that distribution absolutely can not be calculated on the fly at each tally event. The computations involved are way too cumbersome. Instead a pre-processor is needed which takes the ACE data and outputs these probability distribution functions already integrated over outgoing energy and the legendre functional expansion of mu performed.
The pre-processor I wrote for this is called NDPP (http://ndpp.github.io/ source: https://github.com/ndpp/ndpp).

So, how does it perform? Well its not perfect - the tallies obtained using the NDPP data can not ever be identical to what would be obtained using normal analog MC integration (our current scatter-pn type scores). This is both because of truncation error (I use numerical integration techniques in NDPP) as well as interpolation error. In general though the errors are on the order of 0.1 to 0.2%.

But the tallying efficiency is significantly improved as is shown in the Figure below. This figure shows the eigenvalue obtained when generating a P2 MGXS library at each of the number of histories (x-axis) and then pumping this library through MPACT, an MOC code at michigan. Red is using the current nuscatter-pn type tallies. Blue is using the NDPP-based data and track-length estimators.
Notice that the NDPP-based data significantly reduces the "eigenvalue swing", and (not shown) it does significantly reduce the overall uncertainty on each indvidual tally as you would expect. Unfortunately it does incur ~15pcm error due to the numerical and interpolation error I mentioned above.
![pcm_p2](https://cloud.githubusercontent.com/assets/1037107/4034592/177e7344-2c87-11e4-8227-28bc96d4d540.png)

Aside from the 15pcm bias, there is one additional problem: tallying the NDPP data is slow. The NDPP tallies were 85% slower than the analog. This could be due to my programming, but also is because the code has to do more work at each collision simply to get the relevant data, interpolate it, and then sum it to the tallies.[ I can significantly improve this if I make the assumption that the user will only want material-wise macroscopic x/s, but I am not willing to make that assumption yet.]

So, if we scale the x-axis of the above figure by run time, then we obtain the figure below (man I need to change that scale).
This shows that despite this slowdown, the NDPP-based data still gets to within 10pcm (the black lines) of its final 1 billion history value (and then stays there) at two hours while the analog method requires ten hours, yielding a factor of 5 improvement. Any speed-up to the NDPP code will directly improve this.
![pcm_p2_time](https://cloud.githubusercontent.com/assets/1037107/4034739/5279ce98-2c88-11e4-9f77-7c9d5ce2e533.png)

Ok, so thats the bare minimum I can give (keeping this PR short) to say why this would be a nice feature. I can of course answer any questions you have about the method here, by e-mail, or in the developers google group.

# The Code

How did I integrate this in to OpenMC? I created versions of scatter-n/pn/yn and nuscatter-n/pn/yn which use the NDPP data instead. These are simply called ndpp-*. In addition, I added ndpp-chi and ndpp-chi-p (total fission spectra and prompt fission spectra). These arent discussed much above since the benefit isnt as big as it is for scattering moments but could still definitely be useful.

So before the user can access these scores they have to first run NDPP and produce data for a given set of nuclides and energy group structure. This will output a bunch of libraries (one for each zaid.kT pair) and an `ndpp_lib.xml` file which is similar to OpenMC's `cross_sections.xml` file but describes the NDPP-produced libraries.

Once this data is generated the user simply has to request one of the ndpp-* scores in a tally and also specify the location of `ndpp_lib.xml` in the `` element of `tallies.xml`. The user is free to use analog or tracklength estimators for all these types. After that, its off to the races.

Here are some specifics to help you in your review:
1. I created tests for all the new scores. They require NDPP data, and so I created some sample data in openmc/tests/NDPP_data for 1001, 8016, 92235, and HH2O with 2 groups using the room temperature NNDC data. I purposefully created this in the ASCII format so you could see what the data looks like if you want.
2. When the user requests a NDPP scattering score, they must include energy and energyout filters with bins matching the group structure of the NDPP libraries. The energy filter must be declared immediately before energyout. Also, the scattering order must be less than or equal to that in the NDPP library. If any of these fail, appropriate error messages will be raised. The energy filter must be right before energyout so that the tallies can be efficiently summed.
3. The Chi scores only require an energyout filter, the user can have energy if they please; the order doesnt matter here.
4. Right now only one energy group structure (one `ndpp_lib.xml` file and associated ata) can be used by OpenMC per run. In practice this shouldnt matter, but it could be improved upon in the future.
5. The random number stream is not affected by the presence of the NDPP tallies and so the neutron simulation is unchanged by the presence of NDPP tallies.
6. I didnt mention this with the methods section, but NDPP produces the data such that the elastic and total inelastic data are separate. This is because the elastic data is temperature dependent anad the inelastic data is independent of kT. OpenMC takes advantage of this by throwing out the redundant temperature independent NDPP data which could exist say if 92235.71c and 92235.72c both existed in a model.
7. I did not modify CMFD to take advantage of the NDPP data. This was because:
a. When item 4 is addressed this could become trivial. I think of item 4 as a pre-requisite since one probably would prefer to do like 47-group tallies, but only do a 2-grp CMFD to get there.
b. It may not be that big of a deal, I *think* that CMFD's convergence on an eigenvalue depends more on the current since D-hat is adjusted from its normal 1/(3sigtr) value to preserve currents.