Exemple #1
0
    def get_deformation(self, settings):
        """ Either reads or queries for deformation matrix from settings dict"""
        if settings["initial_deformation"]["method"] == 'manual':
            deformation = np.array(
                settings["initial_deformation"]["deformation"])
        elif settings["initial_deformation"]["method"] == 'auto':
            configname = settings["initial_deformation"]["configname"]
            calctype = settings["initial_deformation"]["calctype"]
            sel_tmp = Selection(self.selection.proj, "EMPTY", "config", False)
            sel_tmp.data = pandas.DataFrame(
                {
                    "configname": configname,
                    "selected": 1
                }, index=range(1))
            try:
                os.mkdir(os.path.join(self.selection.proj.path, ".casm/tmp"))
            except:
                pass
            sel_config = sel_tmp.saveas(
                os.path.join(self.selection.proj.path, ".casm/tmp",
                             configname.replace('/', '.')), True)
            sel_config.query(["relaxation_strain(U,0:5,{})".format(calctype)])
            deformation = np.array([
                float(sel_config.data["relaxation_strain(U,{},{})".format(
                    i, calctype)].loc[0]) for i in range(6)
            ])
            if os.path.isfile(
                    os.path.join(self.selection.proj.path, ".casm/tmp",
                                 configname.replace('/', '.'))):
                os.remove(
                    os.path.join(self.selection.proj.path, ".casm/tmp",
                                 configname.replace('/', '.')))
        else:
            raise VaspWrapperError(
                "use manual or auto mode to set initial deformation. see casm format --vasp for settings"
            )

        if deformation.ndim == 1:
            deformation = np.array(
                [[deformation[0], deformation[5], deformation[4]],
                 [deformation[5], deformation[1], deformation[3]],
                 [deformation[4], deformation[3], deformation[2]]])
        return deformation
Exemple #2
0
 def _calc_submit_node_info(settings, config_data):
     """return nodes, ppn from settings of a configuration"""
     if settings["nodes"] != None and settings["ppn"] != None:
         return int(settings["nodes"]), int(settings["ppn"])
     elif settings["atom_per_proc"] != None and settings["ppn"] != None:
         pos = vasp.io.Poscar(os.path.join(config_data["calcdir"],
                                           "POSCAR"))
         num = len(pos.basis)
         nodes = int(
             math.ceil(
                 float(num) / float(settings["atom_per_proc"]) /
                 float(settings["ppn"])))
         return nodes, int(settings["ppn"])
     elif settings["nodes_per_image"] != None and settings["ppn"] != None:
         nodes = int(config_data["n_images"]) * \
             float(settings["nodes_per_image"])
         return nodes, int(settings["ppn"])
     else:
         raise VaspWrapperError(
             "Not enough information to determine nodes and ppn information"
         )
Exemple #3
0
    def __init__(self, selection, calctype=None, auto=True, sort=True):
        """set up attributes for the base class"""
        self.selection = selection
        self.calctype = calctype
        self.auto = auto
        self.sort = sort
        self.casm_directories = self.selection.proj.dir
        self.casm_settings = self.selection.proj.settings
        if self.casm_settings is None:
            raise VaspWrapperError(
                "Not in a CASM project. The file '.casm' directory was not found."
            )

        self.clex = self.casm_settings.default_clex
        if calctype:
            self.clex.calctype = calctype
        self.calc_subdir = ""
        # everything between $(calcdir)/run.*/ and OSZICAR and OUTCAR files
        self.results_subdir = ''
        self.calculator = None
        self.append_selection_data()
Exemple #4
0
    def __init__(self, configdir=None, auto=True, sort=True):
        """
        Construct a VASP relaxation job object.

        Arguments
        ----------

            configdir: str, optional, default=None
              Path to configuration directory. If None, uses the current working
              directory

            auto: boolean, optional, default=True,
              Use True to use the prisms_jobs module's JobDB to manage jobs

            sort: boolean, optional, default=True,
              Use True to sort atoms in POSCAR by type

        """
        print("Construct a casm.vaspwrapper.Relax instance:")

        if configdir is None:
            configdir = os.getcwd()
        print("  Input directory:", configdir)

        # get the configname from the configdir path
        _res = os.path.split(configdir)
        self.configname = os.path.split(_res[0])[1] + "/" + _res[1]
        print("  Configuration:", self.configname)

        print("  Reading CASM settings")
        self.casm_directories = DirectoryStructure(configdir)
        self.casm_settings = ProjectSettings(configdir)
        if self.casm_settings is None:
            raise VaspWrapperError(
                "Not in a CASM project. The file '.casm' directory was not found."
            )

        if os.path.abspath(configdir) != self.configdir:
            print("")
            print("input configdir:", configdir)
            print("determined configname:", self.configname)
            print("expected configdir given configname:", self.configdir)
            raise VaspWrapperError("Mismatch between configname and configdir")

        # fixed to default_clex for now
        self.clex = self.casm_settings.default_clex

        # store path to .../config/calctype.name, and create if not existing
        self.calcdir = self.casm_directories.calctype_dir(
            self.configname, self.clex)
        try:
            os.mkdir(self.calcdir)
        except:
            pass
        print("  Calculations directory:", self.calcdir)

        # read the settings json file
        print("  Reading relax.json settings file")
        sys.stdout.flush()
        setfile = self.casm_directories.settings_path_crawl(
            "relax.json", self.configname, self.clex)

        if setfile is None:
            raise VaspWrapperError(
                "Could not find \"relax.json\" in an appropriate \"settings\" directory"
            )
            sys.stdout.flush()

        else:
            print("  Read settings from:", setfile)
        self.settings = read_settings(setfile)

        # set default settings if not present
        if not "ncore" in self.settings:
            self.settings["ncore"] = None
        if not "npar" in self.settings:
            self.settings["npar"] = None
        if not "kpar" in self.settings:
            self.settings["kpar"] = None
        if not "vasp_cmd" in self.settings:
            self.settings["vasp_cmd"] = None
        if not "ncpus" in self.settings:
            self.settings["ncpus"] = None
        if not "run_limit" in self.settings:
            self.settings["run_limit"] = None
        if not "prerun" in self.settings:
            self.settings["prerun"] = None
        if not "postrun" in self.settings:
            self.settings["postrun"] = None

        self.auto = auto
        self.sort = sort
        print("  DONE\n")
        sys.stdout.flush()
Exemple #5
0
    def run(self):
        """ Setup input files, run a vasp relaxation, and report results """

        # construct the Relax object
        relaxation = vasp.Relax(self.calcdir, self.run_settings())

        # check the current status
        (status, task) = relaxation.status()

        if status == "complete":
            print("Status:", status)
            sys.stdout.flush()

            # mark job as complete in db
            if self.auto:
                try:
                    complete_job()
                except (JobsError, JobDBError, EligibilityError) as e:
                    print(str(e))
                    sys.stdout.flush()

            # write results to properties.calc.json
            self.finalize()
            return

        elif status == "not_converging":
            print("Status:", status)
            self.report_status("failed", "run_limit")
            print("Returning")
            sys.stdout.flush()
            return

        elif status == "incomplete":

            if task == "setup":
                self.setup()

            self.report_status("started")
            (status, task) = relaxation.run()

        else:
            self.report_status("failed", "unknown")
            raise VaspWrapperError("unexpected relaxation status: '" + status +
                                   "' and task: '" + task + "'")
            sys.stdout.flush()

        # once the run is done, update database records accordingly

        if status == "not_converging":

            # mark error
            if self.auto:
                try:
                    error_job("Not converging")
                except (JobsError, JobDBError) as e:
                    print(str(e))
                    sys.stdout.flush()

            print("Not Converging!")
            sys.stdout.flush()
            self.report_status("failed", "run_limit")

            # print a local settings file, so that the run_limit can be extended if the
            #   convergence problems are fixed

            config_set_dir = self.casm_directories.configuration_calc_settings_dir(
                self.configname, self.clex)

            try:
                os.makedirs(config_set_dir)
            except:
                pass
            settingsfile = os.path.join(config_set_dir, "relax.json")
            write_settings(self.settings, settingsfile)

            print("Writing:", settingsfile)
            print("Edit the 'run_limit' property if you wish to continue.")
            sys.stdout.flush()
            return

        elif status == "complete":

            # mark job as complete in db
            if self.auto:
                try:
                    complete_job()
                except (JobsError, JobDBError, EligibilityError) as e:
                    print(str(e))
                    sys.stdout.flush()

            # write results to properties.calc.json
            self.finalize()

        else:
            self.report_status("failed", "unknown")
            raise VaspWrapperError(
                "vasp relaxation complete with unexpected status: '" + status +
                "' and task: '" + task + "'")
            sys.stdout.flush()
Exemple #6
0
    def submit(self):
        """Submit a job for this VASP relaxation"""

        print("Submitting...")
        print("Configuration:", self.configname)
        # first, check if the job has already been submitted and is not completed
        db = JobDB()
        print("Calculation directory:", self.calcdir)
        id = db.select_regex_id("rundir", self.calcdir)
        print("JobID:", id)
        sys.stdout.flush()
        if id != []:
            for j in id:
                job = db.select_job(j)
                # taskstatus = ["Incomplete","Complete","Continued","Check","Error:.*","Aborted"]
                # jobstatus = ["C","Q","R","E","W","H","M"]
                if job["jobstatus"] != "C":
                    print("JobID:", job["jobid"], "  Jobstatus:",
                          job["jobstatus"], "  Not submitting.")
                    sys.stdout.flush()
                    return
                #elif job["taskstatus"] in ["Complete", "Check"] or re.match( "Error:.*", job["taskstatus"]):
                #    print "JobID:", job["jobid"], "  Taskstatus:", job["taskstatus"], "  Not submitting."
                #    sys.stdout.flush()
                #    return

        # second, only submit a job if relaxation status is "incomplete"

        # construct the Relax object
        relaxation = vasp.Relax(self.calcdir, self.run_settings())

        # check the current status
        (status, task) = relaxation.status()

        if status == "complete":
            print("Status:", status, "  Not submitting.")
            sys.stdout.flush()

            # ensure job marked as complete in db
            if self.auto:
                for j in id:
                    job = db.select_job(j)
                    if job["taskstatus"] == "Incomplete":
                        try:
                            complete_job(jobid=j)
                        except (JobsError, JobDBError, EligibilityError) as e:
                            print(str(e))
                            sys.stdout.flush()

            # ensure results report written
            if not os.path.isfile(
                    os.path.join(self.calcdir, "properties.calc.json")):
                self.finalize()

            return

        elif status == "not_converging":
            print("Status:", status, "  Not submitting.")
            sys.stdout.flush()
            return

        elif status != "incomplete":
            raise VaspWrapperError("unexpected relaxation status: '" + status +
                                   "' and task: '" + task + "'")
            sys.stdout.flush()
            return

        print("Preparing to submit a VASP relaxation job")
        sys.stdout.flush()

        # cd to configdir, submit jobs from configdir, then cd back to currdir
        currdir = os.getcwd()
        os.chdir(self.calcdir)

        # determine the number of atoms in the configuration
        print("Counting atoms in the POSCAR")
        sys.stdout.flush()
        pos = vasp.io.Poscar(os.path.join(self.configdir, "POS"))
        N = len(pos.basis)

        # construct command to be run
        cmd = ""
        if self.settings["preamble"] is not None:
            # Append any instructions given in the 'preamble' file, if given
            preamble = self.casm_directories.settings_path_crawl(
                self.settings["preamble"], self.configname, self.clex)
            with open(preamble, 'rb') as my_preamble:
                cmd += "".join(my_preamble.read().decode('utf-8'))
        # Or just execute a single prerun line, if given
        if self.settings["prerun"] is not None:
            cmd += self.settings["prerun"] + "\n"
        cmd += "python -c \"import casm.vaspwrapper; casm.vaspwrapper.Relax('" + self.configdir + "').run()\"\n"
        if self.settings["postrun"] is not None:
            cmd += self.settings["postrun"] + "\n"

        print("Constructing a job")
        sys.stdout.flush()
        # construct a Job
        job = Job(name=wrapper.jobname(self.configname),\
                      account=self.settings["account"],\
                      nodes=int(math.ceil(float(N)/float(self.settings["atom_per_proc"])/float(self.settings["ppn"]))),\
                      ppn=int(self.settings["ppn"]),\
                      walltime=self.settings["walltime"],\
                      pmem=self.settings["pmem"],\
                      qos=self.settings["qos"],\
                      queue=self.settings["queue"],\
                      message=self.settings["message"],\
                      email=self.settings["email"],\
                      priority=self.settings["priority"],\
                      command=cmd,\
                      auto=self.auto)

        print("Submitting")
        sys.stdout.flush()
        # submit the job
        job.submit()
        self.report_status("submitted")

        # return to current directory
        os.chdir(currdir)

        print("CASM VASPWrapper relaxation job submission complete\n")
        sys.stdout.flush()
Exemple #7
0
    def run(self):
        """run the job of a selection"""
        for index, config_data in self.selection.data.iterrows():
            settings = self.read_settings(config_data["setfile"])
            calculation = self.calculator(config_data["calcdir"],
                                          self.run_settings(settings))

            # check the current status
            (status, task) = calculation.status()

            if status == "complete":
                print("Status:", status)
                sys.stdout.flush()

                # mark job as complete in db
                if self.auto:
                    try:
                        complete_job()
                    except (JobsError, JobDBError, EligibilityError) as e:
                        print(str(e))
                        sys.stdout.flush()

                # write results to properties.calc.json
                if (is_converged(calculation)):
                    self.finalize(config_data)
                continue

            elif status == "not_converging":
                print("Status:", status)
                self.report_status(config_data["calcdir"], "failed",
                                   "run_limit")
                print("Returning")
                sys.stdout.flush()
                continue

            elif status == "incomplete":

                self.report_status(config_data["calcdir"], "started")
                (status, task) = calculation.run()

            else:
                self.report_status(config_data["calcdir"], "failed", "unknown")
                raise VaspWrapperError("unexpected relaxation status: '" +
                                       status + "' and task: '" + task + "'")
            sys.stdout.flush()

            # once the run is done, update database records accordingly

            if status == "not_converging":

                # mark error
                if self.auto:
                    try:
                        error_job("Not converging")
                    except (JobsError, JobDBError) as e:
                        print(str(e))
                        sys.stdout.flush()

                print("Not Converging!")
                sys.stdout.flush()
                self.report_status(config_data["calcdir"], "failed",
                                   "run_limit")

                # print a local settings file, so that the run_limit can be extended if the
                #   convergence problems are fixed

                config_set_dir = self.casm_directories.configuration_calc_settings_dir(
                    config_data["name"], self.clex, self.calc_subdir)

                try:
                    os.makedirs(config_set_dir)
                except:
                    pass
                settingsfile = os.path.join(config_set_dir, "calc.json")
                write_settings(settings, settingsfile)

                print("Writing:", settingsfile)
                print("Edit the 'run_limit' property if you wish to continue.")
                sys.stdout.flush()
                continue

            elif status == "complete":

                # mark job as complete in db
                if self.auto:
                    try:
                        complete_job()
                    except (JobsError, JobDBError, EligibilityError) as e:
                        print(str(e))
                        sys.stdout.flush()

                # write results to properties.calc.json
                if is_converged(calculation):
                    self.finalize(config_data)

            else:
                self.report_status(config_data["calcdir"], "failed", "unknown")
                raise VaspWrapperError(
                    "vasp relaxation complete with unexpected status: '" +
                    status + "' and task: '" + task + "'")
            sys.stdout.flush()
Exemple #8
0
    def submit(self):
        """ submit jobs for a selection"""
        self.pre_setup()
        db = pbs.JobDB()
        for index, config_data in self.selection.data.iterrows():
            print("Submitting...")
            print("Configuration:", config_data["name"])
            #first, check if the job has already been submitted and is not completed
            print("Calculation directory:", config_data["calcdir"])
            id = db.select_regex_id("rundir", config_data["calcdir"])
            print("JobID:", id)
            sys.stdout.flush()
            try:
                if id != []:
                    db.update()
                    for j in id:
                        job = db.select_job(j)
                        if job["jobstatus"] != "C":
                            print("JobID:", job["jobid"], "  Jobstatus:",
                                  job["jobstatus"], "  Not submitting.")
                            sys.stdout.flush()
                            raise BreakException
            except BreakException:
                continue
            settings = self.read_settings(config_data["setfile"])
            # construct the Relax object
            calculation = self.calculator(config_data["calcdir"],
                                          self.run_settings(settings))
            # check the current status
            (status, task) = calculation.status()

            if status == "complete":
                print("Status:", status, "  Not submitting.")
                sys.stdout.flush()

                # ensure job marked as complete in db
                if self.auto:
                    for j in id:
                        job = db.select_job(j)
                        if job["taskstatus"] == "Incomplete":
                            try:
                                complete_job(jobid=j)
                            except (JobsError, JobDBError,
                                    EligibilityError) as e:
                                print(str(e))
                                sys.stdout.flush()

                # ensure results report written
                if not os.path.isfile(
                        os.path.join(config_data["calcdir"],
                                     "properties.calc.json")):
                    if (is_converged(calculation)):
                        self.finalize(config_data)

                continue

            elif status == "not_converging":
                print("Status:", status, "  Not submitting.")
                sys.stdout.flush()
                continue

            elif status != "incomplete":
                raise VaspWrapperError("unexpected relaxation status: '" +
                                       status + "' and task: '" + task + "'")
                sys.stdout.flush()
                continue

            print("Preparing to submit a VASP relaxation PBS job")
            sys.stdout.flush()

            # cd to configdir, submit jobs from configdir, then cd back to currdir
            currdir = os.getcwd()
            os.chdir(config_data["calcdir"])

            self.config_setup(config_data)
            nodes, ppn = self._calc_submit_node_info(settings, config_data)

            # construct command to be run
            cmd = ""
            if settings["preamble"] is not None:
                # Append any instructions given in the 'preamble' file, if given
                preamble = self.casm_directories.settings_path_crawl(
                    settings["preamble"], config_data["name"], self.clex,
                    self.calc_subdir)
                with open(preamble) as my_preamble:
                    cmd += "".join(my_preamble)
            # Or just execute a single prerun line, if given
            if settings["prerun"] is not None:
                cmd += settings["prerun"] + "\n"
            cmd += self.run_cmd(config_data["configdir"], self.calctype)
            if settings["postrun"] is not None:
                cmd += settings["postrun"] + "\n"

            print("Constructing a PBS job")
            sys.stdout.flush()
            # construct a pbs.Job
            job = pbs.Job(name=casm.jobname(config_data["configdir"]),
                          account=settings["account"],
                          nodes=nodes,
                          ppn=ppn,
                          walltime=settings["walltime"],
                          pmem=settings["pmem"],
                          qos=settings["qos"],
                          queue=settings["queue"],
                          message=settings["message"],
                          email=settings["email"],
                          priority=settings["priority"],
                          command=cmd,
                          auto=self.auto,
                          software=db.config["software"])

            print("Submitting")
            sys.stdout.flush()
            # submit the job
            job.submit()
            self.report_status(config_data["calcdir"], "submitted")

            # return to current directory
            os.chdir(currdir)

            print("CASM VASPWrapper relaxation PBS job submission complete\n")
            sys.stdout.flush()