Core Domain Model
Core Domain Model
The SamLabs.Armatura.Core layer holds the types that analysis and design work against directly. The critical takeaway is that these abstractions exist to reflect engineering responsibilities, strictly excluding editor responsibilities.
The Top-Level Container (ArmaturaProject) A structural model alone is not the whole story. ArmaturaProject serves as the container for one or more StructuralModel instances, the active design code, project-level extensions, and persistence.
- The Why: Operations like load combination generation, evaluation, result-set building, and design-code selection require context that spans beyond a single physical model.
The Main Engineering Object (StructuralModel) This is the central object for a single structure, owning its nodes, members, supports, materials, sections, loads, and the current AnalysisResultSet. Specific ownership rules dictate how changes propagate:
-
Centralized Data: Nodal and distributed loads are stored centrally on the model rather than on individual entities.
-
Model-Scoped Results: Results are attached to the model as a whole, not incrementally cached on each member or node. The Why: Because structural analysis is inherently model-scoped, the primary result object must be model-scoped as well.
Conservative Result Invalidation When analysis-relevant inputs change (like editing loads or supports), StructuralModel.Results is completely invalidated and discarded.
- The Why: While fine-grained, selective partial reuse sounds efficient, a blunt "discard and replace" strategy favors correctness. It keeps result validity completely predictable and prevents subtle stale-result bugs.
Centralized Materials and Sections Members do not own private copies of their materials or sections.
- The Why: By canonicalizing these references through
EnsureMaterial(...)andEnsureSection(...), the system keeps the active list explicit and avoids silent, accidental duplication across the model.
Typed Load Cases and Combinations Load cases are explicitly typed (e.g., DeadLoadCase, LiveLoadCase).
- The Why: These types are not cosmetic; they carry explicit behaviors—such as
DeadLoadCase.IncludeSelfWeight—that drive how combination generation and design-code workflows behave. Furthermore, the model explicitly supports both user-stored combinations and dynamically generated evaluation scenarios.
Immutable Analysis Snapshots (AnalysisResultSet) Once the analysis pipeline finishes, it produces an immutable AnalysisResultSet containing displacements, reactions, and member forces.
- The Why: It is meant to be queried, never mutated. This keeps the read side dead simple: the model either has a valid result set for its exact current state, or it does not.
Decoupled Design-Code Evaluation Eurocode evaluation logic (clause checks, deflection checks, second-order sensitivity) is substantial but operates through the project rather than being baked into the bare StructuralModel.
- The Why: This separation ensures that raw structural analysis can execute perfectly without design checks, while evaluation can optionally layer on top of those exact same analysis results when a design code is present.
The Strict "Do Not Include" List To prevent the architectural boundary from failing, Core must never accumulate UI responsibilities. This explicitly means keeping out Avalonia views, rendering code, entity/component editor states, and interactive command wiring.