Compare commits
3 Commits
d55c78c694
...
88eb05ae94
| Author | SHA1 | Date | |
|---|---|---|---|
| 88eb05ae94 | |||
| 8d2d261564 | |||
| dffa67d505 |
12
Cargo.lock
generated
12
Cargo.lock
generated
@@ -2923,6 +2923,7 @@ dependencies = [
|
||||
"rand 0.9.2",
|
||||
"simul-core",
|
||||
"simul-euclidean",
|
||||
"simul-lattice",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -2957,6 +2958,17 @@ dependencies = [
|
||||
"thiserror",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "simul-lattice"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"approx",
|
||||
"nalgebra",
|
||||
"rand 0.9.2",
|
||||
"rand_distr",
|
||||
"simul-core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "slab"
|
||||
version = "0.4.12"
|
||||
|
||||
@@ -4,7 +4,7 @@ members = [
|
||||
"simul-core",
|
||||
"simul-euclidean",
|
||||
"simul-io",
|
||||
"simul",
|
||||
"simul", "simul-lattice",
|
||||
]
|
||||
|
||||
[workspace.package]
|
||||
@@ -30,4 +30,5 @@ approx = "0.5"
|
||||
# Internal crates
|
||||
simul-core = { path = "simul-core" }
|
||||
simul-euclidean = { path = "simul-euclidean" }
|
||||
simul-io = { path = "simul-io" }
|
||||
simul-io = { path = "simul-io" }
|
||||
simul-lattice = { path = "simul-lattice" }
|
||||
|
||||
19
PROGRESS.md
19
PROGRESS.md
@@ -38,13 +38,14 @@
|
||||
|
||||
| # | 단위 | 상태 | 시간 | LOC | Tier-1 | 패턴 | 비고 |
|
||||
|---|---|---|---:|---:|---:|---|---|
|
||||
| 1 | Trait 정렬 fix (`Interaction` ↔ `ForceInteraction`) | ⬜ | 한나절 | ~50 | — | P1 | **첫 PR**. 후속 모두의 base. |
|
||||
| 2 | `simul-lattice/` canary (1D random walker) | ⬜ | 1주 | ~200 | (+1 canary) | P1+P2 | 4중 방어선 §11.6-(a) |
|
||||
| 3 | `RMSDForce` → `RmsdInteraction<D>` | ⬜ | 1–2일 | ~150 | +1 | P1 | Theobald–Liu quat align |
|
||||
| 4 | `RGForce` → `RgInteraction<D>` | ⬜ | 1일 | ~80 | +1 | P1 | 단순 — Σ\|r−r_cm\|²/N |
|
||||
| 5 | `OrientationRestraintForce` | ⬜ | 2일 | ~150 | +1 | P1 | rotation matrix |
|
||||
| 6 | `AndersenThermostat` → `Thermostat` trait | ⬜ | 1일 | ~120 | +1 | P12 | VelocityModifier 패턴 정착 |
|
||||
| 7 | Tier-1 wrapper 14건 (Verlet/Langevin/Brownian 단발 + System/Spline/SplineFitter/MultipleForces 등) | ⬜ | 며칠 | ~600 | +14 (현재 2 → 16) | — | T5 addendum §3 게이팅 표 |
|
||||
| 1 | `simul-lattice/` canary (1D random walker) | ⬜ | 1주 | ~200 | (+1 canary) | P2 | 4중 방어선 §11.6-(a). **추상 결정의 데이터 포인트 #2**. |
|
||||
| 2 | 추상 재설계 결정 (Handle을 simul-core로 lift할지) | ⬜ | 한나절 | — | — | P1 | canary 결과 기반. ROADMAP §6 P1 갱신. |
|
||||
| 3 | Trait 정렬 (`Interaction` ↔ `EuclideanInteraction`) | ⬜ | 한나절~1일 | ~50 | — | P1 | (2)에서 결정한 모양으로. |
|
||||
| 4 | `RMSDForce` → `RmsdInteraction<D>` | ⬜ | 1–2일 | ~150 | +1 | P1 | Theobald–Liu quat align |
|
||||
| 5 | `RGForce` → `RgInteraction<D>` | ⬜ | 1일 | ~80 | +1 | P1 | 단순 — Σ\|r−r_cm\|²/N |
|
||||
| 6 | `OrientationRestraintForce` | ⬜ | 2일 | ~150 | +1 | P1 | rotation matrix |
|
||||
| 7 | `AndersenThermostat` → `Thermostat` trait | ⬜ | 1일 | ~120 | +1 | P12 | VelocityModifier 패턴 정착 |
|
||||
| 8 | Tier-1 wrapper 14건 (Verlet/Langevin/Brownian 단발 + System/Spline/SplineFitter/MultipleForces 등) | ⬜ | 며칠 | ~600 | +14 (현재 2 → 16) | — | T5 addendum §3 게이팅 표 |
|
||||
|
||||
**M0+ DoD**:
|
||||
- `cargo test --workspace` 통과
|
||||
@@ -152,9 +153,9 @@
|
||||
|
||||
## 6. 다음 한 단위 (지금 무엇)
|
||||
|
||||
> ⏭ **trait 정렬 fix** (M0+ #1, 한나절)
|
||||
> ⏭ **simul-lattice canary (1D random walker)** (M0+ #1, 1주)
|
||||
>
|
||||
> 이유: 후속 모든 force/integrator 의 base. 현재 `simul-core::Interaction` 과 `simul-euclidean::ForceInteraction` 부정합 (T6 §3.1). 가장 즉시 효과 큰 한 줄 작업. `_template_openmm.rs` 의 Phase 1 정책 주의 블록도 이 fix 후 갱신 가능.
|
||||
> 이유: trait 추상 재설계의 데이터 포인트 #2 확보 — Handle을 simul-core로 lift할지를 *예측*이 아니라 *발견*으로 결정하기 위함. 4중 방어선 §11.6-(a) 살아있는 가드레일도 동시 설치. 1D random walker는 simul-core trait만 사용 — `ForceInteraction` 부정합과 독립이므로 trait fix 선행 불필요.
|
||||
>
|
||||
> 디테일: `learning/M0+.md` §1.
|
||||
|
||||
|
||||
190
learning/M0+.md
190
learning/M0+.md
@@ -10,76 +10,19 @@
|
||||
|
||||
| 순 | 단위 | 시간 | 의존 |
|
||||
|---:|---|---|---|
|
||||
| 1 | **Trait 정렬 fix** | 한나절 | — (이게 후속 모두의 base) |
|
||||
| 2 | **simul-lattice canary** | 1주 | (1) — fix 된 trait 위에서 lattice 가 컴파일되는지 검증 |
|
||||
| 3 | RMSD / RG / OrientationRestraint | 4–5일 | (1) |
|
||||
| 4 | AndersenThermostat → `Thermostat` trait | 1일 | (1) |
|
||||
| 5 | Tier-1 wrapper 14건 | 며칠 | (1)~(4) |
|
||||
| 1 | **simul-lattice canary** (1D random walker) | 1주 | — (simul-core 만 사용, trait fix 와 독립) |
|
||||
| 2 | **추상 재설계 결정** | 한나절 | (1) — canary 결과로 Handle을 simul-core lift할지 결정 |
|
||||
| 3 | **Trait 정렬 fix** | 한나절~1일 | (2) — 결정된 모양으로 실행 |
|
||||
| 4 | RMSD / RG / OrientationRestraint | 4–5일 | (3) |
|
||||
| 5 | AndersenThermostat → `Thermostat` trait | 1일 | (3) |
|
||||
| 6 | Tier-1 wrapper 14건 | 며칠 | (3)~(5) |
|
||||
|
||||
> (1)~(2) 는 *아키텍처* 작업이고 (3)~(5) 는 *구현* 작업이다. 1주차에 (1)+(2) 를 못 끝내면 후순위 단위들이 모두 흔들린다.
|
||||
> (1)~(3) 은 *아키텍처* 작업이다 — 추상이 lattice + euclidean 두 데이터 포인트로 결정된 후 trait fix 실행. (4)~(6) 은 *구현* 작업.
|
||||
> canary 가 trait fix 에 의존하지 않는 이유: 1D random walker 는 `Dynamics<Lattice<1>>` + `StateSpace` 만 사용하며 simul-euclidean 의 `ForceInteraction` 과 무관 — 부정합과 독립.
|
||||
|
||||
---
|
||||
|
||||
## 1. Trait 정렬 fix
|
||||
|
||||
### 배경 (T6 §3.1)
|
||||
현재:
|
||||
```rust
|
||||
// simul-core/src/interaction.rs
|
||||
pub trait Interaction<S: StateSpace>: Send + Sync + Debug {
|
||||
type Output;
|
||||
fn compute(&self, state: &SystemState<S>) -> Self::Output;
|
||||
fn name(&self) -> &'static str;
|
||||
}
|
||||
|
||||
// simul-euclidean/src/interaction/mod.rs
|
||||
pub trait ForceInteraction<const D: usize> {
|
||||
fn compute_forces(
|
||||
&self,
|
||||
client: &Client,
|
||||
positions: &Handle,
|
||||
forces: &mut Handle,
|
||||
n: usize,
|
||||
) -> f64;
|
||||
}
|
||||
```
|
||||
|
||||
`ForceInteraction` 이 `Interaction` 을 구현하지 않는다. 두 trait 가 평행 — `Interaction::Output` associated type 이 lattice 까지 수용 가능한 추상인데 ForceInteraction 이 그 추상을 *우회* 한다.
|
||||
|
||||
### 권고 (T7 P1)
|
||||
`ForceInteraction` 을 `Interaction` 의 *sub-trait* 로:
|
||||
```rust
|
||||
// simul-euclidean
|
||||
pub trait ForceInteraction<const D: usize>:
|
||||
Interaction<Euclidean<D>, Output = (DeviceForces, f64)>
|
||||
{
|
||||
fn compute_forces(...); // 기존 시그니처 유지
|
||||
}
|
||||
```
|
||||
|
||||
또는 간단하게: `Interaction::compute()` 를 `ForceInteraction::compute_forces` 의 wrapper 로 자동 구현하는 default impl 추가.
|
||||
|
||||
### Definition of Done
|
||||
- [ ] `simul-core::Interaction` 이 `ForceInteraction` 의 super-trait
|
||||
- [ ] `cargo test --workspace` 통과 (`nonbonded_openmm.rs` / `harmonic_bond_openmm.rs` 무수정)
|
||||
- [ ] `_template_openmm.rs` 상단의 "trait 부정합 (T6 §3.1) 때문에 일시적" 주석 갱신 또는 제거
|
||||
- [ ] DESIGN.md §"Core Abstractions" 의 trait 다이어그램 갱신
|
||||
|
||||
### 함정
|
||||
- `Interaction::Output` 와 `ForceInteraction::compute_forces` 의 반환 타입이 다르면 super-trait 관계가 안 됨 → associated type 으로 통합
|
||||
- `Send + Sync + Debug + 'static` bound 일관성
|
||||
|
||||
### 학습 가치
|
||||
**중**. Rust trait 의 sub-trait + associated type 조합. `where Self: SuperTrait<...>` ergonomic.
|
||||
|
||||
### 참고 자료
|
||||
- ROADMAP §6 P1
|
||||
- `.team-output/T6-rust-architect.md` §3.1
|
||||
- `.team-output/T7-rust-architect.md` §P1
|
||||
|
||||
---
|
||||
|
||||
## 2. simul-lattice canary (1D random walker)
|
||||
## 1. simul-lattice canary (1D random walker)
|
||||
|
||||
### 배경
|
||||
ROADMAP §11.6-(a). simul-core trait 가 MD-specific 으로 부풀어 오르는 것을 잡기 위한 살아있는 가드레일.
|
||||
@@ -144,7 +87,112 @@ ROADMAP §11.6-(a). simul-core trait 가 MD-specific 으로 부풀어 오르는
|
||||
|
||||
---
|
||||
|
||||
## 3. RMSDForce → `RmsdInteraction<D>`
|
||||
## 2. 추상 재설계 결정
|
||||
|
||||
### 배경
|
||||
canary 구현이 끝난 시점의 *결정 게이트*. `simul-core::Interaction` 에 device handle 개념을 lift 할지, simul-euclidean 에만 sub-trait 으로 둘지를 **두 데이터 포인트** (Euclidean MD + Lattice random walker) 기반으로 결정. 추상을 *예측* 이 아니라 *발견* 으로 정의.
|
||||
|
||||
### 결정 트리
|
||||
- **canary 가 host `Vec<i64>` 만으로 충분** (기대 시나리오) → Handle 을 simul-core 에 올리지 않음. `EuclideanInteraction: Interaction<Euclidean<D>, Output = ForceOutput<D>>` sub-trait 이 device path 를 보유. §3 Trait 정렬 fix 는 sub-trait 추가만 (한나절).
|
||||
- **canary 가 어떤 형태든 buffer/storage 추상을 자연스럽게 요구** → `StateSpace::Buffer` associated type 을 simul-core 에 도입. `SystemState` 리팩터 동반 → 한나절 스코프 초과 → 별도 마일스톤으로 격상.
|
||||
- **결정 보류** (1D random walker 가 너무 trivial 해서 데이터가 부족) → "현재로서 lift 할 근거 없음, M3 (lattice MC 본격) 시 재평가" 로 결정. 결정 자체도 결정.
|
||||
|
||||
### Definition of Done
|
||||
- [ ] 결정 문서 `learning/decisions/abstraction-after-canary.md` 작성 (1페이지)
|
||||
- [ ] DESIGN.md "Core Abstractions" 의 trait 다이어그램에 결정 반영
|
||||
- [ ] §3 Trait 정렬 fix 의 구체 시그니처 (이름: `EuclideanInteraction` 권장) 가 결정됨
|
||||
|
||||
### 함정
|
||||
- 아키텍처를 *예쁘게* 만들려고 lattice 가 필요로 하지 않는 추상을 simul-core 에 끌어오지 말 것. YAGNI.
|
||||
- 반대로, canary 에서 *명백히* device-like 추상이 필요한데 simul-euclidean 에만 두면 다음 lattice 작업 (M3) 에서 또 trait drift 가 생긴다. 두 방향 모두 위험.
|
||||
- 결정 문서를 만들지 않으면 "왜 이 모양이지?" 가 6개월 후 잊힘 → 반드시 짧게라도 기록.
|
||||
|
||||
### 학습 가치
|
||||
**상**. 추상을 *예측* 이 아니라 *발견* 으로 정의하는 절차 자체. 결정 문서화 패턴 ADR (Architecture Decision Record).
|
||||
|
||||
### 참고
|
||||
- 본 M0+.md §1 (canary 결과)
|
||||
- ROADMAP §6 P1, §11.6
|
||||
- `.team-output/T6-rust-architect.md` §3.1 (현 trait 부정합 진단)
|
||||
- `.team-output/T7-rust-architect.md` §P1
|
||||
|
||||
---
|
||||
|
||||
## 3. Trait 정렬 fix
|
||||
|
||||
### 배경 (T6 §3.1)
|
||||
현재:
|
||||
```rust
|
||||
// simul-core/src/interaction.rs
|
||||
pub trait Interaction<S: StateSpace>: Send + Sync + Debug {
|
||||
type Output;
|
||||
fn compute(&self, state: &SystemState<S>) -> Self::Output;
|
||||
fn name(&self) -> &'static str;
|
||||
}
|
||||
|
||||
// simul-euclidean/src/interaction/mod.rs
|
||||
pub trait ForceInteraction<const D: usize> {
|
||||
fn compute_forces(
|
||||
&self,
|
||||
client: &Client,
|
||||
positions: &Handle,
|
||||
forces: &mut Handle,
|
||||
n: usize,
|
||||
) -> f64;
|
||||
}
|
||||
```
|
||||
|
||||
`ForceInteraction` 이 `Interaction` 을 구현하지 않는다. 두 trait 가 평행 — `Interaction::Output` associated type 이 lattice 까지 수용 가능한 추상인데 ForceInteraction 이 그 추상을 *우회* 한다.
|
||||
|
||||
### 권고 (T7 P1, §2 결정 결과 반영)
|
||||
§2 의 결정에 따라 두 가지 모양 중 하나:
|
||||
|
||||
**(a) sub-trait** (Handle simul-core 에 lift 안 함):
|
||||
```rust
|
||||
// simul-euclidean
|
||||
pub trait EuclideanInteraction<const D: usize>:
|
||||
Interaction<Euclidean<D>, Output = (DeviceForces, f64)>
|
||||
{
|
||||
fn compute_forces(...); // 기존 시그니처 유지
|
||||
}
|
||||
```
|
||||
|
||||
**(b) Buffer associated type** (Handle 을 simul-core 로 lift):
|
||||
```rust
|
||||
// simul-core
|
||||
pub trait StateSpace {
|
||||
type Point;
|
||||
type Momentum;
|
||||
type Buffer; // Handle for Euclidean, Vec for Lattice
|
||||
...
|
||||
}
|
||||
```
|
||||
|
||||
(b) 채택 시 SystemState 리팩터 동반 → 별도 마일스톤. (a) 가 한나절 스코프 기본값.
|
||||
|
||||
또는 간단하게: `Interaction::compute()` 를 `ForceInteraction::compute_forces` 의 wrapper 로 자동 구현하는 default impl 추가 — (a) 의 변형.
|
||||
|
||||
### Definition of Done
|
||||
- [ ] `simul-core::Interaction` 이 `EuclideanInteraction` (구 `ForceInteraction`) 의 super-trait
|
||||
- [ ] `cargo test --workspace` 통과 (`nonbonded_openmm.rs` / `harmonic_bond_openmm.rs` 무수정)
|
||||
- [ ] `_template_openmm.rs` 상단의 "trait 부정합 (T6 §3.1) 때문에 일시적" 주석 갱신 또는 제거
|
||||
- [ ] DESIGN.md §"Core Abstractions" 의 trait 다이어그램 갱신
|
||||
|
||||
### 함정
|
||||
- `Interaction::Output` 와 `ForceInteraction::compute_forces` 의 반환 타입이 다르면 super-trait 관계가 안 됨 → associated type 으로 통합
|
||||
- `Send + Sync + Debug + 'static` bound 일관성
|
||||
|
||||
### 학습 가치
|
||||
**중**. Rust trait 의 sub-trait + associated type 조합. `where Self: SuperTrait<...>` ergonomic.
|
||||
|
||||
### 참고 자료
|
||||
- ROADMAP §6 P1
|
||||
- `.team-output/T6-rust-architect.md` §3.1
|
||||
- `.team-output/T7-rust-architect.md` §P1
|
||||
|
||||
---
|
||||
|
||||
## 4. RMSDForce → `RmsdInteraction<D>`
|
||||
|
||||
### 배경
|
||||
OpenMM `RMSDForce`: 두 입자 set 사이의 root-mean-square deviation. 보통 reference 분자와 정렬 후 RMSD 계산. Theobald–Liu (quaternion-based) 알고리즘이 표준.
|
||||
@@ -177,7 +225,7 @@ OpenMM `RMSDForce`: 두 입자 set 사이의 root-mean-square deviation. 보통
|
||||
|
||||
---
|
||||
|
||||
## 4. RGForce → `RgInteraction<D>`
|
||||
## 5. RGForce → `RgInteraction<D>`
|
||||
|
||||
### 배경
|
||||
Radius of gyration: `R_g² = Σᵢ |rᵢ − r_cm|² / N`. 또는 mass-weighted: `Σᵢ mᵢ |rᵢ − r_cm|² / Σᵢ mᵢ`.
|
||||
@@ -205,7 +253,7 @@ Radius of gyration: `R_g² = Σᵢ |rᵢ − r_cm|² / N`. 또는 mass-weighted:
|
||||
|
||||
---
|
||||
|
||||
## 5. OrientationRestraintForce
|
||||
## 6. OrientationRestraintForce
|
||||
|
||||
### 배경
|
||||
참조 분자에 대한 *회전* 제약. `E = k · (1 − cos²(θ))` 또는 quaternion 기반.
|
||||
@@ -235,7 +283,7 @@ Radius of gyration: `R_g² = Σᵢ |rᵢ − r_cm|² / N`. 또는 mass-weighted:
|
||||
|
||||
---
|
||||
|
||||
## 6. AndersenThermostat → `Thermostat` trait
|
||||
## 7. AndersenThermostat → `Thermostat` trait
|
||||
|
||||
### 배경
|
||||
일정 확률 `ν · dt` 로 입자의 속도를 Maxwell–Boltzmann 분포에서 새로 추첨. 캐노니컬 앙상블 (NVT) 의 단순 구현.
|
||||
@@ -267,7 +315,7 @@ Radius of gyration: `R_g² = Σᵢ |rᵢ − r_cm|² / N`. 또는 mass-weighted:
|
||||
|
||||
---
|
||||
|
||||
## 7. Tier-1 wrapper 14건
|
||||
## 8. Tier-1 wrapper 14건
|
||||
|
||||
### 배경
|
||||
`tests/UPSTREAM_TESTS.md` §2 의 "현재 시점 ~14개" 게이팅. 새 *force/integrator 구현* 이 아니라 *기존 simul 의 등가성 검증* 을 추가.
|
||||
|
||||
16
simul-lattice/Cargo.toml
Normal file
16
simul-lattice/Cargo.toml
Normal file
@@ -0,0 +1,16 @@
|
||||
[package]
|
||||
name = "simul-lattice"
|
||||
description = "Lattice space simulations (MD, Brownian, Langevin) for the simul framework"
|
||||
version.workspace = true
|
||||
edition.workspace = true
|
||||
license.workspace = true
|
||||
|
||||
[dependencies]
|
||||
simul-core = { workspace = true }
|
||||
nalgebra = { workspace = true }
|
||||
rand = { workspace = true }
|
||||
rand_distr = { workspace = true }
|
||||
|
||||
[dev-dependencies]
|
||||
approx = { workspace = true }
|
||||
nalgebra = { workspace = true }
|
||||
47
simul-lattice/examples/random_walk_1d.rs
Normal file
47
simul-lattice/examples/random_walk_1d.rs
Normal file
@@ -0,0 +1,47 @@
|
||||
//! Example: 1D simple random walk
|
||||
//!
|
||||
//! Runs N_TRIAL independent walks of TIME steps each, then verifies the
|
||||
//! diffusive scaling: for a 1D simple random walk, <x(t)> = 0 and <x^2(t)> = t.
|
||||
|
||||
use nalgebra::SVector;
|
||||
use rand::{SeedableRng, rngs::StdRng};
|
||||
use simul_core::dynamics::Dynamics;
|
||||
use simul_core::state::SystemState;
|
||||
use simul_lattice::prelude::*;
|
||||
|
||||
fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
const N_TRIAL: usize = 10000;
|
||||
const TIME: usize = 1000;
|
||||
|
||||
let mut rng = StdRng::seed_from_u64(42);
|
||||
let dynamics = RandomWalk1D;
|
||||
|
||||
let mut sum_x = 0.0_f64;
|
||||
let mut sum_x2 = 0.0_f64;
|
||||
|
||||
for _ in 0..N_TRIAL {
|
||||
let mut state: SystemState<Lattice<1>> = SystemState::new();
|
||||
state.positions.push(SVector::<i32, 1>::zeros());
|
||||
|
||||
for _ in 0..TIME {
|
||||
dynamics.step(&mut state, &mut rng);
|
||||
}
|
||||
|
||||
let x = state.positions[0][0] as f64;
|
||||
sum_x += x;
|
||||
sum_x2 += x * x;
|
||||
}
|
||||
|
||||
let mean = sum_x / N_TRIAL as f64;
|
||||
let var = sum_x2 / N_TRIAL as f64;
|
||||
|
||||
println!("RandomWalk1D - 1D simple random walk");
|
||||
println!("=====================================");
|
||||
println!(" Trials : {}", N_TRIAL);
|
||||
println!(" Steps / trial : {}", TIME);
|
||||
println!();
|
||||
println!(" <x> = {:>8.3} (expected ~ 0)", mean);
|
||||
println!(" <x^2> = {:>8.3} (expected ~ {})", var, TIME);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
28
simul-lattice/src/dynamics/mod.rs
Normal file
28
simul-lattice/src/dynamics/mod.rs
Normal file
@@ -0,0 +1,28 @@
|
||||
//! Dynamics implementations for Lattice space
|
||||
|
||||
use crate::space::Lattice;
|
||||
use rand::Rng;
|
||||
use simul_core::dynamics::{Dynamics, TimeType};
|
||||
use simul_core::state::SystemState;
|
||||
|
||||
/// Single particle 1D Random Walk dynamics
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
pub struct RandomWalk1D;
|
||||
|
||||
impl Dynamics<Lattice<1>> for RandomWalk1D {
|
||||
fn step<R: Rng>(&self, state: &mut SystemState<Lattice<1>>, rng: &mut R) -> f64 {
|
||||
for p in state.positions.iter_mut() {
|
||||
p[0] += if rng.random_bool(0.5) { 1 } else { -1 };
|
||||
}
|
||||
1.0 // discrete step
|
||||
}
|
||||
fn time_type(&self) -> TimeType {
|
||||
TimeType::Discrete
|
||||
}
|
||||
fn is_deterministic(&self) -> bool {
|
||||
false
|
||||
}
|
||||
fn name(&self) -> &'static str {
|
||||
"RandomWalk1D"
|
||||
}
|
||||
}
|
||||
15
simul-lattice/src/lib.rs
Normal file
15
simul-lattice/src/lib.rs
Normal file
@@ -0,0 +1,15 @@
|
||||
//! simul-lattice: Discrete space simulations
|
||||
//!
|
||||
//! This crate provides implementations for simulations in discrete space:
|
||||
//! - Molecular dynamics (Verlet integrator)
|
||||
//! - Langevin dynamics (stochastic)
|
||||
//! - Brownian dynamics (overdamped)
|
||||
|
||||
pub mod dynamics;
|
||||
pub mod space;
|
||||
|
||||
pub mod prelude {
|
||||
//! Convenient re-exports for common use
|
||||
pub use crate::dynamics::RandomWalk1D;
|
||||
pub use crate::space::Lattice;
|
||||
}
|
||||
58
simul-lattice/src/space.rs
Normal file
58
simul-lattice/src/space.rs
Normal file
@@ -0,0 +1,58 @@
|
||||
//! Lattice space implementation
|
||||
|
||||
use nalgebra::SVector;
|
||||
use simul_core::space::StateSpace;
|
||||
|
||||
/// D-dimensional Lattice space
|
||||
///
|
||||
/// This is the standard discrete space for molecular dynamics and Brownian motion.
|
||||
/// Points are represented as D-dimensional vectors of i32.
|
||||
#[derive(Clone, Debug, Default)]
|
||||
pub struct Lattice<const D: usize>;
|
||||
|
||||
impl<const D: usize> StateSpace for Lattice<D> {
|
||||
const DIM: usize = D;
|
||||
|
||||
type Point = SVector<i32, D>;
|
||||
type Momentum = ();
|
||||
|
||||
fn is_continuous() -> bool {
|
||||
false
|
||||
}
|
||||
|
||||
fn name() -> &'static str {
|
||||
match D {
|
||||
1 => "Lattice 1D",
|
||||
2 => "Lattice 2D",
|
||||
3 => "Lattice 3D",
|
||||
_ => "Lattice ND",
|
||||
}
|
||||
}
|
||||
|
||||
fn zero_point() -> Self::Point {
|
||||
SVector::zeros()
|
||||
}
|
||||
|
||||
fn zero_momentum() -> Self::Momentum {}
|
||||
}
|
||||
|
||||
/// Type alias for 1D Lattice space
|
||||
pub type Space1D = Lattice<1>;
|
||||
|
||||
/// Type alias for 2D Lattice space
|
||||
pub type Space2D = Lattice<2>;
|
||||
|
||||
/// Type alias for 3D Lattice space
|
||||
pub type Space3D = Lattice<3>;
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn test_lattice_3d() {
|
||||
assert_eq!(Lattice::<3>::DIM, 3);
|
||||
assert!(!Lattice::<3>::is_continuous());
|
||||
assert_eq!(Lattice::<3>::name(), "Lattice 3D");
|
||||
}
|
||||
}
|
||||
@@ -8,14 +8,15 @@ license.workspace = true
|
||||
[features]
|
||||
default = ["euclidean"]
|
||||
euclidean = ["simul-euclidean"]
|
||||
# lattice = ["simul-lattice"] # Future
|
||||
lattice = ["simul-lattice"]
|
||||
|
||||
[dependencies]
|
||||
simul-core = { workspace = true }
|
||||
simul-euclidean = { workspace = true, optional = true }
|
||||
simul-lattice = { workspace = true, optional = true }
|
||||
nalgebra = { workspace = true }
|
||||
rand = { workspace = true }
|
||||
# simul-lattice = { workspace = true, optional = true } # Future
|
||||
|
||||
|
||||
[[example]]
|
||||
name = "hello_argon"
|
||||
|
||||
@@ -27,6 +27,10 @@ pub use simul_core as core;
|
||||
#[cfg(feature = "euclidean")]
|
||||
pub use simul_euclidean as euclidean;
|
||||
|
||||
// Re-export lattice (when feature enabled)
|
||||
#[cfg(feature = "lattice")]
|
||||
pub use simul_lattice as lattice;
|
||||
|
||||
pub mod prelude {
|
||||
//! Convenient re-exports for common use
|
||||
//!
|
||||
@@ -43,4 +47,8 @@ pub mod prelude {
|
||||
// Euclidean types (when enabled)
|
||||
#[cfg(feature = "euclidean")]
|
||||
pub use simul_euclidean::prelude::*;
|
||||
|
||||
// Lattice types (when enabled)
|
||||
#[cfg(feature = "lattice")]
|
||||
pub use simul_lattice::prelude::*;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user