Example #1
0
    def challenge_pseudo(self, pseudo, **kwargs):
        """
        This method represents the main entry point for client code.
        The Dojo receives a pseudo-like object and delegate the execution
        of the tests to the dojo_masters

        Args:
            `Pseudo` object or filename.
        """
        pseudo = Pseudo.aspseudo(pseudo)

        workdir = "DOJO_" + pseudo.name

        # Build master instances.
        masters = [cls(manager=self.manager, max_ncpus=self.max_ncpus,
                       verbose=self.verbose) for cls in self.master_classes]
        isok = False
        for master in masters:
            if master.accept_pseudo(pseudo, **kwargs):
                isok = master.start_training(workdir, **kwargs)
                if not isok:
                    print("master: %s returned isok %s.\n Skipping next trials!" % (master.name, isok))
                    break

        return isok
Example #2
0
    def work_for_pseudo(self, pseudo, accuracy="normal", kppa=6750, 
        ecut=None, toldfe=1.e-8, smearing="fermi_dirac:0.0005", workdir=None, manager=None):
        """
        Returns a `Work` object from the given pseudopotential.

        .. note: 
            0.001 Rydberg is the value used with WIEN2K
        """
        pseudo = Pseudo.aspseudo(pseudo)

        try:
            cif_path = self.get_cif_path(pseudo.symbol)
        except Exception as exc:
            raise CIFNotFoundError(str(exc))

        # Include spin polarization for O, Cr and Mn (antiferromagnetic) 
        # and Fe, Co, and Ni (ferromagnetic). 
        spin_mode = "unpolarized"

        if pseudo.symbol in ["Fe", "Co", "Ni"]: spin_mode = "polarized"
        if pseudo.symbol in ["O", "Cr", "Mn"]: spin_mode = "afm"

        work = DeltaFactorWorkflow(cif_path, pseudo, kppa,
                         spin_mode=spin_mode, toldfe=toldfe, smearing=smearing, 
                         accuracy=accuracy, ecut=ecut, ecutsm=0.05, workdir=workdir, manager=manager 
                        )
        return work
Example #3
0
    def get_pseudos(options):
        """
        Find pseudos in paths, return :class:`PseudoTable` object sorted by atomic number Z.
        Accepts filepaths or directory.
        """
        exts=("psp8",)

        paths = options.pseudos
        if len(paths) == 1 and os.path.isdir(paths[0]):
            top = paths[0]
            paths = find_exts(top, exts, exclude_dirs="_*")
            #table = PseudoTable.from_dir(paths[0])

        pseudos = []
        for p in paths:
            try:
                pseudos.append(Pseudo.from_file(p))
            except Exception as exc:
                warn("Error in %s:\n%s" % (p, exc))

        table = PseudoTable(pseudos)

        # Here we select a subset of pseudos according to family or rows
        if options.rows:
            table = table.select_rows(options.rows)
        elif options.family:
            table = table.select_families(options.family)

        if options.symbols:
            table = table.select_symbols(options.symbols)

        return table.sort_by_z()
Example #4
0
    def accept_pseudo(self, pseudo):
        """
        Return True if the mast can train the pseudo.
        This method is called before testing the pseudo

        A master can train the pseudo if his level == pseudo.dojo_level + 1
        """
        if not isinstance(pseudo, Pseudo):
            pseudo = Pseudo.from_filename(pseudo)

        ready = False
        if pseudo.dojo_level is None:
            # hints are missing
            ready = (self.dojo_level == 0)
        else:
            ready = (pseudo.dojo_level == self.dojo_level - 1)

        if not ready:
            msg = "%s: Sorry, %s-san, I cannot train you" % (
                self.__class__.__name__, pseudo.name)
            print(msg)
        else:
            print("%s: Welcome %s-san, I'm your level-%d trainer" %
                  (self.__class__.__name__, pseudo.name, self.dojo_level))
            self.pseudo = pseudo

        return ready
Example #5
0
    def accept_pseudo(self, pseudo):
        """
        Return True if the mast can train the pseudo.
        This method is called before testing the pseudo

        A master can train the pseudo if his level == pseudo.dojo_level + 1
        """
        if not isinstance(pseudo, Pseudo):
            pseudo = Pseudo.from_filename(pseudo)

        ready = False
        if pseudo.dojo_level is None:
            # hints are missing
            ready = (self.dojo_level == 0)
        else:
            ready = (pseudo.dojo_level == self.dojo_level - 1)

        if not ready:
            msg = "%s: Sorry, %s-san, I cannot train you" % (self.__class__.__name__, pseudo.name)
            print(msg)
        else:
            print("%s: Welcome %s-san, I'm your level-%d trainer" % (self.__class__.__name__, pseudo.name, self.dojo_level))
            self.pseudo = pseudo

        return ready
Example #6
0
    def work_for_pseudo(self, pseudo, accuracy="normal", kppa=6750, ecut=None, pawecutdg=None,
                        toldfe=1.e-9, smearing="fermi_dirac:0.1 eV", workdir=None, manager=None, **kwargs):
        """
        Returns a :class:`Work` object from the given pseudopotential.

        Args:
            kwargs: Extra variables passed to Abinit.

        .. note::

            0.001 Rydberg is the value used with WIEN2K
        """
        pseudo = Pseudo.as_pseudo(pseudo)
        symbol = pseudo.symbol

        if pseudo.ispaw and pawecutdg is None:
            raise ValueError("pawecutdg must be specified for PAW calculations.")

        try:
            cif_path = self.get_cif_path(symbol)
        except Exception as exc:
            raise self.Error(str(exc))

        # Include spin polarization for O, Cr and Mn (antiferromagnetic)
        # and Fe, Co, and Ni (ferromagnetic).
        # antiferromagnetic Cr, O
        # ferrimagnetic Mn
        spin_mode = "unpolarized"

        if symbol in ["Fe", "Co", "Ni"]:
            spin_mode = "polarized"
            if symbol == "Fe":
                kwargs['spinat'] = 2 * [(0, 0, 2.3)]
            if symbol == "Co":
                kwargs['spinat'] = 2 * [(0, 0, 1.2)]
            if symbol == "Ni":
                kwargs['spinat'] = 4 * [(0, 0, 0.6)]

        if symbol in ["O", "Cr", "Mn"]:
            spin_mode = "afm"
            if symbol == 'O':
                kwargs['spinat'] = [(0, 0, 1.5), (0, 0, 1.5), (0, 0, -1.5), (0, 0, -1.5)]
            elif symbol == 'Cr':
                kwargs['spinat'] = [(0, 0, 1.5), (0, 0, -1.5)]
            elif symbol == 'Mn':
                kwargs['spinat'] = [(0, 0, 2.0), (0, 0, 1.9), (0, 0, -2.0), (0, 0, -1.9)]

        # DO NOT CHANGE THE STRUCTURE REPORTED IN THE CIF FILE.
        structure = Structure.from_file(cif_path, primitive=False)

        # Magnetic elements:
        # Start from previous SCF run to avoid getting trapped in local minima 
        connect = symbol in ("Fe", "Co", "Ni", "Cr", "Mn", "O", "Zn", "Cu")

        return DeltaFactorWork(
            structure, pseudo, kppa, connect,
            spin_mode=spin_mode, toldfe=toldfe, smearing=smearing,
            accuracy=accuracy, ecut=ecut, pawecutdg=pawecutdg, ecutsm=0.5,
            workdir=workdir, manager=manager, **kwargs)
Example #7
0
    def __init__(self, structure, struct_type, pseudo, ecut=None, pawecutdg=None, ngkpt=(8, 8, 8),
                 spin_mode="unpolarized", toldfe=1.e-9, smearing="fermi_dirac:0.001 Ha",
                 accuracy="normal", ecutsm=0.05, chksymbreak=0,
                 workdir=None, manager=None, **kwargs):
        """
        Build a :class:`Work` for the computation of the relaxed lattice parameter.

        Args:   
            structure: :class:`Structure` object 
            structure_type: fcc, bcc 
            pseudo: String with the name of the pseudopotential file or :class:`Pseudo` object.
            ecut: Cutoff energy in Hartree
            ngkpt: MP divisions.
            spin_mode: Spin polarization mode.
            toldfe: Tolerance on the energy (Ha)
            smearing: Smearing technique.
            workdir: String specifing the working directory.
            manager: :class:`TaskManager` responsible for the submission of the tasks.
        """
        super(GbrvRelaxAndEosWork, self).__init__(workdir=workdir, manager=manager)
        self.struct_type = struct_type
        self.accuracy = accuracy

        # nband must be large enough to accomodate fractional occupancies.
        fband = kwargs.pop("fband", None)
        self._pseudo = Pseudo.as_pseudo(pseudo)
        nband = gbrv_nband(self.pseudo)

        # Set extra_abivars.
        self.extra_abivars = dict(
            ecut=ecut,
            pawecutdg=pawecutdg,
            toldfe=toldfe,
            prtwf=0,
            #ecutsm=0.5,
            nband=nband,
            #paral_kgb=paral_kgb
        )
                                       
        self.extra_abivars.update(**kwargs)
        self.ecut = ecut
        self.smearing = Smearing.as_smearing(smearing)

        # Kpoint sampling: shiftk depends on struct_type
        shiftk = {"fcc": [0, 0, 0], "bcc": [0.5, 0.5, 0.5]}.get(struct_type)
        #ngkpt = (1,1,1)
        self.ksampling = KSampling.monkhorst(ngkpt, chksymbreak=chksymbreak, shiftk=shiftk)
        self.spin_mode = SpinMode.as_spinmode(spin_mode)
        relax_algo = RelaxationMethod.atoms_and_cell()

        #self.relax_input = RelaxStrategy(structure, pseudo, self.ksampling, relax_algo, 
        #                                 accuracy=accuracy, spin_mode=spin_mode, smearing=smearing, **self.extra_abivars)

        inp = abilab.AbinitInput(structure, pseudo)
        inp.add_abiobjects(self.ksampling, relax_algo, self.spin_mode, self.smearing)
        inp.set_vars(self.extra_abivars)

        # Register structure relaxation task.
        self.relax_task = self.register_relax_task(inp)
Example #8
0
    def add_pseudo(self, pseudo):
        """Add a pseudo to the Dojo."""
        pseudo = Pseudo.as_pseudo(pseudo)

        dojo_report = DojoReport.from_file(pseudo.filepath)

        # Construct the flow 
        flow_workdir = os.path.join(self.workdir, pseudo.name)
        flow = AbinitFlow(workdir=flow_workdir, manager=self.manager, pickle_protocol=0)

        # Construct the flow according to the info found in the dojo report.
        if not pseudo.has_hints:
            # We need the hints in order to run the other tests
            factory = PPConvergenceFactory()
            ecut_work = factory.work_for_pseudo(pseudo, ecut_slice=slice(4, None, 1), nlaunch=4)
            flow.register_work(ecut_work)

        else:
            # Hints are available --> construct a flow for the different trials.
            dojo_trial = "deltafactor"
            if dojo_trial in self.trials:
                # Do we have this element in the deltafactor database?
                #if not df_database().has_symbol(pseudo.symbol):
                #    logger.warning("Cannot find %s in deltafactor database." % pseudo.symbol)

                delta_factory = DeltaFactory()
                kppa = 6750 # 6750 is the value used in the deltafactor code.
                kppa = 1

                for accuracy in self.accuracies:
                    if dojo_report.has_trial(dojo_trial, accuracy): continue
                    ecut, pawecutdg = self._ecut_pawecutdg(pseudo, accuracy)
                    work = delta_factory.work_for_pseudo(pseudo, accuracy=accuracy, kppa=kppa, ecut=ecut, pawecutdg=pawecutdg)

                    logger.info("Adding work for %s with accuracy %s" % (dojo_trial, accuracy))
                    work.set_dojo_accuracy(accuracy)
                    flow.register_work(work)

            # Test if GBRV tests are wanted.
            gbrv_structs = [s.split("_")[1] for s in self.trials if s.startswith("gbrv_")]

            if gbrv_structs:
                gbrv_factory = GbrvFactory()
                for struct_type in gbrv_structs:
                    dojo_trial = "gbrv_" + struct_type
                    for accuracy in self.accuracies:
                        if dojo_report.has_trial(dojo_trial, accuracy): continue
                        ecut, pawecutdg = self._ecut_pawecutdg(pseudo, accuracy)
                        work = gbrv_factory.relax_and_eos_work(pseudo, struct_type, ecut=ecut, pawecutdg=pawecutdg)

                        logger.info("Adding work for %s with accuracy %s" % (dojo_trial, accuracy))
                        work.set_dojo_accuracy(accuracy)
                        flow.register_work(work)

        flow.allocate()
        self.pseudos.append(pseudo)
        self.flows.append(flow)
Example #9
0
    def work_for_pseudo(self, pseudo, **kwargs):
        """
        Create a :class:`Flow` for phonon calculations:

            1) One workflow for the GS run.

            2) nqpt workflows for phonon calculations. Each workflow contains
               nirred tasks where nirred is the number of irreducible phonon perturbations
               for that particular q-point.

            the kwargs are passed to scf_hp_inputs
        """
        try:
            qpt = kwargs['qpt']
        except IndexError:
            raise ValueError('A phonon test needs to specify a qpoint.')

        kwargs.pop('accuracy')

        pseudo = Pseudo.as_pseudo(pseudo)

        structure_or_cif = self.get_cif_path(pseudo.symbol)

        if not isinstance(structure_or_cif, Structure):
            # Assume CIF file
            structure = Structure.from_file(structure_or_cif, primitive=False)
        else:
            structure = structure_or_cif

        nat = len(structure)
        report = pseudo.read_dojo_report()
        ecut_str = '%.1f' % kwargs['ecut']
        #print(ecut_str)
        #print(report['deltafactor'][float(ecut_str)].keys())

        try:
            v0 = nat * report['deltafactor'][ecut_str]['v0']
        except KeyError:
            try:
                v0 = nat * report['deltafactor'][float(ecut_str)]['v0']
            except KeyError:
                # the df calculation at this ecut is not done already so the phonon task can not be created
                return None

        structure.scale_lattice(v0)
        all_inps = self.scf_ph_inputs(pseudos=[pseudo], structure=structure, **kwargs)
        scf_input, ph_inputs = all_inps[0], all_inps[1:]

        work = build_oneshot_phononwork(scf_input=scf_input, ph_inputs=ph_inputs, work_class=PhononDojoWork)
        #print('after build_oneshot_phonon')
        #print(work)
        work.set_dojo_trial(qpt)
        #print(scf_input.keys())
        work.ecut = scf_input['ecut']
        work._pseudo = pseudo
        return work
Example #10
0
    def check_status(self):
        """Check the status of the run, set and return self.status attribute."""
        if self.status == self.S_OK:
            return self._status

        parser = self.OutputParser(self.stdout_path)
        try:
            parser.scan()
        except parser.Error:
            self._status = self.S_ERROR
            return self._status

        logger.info("run_completed:", parser.run_completed)
        if self.status == self.S_DONE and not parser.run_completed:
            logger.info("Run is not completed!")
            self._status = self.S_ERROR

        if parser.run_completed:
            logger.info("setting status to S_OK")
            self._status = self.S_OK
            #########################################
            # Here we initialize results and plotter.
            #########################################
            if parser.warnings:
                self.errors.extend(parser.warnings)

            try:
                self._results = parser.get_results()
            except parser.Error:
                # File may not be completed.
                time.sleep(1)
                try:
                    self._results = parser.get_results()
                except:
                    raise

            self._plotter = parser.make_plotter()

            # Write Abinit pseudopotential.
            filepath = os.path.join(self.workdir, parser.atsym + ".psp8")
            #if os.path.exists(filepath): 
            #    raise RuntimeError("File %s already exists" % filepath)

            # Initialize self.pseudo from file.
            with open(filepath, "w") as fh:
                fh.write(parser.get_pseudo_str())

            self._pseudo = Pseudo.from_file(filepath)

        if parser.errors:
            logger.warning("setting status to S_ERROR")
            self._status = self.S_ERROR
            self.errors.extend(parser.errors)

        return self._status
Example #11
0
    def __init__(self, ps_name):
        """

        """
        self.param = {}
        self.df_data = {}
        self.results = {}
        self.etotal_data = {}
        self.df_extra = np.inf
        self.ps_name = ps_name
        self.pseudo = Pseudo.from_file(ps_name+'.psp8')
Example #12
0
File: input.py Project: kidaa/abipy
    def from_dict(cls, d):
        pseudos = []
        for p in d['pseudos']:
            pseudos.append(Pseudo.from_file(p['filepath']))

        dtsets = d['datasets']
        abiinput = cls(pseudos, ndtset=dtsets[0]['ndtset'], decorators=d["decorators"])

        for n, ds in enumerate(dtsets):
            abiinput.set_vars(dtset=n, **ds)

        return abiinput
Example #13
0
    def challenge_pseudo(self, pseudo):
        pseudo = Pseudo.aspseudo(pseudo)

        workdir = "DOJO_" + pseudo.name

        # Build master instances.
        masters = [cls(runmode=self.runmode, max_ncpus=self.max_ncpus,
                       verbose=verbose) for cls in self.master_classes]

        kwargs = {}
        for master in masters:
            if master.accept_pseudo(pseudo):
                master.start_training(workdir, **kwargs)
Example #14
0
    def from_dict(cls, d):
        pseudos = []
        for p in d['pseudos']:
            pseudos.append(Pseudo.from_file(p['filepath']))

        dtsets = d['datasets']
        abiinput = cls(pseudos,
                       ndtset=dtsets[0]['ndtset'],
                       decorators=d["decorators"])

        for n, ds in enumerate(dtsets):
            abiinput.set_vars(dtset=n, **ds)

        return abiinput
Example #15
0
def get_pseudos(top):
    """
    Find pseudos within top, return :class:`PseudoTable` object sorted by atomic number Z.
    """
    from monty.os.path import find_exts
    from pymatgen.io.abinitio.pseudos import PseudoTable, Pseudo
    exts=("psp8",)
    pseudos = []
    for p in find_exts(top, exts, exclude_dirs="_*"):
        try:
            pseudos.append(Pseudo.from_file(p))
        except Exception as exc:
            from warnings import warn
            warn("Exception in pseudo %s:\n%s" % (p.filepath, exc))
            
    return PseudoTable(pseudos).sort_by_z()
Example #16
0
    def challenge_pseudo(self, pseudo):
        pseudo = Pseudo.aspseudo(pseudo)

        workdir = "DOJO_" + pseudo.name

        # Build master instances.
        masters = [
            cls(runmode=self.runmode,
                max_ncpus=self.max_ncpus,
                verbose=verbose) for cls in self.master_classes
        ]

        kwargs = {}
        for master in masters:
            if master.accept_pseudo(pseudo):
                master.start_training(workdir, **kwargs)
Example #17
0
    def __init__(self, workdir, manager, pseudo, ecut_list_or_slice, atols_mev,
                 toldfe=1.e-8, spin_mode="polarized", 
                 acell=(8, 9, 10), smearing="fermi_dirac:0.1 eV", max_niter=50,):
        """
        Args:
            workdir:
                Working directory.
            pseudo:
                string or Pseudo instance
            ecut_list_or_slice:
                List of cutoff energies or slice object (mainly used for infinite iterations).
            atols_mev:
                List of absolute tolerances in meV (3 entries corresponding to accuracy ["low", "normal", "high"]
            manager:
                `TaskManager` object.
            spin_mode:
                Defined how the electronic spin will be treated.
            acell:
                Lengths of the periodic box in Bohr.
            smearing:
                Smearing instance or string in the form "mode:tsmear". Default: FemiDirac with T=0.1 eV
        """
        self.pseudo = Pseudo.aspseudo(pseudo)

        self.atols_mev = atols_mev
        self.toldfe = toldfe
        self.spin_mode = spin_mode
        self.smearing = Smearing.assmearing(smearing)
        self.acell = acell

        if isinstance(ecut_list_or_slice, slice):
            self.ecut_iterator = iterator_from_slice(ecut_list_or_slice)
        else:
            self.ecut_iterator = iter(ecut_list_or_slice)

        # Construct a generator that returns strategy objects.
        def strategy_generator():
            for ecut in self.ecut_iterator:
                yield self.strategy_with_ecut(ecut)

        super(PseudoIterativeConvergence, self).__init__(strategy_generator(), 
              max_niter=max_niter, workdir=workdir, manager=manager, )

        if not self.isnc:
            raise NotImplementedError("PAW convergence tests are not supported yet")
Example #18
0
    def __init__(self, workdir, manager, pseudo, ecut_list, atols_mev,
                 toldfe=1.e-8, spin_mode="polarized", 
                 acell=(8, 9, 10), smearing="fermi_dirac:0.1 eV"):

        super(PseudoConvergence, self).__init__(workdir, manager)

        # Temporary object used to build the strategy.
        generator = PseudoIterativeConvergence(workdir, manager, pseudo, ecut_list, atols_mev,
                                               toldfe    = toldfe,
                                               spin_mode = spin_mode,
                                               acell     = acell,
                                               smearing  = smearing,
                                               max_niter = len(ecut_list),
                                              )
        self.atols_mev = atols_mev
        self.pseudo = Pseudo.aspseudo(pseudo)

        self.ecut_list = []
        for ecut in ecut_list:
            strategy = generator.strategy_with_ecut(ecut)
            self.ecut_list.append(ecut)
            self.register(strategy)
Example #19
0
    def accept_pseudo(self, pseudo, **kwargs):
        """
        Returns True if the mast can train the pseudo.
        This method is called before testing the pseudo.

        A master can train the pseudo if his level == pseudo.dojo_level + 1
        """
        if not isinstance(pseudo, Pseudo):
            pseudo = Pseudo.from_filename(pseudo)

        ready = False
        pseudo_dojo_level = self.inspect_pseudo(pseudo)
        
        if pseudo_dojo_level is None:
            # Hints are missing
            ready = (self.dojo_level == 0)
        else:
            if pseudo_dojo_level == self.dojo_level:
                # pseudo has already a test associated to this level.
                # check if it has the same accuracy.
                accuracy = kwargs.get("accuracy", "normal")
                if accuracy not in pseudo.dojo_report[self.dojo_key]:
                    ready = True
                else:
                    print("%s: %s has already an entry for accuracy %s" % (self.name, pseudo.name, accuracy))
                    ready = False

            else:
                # Pseudo level must be one less than the level of the master.
                ready = (pseudo_dojo_level == self.dojo_level - 1)

        if not ready:
            print("%s: Sorry, %s-san, I cannot train you" % (self.name, pseudo.name))
        else:
            print("%s: Welcome %s-san, I'm your level-%d trainer" % (self.name, pseudo.name, self.dojo_level))
            self.pseudo = pseudo

        return ready
Example #20
0
    def __init__(self, pseudo, ecut_slice, nlaunch, atols_mev,
                 toldfe=1.e-8, spin_mode="polarized", acell=(8, 9, 10), 
                 smearing="fermi_dirac:0.1 eV", max_niter=300, workdir=None, manager=None):
        """
        Args:
            pseudo: string or :class:`Pseudo` instance
            ecut_slice: List of cutoff energies or slice object (mainly used for infinite iterations).
            nlaunch:
            atols_mev: List of absolute tolerances in meV (3 entries corresponding to accuracy ["low", "normal", "high"]
            spin_mode: Defined how the electronic spin will be treated.
            acell: Lengths of the periodic box in Bohr.
            smearing: :class:`Smearing` instance or string in the form "mode:tsmear". Default: FemiDirac with T=0.1 eV
            max_niter:
            workdir: Working directory.
            manager: :class:`TaskManager` object.
        """
        super(PseudoConvergence, self).__init__(workdir, manager)

        self._pseudo = Pseudo.as_pseudo(pseudo)
        self.nlaunch = nlaunch; assert nlaunch > 0
        self.atols_mev = atols_mev
        self.toldfe = toldfe
        self.spin_mode = SpinMode.as_spinmode(spin_mode)
        self.acell = acell
        self.smearing = Smearing.as_smearing(smearing)
        self.max_niter = max_niter; assert max_niter > 0
        self.ecut_slice = ecut_slice; assert isinstance(ecut_slice, slice)

        self.ecuts = []

        if self.pseudo.ispaw:
            raise NotImplementedError("PAW convergence tests are not supported yet")

        for i in range(self.nlaunch):
            ecut = ecut_slice.start + i * ecut_slice.step
            #if self.ecut_slice.stop is not None and ecut > self.ecut_slice.stop: continue
            self.add_task_with_ecut(ecut)
Example #21
0
    def relax_and_eos_work(self, pseudo, struct_type, ecut=None, pawecutdg=None, ref="ae", **kwargs):
        """
        Returns a :class:`Work` object from the given pseudopotential.

        Args:
            kwargs: Extra variables passed to Abinit.

        .. note::

            GBRV tests are done with the following parameteres:

                - No spin polarization for structural relaxation 
                  (only for magnetic moments for which spin-unpolarized structures are used)
                - All calculations are done on an 8x8x8 k-point density and with 0.002 Ry Fermi-Dirac smearing
        """
        pseudo = Pseudo.as_pseudo(pseudo)

        if pseudo.ispaw and pawecutdg is None:
            raise ValueError("pawecutdg must be specified for PAW calculations.")

        structure = self.make_ref_structure(pseudo.symbol, struct_type=struct_type, ref=ref)
 
        return GbrvRelaxAndEosWork(structure, struct_type, pseudo,
                                   ecut=ecut, pawecutdg=pawecutdg, **kwargs)
Example #22
0
def build_flow(pseudo, options):
    """Build the flow, returns None if no calculation must be performed.""" 
    pseudo = Pseudo.as_pseudo(pseudo)

    workdir = pseudo.basename + "_DOJO"
    if os.path.exists(workdir): 
        warn("Directory %s already exists" % workdir)
        return None
        #raise ValueError("%s exists" % workdir)

    flow = abilab.Flow(workdir=workdir, manager=options.manager)

    extra_abivars = {
            "mem_test": 0,
            "fband": 2,
            "nstep": 100,
            "paral_kgb": options.paral_kgb
            #"nsym": 1,
    }

    report = pseudo.read_dojo_report()
    #print(report)
    #hints = report["hints"]

    # Build ecut mesh.
    try:
        ppgen_ecut = int(report["ppgen_hints"]["high"]["ecut"])

        ecut_list = copy.copy(report["ecuts"])
    except KeyError:
        print('New pseudo without report from the generator, the convergence study is started from 16H')
        report["ppgen_hints"] = {}
        report["ppgen_hints"]["high"] = {} 
        report["ppgen_hints"]["high"]["ecut"] = 16.0
        report["ecuts"] = [16.0, 20.0, 24.0]
        pseudo.write_dojo_report(report)
        ppgen_ecut = int(report["ppgen_hints"]["high"]["ecut"])
        ecut_list = copy.copy(report["ecuts"])

    #if 'extend' in options:
    #    next_ecut = max(ecut_list) + 2
    #    ecut_list.append(next_ecut)

    #if 'new-ecut' in options:
    #    ecut_list.append(options['new-ecut'])

    add_ecuts = False
    if add_ecuts:
        #dense_right = np.linspace(ppgen_ecut, ppgen_ecut + 10, num=6)
        #dense_left = np.linspace(ppgen_ecut-8, ppgen_ecut, num=4, endpoint=False)
        #coarse_high = np.linspace(ppgen_ecut + 15, ppgen_ecut + 40, num=4)

        dense_right = np.arange(ppgen_ecut, ppgen_ecut + 6*2, step=2)
        dense_left = np.arange(max(ppgen_ecut-6, 2), ppgen_ecut, step=2)
        coarse_high = np.arange(ppgen_ecut + 15, ppgen_ecut + 35, step=5)

        ecut_list = list(dense_left) + list(dense_right) + list(coarse_high)

    # Computation of the deltafactor.
    if "df" in options.trials:
        #FIXME
        #factory = DeltaFactory(xc=pseudo.xc)
        if os.path.isfile('LDA'):
            factory = DeltaFactory(xc='LDA')
        else:
            factory = DeltaFactory()
        for ecut in ecut_list:
            if "deltafactor" in report and ecut in report["deltafactor"].keys(): continue
            pawecutdg = 2 * ecut if pseudo.ispaw else None
            # Build and register the workflow.
            work = factory.work_for_pseudo(pseudo, kppa=6750, ecut=ecut, pawecutdg=pawecutdg, **extra_abivars)
            flow.register_work(work, workdir='WDF' + str(ecut))

    # GBRV tests.
    if "gbrv" in options.trials:
        gbrv_factory = GbrvFactory()
        gbrv_structs = ("fcc", "bcc")
        for struct_type in gbrv_structs:
            dojo_trial = "gbrv_" + struct_type
            for ecut in ecut_list:
                if dojo_trial in report and ecut in report[dojo_trial].keys(): continue
                pawecutdg = 2 * ecut if pseudo.ispaw else None
                # FIXME: we use ntime=3, because structure relaxations go bananas after the third step.
                work = gbrv_factory.relax_and_eos_work(pseudo, struct_type, ecut=ecut, ntime=5, pawecutdg=pawecutdg, **extra_abivars)
                flow.register_work(work, workdir="GBRV_" + struct_type + str(ecut))

    # PHONON test
    if "phonon" in options.trials:
        phonon_factory = DFPTPhononFactory()
        for ecut in ecut_list:
            str_ecut = '%.1f' % ecut
            if "phonon" in report and str_ecut in report["phonon"].keys(): continue
            kppa = 1000
            pawecutdg = 2 * ecut if pseudo.ispaw else None
            work = phonon_factory.work_for_pseudo(pseudo, accuracy="high", kppa=kppa, ecut=ecut, pawecutdg=pawecutdg,
                                                  tolwfr=1.e-20, smearing="fermi_dirac:0.0005", qpt=[0,0,0], mem_test=0)
            if work is not None:
                flow.register_work(work, workdir='GammaPhononsAt'+str(ecut))
            else:
                warn('cannot create GammaPhononsAt' + str(ecut) + ' work, factory returned None')

    # PHONON WihtOut Asr test
    if "phwoa" in options.trials:
        phonon_factory = DFPTPhononFactory()
        for ecut in [ecut_list[0], ecut_list[-1]]:
            str_ecut = '%.1f' % ecut
            if "phwoa" in report and str_ecut in report["phwoa"].keys(): continue
            print('phwoa')
            kppa = 1000
            pawecutdg = 2 * ecut if pseudo.ispaw else None
            work = phonon_factory.work_for_pseudo(pseudo, accuracy="high", kppa=kppa, ecut=ecut, pawecutdg=pawecutdg,
                                                  tolwfr=1.e-20, smearing="fermi_dirac:0.0005", qpt=[0,0,0], rfasr=0)
            if work is not None:
                flow.register_work(work, workdir='GammaPhononsAt'+str(ecut)+'WOA')
            else:
                warn('cannot create GammaPhononsAt' + str(ecut) + 'WOA work, factory returned None')


    if len(flow) > 0:
        return flow.allocate()
    else:
        # Empty flow since all trials have been already performed.
        return None
Example #23
0
def main():
    def str_examples():
        examples = """
                   Usage Example:\n
                   ppdojo_run.py Si.psp8  => Build pseudo_dojo flow for Si.fhi\n
                   """
        return examples

    def show_examples_and_exit(error_code=1):
        """Display the usage of the script."""
        #sys.stderr.write(str_examples()+'\n')
        print(str_examples())
        sys.exit(error_code)

    parser = argparse.ArgumentParser(epilog=str_examples())

    parser.add_argument('-m', '--manager', type=str, default=None,  help="Manager file")
    parser.add_argument('-d', '--dry-run', default=False, action="store_true", help="Dry run, build the flow without submitting it")
    parser.add_argument('--paral-kgb', type=int, default=0,  help="Paral_kgb input variable.")
    parser.add_argument('-p', '--plot', default=False, action="store_true", help="Plot convergence when the flow is done")
    parser.add_argument('-n', '--new-ecut', type=int, default=None, action="store", help="Extend the ecut grid with the new-ecut point")

    def parse_trials(s):
        if s == "all": return ["df", "gbrv", "phonon", "phowa"]
        return s.split(",")

    parser.add_argument('--trials', default="all",  type=parse_trials, help=("List of tests e.g --trials=df,gbrv,phonon,phwoa\n"
                        "  df:     test delta factor against all electron refference\n"
                        "  gbrv:   test fcc and bcc lattice parameters agains AE refference\n"
                        "  phonon: test phonon mode at gamma convergence\n"
                        "  phwoa:  test violation of the acoustic sum rule (without enforcing it) at the min and max ecut\n"))

    parser.add_argument('--loglevel', default="ERROR", type=str,
                        help="set the loglevel. Possible values: CRITICAL, ERROR (default), WARNING, INFO, DEBUG")

    parser.add_argument('path', help='pseudopotential file.')

    # Create the parsers for the sub-commands
    #subparsers = parser.add_subparsers(dest='command', help='sub-command help', description="Valid subcommands")
    # Subparser for single command.
    #p_build = subparsers.add_parser('build', help="Build dojo.")

    try:
        options = parser.parse_args()
    except:
        show_examples_and_exit(1)

    # loglevel is bound to the string value obtained from the command line argument. 
    # Convert to upper case to allow the user to specify --loglevel=DEBUG or --loglevel=debug
    import logging
    numeric_level = getattr(logging, options.loglevel.upper(), None)
    if not isinstance(numeric_level, int):
        raise ValueError('Invalid log level: %s' % options.loglevel)
    logging.basicConfig(level=numeric_level)

    options.manager = abilab.TaskManager.from_user_config() if options.manager is None else \
                      abilab.TaskManager.from_file(options.manager)

    if os.path.isfile(options.path):
        # Operate on a single pseudo.
        flow = build_flow(options.path, options)
        if flow is None: 
            warn("DOJO_REPORT is already computed for pseudo %s." % options.path)
            return 0
        if options.dry_run:
            flow.build_and_pickle_dump()
        else:
            # Run the flow with the scheduler.
            #print("nlaunch: %d" % flow.rapidfire())
            flow.make_scheduler().start()

    else:
        # Gather all pseudos starting from the current working directory and run the flows iteratively.
        table = PeriodicTable()
        all_symbols = set(element.symbol for element in table.all_elements)
        #all_symbols = ["H"]
        #print(os.listdir(options.path))

        #print("here", os.path.basename(os.path.dirname(options.path)))
        #print("here", options.path)
        if os.path.basename(os.path.dirname(options.path)) in all_symbols:
            #print("here")
            dirs = [options.path]
        else:
            dirs = [os.path.join(options.path, d) for d in os.listdir(options.path) if d in all_symbols]
        print(dirs)

        pseudos = []
        for d in dirs:
            #print(d)
            pseudos.extend(os.path.join(d, p) for p in os.listdir(d) if p.endswith(".psp8"))

        if not pseudos:
            warn("Empty list of pseudos")
            return 0

        nflows, nlaunch = 0, 0
        #exc_filename = "allscheds_exceptions.log"
        #if os.path.exists(exc_filename):
        #    raise RuntimeError("File %s already exists, remove it before running the script" % exc_filename)
        #exc_log = open(exc_filename, "w")
        exc_log = sys.stderr

        for pseudo in pseudos:
            pseudo = Pseudo.as_pseudo(pseudo)
            report = pseudo.dojo_report
            if "version" not in report: continue

            flow = build_flow(pseudo, options)
            if flow is None: 
                warn("DOJO_REPORT is already computed for pseudo %s." % pseudo.basename)
                continue

            #if os.path.exists(flow.workdir) or nflows >= 2: continue
            nflows += 1

            try:
                flow.make_scheduler().start()
            except Exception as exc:
                # Log exception and proceed with the next pseudo.
                exc_log.write(str(exc))

            new_report = pseudo.read_dojo_report()
            new_report.plot_deltafactor_convergence()
            new_report.plot_gbrv_convergence()
            new_report.plot_phonon_convergence()

            #with open(pseudo.basename + "sched.stdout", "w") as sched_stdout, \
            #     open(pseudo.basename + "sched.stderr", "w") as sched_stderr: 
            #    with RedirectStdStreams(stdout=sched_stdout, stderr=sched_stderr):
            #        try:
            #            flow.make_scheduler().start()
            #        except Exception as exc:
            #            # Log exception and proceed with the next pseudo.
            #            exc_log.write(str(exc))

        #exc_log.close()
        #print("nlaunch: %d" % nlaunch)
        #print("nflows: %d" % nflows)

    return 0
Example #24
0
 def pseudos(self):
     return [Pseudo.as_pseudo(ref_file("14si.pspnc"))]
Example #25
0
    def change_icmod3(self, fcfact_list=(3, 4, 5), rcfact_list=(1.3, 1.35, 1.4, 1.45, 1.5, 1.55)):
        """
        Change the value of fcfact and rcfact in the template. Generate the new pseudos
        and create new directories with the pseudopotentials in the current workding directory.

        Return:
            List of `Pseudo` objects 

        Old version with icmod == 1.
        
        # icmod fcfact
        1 0.085

        New version with icmod == 3.
        # icmod, fcfact (rcfact)
            3    5.0  1.3
        """
        magic = "# icmod fcfact"
        for i, line in enumerate(self.template_lines):
            if line.strip() == magic: break
        else:
            raise ValueError("Cannot find magic line `%s` in template:\n%s" % (magic, "\n".join(self.template_lines)))

        # Extract the parameters from the line.
        pos = i + 1
        line = self.template_lines[pos]

        tokens = line.split()
        icmod = int(tokens[0])

        #if len(tokens) != 3:
        #    raise ValueError("Expecting line with 3 numbers but got:\n%s" % line)
        #icmod, old_fcfact, old_rcfact = int(tokens[0]), float(tokens[1]), float(tokens[2])
        #if icmod != 3:
        #    raise ValueError("Expecting icmod == 3 but got %s" % icmod)

        base_name = os.path.basename(self.filepath).replace(".in", "")
        ppgens = []
        for fcfact, rcfact in product(fcfact_list, rcfact_list):
            new_input = self.template_lines[:]
            new_input[pos] = "%i %s %s\n" % (3, fcfact, rcfact)
            input_str = "".join(new_input)
            #print(input_str)
            ppgen = OncvGenerator(input_str, calc_type=self.calc_type)
            
            name = base_name + "_fcfact%3.2f_rcfact%3.2f" % (fcfact, rcfact)
            ppgen.name = name
            ppgen.stdin_basename = name + ".in"
            ppgen.stdout_basename = name + ".out"

            # Attach fcfact and rcfact to ppgen
            ppgen.fcfact, ppgen.rcfact = fcfact, rcfact

            if not ppgen.start() == 1:
                raise RuntimeError("ppgen.start() failed!")
            ppgens.append(ppgen)

        for ppgen in ppgens:
            retcode = ppgen.wait()
            ppgen.check_status()

        # Ignore errored calculations.
        ok_ppgens = [gen for gen in ppgens if gen.status == gen.S_OK]
        print("%i/%i generations completed with S_OK" % (len(ok_ppgens), len(ppgens)))

        ok_pseudos = []
        for ppgen in ok_ppgens:
            # Copy files to dest
            pseudo = ppgen.pseudo
            #dest = os.path.basename(self.filepath) + "_fcfact%3.2f_rcfact%3.2f" % (ppgen.fcfact, ppgen.rcfact)
            dest = os.path.split(self.filepath)[0]
            shutil.copy(os.path.join(ppgen.workdir,ppgen.stdin_basename), dest)
            shutil.copy(os.path.join(ppgen.workdir,ppgen.stdout_basename), dest)

            # Reduce the number of ecuts in the DOJO_REPORT
            # Re-parse the output and use devel=True to overwrite initial psp8 file
            psp8_path = os.path.join(dest, ppgen.name + ".psp8")
            out_path = os.path.join(dest, ppgen.name + ".out")

            parser = OncvOutputParser(out_path)
            parser.scan()

            # Rewrite pseudo file in devel mode.
            with open(psp8_path, "w") as fh:
                fh.write(parser.get_pseudo_str(devel=True))

            # Build new pseudo.
            p = Pseudo.from_file(psp8_path)
            ok_pseudos.append(p)

        return ok_pseudos
Example #26
0
    def __init__(self, structure_or_cif, pseudo, kppa,
                 spin_mode="polarized", toldfe=1.e-8, smearing="fermi_dirac:0.1 eV",
                 accuracy="normal", ecut=None, ecutsm=0.05, chksymbreak=0, workdir=None, manager=None): 
                 # FIXME Hack in chksymbreack
        """
        Build a `Workflow` for the computation of the deltafactor.

        Args:   
            structure_or_cif:
                Structure objec or string with the path of the CIF file.
            pseudo:
                String with the name of the pseudopotential file or `Pseudo` object.` object.` object.` 
            kppa:
            spin_mode="polarized":
            toldfe=1.e-8:
            smearing="fermi_dirac:0.1 eV":
            workdir:
                String specifing the working directory.
            manager:
                `TaskManager` responsible for the submission of the tasks.
        """
        super(DeltaFactorWorkflow, self).__init__(workdir=workdir, manager=manager)

        if isinstance(structure_or_cif, Structure):
            structure = structure_or_cif
        else:
            # Assume CIF file
            structure = read_structure(structure_or_cif)

        self.pseudo = Pseudo.aspseudo(pseudo)

        structure = AbiStructure.asabistructure(structure)

        smearing = Smearing.assmearing(smearing)

        self._input_structure = structure

        v0 = structure.volume

        # From 94% to 106% of the equilibrium volume.
        self.volumes = v0 * np.arange(94, 108, 2) / 100.

        for vol in self.volumes:
            new_lattice = structure.lattice.scale(vol)

            new_structure = Structure(new_lattice, structure.species, structure.frac_coords)
            new_structure = AbiStructure.asabistructure(new_structure)

            extra_abivars = dict(
                ecutsm=ecutsm,
                toldfe=toldfe,
                prtwf=0,
                paral_kgb=0,
            )

            if ecut is not None:
                extra_abivars.update({"ecut": ecut})

            ksampling = KSampling.automatic_density(new_structure, kppa,
                                                    chksymbreak=chksymbreak)

            scf_input = ScfStrategy(new_structure, self.pseudo, ksampling,
                                    accuracy=accuracy, spin_mode=spin_mode,
                                    smearing=smearing, **extra_abivars)

            self.register(scf_input, task_class=ScfTask)
Example #27
0
    def __init__(self, structure, pseudo, kppa, connect,
                 ecut=None, pawecutdg=None, ecutsm=0.5,
                 spin_mode="polarized", toldfe=1.e-9, smearing="fermi_dirac:0.1 eV",
                 accuracy="normal", chksymbreak=0, workdir=None, manager=None, **kwargs):
        """
        Build a :class:`Work` for the computation of the deltafactor.

        Args:   
            structure: :class:`Structure` object
            pseudo: String with the name of the pseudopotential file or :class:`Pseudo` object.
            kppa: Number of k-points per atom.
            connect: True if the SCF run should be initialized from the previous run.
            spin_mode: Spin polarization mode.
            toldfe: Tolerance on the energy (Ha)
            smearing: Smearing technique.
            workdir: String specifing the working directory.
            manager: :class:`TaskManager` responsible for the submission of the tasks.
        """
        super(DeltaFactorWork, self).__init__(workdir=workdir, manager=manager)

        self._pseudo = Pseudo.as_pseudo(pseudo)

        spin_mode = SpinMode.as_spinmode(spin_mode)
        smearing = Smearing.as_smearing(smearing)

        # Compute the number of bands from the pseudo and the spin-polarization.
        # Add 6 bands to account for smearing.
        #nval = structure.num_valence_electrons(self.pseudo)
        #spin_fact = 2 if spin_mode.nsppol == 2 else 1
        #nband = int(nval / spin_fact) + 6

        # Set extra_abivars
        self.ecut, self.pawecutdg = ecut, pawecutdg

        extra_abivars = dict(
            ecut=ecut,
            pawecutdg=pawecutdg,
            ecutsm=ecutsm,
            toldfe=toldfe,
            #nband=nband,
            prtwf=0 if not connect else 1,
            #paral_kgb=paral_kgb,
            chkprim=0,
            nstep=200,
            #mem_test=0,
        )

        extra_abivars.update(**kwargs)
        self._input_structure = structure
        v0 = structure.volume

        # From 94% to 106% of the equilibrium volume.
        self.volumes = v0 * np.arange(94, 108, 2) / 100.

        for vol in self.volumes:
            new_lattice = structure.lattice.scale(vol)

            new_structure = Structure(new_lattice, structure.species, structure.frac_coords)

            ksampling = KSampling.automatic_density(new_structure, kppa, chksymbreak=chksymbreak)

            #scf_input = ScfStrategy(new_structure, self.pseudo, ksampling,
            #                        accuracy=accuracy, spin_mode=spin_mode,
            #                        smearing=smearing, **extra_abivars)

            scf_input = abilab.AbinitInput(structure=new_structure, pseudos=self.pseudo)
            scf_input.add_abiobjects(ksampling, smearing, spin_mode)
            scf_input.set_vars(extra_abivars)

            self.register_scf_task(scf_input)

        if connect:
            logger.info("Connecting SCF tasks using previous WFK file")
            middle = len(self.volumes) // 2
            filetype = "WFK"
            for i, task in enumerate(self[:middle]):
                task.add_deps({self[i + 1]: filetype})

            for i, task in enumerate(self[middle+1:]):
                task.add_deps({self[middle + i]: filetype})