Material Density Variation

I want multiple regions with the same material but different densities. Is there any way to define density within cell definition rather defining new material?

Hi,

You can’t define density within cell definition as you can see rom this documentation,

I am assuming you’re asking since you are assigning the same material with variable densities to correspond with differing material temperatures within the core (ex. fuel rings having significantly varying temps therefore varying densities) therefore want an expedited method of doing this. I would suggest making use of python API within material definition for this, such as this method I use to generate a unique fuel material for every bundle in my CANDU simulation,

for i, code in enumerate(fuel_array, start=14):
     # Create the variable name dynamically by appending the code
     exec(f"Fuel_{code} = openmc.Material({i}, 'Fuel_{code}')")

     #Execute the OpenMC commands for the dynamically created variable
     exec(f"Fuel_{code}.add_element('U', 1.0, enrichment=0.71)")
     exec(f"Fuel_{code}.add_nuclide('O16', 2.0)")
     exec(f"Fuel_{code}.set_density('g/cm3', fuel_dens)")
     exec(f"Fuel_{code}.volume = fuel_volume")
     exec(f"fuel_materials.append(Fuel_{code})")

This takes the fuel array I use and generates the materials dynamically making it easy to make changes, and since I have over 2000 bundles this was required instead of a huge block of code. It also names them depending on the code within the array, though this part you might not require. For you I would place the density regions into the same array and run this command that will create the materials you require.

Assuming 3 densities for fuel of 6.41, 7.2, and 7.6 (these are just examples) the code would look like,

#Create array you will put the materials into later
fuel_materials =
fuel_array = [6.41, 7.2, 7.6]

for i, code in enumerate(fuel_array):
# Create the variable name dynamically by appending the code
exec(f"Fuel_{code} = openmc.Material( ‘Fuel_{code}’)")

     #Execute the OpenMC commands for the dynamically created variable
     exec(f"Fuel_{code}.add_element('U', 1.0, enrichment=0.71)")
     exec(f"Fuel_{code}.add_nuclide('O16', 2.0)")
     exec(f"Fuel_{code}.set_density('g/cm3', {code})")
     exec(f"Fuel_{code}.volume = fuel_volume")
     exec(f"fuel_materials.append(Fuel_{code})")

Then when you are writing your materials.xml it would look something like this,

materials = openmc.Materials([Sheath, Calandria_tube, Pressure_tube, Moderator, Coolant, CO2, Calandria_vessel, Air, Adjuster, Helium, Light_water, AdjusterA] + fuel_materials)

This would only really be required if you were needing a lot of different densities for the same materials, if it was only a few like the example I gave you can easily just repeat the same material code but with densities adjusted. Let me know if you have any questions

Thanks @Jarret . Your script is helpful in generating material card. However, as OpenMc does not define density in cell, I was interested to introduce density through python API within cell .

What purposed do you require to change the material density specifically at the cell level if you don’t mind me asking? You could just modify the materials at the point you are constructing the cells, and just export the materials at the end of your script where you are exporting the geometry and settings xml’s. Another method is continuing the script I showed up above when constructing cells,

for i, code in enumerate(fuel_array):
    exec(f"fuelcell{code} = openmc.Cell(fill=Fuel_{code}, region=-surf_fuel & +back_surf_fuel & -front_surf_fuel)")
    exec(f"fuelcell{code}.temperature = fuel_temp")

# Create clad side cell for each material
    exec(f"clad_sidecell{code} = openmc.Cell(fill=Sheath, region= +surf_fuel & -clad_outside_surface & +back_surf_fuel & -front_surf_fuel)")
    exec(f"clad_sidecell{code}.temperature = clad_temp")

# Create clad back cell for each material
    exec(f"clad_backcell{code} = openmc.Cell(fill=Sheath, region=-clad_outside_surface & -back_surf_fuel & +back_surf_clad)")
    exec(f"clad_backcell{code}.temperature = clad_temp")

# Create clad front cell for each material
    exec(f"clad_frontcell{code} = openmc.Cell(fill=Sheath, region=-clad_outside_surface & +front_surf_fuel & -front_surf_clad)")
    exec(f"clad_frontcell{code}.temperature = clad_temp")

This in combination with the material definition I showed before will have the code define you material with the correct density, and then assign the specific material to the right cell and construct the cell for you. Therefore, in order to change the density of a cell you would modify which of the arrays it is in and it will automatically construct your mat and cell cards. You can continue this throughout the entire code to make it so that all you need to do is adjust the original arrays for it to reconstruct the entire assembly with the varying densities.