flash-sim 0.0.1__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.
- flash/__init__.py +157 -0
- flash/_bootstrap.py +35 -0
- flash/_core/__init__.py +39 -0
- flash/_core/credentials/__init__.py +44 -0
- flash/_core/credentials/_config.py +191 -0
- flash/_core/credentials/_core.py +277 -0
- flash/_core/credentials/_flash_entries.py +83 -0
- flash/_core/credentials/_minimal.py +73 -0
- flash/_core/credentials/api_keys.py +225 -0
- flash/_core/credentials/deepseek.py +187 -0
- flash/_core/credentials/flash_ssh.py +472 -0
- flash/_core/credentials/gitee.py +220 -0
- flash/_core/credentials/manage.py +359 -0
- flash/_core/credentials/pypi.py +144 -0
- flash/_core/credentials.py +1103 -0
- flash/_core/interface.py +90 -0
- flash/_core/registry.py +35 -0
- flash/_core/schema.py +118 -0
- flash/config/__init__.py +105 -0
- flash/flash_run/PROCESS.md +435 -0
- flash/flash_run/README.md +205 -0
- flash/flash_run/__init__.py +25 -0
- flash/flash_run/env/README.md +272 -0
- flash/flash_run/env/__init__.py +12 -0
- flash/flash_run/env/env_manager.py +535 -0
- flash/flash_run/env/resource_config.py +650 -0
- flash/flash_run/remote/README.md +313 -0
- flash/flash_run/remote/__init__.py +20 -0
- flash/flash_run/remote/remote_check.py +70 -0
- flash/flash_run/remote/remote_deploy.py +792 -0
- flash/flash_run/remote/remote_workflow.py +142 -0
- flash/flash_run/remote/route_tester.py +465 -0
- flash/flash_run/remote/ssh_check.py +107 -0
- flash/input_gen/README.md +535 -0
- flash/input_gen/__init__.py +170 -0
- flash/input_gen/gen_Grid_markRefineDerefine/GEN_GRID_GUIDE.md +68 -0
- flash/input_gen/gen_Grid_markRefineDerefine/README.md +327 -0
- flash/input_gen/gen_Grid_markRefineDerefine/__init__.py +0 -0
- flash/input_gen/gen_Grid_markRefineDerefine/generator.py +567 -0
- flash/input_gen/gen_checker/GEN_CHECKER_GUIDE.md +148 -0
- flash/input_gen/gen_checker/__init__.py +6 -0
- flash/input_gen/gen_checker/checker.py +274 -0
- flash/input_gen/gen_checker/ploter/__init__.py +13 -0
- flash/input_gen/gen_checker/ploter/density_plotter.py +195 -0
- flash/input_gen/gen_checker/ploter/pulse_plotter.py +158 -0
- flash/input_gen/gen_checker/ploter/ray_plotter.py +277 -0
- flash/input_gen/gen_config/GEN_CONFIG_GUIDE.md +534 -0
- flash/input_gen/gen_config/__init__.py +9 -0
- flash/input_gen/gen_config/generator.py +205 -0
- flash/input_gen/gen_eos_op/GEN_EOS_OP_GUIDE.md +224 -0
- flash/input_gen/gen_eos_op/__init__.py +10 -0
- flash/input_gen/gen_eos_op/generator.py +481 -0
- flash/input_gen/gen_f90/__init__.py +0 -0
- flash/input_gen/gen_makefile/GEN_MAKEFILE_GUIDE.md +56 -0
- flash/input_gen/gen_makefile/__init__.py +9 -0
- flash/input_gen/gen_makefile/generator.py +32 -0
- flash/input_gen/gen_newpara/README.md +400 -0
- flash/input_gen/gen_newpara/RP_Reference.md +639 -0
- flash/input_gen/gen_newpara/__init__.py +19 -0
- flash/input_gen/gen_newpara/generator.py +643 -0
- flash/input_gen/gen_otherf90s/GEN_OTHER_F90S_GUIDE.md +231 -0
- flash/input_gen/gen_otherf90s/__init__.py +0 -0
- flash/input_gen/gen_par/GEN_PAR_GUIDE.md +657 -0
- flash/input_gen/gen_par/__init__.py +18 -0
- flash/input_gen/gen_par/defaults.py +510 -0
- flash/input_gen/gen_par/generator.py +445 -0
- flash/input_gen/gen_par/materials.py +141 -0
- flash/input_gen/gen_shell_script/GEN_SHELL_SCRIPT_GUIDE.md +120 -0
- flash/input_gen/gen_shell_script/__init__.py +12 -0
- flash/input_gen/gen_shell_script/generator.py +850 -0
- flash/input_gen/gen_sim_data/GEN_SIM_DATA_GUIDE.md +306 -0
- flash/input_gen/gen_sim_data/__init__.py +10 -0
- flash/input_gen/gen_sim_data/generator.py +87 -0
- flash/input_gen/gen_sim_init/GEN_SIM_INIT_GUIDE.md +216 -0
- flash/input_gen/gen_sim_init/__init__.py +9 -0
- flash/input_gen/gen_sim_init/generator.py +104 -0
- flash/input_gen/gen_sim_initblock/GEN_SIM_INITBLOCK_GUIDE.md +330 -0
- flash/input_gen/gen_sim_initblock/__init__.py +17 -0
- flash/input_gen/gen_sim_initblock/generator.py +432 -0
- flash/input_gen/gen_sim_initblock/grid.py +278 -0
- flash/input_gen/gen_sim_initblock/visualizer.py +250 -0
- flash/interface.py +398 -0
- flash/output_processors/__init__.py +50 -0
- flash/output_processors/conftest.py +41 -0
- flash/output_processors/docs/api_reference.md +597 -0
- flash/output_processors/docs/how_to_add_custom_variables.md +417 -0
- flash/output_processors/docs/output_processors_usage.md +596 -0
- flash/output_processors/docs/performance_tuning.md +365 -0
- flash/output_processors/docs/workflow.md +101 -0
- flash/output_processors/hdf5processor/__init__.py +21 -0
- flash/output_processors/hdf5processor/flash_hdf5.py +1224 -0
- flash/output_processors/loader/__init__.py +7 -0
- flash/output_processors/loader/data_loader.py +392 -0
- flash/output_processors/parallel.py +580 -0
- flash/output_processors/plotter/__init__.py +8 -0
- flash/output_processors/plotter/plot_generator.py +471 -0
- flash/output_processors/plotter/plot_style.py +240 -0
- flash/physics/ele_nonlocal/Knudsen_Nonlocal_Summary.md +576 -0
- flash/projects/__init__.py +0 -0
- flash/projects/projects_demo/README.md +94 -0
- flash/projects/projects_demo/__init__.py +17 -0
- flash/projects/projects_demo/ch_center_demo/__init__.py +16 -0
- flash/projects/projects_demo/ch_center_demo/plot_compare.py +169 -0
- flash/projects/projects_demo/ch_center_demo/run_compare.py +148 -0
- flash/scenarios/README.md +669 -0
- flash/scenarios/SNBtest/__init__.py +0 -0
- flash/scenarios/__init__.py +18 -0
- flash/scenarios/base.py +50 -0
- flash/scenarios/center_evolution/__init__.py +2 -0
- flash/scenarios/center_evolution/ch_center/__init__.py +361 -0
- flash/scenarios/center_evolution/ch_center/laserslab1d_local_custom.py +804 -0
- flash/scenarios/collision_compression/__init__.py +38 -0
- flash/scenarios/flash_demo/__init__.py +0 -0
- flash/scenarios/flash_demo/demo_hpc/__init__.py +0 -0
- flash/scenarios/flash_demo/demo_hpc/_plot_utils.py +128 -0
- flash/scenarios/flash_demo/demo_hpc/laserslab1d_hpc_demo_batch.py +1035 -0
- flash/scenarios/flash_demo/demo_hpc/laserslab1d_supercomputer_demo.py +778 -0
- flash/scenarios/flash_demo/demo_hpc/remote_analysis.py +428 -0
- flash/scenarios/flash_demo/demo_hpc/remote_plot_script.py +444 -0
- flash/scenarios/flash_demo/demo_hpc/remote_ssh_helper.py +457 -0
- flash/scenarios/flash_demo/demo_local/__init__.py +0 -0
- flash/scenarios/flash_demo/demo_local/laserslab1d_local_demo.py +343 -0
- flash/scenarios/flash_demo/hello_flash/README.md +447 -0
- flash/scenarios/flash_demo/hello_flash/analyze_density.py +416 -0
- flash/scenarios/flash_demo/hello_flash/deploy_flash.py +828 -0
- flash/scenarios/interpolator.py +286 -0
- flash/scenarios/plasma_preparation/__init__.py +1 -0
- flash/scenarios/registry.py +61 -0
- flash/scenarios/simulator.py +1045 -0
- flash/test/__init__.py +1 -0
- flash/test/flash_mathtest_custom01.py +413 -0
- flash/test/math_test.py +596 -0
- flash/utils/__init__.py +9 -0
- flash/utils/check_hdf5_time.py +22 -0
- flash/utils/convert_pdf_to_md.py +134 -0
- flash/utils/convert_text_to_md.py +102 -0
- flash/utils/extract_knowledge.py +200 -0
- flash_sim-0.0.1.dist-info/METADATA +811 -0
- flash_sim-0.0.1.dist-info/RECORD +143 -0
- flash_sim-0.0.1.dist-info/WHEEL +4 -0
- flash_sim-0.0.1.dist-info/entry_points.txt +3 -0
- flash_sim-0.0.1.dist-info/licenses/LICENSE +386 -0
- flash_sim-0.0.1.dist-info/licenses/NOTICE +138 -0
flash/_core/interface.py
ADDED
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
"""Standalone interface — BaseSimulator for standalone mode.
|
|
2
|
+
|
|
3
|
+
This module provides the BaseSimulator abstract class for use when
|
|
4
|
+
physimx_core is not installed (standalone mode).
|
|
5
|
+
|
|
6
|
+
When physimx_core IS installed, flash/__init__.py will import from
|
|
7
|
+
physimx_core.interface instead.
|
|
8
|
+
"""
|
|
9
|
+
|
|
10
|
+
from __future__ import annotations
|
|
11
|
+
|
|
12
|
+
from abc import ABC, abstractmethod
|
|
13
|
+
from pathlib import Path
|
|
14
|
+
from typing import Any, Dict, List, Optional
|
|
15
|
+
|
|
16
|
+
from .schema import CapabilityCard, InputVar, SimulationRequest, SimulationResult
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
class BaseSimulator(ABC):
|
|
20
|
+
"""Abstract base class for all physics simulation plugins.
|
|
21
|
+
|
|
22
|
+
A simulator plugin must implement:
|
|
23
|
+
- ``capability()`` → declare what physics it can simulate.
|
|
24
|
+
- ``simulate(request)`` → run one simulation and return results.
|
|
25
|
+
|
|
26
|
+
Optionally, it may also implement:
|
|
27
|
+
- ``simulate_batch(requests)`` → run many simulations (parallel-capable).
|
|
28
|
+
"""
|
|
29
|
+
|
|
30
|
+
@abstractmethod
|
|
31
|
+
def capability(self) -> CapabilityCard:
|
|
32
|
+
"""Return a machine-readable declaration of this simulator's capabilities."""
|
|
33
|
+
...
|
|
34
|
+
|
|
35
|
+
@abstractmethod
|
|
36
|
+
def simulate(self, request: SimulationRequest) -> SimulationResult:
|
|
37
|
+
"""Execute one simulation and return structured results.
|
|
38
|
+
|
|
39
|
+
Parameters
|
|
40
|
+
----------
|
|
41
|
+
request : SimulationRequest
|
|
42
|
+
Input containing parameters, work_dir, etc.
|
|
43
|
+
|
|
44
|
+
Returns
|
|
45
|
+
-------
|
|
46
|
+
SimulationResult
|
|
47
|
+
Output. ``result.success`` indicates whether the simulation converged.
|
|
48
|
+
"""
|
|
49
|
+
...
|
|
50
|
+
|
|
51
|
+
def validate_params(self, params: Dict[str, Any]) -> None:
|
|
52
|
+
"""Validate simulation parameters.
|
|
53
|
+
|
|
54
|
+
Default implementation checks temperature range.
|
|
55
|
+
Raises ValueError if validation fails.
|
|
56
|
+
"""
|
|
57
|
+
cap = self.capability()
|
|
58
|
+
input_schema = cap.input_schema
|
|
59
|
+
for key, spec in input_schema.items():
|
|
60
|
+
if key in params:
|
|
61
|
+
val = params[key]
|
|
62
|
+
if spec.low is not None and val < spec.low:
|
|
63
|
+
raise ValueError(f"{key}={val} < minimum {spec.low}")
|
|
64
|
+
if spec.high is not None and val > spec.high:
|
|
65
|
+
raise ValueError(f"{key}={val} > maximum {spec.high}")
|
|
66
|
+
|
|
67
|
+
# ----- optional overrides (with sensible defaults) -------------------
|
|
68
|
+
|
|
69
|
+
def simulate_batch(
|
|
70
|
+
self,
|
|
71
|
+
requests: list[SimulationRequest],
|
|
72
|
+
parallel: bool = False,
|
|
73
|
+
max_workers: int = 4,
|
|
74
|
+
) -> list[SimulationResult]:
|
|
75
|
+
"""Run multiple simulations, optionally in parallel.
|
|
76
|
+
|
|
77
|
+
The default implementation calls ``self.simulate`` in a loop.
|
|
78
|
+
Plugins that support native parallelism should override this method.
|
|
79
|
+
"""
|
|
80
|
+
import concurrent.futures
|
|
81
|
+
|
|
82
|
+
if not parallel:
|
|
83
|
+
return [self.simulate(req) for req in requests]
|
|
84
|
+
|
|
85
|
+
with concurrent.futures.ThreadPoolExecutor(max_workers=max_workers) as executor:
|
|
86
|
+
futures = [executor.submit(self.simulate, req) for req in requests]
|
|
87
|
+
return [f.result() for f in concurrent.futures.as_completed(futures)]
|
|
88
|
+
|
|
89
|
+
|
|
90
|
+
__all__ = ["BaseSimulator"]
|
flash/_core/registry.py
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
"""Standalone simulator registry (minimal, no physimx_core dependency).
|
|
2
|
+
|
|
3
|
+
When physimx_core is not installed, this module provides a basic registry
|
|
4
|
+
for FlashSimulator so that registry-dependent tests can pass.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from typing import Any, Dict, Optional
|
|
8
|
+
|
|
9
|
+
_registry: Dict[str, Any] = {}
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
def register_simulator(name: str, simulator_class: Any) -> None:
|
|
13
|
+
"""Register a simulator class by name."""
|
|
14
|
+
_registry[name.lower()] = simulator_class
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
def get_simulator(name: str) -> Optional[Any]:
|
|
18
|
+
"""Get a registered simulator class by name."""
|
|
19
|
+
return _registry.get(name.lower())
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
def list_simulators() -> list:
|
|
23
|
+
"""List all registered simulator names."""
|
|
24
|
+
return list(_registry.keys())
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
# Auto-register FlashSimulator if available
|
|
28
|
+
try:
|
|
29
|
+
from flash.interface import FlashSimulator
|
|
30
|
+
register_simulator("flash", FlashSimulator)
|
|
31
|
+
except ImportError:
|
|
32
|
+
pass
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
__all__ = ["register_simulator", "get_simulator", "list_simulators"]
|
flash/_core/schema.py
ADDED
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
"""Standalone schema — dataclass versions of physimx_core.schema.
|
|
2
|
+
|
|
3
|
+
This module provides dataclass-based versions of the schema classes
|
|
4
|
+
for use when physimx_core is not installed (standalone mode).
|
|
5
|
+
|
|
6
|
+
When physimx_core IS installed, flash/__init__.py will import from
|
|
7
|
+
physimx_core.schema instead (which uses pydantic for validation).
|
|
8
|
+
"""
|
|
9
|
+
|
|
10
|
+
from __future__ import annotations
|
|
11
|
+
|
|
12
|
+
from dataclasses import dataclass, field
|
|
13
|
+
from datetime import datetime, timezone
|
|
14
|
+
from enum import Enum
|
|
15
|
+
from pathlib import Path
|
|
16
|
+
from typing import Any, Dict, List, Optional
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
# =======================================================================
|
|
20
|
+
# Enums
|
|
21
|
+
# =======================================================================
|
|
22
|
+
|
|
23
|
+
class SimulationStatus(str, Enum):
|
|
24
|
+
PENDING = "pending"
|
|
25
|
+
RUNNING = "running"
|
|
26
|
+
SUCCESS = "success"
|
|
27
|
+
FAILED = "failed"
|
|
28
|
+
CANCELLED = "cancelled"
|
|
29
|
+
TIMEOUT = "timeout"
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
class SimulatorType(str, Enum):
|
|
33
|
+
FLASH = "FLASH"
|
|
34
|
+
FLYCHK = "FLYCHK"
|
|
35
|
+
UNKNOWN = "UNKNOWN"
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
class PhysicsDomain(str, Enum):
|
|
39
|
+
HEDP = "HEDP" # High-Energy-Density Physics
|
|
40
|
+
ICF = "ICF" # Inertial Confinement Fusion
|
|
41
|
+
LASER = "LASER" # Laser-Plasma Interaction
|
|
42
|
+
MAGNETIC = "MAGNETIC" # Magnetic Fusion
|
|
43
|
+
PLASMA = "PLASMA" # Plasma Physics
|
|
44
|
+
GENERAL = "GENERAL" # General plasma physics
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
# =======================================================================
|
|
48
|
+
# Data Models (dataclass-based, no pydantic dependency)
|
|
49
|
+
# =======================================================================
|
|
50
|
+
|
|
51
|
+
@dataclass
|
|
52
|
+
class InputVar:
|
|
53
|
+
"""Input variable specification."""
|
|
54
|
+
low: float
|
|
55
|
+
high: float
|
|
56
|
+
unit: str = ""
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
@dataclass
|
|
60
|
+
class OutputVar:
|
|
61
|
+
"""Output variable specification."""
|
|
62
|
+
dimensions: List[str] = field(default_factory=list)
|
|
63
|
+
unit: str = ""
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
@dataclass
|
|
67
|
+
class SimulationRequest:
|
|
68
|
+
"""Simulation request (standalone version, dataclass-based)."""
|
|
69
|
+
request_id: str = field(default_factory=lambda: datetime.now(timezone.utc).strftime("%Y%m%d_%H%M%S_%f"))
|
|
70
|
+
simulator_type: Optional[SimulatorType] = None
|
|
71
|
+
params: Dict[str, Any] = field(default_factory=dict)
|
|
72
|
+
work_dir: Optional[Path] = None
|
|
73
|
+
timeout: Optional[float] = None
|
|
74
|
+
metadata: Dict[str, Any] = field(default_factory=dict)
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
@dataclass
|
|
78
|
+
class SimulationResult:
|
|
79
|
+
"""Simulation result (standalone version, dataclass-based)."""
|
|
80
|
+
request_id: str = ""
|
|
81
|
+
status: SimulationStatus = SimulationStatus.PENDING
|
|
82
|
+
output_data: Dict[str, Any] = field(default_factory=dict)
|
|
83
|
+
raw_output_path: Optional[Path] = None
|
|
84
|
+
execution_time: float = 0.0
|
|
85
|
+
error_message: Optional[str] = None
|
|
86
|
+
metadata: Dict[str, Any] = field(default_factory=dict)
|
|
87
|
+
|
|
88
|
+
@property
|
|
89
|
+
def success(self) -> bool:
|
|
90
|
+
return self.status == SimulationStatus.SUCCESS
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
@dataclass
|
|
94
|
+
class CapabilityCard:
|
|
95
|
+
"""Simulator capability declaration (standalone, dataclass-based)."""
|
|
96
|
+
simulator_name: str = ""
|
|
97
|
+
simulator_type: SimulatorType = SimulatorType.UNKNOWN
|
|
98
|
+
version: str = ""
|
|
99
|
+
physics_domains: List[PhysicsDomain] = field(default_factory=list)
|
|
100
|
+
supported_dimensions: List[int] = field(default_factory=list)
|
|
101
|
+
input_schema: Dict[str, Any] = field(default_factory=dict)
|
|
102
|
+
output_schema: Dict[str, Any] = field(default_factory=dict)
|
|
103
|
+
estimated_runtime: str = ""
|
|
104
|
+
parallel_scalable: bool = False
|
|
105
|
+
requires_license: bool = False
|
|
106
|
+
homepage: str = ""
|
|
107
|
+
documentation: str = ""
|
|
108
|
+
physics_domain: PhysicsDomain = PhysicsDomain.GENERAL # legacy compat
|
|
109
|
+
input_vars: Dict[str, InputVar] = field(default_factory=dict)
|
|
110
|
+
output_vars: Dict[str, OutputVar] = field(default_factory=dict)
|
|
111
|
+
description: str = ""
|
|
112
|
+
|
|
113
|
+
|
|
114
|
+
__all__ = [
|
|
115
|
+
"SimulationStatus", "SimulatorType", "PhysicsDomain",
|
|
116
|
+
"InputVar", "OutputVar", "SimulationRequest", "SimulationResult",
|
|
117
|
+
"CapabilityCard",
|
|
118
|
+
]
|
flash/config/__init__.py
ADDED
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
"""
|
|
2
|
+
FLASH 仿真基本配置
|
|
3
|
+
═════════════════════
|
|
4
|
+
|
|
5
|
+
管理 FLASH 仿真的运行配置,包括:
|
|
6
|
+
- 本地运行 vs 超算 SSH 运行
|
|
7
|
+
- 超算硬件配置(节点数、CPU/GPU、内存)
|
|
8
|
+
- FLASH 可执行文件路径
|
|
9
|
+
- 编译选项
|
|
10
|
+
|
|
11
|
+
用法示例:
|
|
12
|
+
from flash.config import FlashConfig, get_default_config
|
|
13
|
+
|
|
14
|
+
config = get_default_config()
|
|
15
|
+
config.mode = "ssh" # 切换到超算模式
|
|
16
|
+
config.ssh.host = "ssh.cn-zhongwei-1.paracloud.com"
|
|
17
|
+
config.save()
|
|
18
|
+
"""
|
|
19
|
+
|
|
20
|
+
from pathlib import Path
|
|
21
|
+
from typing import Optional, Dict, Any
|
|
22
|
+
import json
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
DEFAULT_CONFIG_PATH = Path.home() / ".physimx" / "flash_config.json"
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
class FlashConfig:
|
|
29
|
+
"""FLASH 运行配置。"""
|
|
30
|
+
|
|
31
|
+
def __init__(
|
|
32
|
+
self,
|
|
33
|
+
mode: str = "local",
|
|
34
|
+
flash_exe_path: Optional[str] = None,
|
|
35
|
+
ssh_host: Optional[str] = None,
|
|
36
|
+
ssh_port: int = 22,
|
|
37
|
+
ssh_username: Optional[str] = None,
|
|
38
|
+
ssh_password: Optional[str] = None,
|
|
39
|
+
nodes: int = 1,
|
|
40
|
+
ppn: int = 32,
|
|
41
|
+
walltime: str = "01:00:00",
|
|
42
|
+
):
|
|
43
|
+
self.mode = mode # "local" | "ssh"
|
|
44
|
+
self.flash_exe_path = flash_exe_path
|
|
45
|
+
self.ssh_host = ssh_host
|
|
46
|
+
self.ssh_port = ssh_port
|
|
47
|
+
self.ssh_username = ssh_username
|
|
48
|
+
self.ssh_password = ssh_password
|
|
49
|
+
self.nodes = nodes
|
|
50
|
+
self.ppn = ppn
|
|
51
|
+
self.walltime = walltime
|
|
52
|
+
|
|
53
|
+
def to_dict(self) -> Dict[str, Any]:
|
|
54
|
+
return {
|
|
55
|
+
"mode": self.mode,
|
|
56
|
+
"flash_exe_path": self.flash_exe_path,
|
|
57
|
+
"ssh_host": self.ssh_host,
|
|
58
|
+
"ssh_port": self.ssh_port,
|
|
59
|
+
"ssh_username": self.ssh_username,
|
|
60
|
+
"ssh_password": self.ssh_password,
|
|
61
|
+
"nodes": self.nodes,
|
|
62
|
+
"ppn": self.ppn,
|
|
63
|
+
"walltime": self.walltime,
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
@classmethod
|
|
67
|
+
def from_dict(cls, d: Dict[str, Any]) -> "FlashConfig":
|
|
68
|
+
return cls(**d)
|
|
69
|
+
|
|
70
|
+
def save(self, path: Optional[Path] = None):
|
|
71
|
+
"""保存配置到 ~/.physimx/flash_config.json。"""
|
|
72
|
+
path = path or DEFAULT_CONFIG_PATH
|
|
73
|
+
path.parent.mkdir(parents=True, exist_ok=True)
|
|
74
|
+
with open(path, "w", encoding="utf-8") as f:
|
|
75
|
+
json.dump(self.to_dict(), f, indent=2, ensure_ascii=False)
|
|
76
|
+
print(f"[配置] 已保存: {path}")
|
|
77
|
+
|
|
78
|
+
@classmethod
|
|
79
|
+
def load(cls, path: Optional[Path] = None) -> "FlashConfig":
|
|
80
|
+
"""从文件加载配置。"""
|
|
81
|
+
path = path or DEFAULT_CONFIG_PATH
|
|
82
|
+
if not path.exists():
|
|
83
|
+
return cls() # 返回默认配置
|
|
84
|
+
with open(path, encoding="utf-8") as f:
|
|
85
|
+
d = json.load(f)
|
|
86
|
+
return cls.from_dict(d)
|
|
87
|
+
|
|
88
|
+
def __repr__(self) -> str:
|
|
89
|
+
return (
|
|
90
|
+
f"FlashConfig(mode={self.mode!r}, "
|
|
91
|
+
f"ssh={self.ssh_host if self.ssh_host else 'N/A'})"
|
|
92
|
+
)
|
|
93
|
+
|
|
94
|
+
|
|
95
|
+
def get_default_config() -> FlashConfig:
|
|
96
|
+
"""获取默认配置(优先从文件加载)。"""
|
|
97
|
+
return FlashConfig.load()
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
if __name__ == "__main__":
|
|
101
|
+
config = get_default_config()
|
|
102
|
+
print("当前配置:", config)
|
|
103
|
+
config.mode = "local"
|
|
104
|
+
config.save()
|
|
105
|
+
print("配置已保存到:", DEFAULT_CONFIG_PATH)
|