 eventually start tallying information. All right, so now we're in a place where we're gonna start working through each of these piece by piece. We're gonna start with our materials. All right, and we're gonna do all this with a Python API and open MC. Just getting my bearings here. So the first thing we'll do is we're gonna define our fuel material. So for short, we're just gonna call this U02, uranium oxide, okay? And we're gonna create an open MC material. We'll go ahead and provide that material name, and we'll just call it our fuel material. Then we'll go ahead and execute that cell. As we mentioned before, this material is automatically going to be assigned an ID. We've created a few materials already inside of this notebook, and so now we're up to material ID five. So we'll just note that. And now that we have this material, we're gonna start constructing a composition for this material. So there is a method on the material, so we're kind of calling this help function on the U02 object that we just created, and there's a method called addNuclide. So this is gonna indicate to us, how do we add a nuclide to our material and include it in the material composition? A number of parameters are required for this. So one is the nuclide string, and so we use what's referred to as the GND format for specifying nuclides in open MC. We find this to be the most human-readable and accessible. Another code you may find what's referred to as the ZAID, so you'll provide the atomic number and the mass number to the code, and you'll see something like what would it be for plutonium or something. It'd be like 239 and then three more digits, right, and some other information if you have metastable states as well. So we find this to be a little bit more accessible than that, because for plutonium 239, it would just be PU 239. So it's your symbol from the periodic table and then the isotope number that you want to work with. And then you'll provide the percentage of the composition and then the basis for that composition, whether it's by atom percent or by weight slash mass percent. And so we'll go ahead and do that here. So I'll create a new cell and we're just going to pull in some rough composition values for our fuel material. So we're going to add, first we'll add U235. We're going to tell it U02 add nuclide U235, uranium 235. And we'll say we're going to be doing this by atom percent, so we'll do 1.49 E minus O2. And then we're going to specify for the last century that this is going to be by atom percent. And then we'll go ahead and add some U238 as well. Sorry, if you're seeing that, just go ahead and click over right, like I am most times. Sometimes that pops up. So U238 and we'll do like 8.268 E minus O2. Again, by atom percent. And then we're also going to provide our oxygen. For that one, we'll do oxygen 16, so just a single isotope here. And our composition value is going to be, let's say 4.695. So these are kind of pre-computed values. Again, not the ones that we're going to be using later on when we do our exercise, but they will suffice for now. So now we'll go ahead and add those to our, execute that cell and add those to our uranium oxide. And then we can look at our material. And now we see that under this nuclides entry, we now have these isotopes present. Next, we're going to be adding a density to our material. So we can again find out what's required for that by doing help, U02, and then look at the set density. So here we see that this function is, or this method is going to require a couple pieces of information. One is going to be the units that our density is in. And we have all of these different options available that we discussed before, as well as the value of that density. So on my U02, I'm going to set the density. We will set our density in kind of a funky unit, the atoms per barn centimeters. And then we're going to set that density value, let's say to like 7.021 e to the minus 0.2. All right. And again, if we want to make sure that that was effective, we can print our material and look and see that the density was in fact set here. All right. We had some other materials that we need to represent in this model. We'll go ahead and create those as well. One of them was steel. So we'll go ahead and create a material. So I'm going to type in steel equals openmc.mat and then I'll just tab to complete that and select material. We'll give this a name and we'll just call it steel. Sometimes names can be more descriptive, like this might be steel in the upper assembly, this might be steel in the duct versus steel in a wire wrap or something like that. But for now, we'll just use this simple definition, or simple name rather. Then we're going to go ahead and add a density to this. So you can do this in either order. You don't have to add nuclides first or add density first. We just need both of those pieces of information to be there to have a valid material composition. We'll go ahead and set the density for this. Again, in atoms per barn centimeter, and we'll do 0.49. Then we're going to need some nuclides for this, for the nuclides we typically see in steel. Let's see, how am I adding these? We've been adding these by nuclides so far. There's another option here to add by element. This is going to tell OpenMC, I would like to add this element to my material, and here's the percentage of the composition that I would like to use for that element. Iron was mentioned. We're going to go ahead and add that one. These are rough composition estimates, but typically steel is, in large part, iron. These aren't necessarily physical, but we'll say something like it's mostly iron. Then we'll add another element. What's another element that's in steel, commonly? Nice, nailed both of them. Carbon. Then we'll just say the remaining composition is going to be carbon. Now we've created steel. Next we're going to be creating a couple more materials. We're going to need some helium for the gap. We'll go ahead and call that HE4. We'll create a material. I'll say its name. We'll call it helium. We'll set the density on this, like so. Here we're just going to say that the density, we're going to use a different option for the density. We're just going to say it's the sum of the nuclides in atom fraction. This is just normalizing our atom fraction that we provided to the nearest, or to one cubic centimeter. What we provide in our atom fractions, this is how many atoms there are per cubic centimeter. This is convenient because we can just set it directly in our material composition. Sometimes this is preferable, but there are a lot of different ways to specify these materials. Has some asked why nuclides are repeated in matte definition properties? It's a great, wait, sorry, which one? One nuclide, I should. Properties. Oh, I see. Yeah, we've somehow added our nuclides multiple times to our uranium. Thank you for catching that. So this was unintended. This was just a mistake. I think I must have executed that cell. Or maybe somebody else is on my notebook and executing these things at the same time, which would be unfortunate. But we'll go ahead and just reset that by creating that material. Yeah, I'm going to expand on that in just a second. Good question. All right, let's see if we got that corrected. Okay. So real quick, because that was kind of strange, I just want to check that, do you want if you might help me out and see if anybody's on this particular URL that I'm on? We should probably get that corrected. I think somebody else is on my machine. Is anybody on that here in the room? Like, if you look at the IP address at the beginning, are you on that URL by chance? Are we all good? All right, I know it's hard to see. Maybe I can write it on the board. I put it in the chat, too. Okay, we found it. It's somebody online. And it's not, yeah, not their fault. That was, if anybody's fault, it's mine. So I'm just going to get them a new URL real quick. Well, I'll have to provide a lunch. Sorry, I have a check. Okay, that was bound to happen just, you know, some probability that was going to happen at some point during one of these. Sorry about the delay. All right, so hopefully we're all kind of at this point where we're going to create our helium. And so since we're providing it as the sum and we're kind of specifying, well, we're providing it as the sum from one. And so our value for this composition is going to be much lower. But also this is helium. So our density composition is just going to be much lower in general than the two previous materials we created, the steel and the uranium. And then finally, we need a coolant. Yes, here. Yes, so this, when you provide the, this value for the density or this units for the density, you don't need to provide a value because you're telling OpenMC to just take the, take the exact values that you're providing for the composition and use those as the number density for the material. So it's not adjusting anymore by a, like a, yeah, a macroscopic density value. It's just summing them all together in that case. I'm just trying to show all the different ways you can create materials. All right, and then for sodium, we'll keep this one simple and we'll do the same thing where we just are going to sum. And then we will add a new client. And here we'll just add sodium 23 with a value of 2.33, minus 0.2. Again, so the density value is a lot higher in this case. The helium we're, yeah, it's just like a very low density helium that's going to be between the fuel pellets and the cladding as we'll see in a little bit. All right, cool. So let's print out some of those materials. In particular, let's take a look at steel and just see what came of that. All right, so you can see the density was automatically computed for us. And there's something else interesting potentially here about this steel, which I may need to recreate other than that, yeah. So what else is maybe notable about the steel composition that we see here based on what we provided it? Maybe most notably, we only provided it one element, but it was expanded into a different set of isotopes for iron in particular. Okay, so now this is kind of where we're going to start getting into the cross-section data. Somebody mentioned that that's going to be part of what's needed for our simulation. That's exactly right. What OpenMC is doing under the hood here is it is configured with a set of cross-sections ahead of time. So in the environment for this Jupiter notebook, there's an environment variable that's pointing it to the right set of cross-section data. You can also configure that in the OpenMC module itself. So if I were to use openMC.config, we can look at what's in that. And here we see that the cross-sections has been set. When you import OpenMC, it brings in that environment variable and populates this value. We could then change this if we wanted to do a different location in our machine with the cross-sections input for OpenMC from the Python module. And I bring this up at this point because the set of isotopes that iron was expanded into is based on the available isotopes in the nuclear data at the time that you added that element. So it's looking at this cross-sections. It's interrogating the path to this cross-section data set and the cross-sections XML to see what isotopes are available. And then based on elements, abundance data, it's then expanding that so that composition that gets expanded according to the relative abundance of each isotope in the element specified as well. So it's a really convenient way and this way we also guarantee that we aren't expanding an element into something we aren't going to be able to represent during our simulation because we know it's part of our nuclear data. So this is kind of a convenience loop that we have going on behind the scenes in OpenMC. So I'm going to show you one of it here in the text. I just want to take one second to talk about S-alpha-beta tables or thermal tables for OpenMC. We're talking about a fast reactor here so we don't need to worry about this in our materials today. We don't have any moderators or anything like that. So what we're specifying so far in this tutorial is free atom cross-sections. So we're treating all the materials as if we have an atom soup and they're not really interacting with each other. And that's very valid for the neutron energies in this particular model. However, if you're working with a thermal reactor, something that has water or heavy water or any kind of moderator, really, including graphite, and you're going to want to specify a set of thermal tables so that you can better describe the cross-sections at lower neutron energies when they are approximately at the same energy as the thermal motion of the bound atoms in a material. And so I just wanted to note that this is how you would do that. If we had a material called water, there's a method that's called add-s-alpha-beta and then there are specifications for the different s-alpha-beta tables available in OpenMC and they typically follow this format roughly where it's something like give me the adjusted cross-section for hydrogen is the one of concern primarily in water and it'll say give me that for hydrogen in H2O for something like carbon and graphite it'll be like C underscore C in graphite. So there's a number of different s-alpha-beta tables that we provide with the cross-sections. Okay, so now we have a set of materials and we're going to talk about how to get these materials from the Python API into an input file that OpenMC will then interpret and use when we execute a run. So to do this, we have a class that will collect materials together and write them out to an XML file or an OpenMC input file. We use this XML input format because we feel like it's a little bit more... We don't encourage people to like stare at these things. They're not... But they are more human readable than the input format for some other codes we feel like. So you can still look at them and kind of interpret them even if you're a relatively new OpenMC user. But still, the Python API is by far the most powerful way to create inputs and so that's why we do it this way. So to create a material collection, note the extra s here we're going to do OpenMC.materials and then we can pass it a collection of materials. So to start, let's go ahead and put our U02 and note that I've put in kind of a square bracket here. So we're going to pass it a list of materials. As U02, let's go ahead and pass it in steel and we'll just start with those two. And now if we look at our materials object, we see we have those two materials as part of that object. Now we're missing a couple and one thing that makes some of the objects in OpenMC really powerful is that we inherit from native Python types and so along with like kind of for free when we write the code we get a lot of methods that you can use on Python lists if you're familiar with those that you can use on this object as well. So that is to say that if we wanted to take our materials and we want to append our other materials that we haven't included yet, in particular HE4, our helium, our sodium, we can do that with these simple commands here. And then if we print our materials object again we'll see that we have our first two materials containing uranium, our fuel, our steel, and then the helium and the sodium as well. So that's kind of how we group these things together. Finally, we want to be able to export this into an input format that OpenMC will read from disk. And we can do that using the export to XML method of this materials collection. So if I execute that and then I go to this file explorer in the upper, it's this like file icon in the upper left side of the screen there and I click on that then I'll see, we now have this file called bit wider, the materials.xml. So if I double click on that, this is what the input file looks like for OpenMC. And while this is relatively, it's possible I should say to interpret this, it's much easier I would say to look at them in the version of Python, in the Python version that we've been using so far. So I'll double click on our notebook to get back to that. And then I just wanted to note that there's a couple convenience functions that are, they are just that, they're convenience functions. There are other ways to generate these materials but we have ways to generate materials very easily in common input formats that you might get them. And it can just make life a lot, a lot more simple. So one of them is creating materials from a chemical formula. So we talked a little bit about water so we'll go ahead and create a water material. So water, we'll give that a name and we'll set the density of that. We'll do this this time in grams for cubic centimeter and water nominally is about one gram per cubic centimeter. Now we need to add our composition and this is where this functionality comes in. So we can tell it to add elements from a formula. And all we need to provide to that is just the formula itself. So we can just tell it this, this formula is just H2O. And then we can go ahead and print that material type if I make a mistake on. Oh, silly. I tried to print material instead of water, sorry. But, so if I go ahead and do this then we can see that we have our elements, they've been expanded into hydrogen one and two, oxygen 16 and 17. And then based on the isotopes, the more common isotopes of each of those elements, we can see that the ratios are what we would expect. The other thing we can do is mix materials really easily. So this is really useful for homogenization. This is something that happens in CEFR in fact where we have to kind of homogenize some material between the wire wraps and the ductwork and we kind of homogenize that into the sodium to be clear. So here's a couple of materials here. Let's try mixing sodium and steel. And we can do that. The pathway to doing this is a little bit different. When we're mixing materials, we don't have a material already and that's why instead of calling this method on an existing material object we're going to call this as a functionality of the material type itself. And so we're going to give this class OpenMC.material and say I'll tell it to mix materials. And then I myself right now don't remember what needs the order of the arguments that needs to go into this and so we're just going to take a look. So an alternative to saying well let's do it this way. So I'm just going to say help openMC.material mix materials. And so now I could not do this on my own because I just don't remember what the requirements are. I can just ask for the help of this method and I can see now that I need to pass it first the materials that I want to mix. Second, the fractions of each material and then how they're going to be combined or the percentage type that the isotopes are going to be represented in at the end. And then I can optionally provide it a name for this brand new material that I've created. So knowing that I'll then do I'll meet that specification and just say the materials I'm going to pass in are sodium well the two that I want to mix I'm going to and then the relative compositions we'll say this thing is going to be mostly sodium and a little bit steel. We'll mix them by atom percentage and provide it a name at the end sorry this line is getting a little bit long. And then we'll print that new material and so here we are we see that we have our same set of isotopes from the steel that we created before and they've they're all roughly in order of magnitude lower than our sodium 23 that we've added in as well which is about what we would expect for this material mixture. So that can be really handy. One thing we're going to do is just take a look real quick at what's inside of this cross-sections file. There's a lot about how OpenMC finds it before so if I'm scrolling up we can see this is how it finds it this is where it is on our system but let's just take a quick look at what is in that cross-sections file. So you can copy these commands in I wouldn't worry too much about it we just want to kind of have this for our own exploration and this information is also in the solution notebook but I just want to give you an idea of what the composition of this cross-sections XML is. So here it's saying this is the isotope that we're looking at and this is essentially kind of a cross-reference of the isotope that we're specifying to the data file on the system and so we're saying for hydrogen one here's the name of the data file so in theory you could generate your own hydrogen one and call it hydrogen one mine and place it into the data directory where this cross-section file is and then update the path here and it will use your new data file and you can do that all through the OpenMC data API as well and then we want to know what particle type we're trying to represent here so that we get the reactions we expect and the data that we expect needed to model those reactions and then this goes all the way down through the list of isotopes So really this file is just a manifest connecting an isotope name to the data file that can have an arbitrary name One last, oh yeah question? How you might what? Oh yeah, that's a good question The question was how can we take the nuclear data library and manipulate it or change it and then use it in OpenMC So that's kind of a whole topic in and of itself also There is a data API in OpenMC So if I go down here or we just look at OpenMC.data We have a whole bunch of information for handling ACE files, looking at the angle distribution energy distributions Let's see if we can try to find some of the more higher level stuff So we can look at doing things like working with the data library as well So you can import these things using the data API You can import them from ACE files or from the OpenMC data itself and that's where you can make changes to it and then re-export that data library. Is that helpful? Yeah Yeah, that's a good question So essentially the question was about temperature treatment and in particular Doppler broadening OpenMC has a couple different ways to handle temperature treatment We'll talk about this a little bit later but just briefly right now it can take temperature values from the cross-section data and either use the nearest temperature value or it will interpolate between two temperature values to capture the Doppler broadening It also has a more advanced technique for handling Doppler broadening which is called the window-multipole format and so this does on-the-fly Doppler broadening for a specific temperature so there's no interpolation involved in this technique since the true Doppler broadening based on atomic models that was developed recently by MIT but OpenMC supports that currently so you can do on-the-fly Doppler broadening as well Let's do a quick example about creating a material So we'll call this uranium call it this material name, fuel So this will just be a temporary material that we use This is mainly to highlight the enrichment capability in OpenMC So if we were to add element and look at well, yeah, let's take a look at that So we're going to do help openMC.material.addElement and if we look at this we'll see there's a number of different parameters we've used this method before in fact and so we can see we've passed it the element the percent and then the percent type options here, one being the enrichment So based on that natural abundance data that we have in OpenMC for different elements it can then take that and modify it so that you get an enriched version of the material that you're dealing with and so you can say you can also specify what target you'd like to use so if I wanted to enrich water or something like that you could also do that as well if you get heavy water or something for specific enrichment of H2 then you could do that too Inon asked, could you please repeat the cross-section part again so he missed to add the cross-section file so you mean about the how to add the cross-section file just above maybe this part yeah, sorry I wish I would have left that in the proper notebook or in the tutorial notebook let's see, I can copy that into the chat sorry about that, I meant to leave that in the tutorial so that we wouldn't have to all write that but I just copied it into the chat on the zoom, I hope that's helpful okay, so we're going to add this element, it's just going to be uranium so it'll expand it into all the isotopes we have the composition value is going to be let's say 100% in this case and then the type will be an atom fraction and we'll say the enrichment the 3% oh, I missed a comma okay, so u it's going to be 100% uranium we're going to do this by atom fraction and then we will do our enrichment we'll say 3 and then we'll specify the enrichment target as u235 unsurprisingly and then we'll print that oh, I messed up on my syntax again oh, I have an extra period here so, I made a mistake I have 1.0 here and then I have an extra dot at the end so we'll go ahead and get rid of that oh, right, right, right I chose a poor example, sorry so in particular we don't need to provide an enrichment target for this particular case for uranium because we expect it to be u235 and so we see the slightly elevated value of u235 here in comparison to u238 okay, this is a good time to take a minute or two to pause and ask any questions before we get into our next section which is going to be defining geometry are there any questions I know that's a lot there's quite a bit to defining materials there's a lot to explore there but I'm hoping that what we have is going forward and I think the main things to to try to take away from some of the material we've learned is how to get more information from an object using these help methods and exploring them the other one that we've talked about was doing openMC.material and then just doing a dot at the end and using tab-complete to see like, oh, well this is how I add a macroscopic cross-section exploring that to see, oh, this is the ability to clone a material what does that do and just find your own way kind of through the API that's really what we're trying to empower you with today there's one question can you please repeat about specifying enrichment over u235 just yeah sure so for u235 there's a special treatment so I'll try to reproduce that error that I had so the there's a special procedure for this we have a driver for uranium in general we kind of have made an assumption in openMC that when you're enriching your uranium element that you're going to be doing with u235 and there's a lot more that goes into that because the the masses are so close together relative to enriching something like hydrogen and water or lithium or something like that the masses are very different and so it's very easy to get the enrichment very accurate but with uranium it's slightly more difficult so there's a special procedure implemented in openMC to take care of that okay so now we have a set of materials and let's just kind of like take stock of what we have create a new cell and we'll just print our materials collection so thanks for taking that little side trip on different ways to create materials with me and now we'll kind of just review what we have in our materials collection we have our fuel, steel, helium and sodium we have our compositions all set and our densities all ready to go so that kind of checks first box here we have our materials, we've talked about our cross section data and now we're going to move on to creating the geometry where we can apply those materials so there's some really fun features here this might be like my favorite part of interacting and building an openMC model with the python API because it just gives you feedback as you're building it in an environment like this so a little bit about the geometry type the native geometry type in openMC we use constructive solid geometry so what that refers to is a geometry type where you define surfaces and then, so for example we can define surfaces like planes cylinders, spheres all the way up to more complex shapes like tori and general quadratic surfaces as well so if you wanted like a hyperbolic cylinder or something like that you could also define that if you wanted to generally though, for reactor geometries we're looking at more simple constructs I think I'm kind of limited in my space that I have to work with so the way that CSG generally works is we can define a set of surfaces and then we can define 3D space or regions in our model using different sides of those surfaces so for example if we had something like a plane that cuts through kind of just the center of our model we could define a cylinder as well like this a lot of surfaces unless they are self specified closed surfaces like a sphere they're assumed to be infinite in openMC modeling so this cylinder that I have here is assumed to be infinite into the board alright, same with this plane it goes on forever we can define 3D spaces by taking half spaces of this and then combining them together so for example if I wanted to model this half of the of the like this section then I would say that I'm on the positive side of this surface and I am on the inside or the negative side of this cylinder and that's how you would get this space now if I wanted to model everything over here let's say everything outside of the cylinder and on the negative side of this plane it would be the intersection of the negative side of the plane and the outside of the cylinder okay, so just kind of a basic or a crash course I guess in CSG geometry I think it will become even more clear as we go using the Python API so as I mentioned we have surfaces and then we can take these surfaces and build them into half spaces and then finally the 3D region is comprised of these half spaces so you can do these with intersections are probably the most common you can also do them with unions so we can define a region that is both the space on the negative side of the plane and outside the cylinder so you can create these really complex regions but we'll keep it relatively simple today and we should be able to explore how those work as we go another big component to OpenMC and a different to our surfaces our half spaces and regions is the cell and really the cell is just a way of tying a 3D space to a material or a universe or a lattice or some other geometric constructs inside of that 3D space so those are kind of the options like a cell will specify inside of this space is a material or there's more geometry that we're going to specify alright so let's just try messing around with some of these objects so first we're going to create a sphere we'll keep it simple so we'll just create a unit sphere and again if I were to not know anything about OpenMC I could just say like oh I wonder if there's a sphere object so I could start typing it and hit tab and we'll have more information about that as needed the sphere class takes a bunch of information optionally takes a bunch of information but to keep it simple we can just allow the sphere by default it's at the origin and we can provide it with a radius of of 1 sorry by default it has a radius of 1 and then there's some other arguments that can go into it that we'll talk about a little bit more as we go through this okay here we go so we'll go ahead and create a sphere with a radius of 1 and then we'll specify other pieces of information on surfaces that can be important as boundary types by default OpenMC surfaces have a transmission boundary type meaning that particles are just going to pass through it into the other side whatever may be on the other side of that surface whether it's a material or more geometry etc and then like most objects we can then print this and so we'll see that this surface we can look at the coefficients of this surface its boundary type what type the object itself is and then we'll also note here that just like materials this surface object was assigned an ID so now we have a surface we can start specifying regions or half spaces with this and so we can specify a region that's the inside of the sphere just by saying using the plus or minus operators in python and then the name of that surface so if we look at this once we've created it we'll see that we've created the inside of the sphere and then we can look at the type and see that that's now a half space okay we can also interrogate our region pretty cleanly within the python api to make sure that the region we've created we think we've created is the one that we've actually created so we can do things like is the point 0, 0, 0 the inside of the sphere what do we expect to see as a result is true then can somebody give me a point outside of the sphere there are lots of them right say 2, 3, 0 and that point is not inside the sphere now we can define the outside of the sphere in a similar manner by saying that it's the positive side of that sphere and then if we were to do the same thing to check to see if the point 2, 3, 0 and x, y, z if that's in the outside of the sphere region and so here we are, true enough right so we kind of have a basis for how to create regions using one surface so now we can look at how to combine the sides of multiple surfaces into regions and what we'll do to do that we're just going to try to model the top hemisphere of this sphere so we're going to create a z plane and again if I were to not know anything about open MC I could start looking through this and start seeing like oh do we have a z oh yeah we have a z cone cylinder so we can do a z oriented torus but for this purpose we want to do a z plane so that tab completes really powerful again just reiterating that and so for this we're just going to specify z equals 0 the argument's a little bit different so I'll use my help function and it just wants me to use a slightly different argument name here so if I look at what it's asking for it's looking for z, 0 instead of what I provided we'll get our z plane and then we're going to define what we'll call the northern hemisphere so knowing what we know now about surfaces how would we define this region so we need to take two parts so one part so let's just start with like the sphere which side of the sphere do we want to use the inside and then to combine that with a different region we're going to use this operator which is the and so we're taking things that are the inside of the sphere and it's going to be on what side of the z plane plus, yeah, great okay so we've created that region and now we can see that if we did a point like 0, 0, 0.5 is that in our northern sorry hemisphere that's true value and do a value below the z axis that points now not in the northern hemisphere for a lot of regions in OpenMC we can define bounding boxes really clearly for this also this can be useful if you wanted to say define a source that only occurs in a specific region in the model you can get that bounding box and supply it to OpenMC to sample points within that box and those are available on these objects as just an attribute of the region so if I just type in northern hemisphere bounding box and I execute it it's going to give me a bounding box and it tells me that the lower left of this in x, y is negative 1, negative 1 and 0 for the z plane and then it goes all the way up to 1, 1, 1 as I mentioned before there's a whole slew or a bunch of different surfaces available in OpenMC here's a list of most of them but there's a full list available in the link in the notebook as well we talked a little bit about boundary conditions there are a number of different boundary conditions you can apply in OpenMC if your vacuum boundary condition where particles cross that surface they'll be terminated meaning that they've left the problem domain reflective they can do periodic as well so if you had something like an asymmetric region that you wanted to model with planar boundaries you could do that and then a white boundary condition also for kind of a noisy boundary condition alright, so we mentioned a little bit that we let's see, boundary type, sphere, vacuum good, good and we can change those after the fact I just wanted to add in my notes to just note this again that we have this sphere object and that we can change the boundary type even after we've created it we specified it originally as transmission which is the default boundary type but we can change that to vacuum as well and we can tell or confirm to ourselves that that has changed just by looking here then let's see we can start talking a little bit about cells so again OpenMC's cells are really just a way to tie these 3D regions to a material for now we'll just say that's what they'll do and we can create a cell without any information and we'll just look at what comes of that so the cells created some other cells prior just for experimentation when we were learning about OpenMC objects and so here we see that this cell's ID has been automatically assigned to 4, the fill of this cell that would be the material or a universe that we'll learn about later has not been set the region has not been set either you can also rotate the contents of a cell and you can translate the contents of a cell also and then the volume property that we talked about with materials is very similar in that it won't be set until we perform a volume calculation or specify it manually because you can set those values manually is there a question? that's a really good question so the question was we can rotate and translate cells as we see here but can we scale contents within cells? and the answer is no we cannot currently do that it would be a really interesting feature to add and that brought up another point in my mind that I should mention that all of the units of geometry and OpenMC are in centimeters so everything we're dealing with here is in centimeters so now let's go ahead and create a cell and set the fill of this cell so now we're going to set it to steel so this cell in OpenMC will be filled to steel and we'll set the region as well to our northern hemisphere and we'll just print the cell to ensure to reassure ourselves that those things have been applied so now this fill is going to be filled with material 13 and it contains this region so this region specification is based on the surface IDs so this is the most human readable thing to be honest but it confirms to us that we have set the region of this cell so we've now built up some knowledge of how to construct surfaces how to specify 3D regions and then apply them to a cell which is a primitive geometric object in OpenMC now we're going to kind of do the final part of creating a geometry this is a really basic geometry and that is to put that cell into what's called a universe so a universe in OpenMC is essentially just a collection of geometry that can be used and reused in different places in the geometry model this is really useful to us in the Monte Carlo world because I'll just note so far that I haven't really talked about meshing or anything like we've done in the open foam tutorial that we had yesterday we're representing all of these pieces of information as analytic geometry objects so to specify for a 17 by 17 like assembly each individual set of cells and their translated values etc etc and then to do that for an entire core is sort of untenable and so what we do is we kind of collect these things into unit cells that we can then reproduce regularly throughout the geometry and that's where these universes come in really handy we'll do some work with that later on as we get closer to modeling the EFR assembly so really all we need to know for now is that universes are required for an OpenMC geometry we need to have one root universe we call it like at the top of the geometry and they're just a collection of cells and so we can go ahead and create one of these and again similar to other things I can just type even just the first letter and see what comes up and I can start looking around and see oh yeah there's a universe class here for OpenMC and then I can provide at the cell that we've created above and I can do that in a list oh maybe I need to specify cells I could also use the add cell method I won't do help on this to insert a whole bunch of text but that is also another option or I could use the add cells if I have multiple cells that I want add to this universe after the fact so I could create this and specify an initial set of cells to provide to the universe and then create more later on and add them in as I go but here we already have them in place so now that I have those there's a lot of really nice this is where I think the interactive capabilities for plotting come into play and they really demonstrate the power of the ability to interactively engage with and interrogate this model so the plot the universe as an OpenMC can be plotted directly within a notebook you can do this from a Python interpreter and save an image and things like that so here we'll be using it in the notebook to get information on what these geometric regions look like back almost instantaneously so a little bit of info on what goes into these so first we need to specify some information for the bounds of the view that we're taking of this model like the origin of the view how wide it is in terms of the geometric units so how many centimeters by how many centimeters the number of pixels we would like this image to have the basis so we can currently do axis align slices of the geometry using this method we can't really do much off axis right now and then how we want to color this and we can also provide a set of colors so that we color different pieces of the domain or different cells with a specific color if we prefer which can be really useful for figure generation if you're doing a publication so here we know that we have a sphere with radius one so we're going to set our width in terms of geometric units to just two by two and then that's really all we should need to provide for it to plot this and it might take a second but here we are so the ability to do the point interrogation is this point inside of this region is that point inside of this region is convenient for a good spot check but I think this is really the way to go if you want to interrogate your geometry in more of an intuitive fashion there's a one question sounds like there's a question online to the coordinates of the main universe sub universes all share the same coordinate of the real one that's a good question, no they do not so if you are moving into a cell that is filled with a replicated geometry when the particles move into the lower into that universe inside the cell they're going to be, it's all going to be translated to the local coordinates of that universe that's a good question alright, so we have this image of our region that we've created and we see that we see a full cylinder, or sorry, a full sphere because we're looking at it with an x, y basis a radius of one would go from negative one to one diameter of one would be from negative point five to point five it does look a little short doesn't it that's odd yeah you can do 3D plots with openMC but it's more complicated than what we're going to look at today I can send you some documentation on that that is strange, I think that's a scaling issue with a plot I'll take a look at that and the break and see what's going on okay, cool so, whoops I misspelled universe so to see some of the features sorry I'm just, now my brain's stuck on this, it's so weird because here it looks correct so to see some of the features of this region that we've created, we can change the basis of the slice, so here we're looking by default at an x, y slice because we took this this slice through the z plane we're going to see the full sphere but here if we do this with a basis of xz then we'll see this northern hemisphere cool, alright so if we have a particular fondness for certain colors, for certain materials I know some people feel like air should have a certain color in your models and so on and so forth we can specify those as well and so just to provide an example of that we're going to create a dictionary so one of these objects that we saw before in the introduction to this work and we're going to provide the key on the left side of ours delimiter, the colon and then we're going to provide on the other side, we can provide it different options here we can provide it the name of a color so I think fuchsia but I think we need to specify that you can specify it by name that's cool so you can specify a color by name or by the RGB value, so whatever that would be for fuchsia, I really don't know offhand but gray gray would be something like 75, 75, 75 so if we have a dictionary of colors kind of telling us that we want this cell to be this color and then we hand it to the plot method we can tell it the width we'll say the basis should still be in the XZ and then we'll say the colors are going to be the colors that we provided above I didn't think fuchsia was a valid color I'm not sure why that's in there, that's so weird so we're going to change to a different color can somebody shout out a color that they'd like this cell to be red? okay there are two reds at the same time that's like some crazy psychological thing so if we specify that we can do it this way we could also have specified this by RGB value so if we did like 255, 00 we'd see that's red as well alright so for our pin cell geometry that kind of wraps up our geometry discussion for now and we'll go ahead and move on to modeling the pin cell geometry and hopefully running a simulation before we go off to get some lunch here but before I dive into the final parts of modeling this exact pin cell, are there any questions? can I control the increment of the plot scale? I don't quite understand the question the plot scale you can make it larger so if I were to take this and say instead of the default pixel size which I think is like 200 by 200 maybe and increase that to 800 or yeah 600 by 600 instead then we get a much larger image so I hope that's what they meant any questions in the room? okay cool so back to this we talked about our geometry a little bit everybody follows you can who follows exactly I mean who completed all the exercises and who was not able to stop somewhere stopped along the way a few so we'll go ahead and move forward to model this pin cell geometry so if you got the materials created from the geometry section or any of the others so far this is a good time to maybe try to pick up from here because everything we're doing should be new in terms of the geometry from this point forward all the information we're creating is new not the concepts okay so we're going to need a little bit of information about the different surfaces we're going to create for our pin cell here there's going to be the inner surface there's a hole through the middle of the fuel in these geometries so this is where some helium is going to flow there's an outer surface of the fuel so the fuel pellets are annular and then there's a gap and then an inner surface of the cladding the steel cladding that we're going to use here and then the outer surface of the cladding so that's going to kind of comprise all the surfaces that we need to model the pin cell yes yeah yeah this is just but this is just the the enriched fuel section okay so we're going to create those surfaces let's see so the fuel hole radius we're going to call a z-cylinder and that has a size of 0.08 020 okay I spelled that incorrectly it's not hole, it's hole fuel hole radius let's see and we call this the fuel outer radius and that one is 0.25565 all these values are up at the top by the way I believe up here so we need to reference them up here even though I have a typo in one of them and then the next one is going to be the cladding inner radius 2 so that one is 0.27112 and the last one is the outer cladding radius 0.34 030 sorry thank you 0.30499 okay so according to the TCS spec these are the dimensions of our surfaces alright so now we need to create different regions for this so we're going to say that the hole region so the inner hole region is just going to be well oh wait did everybody get this typed in because this could take a second I don't want people to fall behind at this point so just you know I'll give it a minute or two here for everybody to type this in we'll move forward but this will be on the screen for a little bit so then for the hole region it's just going to be the inside for the fuel hole radius for the fuel itself the fuel region it's going to be the outside of the fuel hole radius and the inside of the fuel's outer radius and then we're going to have this gap the gap region is going to be the outside of what somebody give me a give me a shout out thank you fuel outer radius and then the inside of the cladding inner radius okay so we're kind of building up these annular sections and we'll plot them soon so we can make sure we've done this right and then we'll have the cladding region which is going to be the outside of the inner cladding radius oh sorry and the inside of the outer radius and then finally so we have all these regions we have the outside of the fuel we have a gap I guess this would be the inside of the cladding the outside of the cladding so we have our hole that's just the inside of this first surface the fuel which is going to be the outside of the first surface outside of that hole radius and the inside of the fuel radius and then we have our gap so it's going to be the outside of the fuel inside of the cladding this is a disproportionate gap is very, very small. And then finally, we have our steel cladding, which is going to be the outside of the inner cladding radius and the inside of the outer cladding radius. So we're just creating these annular kind of sections as we go out. And then finally, we need something out here. Is there a question? OK. So finally, we need somewhere out here that's going to be our sodium. We need coolant and a reactor. So we needed to find that region as well. So we'll define a coolant region that is the cladding that is the outside of our outer radius. So everything outside of there is just going to be coolant for now. And then so because we want to create a some kind of finite bounded model that we can simulate, we're going to add some planes. So we're going to add a y plane on top and bottom and an x plane to the left and the right of this. OK. So let's go ahead and do that. We'll just call the first one the top. It's going to be a y plane at y0 equals. So this means the y intercept of this plane is, yeah, based on the pitch of the model, which is 0.695. If I recall correctly, right. OK, so a little bit on the pitch. So this dimensions of where these planes lie is going to be based on the pitch of the pin cells in the reactor. So the pitch refers to have a lattice of cells, just the space. And so to model this, we want it to be in total the distance. So if our origin's here, then we need our intercept for the y planes to be half of the pitch, right, because we've only gone halfway across this pitch distance. So we can just do that by specifying that this is the pitch over 2. And then for the bottom, it's just going to be the negative of that. This looks for the square geometry, not for hexagonal. That's correct, yeah. But you model like you. Yeah, we're just modeling as if this were an rectangular lattice. That's a good point, Vladimir. But in the true CEFR, it's in a hexagonal lattice, and we'll talk about that a little bit later today. So then we'll create a x plane on the left side. This will be pitch over 2, x plane, x 0. And that's going to be pitch over 2, positive. OK, so because this is going to be the boundary of our problem, we need to apply boundary conditions. And in fact, open MC currently won't run unless you've supplied boundary conditions that are non-transmission of some kind, because essentially particles would have no way of being terminated in a valid way. They would either exit the geometry entirely and just go on off into infinity, or they would bounce around in the geometry forever. So those are both not really valid ways to handle particle termination. So we need to supply boundary conditions. And in this case, we're going to do a reflective boundary condition on all of these planes so that this is going to be modeled as a pin cell in an infinite sea of pin cells. So we can set the boundary conditions on these surfaces all in one go in a really easy way, thanks to being able to model this in Python. So we'll say for surface in this list of surfaces that we'll supply, our top, the left, I'll do top, bottom, left, and right, we're going to set that surface's boundary condition for boundary type. Try to get this word right. We only say de de de de de de de de de de. Reluctive. OK? Now for our coolant region, so far, what we have here is we initially said it was just going to be the outside of the cladding. And now we want to bound that with these four planes that we've added as well to complete our 2D version of this pin cell. So we want to be on the lower side of our top plane, so coming down. We want to be on the upper side of the bottom plane, so the positive side of the bottom plane. We want to be on the positive side of the left plane, we want to be on the negative side of the right plane. And then when we combine that with being outside of the cladding outer radius, we should have the region that we're looking for. Now we're going to go ahead and construct the cells that we need for this. So there's going to be a few to model. So first we'll start with the fuel hole. And to keep things kind of succinct, we can specify the region for this as part of the creation of this cell. And so we can call that the whole region. And we can say that the fill in that region is going to be our helium. We are going to have the fuel itself. The region for that is going to be the fuel region. The fill is going to be our uranium oxide material from before. We're going to have the gap cell, which is a cell region, is the gap region, gap region. And that is also going to be filled with our helium. We'll then have the cladding cell region. And that's going to be filled with our steel. Whole region is not defined. That's odd. OK, I must have, oh, I think I made an error here. And I, again, typed this as hold. But it should have been whole. So a little syntax error for me to fix in this section here. But hopefully that didn't happen to you. Let's see. And then we need our coolant cell. So that's going to be openMC.cell. Excuse me. Just fuel is everything that potentially can react with needles, right? Like, gap helium? Everything can potentially react with neutrons, yes. And sodium, is exception? Sodium's the exception? I mean, like, coolant fuel, what is the difference like between coolant fuel hole, fuel cell, gap cell, clad cell? Why not coolant cell? Oh, I'm doing the coolant cell right now. Did I miss something? I mean, like, fuel hole, fuel cell. Maybe it'll become more clear when we plot it. I'll check in with you when we plot it. So for the coolant cell, we'll use the coolant region. And then we'll fill that with our sodium material. So now we'll go ahead and assign this to a universe. We'll call this the root universe of our geometry. And we'll do this just using a slightly different approach to what we did before for adding cells. So we'll go ahead and create the universe. And then we can just say add cells. And then the cells that we want to add are the fuel hole. Yeah, I keep making that same type of fuel cell. The gap cell, oops, and the cladding cell. And then finally, our coolant cell. Oh, I forgot to close the parentheses at the end here on this call. So now we can print this root universe. And we see that we have a CSG geometry that contains cells 5, 6, 7, 8, and 9. And then we can plot this also. So if we do a plot, if we just do this, I believe OpenMC will try to figure out the bounding box of your geometry. So since we've set up our geometry with planes on all sides, it's very easy for OpenMC to figure out how to bound the plot of our model. And so I didn't need to pass anything in particular to this plotting function. But when I did so, when I executed that plotting method, it gave us this image. So hopefully if you do the same, you'll see the same image. I'll try to keep that on screen so people can reference it. The coolant cell, this one. So finally, now that we have a root universe, we can specify a geometry object in OpenMC. So this object doesn't do anything particularly special, but it just helps us manage the input and output of this geometry to file. There's a couple of convenience methods in it as well. So for this, I'm just gonna provide it the root universe, and then we'll have this geometry. And similar to our materials object, is our collection of materials to help us export to our input file. We can do the same with this geometry object and export it to an XML file as well. And so once we've done those couple of steps, if we go back to our file explorer briefly, then we should be able to see, yes, a geometry XML file that contains all this information, but of course in a format that's a little bit harder to interpret than just being able to plot it in the Python interpreter. So I'll double click on my notebook to go back. And now we're really close to just being able to run our first OpenMC simulation. So let's try to get there in the next five minutes or so and we can all go eat. There's one question. The root universe is the real universe? The universe, root universe is the real universe? I don't know, I'm not sure how to address that. The root universe is the real universe. Maybe, could you ask them to elaborate a little bit and then I can answer maybe before we go to lunch. So we did geometry. We've done materials and now we need settings. So the two things that were mentioned, which were spot on were the source and the number of particle batches that we want to run, okay? Tally's we'll get to a little bit later this afternoon, but for now to like the critical pieces that you need for to run OpenMC in Eigenvalue mode are the materials, the geometry and some settings. So real briefly we're going to talk about the starting source. For Eigenvalue problems, the starting source is somewhat arbitrary, but it can help you get to a converged vision source faster if you make a good guess. For a pencil problem like this, it's relatively easy. We're just gonna need to specify a spatial source term. And so we can do that by specifying a spatial distribution using the OpenMC stats module. Inside of the stats there are a whole bunch of different distributions that you can use in energy and space. There's max, for example, in energy, there's Maxwell distributions, there's angular distributions for azimuthal, for any kind of polar distributions you might want, things like this. And you can combine those all together to make sources, but in our case, we're gonna do like a relatively simple spatial term for our source, which is just saying that we need to sample neutrons at this particular location in space. And so we'll start them at a point of zero, zero, 0.1, because remember we have this hole here. And the idea is that we wanna sample neutrons in the fissionable material. So once we've created this spatial distribution, we can then create a source. So we can create this thing that's called an independent source. So an independent source just meaning that we have distributions that are independent in angle, energy, and space. They're not cross-correlated in any way. That's just what the independent means there. And then we can specify the spatial distribution just by passing that object that we've created into the independent source. Okay, so source for, at least for I-Gid value simulations, pretty straightforward to handle. And if you don't supply one of these, that should be clear. If you don't supply one of these in OpenMC, it will by default just try to source neutrons at the origin of the problem, and then converge a fission source. We wanna kind of modify R as just a little bit because we have this hole in the center of the pin cell. So finally, we can create a settings object. Oops. And this is gonna allow us to specify a whole bunch of different information in OpenMC. This is where all the bells and whistles are for OpenMC. And so if I look at the setting, there's a whole bunch of different values that I can set. And that's gonna modify the physics behavior, the tallies, what types of particles are enabled in the simulation, and what type of physics treatments we're using potentially. But for the purposes of the next couple of minutes here, we just need a few pieces of information. So one, we need to apply our source term. And we can do that just as simply as saying, the setting source is gonna be the source object that we created above. We need to tell it how many batches of particles we'd like to run. For our purposes, we're just gonna run 50 batches. How many of those batches are going to be our inactive batches or the batches where we're just running things to converge a fission source for the remaining batches? Let's say we're gonna run 10 inactive batches. And then how many particles we're gonna run for each batch of the simulation? And for our purposes, we're just gonna do 1,000 particles. So we get a relatively quick run. These parameters, there's a lot of knowledge that needs to go behind these that are just problem dependent. For a pencil problem, it's relatively straightforward. Then we can go ahead and export our settings. And since I'm still in the file explorer over here, I can see that this created a settings XML file that OpenMC will look at and interpret. Okay, so at this point, we now have the input files required that we've talked about before. We have our geometry, our materials, our settings. And we are ready to run an OpenMC calculation. There's a section here on temperature treatment. I'm gonna move past it for now and we'll pick it up after lunch because I'd like us to just get to an OpenMC run. And we can do that from the Python interpreter just as simply as calling OpenMC run. And so what this is doing under the hood, if you're more familiar with Linux, is it's just gonna look at the environment and find the OpenMC executable and run it using the inputs in the same directory we're currently in right now. There are two questions. One is the previous one, the some said the real universe, that one that will be calculated is the same with the root universe. Yes, yeah, that's correct. Thank you. Thank you for clarifying in the chat. Appreciate it, but yes, that's right. It's the real universe that's going to be simulated. And the other question is what is the use of inactive batches? Inactive batches, so the inactive batches are the sets of particles that we run to figure out what the fission source looks like in these types of calculation for the active batches or the remaining set of batches. Okay, I'm just gonna walk through the output from our first, hopefully our first OpenMC simulation and then we can break. So here we see the header. This just gives us some information about OpenMC. Some of it can be very useful for reproducibility such as the commit hash from the last piece of information that was added to OpenMC. The parallelism, so if we were running with MPI, distributed memory parallelism, we would see an entry for that, but here we're just running with shared memory with four threads. So in this simulation, OpenMC is leveraging parallelism. We see where it's loading all the cross-section information and it's giving us some information about the minimum and maximum temperature set in our problem. We'll look at that when we get back from lunch in more detail. And then it's showing us here the eigenvalue or the k-effective value for each batch that we're running. So for the first set of batches, it's not showing us the average or the accumulated eigenvalue because these are just the inactive batches and we're not tallying any information. And then once we have run two batches in the active cycles, it starts producing that information as we go. It does this for all the batches in our simulation and then finally writes out a state point file which is essentially everything that contains the results of our simulation, which we'll explore later. And then it provides us some information on the timing, how long it took to read cross-sections, how long it took to perform the simulation, to do parallel communication, and then in total how much time it took along with particle rates for the simulation. And then it reports out the k-effective value using multiple different estimators, so the collision, track length, and absorption estimators, and then the combined k-effective from all of those together. Here, just to validate that we made our geometry correctly, there's no leakage, so the open MC will determine when particles go through a vacuum boundary condition and tell us what the leakage percentage is and the problem also. But for us, because we had reflective boundary conditions in our 2D problem, all the particles kind of just stayed in the system. Any questions in the chat? Okay, cool. Let's just say any questions you have come and bother me at lunch, if that sounds okay, yeah. That's a good question. The question was, do we need to start by defining materials first and then apply them to the geometry? Can that be done in one order versus another? And the answer is you can do it in whatever order you like. So if you wanted to create the entire geometry first and then specify materials, you can do that. Or you could specify materials and then geometry. Either way, yeah. You can do the settings first and whatever. It's just as the important, like what open MC is gonna interpret is what is in these XML files at the end of the day. So, oh, that's a good question. So in contrast to other Monte Carlo codes, the way that they sometimes specify boundary conditions is that I would also need to specify the region outside of my pin cell, outside of the geometry of interest and to say that if a particle enters that region, it should be terminated. In open MC, we do use surface boundary conditions instead. So there was no need for us to specify anything outside of the true geometry. That's a good question, yeah. There's one question from on chat. Can you model plate type view, plate type? Oh, plate, yeah. You can certainly do that with open MC, yeah. 130, 130, okay. Okay, sounds good. Yeah, let's go get some lunch and feel free to ask me questions or if you need, if you want a hand with anything that we've been doing, let me know too, because I'd love to get people caught up if needed. I'm gonna shut down the Amazon stuff at the end of the week, but it'll be up all week, so.