예제 #1
0
def itest_phonon_restart(fwp):
    """Test the restart of phonon calculations with the scheduler."""
    # Crystalline AlAs: computation of the second derivative of the total energy
    structure = abidata.structure_from_ucell("AlAs")

    # List of q-points for the phonon calculation (4,4,4) mesh.
    qpoints = np.reshape([
             0.00000000E+00,  0.00000000E+00,  0.00000000E+00,
             2.50000000E-01,  0.00000000E+00,  0.00000000E+00,
             #5.00000000E-01,  0.00000000E+00,  0.00000000E+00,  # XXX Uncomment this line to test restart from 1DEN
                                                                 # Too long --> disabled
            ], (-1, 3))

    # Global variables used both for the GS and the DFPT run.
    global_vars = dict(nband=4,
                       ecut=3.0,
                       ngkpt=[4, 4, 4],
                       shiftk=[0, 0, 0],
                       tolvrs=1.0e-5,
                    )

    multi = abilab.MultiDataset(structure=structure, pseudos=abidata.pseudos("13al.981214.fhi", "33as.pspnc"), 
                                ndtset=1+len(qpoints))

    multi.set_vars(global_vars)

    for i, qpt in enumerate(qpoints):
        # Response-function calculation for phonons.
        multi[i+1].set_vars(
            rfphon=1,        # Will consider phonon-type perturbation.
            nqpt=1,          # One wavevector is to be considered.
            qpt=qpt,         # q-wavevector.
            kptopt=3,
            nstep=5,         # This is to trigger the phonon restart.
        )
        #rfatpol   1 1   # Only the first atom is displaced
        #rfdir   1 0 0   # Along the first reduced coordinate axis
        #kptopt   2      # Automatic generation of k points, taking

                                                           # i == 0 --> restart from WFK
        if i == 1: multi[i+1].set_vars(prtwf=-1, nstep=5)  # Restart with WFK and smart- io.
        if i == 2: multi[i+1].set_vars(prtwf=0, nstep=8)   # Restart from 1DEN. Too long --> disabled.

    all_inps = multi.split_datasets()
    scf_input, ph_inputs = all_inps[0], all_inps[1:]

    flow = abilab.phonon_flow(fwp.workdir, scf_input, ph_inputs, manager=fwp.manager)
    flow.set_garbage_collector()

    for task in flow.iflat_tasks():
        task.manager.qadapter.max_num_launches = 20

    assert flow.make_scheduler().start() == 0

    flow.check_status(show=True, verbose=1)
    assert all(work.finalized for work in flow)
    assert flow.all_ok

    assert sum(task.num_restarts for task in flow.iflat_tasks()) > 0
예제 #2
0
def build_flow(options):
    # Set working directory (default is the name of the script with '.py' removed and "run_" replaced by "flow_")
    if not options.workdir:
        options.workdir = os.path.basename(sys.argv[0]).replace(".py", "").replace("run_", "flow_")

    structure = abidata.structure_from_ucell("GaAs")
    pseudos = abidata.pseudos("Ga-low_r.psp8", "As_r.psp8")
    num_electrons = structure.num_valence_electrons(pseudos)
    #print("num_electrons:", num_electrons)

    # Usa same shifts in all tasks.
    ngkpt = [4, 4, 4]
    shiftk = [
        [0.5, 0.5, 0.5],
        [0.5, 0.0, 0.0],
        [0.0, 0.5, 0.0],
        [0.0, 0.0, 0.5],
    ]

    # NSCF run on k-path with large number of bands
    kptbounds = [
        [0.5, 0.0, 0.0],  # L point
        [0.0, 0.0, 0.0],  # Gamma point
        [0.0, 0.5, 0.5],  # X point
    ]

    # Initialize the flow.
    flow = flowtk.Flow(options.workdir, manager=options.manager)

    for nspinor in [1, 2]:
        # Multi will contain two datasets (GS + NSCF) for the given nspinor.
        multi = abilab.MultiDataset(structure=structure, pseudos=pseudos, ndtset=2)

        # Global variables.
        multi.set_vars(
            ecut=20,
            nspinor=nspinor,
            nspden=1 if nspinor == 1 else 4,
            so_psp="*0" if nspinor == 1 else "*1",   # Important!
            #paral_kgb=1,
        )

        nband_occ = num_electrons // 2 if nspinor == 1 else num_electrons
        #print(nband_occ)

        # Dataset 1 (GS run)
        multi[0].set_vars(tolvrs=1e-8, nband=nband_occ + 4)
        multi[0].set_kmesh(ngkpt=ngkpt, shiftk=shiftk, kptopt=1 if nspinor == 1 else 4)

        multi[1].set_vars(iscf=-2, nband=nband_occ + 4, tolwfr=1.e-12)
        multi[1].set_kpath(ndivsm=10, kptbounds=kptbounds)

        # Get the SCF and the NSCF input.
        scf_input, nscf_input = multi.split_datasets()

        flow.register_work(flowtk.BandStructureWork(scf_input, nscf_input))

    return flow
예제 #3
0
def make_inputs(paw=False):
    pseudos = abidata.pseudos("14si.pspnc", "8o.pspnc") if not paw else \
              abidata.pseudos("Si.GGA_PBE-JTH-paw.xml", "o.paw")

    structure = abidata.structure_from_ucell("SiO2-alpha")

    multi = abilab.MultiDataset(structure, pseudos=pseudos, ndtset=4)

    ecut = 24
    multi.set_vars(
        ecut=ecut,
        pawecutdg=ecut * 2 if paw else None,
        paral_kgb=0,
        istwfk="*1",
        timopt=-1,
    )

    multi.set_kmesh(ngkpt=[4, 4, 3], shiftk=[0.0, 0.0, 0.0])

    gs, nscf, scr, sigma = multi.split_datasets()

    # Dataset 1 (GS run)
    gs.set_vars(
        tolvrs=1e-6,
        nband=28,
    )

    # Dataset 2 (NSCF run)
    nscf.set_vars(
        iscf=-2,
        tolwfr=1e-4,
        nband=600,
        nbdbuf=200,
    )

    # Dataset3: Calculation of the screening.
    scr.set_vars(
        optdriver=3,
        gwpara=2,
        nband=25,
        ecutwfn=ecut,
        symchi=1,
        inclvkb=0,
        ecuteps=6.0,
    )

    # Dataset4: Calculation of the Self-Energy matrix elements (GW corrections)
    sigma.set_vars(
        optdriver=4,
        gwpara=2,
        ecutwfn=ecut,
        ecuteps=6.0,
        ecutsigx=ecut,
        symsigma=1,
        gw_qprange=1,
    )

    return gs, nscf, scr, sigma
예제 #4
0
def make_inputs(paw=False):
    # Crystalline silicon
    # Calculation of the GW correction to the direct band gap in Gamma
    # Dataset 1: ground state calculation
    # Dataset 2: BSE with haydock method and model dielectric function.
    structure = abilab.Structure.from_file(abidata.cif_file("si.cif"))
    pseudos = abidata.pseudos("14si.pspnc") if not paw else abidata.pseudos(
        "Si.GGA_PBE-JTH-paw.xml")

    multi = abilab.MultiDataset(structure, pseudos=pseudos, ndtset=2)

    ecut = 8
    multi.set_vars(
        ecut=ecut,
        pawecutdg=ecut * 4 if paw else None,
        nsppol=1,
        timopt=-1,
        istwfk="*1",
        paral_kgb=0,
    )

    # This grid is the most economical, but does not contain the Gamma point.
    multi.set_kmesh(
        ngkpt=[8, 8, 8],
        shiftk=[0.0, 0.0, 0.0],
    )

    gs, bse = multi.split_datasets()

    gs.set_vars(
        tolvrs=1e-6,
        nband=8,
    )

    # Dataset 6 BSE equation with Model dielectric function and Haydock (only resonant + W + v)
    # Note that SCR file is not needed here
    bse.set_vars(
        optdriver=99,
        ecutwfn=ecut,
        ecuteps=4.0,
        inclvkb=2,
        bs_algorithm=2,  # Haydock
        bs_haydock_niter=60,  # No. of iterations for Haydock
        bs_exchange_term=1,
        bs_coulomb_term=21,  # Use model W and full W_GG.
        mdf_epsinf=12.0,
        bs_calctype=1,  # Use KS energies and orbitals to construct L0
        mbpt_sciss="0.8 eV",
        bs_coupling=0,
        bs_loband=2,
        nband=8,
        bs_freq_mesh="0 10 0.1 eV",
        bs_hayd_term=0,  # No terminator
        #gwmem=01               # Compute the model-dielectric function on-the-fly.
    )

    return gs, bse
예제 #5
0
def make_scf_nscf_dos_inputs(structure, pseudos, luj_params, paral_kgb=1):
    # Input file taken from tldau_2.in
    multi = abilab.MultiDataset(structure, pseudos=pseudos, ndtset=3)

    # Global variables
    global_vars = dict(
        # 
        ecut=12,
        pawecutdg=30,
        nband=40,
        occopt=7,
        tsmear=0.015,
        nstep=50,
        paral_kgb=paral_kgb,
        #
        # Spin
        nsppol=1,
        nspden=2,
        nspinor=1,
        spinat=[0,  0,  1,
                0,  0, -1,
                0,  0,  0,
                0,  0,  0],
        # Kpoint Grid
        # The k point grid is not symmetric, but the calculations being 
        # for the ground-state, this is not a problem.
    )

    multi.set_vars(global_vars)
    multi.set_vars(luj_params.to_abivars())

    # GS run.
    multi[0].set_vars(
        iscf=17,
        toldfe=1.0e-8,
        ngkpt=[2, 2, 2],
        chksymbreak=0, 
    )

    # Band structure run.
    multi[1].set_kpath(ndivsm=6)
    multi[1].set_vars(tolwfr=1e-10)

    # Dos calculation.
    multi[2].set_vars(
        iscf=-3,   # NSCF calculation
        ngkpt=structure.calc_ngkpt(nksmall=8),      
        shiftk=[0.0, 0.0, 0.0],
        nshiftk=1,
        tolwfr=1.e-8,
        #pawprtdos=1,
    )

    # Generate two input files for the GS and the NSCF run 
    scf_input, nscf_input, dos_input = multi.split_datasets()

    return scf_input, nscf_input, dos_input
예제 #6
0
def make_inputs(tvars):
    """Constrcut the input files."""
    structure = abidata.structure_from_ucell("GaAs")

    multi = abilab.MultiDataset(structure, pseudos=abidata.pseudos("31ga.pspnc", "33as.pspnc"), ndtset=5)

    # Global variables
    kmesh = dict(ngkpt=[4, 4, 4],
                 nshiftk=4,
                 shiftk=[[0.5, 0.5, 0.5],
                         [0.5, 0.0, 0.0],
                         [0.0, 0.5, 0.0],
                         [0.0, 0.0, 0.5]])

    global_vars = dict(ecut=2, paral_kgb=tvars.paral_kgb)
    global_vars.update(kmesh)

    multi.set_vars(global_vars)

    # Dataset 1 (GS run)
    multi[0].set_vars(
        tolvrs=1e-6,
        nband=4)

    # NSCF run with large number of bands, and points in the the full BZ
    multi[1].set_vars(
        iscf=-2,
        nband=20,
        nstep=25,
        kptopt=1,
        tolwfr=1.e-8)
        #kptopt=3)

    # Fourth dataset: ddk response function along axis 1
    # Fifth dataset: ddk response function along axis 2
    # Sixth dataset: ddk response function along axis 3
    for idir in range(3):
        rfdir = 3 * [0]
        rfdir[idir] = 1

        multi[2+idir].set_vars(
            iscf=-3,
            nband=20,
            nstep=1,
            nline=0,
            prtwf=3,
            kptopt=3,
            nqpt=1,
            qpt=[0.0, 0.0, 0.0],
            rfdir=rfdir,
            rfelfd=2,
            tolwfr=1.e-9,
        )

    # scf_inp, nscf_inp, ddk1, ddk2, ddk3
    return multi.split_datasets()
예제 #7
0
def make_inputs(paral_kgb=1):
    """
    Returns a tuple of 4 input files for SCF, NSCF, SCR, SIGMA calculations.
    These files are then used as templates for the convergence study
    wrt ecuteps and the number of bands in W.
    """
    multi = abilab.MultiDataset(abidata.structure_from_ucell("SiC"),
                                pseudos=abidata.pseudos(
                                    "14si.pspnc", "6c.pspnc"),
                                ndtset=4)

    ecut = 12
    global_vars = dict(ecut=ecut, istwfk="*1", paral_kgb=paral_kgb, gwpara=2)

    ecuteps = 4
    ngkpt = [4, 4, 4]
    shiftk = [0, 0, 0]

    multi.set_vars(global_vars)
    multi.set_kmesh(ngkpt=ngkpt, shiftk=shiftk)

    # SCF
    multi[0].set_vars(
        nband=10,
        tolvrs=1.e-8,
    )

    # NSCF
    multi[1].set_vars(nband=25, tolwfr=1.e-8, iscf=-2)

    # SCR
    multi[2].set_vars(
        optdriver=3,
        ecutwfn=ecut,
        nband=20,
        symchi=1,
        inclvkb=0,
        ecuteps=ecuteps,
    )

    # SIGMA
    multi[3].set_vars(
        optdriver=4,
        nband=20,
        ecutwfn=ecut,
        ecutsigx=ecut,
        #ecutsigx=(4*ecut), ! This is problematic
        symsigma=1,
        ecuteps=ecuteps,
    )

    multi[3].set_kptgw(kptgw=[[0, 0, 0], [0.5, 0, 0]], bdgw=[1, 8])

    return multi.split_datasets()
예제 #8
0
def make_ion_ioncell_inputs(paral_kgb=0):

    structure = abilab.Structure.from_file(abidata.cif_file("si.cif"))

    # Perturb the structure (random perturbation of 0.1 Angstrom)
    # then compress the volume to trigger dilatmx.
    structure.perturb(distance=0.1)
    structure.scale_lattice(structure.volume * 0.6)

    global_vars = dict(
        ecut=4,
        ngkpt=[4, 4, 4],
        shiftk=[0, 0, 0],
        nshiftk=1,
        chksymbreak=0,
        paral_kgb=paral_kgb,
        iomode=3,
        #prtwf=0,
    )

    multi = abilab.MultiDataset(structure,
                                pseudos=abidata.pseudos("14si.pspnc"),
                                ndtset=2)

    # Global variables
    multi.set_vars(global_vars)

    # Dataset 1 (Atom Relaxation)
    multi[0].set_vars(
        optcell=0,
        ionmov=2,
        tolrff=0.02,
        tolmxf=5.0e-5,
        #ntime=50,
        ntime=3,  #To test the restart
        #dilatmx=1.1, # FIXME: abinit crashes if I don't use this
    )

    # Dataset 2 (Atom + Cell Relaxation)
    multi[1].set_vars(
        optcell=1,
        ionmov=2,
        ecutsm=0.5,
        dilatmx=1.02,
        tolrff=0.02,
        tolmxf=5.0e-5,
        strfact=100,
        #ntime=50,
        ntime=3,  # To test the restart
    )

    ion_inp, ioncell_inp = multi.split_datasets()
    return ion_inp, ioncell_inp
예제 #9
0
def raman_workflow(structure, pseudos, scf_t, ksamp):
    # Generate 3 different input files for computing optical properties with BSE.

    inp = abilab.MultiDataset(structure, pseudos=pseudos, ndtset=2)

    inp.set_vars(**global_vars)

    vars_ksamp = ksamp.to_abivars()
    vars_ksamp.pop("#comment", None)

    inp.set_vars(**vars_ksamp)

    # NSCF run
    inp[0].set_vars(
        iscf=-2,
        nband=10 * len(structure),
        nbdbuf=2 * len(structure),
        nstep=500,
        tolwfr=1.e-22,
    )

    inp[1].set_vars(
        gwmem=10,
        gwpara=2,
        optdriver=99,
        nband=5 * len(structure),  # 10 bands for 2 atoms
        bs_loband=1 * len(structure),  # start at 2 for 2 atoms
        bs_algorithm=2,  # Haydock
        bs_calctype=1,  # KS wavefunctions
        bs_coulomb_term=21,  # Use model dielectric function
        mdf_epsinf=12.0,
        bs_exchange_term=1,  # Exchange term included
        bs_freq_mesh="0 10 0.01 eV",
        bs_hayd_term=0,
        bs_coupling=0,
        bs_haydock_tol="-0.01 0",
        bs_haydock_niter=1000,
        inclvkb=2,
        ecuteps=4,
        soenergy="0.8 eV",
        ecutwfn=global_vars["ecut"],
    )

    nscf_inp, bse_inp = inp.split_datasets()

    workflow = abilab.Work()
    nscf_t = workflow.register(nscf_inp,
                               deps={scf_t: "DEN"},
                               task_class=abilab.NscfTask)
    bse_t = workflow.register_bse_task(bse_inp, deps={nscf_t: "WFK"})

    return workflow
예제 #10
0
def scf_ph_inputs(tvars=None):
    """
    This function constructs the input files for the phonon calculation:
    GS input + the input files for the phonon calculation.
    """
    # Crystalline AlAs: computation of the second derivative of the total energy
    structure = abidata.structure_from_ucell("AlAs")

    # List of q-points for the phonon calculation (4,4,4) mesh.
    qpoints = [
             0.00000000E+00,  0.00000000E+00,  0.00000000E+00,
             2.50000000E-01,  0.00000000E+00,  0.00000000E+00,
             5.00000000E-01,  0.00000000E+00,  0.00000000E+00,
             2.50000000E-01,  2.50000000E-01,  0.00000000E+00,
             5.00000000E-01,  2.50000000E-01,  0.00000000E+00,
            -2.50000000E-01,  2.50000000E-01,  0.00000000E+00,
             5.00000000E-01,  5.00000000E-01,  0.00000000E+00,
            -2.50000000E-01,  5.00000000E-01,  2.50000000E-01,
            ]

    qpoints = np.reshape(qpoints, (-1,3))

    # Global variables used both for the GS and the DFPT run.
    global_vars = dict(nband=4,
                       ecut=3.0,
                       ngkpt=[4, 4, 4],
                       shiftk=[0, 0, 0],
                       tolvrs=1.0e-6,
                       paral_kgb=0 if tvars is None else tvars.paral_kgb,
                    )

    multi = abilab.MultiDataset(structure=structure, pseudos=abidata.pseudos("13al.981214.fhi", "33as.pspnc"), 
                              ndtset=1+len(qpoints))

    multi.set_vars(global_vars)

    for i, qpt in enumerate(qpoints):
        # Response-function calculation for phonons.
        multi[i+1].set_vars(
            nstep=20,
            rfphon=1,        # Will consider phonon-type perturbation
            nqpt=1,          # One wavevector is to be considered
            qpt=qpt,         # This wavevector is q=0 (Gamma)
            kptopt=3,
            )

            #rfatpol   1 1   # Only the first atom is displaced
            #rfdir   1 0 0   # Along the first reduced coordinate axis
            #kptopt   2      # Automatic generation of k points, taking

    # Split input into gs_inp and ph_inputs
    return multi.split_datasets()
예제 #11
0
def itest_metagga_ebands_flow(fwp, tvars):
    """
    Test band structure calculation with meta-GGA
    """
    if not fwp.abinit_build.has_libxc:
        pytest.skip(
            "itest_metagga_ebands_flow requires libxc support in Abinit.")

    from abipy.data.hgh_pseudos import HGH_TABLE
    multi = abilab.MultiDataset(structure=abidata.cif_file("si.cif"),
                                pseudos=HGH_TABLE,
                                ndtset=2)

    # Global variables
    shiftk = [
        float(s)
        for s in "0.5 0.5 0.5 0.5 0.0 0.0 0.0 0.5 0.0 0.0 0.0 0.5".split()
    ]
    multi.set_vars(ecut=20,
                   diemac=12,
                   iomode=3,
                   ixc=-208012,
                   prtkden=1,
                   usekden=1)

    # Dataset 1
    multi[0].set_vars(tolvrs=1e-7)
    multi[0].set_kmesh(ngkpt=[2, 2, 2], shiftk=shiftk)

    # Dataset 2
    multi[1].set_vars(tolwfr=1e-8)
    multi[1].set_kpath(ndivsm=2)

    scf_input, nscf_input = multi.split_datasets()
    work = flowtk.works.BandStructureWork(scf_input=scf_input,
                                          nscf_input=nscf_input)

    flow = abilab.Flow(workdir=fwp.workdir, manager=fwp.manager)
    flow.register_work(work)
    flow.build_and_pickle_dump(abivalidate=True)

    fwp.scheduler.add_flow(flow)
    assert fwp.scheduler.start() == 0
    assert not fwp.scheduler.exceptions
    #assert fwp.scheduler.nlaunch == 3

    flow.show_status()
    if not flow.all_ok:
        flow.debug()
        raise RuntimeError()
    assert all(work.finalized for work in flow)
예제 #12
0
def make_ngkpt_flow():
    ngkpt_list = [(2, 2, 2), (4, 4, 4), (6, 6, 6), (8, 8, 8)]

    multi = abilab.MultiDataset(structure=abidata.cif_file("si.cif"),
                                pseudos=abidata.pseudos("14si.pspnc"),
                                ndtset=len(ngkpt_list))
    # Global variables
    multi.set_vars(ecut=10, tolvrs=1e-9)

    for i, ngkpt in enumerate(ngkpt_list):
        multi[i].set_kmesh(ngkpt=ngkpt, shiftk=[0, 0, 0])

    return NgkptFlow.from_inputs(workdir="flow_base3_ngkpt",
                                 inputs=multi.split_datasets())
예제 #13
0
def build_flow(options):
    # Working directory (default is the name of the script with '.py' removed and "run_" replaced by "flow_")
    workdir = options.workdir
    if not options.workdir:
        workdir = os.path.basename(__file__).replace(".py", "").replace(
            "run_", "flow_")

    flow = flowtk.Flow(workdir, manager=options.manager, remove=options.remove)

    pseudos = data.pseudos("14si.pspnc", "6c.pspnc")
    structure = data.structure_from_ucell("SiC")

    global_vars = dict(
        chksymbreak=0,
        ecut=20,
        paral_kgb=0,
        iomode=3,
    )

    ngkpt = [4, 4, 4]
    shiftk = [[0.5, 0.5, 0.5], [0.5, 0.0, 0.0], [0.0, 0.5, 0.0],
              [0.0, 0.0, 0.5]]

    multi = abilab.MultiDataset(structure, pseudos=pseudos, ndtset=2)
    multi.set_vars(global_vars)

    relax_inp, nscf_inp = multi.split_datasets()

    relax_inp.set_kmesh(ngkpt=ngkpt, shiftk=shiftk)
    relax_inp.set_vars(
        toldff=1e-6,
        tolmxf=1e-5,
        strfact=100,
        ecutsm=0.5,
        dilatmx=1.15,
        ntime=100,
        ionmov=2,
        optcell=1,
    )

    nscf_inp.set_kpath(ndivsm=20)
    nscf_inp.tolwfr = 1e-22

    # Initialize the work.
    relax_task = flow.register_task(relax_inp, task_class=flowtk.RelaxTask)

    #work = RelaxWork(self, ion_input, ioncell_input, workdir=None, manager=None):
    #nscf_task = flow.register_task(nscf_inp, deps={relax_task: "DEN"}, task_class=flowtk.NscfTask)

    return flow
예제 #14
0
def build_flow(options):
    """
    Build and return a flow performing structural relaxations with different k-point samplings.
    """
    # Set working directory (default is the name of the script with '.py' removed and "run_" replaced by "flow_")
    if not options.workdir:
        if os.getenv("READTHEDOCS", False):
            __file__ = os.path.join(os.getcwd(), "run_relax_vs_kpts.py")
        options.workdir = os.path.basename(__file__).replace(
            ".py", "").replace("run_", "flow_")

    # List of k-meshes.
    ngkpt_list = [
        [3, 3, 2],
        [6, 6, 4],
        [8, 8, 6],
    ]

    structure = abilab.Structure.from_file(abidata.cif_file("gan2.cif"))
    pseudos = abidata.pseudos("Ga.oncvpsp", "N.oncvpsp")

    # Build multidataset.
    multi = abilab.MultiDataset(structure=structure,
                                pseudos=pseudos,
                                ndtset=len(ngkpt_list))

    # Set global variables for structural relaxation. Note dilatmx and ecutsm
    # Ecut should depend on pseudos.
    multi.set_vars(
        ecut=15,  # Too low
        optcell=2,
        ionmov=3,
        tolrff=5.0e-2,
        tolmxf=5.0e-5,
        ntime=50,
        dilatmx=1.05,  # Important!
        ecutsm=0.5,  # Important!
    )

    # Here we set the k-meshes (Gamma-centered for simplicity)
    for i, ngkpt in enumerate(ngkpt_list):
        multi[i].set_kmesh(ngkpt=ngkpt, shiftk=[0, 0, 0])

    # As the calculations are independent, we can use Flow.from_inputs
    # and call split_datasets to create len(ngkpt_list) inputs.
    # Note that it's a good idea to specify the task_class so that AbiPy knows how to restart the calculation.
    return flowtk.Flow.from_inputs(options.workdir,
                                   inputs=multi.split_datasets(),
                                   task_class=flowtk.RelaxTask)
예제 #15
0
def make_ngkpt_flow(ngkpt_list=((2, 2, 2), (4, 4, 4), (6, 6, 6), (8, 8, 8)),
                    structure_file=None,
                    metal=False):
    """
    A `factory function` (a function that returns an instance of the class defined above. If no specific system is
    specified, structure_file=None, an flow for silicon in constructed and returned.
    """
    # Defining the structure and adding the appropriate pseudo potentials
    if structure_file is None:
        multi = abilab.MultiDataset(structure=abidata.cif_file("si.cif"),
                                    pseudos=abidata.pseudos("14si.pspnc"),
                                    ndtset=len(ngkpt_list))
        workdir = "flow_lesson_Si_kpoint_convergence"
    else:
        structure = abilab.Structure.from_file(structure_file)
        pseudos = get_pseudos(structure)
        multi = abilab.MultiDataset(structure,
                                    pseudos=pseudos,
                                    ndtset=len(ngkpt_list))
        workdir = "flow_lesson_" + structure.composition.reduced_formula + "_kpoint_convergence"

    # Add mnemonics to input file.
    multi.set_mnemonics(True)

    # Global variables
    multi.set_vars(ecut=10, tolvrs=1e-9)

    if metal:
        multi.set_vars(occopt=7, tsmear=0.04)

    # Specific variables for the different calculations
    for i, ngkpt in enumerate(ngkpt_list):
        multi[i].set_kmesh(ngkpt=ngkpt, shiftk=[0, 0, 0])

    return abilab.Flow.from_inputs(workdir=workdir,
                                   inputs=multi.split_datasets())
예제 #16
0
def make_ecut_flow(structure_file=None, ecut_list=(10, 12, 14, 16, 18)):
    """
    Build and return a `Flow` to perform a convergence study wrt to ecut.

    Args:
        structure_file: (optional) file containing the crystalline structure.  
            If None, crystalline silicon structure.
        ecut_list: List of cutoff energies to be investigated.
    """
    # Define the structure and add the necessary pseudos:
    if structure_file is None:
        multi = abilab.MultiDataset(structure=abidata.cif_file("si.cif"),
                                    pseudos=abidata.pseudos("14si.pspnc"),
                                    ndtset=len(ecut_list))
        workdir = "flow_Si_ecut_convergence"
    else:
        structure = abilab.Structure.from_file(structure_file)
        pseudos = abilab.PseudoTable()  ## todo fix this
        multi = abilab.MultiDataset(structure,
                                    pseudos=pseudos,
                                    ndtset=len(ecut_list))
        workdir = "flow_" + structure.composition.reduced_formula + "_ecut_convergence"

    # Add mnemonics to the input files.
    multi.set_mnemonics(True)

    # Global variables
    multi.set_vars(tolvrs=1e-9)
    multi.set_kmesh(ngkpt=[4, 4, 4], shiftk=[0, 0, 0])

    # Here we set the value of ecut used by the i-th task.
    for i, ecut in enumerate(ecut_list):
        multi[i].set_vars(ecut=ecut)

    return abilab.Flow.from_inputs(workdir=workdir,
                                   inputs=multi.split_datasets())
예제 #17
0
def make_ion_ioncell_inputs(tvars, dilatmx, scalevol=1, ntime=50):
    structure = abilab.Structure.from_file(abidata.cif_file("si.cif"))

    # Perturb the structure (random perturbation of 0.1 Angstrom)
    #structure.perturb(distance=0.01)

    # Compress the lattice so that ABINIT complains about dilatmx
    structure.scale_lattice(structure.volume * scalevol)

    global_vars = dict(
        ecut=6,
        ecutsm=0.5,
        ngkpt=[4, 4, 4],
        shiftk=[0, 0, 0],
        nshiftk=1,
        chksymbreak=0,
        paral_kgb=tvars.paral_kgb,
    )

    multi = abilab.MultiDataset(structure,
                                pseudos=abidata.pseudos("14si.pspnc"),
                                ndtset=2)

    # Global variables
    multi.set_vars(global_vars)

    # Dataset 1 (Atom Relaxation)
    multi[0].set_vars(
        optcell=0,
        ionmov=2,
        tolrff=0.02,
        tolmxf=5.0e-5,
        ntime=ntime,
    )

    # Dataset 2 (Atom + Cell Relaxation)
    multi[1].set_vars(
        optcell=1,
        ionmov=2,
        dilatmx=dilatmx,
        tolrff=0.02,
        tolmxf=5.0e-5,
        strfact=100,
        ntime=ntime,
    )

    ion_inp, ioncell_inp = multi.split_datasets()
    return ion_inp, ioncell_inp
예제 #18
0
def make_scf_nscf_inputs(tvars, pp_paths, nstep=50):
    """
    Returns two input files: GS run and NSCF on a high symmetry k-mesh
    """
    multi = abilab.MultiDataset(structure=abidata.cif_file("si.cif"),
                                pseudos=abidata.pseudos(pp_paths),
                                ndtset=2)

    nval = multi[0].num_valence_electrons
    assert all(inp.num_valence_electrons == 8 for inp in multi)

    # Global variables
    ecut = 4
    global_vars = dict(
        ecut=ecut,
        nband=int(nval / 2),
        nstep=nstep,
        paral_kgb=tvars.paral_kgb,
        timopt=-1,
    )

    if multi.ispaw:
        global_vars.update(pawecutdg=2 * ecut)

    multi.set_vars(global_vars)

    # Dataset 1 (GS run)
    multi[0].set_kmesh(ngkpt=[4, 4, 4], shiftk=[0, 0, 0])
    #multi[0].set_vars(prtden=1, prtpot=1, prtvha=1, prtvxc=1, prtvhxc=1)
    multi[0].set_vars(tolvrs=1e-4)

    # Dataset 2 (NSCF run)
    kptbounds = [
        [0.5, 0.0, 0.0],  # L point
        [0.0, 0.0, 0.0],  # Gamma point
        [0.0, 0.5, 0.5],  # X point
    ]

    multi[1].set_kpath(ndivsm=2, kptbounds=kptbounds)
    multi[1].set_vars(tolwfr=1e-6)

    # Generate two input files for the GS and the NSCF run.
    scf_input, nscf_input = multi.split_datasets()

    return scf_input, nscf_input
예제 #19
0
def make_scf_nscf_inputs(paral_kgb=1):
    """Returns two input files: GS run and NSCF on a high symmetry k-mesh."""
    pseudos = abidata.pseudos("14si.pspnc")
    #pseudos = data.pseudos("Si.GGA_PBE-JTH-paw.xml")

    multi = abilab.MultiDataset(structure=abidata.cif_file("si.cif"),
                                pseudos=pseudos,
                                ndtset=2)
    multi.set_mnemonics(True)

    # Global variables
    ecut = 6
    global_vars = dict(
        ecut=ecut,
        nband=8,
        timopt=-1,
        istwfk="*1",
        nstep=15,
        paral_kgb=paral_kgb,
        iomode=3,
    )

    if multi.ispaw:
        global_vars.update(pawecutdg=2 * ecut)

    multi.set_vars(global_vars)

    # Dataset 1 (GS run)
    multi[0].set_kmesh(ngkpt=[8, 8, 8], shiftk=[0, 0, 0])
    multi[0].set_vars(tolvrs=1e-6)

    # Dataset 2 (NSCF run)
    kptbounds = [
        [0.5, 0.0, 0.0],  # L point
        [0.0, 0.0, 0.0],  # Gamma point
        [0.0, 0.5, 0.5],  # X point
    ]

    multi[1].set_kpath(ndivsm=6, kptbounds=kptbounds)
    multi[1].set_vars(tolwfr=1e-12)

    # Generate two input files for the GS and the NSCF run
    scf_input, nscf_input = multi.split_datasets()
    return scf_input, nscf_input
예제 #20
0
def make_ebands_flow():
    """Band structure calculation."""
    multi = abilab.MultiDataset(structure=abidata.cif_file("si.cif"),
                                pseudos=abidata.pseudos("14si.pspnc"),
                                ndtset=2)
    # Global variables
    multi.set_vars(ecut=10)

    # Dataset 1
    multi[0].set_vars(tolvrs=1e-9)
    multi[0].set_kmesh(ngkpt=[4, 4, 4], shiftk=[0, 0, 0])

    # Dataset 2
    multi[1].set_vars(tolwfr=1e-15)
    multi[1].set_kpath(ndivsm=5)

    scf_input, nscf_input = multi.split_datasets()

    return flowtk.bandstructure_flow(workdir="flow_base3_ebands",
                                     scf_input=scf_input,
                                     nscf_input=nscf_input)
예제 #21
0
def build_relax_flow(options):
    """
    Crystalline silicon: computation of the optimal lattice parameter.
    Convergence with respect to the number of k points. Similar to tbase3_4.in
    """
    # Structural relaxation for different k-point samplings.
    ngkpt_list = [(2, 2, 2), (4, 4, 4)]

    shiftk = [
        float(s)
        for s in "0.5 0.5 0.5 0.5 0.0 0.0 0.0 0.5 0.0 0.0 0.0 0.5".split()
    ]

    multi = abilab.MultiDataset(structure=abidata.cif_file("si.cif"),
                                pseudos=abidata.pseudos("14si.pspnc"),
                                ndtset=len(ngkpt_list))

    # Global variables
    multi.set_vars(
        ecut=8,
        tolvrs=1e-9,
        optcell=1,
        ionmov=3,
        ntime=10,
        dilatmx=1.05,
        ecutsm=0.5,
        diemac=12,
        iomode=3,
    )

    for i, ngkpt in enumerate(ngkpt_list):
        multi[i].set_kmesh(ngkpt=ngkpt, shiftk=shiftk)

    workdir = options.workdir if (options
                                  and options.workdir) else "flow_base3_relax"

    return flowtk.Flow.from_inputs(workdir,
                                   inputs=multi.split_datasets(),
                                   task_class=flowtk.RelaxTask)
예제 #22
0
def build_ngkpt_flow(options):
    """
    Crystalline silicon: computation of the total energy
    Convergence with respect to the number of k points. Similar to tbase3_3.in

    Args:
        options: Command line options.

    Return:
        Abinit Flow object.
    """
    # Definition of the different grids
    ngkpt_list = [(2, 2, 2), (4, 4, 4), (6, 6, 6), (8, 8, 8)]

    # These shifts will be the same for all grids
    shiftk = [
        float(s)
        for s in "0.5 0.5 0.5 0.5 0.0 0.0 0.0 0.5 0.0 0.0 0.0 0.5".split()
    ]

    # Build MultiDataset object (container of `ndtset` inputs).
    # Structure is initialized from CIF file.
    multi = abilab.MultiDataset(structure=abidata.cif_file("si.cif"),
                                pseudos=abidata.pseudos("14si.pspnc"),
                                ndtset=len(ngkpt_list))

    # These variables are the same in each input.
    multi.set_vars(ecut=8, toldfe=1e-6, diemac=12.0, iomode=3)

    # Each input has its own value of `ngkpt`. shiftk is constant.
    for i, ngkpt in enumerate(ngkpt_list):
        multi[i].set_kmesh(ngkpt=ngkpt, shiftk=shiftk)

    workdir = options.workdir if (options
                                  and options.workdir) else "flow_base3_ngkpt"

    # Split the inputs by calling multi.datasets() and pass the list of inputs to Flow.from_inputs.
    return flowtk.Flow.from_inputs(workdir, inputs=multi.split_datasets())
예제 #23
0
def make_relax_flow(structure_file=None):
    """
    Build and return a flow that perform a structural relaxation for different k-point samplings.
    """
    ngkpt_list = [[3, 3, 2], [6, 6, 4], [8, 8, 6]]

    if structure_file is None:
        structure = abilab.Structure.from_file(abidata.cif_file("gan2.cif"))
    else:
        structure = abilab.Structure.from_file(structure_file)

    multi = abilab.MultiDataset(structure=structure,
                                pseudos=get_pseudos(structure),
                                ndtset=len(ngkpt_list))

    # Add mnemonics to input file.
    multi.set_mnemonics(True)

    # Global variables
    multi.set_vars(
        ecut=20,
        tolrff=5.0e-2,
        nstep=30,
        optcell=2,
        ionmov=3,
        ntime=50,
        dilatmx=1.05,
        ecutsm=0.5,
        tolmxf=5.0e-5,
    )

    for i, ngkpt in enumerate(ngkpt_list):
        multi[i].set_kmesh(ngkpt=ngkpt, shiftk=[0, 0, 0])

    return abilab.Flow.from_inputs("flow_gan_relax",
                                   inputs=multi.split_datasets(),
                                   task_class=abilab.RelaxTask)
예제 #24
0
def make_scf_nscf_inputs(structure, pseudos, paral_kgb=1):
    """return GS, NSCF (band structure), and DOSes input."""

    multi = abilab.MultiDataset(structure, pseudos=pseudos, ndtset=5)

    # Global variables
    global_vars = dict(
        ecut=10,
        nband=11,
        timopt=-1,
        occopt=4,  # Marzari smearing
        tsmear=0.03,
        paral_kgb=paral_kgb,
    )

    multi.set_vars(global_vars)

    # Dataset 1 (GS run)
    multi[0].set_kmesh(ngkpt=[8, 8, 8], shiftk=structure.calc_shiftk())

    multi[0].set_vars(tolvrs=1e-6)

    # Dataset 2 (NSCF Band Structure)
    multi[1].set_kpath(ndivsm=6)
    multi[1].set_vars(tolwfr=1e-12)

    # Dos calculations with increasing k-point sampling.
    for i, nksmall in enumerate([4, 8, 16]):
        multi[i + 2].set_vars(
            iscf=-3,  # NSCF calculation
            ngkpt=structure.calc_ngkpt(nksmall),
            shiftk=[0.0, 0.0, 0.0],
            tolwfr=1.0e-10,
        )

    # return GS, NSCF (band structure), DOSes input.
    return multi.split_datasets()
예제 #25
0
def make_relax_flow():
    # Structural relaxation for different k-point samplings.
    ngkpt_list = [(2, 2, 2), (4, 4, 4)]
    multi = abilab.MultiDataset(structure=abidata.cif_file("si.cif"),
                                pseudos=abidata.pseudos("14si.pspnc"),
                                ndtset=len(ngkpt_list))

    # Global variables
    multi.set_vars(
        ecut=10,
        tolvrs=1e-9,
        optcell=1,
        ionmov=3,
        ntime=10,
        dilatmx=1.05,
        ecutsm=0.5,
    )

    for i, ngkpt in enumerate(ngkpt_list):
        multi[i].set_kmesh(ngkpt=ngkpt, shiftk=[0, 0, 0])

    return RelaxFlow.from_inputs("flow_base3_relax",
                                 inputs=multi.split_datasets(),
                                 task_class=flowtk.RelaxTask)
예제 #26
0
def make_inputs(options):
    structure = abilab.Structure.from_abivars(unit_cell)

    if options.paw:
        raise RuntimeError("PAW is not implemented")
    else:
        pseudos = abidata.pseudos("26fe.pspnc", "83-Bi.GGA.fhi", '8o.pspnc')
        #pseudos = ["fe.pot", "bi.pot", 'o.pot']

    gs_inp = abilab.MultiDataset(structure, pseudos=pseudos, ndtset=2)
    gs_inp.set_vars(global_vars)

    gs_inp.set_vars(timopt=-1, kptopt=3, mem_test=0)

    gs_inp[0].set_vars(tolvrs=1.0e-18)

    gs_inp[1].set_vars(
        iscf=-2,
        tolwfr=1.0e-22,
        nband=100,
        nbdbuf=10,
    )

    return gs_inp.split_datasets()
예제 #27
0
def make_scf_nscf_inputs(structure, paral_kgb=1):
    multi = abilab.MultiDataset(structure,
                                pseudos=data.pseudos("14si.pspnc"),
                                ndtset=2)

    # Global variables
    global_vars = dict(
        ecut=6,
        nband=8,
        timopt=-1,
        paral_kgb=0,
        #nstep=4, # This is not enough to converge. Used to test the automatic restart.
        nstep=10,
        iomode=3,
    )

    multi.set_vars(global_vars)

    # Dataset 1 (GS run)
    multi[0].set_kmesh(ngkpt=[8, 8, 8], shiftk=[0, 0, 0])
    multi[0].set_vars(tolvrs=1e-6)

    # Dataset 2 (NSCF run)
    kptbounds = [
        [0.5, 0.0, 0.0],  # L point
        [0.0, 0.0, 0.0],  # Gamma point
        [0.0, 0.5, 0.5],  # X point
    ]

    multi[1].set_kpath(ndivsm=6, kptbounds=kptbounds)
    multi[1].set_vars(tolwfr=1e-12)

    # Generate two input files for the GS and the NSCF run
    scf_input, nscf_input = multi.split_datasets()

    return scf_input, nscf_input
예제 #28
0
def make_g0w0_inputs(ngkpt, tvars):
    """
    Input files for the calculation of the GW corrections.

    Returns: gs_input, nscf_input, scr_input, sigma_input
    """
    multi = abilab.MultiDataset(structure=abidata.cif_file("si.cif"),
                                pseudos=abidata.pseudos("14si.pspnc"), ndtset=4)

    # This grid is the most economical, but does not contain the Gamma point.
    scf_kmesh = dict(
        ngkpt=ngkpt,
        shiftk=[0.5, 0.5, 0.5,
                0.5, 0.0, 0.0,
                0.0, 0.5, 0.0,
                0.0, 0.0, 0.5]
    )

    # This grid contains the Gamma point, which is the point at which
    # we will compute the (direct) band gap.
    gw_kmesh = dict(
        ngkpt=ngkpt,
        shiftk=[0.0, 0.0, 0.0,
                0.0, 0.5, 0.5,
                0.5, 0.0, 0.5,
                0.5, 0.5, 0.0]
    )

    # Global variables. gw_kmesh is used in all datasets except DATASET 1.
    ecut = 4

    multi.set_vars(
        ecut=ecut,
        pawecutdg=ecut*2 if multi.ispaw else None,
        istwfk="*1",
        paral_kgb=tvars.paral_kgb,
        gwpara=2,
    )
    multi.set_kmesh(**gw_kmesh)

    # Dataset 1 (GS run)
    multi[0].set_kmesh(**scf_kmesh)
    multi[0].set_vars(tolvrs=1e-6, nband=4)

    # Dataset 2 (NSCF run)
    multi[1].set_vars(iscf=-2,
                      tolwfr=1e-10,
                      nband=10,
                      nbdbuf=2)

    # Dataset3: Calculation of the screening.
    multi[2].set_vars(
        optdriver=3,
        nband=8,
        ecutwfn=ecut,
        symchi=1,
        inclvkb=0,
        ecuteps=2.0,
    )

    # Dataset4: Calculation of the Self-Energy matrix elements (GW corrections)
    kptgw = [
         -2.50000000E-01, -2.50000000E-01,  0.00000000E+00,
         -2.50000000E-01,  2.50000000E-01,  0.00000000E+00,
          5.00000000E-01,  5.00000000E-01,  0.00000000E+00,
         -2.50000000E-01,  5.00000000E-01,  2.50000000E-01,
          5.00000000E-01,  0.00000000E+00,  0.00000000E+00,
          0.00000000E+00,  0.00000000E+00,  0.00000000E+00,
      ]

    multi[3].set_vars(
            optdriver=4,
            nband=10,
            ecutwfn=ecut,
            ecuteps=2.0,
            ecutsigx=2.0,
            symsigma=1,
            #gw_qprange=0,
    )

    bdgw = [4, 5]
    multi[3].set_kptgw(kptgw, bdgw)

    return multi.split_datasets()
예제 #29
0
파일: sigma_cd.py 프로젝트: zbwang/abipy
def make_inputs(paw=False):
    # Crystalline silicon
    # Calculation of the GW correction to the direct band gap in Gamma
    # Dataset 1: ground state calculation
    # Dataset 2: NSCF calculation
    # Dataset 3: calculation of the screening
    # Dataset 4: calculation of the Self-Energy matrix elements (GW corrections)
    structure = abilab.Structure.from_file(abidata.cif_file("si.cif"))
    pseudos = abidata.pseudos("14si.pspnc") if not paw else abidata.pseudos("Si.GGA_PBE-JTH-paw.xml")

    multi = abilab.MultiDataset(structure, pseudos=pseudos, ndtset=4)

    ecut = 14
    multi.set_vars(
        ecut=ecut,
        pawecutdg=ecut*4 if paw else None,
        timopt=-1,
        istwfk="*1",
        paral_kgb=0,
    )


    multi.set_kmesh(
        ngkpt=[6,6,6],
        shiftk=[0.0, 0.0, 0.0],
    )

    gs, nscf, scr, sigma = multi.split_datasets()

    gs.set_vars(tolvrs=1e-6,
                nband=4,)

    # Dataset 2 (NSCF run)
    # Here we select the second dataset directly with the syntax inp[2]
    nscf.set_vars(iscf=-2,
                  tolwfr=1e-8,
                  nband=300,
                  nbdbuf=50,
                  )

    # Dataset3: Calculation of the screening.
    scr.set_vars(
        optdriver=3,
        gwcalctyp=9,
        gwpara=2,
        nband=25,
        ecutwfn=ecut,
        symchi=1,
        awtr=2,
        inclvkb=0,
        ecuteps=4.0,
        spmeth=1,        # Use Hilbert transform : Im chi0 --> chi0.
        nomegasf=250,    # Number of points for Imchi0
        nfreqre=50,
        nfreqim=10,
        freqremax="25 eV",
        freqremin="0 eV",
    )

    # Dataset4: Calculation of the Self-Energy matrix elements (GW corrections)
    sigma.set_vars(
        optdriver=4,
        gwcalctyp=9,
        gwpara=2,
        nband=35,
        ecutwfn=ecut,
        ecuteps=4.0,
        ecutsigx=ecut,
        symsigma=1,
        gw_qprange=1,
    )

    return gs, nscf, scr, sigma
예제 #30
0
def build_flow(options, paral_kgb=0):
    # Working directory (default is the name of the script with '.py' removed and "run_" replaced by "flow_")
    workdir = options.workdir
    if not options.workdir:
        workdir = os.path.basename(__file__).replace(".py", "").replace(
            "run_", "flow_")

    multi = abilab.MultiDataset(structure=data.structure_from_ucell("GaAs"),
                                pseudos=data.pseudos("31ga.pspnc",
                                                     "33as.pspnc"),
                                ndtset=5)

    # Global variables
    kmesh = dict(ngkpt=[4, 4, 4],
                 nshiftk=4,
                 shiftk=[[0.5, 0.5, 0.5], [0.5, 0.0, 0.0], [0.0, 0.5, 0.0],
                         [0.0, 0.0, 0.5]])

    global_vars = dict(ecut=2, paral_kgb=paral_kgb)
    global_vars.update(kmesh)

    multi.set_vars(global_vars)

    # Dataset 1 (GS run)
    multi[0].set_vars(
        tolvrs=1e-6,
        nband=4,
    )

    # NSCF run with large number of bands, and points in the the full BZ
    multi[1].set_vars(
        iscf=-2,
        nband=20,
        nstep=25,
        kptopt=1,
        tolwfr=1.e-9,
        #kptopt=3,
    )

    # Fourth dataset : ddk response function along axis 1
    # Fifth dataset : ddk response function along axis 2
    # Sixth dataset : ddk response function along axis 3
    for dir in range(3):
        rfdir = 3 * [0]
        rfdir[dir] = 1

        multi[2 + dir].set_vars(
            iscf=-3,
            nband=20,
            nstep=1,
            nline=0,
            prtwf=3,
            kptopt=3,
            nqpt=1,
            qpt=[0.0, 0.0, 0.0],
            rfdir=rfdir,
            rfelfd=2,
            tolwfr=1.e-9,
        )

    scf_inp, nscf_inp, ddk1, ddk2, ddk3 = multi.split_datasets()

    # Initialize the flow.
    flow = abilab.Flow(workdir, manager=options.manager, remove=options.remove)

    bands_work = abilab.BandStructureWork(scf_inp, nscf_inp)
    flow.register_work(bands_work)

    ddk_work = abilab.Work()
    for inp in [ddk1, ddk2, ddk3]:
        ddk_work.register_ddk_task(inp, deps={bands_work.nscf_task: "WFK"})

    flow.register_work(ddk_work)

    # Optic does not support MPI with ncpus > 1.
    optic_input = abilab.OpticInput(
        broadening=0.002,  # Value of the smearing factor, in Hartree
        domega=0.0003,  # Frequency mesh.
        maxomega=0.3,
        scissor=0.000,  # Scissor shift if needed, in Hartree
        tolerance=0.002,  # Tolerance on closeness of singularities (in Hartree)
        num_lin_comp=
        1,  # Number of components of linear optic tensor to be computed
        lin_comp=11,  # Linear coefficients to be computed (x=1, y=2, z=3)
        num_nonlin_comp=
        2,  # Number of components of nonlinear optic tensor to be computed
        nonlin_comp=(123, 222),  # Non-linear coefficients to be computed
    )

    # TODO
    # Check is the order of the 1WF files is relevant. Can we use DDK files ordered
    # in an arbitrary way or do we have to pass (x,y,z)?
    optic_task = abilab.OpticTask(optic_input,
                                  nscf_node=bands_work.nscf_task,
                                  ddk_nodes=ddk_work)
    flow.register_task(optic_task)

    return flow