diff --git a/examples/sample_blanket.json b/examples/sample_blanket.json index 10e9233..618e200 100644 --- a/examples/sample_blanket.json +++ b/examples/sample_blanket.json @@ -1,5 +1,5 @@ { - "class": "HCPB_blanket", + "class": "HCPBBlanket", "geometry": { "pin spacing": 135, "pin vertical offset": 0, @@ -23,7 +23,7 @@ }, "components": { "pin": { - "class": "pin", + "class": "PinAssembly", "material": { "cladding": "EUROFER", "pressure tube": "EUROFER", @@ -57,7 +57,7 @@ } }, "first_wall": { - "class": "first_wall", + "class": "FirstWallComponent", "material": "Tungsten", "geometry": { "inner width": 1480, @@ -78,7 +78,7 @@ } }, "front_rib": { - "class": "front_rib", + "class": "FrontRib", "geometry": { "thickness": 30, "side channel width": 10, @@ -87,7 +87,7 @@ } }, "back_rib": { - "class": "back_rib", + "class": "BackRib", "geometry": { "thickness": 60, "side channel width": 10, @@ -96,7 +96,7 @@ } }, "coolant_outlet_plenum": { - "class": "coolant_outlet_plenum", + "class": "CoolantOutletPlenum", "geometry": { "length": 120, "width": 1000, diff --git a/examples/sample_blanket_ring.json b/examples/sample_blanket_ring.json index 2c3c6cf..d6f61bc 100644 --- a/examples/sample_blanket_ring.json +++ b/examples/sample_blanket_ring.json @@ -1,5 +1,5 @@ { - "class": "blanket_ring", + "class": "BlanketRingAssembly", "geometry": { "minimum radius": 580 }, diff --git a/examples/sample_blanket_shell.json b/examples/sample_blanket_shell.json index 4d64ab7..f5ef6d5 100644 --- a/examples/sample_blanket_shell.json +++ b/examples/sample_blanket_shell.json @@ -1,5 +1,5 @@ { - "class": "blanket_shell", + "class": "BlanketShellAssembly", "geometry": { "pin spacing": 135, "vertical offset": 0, diff --git a/examples/sample_first_wall.json b/examples/sample_first_wall.json index e6fe009..b9936cc 100644 --- a/examples/sample_first_wall.json +++ b/examples/sample_first_wall.json @@ -1,5 +1,5 @@ { - "class": "first_wall", + "class": "FirstWallComponent", "material": "Tungsten", "geometry": { "inner width": 1480, diff --git a/examples/sample_mini_blanket.json b/examples/sample_mini_blanket.json index 2982fc2..0070ce1 100644 --- a/examples/sample_mini_blanket.json +++ b/examples/sample_mini_blanket.json @@ -1,5 +1,5 @@ { - "class": "blanket_shell", + "class": "BlanketShellAssembly", "geometry": { "pin spacing": 135, "vertical offset": 0, @@ -7,7 +7,7 @@ }, "components": { "first_wall": { - "class": "first_wall", + "class": "FirstWallComponent", "material": "Tungsten", "geometry": { "inner width": 480, @@ -19,7 +19,7 @@ } }, "pin": { - "class": "pin", + "class": "PinAssembly", "material": { "cladding": "Steel", "pressure tube": "Steel", diff --git a/examples/sample_morphology.json b/examples/sample_morphology.json index 325702a..8dda380 100644 --- a/examples/sample_morphology.json +++ b/examples/sample_morphology.json @@ -1,10 +1,10 @@ [ { - "class": "neutron_test_facility", + "class": "NeutronTestFacility", "morphology": "overlap", "components": [ { - "class" : "source", + "class" : "SourceAssembly", "filepath": "./dummy_source.stp", "group": "neutron_source", "manufacturer": "blobcorp", @@ -15,10 +15,10 @@ }, { - "class": "room", + "class": "RoomAssembly", "components": [ { - "class": "surrounding_walls", + "class": "SurroundingWallsComponent", "material": "SS", "air": "some_gas", "geometry": { @@ -28,7 +28,7 @@ }, { - "class": "wall", + "class": "WallComponent", "material": "SS", "geometry": { "thickness": 5, diff --git a/examples/sample_pin.json b/examples/sample_pin.json index 3dc9f78..8ec4a84 100644 --- a/examples/sample_pin.json +++ b/examples/sample_pin.json @@ -1,5 +1,5 @@ { - "class": "pin", + "class": "PinAssembly", "material": { "cladding": "EUROFER", "pressure tube": "EUROFER", diff --git a/src/hypnos/assemblies.py b/src/hypnos/assemblies.py index 3dd7aab..ef3f5c5 100644 --- a/src/hypnos/assemblies.py +++ b/src/hypnos/assemblies.py @@ -40,7 +40,6 @@ from hypnos.geometry import Vertex, arctan from hypnos.cubit_functions import to_bodies from hypnos.constants import ( - CLASS_MAPPING, NEUTRON_TEST_FACILITY_REQUIREMENTS, ROOM_REQUIREMENTS, BLANKET_REQUIREMENTS, @@ -177,7 +176,7 @@ def get_components_of_class(self, classes: list) -> list: return component_list def set_mesh_size(self, component_classes: list, size: int): - component_classes = [globals()[CLASS_MAPPING[classname]] for classname in component_classes] + component_classes = [classdict()[classname] for classname in component_classes] components = self.get_components_of_class(component_classes) for component in components: if isinstance(component, SimpleComponent): @@ -412,7 +411,7 @@ def __init__(self, json_object): # Take out any walls from component list json_walls = [] for json_component in component_list: - if json_component["class"] == "wall": + if json_component["class"] == "WallComponent": json_walls.append(json_component) component_list.remove(json_component) json_object["components"] = component_list @@ -869,17 +868,17 @@ def setup_assembly(self): def __add_component_attributes(self): for component in self.component_list: - if component["class"] == "first_wall": + if component["class"] == "FirstWallComponent": self.first_wall_geometry = component["geometry"] self.first_wall_material = component["material"] - elif component["class"] == "pin": + elif component["class"] == "PinAssembly": self.breeder_materials = component["material"] self.breeder_geometry = component["geometry"] - elif component["class"] == "front_rib": + elif component["class"] == "FrontRib": self.front_ribs_geometry = component["geometry"] - elif component["class"] == "back_rib": + elif component["class"] == "BackRib": self.back_ribs_geometry = component["geometry"] - elif component["class"] == "coolant_outlet_plenum": + elif component["class"] == "CoolantOutletPlenum": self.cop_geometry = component["geometry"] def __dict_with_height(self): @@ -1129,10 +1128,8 @@ def get_all_geometries_from_components(component_list) -> list[CubitInstance]: for component in component_list: if isinstance(component, CubitInstance): instances.append(component) - elif isinstance(component, SimpleComponent): - instances += component.subcomponents - elif isinstance(component, GenericComponentAssembly): - instances += component.get_all_geometries() + elif isinstance(component, ComponentBase): + instances += component.get_geometries() return instances @@ -1187,8 +1184,24 @@ def construct(json_object: dict, *args): Returns ------- - SimpleComponent | GenericComponentAssembly + ComponentBase Instantiated python class ''' - constructor = globals()[CLASS_MAPPING[json_object["class"]]] + constructor = classdict(ComponentBase)[json_object["class"]] return constructor(json_object, *args) + + +# it take so long to run :( +def classdict(cls): + '''Find all subclasses recursively. + + Returns + ------- + dict + {"Class": Class} + ''' + return_dict = {} + for subcls in cls.__subclasses__(): + return_dict[subcls.__name__] = subcls + return_dict.update(classdict(subcls)) + return return_dict diff --git a/src/hypnos/components.py b/src/hypnos/components.py index 2b04a5b..5ba5208 100644 --- a/src/hypnos/components.py +++ b/src/hypnos/components.py @@ -68,13 +68,6 @@ def classname(self, new_classname): def classname(self): del self._classname - @classmethod - def from_classname(cls, classname, params): - for toplvl in cls.__subclasses__(): - for construct_lvl in toplvl.__subclasses__(): - if construct_lvl.classname == classname: - return construct_lvl(params) - def check_sanity(self): '''Check whether the parameters supplied to this instance are physical ''' diff --git a/src/hypnos/constants.py b/src/hypnos/constants.py index 8ef78c6..760a84a 100644 --- a/src/hypnos/constants.py +++ b/src/hypnos/constants.py @@ -8,43 +8,17 @@ ''' # required components for assemblies to be generated -NEUTRON_TEST_FACILITY_REQUIREMENTS = ["room", "source"] -BLANKET_REQUIREMENTS = ["breeder", "structure"] -ROOM_REQUIREMENTS = ["blanket", "surrounding_walls"] -BLANKET_SHELL_REQUIREMENTS = ["first_wall", "pin"] +NEUTRON_TEST_FACILITY_REQUIREMENTS = ["RoomAssembly", "SourceAssembly"] +BLANKET_REQUIREMENTS = ["BreederComponent", "StructureComponent"] +ROOM_REQUIREMENTS = ["BlanketComponent", "SurroundingWallsComponent"] +BLANKET_SHELL_REQUIREMENTS = ["FirstWallComponent", "PinAssembly"] HCPB_BLANKET_REQUIREMENTS = [ - "first_wall", - "pin", - "front_rib", - "back_rib", - "coolant_outlet_plenum" + "FirstWallComponent", + "PinAssembly", + "FrontRib", + "BackRib", + "CoolantOutletPlenum" ] -# LEGACY - classes according to what make_geometry subfunction(?) needs to be called -BLOB_CLASSES = ["complex", "breeder", "structure", "air"] -ROOM_CLASSES = ["surrounding_walls"] -WALL_CLASSES = ["wall"] - # LEGACY - currently only supports exclusive, inclusive, and overlap FACILITY_MORPHOLOGIES = ["exclusive", "inclusive", "overlap", "wall"] - -# mapping from json class names to python class names -CLASS_MAPPING = { - "complex": "ComplexComponent", - "external": "ExternalComponentAssembly", - "source": "SourceAssembly", - "neutron_test_facility": "NeutronTestFacility", - "blanket": "BlanketAssembly", - "room": "RoomAssembly", - "surrounding_walls": "SurroundingWallsComponent", - "breeder": "BreederComponent", - "structure": "StructureComponent", - "pin": "PinAssembly", - "cladding": "CladdingComponent", - "pressure_tube": "PressureTubeComponent", - "multiplier": "MultiplierComponent", - "first_wall": "FirstWallComponent", - "blanket_shell": "BlanketShellAssembly", - "blanket_ring": "BlanketRingAssembly", - "HCPB_blanket": "HCPBBlanket" -} diff --git a/src/hypnos/default_params.py b/src/hypnos/default_params.py index 27090ee..6b235f1 100644 --- a/src/hypnos/default_params.py +++ b/src/hypnos/default_params.py @@ -8,7 +8,7 @@ ''' PIN = { - "class": "pin", + "class": "PinAssembly", "material": { "cladding": "EUROFER", "pressure tube": "EUROFER", @@ -43,7 +43,7 @@ } FIRST_WALL = { - "class": "first_wall", + "class": "FirstWallComponent", "material": "Tungsten", "geometry": { "inner width": 1480, @@ -65,34 +65,34 @@ } BLANKET_SHELL = { - "class": "blanket_shell", + "class": "BlanketShellAssembly", "geometry": { "pin spacing": 135, "vertical offset": 0, "horizontal offset": 0 }, "components": { - "pin": PIN, - "first_wall": FIRST_WALL + "PinAssembly": PIN, + "FirstWallComponent": FIRST_WALL } } BLANKET_RING = { - "class": "blanket_ring", + "class": "BlanketRingAssembly", "geometry": { "minimum radius": 580 }, "components": { - "blanket_shell": { - "class": "blanket_shell", + "BlanketShellAssembly": { + "class": "BlanketShellAssembly", "geometry": { "pin spacing": 135, "vertical offset": 0, "horizontal offset": 0 }, "components": { - "first_wall": { - "class": "first_wall", + "FirstWallComponent": { + "class": "FirstWallComponent", "material": "Tungsten", "geometry": { "inner width": 480, @@ -103,8 +103,8 @@ "height": 580 } }, - "pin": { - "class": "pin", + "PinAssembly": { + "class": "PinAssembly", "material": { "cladding": "EUROFER", "pressure tube": "EUROFER", @@ -137,7 +137,7 @@ } HCPB_BLANKET = { - "class": "HCPB_blanket", + "class": "HCPBBlanket", "geometry": { "pin spacing": 135, "pin vertical offset": 0, @@ -160,8 +160,8 @@ "FW backplate thickness": 100 }, "components": { - "pin": { - "class": "pin", + "PinAssembly": { + "class": "PinAssembly", "material": { "cladding": "EUROFER", "pressure tube": "EUROFER", @@ -194,8 +194,8 @@ "filter lid length": 300 } }, - "first_wall": { - "class": "first_wall", + "FirstWallComponent": { + "class": "FirstWallComponent", "material": "Tungsten", "geometry": { "inner width": 1480, @@ -215,8 +215,8 @@ "channel spacing": 10 } }, - "front_rib": { - "class": "front_rib", + "FrontRib": { + "class": "FrontRib", "geometry": { "thickness": 30, "side channel width": 10, @@ -224,8 +224,8 @@ "side channel horizontal offset": 0 } }, - "back_rib": { - "class": "back_rib", + "BackRib": { + "class": "BackRib", "geometry": { "thickness": 60, "side channel width": 10, @@ -233,8 +233,8 @@ "side channel horizontal offset": 70 } }, - "coolant_outlet_plenum": { - "class": "coolant_outlet_plenum", + "CoolantOutletPlenum": { + "class": "CoolantOutletPlenum", "geometry": { "length": 120, "width": 1000, diff --git a/src/hypnos/geometry_maker.py b/src/hypnos/geometry_maker.py index e04b402..5845c4b 100644 --- a/src/hypnos/geometry_maker.py +++ b/src/hypnos/geometry_maker.py @@ -8,32 +8,14 @@ ''' from hypnos.tracking import Tracker -from hypnos.assemblies import construct +from hypnos.components import ComponentBase +from hypnos.assemblies import classdict from hypnos.generic_classes import CubismError, cmd from hypnos.cubit_functions import initialise_cubit, reset_cubit from hypnos.parsing import extract_data, ParameterFiller, get_format_extension import functools -def make_everything(json_object): - '''Construct all specified components - - Parameters - ---------- - json_object : dict or list - Description of geometry(ies) to construct in cubit - - Returns - ------- - Class corresponding to constructed geometry - ''' - if type(json_object) is list: - return [construct(json_component) for json_component in json_object] - elif type(json_object) is dict: - return [construct(json_object)] - raise CubismError("json object not recognised") - - def log_method(method_name: str): '''Decorator to print logs for class methods @@ -72,6 +54,7 @@ def __init__(self) -> None: self.print_parameter_logs = False self.track_components = False self.key_route_delimiter = '/' + self.class_dict = classdict(ComponentBase) def fill_design_tree(self): '''Process design_tree manually @@ -188,7 +171,7 @@ def __build_param_dict(self, key_route: list, param_dict: dict, updated_value): raise CubismError("Path given does not correspond to existing parameters") param_dict[key_route[0]] = self.__build_param_dict(key_route[1:], param_dict[key_route[0]], updated_value) return param_dict - + @log_method("Making geometry") def make_geometry(self): '''Build geometry corresponding to design tree in cubit @@ -197,7 +180,15 @@ def make_geometry(self): ------- Class corresponding to the constructed cubit geometry ''' - self.constructed_geometry = make_everything(self.design_tree) + params = self.design_tree + classname = params["class"] + + if type(self.design_tree) is list: + self.constructed_geometry = [self.class_dict[classname](param) for param in params] + elif type(self.design_tree) is dict: + self.constructed_geometry = [self.class_dict[classname](params)] + else: + raise CubismError("json object not recognised") return self.constructed_geometry @log_method("Imprint and merge") diff --git a/tests/geometry_maker_testing/parse_this.json b/tests/geometry_maker_testing/parse_this.json index e2be44d..cb79917 100644 --- a/tests/geometry_maker_testing/parse_this.json +++ b/tests/geometry_maker_testing/parse_this.json @@ -1 +1 @@ -{"class": "pin"} \ No newline at end of file +{"class": "PinAssembly"} \ No newline at end of file diff --git a/tests/sample_test.json b/tests/sample_test.json index 04a1682..769359b 100644 --- a/tests/sample_test.json +++ b/tests/sample_test.json @@ -1,5 +1,5 @@ { - "class": "HCPB_blanket", + "class": "HCPBBlanket", "geometry": { "pin spacing": 135, "pin vertical offset": 0, @@ -22,9 +22,9 @@ "FW backplate thickness": 100 }, "components": { - "pin": {"class": "pin"}, - "first_wall": { - "class": "first_wall", + "PinAssembly": {"class": "PinAssembly"}, + "FirstWallComponent": { + "class": "FirstWallComponent", "material": "Tungsten", "geometry": { "inner width": 1480, @@ -44,8 +44,8 @@ "channel spacing": 10 } }, - "front_rib": { - "class": "front_rib", + "FrontRib": { + "class": "FrontRib", "geometry": { "thickness": 30, "side channel width": 10, @@ -53,8 +53,8 @@ "side channel horizontal offset": 0 } }, - "back_rib": { - "class": "back_rib", + "BackRib": { + "class": "BackRib", "geometry": { "thickness": 60, "side channel width": 10, @@ -62,8 +62,8 @@ "side channel horizontal offset": 70 } }, - "coolant_outlet_plenum": { - "class": "coolant_outlet_plenum", + "CoolantOutletPlenum": { + "class": "CoolantOutletPlenum", "geometry": { "length": 120, "width": 1000, diff --git a/tests/test_geometry_maker.py b/tests/test_geometry_maker.py index 3d41b16..643462b 100644 --- a/tests/test_geometry_maker.py +++ b/tests/test_geometry_maker.py @@ -1,4 +1,4 @@ -from hypnos.geometry_maker import GeometryMaker, make_everything +from hypnos.geometry_maker import GeometryMaker from hypnos.default_params import PIN from hypnos.generic_classes import CubismError from hypnos.assemblies import PinAssembly @@ -104,27 +104,6 @@ def goldpath(pytestconfig): return pytestconfig.rootpath / "tests" / "gold" -def test_make_everything(): - # this should make a pin assembly - geom_list = make_everything(PIN) - geom = geom_list[0] - assert len(geom_list) == 1 - assert isinstance(geom, PinAssembly) - - # make sure it contains all the components we want - comp_classes = [type(comp) for comp in geom.components] - for pin_comp in PIN_COMPS: - assert pin_comp in comp_classes - - fake_json_obj = [PIN] - json_list = make_everything(fake_json_obj) - assert len(json_list) == 1 - assert isinstance(json_list[0], PinAssembly) - - with pytest.raises(CubismError): - make_everything(1) - - def test_parse_json(parsed): assert parsed.design_tree == PIN