Esempio n. 1
0
    def on_execute_gencase(self):
        """ Saves data into disk and uses GenCase to generate the case files."""
        self.on_save_case()
        if not Case.the().executable_paths.gencase:
            warning_dialog(__("GenCase executable is not set."))
            return

        gencase_full_path = path.abspath(Case.the().executable_paths.gencase)
        arguments = [
            "{path}/{name}_Def".format(path=Case.the().path,
                                       name=Case.the().name),
            "{path}/{name}_out/{name}".format(path=Case.the().path,
                                              name=Case.the().name),
            "-save:+all"
        ]
        cmd_string = "{} {}".format(gencase_full_path, " ".join(arguments))

        refocus_cwd()
        process = QtCore.QProcess(get_fc_main_window())
        process.setWorkingDirectory(Case.the().path)
        ensure_process_is_executable_or_fail(gencase_full_path)
        process.start(gencase_full_path, arguments)
        debug("Executing -> {}".format(cmd_string))
        process.waitForFinished()

        try:
            output = str(process.readAllStandardOutput().data(),
                         encoding='utf-8')
        except UnicodeDecodeError:
            output = str(process.readAllStandardOutput().data(),
                         encoding='latin1')

        if process.exitCode():
            Case.the().info.is_gencase_done = False
            error_dialog(
                __("Error executing GenCase. Did you add objects to the case?. Another reason could be memory issues. View details for more info."
                   ), output)
        else:
            try:
                total_particles_text = output[
                    output.index("Total particles: "):output.index(" (bound=")]
                total_particles = int(
                    total_particles_text[total_particles_text.index(": ") +
                                         2:])
                Case.the().info.particle_number = total_particles
                GencaseCompletedDialog(particle_count=total_particles,
                                       detail_text=output,
                                       cmd_string=cmd_string,
                                       parent=get_fc_main_window()).show()
                Case.the().info.is_gencase_done = True
                self.on_save_case()
                Case.the().info.needs_to_run_gencase = False
            except ValueError:
                print_exc()
                Case.the().info.is_gencase_done = False
                Case.the().info.needs_to_run_gencase = True

        # Refresh widget enable/disable status as GenCase finishes
        self.gencase_completed.emit(Case.the().info.is_gencase_done)
Esempio n. 2
0
    def on_ex_simulate(self):
        """ Defines what happens on simulation button press.
            It shows the run window and starts a background process with dualsphysics running. Updates the window with useful info."""

        refocus_cwd()

        if Case.the().info.needs_to_run_gencase:
            # Warning window about save_case
            warning_dialog(
                "You should run GenCase again. Otherwise, the obtained results may not be as expected"
            )

        static_params_exe = [
            Case.the().get_out_xml_file_path(),
            Case.the().get_out_folder_path(), "-{device}".format(
                device=self.device_selector.currentText().lower()), "-svres"
        ]

        additional_parameters = list()
        if Case.the().info.run_additional_parameters:
            additional_parameters = Case.the(
            ).info.run_additional_parameters.split(" ")

        final_params_ex = static_params_exe + additional_parameters
        cmd_string = "{} {}".format(Case.the().executable_paths.dsphysics,
                                    " ".join(final_params_ex))

        run_dialog = RunDialog(
            case_name=Case.the().name,
            processor=self.device_selector.currentText(),
            number_of_particles=Case.the().info.particle_number,
            cmd_string=cmd_string,
            parent=get_fc_main_window())
        run_dialog.set_value(0)
        run_dialog.run_update(0, 0, None)
        Case.the().info.is_simulation_done = False

        run_fs_watcher = QtCore.QFileSystemWatcher()

        self.simulation_started.emit()

        # Cancel button handler
        def on_cancel():
            log(__("Stopping simulation"))
            if process:
                process.kill()
            run_dialog.hide_all()
            Case.the().info.is_simulation_done = True
            self.simulation_cancelled.emit()

        run_dialog.cancelled.connect(on_cancel)

        # Launch simulation and watch filesystem to monitor simulation
        filelist = [
            f for f in os.listdir(Case.the().path + "/" + Case.the().name +
                                  "_out/") if f.startswith("Part")
        ]
        for f in filelist:
            os.remove(Case.the().path + "/" + Case.the().name + "_out/" + f)

        def on_dsph_sim_finished(exit_code):
            """ Simulation finish handler. Defines what happens when the process finishes."""

            # Reads output and completes the progress bar
            try:
                output = str(process.readAllStandardOutput().data(),
                             encoding='utf-8')
            except UnicodeDecodeError:
                output = str(process.readAllStandardOutput().data(),
                             encoding='latin1')

            run_dialog.set_detail_text(str(output))
            run_dialog.run_complete()

            run_fs_watcher.removePath(Case.the().path + "/" + Case.the().name +
                                      "_out/")

            if exit_code == 0:
                # Simulation went correctly
                Case.the().info.is_simulation_done = True
                Case.the().info.needs_to_run_gencase = False
                self.simulation_complete.emit(True)
            else:
                # In case of an error
                Case.the().info.needs_to_run_gencase = True
                if "exception" in str(output).lower():
                    log("There was an error on the execution. Opening an error dialog for that."
                        )
                    run_dialog.hide()
                    self.simulation_complete.emit(False)
                    error_dialog(
                        __("An error occurred during execution. Make sure that parameters exist and are properly defined. "
                           "You can also check your execution device (update the driver of your GPU). Read the details for more information."
                           ), str(output))
            save_case(Case.the().path, Case.the())

        # Launches a QProcess in background
        process = QtCore.QProcess(get_fc_main_window())
        process.finished.connect(on_dsph_sim_finished)

        ensure_process_is_executable_or_fail(
            Case.the().executable_paths.dsphysics)
        if platform in ("linux", "linux2"):
            os.environ["LD_LIBRARY_PATH"] = os.path.dirname(
                Case.the().executable_paths.dsphysics)
        process.start(Case.the().executable_paths.dsphysics, final_params_ex)

        def on_fs_change():
            """ Executed each time the filesystem changes. This updates the percentage of the simulation and its details."""
            run_file_data = ""
            with open(Case.the().path + "/" + Case.the().name + "_out/Run.out",
                      "r",
                      encoding="utf-8") as run_file:
                run_file_data = run_file.readlines()

            # Fill details window
            run_dialog.set_detail_text("".join(run_file_data))

            # Set percentage scale based on timemax
            for l in run_file_data:
                if Case.the().execution_parameters.timemax == -1:
                    if "TimeMax=" in l:
                        Case.the().execution_parameters.timemax = float(
                            l.split("=")[1])

            current_value: float = 0.0
            totalpartsout: int = 0
            last_estimated_time = None

            # Update execution metrics
            last_part_lines = list(
                filter(
                    lambda x: "Part_" in x and "stored" not in x and "      "
                    in x, run_file_data))
            if last_part_lines:
                current_value = (float(last_part_lines[-1].split(None)[1]) *
                                 float(100)) / float(
                                     Case.the().execution_parameters.timemax)
            else:
                current_value = None

            # Update particles out
            last_particles_out_lines = list(
                filter(lambda x: "(total: " in x and "Particles out:" in x,
                       run_file_data))
            if last_particles_out_lines:
                totalpartsout = int(last_particles_out_lines[-1].split(
                    "(total: ")[1].split(")")[0])

            try:
                last_estimated_time = str(" ".join(
                    last_part_lines[-1].split(None)[-2:]))
            except IndexError:
                last_estimated_time = None

            # Update run dialog
            run_dialog.run_update(current_value, totalpartsout,
                                  last_estimated_time)

        # Set filesystem watcher to the out directory.
        run_fs_watcher.addPath(Case.the().path + "/" + Case.the().name +
                               "_out/")
        run_fs_watcher.directoryChanged.connect(on_fs_change)

        # Handle error on simulation start
        if process.state() == QtCore.QProcess.NotRunning:
            # Probably error happened.
            run_fs_watcher.removePath(Case.the().path + "/" + Case.the().name +
                                      "_out/")
            process = None
            error_dialog(
                "Error on simulation start. Check that the DualSPHysics executable is correctly set."
            )
        else:
            run_dialog.show()
    def execute_bathymetry_tool(self):
        """ Executes bathymetry tool and returns the output path of the generated file. """

        export_process = QtCore.QProcess(get_fc_main_window())
        temp_dir = gettempdir()
        working_dialog = WorkingDialog(self)

        def on_export_finished():
            temp_bathymetry_file_path = "{}/output.stl".format(temp_dir)
            import_geo(filename=str(temp_bathymetry_file_path),
                       scale_x=1.0,
                       scale_y=1.0,
                       scale_z=1.0,
                       name=str(self.geo_objname_text.text()),
                       autofill=self.geo_autofill_chck.isChecked(),
                       case=Case.the())
            working_dialog.accept()

        executable_parameters = [
            "-loadpos",
            str(self.geo_file_path.text()),
            "-move:{}:{}:{}".format(self.bath_move_x_e.text(),
                                    self.bath_move_y_e.text(),
                                    self.bath_move_z_e.text()),
            "-rotate:{}:{}:{}".format(self.bath_rotate_x_e.text(),
                                      self.bath_rotate_y_e.text(),
                                      self.bath_rotate_z_e.text()),
            "-scale:{}:{}:{}".format(self.bath_scale_x_e.text(),
                                     self.bath_scale_y_e.text(),
                                     self.bath_scale_z_e.text())
        ]

        if self.bath_selection_enabled_chk.isChecked():
            executable_parameters.append("-selposmin:{}:{}".format(
                self.bath_selection_point_x_e.text(),
                self.bath_selection_point_y_e.text()))
            executable_parameters.append("-selsize:{}:{}".format(
                self.bath_selection_size_x_e.text(),
                self.bath_selection_size_y_e.text()))

        executable_parameters.append("-gdp:{}".format(
            self.bath_grid_dp_x_e.text()))

        if self.bath_initdomain_enabled_chk.isChecked():
            executable_parameters.append("-gposmin:{}:{}".format(
                self.bath_initdomain_point_x_e.text(),
                self.bath_initdomain_point_y_e.text()))
            executable_parameters.append("-gsize:{}:{}".format(
                self.bath_initdomain_size_x_e.text(),
                self.bath_initdomain_size_y_e.text()))

        if self.bath_xmin_check.isChecked():
            executable_parameters.append("-gexpandxmin:{}:{}:{}:{}".format(
                self.bath_xmin_size_e.text(), self.bath_xmin_z_e.text(),
                self.bath_xmin_size2_e.text(), self.bath_xmin_z2_e.text()))

        if self.bath_xmax_check.isChecked():
            executable_parameters.append("-gexpandxmax:{}:{}:{}:{}".format(
                self.bath_xmax_size_e.text(), self.bath_xmax_z_e.text(),
                self.bath_xmax_size2_e.text(), self.bath_xmax_z2_e.text()))

        if self.bath_ymin_check.isChecked():
            executable_parameters.append("-gexpandymin:{}:{}:{}:{}".format(
                self.bath_ymin_size_e.text(), self.bath_ymin_z_e.text(),
                self.bath_ymin_size2_e.text(), self.bath_ymin_z2_e.text()))

        if self.bath_ymax_check.isChecked():
            executable_parameters.append("-gexpandymax:{}:{}:{}:{}".format(
                self.bath_ymax_size_e.text(), self.bath_ymax_z_e.text(),
                self.bath_ymax_size2_e.text(), self.bath_ymax_z2_e.text()))

        if self.bath_periodicx_enabled_chk.isChecked():
            executable_parameters.append("-gperix:{}:{}".format(
                self.bath_periodicx_rampwidth_x_e.text(),
                self.bath_periodicx_flatwidth_x_e.text()))

        if self.bath_periodicy_enabled_chk.isChecked():
            executable_parameters.append("-gperiy:{}:{}".format(
                self.bath_periodicy_rampwidth_x_e.text(),
                self.bath_periodicy_flatwidth_x_e.text()))

        if self.bath_finalmove_enabled_chk.isChecked():
            executable_parameters.append("-gmove:{}:{}:{}".format(
                self.bath_finalmove_x_e.text(), self.bath_finalmove_y_e.text(),
                self.bath_finalmove_z_e.text()))

        executable_parameters.append("-savegrid:stl:mm")
        executable_parameters.append("{}/output.stl".format(temp_dir))

        self.save_default_data()

        export_process.finished.connect(on_export_finished)
        ensure_process_is_executable_or_fail(
            Case.the().executable_paths.bathymetrytool)
        debug("Executing: {} {}".format(
            Case.the().executable_paths.bathymetrytool,
            " ".join(executable_parameters)))
        export_process.start(Case.the().executable_paths.bathymetrytool,
                             executable_parameters)
        working_dialog.exec()