OpenMC Independent Depletion Operator Split Time Steps

Hi all,

I have a simulation where I would like to have transport coupled depletion for some time steps and transport independent depletion for some time steps. The issue I had was that running with full transport coupling seems to take the same amount of time as the transport independent operator. However, in my results, the keff data was not present for the transport independent steps, so it seemed like things were running as intended.

After looking into things a bit, I noticed the issue is that OpenMC performs transport again instead of using the previous result data if the independent operator steps aren’t in a list. I’ve included a minimal working example here to demonstrate what I mean. The desired behavior from this MWE is for OpenMC to run the first step with transport, and then run the independent steps using the data from the first step. However, transport is run each time for each transport independent step. Is there a way to avoid this if there are not many transport independent steps in a row and the days are split up in the script?

I know the solution for this MWE would be to remove the loop for the transport independent simulations and instead use a list of day steps, but for my more complex problem I want to have a mix of transport coupled and independent steps. Because of this mix of operator types, I can only get slight improvements by making lists of steps that use the same operator type in a row.

import openmc
import numpy as np
import openmc.deplete

def model():
    f = openmc.Material(name="f")
    f.add_element("U", 1, percent_type="ao", enrichment=4.25)
    f.add_element("O", 2)
    f.set_density("g/cc", 10.4)

    w = openmc.Material(name="w")
    w.add_element("O", 1)
    w.add_element("H", 2)
    w.set_density("g/cc", 1.0)

    radii = [0.42, 0.45]
    f.volume = np.pi * radii[0] ** 2
    w.volume = np.pi * (radii[1]**2 - radii[0]**2)

    materials = openmc.Materials([f, w])

    surf_f = openmc.Sphere(r=radii[0])
    surf_w = openmc.Sphere(r=radii[1], boundary_type='reflective')
    cell_f = openmc.Cell(fill=f, region=-surf_f)
    cell_w = openmc.Cell(fill=w, region=+surf_f & -surf_w)
    geometry = openmc.Geometry([cell_f, cell_w])

    settings = openmc.Settings()
    settings.particles = 100
    settings.inactive = 0
    settings.batches = 10

    return openmc.Model(geometry, materials, settings), f, w


if __name__ == "__main__":
    power = 174.0
    rate = 1E-5
    chain_file = f'../../data/chain_casl_pwr.xml'
    nuclide_list = ['U235']
    time_step = 1
    total_independent_steps = 3

    model, fuel, water, materials = model()

    # First depletion step with transport
    op = openmc.deplete.CoupledOperator(model, chain_file)
    integrator = openmc.deplete.PredictorIntegrator(
        op, [1], power, timestep_units = 'd')
    integrator.integrate()

    # Depletion steps without transport
    for i in total_independent_steps:
        previous_results = openmc.deplete.Results('depletion_results.h5')
        micro_xs = openmc.deplete.MicroXS.from_model(model,
                                                    fuel,
                                                    chain_file)
        operator = openmc.deplete.IndependentOperator(fuel,
                                                    micro_xs,
                                                    chain_file,
                                                    prev_results=previous_results)
        integrator = openmc.deplete.PredictorIntegrator(
            op, [1], power, timestep_units = 'd')
        integrator.integrate()
1 Like

Hi LukeSeifert

Thanks for posting this, if I understand correctly would removing that for loop help?

I have a more linear example here which calls these methods in this order and I don’t make use of the prev_results argument.

openmc.deplete.MicroXS.from_model
openmc.deplete.IndependentOperator
openmc.deplete.PredictorIntegrator

Also just to note this part of openmc is getting some attention and has had a few improvements in the deveplo branch that might be of interest pr2540, PR2539 and PR2559

1 Like

Hi Shimwell,

Thanks for the response! I see now that the microXS.from_model function requires an OpenMC run to generate those cross sections, which is why my simulations were taking far longer than expected. So, moving the micro_xs variable declaration outside the loop speeds things up and requires only one additional transport simulation.

It seems that from_array and from_csv for microXS do not require transport to be run, so I will try and get one of those to pull data from the most recent transport run. I’m not sure how easy/difficult that will be, but I will post an update here once I’ve worked on things more.

Unfortunately, the IndependentOperator currently does not have the ability to estimate k_inf (we can’t really estimate k_eff unless we do simulations with the geomerty, which would require doing a particle simulation which was what we wanted to get away from in the first place!). I had planned from the start to add it in, but I ran out of time. There is an open issue in the OpenMC repo with some starter code if you want to take a crack at it.

1 Like