Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Differentiate materials in DAGMC universes #3056

Open
wants to merge 69 commits into
base: develop
Choose a base branch
from

Conversation

bam241
Copy link
Contributor

@bam241 bam241 commented Jun 22, 2024

Description

This allows to differentiate materials in DAGMC universe when using the same DAGMC geometry to fill different CG cells

This provides a mechanism to overload material assignment embedded in the DAGMC geometry by providing a dict {ref_mat_name:[mat_instances]}
This allows enrich the Model.differentiate_depletable_material() method from the Python API, to allows automatic differentiation of the depletable materials of a DAGMC geometry inserted multiple times.

Checklist

  • I have performed a self-review of my own code
  • I have run clang-format (version 15) on any C++ source files (if applicable)
  • I have followed the style guidelines for Python source files (if applicable)
  • I have made corresponding changes to the documentation (if applicable)
  • I have added tests that prove my fix is effective or that my feature works (if applicable)

this should address #2923

This work has been sponsored by NAAREA.

@bam241 bam241 marked this pull request as ready for review August 12, 2024 15:30
Copy link
Contributor

@pshriwise pshriwise left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not an easy task @bam241 and I think I see where you're going with it. My main concern with the current implementation is the amount of DAGMC-specific code in higher-level sections of the Python API. I think there's some refactoring we can do to avoid special logic in the Model and (maybe) Geometry classes.

I'd say this is optional for this PR, but now that we have additional DAGMC* classes appearing I wonder if it would be best to move them all into a dagmc.py file in the Python API. I thought doing this in the C++ code was nice as DAGMC constructs have their own special logic to some degree. It would reduce the size of our cell.py and universe.py files as well. I can tackle that afte we finish this PR though. Making an issue to track...

openmc/lib/dagmc.py Outdated Show resolved Hide resolved
openmc/lib/dagmc.py Outdated Show resolved Hide resolved
openmc/model/model.py Outdated Show resolved Hide resolved
openmc/model/model.py Outdated Show resolved Hide resolved
openmc/model/model.py Outdated Show resolved Hide resolved
openmc/universe.py Outdated Show resolved Hide resolved
openmc/universe.py Outdated Show resolved Hide resolved
openmc/universe.py Outdated Show resolved Hide resolved
include/openmc/cell.h Show resolved Hide resolved
openmc/geometry.py Outdated Show resolved Hide resolved
Copy link
Contributor

@pshriwise pshriwise left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Some line comments and a couple of design questions. The main one being how material overrides are handled if applied to multiple cells.

openmc/dagmc.py Outdated Show resolved Hide resolved
openmc/model/model.py Outdated Show resolved Hide resolved
openmc/model/model.py Outdated Show resolved Hide resolved
openmc/model/model.py Outdated Show resolved Hide resolved
openmc/dagmc.py Outdated Show resolved Hide resolved
openmc/dagmc.py Outdated Show resolved Hide resolved
instance_material_overrides.find(mat_str) !=
instance_material_overrides.end()) {

for (auto mat_str_instance :
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A check here that the number of entries in the override dictionary is the same as the cell size would probably be wrothwhile.

What happens if the material override dictionary need to apply to more than one cell with many instances? It appears that the material assignment would start over again at the beginning of the iterable.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this question still stands? If I'm missing something can you point to the response or code change that resolves it?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I might have miss understood you, if so sorry for marking this as resolved.

I added the test before the for loop.
L236-242

If the material overrides apply to multiple cells, that means that those cells shared the same initial material assignement in the same DAGMCgeometry.

I think I see where the problem is, this works to differenciate materials in case of multiple insertion of the same DAGMC Geometry, this does not aim to differenciate assignement of a single material to multiple cells of the same DAGMC Universe.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah exactly. If the multiple DAGMC cells uses the same material and those cells have multiple instances, it isn't clear to which cell the material overrides will apply. It seems as though it would be the same for both cells, resulting in the same material usage for those cells in each use of the DAGMC universe. In the end I don't think this will accomplish material differentiation as desired.

Copy link
Contributor Author

@bam241 bam241 Sep 25, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That was the intended behaviour,
Not to change the number of materials used in a DAGMC geometry but to replace the assigned materials each time the DAGMC is inserted again.

So if two cells share the same material assignment in the h5 file, the overriding material will be apply to both cells.

To go back to the previous loop,
mat_A is assigned to Cell1 and Cell2 that are part of a DAGMC Geometry
so we have:
Cell1.material_[0] = mat_A
Cell2.material_[0] = mat_A

If we insert the DAGMC geometry 3 times and we have a override element such as: mat_A:[mat_A_0, mat_A_1, mat_A_2]

So
Cell1.material_[0] = mat_A_0
Cell1.material_[1] = mat_A_1
Cell1.material_[2] = mat_A_2

Cell2.material_[0] = mat_A_0
Cell2.material_[1] = mat_A_1
Cell2.material_[2] = mat_A_2

The goal was not to change the assignment defined in the DAGMC Geometry, but to differentiate the materials between different occurrence of the same DAGMC Geometry in the simulation

I am happy to discuss if we want to have a different behaviour, but I can see why differentiate material in a way that differentiation of a material assigned to multiple volumes of the DAGMC geometry, could be useful, but it could also be dangerous.

Copy link
Contributor Author

@bam241 bam241 Oct 3, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Personally, I like option a. I know it leaves more room for error if the user makes manual modifications after the call to diff_burnable_mats, but historically the design of OpenMC has favored flexibility in these cases.

When talking about user manual override of the material assignment I was not referring to user manual modification after the call to diff_burnable_mats but simply a user wanting to override some materials of the DAGMC geometry writing manually the DAGMCUniverse.material_overrides or using DAGMCUniverse.add_material_override

I think it is a nice feature to be able to "replace" material from the original DAGMC geometry by mapping the original name with the news materials (for either unique or multiple DAGMC occurrence). It is also nice that it is 100% Python so it does not require to have the openmc.lib enabled.

I also like the "vision" you have, when using diff_burnable_mats to create a mapping between DAGMCCell.id and the materials for each instances of this cell.

IMO, we need to enable both, and find a way to pass that information correctly to the cpp.

Copy link
Contributor Author

@bam241 bam241 Oct 3, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Going back to data structures, what do you think of representing the overrides in a DAGMCCell.fill attribute?

Do you mean when using the diff_burnable_mats ?
because we already write the override in the cell.fill.
For DAGMCCell, it is then used to generate the material_override node in the xml.

As to have find_buranle_mats only works with DAGMCCell when openmc.lib is enable, we could pass back the information directly to the cpp DAGMCCell.
Or add a method to pass it.

Is that what you meant ?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When talking about user manual override of the material assignment I was not referring to user manual modification after the call to diff_burnable_mats but simply a user wanting to override some materials of the DAGMC geometry writing manually the DAGMCUniverse.material_overrides or using DAGMCUniverse.add_material_override

I think it is a nice feature to be able to "replace" material from the original DAGMC geometry by mapping the original name with the news materials (for either unique or multiple DAGMC occurrence).

IMO, we need to enable both, and find a way to pass that information correctly to the cpp.

I think we're in agreement that we can and should support both use cases of material overrides we've outlined above. My main point was that I think we can use the same override data structure (be it with a dict on the DAGMCUniverse or using the DAGMCCell.fill attribute).

It is also nice that it is 100% Python so it does not require to have the openmc.lib enabled.

I don't quite see how we can do this without using the openmc.lib module at some point myself, but you have a way to accomplish this in mind, great!

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you mean when using the diff_burnable_mats ? because we already write the override in the cell.fill. For DAGMCCell, it is then used to generate the material_override node in the xml.

Ah, yeah you're right. I was thinking that if the information is stored on the DAGMCCell objects then we're kind of duplicating it in the material_overrides attribute. So I was wondering if we might just populate the XML element from the DAGMCCell objects during export and not have an attribute on the DAGMCUniverse. However, I'm not sure how one would handle importing an XML file without generating DAGMCCell objects. I think we can look into that further down the line. Not super important at the moment.

As to have find_buranle_mats only works with DAGMCCell when openmc.lib is enable, we could pass back the information directly to the cpp DAGMCCell. Or add a method to pass it.

Is that what you meant ?

This would be kind of nifty, but I don't think we need to worry about it at the moment.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I added a new implementation for this.

basically in the python DAGMCUniverse before generating the xml node for the DAGMCUniverse, one update the override_materials dict with the cell.fill (if the cells have multiple instance and an Iterable fill, i.e. the DAGMCCell is inserted multiple times in the Geometry, and has a different fill for each instance.)

If an override_material has already been set overloading per material name, I decided to keep both.
And on loading the DAGMC geometry (C++) to prioritise the override per cell Id then override per material name then fall back to material assignment as stated in the DAGMC file.

openmc/lib/dagmc.py Outdated Show resolved Hide resolved
openmc/dagmc.py Outdated Show resolved Hide resolved
openmc/dagmc.py Outdated Show resolved Hide resolved
Co-authored-by: Patrick Shriwise <[email protected]>
@pshriwise
Copy link
Contributor

I wanted to note that the ability to differentiate materials in the Model.differentiate_mats without applying material volumes added in this PR might help with those looking to determine the volume of cell instances (albeit in a roundabout way by performing a material volume calculation afterward)

#2367

@bam241
Copy link
Contributor Author

bam241 commented Sep 22, 2024

@pshriwise,
I think I have addressed all your comments.

the only remaining is the reference the materials per id in the override_material dict

Copy link
Contributor

@pshriwise pshriwise left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Another round. Getting closer I think!

include/openmc/capi.h Outdated Show resolved Hide resolved
openmc/dagmc.py Show resolved Hide resolved
openmc/dagmc.py Outdated Show resolved Hide resolved
openmc/dagmc.py Show resolved Hide resolved
openmc/dagmc.py Show resolved Hide resolved
openmc/lib/dagmc.py Show resolved Hide resolved
openmc/universe.py Show resolved Hide resolved
instance_material_overrides.find(mat_str) !=
instance_material_overrides.end()) {

for (auto mat_str_instance :
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this question still stands? If I'm missing something can you point to the response or code change that resolves it?

src/dagmc.cpp Outdated Show resolved Hide resolved
@bam241
Copy link
Contributor Author

bam241 commented Oct 8, 2024

@pshriwise I think I have addressed all your comments.

Copy link
Contributor

@pshriwise pshriwise left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is looking good @bam241! We're getting into the nit-picky phase now.

There are one or two sections that are DAGMC-specific in model.py and I wonder if we can figure out a way to build those into the DAGMC classes. I'll think on it some more, but then it'll fit in pretty seamlessly with native geometry in OpenMC.

@@ -252,12 +252,12 @@ void Cell::to_hdf5(hid_t cell_group) const
// default constructor
CSGCell::CSGCell()
{
geom_type_ = GeometryType::CSG;
geom_type() = GeometryType::CSG;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There are a couple usages of geom_type_ directly in particle.cpp (and perhaps elsewhere). Can you update those lines as well please?

Copy link
Contributor Author

@bam241 bam241 Oct 9, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

changed all geom_type_ call to geom_type()
changed suface.h accordingly

openmc/lib/dagmc.py Show resolved Hide resolved
openmc/model/model.py Outdated Show resolved Hide resolved
openmc/model/model.py Outdated Show resolved Hide resolved
openmc/model/model.py Outdated Show resolved Hide resolved
openmc/cell.py Outdated Show resolved Hide resolved
openmc/dagmc.py Outdated Show resolved Hide resolved
openmc/dagmc.py Outdated Show resolved Hide resolved
f"Material name '{mat_name}' not found in DAGMC file")
cv.check_iterable_type('material objects', overrides, str)

self.material_overrides[mat_name] = overrides
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does this support a single override as well as a list? Might be convenient to support that if one wants to override a material for all of the cell instances.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should allow to override per cell_id and material name

openmc/dagmc.py Outdated
None
"""
for cell in self.cells.values():
if cell.n_instances > 1 and isinstance(cell.fill, Iterable):
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there a reason this is restriced to cells with more than one instance?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

your comment made me thinking :)

You are right, if cell.fill is an Iterable then cell.n_instances has to have more than one instance.

I though about the eventuallity to remove restrictions on Iterable,(and cell.n_instance), but as all DAGMCcells, when sync get their fill property that would me filling the override materials dict with all the fill of all DAGMCcells overridden or not.

@bam241
Copy link
Contributor Author

bam241 commented Oct 11, 2024

@pshriwise I think I addressed your last round of comments.

As I moved the DAGMCUniverse from openmc.universe to openmc.dagmc and shuffled some methods from Universe to UniverseBase ,
in the mean time openmc.universe has been updated on develop,
It is difficult to make sure I didn't miss any update to DAGMCUniverse, Universe and UniverseBase while resolving the conflict.

I would suggest extra caution when reviewing those part, in case I missed any (I have been careful... but I might have missed something) and would ask for as much swiftness as we can have to conclude this (without impacting the quality) to avoid any additional complicated conflict :)

@bam241
Copy link
Contributor Author

bam241 commented Oct 12, 2024

@pshriwise here is an other illustration of the CI inconsistance:
bam241#1

I have a PR with this branch on my fork, the [Python 3.10 (omp=y, mpi=y, dagmc=y, ncrystal=, libmesh=, event= vectfit=)](https://github.com/openmc-dev/openmc/pull/3056#logs) test failed after 6h. while here it worked in 1h

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants