Skip to content

Commit

Permalink
Serpent Interface Upgrade (#2290)
Browse files Browse the repository at this point in the history
* serpent modifications

* fixed subdomain statistics

* Updated Serpent Interface to use serpent tools and parse new output files

* fixed error msg

* new utility script

* fixed parser

* added documentation

* updated test

* removed bumat

* remove iso file

* new input

* added EOL if burn up calc

* added eol

* modified reactivity

* added tests

* in utils only python 2 syntax is allowed

* fixed typo

* still some python3 syntax in utils that is not allowed in regression test machine centos8 (since by default it stills uses python 2 for initial installation of plugins

* Update ravenframework/CodeInterfaceClasses/SERPENT/utilityForCreatingVariables/generateRavenVariables.py

* Update ravenframework/CodeInterfaceClasses/SERPENT/SerpentInterface.py

* Apply suggestions from code review

fixed some exceptions

* removed file of iso list that is not used anymore

* Added doc for EOL parameter

* addressed Wang's comments

* add optional to pip
  • Loading branch information
alfoa authored Apr 4, 2024
1 parent ed708c7 commit ad44499
Show file tree
Hide file tree
Showing 41 changed files with 3,303 additions and 7,865 deletions.
1 change: 1 addition & 0 deletions dependencies.xml
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,7 @@ Note all install methods after "main" take
<liblapack skip_check='True' os='mac' machine='x86_64'>3.9.0=20_osx64_openblas</liblapack>
<!-- source="mamba" are the ones installed when mamba is installed -->
<mamba source="mamba" skip_check='True'/>
<serpentTools optional='True' source="pip"/>
</main>
<alternate name="pip">
<hdf5>remove</hdf5>
Expand Down
308 changes: 203 additions & 105 deletions doc/user_manual/code_interfaces/serpent.tex

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion doc/user_manual/raven_user_manual.tex
Original file line number Diff line number Diff line change
Expand Up @@ -292,7 +292,7 @@
\\Alp Tezbasaran (new external code interface)
\\Anthoney A. Griffith (Bayesian optimization)
\\Jacob A. Bryan (TSA module)
\\Haoyu Wang (DMD amd DMDc)
\\Haoyu Wang (DMDc)
\\Khang Nguyen (new external code interface)
}

Expand Down
88 changes: 43 additions & 45 deletions ravenframework/CodeInterfaceClasses/SERPENT/SerpentInterface.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,33 +16,41 @@
"""
#External Modules--------------------begin
import os
import sys
#External Modules--------------------end

#Internal Modules--------------------begin
from ravenframework.utils import utils
from ..Generic.GenericCodeInterface import GenericCode
from . import serpentOutputParser as op
#Internal Modules--------------------end

class SERPENT(GenericCode):
"""
Provides code to interface RAVEN to SERPENT
This class is used as a code interface for SERPENT in RAVEN. It expects
input parameters to be specified by input file, input files be specified by either
command line or in a main input file, and produce a csv output.
It is based on the code interface developed by jbae11 and mostly re-written.
The class has been upgraded since its first version to allow
the usage of the interface for both steadystate and depletion calculations.
The output parsing is performed leveraging the library
serpentTools (https://serpent-tools.readthedocs.io/en/master/index.html)
Multiple output formats are now processable (both for steady state and depletion)
"""
def __init__(self):
"""
Initializes the SERPENT Interface.
@ In, None
@ Out, None
"""
# check if serpentTools is available, raise error it otherwise
try:
import serpentTools
except ImportError:
raise ImportError("serpentTools not found and SERPENT Interface has been invoked. Install serpentTools through pip!")
# intialize code interface
GenericCode.__init__(self)
self.printTag = 'SERPENT'# Print Tag
self.isotope_list_f = None # isotope list file (if any)
self.isotopes = [] # isotopes to collect
self.traceCutOff = 1.e-7 # cutoff threshold for ignoring isotopes
self.printTag = 'SERPENT' # Print Tag
self._fileTypesToRead = ['ResultsReader'] # container of file types to read
# in case of burnup calc, the interface can compute the time at which FOMs (e.g. keff) crosses
# a target. For example (default), we can compute the time (burnDays) at which absKeff crosses 1.0
self.eolTarget = {'absKeff':1.0}

def _findInputFile(self, inputFiles):
"""
Expand All @@ -67,21 +75,28 @@ def _readMoreXML(self,xmlNode):
@ In, xmlNode, xml.etree.ElementTree.Element, Xml element node
@ Out, None.
"""
isotopeList = xmlNode.find("isotope_list")
eolNodes = xmlNode.findall("EOL")
for eolNode in eolNodes:
if eolNode is not None:
target = eolNode.attrib.get('target')
if target is None:
raise ValueError(self.printTag+' ERROR: "target" attribute in <EOL> must be present if <EOL> node is inputted')
value = float(eolNode.text)
self.eolTarget[target] = value

if isotopeList is None:
raise IOError(self.printTag+' ERROR: <isotope_list> node not inputted!!')
body = isotopeList.text.strip()
if "," in body:
self.isotopes = [iso.strip() for iso in body.split(",")]
else:
if not body.strip().endswith(".csv"):
raise IOError(self.printTag+' ERROR: <isotope_list> file must be a CSV!!')
self.isotope_list_f = body
cutOff = xmlNode.find("traceCutOff")

if cutOff is not None:
self.traceCutOff = float(cutOff.text)
# by default only the "_res.m" file is read.
# if additional files are required, the user should request them here
addFileTypes = xmlNode.find("additionalFileTypes")
if addFileTypes is not None:
serpentFileTypes = [ft.strip().lower() for ft in addFileTypes.text.split(",")]
if 'ResultsReader' in serpentFileTypes:
# we pop this because it is the default
serpentFileTypes.pop(serpentFileTypes.index('ResultsReader'))
for ft in serpentFileTypes:
if ft not in op.serpentOutputAvailableTypes:
raise ValueError(self.printTag+f' ERROR: <Serpent File Type> {ft} not supported! Available types are "'
f'{", ".join(op.serpentOutputAvailableTypes)}!!')
self._fileTypesToRead += serpentFileTypes

def initialize(self, runInfo, oriInputFiles):
"""
Expand All @@ -90,15 +105,9 @@ def initialize(self, runInfo, oriInputFiles):
@ In, oriInputFiles, list, list of the original input files
@ Out, None
"""
# read the isotopes
if self.isotope_list_f is not None:
self.isotopes = []
if not os.path.isabs(self.isotope_list_f):
self.isotope_list_f = os.path.join(runInfo['WorkingDir'], self.isotope_list_f)
lines = open(self.isotope_list_f,"r").readlines()
for line in lines:
self.isotopes+= [elm.strip() for elm in line.split(",")]
inputFile = self._findInputFile(oriInputFiles)
# check if all the output files will be actually generated by the provided input
op.checkCompatibilityFileTypesAndInputFile(inputFile, self._fileTypesToRead)
# set the extension
self.setInputExtension([inputFile.getExt()])

Expand Down Expand Up @@ -136,19 +145,8 @@ def finalizeCodeOutput(self, command, output, workDir):
@ In, workDir, string, working directory path
@ Out, None
"""
# resfile would be 'input.serpent_res.m'
# this is the file produced by RAVEN
inputRoot = output.replace("_res","")
resfile = os.path.join(workDir, output+".m")
inputFile = os.path.join(workDir,inputRoot)
inbumatfile = os.path.join(workDir, inputRoot+".bumat0")
outbumatfile = os.path.join(workDir, inputRoot+".bumat1")
# parse files into dictionary
keffDict = op.searchKeff(resfile)
# the second argument is the percent cutoff
inBumatDict = op.bumatRead(inbumatfile, self.traceCutOff)
outBumatDict = op.bumatRead(outbumatfile, self.traceCutOff)
outputParser = op.SerpentOutputParser(self._fileTypesToRead, os.path.join(workDir,inputRoot), self.eolTarget)
results = outputParser.processOutputs()
return results

outputPath = os.path.join(workDir, output+'.csv')
op.makeCsv(outputPath, inBumatDict, outBumatDict,
keffDict, self.isotopes, inputFile)
Loading

0 comments on commit ad44499

Please sign in to comment.