Files
FESADev/phases/solver-core-skeleton/step4.md
T
2026-06-12 01:31:31 +09:00

113 lines
4.2 KiB
Markdown

# Step 4: dof-manager
## 읽어야 할 파일
먼저 아래 파일들을 읽고 프로젝트의 아키텍처와 이전 step 산출물을 파악하라:
- `/AGENTS.md`
- `/docs/PRD.md`
- `/docs/ARCHITECTURE.md`
- `/docs/ADR.md`
- `/src/fesa/model/boundary_condition.hpp`
- `/src/fesa/analysis/analysis_model.hpp`
- `/tests/unit/analysis_model_view_test.cpp`
이전 step에서 만들어진 model object와 AnalysisModel을 꼼꼼히 읽고, equation numbering이 Node/Element로 새지 않도록 유지하라.
## 작업
node별 DOF 정의, constrained/free mapping, equation numbering, sparse pattern ownership의 최소 골격을 `/src/fesa/fem/`에 구현한다.
필수 파일:
- `/src/fesa/fem/dof_key.hpp`
- `/src/fesa/fem/dof_manager.hpp`
- `/tests/unit/dof_manager_numbering_test.cpp`
필수 interface:
```cpp
namespace fesa::fem {
struct DofKey {
core::NodeId node_id;
model::DofComponent component;
};
bool operator==(const DofKey& lhs, const DofKey& rhs);
class DofManager {
public:
void define_node_dofs(core::NodeId node_id, std::vector<model::DofComponent> components);
void apply_boundary_condition(const model::BoundaryCondition& bc);
void number_equations();
int total_dof_count() const;
int free_dof_count() const;
int constrained_dof_count() const;
bool is_constrained(DofKey key) const;
int equation_id(DofKey key) const;
std::optional<int> free_equation_id(DofKey key) const;
std::vector<double> expand_free_vector(const std::vector<double>& free_values) const;
const std::vector<std::pair<int, int>>& sparse_pattern() const;
};
} // namespace fesa::fem
```
구현 규칙:
- Equation id는 `DofManager` 내부에만 저장한다.
- `equation_id`는 전체 DOF ordering의 dense id를 반환한다.
- `free_equation_id`는 constrained DOF면 `std::nullopt`를 반환한다.
- `number_equations()`는 deterministic ordering을 보장한다:
- node id value 오름차순
- component enum 순서 오름차순
- `expand_free_vector`는 constrained DOF 값을 0.0으로 채우고 free DOF 값만 배치한다.
- `sparse_pattern()`은 skeleton 단계에서 free equation ids의 dense full matrix pattern을 deterministic pair list로 보유해도 된다.
- missing DOF 조회는 `std::invalid_argument`를 던진다.
## Tests To Write First
- `/tests/unit/dof_manager_numbering_test.cpp`
- 두 node에 `ux`, `uy`를 정의하고 deterministic equation id ordering을 확인한다.
- boundary condition 적용 후 constrained/free count가 맞는지 확인한다.
- constrained key의 `free_equation_id``std::nullopt`임을 확인한다.
- free vector가 full vector로 재구성될 때 constrained DOF가 0.0으로 채워지는지 확인한다.
- sparse pattern pair list가 free equation id 기반 deterministic dense pattern을 가진다.
- model::Node나 model::Element를 수정하지 않고도 equation numbering이 가능함을 확인한다.
RED 확인:
1. 테스트 파일을 먼저 작성한다.
2. targeted CTest를 실행해 missing `dof_manager.hpp`로 실패함을 확인한다.
3. 그 뒤 production headers를 작성한다.
## Acceptance Criteria
```powershell
python -m unittest discover -s scripts -p "test_*.py"
python scripts/validate_workspace.py
ctest --test-dir build/msvc-debug --output-on-failure -C Debug -R dof_manager_numbering_test
```
## 검증 절차
1. 위 AC 커맨드를 실행한다.
2. 아키텍처 체크리스트를 확인한다:
- DofManager가 equation numbering을 전담하는가?
- Node/Element public interface가 equation id로 오염되지 않았는가?
- sparse pattern ownership이 DofManager 내부에 있는가?
3. 결과에 따라 `phases/solver-core-skeleton/index.json`의 step 4를 업데이트한다:
- 성공: `"status": "completed"`, `"summary": "DofManager deterministic numbering and constrained/free mapping added"`
- 3회 수정 시도 후 실패: `"status": "error"`, `"error_message": "구체적 에러 내용"`
- 사용자 개입 필요: `"status": "blocked"`, `"blocked_reason": "구체적 사유"` 후 중단
## 금지사항
- Solver backend, assembly matrix, MKL adapter를 구현하지 마라.
- Node 또는 Element에 equation id field를 추가하지 마라.
- JavaScript/TypeScript/npm fallback을 추가하지 마라.