Пример #1
0
class ExportSimulationThread(QThread):
    """Class for exporting Standard Interface Template."""
    processing_finished = Signal()

    def __init__(self, out_dir):
        """
        Constructor.

        Args:
            out_dir (str): output directory
        """
        super().__init__()
        self.out_dir = out_dir
        self.query = None
        self.sim_query_helper = None
        self.coverage_mapper = None
        self._exporter = None
        self.simulation_name = None
        self.sim_component = None
        self._logger = logging.getLogger('standard_interface_template')
        self.files_exported = []

    def run(self):
        """
        Exports the coverages and the mesh.

        Raises:
            (Exception): There was a problem writing the simulation file.
        """
        try:
            self._setup_query()
            self.coverage_mapper.do_map()
            self._do_export()
        except Exception:
            self._logger.exception('Error exporting simulation:')
        finally:
            self.processing_finished.emit()

    def _setup_query(self):
        """Queries from XMS to grab the simulation."""
        self._logger.info('Establishing communication with SMS.')
        self.query = Query()
        self.query.get_xms_agent().set_retries(1)
        r = self.query.get('simulation_name')
        self.simulation_name = r['simulation_name'][0].get_as_string()
        r = self.query.get()['none']
        self._simulation_name = r[0].get_simulation_name()
        self.query.select('StandardInterfaceTemplate#Sim_Manager')
        self.sim_query_helper = SimQueryHelper(self.query)
        self.sim_query_helper.get_simulation_data(True)
        self.sim_component = self.sim_query_helper.sim_component
        self.coverage_mapper = CoverageMapper(self.sim_query_helper, generate_snap=False)

    def _do_export(self):
        """Export the simulation."""
        self.export_geometry()
        self.export_materials()
        self.export_boundary_conditions()
        self.export_simulation()

    def export_geometry(self):
        """
        Exports the Standard Template Interface geometry file.

        Raises:
            (Exception): There was no geometry to write to the geometry file.
        """
        self._logger.info('Writing Standard Interface Template geometry file.')
        co_grid = self.coverage_mapper.co_grid
        if not co_grid:
            err_str = 'No mesh found aborting model export'
            self._logger.error(err_str)
            raise RuntimeError(err_str)
        base_name = f'{self.simulation_name}.example_geometry'
        self.files_exported.append(f'Grid "{base_name}"')
        file_name = os.path.join(self.out_dir, base_name)
        ugrid = co_grid.ugrid
        writer = GeometryWriter(file_name=file_name, grid=ugrid)
        writer.write()
        self._logger.info('Success writing Standard Interface Template geometry file.')

    def export_materials(self):
        """Exports the Standard Template Interface material file."""
        self._logger.info('Writing Standard Interface Template material file.')
        base_name = f'{self.simulation_name}.example_materials'
        file_name = os.path.join(self.out_dir, base_name)
        self.files_exported.append(f'Materials "{base_name}"')
        writer = MaterialsWriter(file_name=file_name,
                                 mat_grid_cells=self.coverage_mapper.material_comp_id_to_grid_cell_ids,
                                 mat_component=self.sim_query_helper.material_component)
        writer.write()
        self._logger.info('Success writing Standard Interface Template material file.')

    def export_boundary_conditions(self):
        """Exports the Standard Interface Template boundary conditions file."""
        arc_to_grid = self.coverage_mapper.bc_arc_id_to_grid_ids
        arc_to_comp_id = self.coverage_mapper.bc_arc_id_to_comp_id
        self._logger.info('Writing Standard Interface Template boundary conditions file.')
        base_name = f'{self.simulation_name}.example_boundary'
        file_name = os.path.join(self.out_dir, base_name)
        self.files_exported.append(f'Boundary_Conditions "{base_name}"')
        writer = BoundaryConditionsWriter(file_name=file_name, arc_to_ids=arc_to_comp_id, arc_points=arc_to_grid,
                                          bc_component=self.coverage_mapper.bc_component)
        writer.write()
        self._logger.info('Success writing Standard Interface Template boundary conditions file.')

    def export_simulation(self):
        """Exports the Standard Interface Template simulation file."""
        self._logger.info('Writing Standard Interface Template simulation file.')
        base_name = f'{self.simulation_name}.example_simulation'
        file_name = os.path.join(self.out_dir, base_name)
        writer = SimulationWriter(file_name=file_name, simulation_data=self.sim_query_helper.sim_component,
                                  other_files=self.files_exported)
        writer.write()
        self._logger.info('Success writing Standard Interface Template simulation file.')
Пример #2
0
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()
Пример #3
0
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
Пример #4
0
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()