class ImportSimulationThread(QThread): """Read an Standard Interface Template simulation when a *.example_simulation file is opened in XMS.""" processing_finished = Signal() def __init__(self, xms_data=None): """ Construct the Importer. Args: xms_data (:obj:`dict`): XMS data dictionary. Useful for testing because it will avoid any Query calls. { 'filename': '', # Path to the *.example_simulation file to read 'comp_dir': '', # Path to the XMS "Components" temp folder } """ super().__init__() self._logger = logging.getLogger('standard_interface_template') self._xms_data = xms_data self._query = None self._root_idx = -1 self._build_vertices = [] self._boundary_conditions_reader = None self._geometry_reader = None self._materials_reader = None self._simulation_reader = None # Stuff we will be sending back to XMS self._sim_comp = None self._mesh = None self._bc_cov = None self._bc_do_comp = None # data_object for BC coverage component self._mat_cov = None self._mat_do_comp = None # data_object for Material coverage component if not self._xms_data: self._get_xms_data() def _get_xms_data(self): """Get all data from XMS needed to import the Standard Interface Template simulation.""" self._logger.info('Retrieving data from XMS...') self._xms_data = { 'filename': '', 'comp_dir': '', } try: self._query = Query() self._query.get_xms_agent().set_retries(1) self._xms_data['filename'] = self._query.get_read_file() # Add a new Standard Interface Template simulation sim = Simulation() sim.set_model_name("StandardInterfaceTemplate") sim.set_simulation_name( os.path.splitext(os.path.basename( self._xms_data['filename']))[0]) arg_list = [{"none": sim, "#description": "Build"}] place_marks = self._query.add(arg_list) if place_marks: self._root_idx = place_marks[0] # Get the XMS temp directory start_ctxt = self._query.get_context() self._query.select('InstallResources') temp_dir = self._query.get( 'Temporary Directory')['Temporary Directory'] if not temp_dir or not temp_dir[0]: raise RuntimeError("Could not get XMS temporary directory.") delete_dir = temp_dir[0].get_as_string() self._xms_data['comp_dir'] = os.path.join( os.path.dirname(delete_dir), 'Components') shutil.rmtree(delete_dir, ignore_errors=True) self._query.set_context(start_ctxt) except Exception: self._logger.exception( 'Unable to retrieve data from SMS needed to import Standard Interface Template simulation' ) def _add_xms_data(self): """ Send imported data to XMS. Raises: (Exception): There was a problem sending the imported data to XMS. """ self._logger.info('Preparing to send imported data to SMS...') sim_comp_idx = None if self._sim_comp: # Add the hidden simulation component arg_list = [{ '#description': 'StandardInterfaceTemplate#Sim_Manager', '': self._sim_comp }] place_marks = self._query.add(arg_list, self._root_idx) if place_marks: sim_comp_idx = place_marks[0] self._build_vertices.append(sim_comp_idx) else: raise RuntimeError( "Could not create Standard Interface Template simulation.") if self._mesh: # add the mesh to the Query Context mesh_list = [{ '#description': 'BuildNoTake', 'Geometry': self._mesh }] self._query.add(mesh_list, self._root_idx) take_list = [{ '#description': 'AddTakeUuid', '': self._mesh.get_uuid() }] self._build_vertices.extend(self._query.add(take_list)) if self._bc_cov: # Add the Boundary Conditions coverage geometry and its hidden component. self._build_vertices.extend( self._query.add([{ '#description': 'BuildNoTake', 'Coverage': self._bc_cov, 'COVERAGE_TYPE': 'StandardInterfaceTemplate#Boundary Conditions Coverage' }], self._root_idx)) if self._bc_do_comp: # Add the Boundary Conditions coverage's hidden component self._build_vertices.extend( self._query.add([{ '#description': 'StandardInterfaceTemplate#Boundary_Coverage_Component', '': self._bc_do_comp }], self._build_vertices[-1])) arg_list = [{ "": self._bc_cov.get_uuid(), "#description": "AddTakeUuid" }] if sim_comp_idx is not None: self._build_vertices.extend( self._query.add(arg_list, sim_comp_idx)) if self._mat_cov: # Add the materials coverage geometry and its hidden component. if self._mat_cov: self._build_vertices.extend( self._query.add([{ '#description': 'BuildNoTake', 'Coverage': self._mat_cov, 'COVERAGE_TYPE': 'StandardInterfaceTemplate#Materials Coverage' }], self._root_idx)) if self._mat_do_comp: # Add the material coverage's hidden component. self._build_vertices.extend( self._query.add([{ '#description': 'StandardInterfaceTemplate#Materials_Coverage_Component', '': self._mat_do_comp }], self._build_vertices[-1])) # Link the materials coverage to the simulation arg_list = [{ "": self._mat_cov.get_uuid(), "#description": "AddTakeUuid" }] if sim_comp_idx is not None: self._build_vertices.extend( self._query.add(arg_list, sim_comp_idx)) self.send() def _read_boundary_conditions(self, filename): """ Read parameters from a *.example_boundary file. Args: filename (str): Filepath of the *.example_boundary file. """ self._boundary_conditions_reader = BoundaryConditionsReader() self._boundary_conditions_reader.read(filename) self._build_bc_coverage() comp_uuid = str(uuid.uuid4()) bc_comp_dir = os.path.join(self._xms_data['comp_dir'], comp_uuid) os.makedirs(bc_comp_dir, exist_ok=True) bc_main_file = os.path.join(bc_comp_dir, 'boundary_coverage_comp.nc') bc_component = BoundaryCoverageComponent(bc_main_file) bc_df = bc_component.data.coverage_data.to_dataframe() column_list = bc_df.columns.tolist() bc_df = bc_df.append( pandas.DataFrame.from_dict( self._boundary_conditions_reader.data))[column_list] bc_component.data.coverage_data = bc_df.to_xarray() bc_component.data.commit() # Write component id and BC arc att ids to a file so we can initialize them in get_initial_display_options ids = list(bc_component.data.coverage_data.comp_id.values) id_file = os.path.join(bc_comp_dir, BC_COVERAGE_INITIAL_ATT_ID_FILE) write_display_option_ids(id_file, ids) id_file = os.path.join(bc_comp_dir, BC_COVERAGE_INITIAL_COMP_ID_FILE) write_display_option_ids(id_file, ids) self._bc_do_comp = Component() self._bc_do_comp.set_uuid(comp_uuid) self._bc_do_comp.set_unique_name_and_model_name( 'Boundary_Coverage_Component', 'StandardInterfaceTemplate') self._bc_do_comp.set_main_file(bc_main_file) def _read_simulation(self): """Read parameters from a *.example_simulation file.""" self._simulation_reader = SimulationReader() self._simulation_reader.read(self._xms_data['filename']) comp_uuid = str(uuid.uuid4()) sim_comp_dir = os.path.join(self._xms_data['comp_dir'], comp_uuid) os.makedirs(sim_comp_dir, exist_ok=True) sim_main_file = os.path.join(sim_comp_dir, 'sim_comp.nc') sim_data = SimulationData(sim_main_file) sim_data.info.attrs['user_text'] = self._simulation_reader.user_text sim_data.info.attrs['user_option'] = self._simulation_reader.user_type sim_data.commit() self._sim_comp = Component() self._sim_comp.set_uuid(comp_uuid) self._sim_comp.set_unique_name_and_model_name( 'Sim_Manager', 'StandardInterfaceTemplate') self._sim_comp.set_main_file(sim_main_file) def _read_geometry(self, filename): """ Read mesh geometry from a *.example_geometry file. Args: filename (str): Filepath of the *.example_geometry file. """ self._geometry_reader = GeometryReader() self._geometry_reader.read(filename) self._mesh = UGrid(self._geometry_reader.temp_mesh_file) self._mesh.set_name('Mesh') self._mesh.set_uuid(str(uuid.uuid4())) def _read_materials(self, filename): """ Read material assignments from a *.example_materials file. Args: filename (str): Filepath of the *.example_materials file. """ self._materials_reader = MaterialsReader() self._materials_reader.read(filename) # Create a dataset of materials (size of cells) cell_materials = [ 0 for _ in range(self._geometry_reader.cogrid.ugrid.cell_count) ] for material, cells in self._materials_reader.material_cells.items(): for cell in cells: cell_materials[cell] = material cov_name = 'Materials' cov_builder = GridCellToPolygonCoverageBuilder( self._geometry_reader.cogrid, cell_materials, None, cov_name) new_cov_geom = cov_builder.create_polygons_and_build_coverage() self._mat_cov = new_cov_geom comp_uuid = str(uuid.uuid4()) mat_comp_dir = os.path.join(self._xms_data['comp_dir'], comp_uuid) os.makedirs(mat_comp_dir, exist_ok=True) mat_main_file = os.path.join(mat_comp_dir, 'materials_coverage_comp.nc') mat_component = MaterialsCoverageComponent(mat_main_file) mat_component.data.coverage_data = pandas.DataFrame.from_dict( self._materials_reader.data).to_xarray() mat_component.data.commit() # Write component id and polygon att ids to a file so we can initialize them in get_initial_display_options att_ids = [] comp_ids = [] for mat_id, poly_ids in cov_builder.dataset_polygon_ids.items(): if mat_id < 0: # pragma no cover continue # Don't need to write out unassigned polygons since it is the default category. non_default_poly_ids = [ poly_id for poly_id in poly_ids if poly_id > 0 ] att_ids.extend(non_default_poly_ids) comp_ids.extend([mat_id for _ in range(len(non_default_poly_ids))]) id_file = os.path.join(mat_comp_dir, MAT_COVERAGE_INITIAL_ATT_ID_FILE) write_display_option_ids(id_file, att_ids) id_file = os.path.join(mat_comp_dir, MAT_COVERAGE_INITIAL_COMP_ID_FILE) write_display_option_ids(id_file, comp_ids) self._mat_do_comp = Component() self._mat_do_comp.set_uuid(comp_uuid) self._mat_do_comp.set_unique_name_and_model_name( 'Materials_Coverage_Component', 'StandardInterfaceTemplate') self._mat_do_comp.set_main_file(mat_main_file) def _build_bc_coverage(self): """Create the data_objects Boundary Conditions Coverage from data imported from the *.example_boundary file.""" self._logger.info('Building Boundary Conditions coverage geometry...') self._bc_cov = Coverage() self._bc_cov.set_name('Boundary Conditions') self._bc_cov.set_uuid(str(uuid.uuid4())) arc_builder = CoverageArcBuilder( self._geometry_reader.cogrid.ugrid.locations) for nodestring in self._boundary_conditions_reader.arcs.values(): arc_builder.add_arc(nodestring[0], nodestring[-1], nodestring[1:-1]) self._bc_cov.set_arcs(arc_builder.arcs) self._bc_cov.complete() def read(self): """ Trigger the read of the Standard Interface Template simulation. Raises: (Exception): There was a problem reading the simulation file. """ try: self._logger.info('Reading the simulation.') self._read_simulation() read_directory = os.path.dirname(self._xms_data['filename']) self._read_geometry( os.path.join(read_directory, self._simulation_reader.grid_file)) self._read_boundary_conditions( os.path.join(read_directory, self._simulation_reader.boundary_file)) self._read_materials( os.path.join(read_directory, self._simulation_reader.materials_file)) if self._query: self._add_xms_data() except Exception: self._logger.exception('Error importing simulation:') finally: self.processing_finished.emit() def send(self): """Send imported data to XMS.""" if self._query: ctxt = self._query.get_context() for build_vertex in self._build_vertices: ctxt.set_place_mark(build_vertex) self._query.set_context(ctxt) self._query.send() def run(self): """ Creates coverages, a simulation, and a mesh for XMS. Raises: (Exception): There was a problem reading the simulation file. """ try: self.read() except Exception as error: self._logger.exception(f'Error importing simulation: {str(error)}') raise error finally: self.processing_finished.emit()
class CheckThread: """Writes Standard Interface Template input files.""" def __init__(self): """Constructor.""" super().__init__() self._query = None self._start_context = None self._simulation_name = None self._sim_query_helper = None self.sim_component = None self.ugrid = None self.grid_units = None self.bc_data = None self.bc_comp_ids_to_arc_ids = None self.mat_data = None def run(self): """ Creates the snap preview of coverages onto the mesh. Raises: (RuntimeError): Failed to check the simulation for errors. """ try: self._setup_query() self._get_data() checker = SimulationCheck(self) errors = checker.run_check() if errors: self._query.set_context(self._root_context) self._query.add(errors) self._query.send() except: # noqa raise RuntimeError('Error checking simulation.') def _setup_query(self): """Setup communication with XMS.""" self._query = Query() self._query.get_xms_agent().set_retries(1) self._root_context = self._query.get_context() r = self._query.get('simulation_name') self._simulation_name = r['simulation_name'][0].get_as_string() self._query.select('StandardInterfaceTemplate#Sim_Manager') self._sim_query_helper = SimQueryHelper(self._query) self._sim_query_helper.get_geometry(False) self._sim_query_helper.get_boundary_conditions_coverage() self._sim_query_helper.get_materials_coverage() def _get_data(self): """Set member variables from data in SimQueryHelper.""" self.sim_component = self._sim_query_helper.sim_component self.grid_units = self._sim_query_helper.grid_units if self._sim_query_helper.co_grid: self.ugrid = self._sim_query_helper.co_grid.ugrid bc = self._sim_query_helper.boundary_conditions_component if bc: self.bc_data = bc.data if bc.cov_uuid in bc.comp_to_xms: self.bc_comp_ids_to_arc_ids = bc.comp_to_xms[bc.cov_uuid] mat = self._sim_query_helper.material_component if mat: self.mat_data = mat.data
class ImportGeometryThread(ImportSimulationThread): """Read an Standard Interface Template simulation when a *.example_geometry file is opened in XMS.""" processing_finished = Signal() def __init__(self, xms_data=None): """ Construct the Importer. Args: xms_data (:obj:`dict`): XMS data dictionary. Useful for testing because it will avoid any Query calls. { 'filename': '', # Path to the *.example_simulation file to read 'comp_dir': '', # Path to the XMS "Components" temp folder } """ super().__init__(xms_data) def _get_xms_data(self): """Get all data from XMS needed to import the Standard Interface Template simulation.""" self._logger.info('Retrieving data from XMS...') self._xms_data = { 'filename': '', 'comp_dir': '', } try: self._query = Query() self._query.get_xms_agent().set_retries(1) self._xms_data['filename'] = self._query.get_read_file() # Get the XMS temp directory start_ctxt = self._query.get_context() self._query.select('InstallResources') temp_dir = self._query.get( 'Temporary Directory')['Temporary Directory'] if not temp_dir or not temp_dir[0]: raise RuntimeError("Could not get XMS temporary directory.") delete_dir = temp_dir[0].get_as_string() self._xms_data['comp_dir'] = os.path.join( os.path.dirname(delete_dir), 'Components') shutil.rmtree(delete_dir, ignore_errors=True) self._query.set_context(start_ctxt) except Exception: self._logger.exception( 'Unable to retrieve data from SMS needed to import Standard Interface Template simulation' ) def read(self): """ Trigger the read of the Standard Interface Template geometry. Raises: (Exception): There was a problem reading the geometry file. """ try: self._logger.info('Reading the geometry.') self._read_geometry(self._xms_data['filename']) if self._query: self._add_xms_data() except Exception: self._logger.exception('Error importing geometry:') finally: self.processing_finished.emit()