113 lines
4.1 KiB
Markdown
113 lines
4.1 KiB
Markdown
# Step 5: analysis-state
|
|
|
|
## 읽어야 할 파일
|
|
|
|
먼저 아래 파일들을 읽고 프로젝트의 아키텍처와 이전 step 산출물을 파악하라:
|
|
|
|
- `/AGENTS.md`
|
|
- `/docs/PRD.md`
|
|
- `/docs/ARCHITECTURE.md`
|
|
- `/docs/ADR.md`
|
|
- `/src/fesa/fem/dof_manager.hpp`
|
|
- `/tests/unit/dof_manager_numbering_test.cpp`
|
|
|
|
이전 step에서 만들어진 DofManager를 꼼꼼히 읽고, 해석 중 변하는 물리량은 AnalysisState가 소유하도록 유지하라.
|
|
|
|
## 작업
|
|
|
|
displacement 중심의 최소 `AnalysisState`를 `/src/fesa/analysis/`에 구현한다.
|
|
|
|
필수 파일:
|
|
|
|
- `/src/fesa/analysis/analysis_state.hpp`
|
|
- `/tests/unit/analysis_state_vectors_test.cpp`
|
|
|
|
필수 interface:
|
|
|
|
```cpp
|
|
namespace fesa::analysis {
|
|
|
|
struct IterationState {
|
|
double time = 0.0;
|
|
int increment = 0;
|
|
int iteration = 0;
|
|
};
|
|
|
|
class AnalysisState {
|
|
public:
|
|
explicit AnalysisState(int total_dof_count);
|
|
|
|
const std::vector<double>& displacement() const;
|
|
const std::vector<double>& velocity() const;
|
|
const std::vector<double>& acceleration() const;
|
|
const std::vector<double>& temperature() const;
|
|
const std::vector<double>& external_force() const;
|
|
const std::vector<double>& internal_force() const;
|
|
const std::vector<double>& residual() const;
|
|
|
|
void set_displacement(std::vector<double> values);
|
|
void set_external_force(std::vector<double> values);
|
|
void set_internal_force(std::vector<double> values);
|
|
void update_residual();
|
|
|
|
IterationState& iteration_state();
|
|
const IterationState& iteration_state() const;
|
|
|
|
void set_element_state(core::ElementId element_id, std::vector<double> state);
|
|
const std::vector<double>* element_state(core::ElementId element_id) const;
|
|
};
|
|
|
|
} // namespace fesa::analysis
|
|
```
|
|
|
|
구현 규칙:
|
|
|
|
- 모든 vector는 `total_dof_count` 크기로 초기화한다.
|
|
- `update_residual()`은 `external_force - internal_force`를 component-wise로 계산한다.
|
|
- setter는 입력 vector 크기가 맞지 않으면 `std::invalid_argument`를 던진다.
|
|
- temperature는 Phase skeleton에서 0.0 vector로 둔다.
|
|
- element state는 향후 integration point state 확장을 위한 최소 map으로 둔다.
|
|
- AnalysisState는 Domain, AnalysisModel, DofManager를 소유하지 않는다.
|
|
|
|
## Tests To Write First
|
|
|
|
- `/tests/unit/analysis_state_vectors_test.cpp`
|
|
- 생성 시 displacement/velocity/acceleration/temperature/force/residual vector 크기와 0.0 초기값을 확인한다.
|
|
- displacement setter가 값을 보존한다.
|
|
- external/internal force 설정 후 residual이 `Fext - Fint`가 되는지 확인한다.
|
|
- 크기가 맞지 않는 vector setter가 `std::invalid_argument`를 던진다.
|
|
- time/increment/iteration 값이 저장된다.
|
|
- element state를 element id로 저장/조회한다.
|
|
|
|
RED 확인:
|
|
|
|
1. 테스트 파일을 먼저 작성한다.
|
|
2. targeted CTest를 실행해 missing `analysis_state.hpp`로 실패함을 확인한다.
|
|
3. 그 뒤 production header를 작성한다.
|
|
|
|
## 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 analysis_state_vectors_test
|
|
```
|
|
|
|
## 검증 절차
|
|
|
|
1. 위 AC 커맨드를 실행한다.
|
|
2. 아키텍처 체크리스트를 확인한다:
|
|
- AnalysisState가 해석 중 변하는 물리량을 소유하는가?
|
|
- Domain이나 AnalysisModel을 복사/소유하지 않는가?
|
|
- displacement 중심이되 velocity/acceleration/temperature 확장 지점을 유지하는가?
|
|
3. 결과에 따라 `phases/solver-core-skeleton/index.json`의 step 5를 업데이트한다:
|
|
- 성공: `"status": "completed"`, `"summary": "AnalysisState vector ownership and residual update added"`
|
|
- 3회 수정 시도 후 실패: `"status": "error"`, `"error_message": "구체적 에러 내용"`
|
|
- 사용자 개입 필요: `"status": "blocked"`, `"blocked_reason": "구체적 사유"` 후 중단
|
|
|
|
## 금지사항
|
|
|
|
- Solver backend나 numerical integration loop를 구현하지 마라.
|
|
- HDF5 writer를 이 step에서 구현하지 마라.
|
|
- JavaScript/TypeScript/npm fallback을 추가하지 마라.
|