Skip to content

Commit

Permalink
Reworked CLI
Browse files Browse the repository at this point in the history
  • Loading branch information
d-wortmann committed Jun 12, 2024
1 parent 32c3cef commit c15d1c3
Show file tree
Hide file tree
Showing 5 changed files with 151 additions and 31 deletions.
6 changes: 4 additions & 2 deletions aiida_fleur/cmdline/launch/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,8 @@
from .launch import launch_inpgen
from .launch import launch_fleur
from .launch import launch_scf
from .launch import launch_banddos
from .launch import launch_dos
from .launch import launch_band
from .launch import launch_relax
from .launch import launch_eos
from .launch import launch_corehole
Expand All @@ -36,7 +37,8 @@ def cmd_launch():
cmd_launch.add_command(launch_inpgen)
cmd_launch.add_command(launch_fleur)
cmd_launch.add_command(launch_scf)
cmd_launch.add_command(launch_banddos)
cmd_launch.add_command(launch_dos)
cmd_launch.add_command(launch_band)
cmd_launch.add_command(launch_relax)
cmd_launch.add_command(launch_eos)
cmd_launch.add_command(launch_corehole)
Expand Down
85 changes: 78 additions & 7 deletions aiida_fleur/cmdline/launch/launch.py
Original file line number Diff line number Diff line change
Expand Up @@ -218,7 +218,7 @@ def launch_scf(structure, inpgen, calc_parameters, fleurinp, fleur, wf_parameter
f.write(wf.outputs.last_calc.retrieved.get_object_content(file,"rb"))

@click.command('relax')
@options.STRUCTURE_OR_FILE(default=defaults.get_si_bulk_structure, show_default=True)
@options.STRUCTURE_OR_FILE(default="inp.xml", show_default=True)
@options.INPGEN()
@options.CALC_PARAMETERS()
@options.FLEUR()
Expand All @@ -234,9 +234,24 @@ def launch_relax(structure, inpgen, calc_parameters, fleur, wf_parameters, scf_p
# TODO final scf input
"""
workchain_class = WorkflowFactory('fleur.base_relax')
from aiida_fleur.workflows.relax import FleurRelaxWorkChain

if isinstance(structure, FleurinpData):
fleurinp=structure
structure=None
inpgen=None

# we need a scf_paramters dict to change the forcemix if required later
if scf_parameters==None:
scf_parameters=Dict(dict= {
'force_dict': {'forcemix': 'BFGS'},
'inpxml_changes': []
})

#workchain_class = WorkflowFactory('fleur.base_relax')
inputs = {
'scf': {
'fleurinp': fleurinp,
'wf_parameters': scf_parameters,
'structure': structure,
'calc_parameters': calc_parameters,
Expand All @@ -246,11 +261,35 @@ def launch_relax(structure, inpgen, calc_parameters, fleur, wf_parameters, scf_p
},
'wf_parameters': wf_parameters
}


inputs = clean_nones(inputs)
builder = workchain_class.get_builder()
builder = FleurRelaxWorkChain.get_builder()
builder.update(inputs)
utils.launch_process(builder, daemon)
pk=utils.launch_process(builder, daemon)

#Now create output files
if fleurinp and not daemon:
from aiida.orm import load_node
wf=load_node(pk)
relax_output=wf.outputs.output_relax_wc_para.get_dict()
relax_output["Relax-uuid"]=wf.uuid
relax_output["retrieved-uuid"]=wf.outputs.last_scf.last_calc.retrieved.uuid


#json with dict
import json
with open("relax.json","w") as file:
json.dump(relax_output,file,indent=2)
#plot
from aiida_fleur.tools.plot.fleur import plot_fleur
plot_fleur([wf],save=True,show=False)

#store files
for file in ["relax.xml","out.xml","cdn1","cdn_last.hdf"]:
if file in wf.outputs.last_scf.last_calc.retrieved.list_object_names():
with open(file,"wb") as f:
f.write(wf.outputs.last_scf.last_calc.retrieved.get_object_content(file,"rb"))

@click.command('eos')
@options.STRUCTURE_OR_FILE(default="inp.xml", show_default=True)
Expand Down Expand Up @@ -320,19 +359,47 @@ def launch_eos(structure, inpgen, calc_parameters, fleur, wf_parameters, scf_par



@click.command('banddos')
@click.command('dos')
@options.FLEURINP(default='inp.xml')
@options.FLEUR()
@options.WF_PARAMETERS()
@options.REMOTE()
@options.DAEMON()
@options.SETTINGS()
@options.OPTION_NODE()
def launch_banddos(fleurinp, fleur, wf_parameters, parent_folder, daemon, settings, option_node):
def launch_dos(fleurinp, fleur, wf_parameters, parent_folder, daemon, settings, option_node):
"""
Launch a banddos workchain
Launch a banddos workchain (special command to set the dos as a default mode)
"""
if wf_parameters==None:
wf_parameters=Dict({"mode":"dos"})
else:
wf_dict=wf_parameters.get_dict()
wf_dict["mode"]="dos"
wf_parameters=Dict(wf_dict)

launch_banddos(fleurinp, fleur, wf_parameters, parent_folder, daemon, settings, option_node)


@click.command('band')
@options.FLEURINP(default='inp.xml')
@options.FLEUR()
@options.WF_PARAMETERS()
@options.REMOTE()
@options.DAEMON()
@options.SETTINGS()
@options.OPTION_NODE()
def launch_band(fleurinp, fleur, wf_parameters, parent_folder, daemon, settings, option_node):
"""
Launch a banddos workchain in 'band' mode
"""
#Band is default
launch_banddos(fleurinp, fleur, wf_parameters, parent_folder, daemon, settings, option_node)

def launch_banddos(fleurinp, fleur, wf_parameters, parent_folder, daemon, settings, option_node):
"""
Launch a banddos workchain
"""
workchain_class = WorkflowFactory('fleur.banddos')
inputs = {
'wf_parameters': wf_parameters,
Expand All @@ -354,6 +421,10 @@ def launch_banddos(fleurinp, fleur, wf_parameters, parent_folder, daemon, settin
import json
with open("banddos.json","w") as file:
json.dump(banddos_output,file,indent=2)
#the banddos.hdf file
with open(f"banddos.hdf","wb") as f:
f.write(wf.outputs.banddos_calc.retrieved.get_object_content("banddos.hdf",'rb'))

#plot
from aiida_fleur.tools.plot.fleur import plot_fleur
plot_fleur(wf,save=True,show=False)
Expand Down
49 changes: 33 additions & 16 deletions aiida_fleur/cmdline/util/types.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,15 +26,28 @@
'"energy_converged": 0.002,\n'
'"mode": "density",\n'
'"itmax_per_run": 30}',
"banddos":'{"mode": "band",\n'
'"kpath": "auto",\n'
'"klistname": "path-3",\n'
'"kpoints_number": None,\n'
'"kpoints_distance": None,\n'
'"kpoints_explicit": None,\n'
'"sigma": 0.005,\n'
'"emin": -0.50,\n'
'"emax": 0.90\n}'
"band":'{\n'
'// Select your k-points\n'
'"kpath": "auto"// This can be "auto" (meaning you try to pick a good choice automatically from inp.xml) or "seek" to use seek-k-path\n'
'//",klistname": "path-3"//You can specify directly a list in the inp.xml/kpts.xml\n'
'//",kpoints_number": 200\n'
'//",kpoints_distance": 0.1\n'
'//",kpoints_explicit": None\n}',
"dos":'{\n'
'// Select your k-points\n'
'//"klistname": "path-3",//You can specify directly a list in the inp.xml/kpts.xml\n'
'//"kpoints_number": 200,\n'
'//"kpoints_distance": 0.1,\n'
'// These parameters are relevant for the DOS mode\n'
'"sigma": 0.005\n'
'",emin": -0.50\n'
'",emax": 0.90\n}',
"relax":'{\n'
'"film_distance_relaxation": "False", // if True, sets relaxXYZ="FFT" for all atoms\n'
'"force_criterion": 0.049, // Sets the threshold of the largest force\n'
'"relax_iter": 5 // Maximum number of optimization iterations\n'
'}'

}


Expand Down Expand Up @@ -78,10 +91,11 @@ def convert(self,value,param,ctx):
with open(value,"r") as f:
import json
dict_from_file=json.load(f)

scf_wf=load_node(dict_from_file["SCF-uuid"])
print(scf_wf)
return scf_wf.outputs.last_calc.remote_folder
if 'SCF-uuid' in dict_from_file:
scf_wf=load_node(dict_from_file["SCF-uuid"])
return scf_wf.outputs.last_calc.remote_folder
if 'retrieved-uuid' in dict_from_file:
return dict_from_file["retrieved-uuid"]
except:
return None

Expand All @@ -104,14 +118,17 @@ def convert(self,value,param,ctx):
try:
with open(value,"r") as f:
import json
wf_param=json.load(f)
except:
from json_minify import json_minify

wf_param=json.loads(json_minify(f.read()))
except RuntimeError as error:
print(error)
print(f"{value} could not be converted into a dict")
os.abort()
aiida_dict=DataFactory("dict")
wf_dict=aiida_dict(wf_param)

return wf_dict.store()
return wf_dict

#Now load from aiida
wf_dict = types.DataParamType(sub_classes=('aiida.data:core.dict',)).convert(value, param, ctx)
Expand Down
2 changes: 1 addition & 1 deletion aiida_fleur/parsers/fleur.py
Original file line number Diff line number Diff line change
Expand Up @@ -280,7 +280,7 @@ def parse(self, **kwargs):
except NotExistent:
old_relax_text = ''
else:
if relax_name in fleurinp.list_object_names():
if relax_name in fleurinp.base.repository.list_object_names():
with fleurinp.open(relax_name, 'r') as rlx:
old_relax_text = rlx.read()
else:
Expand Down
40 changes: 35 additions & 5 deletions aiida_fleur/tools/plot/fleur.py
Original file line number Diff line number Diff line change
Expand Up @@ -62,11 +62,12 @@ def plot_fleur(*args, save=False, show_dict=False, show=True, backend=None, **kw
for arg in args:
if isinstance(arg, list):
# try plot together
print("mn:",arg)
p1 = plot_fleur_mn(arg, save=save, show=show, backend=backend, **kwargs)
if len(p1) == 1:
p1 = p1[0]
else:
#print(arg)
print("sn:",arg)
# plot alone
p1 = plot_fleur_sn(arg, show_dict=show_dict, show=show, save=save, backend=backend, **kwargs)
all_plots.append(p1)
Expand All @@ -90,7 +91,7 @@ def plot_fleur_sn(node, show_dict=False, **kwargs):
except KeyError as exc:
raise ValueError('Sorry, I do not know how to visualize'
f' this node in plot_fleur: {workflow_name} {node}') from exc

print(plot_nodes)
plot_result = plotf(*plot_nodes, **kwargs)

return plot_result
Expand Down Expand Up @@ -432,16 +433,44 @@ def plot_fleur_banddos_wc(param_node,
return plot_res


def plot_fleur_relax_wc(node, labels=None, save=False, show=True, **kwargs):
def plot_fleur_relax_wc(node, labels=None, save=False, show=True, backend='bokeh', **kwargs):
"""
This methods takes an AiiDA output parameter node from a relaxation
workchain and plots some information about atom movements and forces
"""
from masci_tools.vis.common import convergence_plot

if labels is None:
labels = []
labels = [n.pk for n in node]

if isinstance(node, list):
if len(node) > 2:
return # TODO
else:
node = node[0]

output_d = node.get_dict()
forces = output_d.get('force')
total_energies=output_d.get('energy')
iteration=range(len(forces))

add_args = {}
if backend == 'bokeh':
add_args['legend_label'] = labels
else:
add_args['plot_label'] = labels

raise NotImplementedError

plot_res = convergence_plot(iteration,
forces,
total_energies,
show=show,
save_plots=save,
backend=backend,
saveas_distance="force_convergence",
ylabel_distance="Largest force [Htr/bohr]",
**kwargs)
return plot_res

def plot_fleur_corehole_wc(nodes, labels=None, save=False, show=True, **kwargs):
"""
Expand Down Expand Up @@ -618,6 +647,7 @@ def plot_fleur_cfcoeff_wc(param_node,
'FleurBandWorkChain': plot_fleur_band_wc,
'FleurBandDosWorkChain': plot_fleur_banddos_wc,
'FleurCFCoeffWorkChain': plot_fleur_cfcoeff_wc,
'FleurRelaxWorkChain': plot_fleur_relax_wc,
#'fleur_corehole_wc' : plot_fleur_corehole_wc, #support of < 1.5 release
#'fleur_initial_cls_wc' : plot_fleur_initial_cls_wc, #support of < 1.5 release
#'FleurInitialCLSWorkChain' : plot_fleur_initial_cls_wc,
Expand Down

0 comments on commit c15d1c3

Please sign in to comment.