From c134a74520932a215bd1ea2e7fecf56079c49dec Mon Sep 17 00:00:00 2001 From: ChasingNeutrons Date: Tue, 17 Sep 2024 15:15:07 +0100 Subject: [PATCH 1/6] Beginning to support SCONE Very basic modifications - lots more to do --- csg2csg/SCONECellCard.py | 71 ++++++++ csg2csg/SCONEInput.py | 69 ++++++++ csg2csg/SCONEMaterialCard.py | 65 +++++++ csg2csg/SCONESurfaceCard.py | 334 +++++++++++++++++++++++++++++++++++ csg2csg/__main__.py | 10 +- 5 files changed, 548 insertions(+), 1 deletion(-) create mode 100644 csg2csg/SCONECellCard.py create mode 100644 csg2csg/SCONEInput.py create mode 100644 csg2csg/SCONEMaterialCard.py create mode 100644 csg2csg/SCONESurfaceCard.py diff --git a/csg2csg/SCONECellCard.py b/csg2csg/SCONECellCard.py new file mode 100644 index 0000000..e4af7af --- /dev/null +++ b/csg2csg/SCONECellCard.py @@ -0,0 +1,71 @@ +#!/usr/env/python3 + +from csg2csg.MCNPFormatter import mcnp_line_formatter + +from csg2csg.CellCard import CellCard +from enum import Enum +import re +import math + +# turn the generic operation type into a scone relevant text string +def scone_op_from_generic(Operation): + # if we are not of type operator - we are string do nowt + if not isinstance(Operation, CellCard.OperationType): + if Operation == "(": + return " < " + elif Operation == ")": + return " > " + else: + return Operation + else: + # otherwise we need to do something + if Operation == CellCard.OperationType["NOT"]: + string = " # " + elif Operation == CellCard.OperationType["AND"]: + string = " " + elif Operation == CellCard.OperationType["UNION"]: + string = " : " + else: + string = "unknown operation" + # return the operation + return string + + +# write the cell card for a scone cell given a generic cell card +def write_scone_cell(filestream, CellCard): + + # print (CellCard) + string = str(CellCard.cell_id) + "{type unionCell; id " + str(cellCard.cell_id) + "; " + string += " " + str(CellCard.cell_universe) + " " + # Is it possible to fill with universes??? + # May need to keep track of universe definitions and return + # to write these separately + if CellCard.cell_fill != 0: + string += " filltype mat; material " + str(CellCard.cell_fill) + "; " + + # base level universe cant have material + if CellCard.cell_fill == 0: + # material 0 is void + if CellCard.cell_material_number == 0: + string += " filltype mat; material void; " + else: + string += str(CellCard.cell_material_number) + " " + + string += "[ " + + # build the cell description + for item in CellCard.cell_interpreted: + string += serpent_op_from_generic(item) + + string += " ]; }\n" + + # removes any multiple spaces + string = re.sub(" +", " ", string) + + string = mcnp_line_formatter(string) + + filestream.write(string) + +class SCONECellCard(CellCard): + def __init__(self, card_string): + CellCard.__init__(self, card_string) diff --git a/csg2csg/SCONEInput.py b/csg2csg/SCONEInput.py new file mode 100644 index 0000000..fb966aa --- /dev/null +++ b/csg2csg/SCONEInput.py @@ -0,0 +1,69 @@ +# /usr/env/python3 + +from csg2csg.Input import InputDeck +from csg2csg.SCONESurfaceCard import SCONESurfaceCard, write_scone_surface +from csg2csg.SCONECellCard import SCONECellCard, write_scone_cell +from csg2csg.SCONEMaterialCard import SCONEMaterialCard, write_scone_material + +import logging +import re + + +class SCONEInput(InputDeck): + """SCONEInput class - does the actual processing""" + + # constructor + def __init__(self, filename=""): + InputDeck.__init__(self, filename) + + # write the SCONE surface definitions + def __write_scone_surfaces(self, filestream): + filestream.write("% --- surface definitions --- %\n") + # Open the SCONE geometry card + filestream.write("geometry { \n") + # Surely there is a way to customise this? + filestream.write("boundary (0 0 0 0 0 0); \n") + filestream.write("graph {type shrunk;} \n") + filestream.write("surfaces { \n") + for surface in self.surface_list: + write_scone_surface(filestream, surface) + filestream.write("} \n") + return + + # Write the SCONE Cell definitions + def __write_scone_cells(self, filestream): + filestream.write("% --- cell definitions --- %\n") + filestream.write("cells { \n") + for cell in self.cell_list: + write_scone_cell(filestream, cell) + filestream.write("} \n") + # Close the SCONE geometry card + # Need to do something about universes! + # E.g., add in a rootUniverse and a single cellUniverse containing all cells + # Most codes have universes implicit in their cells, complicating things slightly. + filestream.write("} \n") + return + + # write the material compositions + def __write_scone_materials(self, filestream): + filestream.write("% --- material definitions --- %\n") + # Open the SCONE nuclearData card + filestream.write("nuclearData { \n") + filestream.write("handles { \n") + filestream.write("ce {type aceNeutronDatabase; acelibrary $SCONE_ACE; ures 0;} \n") + filestream.write("} \n") + filestream.write("materials { \n") + for material in self.material_list: + write_scone_material(filestream, self.material_list[material]) + filestream.write("} \n") + filestream.write("} \n") + return + + # main write scone method, depending upon where the geometry + # came from + def write_scone(self, filename, flat=True): + f = open(filename, "w") + self.__write_scone_surfaces(f) + self.__write_scone_cells(f) + self.__write_scone_materials(f) + f.close() diff --git a/csg2csg/SCONEMaterialCard.py b/csg2csg/SCONEMaterialCard.py new file mode 100644 index 0000000..455f73e --- /dev/null +++ b/csg2csg/SCONEMaterialCard.py @@ -0,0 +1,65 @@ +#!/usr/env/python3 + +from csg2csg.MaterialCard import MaterialCard +from csg2csg.MCNPFormatter import get_fortran_formatted_number + +# write a specific serpent material card +def write_scone_material(filestream, material): + + string = material.material_name + "{ \n" + string += "composition { \n" + for nuc in material.composition_dictionary: + string += "{} {:e}; \n".format(nuc, material.composition_dictionary[nuc]) + string += "} \n" + + # if its a non tally material set the relevant colour + if material.material_colour: + string += " rgb " + material.material_colour + "\n" + else: + string += "\n" + + string += "} \n" + filestream.write(string) + return + + +""" Class to handle SCONEMaterialCard translation +""" + + +class SCONEMaterialCard(MaterialCard): + def __init__(self, material_number, material_name, material_density, card_string): + MaterialCard.__init__(self, material_number, card_string) + self.material_name = material_name + self.material_number = material_number + self.density = material_density + self.__process_string() + + # populate the SCONE Material Card + def __process_string(self): + # need to reset the dictionary + # otherwise state seems to linger - weird + self.composition_dictionary = {} + + mat_string = self.text_string + mat_string = mat_string.replace("\n", " ") + + # split string + tokens = mat_string.split() + + if len(tokens) % 2 != 0: + raise Exception("Material string not correctly processed") + + while len(tokens) != 0: + nuclide = tokens[0].split(".") + nucid = nuclide[0] + try: + xsid = nuclide[1] + except: + xsid = "" + frac = get_fortran_formatted_number(tokens[1]) + tokens.pop(0) + tokens.pop(0) + self.composition_dictionary[nucid] = frac + self.xsid_dictionary[nucid] = xsid + return diff --git a/csg2csg/SCONESurfaceCard.py b/csg2csg/SCONESurfaceCard.py new file mode 100644 index 0000000..8d486d4 --- /dev/null +++ b/csg2csg/SCONESurfaceCard.py @@ -0,0 +1,334 @@ +#!/usr/env/python3 + +from csg2csg.SurfaceCard import SurfaceCard +from math import sqrt + +# write the general form of a plane +def scone_plane_string(SurfaceCard): + string = " plane; coeffs ( " + string += str(SurfaceCard.surface_coefficients[0]) + " " + string += str(SurfaceCard.surface_coefficients[1]) + " " + string += str(SurfaceCard.surface_coefficients[2]) + " " + string += str(SurfaceCard.surface_coefficients[3]) + "); " + return string + + +# write the specific x form of the plane +def scone_plane_x_string(SurfaceCard): + string = " xPlane; x0 " + str(SurfaceCard.surface_coefficients[3]) + ";" + return string + + +# write the specific y form of the plane +def scone_plane_y_string(SurfaceCard): + string = " yPlane; y0 " + str(SurfaceCard.surface_coefficients[3]) + ";" + return string + + +# write the specific z form of the plane +def scone_plane_z_string(SurfaceCard): + string = " zPlane; z0 " + str(SurfaceCard.surface_coefficients[3]) + ";" + return string + + +# write a cylinder_x +def scone_cylinder_x(SurfaceCard): + string = " xCylinder; radius " + str(SurfaceCard.surface_coefficients[0]) + "; " + string += "origin ( 0.0 " + str(SurfaceCard.surface_coefficients[1]) + " " + string += str(SurfaceCard.surface_coefficients[2]) + "); " + return string + + +# write a cylinder_y +def scone_cylinder_y(SurfaceCard): + string = " yCylinder; radius " + str(SurfaceCard.surface_coefficients[0]) + "; " + string += "origin (" + str(SurfaceCard.surface_coefficients[1]) + " 0 " + string += str(SurfaceCard.surface_coefficients[2]) + "); " + return string + + +# write a cylinder_z +def scone_cylinder_z(SurfaceCard): + string = " zCylinder; radius " + str(SurfaceCard.surface_coefficients[0]) + "; " + string += "origin (" + str(SurfaceCard.surface_coefficients[1]) + " " + string += str(SurfaceCard.surface_coefficients[2]) + " 0); " + return string + + +# write a sphere +def scone_sphere(SurfaceCard): + string = " sphere; radius " + str(SurfaceCard.surface_coefficients[0]) + "; " + string += "origin (" + str(SurfaceCard.surface_coefficients[1]) + " " + string += str(SurfaceCard.surface_coefficients[2]) + " " + string += str(SurfaceCard.surface_coefficients[3]) + "); " + return string + + +# write a general quadratic +def scone_gq(SurfaceCard): + string = " quadratic " + for coefficient in SurfaceCard.surface_coefficients: + string += " " + str(coefficient) + " " + string += "\n" + return string + + +# its not clear how we deal with +-1 cones for serpent} +# write a cone along x - jaakko has implemented a special +# version for mcnp comparisons - ckx/y/z +def serpent_cone_x(SurfaceCard): + x = SurfaceCard.surface_coefficients[0] + y = SurfaceCard.surface_coefficients[1] + z = SurfaceCard.surface_coefficients[2] + r = SurfaceCard.surface_coefficients[3] + + if len(SurfaceCard.surface_coefficients) > 4: + side = SurfaceCard.surface_coefficients[4] + string = " {} {:f} {:f} {:f} {:f} {:f}\n".format("ckx", x, y, z, r, side) + else: + string = " {} {:f} {:f} {:f} {:f}\n".format("ckx", x, y, z, r) + + return string + + +# scone a cone along y +def scone_cone_y(SurfaceCard): + x = SurfaceCard.surface_coefficients[0] + y = SurfaceCard.surface_coefficients[1] + z = SurfaceCard.surface_coefficients[2] + r = SurfaceCard.surface_coefficients[3] + + if len(SurfaceCard.surface_coefficients) > 4: + side = SurfaceCard.surface_coefficients[4] + string = " {} {:f} {:f} {:f} {:f} {:f}\n".format("cky", x, y, z, r, side) + else: + string = " {} {:f} {:f} {:f} {:f}\n".format("cky", x, y, z, r) + + return string + + +# scone a cone along z +def scone_cone_z(SurfaceCard): + x = SurfaceCard.surface_coefficients[0] + y = SurfaceCard.surface_coefficients[1] + z = SurfaceCard.surface_coefficients[2] + r = SurfaceCard.surface_coefficients[3] + + if len(SurfaceCard.surface_coefficients) > 4: + side = SurfaceCard.surface_coefficients[4] + string = " {} {:f} {:f} {:f} {:f} {:f}\n".format("ckz", x, y, z, r, side) + else: + string = " {} {:f} {:f} {:f} {:f}\n".format("ckz", x, y, z, r) + + return string + + +# scone a torus x +def scone_torus_x(SurfaceCard): + x = SurfaceCard.surface_coefficients[0] + y = SurfaceCard.surface_coefficients[1] + z = SurfaceCard.surface_coefficients[2] + a = SurfaceCard.surface_coefficients[3] + b = SurfaceCard.surface_coefficients[4] + c = SurfaceCard.surface_coefficients[5] + string = " {} {:f} {:f} {:f} {:f} {:f} {:f}\n".format("torx", x, y, z, a, b, c) + return string + + +# scone a torus y +def scone_torus_y(SurfaceCard): + x = SurfaceCard.surface_coefficients[0] + y = SurfaceCard.surface_coefficients[1] + z = SurfaceCard.surface_coefficients[2] + a = SurfaceCard.surface_coefficients[3] + b = SurfaceCard.surface_coefficients[4] + c = SurfaceCard.surface_coefficients[5] + string = " {} {:f} {:f} {:f} {:f} {:f} {:f}\n".format("tory", x, y, z, a, b, c) + return string + + +# scone a torus z +def scone_torus_z(SurfaceCard): + x = SurfaceCard.surface_coefficients[0] + y = SurfaceCard.surface_coefficients[1] + z = SurfaceCard.surface_coefficients[2] + a = SurfaceCard.surface_coefficients[3] + b = SurfaceCard.surface_coefficients[4] + c = SurfaceCard.surface_coefficients[5] + string = " {} {:f} {:f} {:f} {:f} {:f} {:f}\n".format("torz", x, y, z, a, b, c) + return string + + +""" +# write a conex +def serpent_cone_x(SurfaceCard): + + mcnp xyz r2 -1 +1 + * + || + | \ + | \ + | \ + | \ + | \ + *------* + + From the bounding coodinate appropriate in + this case - if pointing down need the lowest value + + + # cone points down from xyz + if SurfaceCard.surface_coefficients[4] == -1: + h = abs(SurfaceCard.b_box[0]) + x = SurfaceCard.b_box[0] + # cone point up from xyz + if SurfaceCard.surface_coefficients[4] == 1: + h = abs(SurfaceCard.b_box[1]) + x = SurfaceCard.b_box[1] + + y = SurfaceCard.surface_coefficients[1] + z = SurfaceCard.surface_coefficients[2] + r = h*sqrt(SurfaceCard.surface_coefficients[3]) + + string = ' {} {:f} {:f} {:f} {:f} {:f}'.format("conx",x,y,z,r,h) + + return string + +# write a cone y +def serpent_cone_y(SurfaceCard): + + mcnp xyz r2 -1 +1 + * + || + | \ + | \ + | \ + | \ + | \ + *------* + + From the bounding coodinate appropriate in + this case - if pointing down need the lowest value + + + # cone points down from xyz + if SurfaceCard.surface_coefficients[4] == -1: + h = abs(SurfaceCard.b_box[2]) + y = SurfaceCard.b_box[2] + # cone point up from xyz + if SurfaceCard.surface_coefficients[4] == 1: + h = abs(SurfaceCard.b_box[3]) + y = SurfaceCard.b_box[3] + + x = SurfaceCard.surface_coefficients[0] + z = SurfaceCard.surface_coefficients[2] + r = h*sqrt(SurfaceCard.surface_coefficients[3]) + + string = ' {} {:f} {:f} {:f} {:f} {:f}'.format("cony",x,y,z,r,h) + + return string + +# write a cone z +def serpent_cone_z(SurfaceCard): + + mcnp xyz r2 -1 +1 + * + || + | \ + | \ + | \ + | \ + | \ + *------* + + From the bounding coodinate appropriate in + this case - if pointing down need the lowest value + + + # cone points down from xyz + if SurfaceCard.surface_coefficients[4] == -1: + h = abs(SurfaceCard.b_box[5]) + z = SurfaceCard.b_box[5] + # cone point up from xyz + if SurfaceCard.surface_coefficients[4] == 1: + h = abs(SurfaceCard.b_box[6]) + z = SurfaceCard.b_box[6] + + x = SurfaceCard.surface_coefficients[0] + y = SurfaceCard.surface_coefficients[1] + r = h*sqrt(SurfaceCard.surface_coefficients[3]) + + + return string + +""" + +# write the surface description to file +def write_serpent_surface(filestream, SurfaceCard): + # NOTE this appears to be a nice way to get a pythonic case statement + # is it equally ugly as below? + # return { + # SurfaceCard.SurfaceType["PLANE_GENERAL"]: surface_plane_write(Surface, + # SurfaceCard.SurfaceType["CYLINDER_Y"]: "cylinder_y\n" + # }.get(SurfaceCard.surface_type,"surface not supported") + + string = str(SurfaceCard.surface_id) + "{ id " + str(SurfaceCard.surface_id) + "; type " + + if SurfaceCard.surface_type is SurfaceCard.SurfaceType["PLANE_GENERAL"]: + string += scone_plane_string(SurfaceCard) + filestream.write(string) + elif SurfaceCard.surface_type is SurfaceCard.SurfaceType["PLANE_X"]: + string += scone_plane_x_string(SurfaceCard) + filestream.write(string) + elif SurfaceCard.surface_type is SurfaceCard.SurfaceType["PLANE_Y"]: + string += scone_plane_y_string(SurfaceCard) + filestream.write(string) + elif SurfaceCard.surface_type is SurfaceCard.SurfaceType["PLANE_Z"]: + string += scone_plane_z_string(SurfaceCard) + filestream.write(string) + elif SurfaceCard.surface_type is SurfaceCard.SurfaceType["CYLINDER_X"]: + string += scone_cylinder_x(SurfaceCard) + filestream.write(string) + elif SurfaceCard.surface_type is SurfaceCard.SurfaceType["CYLINDER_Y"]: + string += scone_cylinder_y(SurfaceCard) + filestream.write(string) + elif SurfaceCard.surface_type is SurfaceCard.SurfaceType["CYLINDER_Z"]: + string += scone_cylinder_z(SurfaceCard) + filestream.write(string) + elif SurfaceCard.surface_type is SurfaceCard.SurfaceType["SPHERE_GENERAL"]: + string += scone_sphere(SurfaceCard) + filestream.write(string) + elif SurfaceCard.surface_type is SurfaceCard.SurfaceType["CONE_X"]: + string += scone_cone_x(SurfaceCard) + filestream.write(string) + elif SurfaceCard.surface_type is SurfaceCard.SurfaceType["CONE_Y"]: + string += scone_cone_y(SurfaceCard) + filestream.write(string) + elif SurfaceCard.surface_type is SurfaceCard.SurfaceType["CONE_Z"]: + string += scone_cone_z(SurfaceCard) + filestream.write(string) + elif SurfaceCard.surface_type is SurfaceCard.SurfaceType["TORUS_X"]: + string += scone_torus_x(SurfaceCard) + filestream.write(string) + elif SurfaceCard.surface_type is SurfaceCard.SurfaceType["TORUS_Y"]: + string += scone_torus_y(SurfaceCard) + filestream.write(string) + elif SurfaceCard.surface_type is SurfaceCard.SurfaceType["TORUS_Z"]: + string += scone_torus_z(SurfaceCard) + filestream.write(string) + elif SurfaceCard.surface_type is SurfaceCard.SurfaceType["GENERAL_QUADRATIC"]: + string += scone_gq(SurfaceCard) + filestream.write(string) + else: + filestream.write("surface not supported\n") + + string += " }\n" + return + + +class SCONESurfaceCard(SurfaceCard): + def __init__(self, card_string): + SurfaceCard.__init__(self, card_string) + + def write(self): + print("hello") diff --git a/csg2csg/__main__.py b/csg2csg/__main__.py index 2fa8d90..bb4f0f0 100755 --- a/csg2csg/__main__.py +++ b/csg2csg/__main__.py @@ -36,7 +36,7 @@ def main(): parser.add_argument( "-f", "--format", - choices=["mcnp", "serpent", "openmc", "phits", "fluka"], + choices=["mcnp", "serpent", "openmc", "phits", "fluka", "scone"], help="format of the input file", default="mcnp", ) @@ -91,6 +91,8 @@ def main(): raise NotImplementedError("Phits input files are not supported yet") elif args.format == "fluka": raise NotImplementedError("Fluka input files are not supported yet") + elif args.format == "scone": + raise NotImplementedError("SCONE input files are not supported yet") for code in codes: if "serpent" in code: @@ -123,6 +125,12 @@ def main(): fluka.from_input(input) mkdir("fluka") fluka.write_fluka("fluka/fluka.inp") + if "scone" in code: + print("Producing SCONE output...") + scone = SCONEInput() + scone.from_input(input) + mkdir("scone") + scone.write_scone("scone/scone.inp") logging.info("Finished") From 4b4f2eed8940e42ce3da38cdf30daaf350494e05 Mon Sep 17 00:00:00 2001 From: ChasingNeutrons Date: Fri, 20 Sep 2024 20:18:21 +0100 Subject: [PATCH 2/6] Added universe card Useful for writing SCONE inputs --- csg2csg/Input.py | 11 +++ csg2csg/SCONECellCard.py | 23 +++-- csg2csg/SCONEMaterialCard.py | 21 ++--- csg2csg/SCONESurfaceCard.py | 162 +++++++++++++++++------------------ csg2csg/SCONEUniverseCard.py | 61 +++++++++++++ csg2csg/UniverseCard.py | 87 +++++++++++++++++++ 6 files changed, 262 insertions(+), 103 deletions(-) create mode 100644 csg2csg/SCONEUniverseCard.py create mode 100644 csg2csg/UniverseCard.py diff --git a/csg2csg/Input.py b/csg2csg/Input.py index 5f09c38..383b331 100644 --- a/csg2csg/Input.py +++ b/csg2csg/Input.py @@ -22,6 +22,7 @@ def __init__(self, filename, quick=False): # TODO maybe these should be dictionaries by index self.cell_list = [] self.surface_list = [] + self.universe_list = [] self.last_free_surface_index = 0 self.importance_list = {} # dictionary of importances self.material_list = {} @@ -87,3 +88,13 @@ def split_unions(self): # match any splitable unions - this will look like (stuff):(stuff):(stuff) # so we could make 3 cells from that continue + + # prepare universe entries given cells + def create_universes_from_cells(self): + universe_ids = set() + # count unique universe IDs + universe_ids.add(cell.universe for cell in self.cell_list) + for uni in universe_ids: + self.universe_list.append( + UniverseCard(universe_ids[uni],self.cell_list) + ) diff --git a/csg2csg/SCONECellCard.py b/csg2csg/SCONECellCard.py index e4af7af..d77c1c6 100644 --- a/csg2csg/SCONECellCard.py +++ b/csg2csg/SCONECellCard.py @@ -34,24 +34,31 @@ def scone_op_from_generic(Operation): # write the cell card for a scone cell given a generic cell card def write_scone_cell(filestream, CellCard): + # If cell is in the root universe and outside the boundary, skip it. + # Presently assumes only two cells in the root, with one surface, + # as in Serpent. + if CellCard.universe == 0 and CellCard.surfaces[0] >= 0: + return + # print (CellCard) - string = str(CellCard.cell_id) + "{type unionCell; id " + str(cellCard.cell_id) + "; " - string += " " + str(CellCard.cell_universe) + " " - # Is it possible to fill with universes??? - # May need to keep track of universe definitions and return + string = str(CellCard.cell_id) + "{type unionCell; id " + string += str(cellCard.cell_id) + "; " + + # Need to keep track of universe definitions and return # to write these separately if CellCard.cell_fill != 0: - string += " filltype mat; material " + str(CellCard.cell_fill) + "; " + string += " filltype uni; universe " + str(CellCard.cell_fill) + "; " - # base level universe cant have material + # Doesn't have a universe - has a material if CellCard.cell_fill == 0: # material 0 is void + string += " filltype mat; material " if CellCard.cell_material_number == 0: - string += " filltype mat; material void; " + string += " void; " else: string += str(CellCard.cell_material_number) + " " - string += "[ " + string += "surfaces [ " # build the cell description for item in CellCard.cell_interpreted: diff --git a/csg2csg/SCONEMaterialCard.py b/csg2csg/SCONEMaterialCard.py index 455f73e..f4c92e7 100644 --- a/csg2csg/SCONEMaterialCard.py +++ b/csg2csg/SCONEMaterialCard.py @@ -6,15 +6,18 @@ # write a specific serpent material card def write_scone_material(filestream, material): - string = material.material_name + "{ \n" + string = "! " + self.material_name + " \n" + string += str(material.material_number) + "{ \n" string += "composition { \n" for nuc in material.composition_dictionary: - string += "{} {:e}; \n".format(nuc, material.composition_dictionary[nuc]) + string += "{} {:e}; \n".format( + nuc, material.composition_dictionary[nuc] + ) string += "} \n" # if its a non tally material set the relevant colour if material.material_colour: - string += " rgb " + material.material_colour + "\n" + string += " rgb (" + material.material_colour + "); \n" else: string += "\n" @@ -28,7 +31,8 @@ def write_scone_material(filestream, material): class SCONEMaterialCard(MaterialCard): - def __init__(self, material_number, material_name, material_density, card_string): + def __init__(self, material_number, material_name, + material_density, card_string): MaterialCard.__init__(self, material_number, card_string) self.material_name = material_name self.material_number = material_number @@ -52,14 +56,11 @@ def __process_string(self): while len(tokens) != 0: nuclide = tokens[0].split(".") - nucid = nuclide[0] - try: - xsid = nuclide[1] - except: - xsid = "" + xsid = nuclide[0] + temp = nuclide[1].rstrip('c') frac = get_fortran_formatted_number(tokens[1]) tokens.pop(0) tokens.pop(0) self.composition_dictionary[nucid] = frac - self.xsid_dictionary[nucid] = xsid + self.xsid_dictionary[nucid] = xsid + "." + temp return diff --git a/csg2csg/SCONESurfaceCard.py b/csg2csg/SCONESurfaceCard.py index 8d486d4..8ff8eb7 100644 --- a/csg2csg/SCONESurfaceCard.py +++ b/csg2csg/SCONESurfaceCard.py @@ -1,7 +1,7 @@ #!/usr/env/python3 from csg2csg.SurfaceCard import SurfaceCard -from math import sqrt +from math import sqrt, atan, degrees # write the general form of a plane def scone_plane_string(SurfaceCard): @@ -33,32 +33,32 @@ def scone_plane_z_string(SurfaceCard): # write a cylinder_x def scone_cylinder_x(SurfaceCard): - string = " xCylinder; radius " + str(SurfaceCard.surface_coefficients[0]) + "; " - string += "origin ( 0.0 " + str(SurfaceCard.surface_coefficients[1]) + " " - string += str(SurfaceCard.surface_coefficients[2]) + "); " + string = " xCylinder; radius " + str(SurfaceCard.surface_coefficients[0]) + string += "; origin ( 0.0 " + str(SurfaceCard.surface_coefficients[1]) + string += " " + str(SurfaceCard.surface_coefficients[2]) + "); " return string # write a cylinder_y def scone_cylinder_y(SurfaceCard): - string = " yCylinder; radius " + str(SurfaceCard.surface_coefficients[0]) + "; " - string += "origin (" + str(SurfaceCard.surface_coefficients[1]) + " 0 " + string = " yCylinder; radius " + str(SurfaceCard.surface_coefficients[0]) + string += "; origin (" + str(SurfaceCard.surface_coefficients[1]) + " 0 " string += str(SurfaceCard.surface_coefficients[2]) + "); " return string # write a cylinder_z def scone_cylinder_z(SurfaceCard): - string = " zCylinder; radius " + str(SurfaceCard.surface_coefficients[0]) + "; " - string += "origin (" + str(SurfaceCard.surface_coefficients[1]) + " " + string = " zCylinder; radius " + str(SurfaceCard.surface_coefficients[0]) + string += "; origin (" + str(SurfaceCard.surface_coefficients[1]) + " " string += str(SurfaceCard.surface_coefficients[2]) + " 0); " return string # write a sphere def scone_sphere(SurfaceCard): - string = " sphere; radius " + str(SurfaceCard.surface_coefficients[0]) + "; " - string += "origin (" + str(SurfaceCard.surface_coefficients[1]) + " " + string = " sphere; radius " + str(SurfaceCard.surface_coefficients[0]) + string += "; origin (" + str(SurfaceCard.surface_coefficients[1]) + " " string += str(SurfaceCard.surface_coefficients[2]) + " " string += str(SurfaceCard.surface_coefficients[3]) + "); " return string @@ -66,27 +66,39 @@ def scone_sphere(SurfaceCard): # write a general quadratic def scone_gq(SurfaceCard): - string = " quadratic " + string = " quadric; coeffs ( " for coefficient in SurfaceCard.surface_coefficients: string += " " + str(coefficient) + " " - string += "\n" + string += "); " return string -# its not clear how we deal with +-1 cones for serpent} -# write a cone along x - jaakko has implemented a special -# version for mcnp comparisons - ckx/y/z -def serpent_cone_x(SurfaceCard): +def scone_cone_x(SurfaceCard): x = SurfaceCard.surface_coefficients[0] y = SurfaceCard.surface_coefficients[1] z = SurfaceCard.surface_coefficients[2] - r = SurfaceCard.surface_coefficients[3] - - if len(SurfaceCard.surface_coefficients) > 4: - side = SurfaceCard.surface_coefficients[4] - string = " {} {:f} {:f} {:f} {:f} {:f}\n".format("ckx", x, y, z, r, side) + t2 = SurfaceCard.surface_coefficients[3] + sign = SurfaceCard.surface_coefficients[4] + + # Do trigonometry to convert mcnp tangent squared, t2, into + # angle and determine hMin and hMax. + # If sign is negative, hMax = vertex = 0, hMin = -10E10 + # If sign is positive, hMin = vertex = 0, hMax = 10E10 + # A bit of a fudge for now. + # Assume no truncation, like in MCNP + if sign < 0: + hMin = -1E10 + hMax = 0 else: - string = " {} {:f} {:f} {:f} {:f}\n".format("ckx", x, y, z, r) + hMin = 0 + hMax = 1E10 + + angle = math.degrees(math.atan(math.sqrt(t2))) + + string = " {} {:f} {:f} {:f} {}\n".format( + " xCone; vertex (", x, y, z," ); ") + string += "angle " + str(angle) + "; hMin " + str(hMin) + string += "; hMax " + str(hMax) + "; \n" return string @@ -96,13 +108,28 @@ def scone_cone_y(SurfaceCard): x = SurfaceCard.surface_coefficients[0] y = SurfaceCard.surface_coefficients[1] z = SurfaceCard.surface_coefficients[2] - r = SurfaceCard.surface_coefficients[3] - - if len(SurfaceCard.surface_coefficients) > 4: - side = SurfaceCard.surface_coefficients[4] - string = " {} {:f} {:f} {:f} {:f} {:f}\n".format("cky", x, y, z, r, side) + t2 = SurfaceCard.surface_coefficients[3] + sign = SurfaceCard.surface_coefficients[4] + + # Do trigonometry to convert mcnp tangent squared, t2, into + # angle and determine hMin and hMax. + # If sign is negative, hMax = vertex = 0, hMin = -10E10 + # If sign is positive, hMin = vertex = 0, hMax = 10E10 + # A bit of a fudge for now. + # Assume no truncation, like in MCNP + if sign < 0: + hMin = -1E10 + hMax = 0 else: - string = " {} {:f} {:f} {:f} {:f}\n".format("cky", x, y, z, r) + hMin = 0 + hMax = 1E10 + + angle = math.degrees(math.atan(math.sqrt(t2))) + + string = " {} {:f} {:f} {:f} {}\n".format( + " yCone; vertex (", x, y, z," ); ") + string += "angle " + str(angle) + "; hMin " + str(hMin) + string += "; hMax " + str(hMax) + "; \n" return string @@ -112,50 +139,29 @@ def scone_cone_z(SurfaceCard): x = SurfaceCard.surface_coefficients[0] y = SurfaceCard.surface_coefficients[1] z = SurfaceCard.surface_coefficients[2] - r = SurfaceCard.surface_coefficients[3] - - if len(SurfaceCard.surface_coefficients) > 4: - side = SurfaceCard.surface_coefficients[4] - string = " {} {:f} {:f} {:f} {:f} {:f}\n".format("ckz", x, y, z, r, side) + t2 = SurfaceCard.surface_coefficients[3] + sign = SurfaceCard.surface_coefficients[4] + + # Do trigonometry to convert mcnp tangent squared, t2, into + # angle and determine hMin and hMax. + # If sign is negative, hMax = vertex = 0, hMin = -10E10 + # If sign is positive, hMin = vertex = 0, hMax = 10E10 + # A bit of a fudge for now. + # Assume no truncation, like in MCNP + if sign < 0: + hMin = -1E10 + hMax = 0 else: - string = " {} {:f} {:f} {:f} {:f}\n".format("ckz", x, y, z, r) - - return string - - -# scone a torus x -def scone_torus_x(SurfaceCard): - x = SurfaceCard.surface_coefficients[0] - y = SurfaceCard.surface_coefficients[1] - z = SurfaceCard.surface_coefficients[2] - a = SurfaceCard.surface_coefficients[3] - b = SurfaceCard.surface_coefficients[4] - c = SurfaceCard.surface_coefficients[5] - string = " {} {:f} {:f} {:f} {:f} {:f} {:f}\n".format("torx", x, y, z, a, b, c) - return string - + hMin = 0 + hMax = 1E10 -# scone a torus y -def scone_torus_y(SurfaceCard): - x = SurfaceCard.surface_coefficients[0] - y = SurfaceCard.surface_coefficients[1] - z = SurfaceCard.surface_coefficients[2] - a = SurfaceCard.surface_coefficients[3] - b = SurfaceCard.surface_coefficients[4] - c = SurfaceCard.surface_coefficients[5] - string = " {} {:f} {:f} {:f} {:f} {:f} {:f}\n".format("tory", x, y, z, a, b, c) - return string + angle = math.degrees(math.atan(math.sqrt(t2))) + string = " {} {:f} {:f} {:f} {}\n".format( + " zCone; vertex (", x, y, z," ); ") + string += "angle " + str(angle) + "; hMin " + str(hMin) + string += "; hMax " + str(hMax) + "; \n" -# scone a torus z -def scone_torus_z(SurfaceCard): - x = SurfaceCard.surface_coefficients[0] - y = SurfaceCard.surface_coefficients[1] - z = SurfaceCard.surface_coefficients[2] - a = SurfaceCard.surface_coefficients[3] - b = SurfaceCard.surface_coefficients[4] - c = SurfaceCard.surface_coefficients[5] - string = " {} {:f} {:f} {:f} {:f} {:f} {:f}\n".format("torz", x, y, z, a, b, c) return string @@ -264,15 +270,10 @@ def serpent_cone_z(SurfaceCard): """ # write the surface description to file -def write_serpent_surface(filestream, SurfaceCard): - # NOTE this appears to be a nice way to get a pythonic case statement - # is it equally ugly as below? - # return { - # SurfaceCard.SurfaceType["PLANE_GENERAL"]: surface_plane_write(Surface, - # SurfaceCard.SurfaceType["CYLINDER_Y"]: "cylinder_y\n" - # }.get(SurfaceCard.surface_type,"surface not supported") +def write_scone_surface(filestream, SurfaceCard): - string = str(SurfaceCard.surface_id) + "{ id " + str(SurfaceCard.surface_id) + "; type " + string = str(SurfaceCard.surface_id) + "{ id " + string += str(SurfaceCard.surface_id) + "; type " if SurfaceCard.surface_type is SurfaceCard.SurfaceType["PLANE_GENERAL"]: string += scone_plane_string(SurfaceCard) @@ -307,15 +308,6 @@ def write_serpent_surface(filestream, SurfaceCard): elif SurfaceCard.surface_type is SurfaceCard.SurfaceType["CONE_Z"]: string += scone_cone_z(SurfaceCard) filestream.write(string) - elif SurfaceCard.surface_type is SurfaceCard.SurfaceType["TORUS_X"]: - string += scone_torus_x(SurfaceCard) - filestream.write(string) - elif SurfaceCard.surface_type is SurfaceCard.SurfaceType["TORUS_Y"]: - string += scone_torus_y(SurfaceCard) - filestream.write(string) - elif SurfaceCard.surface_type is SurfaceCard.SurfaceType["TORUS_Z"]: - string += scone_torus_z(SurfaceCard) - filestream.write(string) elif SurfaceCard.surface_type is SurfaceCard.SurfaceType["GENERAL_QUADRATIC"]: string += scone_gq(SurfaceCard) filestream.write(string) diff --git a/csg2csg/SCONEUniverseCard.py b/csg2csg/SCONEUniverseCard.py new file mode 100644 index 0000000..2ca51a6 --- /dev/null +++ b/csg2csg/SCONEUniverseCard.py @@ -0,0 +1,61 @@ +#!/usr/env/python3 + +from csg2csg.MCNPFormatter import mcnp_line_formatter + +from csg2csg.UniverseCard import UniverseCard, uni_fill, mat_fill +import re +import math + +# write the universe card for a scone universe given a generic cell card +def write_scone_universe(filestream, UniverseCard): + + # print (UniverseCard) + # TODO support lattice universes + string = str(UniverseCard.universe_id) + "{ type " + if UniverseCard.is_root: + string += "rootUniverse; " + string += "border " + str(UniverseCard.border_surface) + "; " + if UniverseCard.fill_type == uni_fill: + string += "fill u<" + str(UniverseCard.fill_id) + ">; " + else: + string += "fill " + str(UniverseCard.fill_material) + "; " + else: + string += "cellUniverse; " + string += "cells (" + str(UniverseCard.cell_list) + "); " + + # Need to increment by 1 due to SCONE not allowing Universe ID = 0 + # This is used by other codes to denote the base/root universe + string += "id " + str(UniverseCard.universe_id + 1) +"; " + + # Include transformations + if UniverseCard.origin != 0: + # Convert origin to a translation + string += "translation (" + for i in range(3): + string += str(UniverseCard.origin[i]) +" " + string += "); " + + if UniverseCard.rotation != 0: + # Convert rotation matrix to Euler angles following ZXZ convention + # Need to double check conventions: rotate[5] might have a negative + # sign and rot[2] might be * -1 + rotate = UniverseCard.rotation + rot[0] = math.atan2(rotate[2],-rotate[5]) + rot[1] = math.acos(rotate[8]) + rot[2] = math.atan2(rotate[6],rotate[7]) + rot = math.degrees(rot) + string += "rotation (" + for i in range(3): + string += str(rot[i]) +" " + string += "); " + string += " } \n" + + # removes any multiple spaces + string = re.sub(" +", " ", string) + string = mcnp_line_formatter(string) + filestream.write(string) + +class SCONEUniverseCard(UniverseCard): + def __init__(self, card_string): + UniverseCard.__init__(self, card_string) + diff --git a/csg2csg/UniverseCard.py b/csg2csg/UniverseCard.py new file mode 100644 index 0000000..61db533 --- /dev/null +++ b/csg2csg/UniverseCard.py @@ -0,0 +1,87 @@ +# /usr/env/python3 + +from csg2csg.Card import Card +from enum import Enum + +uni_fill = 1 +mat_fill = 2 + +class UniverseCard(Card): + """Class for the storage of the Generic UniverseCard type + methods for the generation of UniverseCards should be placed + here. Classes instanciating UniverseCard objects should be + implemented in its own CodeUniverseCard.py file. + This is primarily intended for SCONE - do any other codes + have explicit cell universe cards? Maybe this is useful for + translating lattices? + """ + + # constructor for the universecard class + def __init__(self, card_string): + self.universe_comment = "" + self.universe_id = 0 + self.cell_list = set() + self.fill_type = 0 + self.fill_id = 0 + self.fill_mat = '' + self.offset = 0 + self.rotation = 0 + self.is_root = 0 + self.border_surface = 0 + self.universe_offset = 0 + self.universe_rotation = 0 + Card.__init__(self, card_string) + + # print method + def __str__(self): + string = "Universe Card: \n" + string += "Universe ID " + str(self.cell_id) + "\n" + string += "Comment " + str(self.cell_comment) + "\n" + string += "Is cell universe? " + str(cell_universe) + "\n" + if self.cell_universe: + string += "Cells in Universe " + str(self.cell_list) + "\n" + string += "Is root? " + str(self.is_root) + "\n" + if self.is_root: + string += "Bounding surface " + str(self.bounding_surface) + "\n" + if self.fill_type == uni_fill: + string += "Contains universe " + str(self.fill_id) + "\n" + else: + string += "Contains material " + self.fill_mat + "\n" + return string + + # Build from CellCard list + # Loops through cell list to identify any cells it contains. + # Also identifies which cells contain it and takes their + # cell transformations as its own. + def build_from_cell_list(self, id, cell_list): + self.cell_list = [] + self.universe_id = id + + # This is the root universe + if id == 0: + self.is_root = 1 + + for cell in cell_list: + + # Universe contains this cell + if cell.cell_universe == id: + self.cell_list.append(cell.cell_id) + + # Root universe cell must be defined by only one surface + if id == 0: + self.bounding_surface = abs(cell.surfaces[0].surface_id) + + + # Universe is contained by this cell + if cell.cell_fill == id: + + # Apply rotations and transformations as appropriate + if cell.cell_universe_rotation != 0: + self.rotation = cell.cell_universe_rotation + + if cell.cell_universe_translation != 0: + self.translation = cell.cell_universe_translation + + + + From 6d5bfab0bed4fa369f8ec220f6dda1de2ac30ffd Mon Sep 17 00:00:00 2001 From: ChasingNeutrons Date: Sat, 21 Sep 2024 12:57:40 +0100 Subject: [PATCH 3/6] Basically works Still need to fix material densities... --- csg2csg/Input.py | 42 ++++++++++++++++++--- csg2csg/SCONECellCard.py | 17 ++++----- csg2csg/SCONEInput.py | 73 +++++++++++++++++++++++++----------- csg2csg/SCONEMaterialCard.py | 55 ++++----------------------- csg2csg/SCONESurfaceCard.py | 43 ++++++++++----------- csg2csg/SCONEUniverseCard.py | 23 ++++++------ csg2csg/UniverseCard.py | 48 +++++++++++++++--------- csg2csg/__main__.py | 3 +- 8 files changed, 166 insertions(+), 138 deletions(-) diff --git a/csg2csg/Input.py b/csg2csg/Input.py index 383b331..cd466a9 100644 --- a/csg2csg/Input.py +++ b/csg2csg/Input.py @@ -1,5 +1,6 @@ # /usr/env/python3 - +from csg2csg.UniverseCard import UniverseCard, uni_fill, mat_fill +import copy class InputDeck: """InputDeck class from which other concrete examples @@ -77,6 +78,7 @@ def from_input(self, InputDeckClass): self.cell_list = InputDeckClass.cell_list self.surface_list = InputDeckClass.surface_list self.material_list = InputDeckClass.material_list + self.universe_list = InputDeckClass.universe_list return # step through each cell and determine if the cell can @@ -92,9 +94,39 @@ def split_unions(self): # prepare universe entries given cells def create_universes_from_cells(self): universe_ids = set() + # count unique universe IDs - universe_ids.add(cell.universe for cell in self.cell_list) + universe_ids.update(cell.cell_universe for cell in self.cell_list) + + # Maybe set is empty? In which case, put every cell in universe 1 + #if not universe_ids: + # universe_ids.add(1) + # for cell in self.cell_list: + # cell.cell_universe = 1 + for uni in universe_ids: - self.universe_list.append( - UniverseCard(universe_ids[uni],self.cell_list) - ) + newUni = UniverseCard() + newUni.build_from_cell_list(uni,self.cell_list) + self.universe_list.append(newUni) + + # Need to ensure there is both a root universe and, if cells, + # a cell universe to hold them. This may imply adding another + # universe to the geometry and changing the cell universe IDs. + # First need to identify whether the root universe has cells. + # If so, duplicate the universe, make the new universe a cell + # universe without being root, remove cells from the root universe, + # and make the root universe contain the new universe. + for uni in self.universe_list: + if uni.is_root: + if uni.cell_list: + newID = max(universe_ids) + 1 + newUni = copy.copy(uni) + newUni.universe_id = newID + newUni.is_root = 0 + newUni.border_surface = 0 + uni.cell_list = [] + uni.fill_type = uni_fill + uni.fill_id = newID + self.universe_list.append(newUni) + + return diff --git a/csg2csg/SCONECellCard.py b/csg2csg/SCONECellCard.py index d77c1c6..f401820 100644 --- a/csg2csg/SCONECellCard.py +++ b/csg2csg/SCONECellCard.py @@ -34,15 +34,17 @@ def scone_op_from_generic(Operation): # write the cell card for a scone cell given a generic cell card def write_scone_cell(filestream, CellCard): - # If cell is in the root universe and outside the boundary, skip it. + # In root universe, identify ....... # Presently assumes only two cells in the root, with one surface, # as in Serpent. - if CellCard.universe == 0 and CellCard.surfaces[0] >= 0: - return + # Allow multiple cells in root. Fix this later! + #if (CellCard.cell_universe == 0 and + #CellCard.cell_surface_list[0] >= 0): + # return # print (CellCard) - string = str(CellCard.cell_id) + "{type unionCell; id " - string += str(cellCard.cell_id) + "; " + string = str(CellCard.cell_id) + " { type unionCell; id " + string += str(CellCard.cell_id) + "; " # Need to keep track of universe definitions and return # to write these separately @@ -62,7 +64,7 @@ def write_scone_cell(filestream, CellCard): # build the cell description for item in CellCard.cell_interpreted: - string += serpent_op_from_generic(item) + string += scone_op_from_generic(item) string += " ]; }\n" @@ -73,6 +75,3 @@ def write_scone_cell(filestream, CellCard): filestream.write(string) -class SCONECellCard(CellCard): - def __init__(self, card_string): - CellCard.__init__(self, card_string) diff --git a/csg2csg/SCONEInput.py b/csg2csg/SCONEInput.py index fb966aa..08ede73 100644 --- a/csg2csg/SCONEInput.py +++ b/csg2csg/SCONEInput.py @@ -1,9 +1,10 @@ # /usr/env/python3 from csg2csg.Input import InputDeck -from csg2csg.SCONESurfaceCard import SCONESurfaceCard, write_scone_surface -from csg2csg.SCONECellCard import SCONECellCard, write_scone_cell -from csg2csg.SCONEMaterialCard import SCONEMaterialCard, write_scone_material +from csg2csg.SCONESurfaceCard import write_scone_surface +from csg2csg.SCONECellCard import write_scone_cell +from csg2csg.SCONEMaterialCard import write_scone_material +from csg2csg.SCONEUniverseCard import write_scone_universe import logging import re @@ -16,14 +17,38 @@ class SCONEInput(InputDeck): def __init__(self, filename=""): InputDeck.__init__(self, filename) - # write the SCONE surface definitions - def __write_scone_surfaces(self, filestream): - filestream.write("% --- surface definitions --- %\n") - # Open the SCONE geometry card + # open the geometry card + def __write_scone_geometry_start(self, filestream): filestream.write("geometry { \n") - # Surely there is a way to customise this? + # Surely there is a way to customise this? Am I missing a + # method somewhere? For now I will leave as vacuum - should be easy + # for the user to change filestream.write("boundary (0 0 0 0 0 0); \n") filestream.write("graph {type shrunk;} \n") + return + + # close the geometry card + def __write_scone_geometry_end(self, filestream): + filestream.write("} \n") + return + + # open the nuclear data card + def __write_scone_data_start(self, filestream): + filestream.write("nuclearData { \n") + filestream.write("handles { \n") + filestream.write("ce {type aceNeutronDatabase; ") + filestream.write("acelibrary $SCONE_ACE; ures 0;} \n") + filestream.write("} \n") + return + + # close the data card + def __write_scone_data_end(self, filestream): + filestream.write("} \n") + return + + # write the SCONE surface definitions + def __write_scone_surfaces(self, filestream): + filestream.write("! --- surface definitions --- !\n") filestream.write("surfaces { \n") for surface in self.surface_list: write_scone_surface(filestream, surface) @@ -32,38 +57,44 @@ def __write_scone_surfaces(self, filestream): # Write the SCONE Cell definitions def __write_scone_cells(self, filestream): - filestream.write("% --- cell definitions --- %\n") + filestream.write("! --- cell definitions --- !\n") filestream.write("cells { \n") for cell in self.cell_list: write_scone_cell(filestream, cell) filestream.write("} \n") - # Close the SCONE geometry card - # Need to do something about universes! - # E.g., add in a rootUniverse and a single cellUniverse containing all cells - # Most codes have universes implicit in their cells, complicating things slightly. - filestream.write("} \n") return + # Write the SCONE universe definitions + # Most codes have universes implicit in their cells, complicating things + # slightly. + def __write_scone_universes(self, filestream): + filestream.write("! --- universe definitions --- !\n") + filestream.write("universes { \n") + for universe in self.universe_list: + write_scone_universe(filestream, universe) + filestream.write("} \n") + # write the material compositions def __write_scone_materials(self, filestream): - filestream.write("% --- material definitions --- %\n") - # Open the SCONE nuclearData card - filestream.write("nuclearData { \n") - filestream.write("handles { \n") - filestream.write("ce {type aceNeutronDatabase; acelibrary $SCONE_ACE; ures 0;} \n") - filestream.write("} \n") + filestream.write("! --- material definitions --- !\n") filestream.write("materials { \n") for material in self.material_list: write_scone_material(filestream, self.material_list[material]) filestream.write("} \n") - filestream.write("} \n") return + # main write scone method, depending upon where the geometry # came from def write_scone(self, filename, flat=True): f = open(filename, "w") + self.__write_scone_geometry_start(f) self.__write_scone_surfaces(f) self.__write_scone_cells(f) + self.create_universes_from_cells() + self.__write_scone_universes(f) + self.__write_scone_geometry_end(f) + self.__write_scone_data_start(f) self.__write_scone_materials(f) + self.__write_scone_data_end(f) f.close() diff --git a/csg2csg/SCONEMaterialCard.py b/csg2csg/SCONEMaterialCard.py index f4c92e7..b66f461 100644 --- a/csg2csg/SCONEMaterialCard.py +++ b/csg2csg/SCONEMaterialCard.py @@ -4,63 +4,22 @@ from csg2csg.MCNPFormatter import get_fortran_formatted_number # write a specific serpent material card -def write_scone_material(filestream, material): +def write_scone_material(filestream, MaterialCard): - string = "! " + self.material_name + " \n" - string += str(material.material_number) + "{ \n" + string = "! " + MaterialCard.material_name + " \n" + string += str(MaterialCard.material_number) + " { \n" string += "composition { \n" - for nuc in material.composition_dictionary: + for nuc in MaterialCard.composition_dictionary: string += "{} {:e}; \n".format( - nuc, material.composition_dictionary[nuc] + nuc, MaterialCard.composition_dictionary[nuc] ) string += "} \n" # if its a non tally material set the relevant colour - if material.material_colour: - string += " rgb (" + material.material_colour + "); \n" - else: - string += "\n" + if MaterialCard.material_colour: + string += "rgb (" + MaterialCard.material_colour + "); \n" string += "} \n" filestream.write(string) return - -""" Class to handle SCONEMaterialCard translation -""" - - -class SCONEMaterialCard(MaterialCard): - def __init__(self, material_number, material_name, - material_density, card_string): - MaterialCard.__init__(self, material_number, card_string) - self.material_name = material_name - self.material_number = material_number - self.density = material_density - self.__process_string() - - # populate the SCONE Material Card - def __process_string(self): - # need to reset the dictionary - # otherwise state seems to linger - weird - self.composition_dictionary = {} - - mat_string = self.text_string - mat_string = mat_string.replace("\n", " ") - - # split string - tokens = mat_string.split() - - if len(tokens) % 2 != 0: - raise Exception("Material string not correctly processed") - - while len(tokens) != 0: - nuclide = tokens[0].split(".") - xsid = nuclide[0] - temp = nuclide[1].rstrip('c') - frac = get_fortran_formatted_number(tokens[1]) - tokens.pop(0) - tokens.pop(0) - self.composition_dictionary[nucid] = frac - self.xsid_dictionary[nucid] = xsid + "." + temp - return diff --git a/csg2csg/SCONESurfaceCard.py b/csg2csg/SCONESurfaceCard.py index 8ff8eb7..8cc4a98 100644 --- a/csg2csg/SCONESurfaceCard.py +++ b/csg2csg/SCONESurfaceCard.py @@ -9,25 +9,28 @@ def scone_plane_string(SurfaceCard): string += str(SurfaceCard.surface_coefficients[0]) + " " string += str(SurfaceCard.surface_coefficients[1]) + " " string += str(SurfaceCard.surface_coefficients[2]) + " " - string += str(SurfaceCard.surface_coefficients[3]) + "); " + string += str(SurfaceCard.surface_coefficients[3]) + "); } \n" return string # write the specific x form of the plane def scone_plane_x_string(SurfaceCard): - string = " xPlane; x0 " + str(SurfaceCard.surface_coefficients[3]) + ";" + string = " xPlane; x0 " + str(SurfaceCard.surface_coefficients[3]) + string += "; } \n" return string # write the specific y form of the plane def scone_plane_y_string(SurfaceCard): - string = " yPlane; y0 " + str(SurfaceCard.surface_coefficients[3]) + ";" + string = " yPlane; y0 " + str(SurfaceCard.surface_coefficients[3]) + string += "; } \n" return string # write the specific z form of the plane def scone_plane_z_string(SurfaceCard): - string = " zPlane; z0 " + str(SurfaceCard.surface_coefficients[3]) + ";" + string = " zPlane; z0 " + str(SurfaceCard.surface_coefficients[3]) + string += "; } \n" return string @@ -35,7 +38,7 @@ def scone_plane_z_string(SurfaceCard): def scone_cylinder_x(SurfaceCard): string = " xCylinder; radius " + str(SurfaceCard.surface_coefficients[0]) string += "; origin ( 0.0 " + str(SurfaceCard.surface_coefficients[1]) - string += " " + str(SurfaceCard.surface_coefficients[2]) + "); " + string += " " + str(SurfaceCard.surface_coefficients[2]) + "); } \n" return string @@ -43,7 +46,7 @@ def scone_cylinder_x(SurfaceCard): def scone_cylinder_y(SurfaceCard): string = " yCylinder; radius " + str(SurfaceCard.surface_coefficients[0]) string += "; origin (" + str(SurfaceCard.surface_coefficients[1]) + " 0 " - string += str(SurfaceCard.surface_coefficients[2]) + "); " + string += str(SurfaceCard.surface_coefficients[2]) + "); } \n" return string @@ -51,16 +54,16 @@ def scone_cylinder_y(SurfaceCard): def scone_cylinder_z(SurfaceCard): string = " zCylinder; radius " + str(SurfaceCard.surface_coefficients[0]) string += "; origin (" + str(SurfaceCard.surface_coefficients[1]) + " " - string += str(SurfaceCard.surface_coefficients[2]) + " 0); " + string += str(SurfaceCard.surface_coefficients[2]) + " 0); } \n" return string # write a sphere def scone_sphere(SurfaceCard): - string = " sphere; radius " + str(SurfaceCard.surface_coefficients[0]) - string += "; origin (" + str(SurfaceCard.surface_coefficients[1]) + " " - string += str(SurfaceCard.surface_coefficients[2]) + " " - string += str(SurfaceCard.surface_coefficients[3]) + "); " + string = " sphere; origin (" + str(SurfaceCard.surface_coefficients[0]) + string += str(SurfaceCard.surface_coefficients[1]) + " " + string += str(SurfaceCard.surface_coefficients[2]) + "); radius " + string += str(SurfaceCard.surface_coefficients[3]) + "; } \n" return string @@ -69,7 +72,7 @@ def scone_gq(SurfaceCard): string = " quadric; coeffs ( " for coefficient in SurfaceCard.surface_coefficients: string += " " + str(coefficient) + " " - string += "); " + string += "); } \n" return string @@ -98,7 +101,7 @@ def scone_cone_x(SurfaceCard): string = " {} {:f} {:f} {:f} {}\n".format( " xCone; vertex (", x, y, z," ); ") string += "angle " + str(angle) + "; hMin " + str(hMin) - string += "; hMax " + str(hMax) + "; \n" + string += "; hMax " + str(hMax) + "; } \n" return string @@ -129,7 +132,7 @@ def scone_cone_y(SurfaceCard): string = " {} {:f} {:f} {:f} {}\n".format( " yCone; vertex (", x, y, z," ); ") string += "angle " + str(angle) + "; hMin " + str(hMin) - string += "; hMax " + str(hMax) + "; \n" + string += "; hMax " + str(hMax) + "; } \n" return string @@ -160,7 +163,7 @@ def scone_cone_z(SurfaceCard): string = " {} {:f} {:f} {:f} {}\n".format( " zCone; vertex (", x, y, z," ); ") string += "angle " + str(angle) + "; hMin " + str(hMin) - string += "; hMax " + str(hMax) + "; \n" + string += "; hMax " + str(hMax) + "; } \n" return string @@ -272,7 +275,7 @@ def serpent_cone_z(SurfaceCard): # write the surface description to file def write_scone_surface(filestream, SurfaceCard): - string = str(SurfaceCard.surface_id) + "{ id " + string = str(SurfaceCard.surface_id) + " { id " string += str(SurfaceCard.surface_id) + "; type " if SurfaceCard.surface_type is SurfaceCard.SurfaceType["PLANE_GENERAL"]: @@ -314,13 +317,5 @@ def write_scone_surface(filestream, SurfaceCard): else: filestream.write("surface not supported\n") - string += " }\n" return - -class SCONESurfaceCard(SurfaceCard): - def __init__(self, card_string): - SurfaceCard.__init__(self, card_string) - - def write(self): - print("hello") diff --git a/csg2csg/SCONEUniverseCard.py b/csg2csg/SCONEUniverseCard.py index 2ca51a6..718a67a 100644 --- a/csg2csg/SCONEUniverseCard.py +++ b/csg2csg/SCONEUniverseCard.py @@ -11,35 +11,37 @@ def write_scone_universe(filestream, UniverseCard): # print (UniverseCard) # TODO support lattice universes - string = str(UniverseCard.universe_id) + "{ type " + string = str(UniverseCard.universe_id + 1) + " { type " if UniverseCard.is_root: string += "rootUniverse; " string += "border " + str(UniverseCard.border_surface) + "; " if UniverseCard.fill_type == uni_fill: - string += "fill u<" + str(UniverseCard.fill_id) + ">; " - else: + string += "fill u<" + str(UniverseCard.fill_id + 1) + ">; " + if UniverseCard.fill_type == mat_fill: string += "fill " + str(UniverseCard.fill_material) + "; " else: - string += "cellUniverse; " - string += "cells (" + str(UniverseCard.cell_list) + "); " + string += "cellUniverse; cells (" + for cell_id in UniverseCard.cell_list: + string += str(cell_id) + " " + string += "); " # Need to increment by 1 due to SCONE not allowing Universe ID = 0 # This is used by other codes to denote the base/root universe string += "id " + str(UniverseCard.universe_id + 1) +"; " # Include transformations - if UniverseCard.origin != 0: + if UniverseCard.universe_offset != 0: # Convert origin to a translation string += "translation (" for i in range(3): - string += str(UniverseCard.origin[i]) +" " + string += str(UniverseCard.universe_offset[i]) +" " string += "); " - if UniverseCard.rotation != 0: + if UniverseCard.universe_rotation != 0: # Convert rotation matrix to Euler angles following ZXZ convention # Need to double check conventions: rotate[5] might have a negative # sign and rot[2] might be * -1 - rotate = UniverseCard.rotation + rotate = UniverseCard.universe_rotation rot[0] = math.atan2(rotate[2],-rotate[5]) rot[1] = math.acos(rotate[8]) rot[2] = math.atan2(rotate[6],rotate[7]) @@ -55,7 +57,4 @@ def write_scone_universe(filestream, UniverseCard): string = mcnp_line_formatter(string) filestream.write(string) -class SCONEUniverseCard(UniverseCard): - def __init__(self, card_string): - UniverseCard.__init__(self, card_string) diff --git a/csg2csg/UniverseCard.py b/csg2csg/UniverseCard.py index 61db533..3a5e545 100644 --- a/csg2csg/UniverseCard.py +++ b/csg2csg/UniverseCard.py @@ -17,7 +17,7 @@ class UniverseCard(Card): """ # constructor for the universecard class - def __init__(self, card_string): + def __init__(self): self.universe_comment = "" self.universe_id = 0 self.cell_list = set() @@ -30,19 +30,19 @@ def __init__(self, card_string): self.border_surface = 0 self.universe_offset = 0 self.universe_rotation = 0 - Card.__init__(self, card_string) + #Card.__init__(self, card_string) # print method def __str__(self): string = "Universe Card: \n" - string += "Universe ID " + str(self.cell_id) + "\n" - string += "Comment " + str(self.cell_comment) + "\n" - string += "Is cell universe? " + str(cell_universe) + "\n" - if self.cell_universe: + string += "Universe ID " + str(self.universe_id) + "\n" + string += "Comment " + str(self.universe_comment) + "\n" + string += "Is cell universe? " + str(bool(self.cell_list)) + "\n" + if bool(self.cell_list): string += "Cells in Universe " + str(self.cell_list) + "\n" string += "Is root? " + str(self.is_root) + "\n" if self.is_root: - string += "Bounding surface " + str(self.bounding_surface) + "\n" + string += "Bounding surface " + str(self.border_surface) + "\n" if self.fill_type == uni_fill: string += "Contains universe " + str(self.fill_id) + "\n" else: @@ -53,34 +53,46 @@ def __str__(self): # Loops through cell list to identify any cells it contains. # Also identifies which cells contain it and takes their # cell transformations as its own. - def build_from_cell_list(self, id, cell_list): + def build_from_cell_list(self, uni_id, cell_list): self.cell_list = [] - self.universe_id = id + self.universe_id = uni_id + + #print(self.__str__()) + #print(uni_id) # This is the root universe - if id == 0: + if uni_id == 0: self.is_root = 1 for cell in cell_list: # Universe contains this cell - if cell.cell_universe == id: + if cell.cell_universe == uni_id: self.cell_list.append(cell.cell_id) - # Root universe cell must be defined by only one surface - if id == 0: - self.bounding_surface = abs(cell.surfaces[0].surface_id) + # Search the root universe for a cell which has a single + # surface in which it is in the positive halfspace. + # This is (probably??) the bounding surface. + # The indicator that a cell is definitely in the positive + # halfspace comes from cell_text_description. Check it for + # a single entry which is positive. + numeric_list = [item for item in cell.cell_text_description if item.lstrip('-').isdigit()] + halfspaces = [int(x) for x in numeric_list] + if (uni_id == 0 and len(halfspaces) == 1): + surface_id = halfspaces[0] + if surface_id > 0: + self.border_surface = surface_id # Universe is contained by this cell - if cell.cell_fill == id: + if cell.cell_fill == uni_id: # Apply rotations and transformations as appropriate if cell.cell_universe_rotation != 0: - self.rotation = cell.cell_universe_rotation + self.universe_rotation = cell.cell_universe_rotation - if cell.cell_universe_translation != 0: - self.translation = cell.cell_universe_translation + if cell.cell_universe_offset != 0: + self.universe_offset = cell.cell_universe_offset diff --git a/csg2csg/__main__.py b/csg2csg/__main__.py index bb4f0f0..e9191c4 100755 --- a/csg2csg/__main__.py +++ b/csg2csg/__main__.py @@ -5,6 +5,7 @@ from csg2csg.OpenMCInput import OpenMCInput from csg2csg.FLUKAInput import FLUKAInput from csg2csg.PhitsInput import PhitsInput +from csg2csg.SCONEInput import SCONEInput # for debug info import logging, sys @@ -71,7 +72,7 @@ def main(): filename = args.input if "all" in args.output: - codes = ["mcnp", "serpent", "openmc", "phits", "fluka"] + codes = ["mcnp", "serpent", "openmc", "phits", "fluka", "scone"] else: codes = args.output From 4d752d74adea0fc38e0c2cc1343df605a8dfd639 Mon Sep 17 00:00:00 2001 From: ChasingNeutrons Date: Mon, 13 Jan 2025 22:05:48 +0000 Subject: [PATCH 4/6] I think it works --- csg2csg/MCNPCellCard.py | 2 +- csg2csg/SCONECellCard.py | 2 +- csg2csg/SCONEMaterialCard.py | 4 +++- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/csg2csg/MCNPCellCard.py b/csg2csg/MCNPCellCard.py index f8f6281..a975c08 100644 --- a/csg2csg/MCNPCellCard.py +++ b/csg2csg/MCNPCellCard.py @@ -313,7 +313,7 @@ def __interpret(self): tokens = self.text_string.split() tokens = string.split() - + self.cell_id = int(tokens[0]) material_number = int(tokens[1]) if material_number > 0: diff --git a/csg2csg/SCONECellCard.py b/csg2csg/SCONECellCard.py index f401820..b4a4c9f 100644 --- a/csg2csg/SCONECellCard.py +++ b/csg2csg/SCONECellCard.py @@ -58,7 +58,7 @@ def write_scone_cell(filestream, CellCard): if CellCard.cell_material_number == 0: string += " void; " else: - string += str(CellCard.cell_material_number) + " " + string += str(CellCard.cell_material_number) + "; " string += "surfaces [ " diff --git a/csg2csg/SCONEMaterialCard.py b/csg2csg/SCONEMaterialCard.py index b66f461..df83004 100644 --- a/csg2csg/SCONEMaterialCard.py +++ b/csg2csg/SCONEMaterialCard.py @@ -9,8 +9,10 @@ def write_scone_material(filestream, MaterialCard): string = "! " + MaterialCard.material_name + " \n" string += str(MaterialCard.material_number) + " { \n" string += "composition { \n" + # Stick on .03 regardless until something to read temperature + # from MCNP is added! for nuc in MaterialCard.composition_dictionary: - string += "{} {:e}; \n".format( + string += "{}.03 {:e}; \n".format( nuc, MaterialCard.composition_dictionary[nuc] ) string += "} \n" From 8236655ce0766529f52eab991f078c5f4821e161 Mon Sep 17 00:00:00 2001 From: ChasingNeutrons Date: Tue, 14 Jan 2025 01:46:44 +0000 Subject: [PATCH 5/6] Tweaks for ATR geometry --- csg2csg/MaterialCard.py | 1 + csg2csg/SCONECellCard.py | 3 ++- csg2csg/SCONEInput.py | 3 ++- csg2csg/SCONEMaterialCard.py | 11 +++++++---- csg2csg/SCONESurfaceCard.py | 18 +++++++++--------- csg2csg/SCONEUniverseCard.py | 6 ++++-- 6 files changed, 25 insertions(+), 17 deletions(-) diff --git a/csg2csg/MaterialCard.py b/csg2csg/MaterialCard.py index 56b0f0e..b7f5591 100644 --- a/csg2csg/MaterialCard.py +++ b/csg2csg/MaterialCard.py @@ -170,3 +170,4 @@ def explode_elements(self): for key in new_nuclides.keys(): self.composition_dictionary[key] = new_nuclides[key] self.xsid_dictionary[key] = "" + diff --git a/csg2csg/SCONECellCard.py b/csg2csg/SCONECellCard.py index b4a4c9f..72060c5 100644 --- a/csg2csg/SCONECellCard.py +++ b/csg2csg/SCONECellCard.py @@ -52,13 +52,14 @@ def write_scone_cell(filestream, CellCard): string += " filltype uni; universe " + str(CellCard.cell_fill) + "; " # Doesn't have a universe - has a material + # Due to SCONE weirdness, all materials are preceded with an 'm' if CellCard.cell_fill == 0: # material 0 is void string += " filltype mat; material " if CellCard.cell_material_number == 0: string += " void; " else: - string += str(CellCard.cell_material_number) + "; " + string += "m" + str(CellCard.cell_material_number) + "; " string += "surfaces [ " diff --git a/csg2csg/SCONEInput.py b/csg2csg/SCONEInput.py index 08ede73..5bf65bd 100644 --- a/csg2csg/SCONEInput.py +++ b/csg2csg/SCONEInput.py @@ -23,6 +23,7 @@ def __write_scone_geometry_start(self, filestream): # Surely there is a way to customise this? Am I missing a # method somewhere? For now I will leave as vacuum - should be easy # for the user to change + filestream.write("type geometryStd; \n") filestream.write("boundary (0 0 0 0 0 0); \n") filestream.write("graph {type shrunk;} \n") return @@ -37,7 +38,7 @@ def __write_scone_data_start(self, filestream): filestream.write("nuclearData { \n") filestream.write("handles { \n") filestream.write("ce {type aceNeutronDatabase; ") - filestream.write("acelibrary $SCONE_ACE; ures 0;} \n") + filestream.write("aceLibrary $SCONE_ACE; ures 0;} \n") filestream.write("} \n") return diff --git a/csg2csg/SCONEMaterialCard.py b/csg2csg/SCONEMaterialCard.py index df83004..7268115 100644 --- a/csg2csg/SCONEMaterialCard.py +++ b/csg2csg/SCONEMaterialCard.py @@ -3,21 +3,24 @@ from csg2csg.MaterialCard import MaterialCard from csg2csg.MCNPFormatter import get_fortran_formatted_number -# write a specific serpent material card +# write a specific scone material card def write_scone_material(filestream, MaterialCard): string = "! " + MaterialCard.material_name + " \n" - string += str(MaterialCard.material_number) + " { \n" + string += "m" + str(MaterialCard.material_number) + " { \n" string += "composition { \n" # Stick on .03 regardless until something to read temperature # from MCNP is added! + # Multiply by adens because SCONE requires absolute densities for nuc in MaterialCard.composition_dictionary: + adens = MaterialCard.density string += "{}.03 {:e}; \n".format( - nuc, MaterialCard.composition_dictionary[nuc] + nuc, MaterialCard.composition_dictionary[nuc] * adens ) + string += "} \n" - # if its a non tally material set the relevant colour + # set the relevant colour if MaterialCard.material_colour: string += "rgb (" + MaterialCard.material_colour + "); \n" diff --git a/csg2csg/SCONESurfaceCard.py b/csg2csg/SCONESurfaceCard.py index 8cc4a98..6f2cc4c 100644 --- a/csg2csg/SCONESurfaceCard.py +++ b/csg2csg/SCONESurfaceCard.py @@ -36,25 +36,25 @@ def scone_plane_z_string(SurfaceCard): # write a cylinder_x def scone_cylinder_x(SurfaceCard): - string = " xCylinder; radius " + str(SurfaceCard.surface_coefficients[0]) - string += "; origin ( 0.0 " + str(SurfaceCard.surface_coefficients[1]) - string += " " + str(SurfaceCard.surface_coefficients[2]) + "); } \n" + string = " xCylinder; radius " + str(SurfaceCard.surface_coefficients[2]) + string += "; origin ( 0.0 " + str(SurfaceCard.surface_coefficients[0]) + string += " " + str(SurfaceCard.surface_coefficients[1]) + "); } \n" return string # write a cylinder_y def scone_cylinder_y(SurfaceCard): - string = " yCylinder; radius " + str(SurfaceCard.surface_coefficients[0]) - string += "; origin (" + str(SurfaceCard.surface_coefficients[1]) + " 0 " - string += str(SurfaceCard.surface_coefficients[2]) + "); } \n" + string = " yCylinder; radius " + str(SurfaceCard.surface_coefficients[2]) + string += "; origin (" + str(SurfaceCard.surface_coefficients[0]) + " 0 " + string += str(SurfaceCard.surface_coefficients[1]) + "); } \n" return string # write a cylinder_z def scone_cylinder_z(SurfaceCard): - string = " zCylinder; radius " + str(SurfaceCard.surface_coefficients[0]) - string += "; origin (" + str(SurfaceCard.surface_coefficients[1]) + " " - string += str(SurfaceCard.surface_coefficients[2]) + " 0); } \n" + string = " zCylinder; radius " + str(SurfaceCard.surface_coefficients[2]) + string += "; origin (" + str(SurfaceCard.surface_coefficients[0]) + " " + string += str(SurfaceCard.surface_coefficients[1]) + " 0); } \n" return string diff --git a/csg2csg/SCONEUniverseCard.py b/csg2csg/SCONEUniverseCard.py index 718a67a..d4ea43a 100644 --- a/csg2csg/SCONEUniverseCard.py +++ b/csg2csg/SCONEUniverseCard.py @@ -11,15 +11,17 @@ def write_scone_universe(filestream, UniverseCard): # print (UniverseCard) # TODO support lattice universes - string = str(UniverseCard.universe_id + 1) + " { type " if UniverseCard.is_root: + string = "root { type " string += "rootUniverse; " string += "border " + str(UniverseCard.border_surface) + "; " if UniverseCard.fill_type == uni_fill: string += "fill u<" + str(UniverseCard.fill_id + 1) + ">; " if UniverseCard.fill_type == mat_fill: - string += "fill " + str(UniverseCard.fill_material) + "; " + # Name preceded by an m due to SCONE weirdness + string += "fill m" + str(UniverseCard.fill_material) + "; " else: + string = str(UniverseCard.universe_id + 1) + " { type " string += "cellUniverse; cells (" for cell_id in UniverseCard.cell_list: string += str(cell_id) + " " From 0e9141af6787a385b39a445992fea364342155d9 Mon Sep 17 00:00:00 2001 From: ChasingNeutrons Date: Fri, 9 May 2025 14:44:01 +0100 Subject: [PATCH 6/6] Add SCONE Complicated by having explicit cell universes. Also fixed an OpenMC test name. --- csg2csg/Input.py | 2 +- csg2csg/MCNPInput.py | 24 +++++----- csg2csg/MCNPSurfaceCard.py | 2 - csg2csg/SCONECellCard.py | 2 +- csg2csg/SCONEInput.py | 2 +- csg2csg/SCONEMaterialCard.py | 12 ++++- csg2csg/SCONESurfaceCard.py | 48 ++++++++++++++----- csg2csg/UniverseCard.py | 14 ++++-- ...enmcmaterial.py => test_openmcmaterial.py} | 0 9 files changed, 71 insertions(+), 35 deletions(-) rename tests/{terst_openmcmaterial.py => test_openmcmaterial.py} (100%) diff --git a/csg2csg/Input.py b/csg2csg/Input.py index cd466a9..439246c 100644 --- a/csg2csg/Input.py +++ b/csg2csg/Input.py @@ -96,7 +96,7 @@ def create_universes_from_cells(self): universe_ids = set() # count unique universe IDs - universe_ids.update(cell.cell_universe for cell in self.cell_list) + universe_ids.update(int(cell.cell_universe) for cell in self.cell_list) # Maybe set is empty? In which case, put every cell in universe 1 #if not universe_ids: diff --git a/csg2csg/MCNPInput.py b/csg2csg/MCNPInput.py index 142923f..400a390 100644 --- a/csg2csg/MCNPInput.py +++ b/csg2csg/MCNPInput.py @@ -635,15 +635,15 @@ def __simplify_cones(self): # loop over the surfaces for surf in self.surface_list: # if we are a cone - print( - surf.surface_type, - surf.surface_type - in [ - SurfaceCard.SurfaceType["CONE_X"], - SurfaceCard.SurfaceType["CONE_Y"], - SurfaceCard.SurfaceType["CONE_Z"], - ], - ) + #print( + # surf.surface_type, + # surf.surface_type + # in [ + # SurfaceCard.SurfaceType["CONE_X"], + # SurfaceCard.SurfaceType["CONE_Y"], + # SurfaceCard.SurfaceType["CONE_Z"], + # ], + #) if surf.surface_type in [ SurfaceCard.SurfaceType["CONE_X"], SurfaceCard.SurfaceType["CONE_Y"], @@ -1166,7 +1166,7 @@ def __get_surface_cards(self, idx): while True: surf_line = strip_dollar_comments(self.file_lines[idx]) if surf_line.isspace(): - logging.debug("%s", "found end of cell cards at line " + str(idx)) + logging.debug("%s", "found end of surface cards at line " + str(idx)) idx += 1 break @@ -1343,7 +1343,7 @@ def process(self): self.__get_material_cards(idx) # need to flatten first to get transformed surface in the # correct place - self.__simplify_cones() + #self.__simplify_cones() self.__flatten_macrobodies() self.__explode_nots() @@ -1401,7 +1401,7 @@ def __write_mcnp_materials(self, filestream): filestream, self.material_list[material], self.preserve_xsid ) - # main write MCNP method, depnds on where the geometry + # main write MCNP method, depends on where the geometry # came from def write_mcnp(self, filename, flat=True): f = open(filename, "w") diff --git a/csg2csg/MCNPSurfaceCard.py b/csg2csg/MCNPSurfaceCard.py index fda1aef..16cbafb 100644 --- a/csg2csg/MCNPSurfaceCard.py +++ b/csg2csg/MCNPSurfaceCard.py @@ -142,7 +142,6 @@ def mcnp_cone_y(SurfaceCard): # write the mcnp form of an cone aligned along the z axis def mcnp_cone_z(SurfaceCard): string = "k/z " - print(SurfaceCard.surface_coefficients) string += str(SurfaceCard.surface_coefficients[0]) + " " string += str(SurfaceCard.surface_coefficients[1]) + " " string += str(SurfaceCard.surface_coefficients[2]) + " " @@ -224,7 +223,6 @@ def write_mcnp_surface(filestream, SurfaceCard): elif SurfaceCard.surface_type == SurfaceCard.SurfaceType["PLANE_Y"]: string += mcnp_plane_y(SurfaceCard) elif SurfaceCard.surface_type == SurfaceCard.SurfaceType["PLANE_Z"]: - print(SurfaceCard) string += mcnp_plane_z(SurfaceCard) elif SurfaceCard.surface_type == SurfaceCard.SurfaceType["CYLINDER_X"]: string += mcnp_cylinder_x(SurfaceCard) diff --git a/csg2csg/SCONECellCard.py b/csg2csg/SCONECellCard.py index 72060c5..ed36681 100644 --- a/csg2csg/SCONECellCard.py +++ b/csg2csg/SCONECellCard.py @@ -49,7 +49,7 @@ def write_scone_cell(filestream, CellCard): # Need to keep track of universe definitions and return # to write these separately if CellCard.cell_fill != 0: - string += " filltype uni; universe " + str(CellCard.cell_fill) + "; " + string += " filltype uni; universe " + str(int(CellCard.cell_fill) + 1) + "; " # Doesn't have a universe - has a material # Due to SCONE weirdness, all materials are preceded with an 'm' diff --git a/csg2csg/SCONEInput.py b/csg2csg/SCONEInput.py index 5bf65bd..30e7211 100644 --- a/csg2csg/SCONEInput.py +++ b/csg2csg/SCONEInput.py @@ -20,10 +20,10 @@ def __init__(self, filename=""): # open the geometry card def __write_scone_geometry_start(self, filestream): filestream.write("geometry { \n") + filestream.write("type geometryStd; \n") # Surely there is a way to customise this? Am I missing a # method somewhere? For now I will leave as vacuum - should be easy # for the user to change - filestream.write("type geometryStd; \n") filestream.write("boundary (0 0 0 0 0 0); \n") filestream.write("graph {type shrunk;} \n") return diff --git a/csg2csg/SCONEMaterialCard.py b/csg2csg/SCONEMaterialCard.py index 7268115..fa7e001 100644 --- a/csg2csg/SCONEMaterialCard.py +++ b/csg2csg/SCONEMaterialCard.py @@ -12,8 +12,17 @@ def write_scone_material(filestream, MaterialCard): # Stick on .03 regardless until something to read temperature # from MCNP is added! # Multiply by adens because SCONE requires absolute densities + dens = MaterialCard.density + if dens > 0: + adens = dens + else: + molar_mass = 0 + for nuc in MaterialCard.composition_dictionary: + molar_mass += MaterialCard.composition_dictionary[nuc] * (int(nuc) % 1000) + + adens = -dens * 6.02214e-01 / molar_mass + for nuc in MaterialCard.composition_dictionary: - adens = MaterialCard.density string += "{}.03 {:e}; \n".format( nuc, MaterialCard.composition_dictionary[nuc] * adens ) @@ -27,4 +36,3 @@ def write_scone_material(filestream, MaterialCard): string += "} \n" filestream.write(string) return - diff --git a/csg2csg/SCONESurfaceCard.py b/csg2csg/SCONESurfaceCard.py index 6f2cc4c..761dd83 100644 --- a/csg2csg/SCONESurfaceCard.py +++ b/csg2csg/SCONESurfaceCard.py @@ -60,7 +60,7 @@ def scone_cylinder_z(SurfaceCard): # write a sphere def scone_sphere(SurfaceCard): - string = " sphere; origin (" + str(SurfaceCard.surface_coefficients[0]) + string = " sphere; origin (" + str(SurfaceCard.surface_coefficients[0]) + " " string += str(SurfaceCard.surface_coefficients[1]) + " " string += str(SurfaceCard.surface_coefficients[2]) + "); radius " string += str(SurfaceCard.surface_coefficients[3]) + "; } \n" @@ -81,22 +81,30 @@ def scone_cone_x(SurfaceCard): y = SurfaceCard.surface_coefficients[1] z = SurfaceCard.surface_coefficients[2] t2 = SurfaceCard.surface_coefficients[3] - sign = SurfaceCard.surface_coefficients[4] - # Do trigonometry to convert mcnp tangent squared, t2, into + if (len(SurfaceCard.surface_coefficients) < 5): + sign = 0 + else: + sign = SurfaceCard.surface_coefficients[4] + + # Do trigonometry to convert mcnp tangent squared, t2, into # angle and determine hMin and hMax. # If sign is negative, hMax = vertex = 0, hMin = -10E10 # If sign is positive, hMin = vertex = 0, hMax = 10E10 + # If +/- 1 is not present in the MCNP definition, make cone infinite # A bit of a fudge for now. # Assume no truncation, like in MCNP if sign < 0: hMin = -1E10 hMax = 0 - else: + elif sign > 0: hMin = 0 hMax = 1E10 + else: + hMin = -1E10 + hMax = 1E10 - angle = math.degrees(math.atan(math.sqrt(t2))) + angle = degrees(atan(sqrt(t2))) string = " {} {:f} {:f} {:f} {}\n".format( " xCone; vertex (", x, y, z," ); ") @@ -112,22 +120,30 @@ def scone_cone_y(SurfaceCard): y = SurfaceCard.surface_coefficients[1] z = SurfaceCard.surface_coefficients[2] t2 = SurfaceCard.surface_coefficients[3] - sign = SurfaceCard.surface_coefficients[4] - # Do trigonometry to convert mcnp tangent squared, t2, into + if (len(SurfaceCard.surface_coefficients) < 5): + sign = 0 + else: + sign = SurfaceCard.surface_coefficients[4] + + # Do trigonometry to convert mcnp tangent squared, t2, into # angle and determine hMin and hMax. # If sign is negative, hMax = vertex = 0, hMin = -10E10 # If sign is positive, hMin = vertex = 0, hMax = 10E10 + # If +/- 1 is not present in the MCNP definition, make cone infinite # A bit of a fudge for now. # Assume no truncation, like in MCNP if sign < 0: hMin = -1E10 hMax = 0 - else: + elif sign > 0: hMin = 0 hMax = 1E10 + else: + hMin = -1E10 + hMax = 1E10 - angle = math.degrees(math.atan(math.sqrt(t2))) + angle = degrees(atan(sqrt(t2))) string = " {} {:f} {:f} {:f} {}\n".format( " yCone; vertex (", x, y, z," ); ") @@ -143,22 +159,30 @@ def scone_cone_z(SurfaceCard): y = SurfaceCard.surface_coefficients[1] z = SurfaceCard.surface_coefficients[2] t2 = SurfaceCard.surface_coefficients[3] - sign = SurfaceCard.surface_coefficients[4] + + if (len(SurfaceCard.surface_coefficients) < 5): + sign = 0 + else: + sign = SurfaceCard.surface_coefficients[4] # Do trigonometry to convert mcnp tangent squared, t2, into # angle and determine hMin and hMax. # If sign is negative, hMax = vertex = 0, hMin = -10E10 # If sign is positive, hMin = vertex = 0, hMax = 10E10 + # If +/- 1 is not present in the MCNP definition, make cone infinite # A bit of a fudge for now. # Assume no truncation, like in MCNP if sign < 0: hMin = -1E10 hMax = 0 - else: + elif sign > 0: hMin = 0 hMax = 1E10 + else: + hMin = -1E10 + hMax = 1E10 - angle = math.degrees(math.atan(math.sqrt(t2))) + angle = degrees(atan(sqrt(t2))) string = " {} {:f} {:f} {:f} {}\n".format( " zCone; vertex (", x, y, z," ); ") diff --git a/csg2csg/UniverseCard.py b/csg2csg/UniverseCard.py index 3a5e545..ca41508 100644 --- a/csg2csg/UniverseCard.py +++ b/csg2csg/UniverseCard.py @@ -7,9 +7,9 @@ mat_fill = 2 class UniverseCard(Card): - """Class for the storage of the Generic UniverseCard type - methods for the generation of UniverseCards should be placed - here. Classes instanciating UniverseCard objects should be + """Class for the storage of the Generic UniverseCard type. + Methods for the generation of UniverseCards should be placed + here. Classes instantiating UniverseCard objects should be implemented in its own CodeUniverseCard.py file. This is primarily intended for SCONE - do any other codes have explicit cell universe cards? Maybe this is useful for @@ -67,7 +67,7 @@ def build_from_cell_list(self, uni_id, cell_list): for cell in cell_list: # Universe contains this cell - if cell.cell_universe == uni_id: + if int(cell.cell_universe) == uni_id: self.cell_list.append(cell.cell_id) # Search the root universe for a cell which has a single @@ -94,6 +94,12 @@ def build_from_cell_list(self, uni_id, cell_list): if cell.cell_universe_offset != 0: self.universe_offset = cell.cell_universe_offset + # Make sure there isn't something silly + #if (cell.cell_fill == uni_id) and (cell.cell_universe == uni_id): + # print(cell.cell_id) + # print(uni_id) + # raise ValueError('Cell contains and is contained by the same universe') + diff --git a/tests/terst_openmcmaterial.py b/tests/test_openmcmaterial.py similarity index 100% rename from tests/terst_openmcmaterial.py rename to tests/test_openmcmaterial.py