ion-CSP 2.0.2__py3-none-any.whl → 2.0.4__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- ion_CSP/__main__.py +5 -0
- ion_CSP/gen_opt.py +1 -1
- ion_CSP/identify_molecules.py +3 -3
- ion_CSP/task_manager.py +396 -0
- ion_CSP/vasp_processing.py +3 -3
- ion_csp-2.0.4.dist-info/METADATA +236 -0
- ion_csp-2.0.4.dist-info/RECORD +19 -0
- {ion_csp-2.0.2.dist-info → ion_csp-2.0.4.dist-info}/WHEEL +1 -1
- ion_csp-2.0.4.dist-info/entry_points.txt +2 -0
- ion_CSP/app.py +0 -201
- ion_csp-2.0.2.dist-info/METADATA +0 -83
- ion_csp-2.0.2.dist-info/RECORD +0 -18
- ion_csp-2.0.2.dist-info/entry_points.txt +0 -2
- {ion_csp-2.0.2.dist-info → ion_csp-2.0.4.dist-info}/licenses/LICENSE +0 -0
- {ion_csp-2.0.2.dist-info → ion_csp-2.0.4.dist-info}/top_level.txt +0 -0
ion_CSP/__main__.py
ADDED
ion_CSP/gen_opt.py
CHANGED
@@ -238,7 +238,7 @@ class CrystalGenerator:
|
|
238
238
|
# 如果在本地运行作业,则只在后续创建一级目录
|
239
239
|
parent = ""
|
240
240
|
# 如果是本地运行,则根据显存占用率阈值,等待可用的GPU
|
241
|
-
selected_gpu = wait_for_gpu(memory_percent_threshold=
|
241
|
+
selected_gpu = wait_for_gpu(memory_percent_threshold=40, wait_time=600)
|
242
242
|
os.environ["CUDA_VISIBLE_DEVICES"] = str(selected_gpu)
|
243
243
|
|
244
244
|
from dpdispatcher import Resources, Task, Submission
|
ion_CSP/identify_molecules.py
CHANGED
@@ -75,12 +75,12 @@ def molecules_information(molecules: List[Dict[str, int]], molecules_flag: bool,
|
|
75
75
|
output = []
|
76
76
|
for element in fixed_order:
|
77
77
|
if element in molecule:
|
78
|
-
output.append(f"{element}
|
78
|
+
output.append(f"{element}{molecule[element]}")
|
79
79
|
# 如果有其他元素,添加到输出中
|
80
80
|
for element in molecule:
|
81
81
|
if element not in fixed_order:
|
82
|
-
output.append(f"{element}
|
83
|
-
formatted_output =
|
82
|
+
output.append(f"{element}{molecule[element]}")
|
83
|
+
formatted_output = ''.join(output)
|
84
84
|
logging.info(f' Molecule {idx + 1} (Total Atoms: {total_atoms}, Count: {count}): {formatted_output}')
|
85
85
|
if molecules_flag:
|
86
86
|
logging.info('Molecular Comparison Successful\n')
|
ion_CSP/task_manager.py
ADDED
@@ -0,0 +1,396 @@
|
|
1
|
+
import os
|
2
|
+
import re
|
3
|
+
import sys
|
4
|
+
import time
|
5
|
+
import psutil
|
6
|
+
import logging
|
7
|
+
import subprocess
|
8
|
+
import importlib.util
|
9
|
+
from pathlib import Path
|
10
|
+
|
11
|
+
|
12
|
+
class TaskManager:
|
13
|
+
"""任务管理器类 - Manages task execution and monitoring"""
|
14
|
+
|
15
|
+
def __init__(self):
|
16
|
+
"""初始化任务管理器 - Initialize task manager"""
|
17
|
+
self.env = "LOCAL"
|
18
|
+
self.project_root = os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
|
19
|
+
self.workspace = Path.cwd()
|
20
|
+
self.log_base = "logs"
|
21
|
+
self.log_dir = self.workspace / self.log_base
|
22
|
+
self.version = self._get_version()
|
23
|
+
self._detect_env()
|
24
|
+
self._setup_logging()
|
25
|
+
|
26
|
+
def __repr__(self):
|
27
|
+
return f"Taskmanager(version={self.version}, env={self.env}, project_root={self.project_root}, workspace={self.workspace}, log_base={self.log_base}, log_dir={self.log_dir})"
|
28
|
+
|
29
|
+
def _get_version(self):
|
30
|
+
"""版本获取"""
|
31
|
+
try:
|
32
|
+
# 使用 importlib 动态加载
|
33
|
+
spec = importlib.util.spec_from_file_location(
|
34
|
+
"ion_CSP",
|
35
|
+
os.path.join(self.project_root, "src/__init__.py")
|
36
|
+
)
|
37
|
+
module = importlib.util.module_from_spec(spec)
|
38
|
+
spec.loader.exec_module(module)
|
39
|
+
return module.__version__
|
40
|
+
except Exception as e:
|
41
|
+
logging.error(f"Version detection failed: {e}")
|
42
|
+
return "unknown"
|
43
|
+
|
44
|
+
def _detect_env(self):
|
45
|
+
"""检测运行环境 - Detect execution environment"""
|
46
|
+
if Path("/.dockerenv").exists() or "DOCKER" in os.environ:
|
47
|
+
self.env = "DOCKER"
|
48
|
+
self.workspace = Path("/app")
|
49
|
+
self.log_dir = Path("/app/logs")
|
50
|
+
self.workspace.mkdir(exist_ok=True)
|
51
|
+
|
52
|
+
def _setup_logging(self):
|
53
|
+
"""配置日志系统 - Configure logging system"""
|
54
|
+
self.log_dir = self.workspace / self.log_base
|
55
|
+
self.log_dir.mkdir(parents=True, exist_ok=True)
|
56
|
+
logging.basicConfig(
|
57
|
+
level=logging.INFO,
|
58
|
+
format="%(asctime)s - %(levelname)s - %(message)s",
|
59
|
+
handlers=[
|
60
|
+
logging.FileHandler(self.log_dir / "system.log"),
|
61
|
+
logging.StreamHandler(),
|
62
|
+
],
|
63
|
+
)
|
64
|
+
|
65
|
+
def _cleanup_task_files(self, module: str, pid: int):
|
66
|
+
"""清理任务相关文件"""
|
67
|
+
log_file = self.log_dir / f"{module}_{pid}.log"
|
68
|
+
if log_file.exists():
|
69
|
+
log_file.unlink()
|
70
|
+
print(f"Cleaned up orphaned log: {log_file.name}")
|
71
|
+
|
72
|
+
def _safe_kill(self, module: str, pid: int):
|
73
|
+
"""安全终止进程并清理残留资源 - Safely kill process and cleanup orphan resources"""
|
74
|
+
try:
|
75
|
+
proc = psutil.Process(pid)
|
76
|
+
# 先尝试优雅终止并等待进程推出
|
77
|
+
proc.terminate()
|
78
|
+
print(f"Termination signal sent to PID {pid}")
|
79
|
+
|
80
|
+
# 正确处理进程退出状态
|
81
|
+
try:
|
82
|
+
exit_code = proc.wait(timeout=5)
|
83
|
+
print(f"PID {pid} exited with code {exit_code}")
|
84
|
+
exit_code = 0 # 正常退出
|
85
|
+
except psutil.TimeoutExpired:
|
86
|
+
print(f"PID {pid} did not exit gracefully, forcing termination...")
|
87
|
+
proc.kill()
|
88
|
+
exit_code = -1 # 强制终止标记
|
89
|
+
# 清理残留文件
|
90
|
+
self._cleanup_task_files(module, pid)
|
91
|
+
input("\nPress Enter to continue...")
|
92
|
+
return exit_code
|
93
|
+
|
94
|
+
except (psutil.NoSuchProcess, psutil.AccessDenied):
|
95
|
+
print(f"PID {pid} already terminated")
|
96
|
+
self._cleanup_task_files(module, pid)
|
97
|
+
input("\nPress Enter to continue...")
|
98
|
+
return -2 # 进程不存在标记
|
99
|
+
except Exception as e:
|
100
|
+
print(f"Error terminating process: {str(e)}")
|
101
|
+
input("\nPress Enter to continue...")
|
102
|
+
return -3 # 其他错误标记
|
103
|
+
|
104
|
+
def _is_pid_running(self, pid: int):
|
105
|
+
"""检查进程是否仍在运行 - Check the process status according to PID"""
|
106
|
+
try:
|
107
|
+
proc = psutil.Process(pid)
|
108
|
+
return proc.status() in (psutil.STATUS_RUNNING, psutil.STATUS_SLEEPING)
|
109
|
+
except psutil.NoSuchProcess:
|
110
|
+
return False
|
111
|
+
|
112
|
+
def _is_valid_task_pid(self, pid: int):
|
113
|
+
"""验证PID是否属于当前程序的任务进程 - Valid the task PID according to log file"""
|
114
|
+
try:
|
115
|
+
proc = psutil.Process(pid)
|
116
|
+
cmdline = " ".join(proc.cmdline())
|
117
|
+
|
118
|
+
# 检查模块标识和Python环境
|
119
|
+
return "python" in proc.name().lower() and (
|
120
|
+
"main_CSP" in cmdline or "main_EE" in cmdline
|
121
|
+
)
|
122
|
+
except (psutil.NoSuchProcess, psutil.AccessDenied):
|
123
|
+
return False
|
124
|
+
|
125
|
+
def _display_tasks(self, tasks, total, current_page, total_pages, function):
|
126
|
+
"""标准化任务显示 - Standardized tasks display"""
|
127
|
+
display = "logs" if function == "view" else "tasks"
|
128
|
+
print(f"\033cPage {current_page}/{total_pages} ({total} {display})")
|
129
|
+
if function == "kill":
|
130
|
+
for i, task in enumerate(tasks, 1):
|
131
|
+
print(
|
132
|
+
f"{i:3}) [{task['module']}] PID:{task['pid']:5} [{task['status']}] - {task['real_log']}"
|
133
|
+
)
|
134
|
+
elif function == "view":
|
135
|
+
for i, task in enumerate(tasks, 1):
|
136
|
+
print(
|
137
|
+
f"{i:3}) [{task['module']}] - {task['real_log']}"
|
138
|
+
)
|
139
|
+
else:
|
140
|
+
raise ValueError(f"Not supported function {function}. Available function: 'view' and 'kill' ")
|
141
|
+
print("\nPage {} of {}".format(current_page, total_pages))
|
142
|
+
# 分页控制
|
143
|
+
print("\nOptions:")
|
144
|
+
if function == "view":
|
145
|
+
print("n) Next page | p) Previous page | f) Filter | q) Quit")
|
146
|
+
elif function == "kill":
|
147
|
+
print("n) Next page | p) Previous page | f) Filter | k) Kill | q) Quit")
|
148
|
+
else:
|
149
|
+
raise ValueError("Unexpected function parameter")
|
150
|
+
|
151
|
+
def _paginate_tasks(self, tasks, function, page_size=10):
|
152
|
+
"""通用分页函数 - Universal tasks pagination"""
|
153
|
+
total = len(tasks)
|
154
|
+
pages = (total + page_size - 1) // page_size
|
155
|
+
current_page = 0
|
156
|
+
filter_bool = False
|
157
|
+
|
158
|
+
while True:
|
159
|
+
start = current_page * page_size
|
160
|
+
end = start + page_size
|
161
|
+
page_tasks = tasks[start:end]
|
162
|
+
if not filter_bool:
|
163
|
+
# 显示当前页内容
|
164
|
+
self._display_tasks(page_tasks, total, current_page+1, pages, function)
|
165
|
+
|
166
|
+
choice = input().strip().upper()
|
167
|
+
if choice == 'N' and current_page < pages-1:
|
168
|
+
current_page += 1
|
169
|
+
elif choice == 'P' and current_page > 0:
|
170
|
+
current_page -= 1
|
171
|
+
elif function == "kill" and choice == "K":
|
172
|
+
try:
|
173
|
+
task_num = input("Enter task number to kill: ").strip()
|
174
|
+
if not task_num.isdigit():
|
175
|
+
raise ValueError
|
176
|
+
# 计算全局任务索引
|
177
|
+
global_index = current_page * 10 + (int(task_num) - 1)
|
178
|
+
if 0 <= global_index < len(tasks):
|
179
|
+
selected_index = global_index
|
180
|
+
confirm = input(
|
181
|
+
f"Confirm termination of {tasks[selected_index]['module']} PID {tasks[selected_index]['pid']}? (y/n): "
|
182
|
+
).lower()
|
183
|
+
if confirm == "y":
|
184
|
+
self._safe_kill(
|
185
|
+
module=tasks[selected_index]["module"],
|
186
|
+
pid=tasks[selected_index]["pid"],
|
187
|
+
)
|
188
|
+
break
|
189
|
+
else:
|
190
|
+
print("Invalid task number")
|
191
|
+
input("\nPress Enter to continue...")
|
192
|
+
except ValueError:
|
193
|
+
print("Please enter a valid number")
|
194
|
+
input("\nPress Enter to continue...")
|
195
|
+
elif function == "view" and choice.isdigit():
|
196
|
+
# 计算全局任务索引
|
197
|
+
global_index = current_page * 10 + (int(choice) - 1)
|
198
|
+
if 0 <= global_index < len(tasks):
|
199
|
+
selected_index = global_index
|
200
|
+
os.system(f"less {tasks[selected_index]['real_log']}")
|
201
|
+
else:
|
202
|
+
print("Invalid selection")
|
203
|
+
input("\nPress Enter to continue...")
|
204
|
+
elif choice == 'Q':
|
205
|
+
break
|
206
|
+
elif choice == 'F':
|
207
|
+
filter_module = input("Please enter a valid module name (CSP or EE)\n")
|
208
|
+
if filter_module in ("CSP", "EE"):
|
209
|
+
self.view_filtered_tasks(filter_module, function)
|
210
|
+
break
|
211
|
+
else:
|
212
|
+
print("Invalid task number")
|
213
|
+
input("\nPress Enter to continue...")
|
214
|
+
else:
|
215
|
+
print("Invalid command")
|
216
|
+
input("\nPress Enter to continue...")
|
217
|
+
|
218
|
+
def task_runner(self, module: str, work_dir: str):
|
219
|
+
"""任务执行器 - Task execution handler"""
|
220
|
+
work_dir = Path(work_dir)
|
221
|
+
work_dir.mkdir(exist_ok=True)
|
222
|
+
|
223
|
+
console_log = work_dir / f"main_{module}_console.log"
|
224
|
+
pid_file = work_dir / "pid.txt"
|
225
|
+
|
226
|
+
# 启动子进程
|
227
|
+
cmd = ["python", "-m", f"src.main_{module}", str(work_dir)]
|
228
|
+
|
229
|
+
with open(console_log, "w") as f:
|
230
|
+
process = subprocess.Popen(
|
231
|
+
cmd,
|
232
|
+
stdout=f,
|
233
|
+
stderr=subprocess.STDOUT,
|
234
|
+
preexec_fn=os.setsid if os.name != "nt" else None,
|
235
|
+
)
|
236
|
+
|
237
|
+
# 等待PID文件创建
|
238
|
+
time.sleep(1)
|
239
|
+
try:
|
240
|
+
with open(pid_file, "w") as f:
|
241
|
+
f.write(str(process.pid))
|
242
|
+
except Exception as e:
|
243
|
+
logging.error(f"Error writing PID file: {e}")
|
244
|
+
process.terminate()
|
245
|
+
return
|
246
|
+
# 创建符号链接
|
247
|
+
output_log = work_dir / f"main_{module}.py_output.log"
|
248
|
+
print(f"Original log file: {output_log}")
|
249
|
+
std_log = Path(self.log_dir) / f"{module}_{process.pid}.log"
|
250
|
+
try:
|
251
|
+
output_log = output_log.resolve()
|
252
|
+
std_log.symlink_to(output_log)
|
253
|
+
os.remove(pid_file)
|
254
|
+
except FileExistsError:
|
255
|
+
os.remove(std_log)
|
256
|
+
std_log.symlink_to(output_log)
|
257
|
+
|
258
|
+
logging.info(f"Started {module} module (PID: {process.pid})")
|
259
|
+
print(f"Task started (PID: {process.pid})")
|
260
|
+
print(f"Normalized log file: {std_log}")
|
261
|
+
|
262
|
+
def view_logs(self, page_size: int = 10):
|
263
|
+
"""查看日志 - View task logs"""
|
264
|
+
log_tasks = []
|
265
|
+
log_pattern = re.compile(r"(CSP|EE)_\d+$") # 正则匹配规范文件名
|
266
|
+
for log_file in self.log_dir.glob("**/*.log"):
|
267
|
+
if not log_pattern.match(log_file.stem):
|
268
|
+
continue
|
269
|
+
try:
|
270
|
+
file_path = log_file.resolve(strict=True)
|
271
|
+
mtime = file_path.stat().st_mtime
|
272
|
+
log_tasks.append({
|
273
|
+
"pid": 0, # 日志无PID
|
274
|
+
"module": log_file.stem.split("_")[0].upper(),
|
275
|
+
"real_log": str(file_path),
|
276
|
+
"mtime": mtime,
|
277
|
+
"log_name": log_file.name,
|
278
|
+
"status": "Static"
|
279
|
+
})
|
280
|
+
except Exception as e:
|
281
|
+
logging.error(f"Error processing {log_file}: {e}")
|
282
|
+
continue
|
283
|
+
self._paginate_tasks(log_tasks, function="view", page_size=page_size)
|
284
|
+
|
285
|
+
def safe_terminate(self):
|
286
|
+
"""安全终止任务 - Safe task termination"""
|
287
|
+
tasks = self.get_related_tasks()
|
288
|
+
if not tasks:
|
289
|
+
print("No running tasks found")
|
290
|
+
input("\nPress Enter to continue...")
|
291
|
+
return
|
292
|
+
|
293
|
+
# 分页显示任务列表
|
294
|
+
filter_bool = False
|
295
|
+
while True:
|
296
|
+
print("\033c", end="") # 清屏指令
|
297
|
+
# 显示当前页任务
|
298
|
+
print(f"\nRunning tasks ({len(tasks)} in total):")
|
299
|
+
if not filter_bool:
|
300
|
+
self._paginate_tasks(tasks, function="kill")
|
301
|
+
break
|
302
|
+
|
303
|
+
def view_filtered_tasks(self, module_filter: str, function: str):
|
304
|
+
"""带分页的过滤任务显示"""
|
305
|
+
all_tasks = self.get_related_tasks()
|
306
|
+
filtered = [t for t in all_tasks if t["module"] == module_filter.upper()]
|
307
|
+
if not filtered:
|
308
|
+
print("No matching tasks found")
|
309
|
+
input("\nPress Enter to continue...")
|
310
|
+
return
|
311
|
+
print(f"\033cFiltered Tasks ({len(filtered)}):")
|
312
|
+
self._paginate_tasks(filtered, function) # 复用通用分页逻辑
|
313
|
+
|
314
|
+
def get_related_tasks(self):
|
315
|
+
"""获取实时任务列表并验证状态 - Get relatd tasks list and validate the status"""
|
316
|
+
tasks = []
|
317
|
+
log_pattern = re.compile(r"(CSP|EE)_\d+$") # 正则匹配规范文件名
|
318
|
+
|
319
|
+
for log_file in self.log_dir.glob("**/*.log"):
|
320
|
+
if not log_pattern.match(log_file.stem):
|
321
|
+
continue # 跳过非标准日志文件
|
322
|
+
try:
|
323
|
+
# 使用正则提取模块和PID
|
324
|
+
match = re.match(r"(CSP|EE)_(\d+)$", log_file.stem)
|
325
|
+
module = match.group(1).upper()
|
326
|
+
pid = int(match.group(2))
|
327
|
+
|
328
|
+
# 验证进程状态
|
329
|
+
if self._is_valid_task_pid(pid):
|
330
|
+
# 获取实际日志路径
|
331
|
+
real_log_path = str(log_file.resolve(strict=True))
|
332
|
+
# 获取文件修改时间戳
|
333
|
+
mtime = log_file.stat().st_mtime
|
334
|
+
status = "Running" if self._is_pid_running(pid) else "Terminated"
|
335
|
+
task_info = (
|
336
|
+
{
|
337
|
+
"pid": pid,
|
338
|
+
"module": module,
|
339
|
+
"real_log": real_log_path,
|
340
|
+
"mtime": mtime,
|
341
|
+
"status": status,
|
342
|
+
}
|
343
|
+
)
|
344
|
+
tasks.append(task_info)
|
345
|
+
except (ValueError, IndexError) as e:
|
346
|
+
logging.error(f"Error parsing log file {log_file}: {e}")
|
347
|
+
continue
|
348
|
+
# 按修改时间降序排列(最新在前)
|
349
|
+
tasks.sort(key=lambda t: t["mtime"], reverse=True)
|
350
|
+
return tasks
|
351
|
+
|
352
|
+
def main_menu(self):
|
353
|
+
"""主菜单循环 - Main menu loop"""
|
354
|
+
while True:
|
355
|
+
os.system("clear" if os.name == "posix" else "cls")
|
356
|
+
print("========== Task Execution Sys1tem ==========")
|
357
|
+
print(f"Current Version: {self.version}")
|
358
|
+
print(f"Current Environment: {self.env}")
|
359
|
+
print(f"Current Directory: {self.workspace}")
|
360
|
+
print(f"Log Base Directory: {self.log_dir}")
|
361
|
+
print("=" * 50)
|
362
|
+
print("1) Run EE Module")
|
363
|
+
print("2) Run CSP Module")
|
364
|
+
print("3) View Logs")
|
365
|
+
print("4) Terminate Tasks")
|
366
|
+
print("q) Exit")
|
367
|
+
print("=" * 50)
|
368
|
+
|
369
|
+
choice = input("Please enter operation: ").strip().lower()
|
370
|
+
if choice == "1":
|
371
|
+
work_dir = input("Enter EE working directory: ").strip()
|
372
|
+
self.task_runner("EE", work_dir)
|
373
|
+
input("\nPress Enter to continue...")
|
374
|
+
elif choice == "2":
|
375
|
+
work_dir = input("Enter CSP working directory: ").strip()
|
376
|
+
self.task_runner("CSP", work_dir)
|
377
|
+
input("\nPress Enter to continue...")
|
378
|
+
elif choice == "3":
|
379
|
+
self.view_logs()
|
380
|
+
elif choice == "4":
|
381
|
+
self.safe_terminate()
|
382
|
+
elif choice == "q":
|
383
|
+
print("\033c", end="") # 清屏指令
|
384
|
+
sys.exit(0)
|
385
|
+
else:
|
386
|
+
print("Invalid selection")
|
387
|
+
input("\nPress Enter to continue...")
|
388
|
+
|
389
|
+
|
390
|
+
def main():
|
391
|
+
manager = TaskManager()
|
392
|
+
manager.main_menu()
|
393
|
+
|
394
|
+
|
395
|
+
if __name__ == "__main__":
|
396
|
+
main()
|
ion_CSP/vasp_processing.py
CHANGED
@@ -224,7 +224,7 @@ class VaspProcessing:
|
|
224
224
|
logging.error(
|
225
225
|
f" Unfinished fine optimization job of CONTCAR_{mlp_density}_{number}"
|
226
226
|
)
|
227
|
-
fine_density, fine_energy = False, False
|
227
|
+
fine_density, fine_energy, molecules_flag = False, False, False
|
228
228
|
|
229
229
|
# 读取根目录下的 config.yaml 信息与对应的 .json 文件
|
230
230
|
config_path = os.path.join(self.base_dir, "config.yaml")
|
@@ -245,8 +245,8 @@ class VaspProcessing:
|
|
245
245
|
packing_coefficient = round(
|
246
246
|
molecular_volumes / fine_atoms_volume, 4
|
247
247
|
)
|
248
|
-
except FileNotFoundError:
|
249
|
-
|
248
|
+
except (FileNotFoundError, UnboundLocalError):
|
249
|
+
packing_coefficient = False
|
250
250
|
|
251
251
|
mlp_energies.append(mlp_energy)
|
252
252
|
rough_densities.append(rough_density)
|
@@ -0,0 +1,236 @@
|
|
1
|
+
Metadata-Version: 2.4
|
2
|
+
Name: ion_CSP
|
3
|
+
Version: 2.0.4
|
4
|
+
Summary: Crystal Structure Design Software Based on Molecular/Ionic Configuration.
|
5
|
+
Home-page: https://github.com/bagabaga007/ion_CSP
|
6
|
+
Author: Ze Yang
|
7
|
+
Author-email: Ze Yang <yangze1995007@163.com>
|
8
|
+
License-Expression: MIT
|
9
|
+
Keywords: ion_crystal, crystal_structure_prediction
|
10
|
+
Classifier: Programming Language :: Python :: 3
|
11
|
+
Classifier: Operating System :: OS Independent
|
12
|
+
Requires-Python: >=3.11
|
13
|
+
Description-Content-Type: text/markdown
|
14
|
+
License-File: LICENSE
|
15
|
+
Requires-Dist: ase==3.23.0
|
16
|
+
Requires-Dist: deepmd-kit==3.0.1
|
17
|
+
Requires-Dist: torch==2.5.0
|
18
|
+
Requires-Dist: dpdispatcher==0.6.7
|
19
|
+
Requires-Dist: numpy==1.26.4
|
20
|
+
Requires-Dist: paramiko==3.5.1
|
21
|
+
Requires-Dist: pyxtal==1.0.4
|
22
|
+
Requires-Dist: phonopy==2.28.0
|
23
|
+
Requires-Dist: rdkit==2024.3.3
|
24
|
+
Requires-Dist: pytest==8.3.4
|
25
|
+
Dynamic: author
|
26
|
+
Dynamic: home-page
|
27
|
+
Dynamic: license-file
|
28
|
+
Dynamic: requires-python
|
29
|
+
|
30
|
+
# Crystal Structure Design Software V2.0
|
31
|
+
|
32
|
+
## 项目概述
|
33
|
+
基于分子/离子构型的晶体结构设计软件通过结合经验公式、机器学习势函数微调、第一性原理分步优化和分子/离子识别技术,实现了从分子/离子构型出发的高效晶体结构筛选。该软件采用模块化设计,支持全流程自动化材料筛选,在保证预测精度的同时显著提升计算效率。
|
34
|
+
|
35
|
+
## 功能特性
|
36
|
+
### 核心功能
|
37
|
+
- **双模块工作流**
|
38
|
+
- **EE模块**:基于经验评估的离子组合生成
|
39
|
+
- **CSP模块**:基于离子晶体结构预测的优化筛选
|
40
|
+
- **智能任务管理**
|
41
|
+
- 实时进程监控(PID跟踪)
|
42
|
+
- 日志文件自动符号链接
|
43
|
+
- 进程安全终止与资源清理
|
44
|
+
- **高级日志系统**
|
45
|
+
- 分页浏览(10条/页)
|
46
|
+
- 模块过滤(CSP/EE)
|
47
|
+
- 软链接解析显示实际路径
|
48
|
+
|
49
|
+
### 技术特性
|
50
|
+
- 跨平台支持(Linux/Docker)
|
51
|
+
- 基于Python 3.11+的面向对象架构
|
52
|
+
- 集成psutil进程管理
|
53
|
+
- 结构化日志记录系统
|
54
|
+
|
55
|
+
## 安装指南
|
56
|
+
### 环境要求
|
57
|
+
| 组件 | 最低版本 |
|
58
|
+
|-------------|----------|
|
59
|
+
| Python | 3.11 |
|
60
|
+
| psutil | 5.9 |
|
61
|
+
| Docker | 20.10 |
|
62
|
+
| ase | 3.23.0 |
|
63
|
+
| deepmd-kit | 3.0.1 |
|
64
|
+
| torch | 2.5.0 |
|
65
|
+
| dpdispatcher| 0.6.7 |
|
66
|
+
| numpy | 1.26.4 |
|
67
|
+
| paramiko | 3.5.1 |
|
68
|
+
| pyxtal | 1.0.4 |
|
69
|
+
| phonopy | 2.28.0 |
|
70
|
+
| rdkit | 2023.03.3|
|
71
|
+
|
72
|
+
### 安装步骤
|
73
|
+
```bash
|
74
|
+
# 创建虚拟环境
|
75
|
+
python -m venv venv
|
76
|
+
source venv/bin/activate # Linux/Mac
|
77
|
+
|
78
|
+
# 安装依赖
|
79
|
+
pip install ion-csp
|
80
|
+
```
|
81
|
+
|
82
|
+
## 快速入门
|
83
|
+
### 交互模式
|
84
|
+
```bash
|
85
|
+
ion-csp
|
86
|
+
```
|
87
|
+
启动交互式命令行界面,支持以下操作:
|
88
|
+
- 模块选择
|
89
|
+
- 日志查看
|
90
|
+
- 进程管理
|
91
|
+
|
92
|
+
### 脚本调用
|
93
|
+
#### EE模块示例
|
94
|
+
```bash
|
95
|
+
./scripts/main_EE.sh examples/example_1
|
96
|
+
```
|
97
|
+
从SMILES表格生成离子组合
|
98
|
+
|
99
|
+
#### CSP模块示例
|
100
|
+
```bash
|
101
|
+
./scripts/main_CSP.sh examples/example_2
|
102
|
+
```
|
103
|
+
从离子组合生成并优化晶体结构
|
104
|
+
|
105
|
+
## 技术架构
|
106
|
+
```mermaid
|
107
|
+
graph TD
|
108
|
+
A[用户界面] --> B[任务管理器]
|
109
|
+
B --> C[EE模块]
|
110
|
+
B --> D[CSP模块]
|
111
|
+
B --> E[日志系统]
|
112
|
+
B --> F[任务调度]
|
113
|
+
C --> G[经验评估引擎]
|
114
|
+
D --> H[晶体预测引擎]
|
115
|
+
E --> I[结构化日志]
|
116
|
+
F --> J[进程终止]
|
117
|
+
```
|
118
|
+
|
119
|
+
## 贡献指南
|
120
|
+
1. Fork仓库并创建特性分支
|
121
|
+
2. 编写单元测试覆盖新功能
|
122
|
+
3. 提交Pull Request时注明关联Issue
|
123
|
+
4. 遵循PEP8代码规范
|
124
|
+
|
125
|
+
## 许可证
|
126
|
+
本项目采用MIT许可证,详见LICENSE文件。
|
127
|
+
|
128
|
+
## 技术支持
|
129
|
+
- **文档更新**:2025年5月
|
130
|
+
- **最新版本**:v2.0.4
|
131
|
+
- **问题追踪**:https://github.com/bagabaga007/ion_CSP/issues
|
132
|
+
|
133
|
+
---
|
134
|
+
|
135
|
+
# Crystal Structure Design Software V2.0
|
136
|
+
|
137
|
+
## Project Overview
|
138
|
+
This software enables efficient crystal structure screening from molecular/ion configurations by integrating empirical formulas, tuned machine learning potentials, stepwise first-principles optimization, and molecular/ion recognition techniques. The modular architecture ensures extensibility and maintainability while maintaining prediction accuracy.
|
139
|
+
|
140
|
+
## Key Features
|
141
|
+
### Core Functionalities
|
142
|
+
- **Dual-Module Workflow**
|
143
|
+
- **EE Module**: Empirical evaluation-based ion combination generation
|
144
|
+
- **CSP Module**: Ion crystal structure prediction and optimization
|
145
|
+
- **Intelligent Task Management**
|
146
|
+
- Real-time process monitoring (PID tracking)
|
147
|
+
- Automatic log file symlink creation
|
148
|
+
- Safe process termination with resource cleanup
|
149
|
+
- **Advanced Logging System**
|
150
|
+
- Paginated log viewing (10 entries/page)
|
151
|
+
- Module-based filtering (CSP/EE)
|
152
|
+
- Symlink resolution for actual log paths
|
153
|
+
|
154
|
+
### Technical Specifications
|
155
|
+
- Cross-platform support (Linux/Docker)
|
156
|
+
- Object-oriented architecture with Python 3.11+
|
157
|
+
- Integrated process management via psutil
|
158
|
+
- Structured logging system
|
159
|
+
|
160
|
+
## Installation
|
161
|
+
### Prerequisites
|
162
|
+
| Component | Min Version |
|
163
|
+
|-------------|-------------|
|
164
|
+
| Python | 3.11 |
|
165
|
+
| psutil | 5.9 |
|
166
|
+
| Docker | 20.10 |
|
167
|
+
| ase | 3.23.0 |
|
168
|
+
| deepmd-kit | 3.0.1 |
|
169
|
+
| torch | 2.5.0 |
|
170
|
+
| dpdispatcher| 0.6.7 |
|
171
|
+
| numpy | 1.26.4 |
|
172
|
+
| paramiko | 3.5.1 |
|
173
|
+
| pyxtal | 1.0.4 |
|
174
|
+
| phonopy | 2.28.0 |
|
175
|
+
| rdkit | 2023.03.3|
|
176
|
+
|
177
|
+
### Installation Steps
|
178
|
+
```bash
|
179
|
+
# Create virtual environment
|
180
|
+
python -m venv venv
|
181
|
+
source venv/bin/activate # Linux/Mac
|
182
|
+
|
183
|
+
# Install dependencies
|
184
|
+
pip install ion-csp
|
185
|
+
```
|
186
|
+
|
187
|
+
## Quick Start
|
188
|
+
### Interactive Mode
|
189
|
+
```bash
|
190
|
+
ion-csp
|
191
|
+
```
|
192
|
+
Launches CLI interface with:
|
193
|
+
- Module selection
|
194
|
+
- Log management
|
195
|
+
- Process control
|
196
|
+
|
197
|
+
### Script Execution
|
198
|
+
#### EE Module Example
|
199
|
+
```bash
|
200
|
+
./scripts/main_EE.sh examples/example_1
|
201
|
+
```
|
202
|
+
Generates ion combinations from SMILES tables
|
203
|
+
|
204
|
+
#### CSP Module Example
|
205
|
+
```bash
|
206
|
+
./scripts/main_CSP.sh examples/example_2
|
207
|
+
```
|
208
|
+
Optimizes crystal structures from ion combinations
|
209
|
+
|
210
|
+
## Technical Architecture
|
211
|
+
```mermaid
|
212
|
+
graph TD
|
213
|
+
A[User Interface] --> B[Task Manager]
|
214
|
+
B --> C[EE Module]
|
215
|
+
B --> D[CSP Module]
|
216
|
+
B --> E[Log System]
|
217
|
+
B --> F[Task Scheduler]
|
218
|
+
C --> G[Empirical Evaluation Engine]
|
219
|
+
D --> H[Crystal Prediction Engine]
|
220
|
+
E --> I[Structured Logs]
|
221
|
+
F --> J[Process Termination]
|
222
|
+
```
|
223
|
+
|
224
|
+
## Contribution Guide
|
225
|
+
1. Fork repository and create feature branch
|
226
|
+
2. Write unit tests for new features
|
227
|
+
3. Submit PR with issue reference
|
228
|
+
4. Follow PEP8 coding standards
|
229
|
+
|
230
|
+
## License
|
231
|
+
MIT License, see LICENSE file.
|
232
|
+
|
233
|
+
## Support
|
234
|
+
- Documentation last updated: May 2025
|
235
|
+
- Latest version: v2.0.4
|
236
|
+
- Issue tracker: https://github.com/bagabaga007/ion_CSP/issues
|
@@ -0,0 +1,19 @@
|
|
1
|
+
ion_CSP/__init__.py,sha256=M5RcbYDdt-UBVpsDKiJWJqLvSFfoBfU6aTUVccgK_BE,190
|
2
|
+
ion_CSP/__main__.py,sha256=XlNCx5eMSrL7yld9ddSYXhjXvg2ZYGD_uk9LdqNabvs,74
|
3
|
+
ion_CSP/convert_SMILES.py,sha256=4fndMcuIEypYtkXWBoS7W7uEXkZXVLeMDshdXEIk5kY,13864
|
4
|
+
ion_CSP/empirical_estimate.py,sha256=_U5VRWSIAiJGcxnP3mnCHn8zKzviFEQhQwN7TjPTnCU,29089
|
5
|
+
ion_CSP/gen_opt.py,sha256=aVZmf2RqePCwZShgpNvzqfntNAW0I0yctWHGXoe3mgw,19463
|
6
|
+
ion_CSP/identify_molecules.py,sha256=hFKXS0Jjd7LyMsYGc9RmnoRPu1ibXF9fYO_9lR3wTfo,4634
|
7
|
+
ion_CSP/log_and_time.py,sha256=6RKegXF8Gc1HqzAbE-PT9ejX3Ncyuz3v3FivujJt8to,9072
|
8
|
+
ion_CSP/mlp_opt.py,sha256=ox4Qxg4D6WzrB8dxVnUWmAngnOA_wdcInP5UhBWsH4c,5535
|
9
|
+
ion_CSP/read_mlp_density.py,sha256=ktGNHYWLi4VrdJK_Hg2ac2-JM2QlVt9iymLxdixkLb8,9663
|
10
|
+
ion_CSP/steps_opt_monitor.sh,sha256=1klPjnK0gqkDbvI9PtjdK5qidJ5G0Mo8q1SfrlLW5xM,3330
|
11
|
+
ion_CSP/task_manager.py,sha256=PGtlvlJb7uzb1YcJyhP7cURQqOO4nNM-VacyZwVXixs,16088
|
12
|
+
ion_CSP/upload_download.py,sha256=Hiz5jKOy9x26hJJdcpt-owQdVUbzzGuGOelro6JozY8,23801
|
13
|
+
ion_CSP/vasp_processing.py,sha256=eQTMKIPBzi1X4HHTqWkHE1Lt8dvCCV-MXPCR3RtKYZ0,13977
|
14
|
+
ion_csp-2.0.4.dist-info/licenses/LICENSE,sha256=2J6A8GT2iIf2LhuWO1_0ilgx7ijzzpQ2BXU7rHKe8Cc,1068
|
15
|
+
ion_csp-2.0.4.dist-info/METADATA,sha256=r9ijfq_Yo5mTqMnCzNT9vYVF-FDSxN9bkHtU99FDdUw,6380
|
16
|
+
ion_csp-2.0.4.dist-info/WHEEL,sha256=0CuiUZ_p9E4cD6NyLD6UG80LBXYyiSYZOKDm5lp32xk,91
|
17
|
+
ion_csp-2.0.4.dist-info/entry_points.txt,sha256=NexQJDs9f69kJA2DgoU6tsA3V8a66nadJRem1U_c_6g,54
|
18
|
+
ion_csp-2.0.4.dist-info/top_level.txt,sha256=aYZa43dDebjLpWPN6bDIlBb6BVwA8gk4ajEjDDK9b9I,8
|
19
|
+
ion_csp-2.0.4.dist-info/RECORD,,
|
ion_CSP/app.py
DELETED
@@ -1,201 +0,0 @@
|
|
1
|
-
#!/usr/bin/env python3
|
2
|
-
import os
|
3
|
-
import sys
|
4
|
-
import time
|
5
|
-
import signal
|
6
|
-
import logging
|
7
|
-
import subprocess
|
8
|
-
from pathlib import Path
|
9
|
-
from datetime import datetime
|
10
|
-
|
11
|
-
|
12
|
-
class TaskManager:
|
13
|
-
def __init__(self):
|
14
|
-
self.env = "LOCAL"
|
15
|
-
self.workspace = Path.cwd()
|
16
|
-
self.log_base = self.workspace / "logs"
|
17
|
-
self._detect_env()
|
18
|
-
self._setup_logging()
|
19
|
-
|
20
|
-
def _detect_env(self):
|
21
|
-
"""环境检测"""
|
22
|
-
if Path("/.dockerenv").exists() or "DOCKER" in os.environ:
|
23
|
-
self.env = "DOCKER"
|
24
|
-
self.workspace = Path("/app")
|
25
|
-
self.log_base = Path("/app/logs")
|
26
|
-
self.workspace.mkdir(exist_ok=True)
|
27
|
-
self.log_base.mkdir(exist_ok=True)
|
28
|
-
|
29
|
-
def _setup_logging(self):
|
30
|
-
"""日志配置"""
|
31
|
-
logging.basicConfig(
|
32
|
-
level=logging.INFO,
|
33
|
-
format="%(asctime)s - %(levelname)s - %(message)s",
|
34
|
-
handlers=[
|
35
|
-
logging.FileHandler(self.log_base / "system.log"),
|
36
|
-
logging.StreamHandler(),
|
37
|
-
],
|
38
|
-
)
|
39
|
-
|
40
|
-
def normalize_path(self, path):
|
41
|
-
"""路径标准化"""
|
42
|
-
path = Path(path).resolve()
|
43
|
-
if self.env == "DOCKER":
|
44
|
-
return str(path.relative_to(self.workspace))
|
45
|
-
return str(path)
|
46
|
-
|
47
|
-
def _get_pid(self, module, work_dir):
|
48
|
-
"""获取进程PID"""
|
49
|
-
log_file = Path(work_dir) / f"main_{module}_console.log"
|
50
|
-
if not log_file.exists():
|
51
|
-
return None
|
52
|
-
try:
|
53
|
-
with open(log_file, "r") as f:
|
54
|
-
for line in f:
|
55
|
-
if "PYTHON_PID:" in line:
|
56
|
-
return int(line.split(":")[-1].strip())
|
57
|
-
except Exception as e:
|
58
|
-
logging.error(f"Error reading PID from log: {e}")
|
59
|
-
return None
|
60
|
-
|
61
|
-
def task_runner(self, module, work_dir):
|
62
|
-
"""任务执行器"""
|
63
|
-
work_dir = Path(work_dir)
|
64
|
-
work_dir.mkdir(exist_ok=True)
|
65
|
-
|
66
|
-
console_log = work_dir / f"main_{module}_console.log"
|
67
|
-
pid_file = work_dir / "pid.txt"
|
68
|
-
|
69
|
-
# 启动子进程
|
70
|
-
cmd = ["python", "-m", f"src.main_{module}", str(work_dir)]
|
71
|
-
|
72
|
-
with open(console_log, "w") as f:
|
73
|
-
process = subprocess.Popen(
|
74
|
-
cmd,
|
75
|
-
stdout=f,
|
76
|
-
stderr=subprocess.STDOUT,
|
77
|
-
preexec_fn=os.setsid if os.name != "nt" else None,
|
78
|
-
)
|
79
|
-
|
80
|
-
# 等待PID文件创建
|
81
|
-
time.sleep(1)
|
82
|
-
try:
|
83
|
-
with open(pid_file, "w") as f:
|
84
|
-
f.write(str(process.pid))
|
85
|
-
except Exception as e:
|
86
|
-
logging.error(f"Error writing PID file: {e}")
|
87
|
-
process.terminate()
|
88
|
-
return
|
89
|
-
# 创建符号链接
|
90
|
-
output_log = work_dir / f"main_{module}.py_output.log"
|
91
|
-
print(f"Original log file: {output_log}")
|
92
|
-
std_log = self.log_base / f"{module}_{process.pid}.log"
|
93
|
-
try:
|
94
|
-
std_log.symlink_to(output_log)
|
95
|
-
os.remove(pid_file)
|
96
|
-
except FileExistsError:
|
97
|
-
os.remove(std_log)
|
98
|
-
std_log.symlink_to(output_log)
|
99
|
-
|
100
|
-
logging.info(f"Started {module} module (PID: {process.pid})")
|
101
|
-
print(f"Task started (PID: {process.pid})")
|
102
|
-
print(f"Normalized log file: {std_log}")
|
103
|
-
|
104
|
-
def terminate_task(self, pid):
|
105
|
-
"""终止任务"""
|
106
|
-
try:
|
107
|
-
os.killpg(os.getpgid(pid), signal.SIGTERM)
|
108
|
-
print(f"Successfully terminated PID {pid}")
|
109
|
-
except ProcessLookupError:
|
110
|
-
print(f"No process found with PID {pid}")
|
111
|
-
except Exception as e:
|
112
|
-
print(f"Error terminating process: {e}")
|
113
|
-
|
114
|
-
def view_logs(self, page_size=10):
|
115
|
-
"""查看日志"""
|
116
|
-
log_files = sorted(
|
117
|
-
self.log_base.glob("**/*.log"), key=os.path.getmtime, reverse=True
|
118
|
-
)
|
119
|
-
if not log_files:
|
120
|
-
print("No logs found")
|
121
|
-
return
|
122
|
-
total_files = len(log_files)
|
123
|
-
total_pages = (total_files + page_size - 1) // page_size # 计算总页数
|
124
|
-
|
125
|
-
current_page = 0
|
126
|
-
while True:
|
127
|
-
start_index = current_page * page_size
|
128
|
-
end_index = start_index + page_size
|
129
|
-
print("\nAvailable logs:")
|
130
|
-
|
131
|
-
# 显示当前页的日志文件
|
132
|
-
for i, f in enumerate(log_files[start_index:end_index], start_index + 1):
|
133
|
-
print(
|
134
|
-
f"{i}) {f.name} ({datetime.fromtimestamp(f.stat().st_mtime).strftime('%Y-%m-%d %H:%M')})"
|
135
|
-
)
|
136
|
-
|
137
|
-
print("\nPage {} of {}".format(current_page + 1, total_pages))
|
138
|
-
if current_page > 0:
|
139
|
-
print("Enter 'p' to go to the previous page.")
|
140
|
-
if current_page < total_pages - 1:
|
141
|
-
print("Enter 'n' to go to the next page.")
|
142
|
-
print("Enter log number to view (q to cancel): ")
|
143
|
-
|
144
|
-
choice = input().strip()
|
145
|
-
if choice.isdigit():
|
146
|
-
choice_index = int(choice) - 1
|
147
|
-
if 0 <= choice_index < total_files:
|
148
|
-
os.system(f"less {log_files[choice_index]}")
|
149
|
-
else:
|
150
|
-
print("Invalid selection")
|
151
|
-
elif choice == "n" and current_page < total_pages - 1:
|
152
|
-
current_page += 1
|
153
|
-
elif choice == "p" and current_page > 0:
|
154
|
-
current_page -= 1
|
155
|
-
elif choice == "q":
|
156
|
-
break
|
157
|
-
else:
|
158
|
-
print("Invalid command")
|
159
|
-
|
160
|
-
def main_menu(self):
|
161
|
-
"""主菜单循环"""
|
162
|
-
while True:
|
163
|
-
os.system("clear" if os.name == "posix" else "cls")
|
164
|
-
print("========== Task Execution System ==========")
|
165
|
-
print(f"Current Environment: {self.env}")
|
166
|
-
print(f"Current Directory: {self.workspace}")
|
167
|
-
print(f"Log Base Directory: {self.log_base}")
|
168
|
-
print("=" * 50)
|
169
|
-
print("1) Run EE Module")
|
170
|
-
print("2) Run CSP Module")
|
171
|
-
print("3) View Logs")
|
172
|
-
print("4) Terminate Task")
|
173
|
-
print("q) Exit")
|
174
|
-
print("=" * 50)
|
175
|
-
|
176
|
-
choice = input("Please select one of the operation: ").strip()
|
177
|
-
if choice == "1":
|
178
|
-
work_dir = input("Enter EE working directory: ").strip()
|
179
|
-
self.task_runner("EE", work_dir)
|
180
|
-
elif choice == "2":
|
181
|
-
work_dir = input("Enter CSP working directory: ").strip()
|
182
|
-
self.task_runner("CSP", work_dir)
|
183
|
-
elif choice == "3":
|
184
|
-
self.view_logs()
|
185
|
-
elif choice == "4":
|
186
|
-
pid = input("Enter PID to terminate: ").strip()
|
187
|
-
if pid.isdigit():
|
188
|
-
self.terminate_task(int(pid))
|
189
|
-
else:
|
190
|
-
print("Invalid PID format")
|
191
|
-
elif choice == "q":
|
192
|
-
print("Exiting system...")
|
193
|
-
sys.exit(0)
|
194
|
-
else:
|
195
|
-
print("Invalid selection")
|
196
|
-
input("\nPress Enter to continue...")
|
197
|
-
|
198
|
-
|
199
|
-
if __name__ == "__main__":
|
200
|
-
manager = TaskManager()
|
201
|
-
manager.main_menu()
|
ion_csp-2.0.2.dist-info/METADATA
DELETED
@@ -1,83 +0,0 @@
|
|
1
|
-
Metadata-Version: 2.4
|
2
|
-
Name: ion_CSP
|
3
|
-
Version: 2.0.2
|
4
|
-
Summary: Crystal Structure Design Software Based on Molecular/Ionic Configuration.
|
5
|
-
Home-page: https://github.com/bagabaga007/ion_CSP
|
6
|
-
Author: yangze
|
7
|
-
Author-email: Ze Yang <yangze1995007@163.com>
|
8
|
-
License: MIT License
|
9
|
-
|
10
|
-
Copyright (c) [2025] [ion_CSP]
|
11
|
-
|
12
|
-
Permission is hereby granted, free of charge, to any person obtaining a copy
|
13
|
-
of this software and associated documentation files (the "Software"), to deal
|
14
|
-
in the Software without restriction, including without limitation the rights
|
15
|
-
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
16
|
-
copies of the Software, and to permit persons to whom the Software is
|
17
|
-
furnished to do so, subject to the following conditions:
|
18
|
-
|
19
|
-
The above copyright notice and this permission notice shall be included in all
|
20
|
-
copies or substantial portions of the Software.
|
21
|
-
|
22
|
-
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
23
|
-
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
24
|
-
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
25
|
-
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
26
|
-
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
27
|
-
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
28
|
-
SOFTWARE.
|
29
|
-
|
30
|
-
Keywords: ion_crystal, crystal_structure_prediction
|
31
|
-
Classifier: Programming Language :: Python :: 3
|
32
|
-
Classifier: License :: OSI Approved :: MIT License
|
33
|
-
Classifier: Operating System :: OS Independent
|
34
|
-
Requires-Python: >=3.11
|
35
|
-
Description-Content-Type: text/markdown
|
36
|
-
License-File: LICENSE
|
37
|
-
Requires-Dist: ase==3.23.0
|
38
|
-
Requires-Dist: deepmd-kit==3.0.1
|
39
|
-
Requires-Dist: torch==2.5.0
|
40
|
-
Requires-Dist: dpdispatcher==0.6.7
|
41
|
-
Requires-Dist: numpy==1.26.4
|
42
|
-
Requires-Dist: paramiko==3.5.1
|
43
|
-
Requires-Dist: pyxtal==1.0.4
|
44
|
-
Requires-Dist: phonopy==2.28.0
|
45
|
-
Requires-Dist: rdkit==2023.03.3
|
46
|
-
Dynamic: author
|
47
|
-
Dynamic: home-page
|
48
|
-
Dynamic: license-file
|
49
|
-
Dynamic: requires-python
|
50
|
-
|
51
|
-
# 基于分子/离子构型的晶体结构设计软件 V2.0
|
52
|
-
|
53
|
-
基于分子/离子构型的晶体结构设计软件可以从分子/离子构型出发,结合经验公式、微调的机器学习势、第一性原理分步优化以及分子/离子识别方法,可以高效且有导向地筛选同时满足结构要求和性质要求的分子/离子晶体结构。该软件实现了分子/离子晶体结构的设计、构建、分析、筛选、评估全流程的自动化与模块化,保证了流程的扩展性和可重用性,能够在保证结果精度的同时,显著提高材料筛选效率。在整个流程中提供了多种检查功能以及结果可视化功能,方便用户使用。该软件使用Python语言编写,提供了完整的面向对象编程支持,在具有较高运行效率的同时使程序更易于理解、扩展和维护。
|
54
|
-
|
55
|
-
# 安装
|
56
|
-
|
57
|
-
在项目根目录下使用以下命令安装依赖:
|
58
|
-
|
59
|
-
pip install -r requirements.txt
|
60
|
-
|
61
|
-
pip install -e .
|
62
|
-
|
63
|
-
chmod +x ./scripts/*.sh
|
64
|
-
|
65
|
-
# 使用示例
|
66
|
-
|
67
|
-
### 使用交互式功能自主选择
|
68
|
-
./scripts/main.sh
|
69
|
-
|
70
|
-
#### 使用经验评估(EE)模块从SMILES表格开始生成离子组合
|
71
|
-
./scripts/main_EE.sh examples/example_1
|
72
|
-
|
73
|
-
|
74
|
-
#### 使用离子晶体结构预测(CSP)模块从离子组合开始生成晶体并筛选和优化
|
75
|
-
./scripts/main_CSP.sh examples/example_2
|
76
|
-
|
77
|
-
# 功能
|
78
|
-
使用经验评估(EE)模块从SMILES表格开始生成离子组合。
|
79
|
-
|
80
|
-
使用离子晶体结构预测(CSP)模块从离子组合开始生成晶体并筛选和优化。
|
81
|
-
|
82
|
-
# 联系
|
83
|
-
如有问题,请联系 yangze1995007@163.com。
|
ion_csp-2.0.2.dist-info/RECORD
DELETED
@@ -1,18 +0,0 @@
|
|
1
|
-
ion_CSP/__init__.py,sha256=M5RcbYDdt-UBVpsDKiJWJqLvSFfoBfU6aTUVccgK_BE,190
|
2
|
-
ion_CSP/app.py,sha256=MnuVdzV6yiTG__SPuWeQ05V0rwYqoJtez2XpdmRZOrU,6996
|
3
|
-
ion_CSP/convert_SMILES.py,sha256=4fndMcuIEypYtkXWBoS7W7uEXkZXVLeMDshdXEIk5kY,13864
|
4
|
-
ion_CSP/empirical_estimate.py,sha256=_U5VRWSIAiJGcxnP3mnCHn8zKzviFEQhQwN7TjPTnCU,29089
|
5
|
-
ion_CSP/gen_opt.py,sha256=i9BxV6881YEO5PQZfYqu4wpJ_JfDfTqn0o2XJ90s9UU,19463
|
6
|
-
ion_CSP/identify_molecules.py,sha256=yzLMWpGW1YM1B4a9cg4Jd1CekTWtXsPWAt-TpwL1Rks,4638
|
7
|
-
ion_CSP/log_and_time.py,sha256=6RKegXF8Gc1HqzAbE-PT9ejX3Ncyuz3v3FivujJt8to,9072
|
8
|
-
ion_CSP/mlp_opt.py,sha256=ox4Qxg4D6WzrB8dxVnUWmAngnOA_wdcInP5UhBWsH4c,5535
|
9
|
-
ion_CSP/read_mlp_density.py,sha256=ktGNHYWLi4VrdJK_Hg2ac2-JM2QlVt9iymLxdixkLb8,9663
|
10
|
-
ion_CSP/steps_opt_monitor.sh,sha256=1klPjnK0gqkDbvI9PtjdK5qidJ5G0Mo8q1SfrlLW5xM,3330
|
11
|
-
ion_CSP/upload_download.py,sha256=Hiz5jKOy9x26hJJdcpt-owQdVUbzzGuGOelro6JozY8,23801
|
12
|
-
ion_CSP/vasp_processing.py,sha256=Pd-_muPDMst-DKj6vGR34e7IFWsSyGiP7q-aMGZXatA,13911
|
13
|
-
ion_csp-2.0.2.dist-info/licenses/LICENSE,sha256=2J6A8GT2iIf2LhuWO1_0ilgx7ijzzpQ2BXU7rHKe8Cc,1068
|
14
|
-
ion_csp-2.0.2.dist-info/METADATA,sha256=OfnWFxuY9bXCwIpbkwJVqh8ZQyM1l78YWr6k44ZmVFk,3719
|
15
|
-
ion_csp-2.0.2.dist-info/WHEEL,sha256=pxyMxgL8-pra_rKaQ4drOZAegBVuX-G_4nRHjjgWbmo,91
|
16
|
-
ion_csp-2.0.2.dist-info/entry_points.txt,sha256=l8q_8U8whrkzO1-8RIppbDco-520Cy3Pq1N5LyLTTLc,49
|
17
|
-
ion_csp-2.0.2.dist-info/top_level.txt,sha256=aYZa43dDebjLpWPN6bDIlBb6BVwA8gk4ajEjDDK9b9I,8
|
18
|
-
ion_csp-2.0.2.dist-info/RECORD,,
|
File without changes
|
File without changes
|