visualdynamics.core.validate¶
validate
¶
The checks on what an object accepts: ids, DOFs, frequencies and damping.
A type annotation tells an editor, a type checker and the API reference
what a value is, and does nothing at run time:
node_id: NDArray[np.int64] does not stop a string being passed. Each
annotation here has a function that enforces it, kept in the same
module so the two do not drift apart.
The errors these catch are the ones that would otherwise pass without
notice. 'x' as a node id already fails inside numpy. 1.7 would
become node 1, and a mode shape would be drawn on the wrong node with
nothing in the file to say why.
Functions:
| Name | Description |
|---|---|
ids |
|
damping |
Damping as a fraction of critical, per mode: finite and zero or |
frequency |
Modal frequencies in Hz, per mode: finite and zero or more. |
modal_coordinate |
The mode index a modal coordinate names, or None for anything |
dofs |
DOF strings, checked and normalized: a node id, then one of |
Functions:¶
ids
¶
values as an int64 id array, or a ValueError naming the values
that are wrong.
Whole numbers only. 1.7 is not node 1 with a rounding error; it
means the caller computed an id, and truncating it without notice
would hide that. Numeric strings are accepted, because the file
formats in this field write ids as text, and requiring every reader
to convert them first would mean many places to get the conversion
wrong.
Ids cannot be negative: an id is a label, and a negative one has no meaning. Zero is allowed, because real files do number from zero.
Set unique where something refers to these by id: nodes,
coordinate systems and blocks. Element ids are labels nothing refers
to (a UNV trace line that lifts the pen, for example), so they are
not checked for duplicates. label names the values in the error
message.
Source code in src/visualdynamics/core/validate.py
damping
¶
Damping as a fraction of critical, per mode: finite and zero or more.
There is no upper bound. Above 1.0 is overdamped, which can be measured even if it is not a mode anyone will animate, so the check is a lower limit and not a range. A negative value comes from a failed fit or an unintended sign convention, and a negative damping synthesizes an FRF that grows without bound.
Source code in src/visualdynamics/core/validate.py
frequency
¶
Modal frequencies in Hz, per mode: finite and zero or more.
Exactly zero is a rigid-body mode, and the FRF synthesis tests for it to cancel its 0/0, so zero is allowed and has a meaning. A negative value is not a frequency.
Source code in src/visualdynamics/core/validate.py
modal_coordinate
¶
The mode index a modal coordinate names, or None for anything
else. This is the one function that reads the M<index> spelling.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
text
|
str
|
A DOF string. |
required |
Returns:
| Type | Description |
|---|---|
int or None
|
The 1-based mode index, or None when the string is not a modal coordinate. |
Source code in src/visualdynamics/core/validate.py
dofs
¶
DOF strings, checked and normalized: a node id, then one of
DIRECTIONS ('101RX+'), or a modal coordinate ('M3', see
modal_coordinate).
A record finds its node on a geometry by its DOF, a shape finds its column by it, and a channel says what it measures with it. A DOF that cannot be parsed would not fail where it was written; it would show up later as a record matched to no node on the geometry. So it is refused here, with a ValueError naming the string.
An unsigned direction is taken as the positive one ('101Z' is
'101Z+'), because that is how people write them by hand. The
direction is upper-cased and the node id written without leading
zeros, so that later comparisons are between identical strings.
A single string is accepted as a list of one.
allow_unknown lets an incomplete DOF through, because a channel
table is written by people and people leave fields out. A DOF
string is the node and the direction concatenated, so whatever was
recorded is what comes out:
| node | direction | DOF |
|---|---|---|
| 101 | Z+ | 101Z+ |
| 101 | — | 101 |
| — | Z+ | Z+ |
| — | — | '' |
All four import. Refusing the file would leave the user nothing to
fix, while an imported record is shown as matching no geometry and
can be corrected in the channel table. A direction that is not a
direction is still refused either way: 101Q+ is a typo, not an
omission, and Q is not an axis.