Exemple #1
0
    def from_input(cls, inp):
        """ Return atom object respecting the input

        Parameters
        ----------
        inp : list or str
           create `AtomInput` from the content of `inp`
        """
        def _get_content(f):
            if f.is_file():
                return open(f, 'r').readlines()
            return None

        if isinstance(inp, (tuple, list)):
            # it is already in correct format
            pass
        elif isinstance(inp, (str, Path)):
            # convert to path
            inp = Path(inp)

            # Check if it is a path or an input
            content = _get_content(inp)
            if content is None:
                content = _get_content(inp / "INP")
            if content is None:
                raise ValueError(
                    f"Could not find any input file in {str(inp)} or {str(inp / 'INP')}"
                )
            inp = content

        else:
            raise ValueError(f"Unknown input format inp={inp}?")

        # Now read lines
        defines = []
        opts = PropertyDict()

        def bypass_comments(inp):
            if inp[0].startswith("#"):
                inp.pop(0)
                bypass_comments(inp)

        def bypass(inp, defines):
            bypass_comments(inp)
            if inp[0].startswith("%define"):
                line = inp.pop(0)
                defines.append(line.split()[1].strip())
                bypass(inp, defines)

        bypass(inp, defines)

        # Now prepare reading
        # First line has to contain the *type* of calculation
        # pg|pe|ae|pt <comment>
        line = inp.pop(0).strip()
        if line.startswith("pg"):
            opts.cc = False
        elif line.startswith("pe"):
            opts.cc = True

        # <flavor> logr?
        line = inp.pop(0).strip().split()
        opts.flavor = line[0]
        if len(line) >= 2:
            opts.logr = float(line[1]) / _Ang2Bohr

        # <element> <xc>' rs'?
        line = inp.pop(0)
        symbol = line.split()[0]
        # now get xc equation
        if len(line) >= 11:
            opts.equation = line[10:10]
        opts.xc = line[:10].split()[1]
        line = line.split()
        if len(line) >= 3:
            opts.libxc = int(line[2])

        # currently not used line
        inp.pop(0)

        # core, valence
        core, valence = inp.pop(0).split()
        opts.core = int(core)
        valence = int(valence)

        orbs = []
        for _ in range(valence):
            n, l, *occ = inp.pop(0).split()
            orb = PropertyDict()
            orb.n = int(n)
            orb.l = int(l)
            # currently we don't distinguish between up/down
            orb.q0 = sum(map(float, occ))
            orbs.append(orb)

        # now we read the line with rc's and core-correction
        rcs = inp.pop(0).split()
        if len(rcs) >= 6:
            # core-correction
            opts.rcore = float(rcs[5]) / _Ang2Bohr

        for orb in orbs:
            orb.R = float(rcs[orb.l]) / _Ang2Bohr

        # Now create orbitals
        orbs = [si.AtomicOrbital(**orb, m=0, zeta=1) for orb in orbs]
        # now re-arrange ensuring we have correct order of l shells
        orbs = sorted(orbs, key=lambda orb: orb.l)
        atom = si.Atom(symbol, orbs)
        return cls(atom, defines, **opts)
Exemple #2
0
    def ArgumentParser(self, p=None, *args, **kwargs):
        """ Returns the arguments that is available for this Sile """
        #limit_args = kwargs.get('limit_arguments', True)
        short = kwargs.get('short', False)

        def opts(*args):
            if short:
                return args
            return [args[0]]

        # We limit the import to occur here
        import argparse

        Bohr2Ang = unit_convert('Bohr', 'Ang')
        Ry2eV = unit_convert('Bohr', 'Ang')

        # The first thing we do is adding the geometry to the NameSpace of the
        # parser.
        # This will enable custom actions to interact with the geometry in a
        # straight forward manner.
        # convert netcdf file to a dictionary
        ion_nc = PropertyDict()
        ion_nc.n = self._variable('orbnl_n')[:]
        ion_nc.l = self._variable('orbnl_l')[:]
        ion_nc.zeta = self._variable('orbnl_z')[:]
        ion_nc.pol = self._variable('orbnl_ispol')[:]
        ion_nc.orbital = self._variable('orb')[:]

        # this gets converted later
        delta = self._variable('delta')[:]
        r = aranged(ion_nc.orbital.shape[1]).reshape(1, -1) * delta.reshape(-1, 1)
        ion_nc.orbital *= r ** ion_nc.l.reshape(-1, 1) / Bohr2Ang * (3./2.)
        ion_nc.r = r * Bohr2Ang
        ion_nc.kb = PropertyDict()
        ion_nc.kb.n = self._variable('pjnl_n')[:]
        ion_nc.kb.l = self._variable('pjnl_l')[:]
        ion_nc.kb.e = self._variable('pjnl_ekb')[:] * Ry2eV
        ion_nc.kb.proj = self._variable('proj')[:]
        delta = self._variable('kbdelta')[:]
        r = aranged(ion_nc.kb.proj.shape[1]).reshape(1, -1) * delta.reshape(-1, 1)
        ion_nc.kb.proj *= r ** ion_nc.kb.l.reshape(-1, 1) / Bohr2Ang * (3./2.)
        ion_nc.kb.r = r * Bohr2Ang

        vna = self._variable('vna')
        r = aranged(vna[:].size) * vna.Vna_delta
        ion_nc.vna = PropertyDict()
        ion_nc.vna.v = vna[:] * Ry2eV * r / Bohr2Ang ** 3
        ion_nc.vna.r = r * Bohr2Ang

        # this is charge (not 1/sqrt(charge))
        chlocal = self._variable('chlocal')
        r = aranged(chlocal[:].size) * chlocal.Chlocal_delta
        ion_nc.chlocal = PropertyDict()
        ion_nc.chlocal.v = chlocal[:] * r / Bohr2Ang ** 3
        ion_nc.chlocal.r = r * Bohr2Ang

        vlocal = self._variable('reduced_vlocal')
        r = aranged(vlocal[:].size) * vlocal.Reduced_vlocal_delta
        ion_nc.vlocal = PropertyDict()
        ion_nc.vlocal.v = vlocal[:] * r / Bohr2Ang ** 3
        ion_nc.vlocal.r = r * Bohr2Ang

        if "core" in self.variables:
            # this is charge (not 1/sqrt(charge))
            core = self._variable('core')
            r = aranged(core[:].size) * core.Core_delta
            ion_nc.core = PropertyDict()
            ion_nc.core.v = core[:] * r / Bohr2Ang ** 3
            ion_nc.core.r = r * Bohr2Ang

        d = {
            "_data": ion_nc,
            "_kb_proj": False,
            "_l": True,
            "_n": True,
        }
        namespace = default_namespace(**d)

        # l-quantum number
        class lRange(argparse.Action):

            def __call__(self, parser, ns, value, option_string=None):
                value = (value
                         .replace("s", 0)
                         .replace("p", 1)
                         .replace("d", 2)
                         .replace("f", 3)
                         .replace("g", 4)
                )
                ns._l = strmap(int, value)[0]
        p.add_argument('-l',
                       action=lRange,
                       help='Denote the sub-section of l-shells that are plotted: "s,f"')

        # n quantum number
        class nRange(argparse.Action):

            def __call__(self, parser, ns, value, option_string=None):
                ns._n = strmap(int, value)[0]
        p.add_argument('-n',
                       action=nRange,
                       help='Denote the sub-section of n quantum numbers that are plotted: "2-4,6"')

        class Plot(argparse.Action):

            def __call__(self, parser, ns, value, option_string=None):
                import matplotlib.pyplot as plt

                # Retrieve values
                data = ns._data

                # We have these plots:
                #  - orbitals
                #  - projectors
                #  - chlocal
                #  - vna
                #  - vlocal
                #  - core (optional)

                # We'll plot them like this:
                #  orbitals | projectors
                #  vna + vlocal | chlocal + core
                #
                # Determine different n, l
                fig, axs = plt.subplots(2, 2)

                # Now plot different orbitals
                for n, l, zeta, pol, r, orb in zip(data.n, data.l, data.zeta,
                                                   data.pol, data.r, data.orbital):
                    if pol == 1:
                        pol = 'P'
                    else:
                        pol = ''
                    axs[0][0].plot(r, orb, label=f"n{n}l{l}Z{zeta}{pol}")
                axs[0][0].set_title("Orbitals")
                axs[0][0].set_xlabel("Distance [Ang]")
                axs[0][0].set_ylabel("Value [a.u.]")
                axs[0][0].legend()

                # plot projectors
                for n, l, e, r, proj in zip(
                        data.kb.n, data.kb.l, data.kb.e, data.kb.r, data.kb.proj):
                    axs[0][1].plot(r, proj, label=f"n{n}l{l} e={e:.5f}")
                axs[0][1].set_title("KB projectors")
                axs[0][1].set_xlabel("Distance [Ang]")
                axs[0][1].set_ylabel("Value [a.u.]")
                axs[0][1].legend()

                axs[1][0].plot(data.vna.r, data.vna.v, label='Vna')
                axs[1][0].plot(data.vlocal.r, data.vlocal.v, label='Vlocal')
                axs[1][0].set_title("Potentials")
                axs[1][0].set_xlabel("Distance [Ang]")
                axs[1][0].set_ylabel("Potential [eV]")
                axs[1][0].legend()

                axs[1][1].plot(data.chlocal.r, data.chlocal.v, label='Chlocal')
                if "core" in data:
                    axs[1][1].plot(data.core.r, data.core.v, label='core')
                axs[1][1].set_title("Charge")
                axs[1][1].set_xlabel("Distance [Ang]")
                axs[1][1].set_ylabel("Charge [Ang^3]")
                axs[1][1].legend()

                if value is None:
                    plt.show()
                else:
                    plt.savefig(value)
        p.add_argument(*opts('--plot', '-p'), action=Plot, nargs='?', metavar='FILE',
                       help='Plot the content basis set file, possibly saving plot to a file.')

        return p, namespace