Dataset schema¶
Schema v4 is selection-driven. Every dataset records a non-empty set of typed `Record` leaves instead of requiring a complete copy of the simulation result.
Record selector tree¶
record is required by generate_dataset(). The complete public selector tree
is:
Record
├── signal -> signal
├── clean_signal -> clean_signal
├── response
│ ├── displacement -> response/displacement
│ ├── velocity -> response/velocity
│ └── acceleration -> response/acceleration
├── system_parameter
│ ├── mass_matrix -> system/mass_matrix
│ ├── damping_matrix -> system/damping_matrix
│ └── stiffness_matrix -> system/stiffness_matrix
├── modal_parameter
│ ├── frequencies_hz -> modal/frequencies_hz
│ └── mode_shapes -> modal/mode_shapes
├── load
│ ├── force -> load/force
│ └── values -> load/values
├── metadata
│ ├── seed -> metadata/seed
│ └── generation -> dataset-level provenance
├── case_parameter -> parameters/<normalized case name>
├── time -> time
└── positions -> positions
Family objects such as Record.response and Record.modal_parameter are
namespaces only. They do not expand to all children and cannot be passed in
record; select each required leaf. Record.case_parameter is one leaf with
dynamic contents: it selects all numeric entries in the final case mapping.
Duplicate fields and an empty selection are rejected.
Shapes of recorded arrays¶
Let N be samples, S sensors, T time points, D generalized coordinates,
M modes, and P reporting positions. Only selected paths exist.
| Path | Shape |
|---|---|
time |
(T,) |
positions |
(P,) |
signal |
(N, S, T) |
clean_signal |
(N, S, T) |
response/displacement |
(N, D, T) |
response/velocity |
(N, D, T) |
response/acceleration |
(N, D, T) |
system/mass_matrix |
(N, D, D) |
system/damping_matrix |
(N, D, D) |
system/stiffness_matrix |
(N, D, D) |
modal/frequencies_hz |
(N, M) |
modal/mode_shapes |
(N, M, P) |
load/force |
(N, D, T) |
load/values |
(N, P, T) |
metadata/seed |
(N,) |
parameters/<normalized name> |
(N, *case_value.shape) |
time and positions are shared coordinates without a sample dimension. All
sample-scoped arrays have a leading N dimension, and every recorded path has
a stable shape across samples. load/values is the rasterized diagnostic field
on positions. For point and moving loads, load/force is projected from exact
coordinates and need not equal a projection of that diagnostic raster.
Storage dtype¶
Simulation calculations and the complete SimulationResult remain float64.
After a simulation finishes, DynaResp filters the result to the requested
fields and casts recorded floating arrays to storage_dtype. The default is
np.float64; use storage_dtype=np.float32 for compact in-memory and Zarr
datasets.
The cast applies to selected signals, responses, matrices, modal data, loads,
floating case values, time, and positions. Integer case values preserve
their values in normalized int64 arrays, and metadata/seed remains uint64.
Field selection reduces retained storage, not solver work or its temporary
memory requirements.
Parameter and target names¶
When Record.case_parameter is selected, case names are normalized for
storage:
| Case name | Parameter path | Target name |
|---|---|---|
masses |
parameters/masses |
masses |
load.rms |
parameters/load_rms |
load.rms |
stiffness_reduction |
parameters/stiffness_reduction |
stiffness_reduction |
Parameter arrays preserve each sampled value's shape after the leading sample
dimension. parameter_keys and target_keys retain their respective logical
names, and both mappings reference the same stored arrays. No duplicate
target/ arrays are written.
Dataset metadata¶
Every schema-v4 dataset stores the structural bookkeeping needed to validate its partial contents:
- schema version and sample count;
- selected record paths and storage dtype;
- logical parameter and target mappings;
- stored array keys.
Selecting Record.metadata.generation additionally stores the DynaResp version,
root seed, builder identities, sensor definitions, variability provenance, and
concrete system and load definitions for the first realization. Selecting
Record.metadata.seed separately stores the effective seed for each sample.
Axes are arrays only when their respective selectors are present; generation
metadata does not duplicate omitted axes.
Schema v4 intentionally has no schema-v3 compatibility path.
StructuralDataset.open() rejects stores with another schema version, so older
datasets must be regenerated or migrated outside DynaResp.
Partial StructuralSample views¶
Indexing materializes only recorded values:
| View | When omitted |
|---|---|
signal, clean_signal, time, positions |
None |
target |
Empty unless Record.case_parameter was selected |
system, modal, load |
Partial or empty dictionaries |
metadata["parameters"] |
Absent unless case parameters were selected |
| generation and per-sample seed metadata | Present only when selected |
sample.metadata always identifies the sample index. Accessing a missing
dataset-level property such as dataset.signal or dataset.time raises a
clear KeyError. Adapters likewise raise KeyError when asked for an
unrecorded input, target, or extra field.
sample = dataset[0]
print(sample.signal)
print(sample.modal["frequencies_hz"])
print(sample.target["temperature_c"])
Zarr storage behavior¶
Zarr output mirrors only the selected path tree as nested groups and arrays. Sample chunks contain at most 32 records. A new dataset is written to a temporary sibling and moved into place only after writing and validation succeed. Failed writes remove the temporary store and never leave a partial destination; an existing destination is not overwritten. Opening validates metadata, selected axes, and cross-array shapes without materializing sample tensors.