Repository navigation
Commit 37707bf
authored
Fix parsing of Nastran small field reals in the modal structural solver (#2859)
## Proposed Changes
`SU2_PY/SU2_Nastran/pysu2_nastran.py` reads the GRID and CORD2R entries
of a Nastran sorted bulk data echo by slicing eight character fields and
then interpreting each slice *positionally*. Two helpers do that
interpretation, and both are only correct when the value happens to be
left flush and to fill all eight columns:
```python
def nastran_float(s):
if s.find("E") == -1:
s = s.replace("-", "e-")
s = s.replace("+", "e+")
if s[0] == "e": # only removes the spurious "e" if it lands on index 0
s = s[1:]
return float(s)
def __checkBlankField(self, string):
if string == " " * 8: # only recognises a blank field exactly eight characters wide
return int(0)
return int(string)
```
Neither assumption is guaranteed. The Quick Reference Guide, *Format of
Bulk Data Entries -> Small Field Format*, says:
> Fields 1 and 10 must be left justified.
> Fields 2 through 9 do not need to be either right or left justified,
although aligning the data fields is good practice.
and on the same page:
> Real numbers may be entered in a variety of ways. For example, the
following are all acceptable versions of the real number seven:
> `7.0 .7E1 0.7+1 .70+1 7.E+0 70.-1`
So three families of legal input abort the FSI run before it starts:
1. **Any negative real that is not left flush.** `nastran_float("
-5.2")` builds `" e-5.2"` and raises `ValueError`. This does not need
the E-less exponent form at all; a plain right justified negative
coordinate is enough. pyNastran, for one, writes every small field with
`'%8s'`/`'%8d'`/`'%8.Nf'`, i.e. right justified.
2. **Lower case `e` and `D` exponents.** `"700.e-2"` becomes
`"700.ee-2"` and `".7D1"` is never converted, in *any* justification.
Both are accepted real formats (`.1d-5` is in the OptiStruct bulk data
guidelines, and the QRG notes that "a double precision specification
requires a 'D' type exponent").
3. **A GRID entry without the optional CD field.** Nastran trims the
trailing blanks of each echo line, so the entry ends after X3 and
`line[48:56]` is `''` -> `int('')` raises. In the tutorial mesh
(`Tutorials/multiphysics/unsteady_fsi_python/Ma01/modal.f06`) CD is
written explicitly, which is why this has not shown up; one column
shorter and it is an empty slice.
The three symptoms are one root cause, so the fix is at the two helpers
rather than at the twelve GRID/CORD2R call sites, which are unchanged.
`nastran_float` normalises the field first and then inserts the omitted
exponent letter at the first sign after the mantissa sign, which is what
the established readers do; `__checkBlankField` treats any
whitespace-only or absent field as blank. `nastran_float` moved to
module level so it can be tested — it was a closure inside
`__readNastranMesh`.
## Verification
I enumerated the QRG spellings of a real crossed with sign and with
left/right/centre justification in an eight column field: **108 fields,
49 of them rejected or miscomputed before, 0 after**. The failures group
as:
| family | left | right | centre |
|---|---|---|---|
| QRG spellings of seven | 0 | 8 | 8 |
| lower case `e` / `D` exponent | 9 | 13 | 11 |
`SU2_PY/SU2_Nastran/test_pysu2_nastran.py` is new: it drives that table
through `nastran_float`, and then builds the same little model (a CORD2R
plus three GRIDs with negative coordinates, an E-less exponent, a blank
CP and an omitted CD) in each justification and reads it through
`__readNastranMesh`, asserting the parsed geometry does not depend on
how the fields were written. 10 tests, all 10 fail on `develop` and pass
here.
There is no Python test harness in the repository at the moment, so this
is plain `unittest` with no new dependency, run with:
```
python -m unittest discover -s SU2_PY/SU2_Nastran
```
Happy to drop the file if you would rather not start a Python test
directory here.
As a no-regression check I read the real tutorial `modal.f06` (124 grid
points, 41 negative coordinate values) with `develop` and with this
branch: the parsed coordinates, IDs, CP, CD and marker sets are
bit-for-bit identical. `pre-commit run` is clean (black 22.6.0). I did
not build the C++ side; nothing outside this Python module is touched.
## Related Work
No related PR that I can find. #2313 is a different problem in the same
file (page headers interrupting a SET1 continuation in the echo) and is
not addressed here.
## PR Checklist
- [x] I am submitting my contribution to the develop branch.
- [x] My contribution generates no new compiler warnings (try with
--warnlevel=3 when using meson). Nothing compiled changes.
- [x] My contribution is commented and consistent with SU2 style
(https://su2code.github.io/docs_v7/Style-Guide/).
- [x] I used the pre-commit hook to prevent dirty commits and used
`pre-commit run --all` to format old commits.
- [x] I have added a test case that demonstrates my contribution, if
necessary.
- [ ] I have updated appropriate documentation (Tutorials, Docs Page,
config_template.cpp), if necessary.1 parent b12aa0c commit 37707bf
4 files changed
Lines changed: 234 additions & 10 deletions
File tree
- SU2_PY
- SU2_Nastran
- TestCases
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
33 | 33 | | |
34 | 34 | | |
35 | 35 | | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
| 41 | + | |
| 42 | + | |
| 43 | + | |
| 44 | + | |
| 45 | + | |
| 46 | + | |
| 47 | + | |
| 48 | + | |
| 49 | + | |
| 50 | + | |
| 51 | + | |
| 52 | + | |
| 53 | + | |
| 54 | + | |
| 55 | + | |
| 56 | + | |
| 57 | + | |
| 58 | + | |
| 59 | + | |
36 | 60 | | |
37 | 61 | | |
38 | 62 | | |
| |||
426 | 450 | | |
427 | 451 | | |
428 | 452 | | |
429 | | - | |
430 | | - | |
431 | | - | |
432 | | - | |
433 | | - | |
434 | | - | |
435 | | - | |
436 | | - | |
437 | 453 | | |
438 | 454 | | |
439 | 455 | | |
| |||
573 | 589 | | |
574 | 590 | | |
575 | 591 | | |
576 | | - | |
| 592 | + | |
| 593 | + | |
577 | 594 | | |
578 | 595 | | |
579 | 596 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
| 41 | + | |
| 42 | + | |
| 43 | + | |
| 44 | + | |
| 45 | + | |
| 46 | + | |
| 47 | + | |
| 48 | + | |
| 49 | + | |
| 50 | + | |
| 51 | + | |
| 52 | + | |
| 53 | + | |
| 54 | + | |
| 55 | + | |
| 56 | + | |
| 57 | + | |
| 58 | + | |
| 59 | + | |
| 60 | + | |
| 61 | + | |
| 62 | + | |
| 63 | + | |
| 64 | + | |
| 65 | + | |
| 66 | + | |
| 67 | + | |
| 68 | + | |
| 69 | + | |
| 70 | + | |
| 71 | + | |
| 72 | + | |
| 73 | + | |
| 74 | + | |
| 75 | + | |
| 76 | + | |
| 77 | + | |
| 78 | + | |
| 79 | + | |
| 80 | + | |
| 81 | + | |
| 82 | + | |
| 83 | + | |
| 84 | + | |
| 85 | + | |
| 86 | + | |
| 87 | + | |
| 88 | + | |
| 89 | + | |
| 90 | + | |
| 91 | + | |
| 92 | + | |
| 93 | + | |
| 94 | + | |
| 95 | + | |
| 96 | + | |
| 97 | + | |
| 98 | + | |
| 99 | + | |
| 100 | + | |
| 101 | + | |
| 102 | + | |
| 103 | + | |
| 104 | + | |
| 105 | + | |
| 106 | + | |
| 107 | + | |
| 108 | + | |
| 109 | + | |
| 110 | + | |
| 111 | + | |
| 112 | + | |
| 113 | + | |
| 114 | + | |
| 115 | + | |
| 116 | + | |
| 117 | + | |
| 118 | + | |
| 119 | + | |
| 120 | + | |
| 121 | + | |
| 122 | + | |
| 123 | + | |
| 124 | + | |
| 125 | + | |
| 126 | + | |
| 127 | + | |
| 128 | + | |
| 129 | + | |
| 130 | + | |
| 131 | + | |
| 132 | + | |
| 133 | + | |
| 134 | + | |
| 135 | + | |
| 136 | + | |
| 137 | + | |
| 138 | + | |
| 139 | + | |
| 140 | + | |
| 141 | + | |
| 142 | + | |
| 143 | + | |
| 144 | + | |
| 145 | + | |
| 146 | + | |
| 147 | + | |
| 148 | + | |
| 149 | + | |
| 150 | + | |
| 151 | + | |
| 152 | + | |
| 153 | + | |
| 154 | + | |
| 155 | + | |
| 156 | + | |
| 157 | + | |
| 158 | + | |
| 159 | + | |
| 160 | + | |
| 161 | + | |
| 162 | + | |
| 163 | + | |
| 164 | + | |
| 165 | + | |
| 166 | + | |
| 167 | + | |
| 168 | + | |
| 169 | + | |
| 170 | + | |
| 171 | + | |
| 172 | + | |
| 173 | + | |
| 174 | + | |
| 175 | + | |
| 176 | + | |
| 177 | + | |
| 178 | + | |
| 179 | + | |
| 180 | + | |
| 181 | + | |
| 182 | + | |
| 183 | + | |
| 184 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
68 | 68 | | |
69 | 69 | | |
70 | 70 | | |
71 | | - | |
| 71 | + | |
| 72 | + | |
72 | 73 | | |
73 | 74 | | |
74 | 75 | | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
26 | 26 | | |
27 | 27 | | |
28 | 28 | | |
| 29 | + | |
| 30 | + | |
29 | 31 | | |
30 | 32 | | |
31 | 33 | | |
| |||
1257 | 1259 | | |
1258 | 1260 | | |
1259 | 1261 | | |
| 1262 | + | |
| 1263 | + | |
| 1264 | + | |
| 1265 | + | |
| 1266 | + | |
| 1267 | + | |
| 1268 | + | |
| 1269 | + | |
| 1270 | + | |
| 1271 | + | |
| 1272 | + | |
| 1273 | + | |
| 1274 | + | |
| 1275 | + | |
| 1276 | + | |
| 1277 | + | |
| 1278 | + | |
| 1279 | + | |
| 1280 | + | |
| 1281 | + | |
1260 | 1282 | | |
1261 | 1283 | | |
1262 | 1284 | | |
| |||
0 commit comments