Пример #1
0
def test_xml_roundtrip(run_in_tmpdir):
    # Create a tally with all possible gizmos
    mesh = openmc.RegularMesh()
    mesh.lower_left = (-10., -10., -10.)
    mesh.upper_right = (
        10.,
        10.,
        10.,
    )
    mesh.dimension = (5, 5, 5)
    mesh_filter = openmc.MeshFilter(mesh)
    tally = openmc.Tally()
    tally.filters = [mesh_filter]
    tally.nuclides = ['U235', 'I135', 'Li6']
    tally.scores = ['total', 'fission', 'heating']
    tally.derivative = openmc.TallyDerivative(variable='nuclide_density',
                                              material=1,
                                              nuclide='Li6')
    tally.triggers = [openmc.Trigger('rel_err', 0.025)]
    tally.triggers[0].scores = ['total', 'fission']
    tallies = openmc.Tallies([tally])

    # Roundtrip through XML and make sure we get what we started with
    tallies.export_to_xml()
    new_tallies = openmc.Tallies.from_xml()
    assert len(new_tallies) == 1
    new_tally = new_tallies[0]
    assert new_tally.id == tally.id
    assert len(new_tally.filters) == 1
    assert isinstance(new_tally.filters[0], openmc.MeshFilter)
    assert np.allclose(new_tally.filters[0].mesh.lower_left, mesh.lower_left)
    assert new_tally.nuclides == tally.nuclides
    assert new_tally.scores == tally.scores
    assert new_tally.derivative.variable == tally.derivative.variable
    assert new_tally.derivative.material == tally.derivative.material
    assert new_tally.derivative.nuclide == tally.derivative.nuclide
    assert len(new_tally.triggers) == 1
    assert new_tally.triggers[0].trigger_type == tally.triggers[0].trigger_type
    assert new_tally.triggers[0].threshold == tally.triggers[0].threshold
    assert new_tally.triggers[0].scores == tally.triggers[0].scores
def make_materials_geometry_tallies(enrichment):

    # MATERIALS

    breeder_material = openmc.Material(1, "PbLi")  # Pb84.2Li15.8
    breeder_material.add_element('Pb', 84.2, percent_type='ao')
    breeder_material.add_element('Li',
                                 15.8,
                                 percent_type='ao',
                                 enrichment=enrichment,
                                 enrichment_target='Li6',
                                 enrichment_type='ao')
    breeder_material.set_density('atom/b-cm', 3.2720171e-2)  # around 11 g/cm3

    steel = openmc.Material(name='steel')
    steel.set_density('g/cm3', 7.75)
    steel.add_element('Fe', 0.95, percent_type='wo')
    steel.add_element('C', 0.05, percent_type='wo')

    mats = openmc.Materials([breeder_material, steel])

    # GEOMETRY

    # surfaces
    vessel_inner = openmc.Sphere(r=500)
    first_wall_outer_surface = openmc.Sphere(r=510)
    breeder_blanket_outer_surface = openmc.Sphere(r=610,
                                                  boundary_type='vacuum')

    # cells
    inner_vessel_region = -vessel_inner
    inner_vessel_cell = openmc.Cell(region=inner_vessel_region)

    first_wall_region = -first_wall_outer_surface & +vessel_inner
    first_wall_cell = openmc.Cell(region=first_wall_region)
    first_wall_cell.fill = steel

    breeder_blanket_region = +first_wall_outer_surface & -breeder_blanket_outer_surface
    breeder_blanket_cell = openmc.Cell(region=breeder_blanket_region)
    breeder_blanket_cell.fill = breeder_material

    universe = openmc.Universe(
        cells=[inner_vessel_cell, first_wall_cell, breeder_blanket_cell])
    geom = openmc.Geometry(universe)

    # SIMULATION SETTINGS
    sett = openmc.Settings()
    sett.batches = 2  # this is minimum number of batches that will be run
    sett.trigger_active = True
    sett.trigger_max_batches = 200  # this is maximum number of batches that will be run
    sett.inactive = 0
    sett.particles = 1000
    sett.run_mode = 'fixed source'

    source = openmc.Source()
    source.space = openmc.stats.Point((0, 0, 0))
    source.angle = openmc.stats.Isotropic()
    source.energy = openmc.stats.Discrete([14e6], [1])
    sett.source = source

    # TALLIES

    tallies = openmc.Tallies()

    cell_filter = openmc.CellFilter(breeder_blanket_cell)
    tbr_tally = openmc.Tally(name='TBR')
    tbr_tally.filters = [cell_filter]
    tbr_tally.scores = [
        '(n,Xt)'
    ]  # MT 205 is the (n,Xt) reaction where X is a wildcard, if MT 105 or (n,t) then some tritium production will be missed, for example (n,nt) which happens in Li7 would be missed
    tbr_tally.triggers = [
        openmc.Trigger(trigger_type='std_dev', threshold=0.01)
    ]  # This stops the simulation if the threshold is meet
    tallies.append(tbr_tally)

    # RUN OPENMC
    model = openmc.model.Model(geom, mats, sett, tallies)
    sp_filename = model.run()

    # OPEN OUPUT FILE
    sp = openmc.StatePoint(sp_filename)

    tbr_tally = sp.get_tally(name='TBR')

    df = tbr_tally.get_pandas_dataframe()

    tbr_tally_result = df['mean'].sum()
    tbr_tally_std_dev = df['std. dev.'].sum()

    return {
        'enrichment': enrichment,
        'tbr_tally_result': tbr_tally_result,
        'tbr_tally_std_dev': tbr_tally_std_dev
    }
Пример #3
0
def simulate_model(enrichment,
                   blanket_thickness=200,
                   firstwall_thickness=5,
                   breeder_material_name="Li4SiO4",
                   temperature_in_C=500,
                   threshold=0.0005,
                   inner_radius=500):

    # MATERIALS from library of materials in neutronics_material_maker package
    breeder_material = Material(
        material_name=breeder_material_name,
        enrichment=enrichment,
        temperature_in_C=temperature_in_C,
    ).neutronics_material

    SS316 = Material(material_name="SS316").neutronics_material
    copper = Material(material_name="copper").neutronics_material

    mats = openmc.Materials([breeder_material, SS316, copper])
    mats.export_to_xml("materials.xml")

    # GEOMETRY#

    first_wall_inner_surface = openmc.Sphere(r=inner_radius)
    first_wall_outer_surface = openmc.Sphere(r=inner_radius +
                                             firstwall_thickness)
    breeder_blanket_outer_surface = openmc.Sphere(
        r=inner_radius + firstwall_thickness + blanket_thickness)
    vessel_outer_surface = openmc.Sphere(r=inner_radius + firstwall_thickness +
                                         blanket_thickness + 10.,
                                         boundary_type="vacuum")

    inner_void_region = -first_wall_inner_surface
    inner_void_cell = openmc.Cell(region=inner_void_region)
    inner_void_cell.name = "inner_void"

    first_wall_region = (-first_wall_outer_surface & +first_wall_inner_surface)
    first_wall_cell = openmc.Cell(region=first_wall_region)
    first_wall_cell.fill = SS316

    breeder_blanket_region = (+first_wall_outer_surface
                              & -breeder_blanket_outer_surface)
    breeder_blanket_cell = openmc.Cell(region=breeder_blanket_region)
    breeder_blanket_cell.fill = breeder_material

    vessel_region = +breeder_blanket_outer_surface & -vessel_outer_surface
    vessel_cell = openmc.Cell(region=vessel_region)
    vessel_cell.name = "vessel"
    vessel_cell.fill = SS316

    universe = openmc.Universe(cells=[
        inner_void_cell, first_wall_cell, breeder_blanket_cell, vessel_cell
    ])

    geom = openmc.Geometry(universe)

    # SIMULATION SETTINGS#

    sett = openmc.Settings()
    sett.batches = 2  # this is minimum number of batches that will be run
    sett.trigger_active = True
    sett.trigger_max_batches = 2000  # this is maximum number of batches that will be run
    sett.inactive = 0
    sett.particles = 1000
    sett.run_mode = "fixed source"

    source = openmc.Source()
    source.space = openmc.stats.Point((150, 0, 0))
    source.angle = openmc.stats.Isotropic()
    source.energy = openmc.stats.Discrete([14.08e6], [1])
    sett.source = source

    # sett.export_to_xml("settings.xml")

    # tally filters
    particle_filter = openmc.ParticleFilter("neutron")
    cell_filter_breeder = openmc.CellFilter(breeder_blanket_cell)

    # TALLIES#
    tallies = openmc.Tallies()

    tally = openmc.Tally(name="TBR")
    tally.filters = [cell_filter_breeder, particle_filter]
    tally.scores = ["(n,Xt)"]
    tally.triggers = [
        openmc.Trigger(trigger_type='rel_err', threshold=threshold)
    ]  # This stops the simulation if the threshold is meet
    tallies.append(tally)

    # RUN OPENMC #
    model = openmc.model.Model(geom, mats, sett, tallies)
    sp_filename = model.run(output=False)

    # RETRIEVING TALLY RESULTS

    sp = openmc.StatePoint(sp_filename)

    json_output = {
        "enrichment": enrichment,
        "inner_radius": inner_radius,
        "firstwall_thickness": firstwall_thickness,
        "blanket_thickness": blanket_thickness,
        "breeder_material_name": breeder_material_name,
        "temperature_in_C": temperature_in_C,
    }

    tally = sp.get_tally(name="TBR")

    df = tally.get_pandas_dataframe()

    json_output["TBR"] = df["mean"].sum()
    json_output["TBR_std_dev"] = df["std. dev."].sum()

    os.system('rm *.h5')

    return json_output
Пример #4
0
def shield(rad, bool, outer, m_batches, m_error, neutrons):

    #MATERIALS#

    min = 1
    max = outer

    R1 = rad[0]
    R2 = rad[1]

    mats = openmc.Materials()

    tungsten = openmc.Material(name='Tungsten')
    tungsten.set_density('g/cm3', 19.0)
    tungsten.add_element('W', 1.0)
    mats.append(tungsten)

    water = openmc.Material(name='Water')
    water.set_density('g/cm3', 1.0)
    water.add_element('H', 2.0)
    water.add_element('O', 1.0)
    mats.append(water)

    eurofer = openmc.Material(name='EUROFER97')
    eurofer.set_density('g/cm3', 7.75)
    eurofer.add_element('Fe', 89.067, percent_type='wo')
    eurofer.add_element('C', 0.11, percent_type='wo')
    eurofer.add_element('Mn', 0.4, percent_type='wo')
    eurofer.add_element('Cr', 9.0, percent_type='wo')
    eurofer.add_element('Ta', 0.12, percent_type='wo')
    eurofer.add_element('W', 1.1, percent_type='wo')
    eurofer.add_element('N', 0.003, percent_type='wo')
    eurofer.add_element('V', 0.2, percent_type='wo')
    mats.append(eurofer)

    boron = openmc.Material(name='Boron')
    boron.set_density('g/cm3', 2.37)
    boron.add_element('B', 1.0)
    mats.append(boron)

    #GEOMETRY#

    sphere1 = openmc.Sphere(R=min)
    sphere2 = openmc.Sphere(R=R1)
    sphere3 = openmc.Sphere(R=R2)
    sphere4 = openmc.Sphere(R=max)
    sphere5 = openmc.Sphere(R=15)
    sphere6 = openmc.Sphere(R=17, boundary_type='vacuum')

    vac1 = -sphere1
    mat1 = +sphere1 & -sphere2
    mat2 = +sphere2 & -sphere3
    mat3 = +sphere3 & -sphere4
    vac2 = +sphere4 & -sphere5
    steel = +sphere5 & -sphere6
    vac3 = +sphere6

    vacuum1 = openmc.Cell(region=vac1)
    first = openmc.Cell(region=mat1)
    first.fill = tungsten
    second = openmc.Cell(region=mat2)
    second.fill = water
    third = openmc.Cell(region=mat3)
    third.fill = tungsten
    vacuum2 = openmc.Cell(region=vac2)
    vessel = openmc.Cell(region=steel)
    vessel.fill = boron
    vacuum3 = openmc.Cell(region=vac3)

    root = openmc.Universe(cells=(vacuum1, first, second, third, vacuum2,
                                  vessel, vacuum3))
    geom = openmc.Geometry(root)

    #SETTINGS#

    batch = 2
    max_batches = m_batches
    inactive = 1
    particles = neutrons

    source = openmc.Source()
    source.space = openmc.stats.Point((0, 0, 0))
    source.angle = openmc.stats.Isotropic()
    source.energy = openmc.stats.Discrete([14e6], [1])

    sett = openmc.Settings()
    sett.batches = batch
    sett.trigger_active = True
    sett.trigger_max_batches = m_batches
    sett.inactive = inactive
    sett.particles = particles
    sett.output = {'tallies': False}
    sett.run_mode = 'fixed source'
    sett.source = source

    #TALLIES#

    tallies = openmc.Tallies()

    filter = openmc.SurfaceFilter(sphere6)

    tally = openmc.Tally(name='leakage')
    tally.scores = ['current']
    tally.filters = [filter]
    trigger = openmc.Trigger('rel_err', m_error / 100)
    tally.triggers = [trigger]
    tallies.append(tally)

    model = openmc.model.Model(geom, mats, sett, tallies)

    #RUN#

    model.run(output=bool)

    #PLOT#

    #plots = openmc.Plots()

    #plot = openmc.Plot()
    #plot.basis = 'xz'
    #plot.origin = (0, 0, 0)
    #plot.width = (200, 200)
    #plot.pixels = (400, 400)
    #plot.color_by = 'material'
    #plot.colors = {tungsten: 'black', water: 'blue'}
    #plots.append(plot)

    #plots.export_to_xml()

    for i in reversed(range(batch, max_batches + 1)):
        filename = 'statepoint.' + str(i).zfill(len(str(max_batches))) + '.h5'
        if os.path.isfile(filename):
            sp = openmc.StatePoint(filename)
            break

    #print('file:',filename)
    leakage = sp.get_tally(name='leakage')
    leakage_mean = leakage.mean[0][0][0]
    leakage_error = leakage.std_dev[0][0][0]
    #print(leakage_mean)
    #print(leakage_error)

    dir = '/home/emiralle/shield_git'
    for zippath in glob.iglob(os.path.join(dir, '*.h5')):
        os.remove(zippath)

    return leakage_mean * 100, leakage_error * 100
Пример #5
0
root_s = openmc.YPlane(y0=-y_p, boundary_type="reflective", name="YMIN")
root_n = openmc.YPlane(y0=+y_p, boundary_type="reflective", name="YMAX")
if DIMENSIONS <= 2:
    z_p = infinite_p
else:
    z_p = finite_p
root_bot = openmc.ZPlane(z0=-z_p, boundary_type="reflective", name="ZMIN")
root_top = openmc.ZPlane(z0=+z_p, boundary_type="reflective", name="ZMAX")

root_cell.region = +root_w & -root_e & +root_s & -root_n & +root_bot & -root_top
root_cell.fill = cell_universe
root_universe.add_cell(root_cell)
openmc_geometry.root_universe = root_universe

# Do the cross section tallies
trigger_5pcm = openmc.Trigger("std_dev", 5E-5)
lib = mgxs.Library(openmc_geometry)
lib.energy_groups = two_groups
lib.mgxs_types = [
    'total', 'nu-fission', 'transport', 'chi', 'consistent nu-scatter matrix'
]
lib.by_nuclide = False
lib.domain_type = "material"
lib.domains = [uo2, water]
lib.tally_trigger = trigger_5pcm
lib.build_library()
openmc_tallies = openmc.Tallies()
lib.add_to_tallies_file(openmc_tallies)

# Monte Carlo parameters and such
openmc_settings = openmc.Settings()
Пример #6
0
# Instantiate a Plots collection and export to XML
plot_file = openmc.Plots([plot])
plot_file.export_to_xml()

###############################################################################
#                   Exporting to OpenMC tallies.xml file
###############################################################################

# Instantiate a tally mesh
mesh = openmc.RegularMesh(mesh_id=1)
mesh.dimension = [4, 4]
mesh.lower_left = [-2, -2]
mesh.width = [1, 1]

# Instantiate tally Filter
mesh_filter = openmc.MeshFilter(mesh)

# Instantiate tally Trigger
trigger = openmc.Trigger(trigger_type='rel_err', threshold=1E-2)
trigger.scores = ['all']

# Instantiate the Tally
tally = openmc.Tally(tally_id=1)
tally.filters = [mesh_filter]
tally.scores = ['total']
tally.triggers = [trigger]

# Instantiate a Tallies collection and export to XML
tallies_file = openmc.Tallies([tally])
tallies_file.export_to_xml()
Пример #7
0
def shield(rad, major, coil, bool, outer, m_batches, m_error, neutrons):

    #MATERIALS#

    min = coil
    max = outer+coil
    major_rad = major + outer

    R1 = rad[0]
    R2 = rad[1]

    mats = openmc.Materials()

    tungsten = openmc.Material(name='Tungsten carbide')
    tungsten.set_density('g/cm3', 15.63)
    tungsten.add_element('W', 1.0)
    tungsten.add_element('C', 1.0)
    mats.append(tungsten)

    water = openmc.Material(name='Water')
    water.set_density('g/cm3', 1.0)
    water.add_element('H', 2.0)
    water.add_element('O', 1.0)
    mats.append(water)

    copper = openmc.Material(name='Copper')
    copper.set_density('g/cm3', 8.5)
    copper.add_element('Cu', 1.0)
    mats.append(copper)

    eurofer = openmc.Material(name='EUROFER97')
    eurofer.set_density('g/cm3', 7.75)
    eurofer.add_element('Fe', 89.067, percent_type='wo')
    eurofer.add_element('C', 0.11, percent_type='wo')
    eurofer.add_element('Mn', 0.4, percent_type='wo')
    eurofer.add_element('Cr', 9.0, percent_type='wo')
    eurofer.add_element('Ta', 0.12, percent_type='wo')
    eurofer.add_element('W', 1.1, percent_type='wo')
    eurofer.add_element('N', 0.003, percent_type='wo')
    eurofer.add_element('V', 0.2, percent_type='wo')
    mats.append(eurofer)

    #GEOMETRY#

    cylinder = openmc.ZCylinder(R=min)

    shield1 = openmc.ZCylinder(R=R1)
    shield2 = openmc.ZCylinder(R=R2)
    shield3 = openmc.ZCylinder(R=max)
    top = major_rad-(max-min)
    shield_sph1 = openmc.Sphere(R=top)
    shield_sph2 = openmc.Sphere(R=major_rad-(max-min)+(max-R2))
    shield_sph3 = openmc.Sphere(R=major_rad-(max-min)+(max-R2)+(R2-R1))

    pit = sqrt(top**2+top**2)
    max_shield = sqrt(top**2+pit**2)+1

    vessel_in = openmc.Sphere(R=major_rad)
    vessel_out = openmc.Sphere(R=max_shield, boundary_type='vacuum')

    magnet = -cylinder & -vessel_in

    mat1 = -shield1 & +cylinder & -shield_sph3  #work on this
    mat2 = -shield2 & +shield1 & -shield_sph2 #work on this
    mat3 = -shield3 & +shield2 & -shield_sph1 #work on this

    plasma = +shield3 & -shield_sph1

    a = +shield_sph1 & -shield_sph2 & +shield2 #work on this
    b = +shield_sph2 & -shield_sph3 & +shield1 #work on this
    c = +shield_sph3 & -vessel_in & +cylinder #work on this

    vessel = +vessel_in & -vessel_out

    plasma_cell = openmc.Cell(region=plasma) #1

    cop_mag = openmc.Cell(region=magnet) #2
    cop_mag.fill = copper

    tung1 = openmc.Cell(region=mat1) #3
    tung1.fill = tungsten
    wat = openmc.Cell(region=mat2) #4
    wat.fill = water
    tung2 = openmc.Cell(region=mat3) #5
    tung2.fill = tungsten

    ste_ves = openmc.Cell(region=vessel) #6
    ste_ves.fill = eurofer

    tung_sph1 = openmc.Cell(region=a) #7
    tung_sph1.fill = tungsten
    wat_sph = openmc.Cell(region=b) #8
    wat_sph.fill = water
    tung_sph2 = openmc.Cell(region=c) #9
    tung_sph2.fill = tungsten

    root = openmc.Universe(cells=(plasma_cell, cop_mag, tung1, wat, tung2, ste_ves, tung_sph1, wat_sph, tung_sph2))
    geom = openmc.Geometry(root)
    root.plot(width=(600.0, 600.0), basis='xz')

    #SETTINGS#

    batch = 2
    max_batches = m_batches
    inactive = 0
    particles = neutrons

    source = openmc.Source()
    source.space = openmc.stats.Box((-top,-top,-top),(top,top,top))
    source.angle = openmc.stats.Isotropic()
    source.energy = openmc.stats.Discrete([14e6], [1])

    sett = openmc.Settings()
    sett.batches = batch
    sett.trigger_active = True
    sett.trigger_max_batches = m_batches
    sett.inactive = inactive
    sett.particles = particles
    sett.output = {'tallies': True}
    sett.run_mode = 'fixed source'
    sett.source = source

    #PLOT#

    plots = openmc.Plots()

    plot = openmc.Plot()
    #plot.type = 'voxel'
    plot.basis = 'xz'
    plot.origin = (0, 0, 0)
    plot.width = (600, 600)
    plot.pixels = (1000, 1000)
    plot.color_by = 'material'
    plot.colors = {tungsten: 'black', water: 'blue', eurofer: 'grey', copper: 'brown'}
    plots.append(plot)

    plots.export_to_xml()

    #TALLIES#

    tallies = openmc.Tallies()

    filter = openmc.CellFilter(cop_mag)

    tally = openmc.Tally(name='total')
    tally.scores = ['total']
    tally.filters = [filter]
    trigger = openmc.Trigger('rel_err', m_error/100)
    tally.triggers = [trigger]
    tallies.append(tally)

    model = openmc.model.Model(geom, mats, sett, tallies)

    #RUN#

    model.run(output=bool)

    for i in reversed(range(batch,max_batches+1)):
        filename = 'statepoint.' +str(i).zfill(len(str(max_batches)))+ '.h5'
        if os.path.isfile(filename):
            sp = openmc.StatePoint(filename)
            break

    #print('file:',filename)
    leakage = sp.get_tally(name='total')
    leakage_mean = leakage.mean[0][0][0]
    leakage_error = leakage.std_dev[0][0][0]
    #print(leakage_mean)
    #print(leakage_error)

    dir = '/home/emiralle/shield_git'
    for zippath in glob.iglob(os.path.join(dir, '*.h5')):
        os.remove(zippath)

    return leakage_mean, leakage_error
Пример #8
0

openmc_cells = openmc_geometry.get_all_material_cells().values()

xsLib = {}
for cell in openmc_cells:
    xsLib[cell.id] = {}
    xsLib[cell.id]['transport']  = mgxs.TransportXS(    groups=fine_groups)
    xsLib[cell.id]['fission']    = mgxs.FissionXS(      groups=fine_groups)
    xsLib[cell.id]['nu-fission'] = mgxs.FissionXS(      groups=fine_groups, nu=True)
    xsLib[cell.id]['nu-scatter'] = mgxs.ScatterMatrixXS(groups=fine_groups, nu=True)
    xsLib[cell.id]['chi']        = mgxs.Chi(            groups=fine_groups)



tally_trigger = openmc.Trigger('std_dev', 1E-2)

for cell in openmc_cells:
    for mgxs_type in xsLib[cell.id]:
        xsLib[cell.id][mgxs_type].tally_trigger = tally_trigger



tallies_file = openmc.Tallies()

# Iterate over all cells and cross section types
for cell in openmc_cells:
    for rxn_type in xsLib[cell.id]:

        xsLib[cell.id][rxn_type].domain = cell
        xsLib[cell.id][rxn_type].by_nuclide = True
Пример #9
0
def sphere_with_firstwall_model(
        material_for_structure,
        blanket_breeder_material,
        blanket_coolant_material,
        firstwall_coolant_material,
        blanket_breeder_li6_enrichment,  # this is a percentage
        coolant_pressure,  # this is in Pa
        blanket_coolant_temperature_in_C,
        firstwall_coolant_temperature_in_C,
        blanket_breeder_fraction,
        blanket_coolant_fraction,
        blanket_structural_fraction,
        blanket_breeder_temperature_in_C = None, #needed for liquid breeders like lithium lead
        firstwall_thickness = 2.7,  # this is in cm
        blanket_thickness = 200,  # this is in cm
        inner_radius = 1000,
        firstwall_armour_fraction = 0.106305, # equivilent to 3mm and based on https://doi.org/10.1016/j.fusengdes.2017.02.008
        firstwall_coolant_fraction= 0.333507, # based on https://doi.org/10.1016/j.fusengdes.2017.02.008
        firstwall_structural_fraction = 0.560188, # based on https://doi.org/10.1016/j.fusengdes.2017.02.008
        blanket_multipler_material = None, #used for combined breeder multiplier options
        blanket_multiplier_fraction = None, #used for combined breeder multiplier options
        blanket_breeder_material_packing_fraction = None, #used for combined breeder multiplier options
        blanket_multiplier_packing_fraction = None, #used for combined breeder multiplier options
        blanket_multiplier_material = None #used for combined breeder multiplier options
        ):

    breeder_percent_in_breeder_plus_multiplier_ratio = 100 * (blanket_breeder_fraction / (blanket_breeder_fraction + blanket_multiplier_fraction))

    inputs = locals()

    """ 
    This function builds materials for the homogenised blanket material, homogenised firstwall material
    The creates a simple sphere geometry with a simple point source and TBR tally on the blanket
    The function also carries out the simulation and writes the results to a JSON file
    """

    # creates homogensied blanket material using a single breeder / multiplier material (e.g lithium lead)
    if blanket_breeder_material == 'Pb842Li158':
        blanket_material =  MultiMaterial(material_tag = 'blanket_material',
                            materials = [
                                        Material(material_name = material_for_structure),
                                        Material(material_name = blanket_coolant_material,
                                                 temperature_in_C = blanket_coolant_temperature_in_C,
                                                 pressure_in_Pa = coolant_pressure),
                                        Material(material_name = blanket_breeder_material, 
                                                 enrichment = blanket_breeder_li6_enrichment,
                                                 temperature_in_C = blanket_breeder_temperature_in_C),
                                        ],
                            fracs = [blanket_structural_fraction,
                                    blanket_coolant_fraction,
                                    blanket_breeder_fraction],
                            percent_type='vo'
                            ).openmc_material

    # creates homogensied blanket material using a combined breeder multiplier material (e.g lithium ceramic with be multiplier)
    else:

        blanket_material =  MultiMaterial(
                                material_tag = 'blanket_material',
                                materials = [
                                            Material(material_name = material_for_structure),
                                            Material(material_name = blanket_coolant_material,
                                                    temperature_in_C = blanket_coolant_temperature_in_C,
                                                    pressure_in_Pa = coolant_pressure),
                                            Material(material_name = blanket_breeder_material, 
                                                    enrichment = blanket_breeder_li6_enrichment,
                                                    packing_fraction = blanket_breeder_material_packing_fraction),
                                            Material(material_name = blanket_multipler_material,
                                                    packing_fraction = blanket_multiplier_packing_fraction),
                                            ],
                                fracs = [blanket_structural_fraction,
                                        blanket_coolant_fraction,
                                        blanket_breeder_fraction,
                                        blanket_multiplier_fraction],
                                percent_type='vo'
                                ).openmc_material


    # creates homogensied firstwall material with eurofer, tungsten and a coolant
    firstwall_material = MultiMaterial(material_tag = 'firstwall_material',
                                        materials = [
                                            Material(material_name = 'tungsten'),
                                            Material(material_name = firstwall_coolant_material,
                                                        temperature_in_C = firstwall_coolant_temperature_in_C,
                                                        pressure_in_Pa = coolant_pressure),
                                            Material(material_name = 'eurofer')],
                                        fracs = [firstwall_armour_fraction,
                                                 firstwall_coolant_fraction,
                                                 firstwall_structural_fraction]
                                        ).openmc_material

    mats = openmc.Materials([blanket_material, firstwall_material]) 

    # creates surfaces
    breeder_blanket_inner_surface = openmc.Sphere(r=inner_radius+firstwall_thickness)
    firstwall_outer_surface = openmc.Sphere(r=inner_radius)  

    inner_void_region = -firstwall_outer_surface 
    inner_void_cell = openmc.Cell(region=inner_void_region) 
    inner_void_cell.name = 'inner_void'

    firstwall_region = +firstwall_outer_surface & -breeder_blanket_inner_surface 
    firstwall_cell = openmc.Cell(name='firstwall', region=firstwall_region)
    firstwall_cell.fill = firstwall_material

    breeder_blanket_outer_surface = openmc.Sphere(r=inner_radius+firstwall_thickness+blanket_thickness, boundary_type='vacuum')
    breeder_blanket_region = -breeder_blanket_outer_surface & +breeder_blanket_inner_surface
    breeder_blanket_cell = openmc.Cell(name = 'breeder_blanket', region=breeder_blanket_region) 
    breeder_blanket_cell.fill = blanket_material

    universe = openmc.Universe(cells=[inner_void_cell, 
                                      firstwall_cell,
                                      breeder_blanket_cell])

    geom = openmc.Geometry(universe)

    # assigns simulation settings
    sett = openmc.Settings()
    sett.batches = 200  # this is minimum number of batches that will be run
    sett.trigger_active = True
    sett.trigger_max_batches =  1500  # this is maximum number of batches that will be run
    sett.particles = 300
    sett.verbosity = 1
    sett.run_mode = 'fixed source'

    # sets a 14MeV (distributuion) point source
    source = openmc.Source()
    source.space = openmc.stats.Point((0,0,0))
    source.angle = openmc.stats.Isotropic()
    source.energy = openmc.stats.Muir(e0=14080000.0, m_rat=5.0, kt=20000.0) #neutron energy = 14.08MeV, AMU for D + T = 5, temperature is 20KeV
    sett.source = source

    # this is the tally set up
    tallies = openmc.Tallies()

    # define filters
    cell_filter_breeder = openmc.CellFilter(breeder_blanket_cell)
    particle_filter = openmc.ParticleFilter(['neutron'])

    # creates the TBR tally using the filters and sets a completion trigger
    tally = openmc.Tally(name='TBR')
    tally.filters = [cell_filter_breeder, particle_filter]
    tally.scores = ['(n,Xt)'] # where X is a wildcard, if MT 105 or (n,t) then some tritium production will be missed, for example (n,nt) which happens in Li7 would be missed
    tally.triggers = [openmc.Trigger(trigger_type='rel_err', threshold=0.0001)]  # This stops the simulation if the threshold is meet
    tallies.append(tally)

    # collects all the model parts and runs the model
    model = openmc.model.Model(geom, mats, sett, tallies)
    sp_filename = model.run(output=False)

    # opens the output file and retrieves the tally results
    sp = openmc.StatePoint(sp_filename)

    tally = sp.get_tally(name='TBR')

    df = tally.get_pandas_dataframe()

    tally_result = df['mean'].sum()
    tally_std_dev = df['std. dev.'].sum()

    # combines the tally results with the input data
    inputs.update({'tbr': tally_result})
    inputs.update({'tbr_error': tally_std_dev})

    return inputs