Skip to content

Commit ddf39f1

Browse files
AnguseZhangamcadmusnjzjz
authored
Allow user defined forward_common_files and backward_files (#482)
* Add Cu's init_surf examples. * Delete personal information * Update examples/init/cu.surf.hcp.111.json Co-authored-by: Jinzhe Zeng <jinzhe.zeng@rutgers.edu> * Add fp.log in backward_files * Add original methane INCAR * Refactor decide_machine; Allow user_defined input and output; * Debug user_defined_forward_common_files * Fix bug in user_forward_common_files * Allow define input and output files * Fix bugs * Fix bugs * Fix bug * Fix bug * Fix bug * Add documentation * Fix bug * Add file for unittest * Fix backward_files and examples. * Fix user_forward_files * Change comments; add support for init; fix cvasp problems * Fix bugs in cvasp of init_bulk * Fix bug in user_forward_files in init_bulk * Fix bug in init's user_forward_files * Fix cvasp bugs in init_bulk * Fix bugs in cvasp of init_bulk * Fix bug in INCAR_md, fixed unit test * Update context.py * Update context.py * Update test_convert_mdata.py * Update context.py * Update test_convert_mdata.py Co-authored-by: Han Wang <amcadmus@gmail.com> Co-authored-by: Jinzhe Zeng <jinzhe.zeng@rutgers.edu>
1 parent a14799a commit ddf39f1

30 files changed

+539
-354
lines changed

README.md

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@
2525
[![conda install](https://img.shields.io/conda/dn/conda-forge/dpgen?label=conda%20install)](https://anaconda.org/conda-forge/dpgen)
2626
[![pip install](https://img.shields.io/pypi/dm/dpgen?label=pip%20install)](https://pypi.org/project/dpgen)
2727

28-
DP-GEN (Deep Generator) is a software written in Python, delicately designed to generate a deep learning based model of interatomic potential energy and force field. DP-GEN is depedent on DeepMD-kit (https://github.com/deepmodeling/deepmd-kit/blob/master/README.md). With highly scalable interface with common softwares for molecular simulation, DP-GEN is capable to automatically prepare scripts and maintain job queues on HPC machines (High Performance Cluster) and analyze results.
28+
DP-GEN (Deep Generator) is a software written in Python, delicately designed to generate a deep learning based model of interatomic potential energy and force field. DP-GEN is dependent on [DeepMD-kit](https://github.com/deepmodeling/deepmd-kit/blob/master/README.md). With highly scalable interface with common softwares for molecular simulation, DP-GEN is capable to automatically prepare scripts and maintain job queues on HPC machines (High Performance Cluster) and analyze results.
2929

3030
If you use this software in any publication, please cite:
3131

@@ -34,7 +34,7 @@ Yuzhi Zhang, Haidi Wang, Weijie Chen, Jinzhe Zeng, Linfeng Zhang, Han Wang, and
3434
### Highlighted features
3535
+ **Accurate and efficient**: DP-GEN is capable to sample more than tens of million structures and select only a few for first principles calculation. DP-GEN will finally obtain a uniformly accurate model.
3636
+ **User-friendly and automatic**: Users may install and run DP-GEN easily. Once succusefully running, DP-GEN can dispatch and handle all jobs on HPCs, and thus there's no need for any personal effort.
37-
+ **Highly scalable**: With modularized code structures, users and developers can easily extend DP-GEN for their most relevant needs. DP-GEN currently supports for HPC systems (Slurm, PBS, LSF and cloud machines ), Deep Potential interface with DeePMD-kit, MD interface with LAMMPS and *ab-initio* calculation interface with VASP, PWSCF,SIESTA and Gaussian. We're sincerely welcome and embraced to users' contributions, with more possibilities and cases to use DP-GEN.
37+
+ **Highly scalable**: With modularized code structures, users and developers can easily extend DP-GEN for their most relevant needs. DP-GEN currently supports for HPC systems (Slurm, PBS, LSF and cloud machines ), Deep Potential interface with DeePMD-kit, MD interface with [LAMMPS](https://www.lammps.org/), [Gromacs](http://www.gromacs.org/) and *ab-initio* calculation interface with VASP, PWSCF, CP2K, SIESTA and Gaussian, Abacus, PWMAT, etc . We're sincerely welcome and embraced to users' contributions, with more possibilities and cases to use DP-GEN.
3838

3939
### Code structure and interface
4040
+ dpgen:
@@ -43,7 +43,8 @@ Yuzhi Zhang, Haidi Wang, Weijie Chen, Jinzhe Zeng, Linfeng Zhang, Han Wang, and
4343
* generator: source codes for main process of deep generator.
4444

4545
* auto_test : source code for undertaking materials property analysis.
46-
* remote : source code for automatically submiting scripts,maintaining job queues and collecting results.
46+
* remote and dispatcher : source code for automatically submiting scripts,maintaining job queues and collecting results.
47+
Notice this part hase been integrated into [dpdispatcher](https://github.com/deepmodeling/dpdispatcher)
4748
* database : source code for collecting data generated by DP-GEN and interface with database.
4849
+ examples : providing example JSON files.
4950

@@ -63,6 +64,15 @@ Options for TASK:
6364
* `test`: Auto-test for Deep Potential.
6465
* `db`: Collecting data from DP-GEN.
6566

67+
68+
[Here](examples) are examples you can refer to. You should make sure that provide a correct [JSON](https://docs.python.org/3/library/json.html) file.
69+
You can use following command to check your JSON file.
70+
```python
71+
import json
72+
#Specify machine parameters in machine.json
73+
json.load(open("machine.json"))
74+
```
75+
6676
## Download and Install
6777
One can download the source code of dpgen by
6878
```bash
@@ -1322,7 +1332,9 @@ mem_limit | Interger | 16 | Maximal memory permitted to apply for the job.
13221332
| # End of resources
13231333
| command | String | "lmp_serial" | Executable path of software, such as `lmp_serial`, `lmp_mpi` and `vasp_gpu`, `vasp_std`, etc.
13241334
| group_size | Integer | 5 | DP-GEN will put these jobs together in one submitting script.
1325-
1335+
| user_forward_files | List of str | ["/path_to/vdw_kernel.bindat"] | These files will be uploaded in each calculation task. You should make sure provide the path exists.
1336+
| user_backward_files | List of str | ["HILLS"] | Besides DP-GEN's normal output, these files will be downloaded after each calculation. You should make sure these files can be generated.
1337+
13261338
## Troubleshooting
13271339
1. The most common problem is whether two settings correspond with each other, including:
13281340
- The order of elements in `type_map` and `mass_map` and **`fp_pp_files`**.

doc/CONTRIBUTING.md

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
# DP-GEN Contributing Guide
2+
Welcome to [DP-GEN](https://github.com/deepmodeling/dpgen/tree/master/dpgen) !
3+
4+
5+
## How to contribute
6+
DP-GEN adopts the same convention as other softwares in DeepModeling Community.
7+
You can first refer to DeePMD-kit's
8+
[Contributing guide](https://github.com/deepmodeling/deepmd-kit/edit/devel/CONTRIBUTING.md)
9+
and [Developer guide](https://github.com/deepmodeling/deepmd-kit/edit/devel/doc/development/index.md).
10+

dpgen/auto_test/common_equi.py

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,9 @@
99
from dpgen.auto_test.calculator import make_calculator
1010
from dpgen.auto_test.mpdb import get_structure
1111
from dpgen.dispatcher.Dispatcher import make_dispatcher
12-
from dpgen.remote.decide_machine import decide_fp_machine, decide_model_devi_machine
1312
from distutils.version import LooseVersion
1413
from dpgen.dispatcher.Dispatcher import make_submission
15-
14+
from dpgen.remote.decide_machine import convert_mdata
1615
lammps_task_type = ['deepmd', 'meam', 'eam_fs', 'eam_alloy']
1716

1817

@@ -133,9 +132,9 @@ def run_equi(confs,
133132
inter_type = inter_param['type']
134133
# vasp
135134
if inter_type == "vasp":
136-
mdata = decide_fp_machine(mdata)
135+
mdata = convert_mdata(mdata, ["fp"])
137136
elif inter_type in lammps_task_type:
138-
mdata = decide_model_devi_machine(mdata)
137+
mdata = convert_mdata(mdata, ["model_devi"])
139138
else:
140139
raise RuntimeError("unknown task %s, something wrong" % inter_type)
141140

dpgen/auto_test/common_prop.py

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,8 @@
1313
from dpgen.auto_test.Vacancy import Vacancy
1414
from dpgen.auto_test.calculator import make_calculator
1515
from dpgen.dispatcher.Dispatcher import make_dispatcher
16-
from dpgen.remote.decide_machine import decide_fp_machine, decide_model_devi_machine
1716
from dpgen.dispatcher.Dispatcher import make_submission
18-
17+
from dpgen.remote.decide_machine import convert_mdata
1918
lammps_task_type = ['deepmd', 'meam', 'eam_fs', 'eam_alloy']
2019

2120

@@ -150,9 +149,9 @@ def run_property(confs,
150149
inter_type = inter_param_prop['type']
151150
# vasp
152151
if inter_type == "vasp":
153-
mdata = decide_fp_machine(mdata)
152+
mdata = convert_mdata(mdata, ["fp"])
154153
elif inter_type in lammps_task_type:
155-
mdata = decide_model_devi_machine(mdata)
154+
mdata = convert_mdata(mdata, ["model_devi"])
156155
else:
157156
raise RuntimeError("unknown task %s, something wrong" % inter_type)
158157

dpgen/auto_test/lib/util.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -77,11 +77,11 @@ def get_machine_info(mdata,task_type):
7777
command = vasp_exec
7878
command = cmd_append_log(command, "log")
7979
elif task_type in lammps_task_type:
80-
lmp_exec = mdata['lmp_command']
80+
model_devi_exec = mdata['model_devi_command']
8181
group_size = mdata['model_devi_group_size']
8282
resources = mdata['model_devi_resources']
8383
machine=mdata['model_devi_machine']
84-
command = lmp_exec + " -i in.lammps"
84+
command = model_devi_exec + " -i in.lammps"
8585
command = cmd_append_log(command, "model_devi.log")
8686
return machine, resources, command, group_size
8787

dpgen/data/gen.py

Lines changed: 44 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -22,14 +22,16 @@
2222
import dpgen.data.tools.sc as sc
2323
from distutils.version import LooseVersion
2424
from dpgen.generator.lib.vasp import incar_upper
25+
from dpgen.generator.lib.utils import symlink_user_forward_files
2526
from pymatgen.core import Structure
2627
from pymatgen.io.vasp import Incar
27-
from dpgen.remote.decide_machine import decide_fp_machine
28+
from dpgen.remote.decide_machine import convert_mdata
2829
from dpgen import ROOT_PATH
2930
from dpgen.dispatcher.Dispatcher import Dispatcher, make_dispatcher, make_submission
3031

3132

3233

34+
3335
def create_path (path,back=False) :
3436
if path[-1] != "/":
3537
path += '/'
@@ -311,12 +313,7 @@ def make_vasp_relax (jdata, mdata) :
311313
os.remove(os.path.join(work_dir, 'POTCAR'))
312314
shutil.copy2( jdata['relax_incar'],
313315
os.path.join(work_dir, 'INCAR'))
314-
is_cvasp = False
315-
if 'cvasp' in mdata['fp_resources'].keys():
316-
is_cvasp = mdata['fp_resources']['cvasp']
317-
if is_cvasp:
318-
cvasp_file=os.path.join(ROOT_PATH,'generator/lib/cvasp.py')
319-
shutil.copyfile(cvasp_file, os.path.join(work_dir, 'cvasp.py'))
316+
320317
out_potcar = os.path.join(work_dir, 'POTCAR')
321318
with open(out_potcar, 'w') as outfile:
322319
for fname in potcars:
@@ -338,8 +335,17 @@ def make_vasp_relax (jdata, mdata) :
338335
os.symlink(ln_src, 'POTCAR')
339336
except FileExistsError:
340337
pass
338+
is_cvasp = False
339+
if 'cvasp' in mdata['fp_resources'].keys():
340+
is_cvasp = mdata['fp_resources']['cvasp']
341+
if is_cvasp:
342+
cvasp_file = os.path.join(ROOT_PATH, 'generator/lib/cvasp.py')
343+
shutil.copyfile(cvasp_file, 'cvasp.py')
341344
os.chdir(work_dir)
342345
os.chdir(cwd)
346+
symlink_user_forward_files(mdata=mdata, task_type="fp",
347+
work_path=os.path.join(os.path.basename(out_dir),global_dirname_02),
348+
task_format= {"fp" : "sys-*"})
343349

344350
def make_scale(jdata):
345351
out_dir = jdata['out_dir']
@@ -373,6 +379,7 @@ def make_scale(jdata):
373379
os.chdir(scale_path)
374380
poscar_scale(pos_src, 'POSCAR', jj)
375381
os.chdir(cwd)
382+
376383

377384
def pert_scaled(jdata) :
378385
out_dir = jdata['out_dir']
@@ -425,7 +432,7 @@ def pert_scaled(jdata) :
425432
shutil.copy2(pos_in, pos_out)
426433
os.chdir(cwd)
427434

428-
def make_vasp_md(jdata) :
435+
def make_vasp_md(jdata, mdata) :
429436
out_dir = jdata['out_dir']
430437
potcars = jdata['potcars']
431438
scale = jdata['scale']
@@ -451,7 +458,9 @@ def make_vasp_md(jdata) :
451458
with open(fname) as infile:
452459
outfile.write(infile.read())
453460
os.chdir(path_md)
454-
os.chdir(cwd)
461+
os.chdir(cwd)
462+
463+
455464

456465
for ii in sys_ps :
457466
for jj in scale :
@@ -478,8 +487,20 @@ def make_vasp_md(jdata) :
478487
os.symlink(os.path.relpath(file_potcar), 'POTCAR')
479488
except FileExistsError:
480489
pass
490+
491+
is_cvasp = False
492+
if 'cvasp' in mdata['fp_resources'].keys():
493+
is_cvasp = mdata['fp_resources']['cvasp']
494+
if is_cvasp:
495+
cvasp_file = os.path.join(ROOT_PATH, 'generator/lib/cvasp.py')
496+
shutil.copyfile(cvasp_file, 'cvasp.py')
481497

482-
os.chdir(cwd)
498+
os.chdir(cwd)
499+
500+
symlink_user_forward_files(mdata=mdata, task_type="fp",
501+
work_path=os.path.join(os.path.basename(out_dir),global_dirname_04),
502+
task_format= {"fp" :"sys-*/scale*/00*"})
503+
483504

484505
def coll_vasp_md(jdata) :
485506
out_dir = jdata['out_dir']
@@ -565,11 +586,14 @@ def run_vasp_relax(jdata, mdata):
565586
work_dir = os.path.join(jdata['out_dir'], global_dirname_02)
566587

567588
forward_files = ["POSCAR", "INCAR", "POTCAR"]
589+
user_forward_files = mdata.get("fp" + "_user_forward_files", [])
590+
forward_files += [os.path.basename(file) for file in user_forward_files]
568591
backward_files = ["OUTCAR","CONTCAR"]
592+
backward_files += mdata.get("fp" + "_user_backward_files", [])
569593
forward_common_files = []
570594
if 'cvasp' in mdata['fp_resources']:
571595
if mdata['fp_resources']['cvasp']:
572-
forward_common_files=['cvasp.py']
596+
forward_files +=['cvasp.py']
573597
relax_tasks = glob.glob(os.path.join(work_dir, "sys-*"))
574598
relax_tasks.sort()
575599
#dlog.info("work_dir",work_dir)
@@ -624,11 +648,14 @@ def run_vasp_md(jdata, mdata):
624648
md_nstep = jdata['md_nstep']
625649

626650
forward_files = ["POSCAR", "INCAR", "POTCAR"]
651+
user_forward_files = mdata.get("fp" + "_user_forward_files", [])
652+
forward_files += [os.path.basename(file) for file in user_forward_files]
627653
backward_files = ["OUTCAR"]
654+
backward_files += mdata.get("fp" + "_user_backward_files", [])
628655
forward_common_files = []
629656
if 'cvasp' in mdata['fp_resources']:
630657
if mdata['fp_resources']['cvasp']:
631-
forward_common_files=['cvasp.py']
658+
forward_files +=['cvasp.py']
632659

633660
path_md = work_dir
634661
path_md = os.path.abspath(path_md)
@@ -694,7 +721,7 @@ def gen_init_bulk(args) :
694721

695722
if args.MACHINE is not None:
696723
# Selecting a proper machine
697-
mdata = decide_fp_machine(mdata)
724+
mdata = convert_mdata(mdata, ["fp"])
698725
#disp = make_dispatcher(mdata["fp_machine"])
699726

700727
# Decide work path
@@ -757,9 +784,12 @@ def gen_init_bulk(args) :
757784
pert_scaled(jdata)
758785
elif stage == 3 :
759786
dlog.info("Current stage is 3, run a short md")
760-
make_vasp_md(jdata)
761787
if args.MACHINE is not None:
788+
make_vasp_md(jdata, mdata)
762789
run_vasp_md(jdata, mdata)
790+
else:
791+
make_vasp_md(jdata, {"fp_resources":{}})
792+
763793
elif stage == 4 :
764794
dlog.info("Current stage is 4, collect data")
765795
coll_vasp_md(jdata)

dpgen/data/surf.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
import dpgen.data.tools.bcc as bcc
1212
from dpgen import dlog
1313
from dpgen import ROOT_PATH
14-
from dpgen.remote.decide_machine import decide_fp_machine
14+
from dpgen.remote.decide_machine import convert_mdata
1515
from dpgen.dispatcher.Dispatcher import Dispatcher, make_dispatcher
1616
#-----PMG---------
1717
from pymatgen.io.vasp import Poscar
@@ -596,7 +596,7 @@ def gen_init_surf(args):
596596

597597
if args.MACHINE is not None:
598598
# Decide a proper machine
599-
mdata = decide_fp_machine(mdata)
599+
mdata = convert_mdata(mdata, ["fp"])
600600
# disp = make_dispatcher(mdata["fp_machine"])
601601

602602
#stage = args.STAGE

dpgen/generator/ch4/machine.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@
2121
"_comment": "that's all"
2222
},
2323

24-
"lmp_command": "/sharedext4/softwares/lammps/bin/lmp_serial",
24+
"model_devi_command": "/sharedext4/softwares/lammps/bin/lmp_serial",
2525
"model_devi_group_size": 1,
2626
"_comment": "model_devi on localhost",
2727
"model_devi_machine": {

dpgen/generator/lib/utils.py

Lines changed: 35 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
#!/usr/bin/env python3
22

33
import os, re, shutil, logging
4+
import glob
45

56
iter_format = "%06d"
67
task_format = "%02d"
@@ -60,4 +61,37 @@ def log_task (message) :
6061

6162
def record_iter (record, ii, jj) :
6263
with open (record, "a") as frec :
63-
frec.write ("%d %d\n" % (ii, jj))
64+
frec.write ("%d %d\n" % (ii, jj))
65+
66+
def symlink_user_forward_files(mdata, task_type, work_path, task_format = None):
67+
'''
68+
Symlink user-defined forward_common_files
69+
Current path should be work_path, such as 00.train
70+
71+
Parameters
72+
---------
73+
mdata : dict
74+
machine parameters
75+
task_type: str
76+
task_type, such as "train"
77+
work_path : str
78+
work_path, such as "iter.000001/00.train"
79+
Returns
80+
-------
81+
None
82+
'''
83+
user_forward_files = mdata.get(task_type + "_" + "user_forward_files", [])
84+
#Angus: In the future, we may unify the task format.
85+
if task_format is None:
86+
task_format = {"train" : "0*", "model_devi" : "task.*", "fp": "task.*"}
87+
#"init_relax" : "sys-*", "init_md" : "sys-*/scale*/00*"
88+
for file in user_forward_files:
89+
assert os.path.isfile(file) ,\
90+
"user_forward_file %s of %s stage doesn't exist. " % (file, task_type)
91+
tasks = glob.glob(os.path.join(work_path, task_format[task_type]))
92+
for task in tasks:
93+
if os.path.isfile(os.path.join(task, os.path.basename(file))):
94+
os.remove(os.path.join(task, os.path.basename(file)))
95+
os.symlink(file, os.path.join(task, os.path.basename(file)))
96+
return
97+

0 commit comments

Comments
 (0)