Skip to content

Commit 34f1acd

Browse files
Merge pull request #77 from deepmodeling/devel-1.2.0
1.2.6
2 parents c8deba1 + 8128758 commit 34f1acd

File tree

17 files changed

+123
-80
lines changed

17 files changed

+123
-80
lines changed

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,9 @@
1818
* Modify the single-step run command from `test` to `do` for improved clarity and consistencey
1919

2020
## APEX Bohrium App
21-
[![](https://img.shields.io/badge/APP-BohriumApp-orange.svg)](https://app.bohrium.dp.tech/apex/)
21+
[![](https://img.shields.io/badge/APP-BohriumApp-orange.svg)](https://bohrium.dp.tech/apps/apex)
2222

23-
APEX also provides a web-based [Bohrium App](https://app.bohrium.dp.tech/apex/) for rapid and easy alloy property calculations without intensive JSON configuration (Note: one will need a Bohrium account to access this service).
23+
APEX also provides a web-based [Bohrium App](https://bohrium.dp.tech/apps/apex) for rapid and easy alloy property calculations without intensive JSON configuration (Note: one will need a Bohrium account to access this service).
2424

2525
## How to cite APEX
2626
[![](https://img.shields.io/badge/DOI-10.48550/arXiv.2404.17330-red.svg)](https://doi.org/10.48550/arXiv.2404.17330)

apex/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import os
2-
__version__ = '1.2.0'
2+
__version__ = '1.2.6'
33
LOCAL_PATH = os.getcwd()
44

55

apex/config.py

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,8 @@ class Config:
2929
email: str = None
3030
password: str = None
3131
program_id: int = None
32+
job_type: str = "container"
33+
platform: str = "ali"
3234

3335
# DispachterExecutor config
3436
dispatcher_config: dict = None
@@ -108,8 +110,8 @@ def __post_init__(self):
108110
"password": self.password,
109111
"program_id": self.program_id,
110112
"input_data": {
111-
"job_type": "container",
112-
"platform": "ali",
113+
"job_type": self.job_type,
114+
"platform": self.platform,
113115
"scass_type": self.scass_type,
114116
},
115117
},
@@ -280,7 +282,7 @@ def get_executor(
280282
self,
281283
dispatcher_config: dict
282284
) -> DispatcherExecutor:
283-
if not (self.context_type or self.machine):
285+
if not (self.context_type or self.machine or self.dispatcher_config):
284286
executor = None
285287
else:
286288
# get arguments for instantiation of the DispatcherExecutor

apex/core/common_equi.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -189,7 +189,11 @@ def post_equi(confs, inter_param):
189189
inter = make_calculator(inter_param, poscar)
190190
res = inter.compute(ii)
191191
contcar = os.path.join(ii, "CONTCAR")
192-
ss = Structure.from_file(contcar)
192+
try:
193+
ss = Structure.from_file(contcar)
194+
except FileNotFoundError:
195+
logging.warning(f"No CONTCAR found in {ii}, skip")
196+
continue
193197
st = StructureInfo(ss)
194198
struct_info_dict = {
195199
"space_group_symbol": st.space_group_symbol,

apex/core/property/EOS.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ def __init__(self, parameter, inter_param=None):
5858
def make_confs(self, path_to_work, path_to_equi, refine=False):
5959
path_to_work = os.path.abspath(path_to_work)
6060
if os.path.exists(path_to_work):
61-
logging.warning("%s already exists" % path_to_work)
61+
logging.debug("%s already exists" % path_to_work)
6262
else:
6363
os.makedirs(path_to_work)
6464
path_to_equi = os.path.abspath(path_to_equi)

apex/core/property/Elastic.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ def __init__(self, parameter, inter_param=None):
5555
def make_confs(self, path_to_work, path_to_equi, refine=False):
5656
path_to_work = os.path.abspath(path_to_work)
5757
if os.path.exists(path_to_work):
58-
logging.warning("%s already exists" % path_to_work)
58+
logging.debug("%s already exists" % path_to_work)
5959
else:
6060
os.makedirs(path_to_work)
6161
path_to_equi = os.path.abspath(path_to_equi)

apex/core/property/Gamma.py

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@ def __init__(self, parameter, inter_param=None):
8282
def make_confs(self, path_to_work, path_to_equi, refine=False):
8383
path_to_work = os.path.abspath(path_to_work)
8484
if os.path.exists(path_to_work):
85-
logging.warning("%s already exists" % path_to_work)
85+
logging.debug("%s already exists" % path_to_work)
8686
else:
8787
os.makedirs(path_to_work)
8888
path_to_equi = os.path.abspath(path_to_equi)
@@ -247,11 +247,9 @@ def make_confs(self, path_to_work, path_to_equi, refine=False):
247247
os.remove(jj)
248248
task_list.append(output_task)
249249
# print("# %03d generate " % ii, output_task)
250-
print(
251-
"# %03d generate " % count,
252-
output_task,
253-
" \t %d atoms" % len(obtained_slab.sites)
254-
)
250+
251+
logging.info(f"# {count} generate {output_task}, with{len(obtained_slab.sites)} atoms")
252+
255253
# make confs
256254
obtained_slab.to("POSCAR.tmp", "POSCAR")
257255
vasp_utils.regulate_poscar("POSCAR.tmp", "POSCAR")

apex/core/property/Interstitial.py

Lines changed: 55 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,10 @@
99
from monty.serialization import dumpfn, loadfn
1010
from pymatgen.analysis.defects.generators import VoronoiInterstitialGenerator
1111
from pymatgen.analysis.defects.core import Interstitial as pmgInterstitial
12-
from pymatgen.core.structure import Structure
12+
from pymatgen.core.structure import Structure, Lattice
1313
from pymatgen.core.sites import PeriodicSite
14+
from pymatgen.core.tensors import Tensor
15+
from pymatgen.core.operations import SymmOp
1416

1517
from apex.core.calculator.lib import abacus_utils
1618
from apex.core.calculator.lib import lammps_utils
@@ -23,6 +25,7 @@
2325
upload_packages.append(__file__)
2426

2527
PREDEFINED_LIST = ['bcc', 'fcc', 'hcp']
28+
TOL = 1e-5
2629

2730
class Interstitial(Property):
2831
def __init__(self, parameter, inter_param=None):
@@ -33,7 +36,7 @@ def __init__(self, parameter, inter_param=None):
3336
default_supercell = [1, 1, 1]
3437
parameter["supercell"] = parameter.get("supercell", default_supercell)
3538
self.supercell = parameter["supercell"]
36-
self.insert_ele = parameter["insert_ele"]
39+
self.insert_ele = parameter.get("insert_ele", None)
3740
parameter["lattice_type"] = parameter.get("lattice_type", None)
3841
self.lattice_type = parameter["lattice_type"]
3942
parameter["voronoi_param"] = parameter.get("voronoi_param", {})
@@ -64,7 +67,7 @@ def __init__(self, parameter, inter_param=None):
6467
def make_confs(self, path_to_work, path_to_equi, refine=False):
6568
self.path_to_work = os.path.abspath(path_to_work)
6669
if os.path.exists(path_to_work):
67-
logging.warning("%s already exists" % path_to_work)
70+
logging.debug("%s already exists" % path_to_work)
6871
else:
6972
os.makedirs(path_to_work)
7073
path_to_equi = os.path.abspath(path_to_equi)
@@ -157,7 +160,9 @@ def make_confs(self, path_to_work, path_to_equi, refine=False):
157160
ss = abacus_utils.stru2Structure(equi_contcar)
158161
else:
159162
ss = Structure.from_file(equi_contcar)
160-
163+
rot = Tensor.get_ieee_rotation(ss)
164+
op = SymmOp.from_rotation_and_translation(rot)
165+
ss.apply_operation(op)
161166
# get structure type
162167
os.chdir(self.path_to_work)
163168
# convert site element into same type for a pseudo-structure just for simple lattice type judgment
@@ -171,6 +176,7 @@ def make_confs(self, path_to_work, path_to_equi, refine=False):
171176
orig_st = StructureInfo(ss, symprec=0.1, angle_tolerance=5)
172177
conv_ss = orig_st.conventional_structure
173178
conv_ss.to("POSCAR", "POSCAR")
179+
conv_ss.to("POSCAR_conv", "POSCAR")
174180
ss = conv_ss
175181
if self.lattice_type:
176182
print(f'Adopt user indicated lattice type: {self.lattice_type}')
@@ -182,8 +188,31 @@ def make_confs(self, path_to_work, path_to_equi, refine=False):
182188
self.insert_element_task = os.path.join(self.path_to_work, "element.out")
183189
if os.path.isfile(self.insert_element_task):
184190
os.remove(self.insert_element_task)
191+
if not self.insert_ele:
192+
self.insert_ele = [str(ii) for ii in set(ss.composition.elements)]
185193
for ii in self.insert_ele:
186194
if self.structure_type in PREDEFINED_LIST:
195+
# rotate and translate hcp structure to specific orientation for interstitial generation
196+
if self.structure_type == 'hcp':
197+
theta = -2 * np.pi / 3
198+
rot_m = np.array([
199+
[np.cos(theta), -np.sin(theta), 0],
200+
[np.sin(theta), np.cos(theta), 0],
201+
[0, 0, 1]
202+
])
203+
op = SymmOp.from_rotation_and_translation(rotation_matrix=rot_m)
204+
ss.apply_operation(op)
205+
new_lattice = Lattice([
206+
ss.lattice.matrix[0] * -1, ss.lattice.matrix[1] * -1, ss.lattice.matrix[2]
207+
])
208+
new_frac_coords = ss.frac_coords.copy()
209+
if not ((new_frac_coords[0][0] < 0.5 and new_frac_coords[0][2] < 0.5)\
210+
or (new_frac_coords[0][0] > 0.5 and new_frac_coords[0][2] > 0.5)):
211+
new_frac_coords[0][2] = ss.frac_coords[1][2]
212+
new_frac_coords[1][2] = ss.frac_coords[0][2]
213+
new_ss = Structure(new_lattice, ss.species, new_frac_coords, coords_are_cartesian=False)
214+
ss = new_ss
215+
ss.to(os.path.join(self.path_to_work, 'POSCAR_conv'), 'POSCAR')
187216
# produce a pseudo interstitial structure for later modification
188217
vds = [pmgInterstitial(ss, PeriodicSite(ii, [0.12, 0.13, 0.14], ss.lattice))]
189218
else:
@@ -250,10 +279,11 @@ def make_confs(self, path_to_work, path_to_equi, refine=False):
250279

251280
# create pre-defined special SIA structure for bcc fcc and hcp
252281
if self.structure_type in PREDEFINED_LIST:
282+
self.task_list = []
253283
if not os.path.isfile("task.000000/POSCAR"):
254284
raise RuntimeError("need task.000000 structure as reference")
255285

256-
with open('POSCAR', "r") as fin:
286+
with open('POSCAR_conv', "r") as fin:
257287
fin.readline()
258288
scale = float(fin.readline().split()[0])
259289
self.latt_param = float(fin.readline().split()[0])
@@ -266,13 +296,12 @@ def make_confs(self, path_to_work, path_to_equi, refine=False):
266296
ss = ii.split()
267297
if len(ss) > 3:
268298
if (
269-
abs(0.12 / self.supercell[0] - float(ss[0])) < 1e-5
270-
and abs(0.13 / self.supercell[1] - float(ss[1])) < 1e-5
271-
and abs(0.14 / self.supercell[2] - float(ss[2])) < 1e-5
299+
abs(0.12 / self.supercell[0] - float(ss[0])) < TOL
300+
and abs(0.13 / self.supercell[1] - float(ss[1])) < TOL
301+
and abs(0.14 / self.supercell[2] - float(ss[2])) < TOL
272302
):
273303
chl = idx
274-
# pseudo-task only run original POSCAR to save calculation resources
275-
shutil.copyfile("POSCAR", "task.000000/POSCAR")
304+
shutil.rmtree("task.000000")
276305

277306
os.chdir(cwd)
278307
# specify interstitial structures
@@ -281,9 +310,9 @@ def make_confs(self, path_to_work, path_to_equi, refine=False):
281310
ss = ii.split()
282311
if len(ss) > 3:
283312
if (
284-
abs(0.5 / self.supercell[0] - float(ss[0])) < 1e-5
285-
and abs(0.5 / self.supercell[1] - float(ss[1])) < 1e-5
286-
and abs(0.5 / self.supercell[2] - float(ss[2])) < 1e-5
313+
abs(0.5 / self.supercell[0] - float(ss[0])) < TOL
314+
and abs(0.5 / self.supercell[1] - float(ss[1])) < TOL
315+
and abs(0.5 / self.supercell[2] - float(ss[2])) < TOL
287316
):
288317
center = idx
289318
bcc_interstital_dict = {
@@ -304,16 +333,16 @@ def make_confs(self, path_to_work, path_to_equi, refine=False):
304333
ss = ii.split()
305334
if len(ss) > 3:
306335
if (
307-
abs(1 / self.supercell[0] - float(ss[0])) < 1e-5
308-
and abs(0.5 / self.supercell[1] - float(ss[1])) < 1e-5
309-
and abs(0.5 / self.supercell[2] - float(ss[2])) < 1e-5
336+
abs(1 / self.supercell[0] - float(ss[0])) < TOL
337+
and abs(0.5 / self.supercell[1] - float(ss[1])) < TOL
338+
and abs(0.5 / self.supercell[2] - float(ss[2])) < TOL
310339
):
311340
face = idx
312341

313342
if (
314-
abs(1 / self.supercell[0] - float(ss[0])) < 1e-5
315-
and abs(1 / self.supercell[1] - float(ss[1])) < 1e-5
316-
and abs(1 / self.supercell[2] - float(ss[2])) < 1e-5
343+
abs(1 / self.supercell[0] - float(ss[0])) < TOL
344+
and abs(1 / self.supercell[1] - float(ss[1])) < TOL
345+
and abs(1 / self.supercell[2] - float(ss[2])) < TOL
317346
):
318347
corner = idx
319348

@@ -349,9 +378,9 @@ def make_confs(self, path_to_work, path_to_equi, refine=False):
349378
ss = ii.split()
350379
if len(ss) > 3:
351380
if (
352-
abs(1/3 / self.supercell[0] - float(ss[0])) < 1e-5
353-
and abs(2/3 / self.supercell[1] - float(ss[1])) < 1e-5
354-
and abs(0.25 / self.supercell[2] - float(ss[2])) < 1e-5
381+
abs(1/3 / self.supercell[0] - float(ss[0])) < TOL
382+
and abs(2/3 / self.supercell[1] - float(ss[1])) < TOL
383+
and abs(0.25 / self.supercell[2] - float(ss[2])) < TOL
355384
):
356385
center = idx
357386
hcp_interstital_dict = {
@@ -387,7 +416,7 @@ def __gen_tasks(self, interstitial_dict):
387416
cwd = os.getcwd()
388417
for ii, (type_str, adjust_dict) in enumerate(interstitial_dict.items()):
389418
output_task = os.path.join(
390-
self.path_to_work, "task.%06d" % (len(self.dss) + ii)
419+
self.path_to_work, "task.%06d" % (len(self.dss) + ii - 1)
391420
)
392421
os.makedirs(output_task, exist_ok=True)
393422
os.chdir(output_task)
@@ -414,10 +443,11 @@ def __gen_tasks(self, interstitial_dict):
414443
print(f"gen {type_str}")
415444
os.chdir(cwd)
416445

417-
total_task = len(self.dss) + len(interstitial_dict)
446+
total_task = len(self.dss) + len(interstitial_dict) - 1
418447

419448
return total_task
420449

450+
421451
def post_process(self, task_list):
422452
if True:
423453
fin1 = open(os.path.join(task_list[0], "..", "element.out"), "r")
@@ -472,7 +502,7 @@ def _compute_lower(self, output_file, all_tasks, all_res):
472502
equi_result = loadfn(os.path.join(equi_path, "result.json"))
473503
equi_epa = equi_result["energies"][-1] / sum(equi_result["atom_numbs"])
474504

475-
for idid, ii in enumerate(all_tasks[1:], start=1): # skip task.000000
505+
for idid, ii in enumerate(all_tasks, start=0): # skip task.000000
476506
structure_dir = os.path.basename(ii)
477507
task_result = loadfn(all_res[idid])
478508
interstitial_type = loadfn(os.path.join(ii, 'interstitial_type.json'))

apex/core/property/Phonon.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@ def __init__(self, parameter, inter_param=None):
8282
def make_confs(self, path_to_work, path_to_equi, refine=False):
8383
path_to_work = os.path.abspath(path_to_work)
8484
if os.path.exists(path_to_work):
85-
logging.warning("%s already exists" % path_to_work)
85+
logging.debug("%s already exists" % path_to_work)
8686
else:
8787
os.makedirs(path_to_work)
8888
path_to_equi = os.path.abspath(path_to_equi)

apex/core/property/Surface.py

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ def __init__(self, parameter, inter_param=None):
6060
def make_confs(self, path_to_work, path_to_equi, refine=False):
6161
path_to_work = os.path.abspath(path_to_work)
6262
if os.path.exists(path_to_work):
63-
logging.warning("%s already exists" % path_to_work)
63+
logging.debug("%s already exists" % path_to_work)
6464
else:
6565
os.makedirs(path_to_work)
6666
path_to_equi = os.path.abspath(path_to_equi)
@@ -174,11 +174,9 @@ def make_confs(self, path_to_work, path_to_equi, refine=False):
174174
if os.path.exists(jj):
175175
os.remove(jj)
176176
task_list.append(output_task)
177-
print(
178-
"# %03d generate " % ii,
179-
output_task,
180-
" \t %d atoms" % len(all_slabs[ii].sites),
181-
)
177+
178+
logging.info(f"{ii} generate {output_task} {len(all_slabs[ii].sites)} atoms")
179+
182180
# make confs
183181
all_slabs[ii].to("POSCAR.tmp", "POSCAR")
184182
vasp_utils.regulate_poscar("POSCAR.tmp", "POSCAR")

0 commit comments

Comments
 (0)