|
52 | 52 |
|
53 | 53 | """ |
54 | 54 | from __future__ import annotations |
| 55 | +import warnings |
55 | 56 | from typing import Optional, Any, TYPE_CHECKING |
56 | 57 |
|
57 | 58 | from pyNastran.utils.numpy_utils import integer_types |
@@ -1396,12 +1397,14 @@ def _init_from_empty(cls): |
1396 | 1397 | params = {'CSTIFF' : 1} |
1397 | 1398 | return BCTPARM(csid, params, comment='') |
1398 | 1399 |
|
1399 | | - def _finalize_hdf5(self, encoding): |
| 1400 | + def _finalize_hdf5(self, encoding: str): |
1400 | 1401 | """hdf5 helper function""" |
1401 | 1402 | keys, values = self.params |
1402 | 1403 | self.params = {key : value for key, value in zip(keys, values)} |
1403 | 1404 |
|
1404 | | - def __init__(self, csid, params, comment=''): |
| 1405 | + def __init__(self, csid: int, |
| 1406 | + params: dict[str, int | float], |
| 1407 | + comment: str=''): |
1405 | 1408 | """ |
1406 | 1409 | Creates a BCTPARM card |
1407 | 1410 |
|
@@ -1447,89 +1450,77 @@ def add_card(cls, card: BDFCard, comment: str=''): |
1447 | 1450 |
|
1448 | 1451 | """ |
1449 | 1452 | csid = integer(card, 1, 'csid') |
1450 | | - i = 2 |
1451 | | - j = 1 |
1452 | | - params = {} |
1453 | | - while i < card.nfields: |
1454 | | - param = string(card, i, 'param%s' % j) |
1455 | | - i += 1 |
1456 | | - if param == 'TYPE' and 0: |
1457 | | - value = integer_or_blank(card, i, 'value%s' % j, default=0) |
1458 | | - assert value in [0, 1, 2], 'TYPE must be [0, 1, 2]; TYPE=%r' % value |
1459 | | - elif param == 'PENN': |
1460 | | - #PENN 10.0 |
1461 | | - value = double(card, i, 'value%s' % j) |
1462 | | - elif param == 'PENT': |
1463 | | - #PENT 0.5 |
1464 | | - value = double(card, i, 'value%s' % j) |
1465 | | - elif param == 'CTOL': |
1466 | | - #CTOL 10.0 |
1467 | | - value = double(card, i, 'value%s' % j) |
1468 | | - elif param == 'SHLTHK': |
1469 | | - #SHLTHK 1 |
1470 | | - value = integer(card, i, 'value%s' % j) |
1471 | | - #elif param == 'TYPE': # NX |
1472 | | - #value = string_or_blank(card, i, 'value%s' % j, default='FLEX').upper() |
1473 | | - #assert value in ['FLEX', 'RIGID', 'COATING'], 'TYPE must be [FLEX, RIGID, COATING.]; CSTIFF=%r' % value |
1474 | | - |
1475 | | - #elif param == 'NSIDE': |
1476 | | - #value = integer_or_blank(card, i, 'value%s' % j, default=1) |
1477 | | - #assert value in [1, 2], 'NSIDE must be [1, 2]; NSIDE=%r' % value |
1478 | | - #elif param == 'TBIRTH': |
1479 | | - #value = double_or_blank(card, i, 'value%s' % j, default=0.0) |
1480 | | - #elif param == 'TDEATH': |
1481 | | - #value = double_or_blank(card, i, 'value%s' % j, default=0.0) |
1482 | | - #elif param == 'INIPENE': |
1483 | | - #value = integer_or_blank(card, i, 'value%s' % j, default=0) |
1484 | | - #assert value in [0, 1, 2, 3], 'INIPENE must be [0, 1, 2]; INIPENE=%r' % value |
1485 | | - #elif param == 'PDEPTH': |
1486 | | - #value = double_or_blank(card, i, 'value%s' % j, default=0.0) |
1487 | | - #elif param == 'SEGNORM': |
1488 | | - #value = integer_or_blank(card, i, 'value%s' % j, default=0) |
1489 | | - #assert value in [-1, 0, 1], 'SEGNORM must be [-1, 0, 1]; SEGNORM=%r' % value |
1490 | | - #elif param == 'OFFTYPE': |
1491 | | - #value = integer_or_blank(card, i, 'value%s' % j, default=0) |
1492 | | - #assert value in [0, 1, 2], 'OFFTYPE must be [0, 1, 2]; OFFTYPE=%r' % value |
1493 | | - #elif param == 'OFFSET': |
1494 | | - #value = double_or_blank(card, i, 'value%s' % j, default=0.0) |
1495 | | - #elif param == 'TZPENE': |
1496 | | - #value = double_or_blank(card, i, 'value%s' % j, default=0.0) |
1497 | | - |
1498 | | - #elif param == 'CSTIFF': |
1499 | | - #value = integer_or_blank(card, i, 'value%s' % j, default=0) |
1500 | | - #assert value in [0, 1], 'CSTIFF must be [0, 1]; CSTIFF=%r' % value |
1501 | | - #elif param == 'TIED': |
1502 | | - #value = integer_or_blank(card, i, 'value%s' % j, default=0) |
1503 | | - #assert value in [0, 1], 'TIED must be [0, 1]; TIED=%r' % value |
1504 | | - #elif param == 'TIEDTOL': |
1505 | | - #value = double_or_blank(card, i, 'value%s' % j, default=0.0) |
1506 | | - #elif param == 'EXTFAC': |
1507 | | - #value = double_or_blank(card, i, 'value%s' % j, default=0.001) |
1508 | | - #assert 1.0E-6 <= value <= 0.1, 'EXTFAC must be 1.0E-6 < EXTFAC < 0.1; EXTFAC=%r' % value |
1509 | | - else: |
1510 | | - # FRICMOD, FPARA1/2/3/4/5, EPSN, EPST, CFACTOR1, PENETOL |
1511 | | - # NCMOD, TCMOD, RFORCE, LFORCE, RTPCHECK, RTPMAX, XTYPE |
1512 | | - # ... |
1513 | | - value = integer_double_or_blank(card, i, 'value%s' % j) |
1514 | | - assert value is not None, '%s%i must not be None' % (param, j) |
1515 | | - |
1516 | | - params[param] = value |
1517 | | - i += 1 |
1518 | | - j += 1 |
1519 | | - if j == 4: |
1520 | | - i += 1 |
| 1453 | + params = read_param_dict(card, cls._get_param_value_from_card) |
1521 | 1454 | return BCTPARM(csid, params, comment=comment) |
1522 | 1455 |
|
1523 | | - def raw_fields(self): |
| 1456 | + def _get_param_value_from_card( |
| 1457 | + card: BDFCard, |
| 1458 | + i: int, j: int) -> tuple[str, int | float]: |
| 1459 | + param = string(card, i, 'param%s' % j) |
| 1460 | + if param == 'TYPE' and 0: |
| 1461 | + value = integer_or_blank(card, i+1, f'value{j:d}', default=0) |
| 1462 | + assert value in [0, 1, 2], 'TYPE must be [0, 1, 2]; TYPE=%r' % value |
| 1463 | + elif param == 'PENN': |
| 1464 | + # PENN 10.0 |
| 1465 | + value = double(card, i+1, 'value%s' % j) |
| 1466 | + elif param == 'PENT': |
| 1467 | + # PENT 0.5 |
| 1468 | + value = double(card, i+1, 'value%s' % j) |
| 1469 | + elif param == 'CTOL': |
| 1470 | + # CTOL 10.0 |
| 1471 | + value = double(card, i+1, 'value%s' % j) |
| 1472 | + elif param == 'SHLTHK': |
| 1473 | + # SHLTHK 1 |
| 1474 | + value = integer(card, i+1, 'value%s' % j) |
| 1475 | + # elif param == 'TYPE': # NX |
| 1476 | + # value = string_or_blank(card, i, 'value%s' % j, default='FLEX').upper() |
| 1477 | + # assert value in ['FLEX', 'RIGID', 'COATING'], 'TYPE must be [FLEX, RIGID, COATING.]; CSTIFF=%r' % value |
| 1478 | + |
| 1479 | + # elif param == 'NSIDE': |
| 1480 | + # value = integer_or_blank(card, i+1, 'value%s' % j, default=1) |
| 1481 | + # assert value in [1, 2], 'NSIDE must be [1, 2]; NSIDE=%r' % value |
| 1482 | + # elif param == 'TBIRTH': |
| 1483 | + # value = double_or_blank(card, i+1, 'value%s' % j, default=0.0) |
| 1484 | + # elif param == 'TDEATH': |
| 1485 | + # value = double_or_blank(card, i+1, 'value%s' % j, default=0.0) |
| 1486 | + # elif param == 'INIPENE': |
| 1487 | + # value = integer_or_blank(card, i+1, 'value%s' % j, default=0) |
| 1488 | + # assert value in [0, 1, 2, 3], 'INIPENE must be [0, 1, 2]; INIPENE=%r' % value |
| 1489 | + # elif param == 'PDEPTH': |
| 1490 | + # value = double_or_blank(card, i+1, 'value%s' % j, default=0.0) |
| 1491 | + # elif param == 'SEGNORM': |
| 1492 | + # value = integer_or_blank(card, i+1, 'value%s' % j, default=0) |
| 1493 | + # assert value in [-1, 0, 1], 'SEGNORM must be [-1, 0, 1]; SEGNORM=%r' % value |
| 1494 | + # elif param == 'OFFTYPE': |
| 1495 | + # value = integer_or_blank(card, i+1, 'value%s' % j, default=0) |
| 1496 | + # assert value in [0, 1, 2], 'OFFTYPE must be [0, 1, 2]; OFFTYPE=%r' % value |
| 1497 | + # elif param == 'OFFSET': |
| 1498 | + # value = double_or_blank(card, i+1, 'value%s' % j, default=0.0) |
| 1499 | + # elif param == 'TZPENE': |
| 1500 | + # value = double_or_blank(card, i+1, 'value%s' % j, default=0.0) |
| 1501 | + |
| 1502 | + # elif param == 'CSTIFF': |
| 1503 | + # value = integer_or_blank(card, i+1, 'value%s' % j, default=0) |
| 1504 | + # assert value in [0, 1], 'CSTIFF must be [0, 1]; CSTIFF=%r' % value |
| 1505 | + # elif param == 'TIED': |
| 1506 | + # value = integer_or_blank(card, i+1, 'value%s' % j, default=0) |
| 1507 | + # assert value in [0, 1], 'TIED must be [0, 1]; TIED=%r' % value |
| 1508 | + # elif param == 'TIEDTOL': |
| 1509 | + # value = double_or_blank(card, i+1, 'value%s' % j, default=0.0) |
| 1510 | + # elif param == 'EXTFAC': |
| 1511 | + # value = double_or_blank(card, i+1, 'value%s' % j, default=0.001) |
| 1512 | + # assert 1.0E-6 <= value <= 0.1, 'EXTFAC must be 1.0E-6 < EXTFAC < 0.1; EXTFAC=%r' % value |
| 1513 | + else: |
| 1514 | + # FRICMOD, FPARA1/2/3/4/5, EPSN, EPST, CFACTOR1, PENETOL |
| 1515 | + # NCMOD, TCMOD, RFORCE, LFORCE, RTPCHECK, RTPMAX, XTYPE |
| 1516 | + # ... |
| 1517 | + value = integer_double_or_blank(card, i+1, 'value%s' % j) |
| 1518 | + assert value is not None, '%s%i must not be None' % (param, j) |
| 1519 | + return param, value |
| 1520 | + |
| 1521 | + def raw_fields(self) -> list[str | int | float]: |
1524 | 1522 | fields = ['BCTPARM', self.csid] |
1525 | | - i = 0 |
1526 | | - for key, value in sorted(self.params.items()): |
1527 | | - if i == 3: |
1528 | | - fields.append(None) |
1529 | | - i = 0 |
1530 | | - fields.append(key) |
1531 | | - fields.append(value) |
1532 | | - i += 1 |
| 1523 | + fields.extend(params_listify(self.params)) |
1533 | 1524 | return fields |
1534 | 1525 |
|
1535 | 1526 | def write_card(self, size: int=8, is_double: bool=False) -> str: |
@@ -1606,83 +1597,77 @@ def add_card(cls, card: BDFCard, comment: str=''): |
1606 | 1597 |
|
1607 | 1598 | """ |
1608 | 1599 | csid = integer(card, 1, 'csid') |
1609 | | - i = 2 |
1610 | | - j = 1 |
1611 | | - params = {} |
| 1600 | + |
1612 | 1601 | all_params = [ |
1613 | 1602 | 'TYPE', 'NSIDE', 'TBIRTH', 'TDEATH', 'INIPENE', |
1614 | 1603 | 'PDEPTH', 'SEGNORM', 'OFFTYPE', 'OFFSET', |
1615 | 1604 | 'TZPENE', 'CSTIFF', 'TIED', 'TIEDTOL', 'EXTFAC'] |
1616 | 1605 | all_params.sort() |
1617 | | - while i < card.nfields: |
1618 | | - param = string(card, i, f'param{j}') |
1619 | | - assert param in all_params, f'param={param!r} is not allowed; allowed={all_params}' |
1620 | | - i += 1 |
1621 | | - if param == 'TYPE': |
1622 | | - value = integer_or_blank(card, i, 'value%s' % j, default=0) |
1623 | | - assert value in [0, 1, 2], 'TYPE must be [0, 1, 2]; TYPE=%r' % value |
1624 | | - #elif param == 'TYPE': # NX |
1625 | | - #value = string_or_blank(card, i, 'value%s' % j, 'FLEX').upper() |
1626 | | - #assert value in ['FLEX', 'RIGID', 'COATING'], 'TYPE must be [FLEX, RIGID, COATING.]; CSTIFF=%r' % value |
1627 | | - |
1628 | | - elif param == 'NSIDE': |
1629 | | - value = integer_or_blank(card, i, 'value%s' % j, default=1) |
1630 | | - assert value in [1, 2], 'NSIDE must be [1, 2]; NSIDE=%r' % value |
1631 | | - elif param == 'TBIRTH': |
1632 | | - value = double_or_blank(card, i, 'value%s' % j, default=0.0) |
1633 | | - elif param == 'TDEATH': |
1634 | | - value = double_or_blank(card, i, 'value%s' % j, default=0.0) |
1635 | | - elif param == 'INIPENE': |
1636 | | - value = integer_or_blank(card, i, 'value%s' % j, default=0) |
1637 | | - assert value in [0, 1, 2, 3], 'INIPENE must be [0, 1, 2]; INIPENE=%r' % value |
1638 | | - elif param == 'PDEPTH': |
1639 | | - value = double_or_blank(card, i, 'value%s' % j, default=0.0) |
1640 | | - elif param == 'SEGNORM': |
1641 | | - value = integer_or_blank(card, i, 'value%s' % j, default=0) |
1642 | | - assert value in [-1, 0, 1], 'SEGNORM must be [-1, 0, 1]; SEGNORM=%r' % value |
1643 | | - elif param == 'OFFTYPE': |
1644 | | - value = integer_or_blank(card, i, 'value%s' % j, default=0) |
1645 | | - assert value in [0, 1, 2], 'OFFTYPE must be [0, 1, 2]; OFFTYPE=%r' % value |
1646 | | - elif param == 'OFFSET': |
1647 | | - value = double_or_blank(card, i, 'value%s' % j, default=0.0) |
1648 | | - elif param == 'TZPENE': |
1649 | | - value = double_or_blank(card, i, 'value%s' % j, default=0.0) |
1650 | | - |
1651 | | - elif param == 'CSTIFF': |
1652 | | - value = integer_or_blank(card, i, 'value%s' % j, default=0) |
1653 | | - assert value in [0, 1], 'CSTIFF must be [0, 1]; CSTIFF=%r' % value |
1654 | | - elif param == 'TIED': |
1655 | | - value = integer_or_blank(card, i, 'value%s' % j, default=0) |
1656 | | - assert value in [0, 1], 'TIED must be [0, 1]; TIED=%r' % value |
1657 | | - elif param == 'TIEDTOL': |
1658 | | - value = double_or_blank(card, i, 'value%s' % j, default=0.0) |
1659 | | - elif param == 'EXTFAC': |
1660 | | - value = double_or_blank(card, i, 'value%s' % j, default=0.001) |
1661 | | - assert 1.0E-6 <= value <= 0.1, 'EXTFAC must be 1.0E-6 < EXTFAC < 0.1; EXTFAC=%r' % value |
1662 | | - else: |
1663 | | - # FRICMOD, FPARA1/2/3/4/5, EPSN, EPST, CFACTOR1, PENETOL |
1664 | | - # NCMOD, TCMOD, RFORCE, LFORCE, RTPCHECK, RTPMAX, XTYPE |
1665 | | - # ... |
1666 | | - value = integer_double_or_blank(card, i, 'value%s' % j) |
1667 | | - assert value is not None, '%s%i must not be None' % (param, j) |
| 1606 | + params = read_param_dict(card, cls._get_param_value_from_card) |
| 1607 | + for param in params: |
| 1608 | + if param not in all_params: |
| 1609 | + warnings.warn(f'param={param!r} is not allowed; allowed={all_params}\n{str(card)}') |
1668 | 1610 |
|
1669 | | - params[param] = value |
1670 | | - i += 1 |
1671 | | - j += 1 |
1672 | | - if j == 4: |
1673 | | - i += 1 |
1674 | 1611 | return BCTPARA(csid, params, comment=comment) |
1675 | 1612 |
|
| 1613 | + @staticmethod |
| 1614 | + def _get_param_value_from_card(card: BDFCard, |
| 1615 | + i: int, j: int) -> tuple[str, int | float]: |
| 1616 | + param = string(card, i, f'param{j}') |
| 1617 | + # assert param in all_params, f'param={param!r} is not allowed; allowed={all_params}' |
| 1618 | + i += 1 |
| 1619 | + if param == 'TYPE': |
| 1620 | + value = integer_or_blank(card, i, 'value%s' % j, default=0) |
| 1621 | + assert value in [0, 1, 2], 'TYPE must be [0, 1, 2]; TYPE=%r' % value |
| 1622 | + #elif param == 'TYPE': # NX |
| 1623 | + #value = string_or_blank(card, i, 'value%s' % j, 'FLEX').upper() |
| 1624 | + #assert value in ['FLEX', 'RIGID', 'COATING'], 'TYPE must be [FLEX, RIGID, COATING.]; CSTIFF=%r' % value |
| 1625 | + |
| 1626 | + elif param == 'NSIDE': |
| 1627 | + value = integer_or_blank(card, i, 'value%s' % j, default=1) |
| 1628 | + assert value in [1, 2], 'NSIDE must be [1, 2]; NSIDE=%r' % value |
| 1629 | + elif param == 'TBIRTH': |
| 1630 | + value = double_or_blank(card, i, 'value%s' % j, default=0.0) |
| 1631 | + elif param == 'TDEATH': |
| 1632 | + value = double_or_blank(card, i, 'value%s' % j, default=0.0) |
| 1633 | + elif param == 'INIPENE': |
| 1634 | + value = integer_or_blank(card, i, 'value%s' % j, default=0) |
| 1635 | + assert value in [0, 1, 2, 3], 'INIPENE must be [0, 1, 2]; INIPENE=%r' % value |
| 1636 | + elif param == 'PDEPTH': |
| 1637 | + value = double_or_blank(card, i, 'value%s' % j, default=0.0) |
| 1638 | + elif param == 'SEGNORM': |
| 1639 | + value = integer_or_blank(card, i, 'value%s' % j, default=0) |
| 1640 | + assert value in [-1, 0, 1], 'SEGNORM must be [-1, 0, 1]; SEGNORM=%r' % value |
| 1641 | + elif param == 'OFFTYPE': |
| 1642 | + value = integer_or_blank(card, i, 'value%s' % j, default=0) |
| 1643 | + assert value in [0, 1, 2], 'OFFTYPE must be [0, 1, 2]; OFFTYPE=%r' % value |
| 1644 | + elif param == 'OFFSET': |
| 1645 | + value = double_or_blank(card, i, 'value%s' % j, default=0.0) |
| 1646 | + elif param == 'TZPENE': |
| 1647 | + value = double_or_blank(card, i, 'value%s' % j, default=0.0) |
| 1648 | + |
| 1649 | + elif param == 'CSTIFF': |
| 1650 | + value = integer_or_blank(card, i, 'value%s' % j, default=0) |
| 1651 | + assert value in [0, 1], 'CSTIFF must be [0, 1]; CSTIFF=%r' % value |
| 1652 | + elif param == 'TIED': |
| 1653 | + value = integer_or_blank(card, i, 'value%s' % j, default=0) |
| 1654 | + assert value in [0, 1], 'TIED must be [0, 1]; TIED=%r' % value |
| 1655 | + elif param == 'TIEDTOL': |
| 1656 | + value = double_or_blank(card, i, 'value%s' % j, default=0.0) |
| 1657 | + elif param == 'EXTFAC': |
| 1658 | + value = double_or_blank(card, i, 'value%s' % j, default=0.001) |
| 1659 | + assert 1.0E-6 <= value <= 0.1, 'EXTFAC must be 1.0E-6 < EXTFAC < 0.1; EXTFAC=%r' % value |
| 1660 | + else: |
| 1661 | + # FRICMOD, FPARA1/2/3/4/5, EPSN, EPST, CFACTOR1, PENETOL |
| 1662 | + # NCMOD, TCMOD, RFORCE, LFORCE, RTPCHECK, RTPMAX, XTYPE |
| 1663 | + # ... |
| 1664 | + value = integer_double_or_blank(card, i, 'value%s' % j) |
| 1665 | + assert value is not None, '%s%i must not be None' % (param, j) |
| 1666 | + return param, value |
| 1667 | + |
1676 | 1668 | def raw_fields(self): |
1677 | 1669 | fields = ['BCTPARA', self.csid] |
1678 | | - i = 0 |
1679 | | - for key, value in sorted(self.params.items()): |
1680 | | - if i == 3: |
1681 | | - fields.append(None) |
1682 | | - i = 0 |
1683 | | - fields.append(key) |
1684 | | - fields.append(value) |
1685 | | - i += 1 |
| 1670 | + fields.extend(params_listify(self.params)) |
1686 | 1671 | return fields |
1687 | 1672 |
|
1688 | 1673 | def write_card(self, size: int=8, is_double: bool=False) -> str: |
@@ -1912,3 +1897,50 @@ def write_card(self, size: int=8, is_double: bool=False) -> str: |
1912 | 1897 | if size == 8: |
1913 | 1898 | return self.comment + print_card_8(card) |
1914 | 1899 | return self.comment + print_card_16(card) |
| 1900 | + |
| 1901 | + |
| 1902 | +def params_listify(params: dict[str, int | float], |
| 1903 | + ) -> list[str | int | float]: |
| 1904 | + """ |
| 1905 | + Annoying function for contact params. |
| 1906 | +
|
| 1907 | + 3 sets of params are allowed per line, but: |
| 1908 | + - 1 blank on the first line |
| 1909 | + - 2 blanon the 2nd/3rd/etc. line |
| 1910 | +
|
| 1911 | + """ |
| 1912 | + i = 0 |
| 1913 | + fields = [] |
| 1914 | + for j, (key, value) in enumerate(sorted(params.items())): |
| 1915 | + if j == 3: |
| 1916 | + fields.append(None) |
| 1917 | + i = 0 |
| 1918 | + elif j > 0 and i == 3: |
| 1919 | + fields.append(None) |
| 1920 | + fields.append(None) |
| 1921 | + i = 0 |
| 1922 | + fields.append(key) |
| 1923 | + fields.append(value) |
| 1924 | + i += 1 |
| 1925 | + return fields |
| 1926 | + |
| 1927 | + |
| 1928 | +def read_param_dict(card: BDFCard, |
| 1929 | + read_func) -> dict[str, int | float]: |
| 1930 | + """reading version of params_listify""" |
| 1931 | + params = {} |
| 1932 | + iline = 0 |
| 1933 | + ifield = 2 |
| 1934 | + iparam = 0 |
| 1935 | + while ifield < card.nfields: |
| 1936 | + param, value = read_func(card, ifield, iparam+1) |
| 1937 | + params[param] = value |
| 1938 | + iparam += 1 |
| 1939 | + if iparam % 3 == 0: |
| 1940 | + # every 3 params, reset the line |
| 1941 | + ifield = 9 + 8 * iline |
| 1942 | + iline += 1 |
| 1943 | + else: |
| 1944 | + ifield += 2 |
| 1945 | + assert len(params) > 0, card |
| 1946 | + return params |
0 commit comments