diff --git a/pyNastran/dev/bdf_vectorized3/bdf.py b/pyNastran/dev/bdf_vectorized3/bdf.py index cd94b2000..cc87a9831 100644 --- a/pyNastran/dev/bdf_vectorized3/bdf.py +++ b/pyNastran/dev/bdf_vectorized3/bdf.py @@ -694,7 +694,7 @@ def __init__(self, debug: Union[str, bool, None]=True, #'MAT4', 'MAT5', ## spcs - #'SPC', 'SPCADD', 'SPC1', 'SPCAX', 'SPCOFF', 'SPCOFF1', + 'SPC', 'SPCADD', 'SPC1', #'SPCAX', 'SPCOFF', 'SPCOFF1', ## mpcs #'MPC', 'MPCADD', diff --git a/pyNastran/dev/bdf_vectorized3/bdf_interface/fast_float_print.py b/pyNastran/dev/bdf_vectorized3/bdf_interface/fast_float_print.py index 118560d4a..c96af9cd5 100644 --- a/pyNastran/dev/bdf_vectorized3/bdf_interface/fast_float_print.py +++ b/pyNastran/dev/bdf_vectorized3/bdf_interface/fast_float_print.py @@ -14,7 +14,7 @@ 6 : "%7.0f.", } -def get_float_format(value): +def get_float_format(value: float): #value = 1000000. #value = 100000.0 #value = 123456.78 @@ -22,6 +22,32 @@ def get_float_format(value): if value == 0.0: #print('block 0') return ' 0.0 ' + if value < 0.: + abs_value = abs(value) + # sign, decimal, 1 + if abs_value > 999_995: + #print('A') + # -123_456. + field = print_scientific_8(value) + return field + elif abs_value < 5e-7: + #print('B') + field = print_scientific_8(value) + return field + elif abs_value < 1.: + #print('C') + field = f'{abs_value:7.6f}' + field2 = '-' + field[1:] + return field2 + + magnitude = int(math.floor(math.log10(abs_value))) + format_string = "-%7." + str(5 - magnitude) + "f" + field = format_string % abs_value + #print('D', value, magnitude, field, len(field)) + #if value < -99_995: + #if value < 0.1: + # -0.1 to -1.0 + return field if value < 5e-8: field = print_scientific_8(value) #print('scientific 1;', field) @@ -165,6 +191,18 @@ def main(get_optimal_short_form_float): #get_optimal_short_form_float = get_field_zach #get_optimal_short_form_float = print_float_8 #get_optimal_short_form_float = get_float_format + + value=-0.8732806594999999 #; field_old='-.873281' field_new='-8.733-1' + s = get_optimal_short_form_float(value) + value=-0.6862676525499999 #; field_old='-.686268' field_new='-6.863-1' + s = get_optimal_short_form_float(value) + value=-0.647050147 #; field_old=' -.64705' field_new='-6.471-1' + s = get_optimal_short_form_float(value) + value=-0.9526646215 #; field_old='-.952665' field_new='-9.527-1' + s = get_optimal_short_form_float(value) + value=-0.6291313619 #; field_old='-.629131' field_new='-6.291-1' + s = get_optimal_short_form_float(value) + x = 2e-11 s = get_optimal_short_form_float(x) x = 12e-11 @@ -275,7 +313,11 @@ def main_zach(): def main_new(): main(get_float_format) -if __name__ == '__main__': +def run(): + value = -0.8732806594999999 + out = get_float_format(value) + print(value, out, len(out)) + return import timeit #main(get_field_zach) @@ -289,7 +331,7 @@ def main_new(): #2000000 loops, best of 5: 158 nsec per loop #2000000 loops, best of 5: 152 nsec per loop #2000000 loops, best of 5: 152 nsec per loop - num = 100_000 + num = 10 print('OG:') print(timeit.timeit('main_og()', number=num, setup="from __main__ import main_og")) @@ -306,3 +348,6 @@ def main_new(): x = 1 #main() + +if __name__ == '__main__': + run() diff --git a/pyNastran/dev/bdf_vectorized3/bdf_interface/write_mesh.py b/pyNastran/dev/bdf_vectorized3/bdf_interface/write_mesh.py index 52ed49ba0..c90084bff 100644 --- a/pyNastran/dev/bdf_vectorized3/bdf_interface/write_mesh.py +++ b/pyNastran/dev/bdf_vectorized3/bdf_interface/write_mesh.py @@ -239,7 +239,7 @@ def _write_common(self, bdf_file: TextIOLike, #self._write_superelements(bdf_file, size, is_double, is_long_ids=is_long_ids) #self._write_contact(bdf_file, size, is_double, is_long_ids=is_long_ids) #self._write_parametric(bdf_file, size, is_double, is_long_ids=is_long_ids) - #self._write_rejects(bdf_file, size, is_double, is_long_ids=is_long_ids) + self._write_rejects(bdf_file, size, is_double, is_long_ids=is_long_ids) self._write_coords(bdf_file, size, is_double, is_long_ids=is_long_ids) #if self.acmodl: @@ -459,6 +459,55 @@ def _write_elements(self, bdf_file: TextIOLike, # other #bdf_file.write(model.genel.write(size=size)) + def _write_rejects(self, bdf_file: TextIOLike, + size: int=8, is_double: bool=False, + is_long_ids: Optional[bool]=None) -> None: + """ + Writes the rejected (processed) cards and the rejected unprocessed + cardlines + + """ + from pyNastran.bdf.field_writer import print_card_8, print_card_16 + if size == 8: + print_func = print_card_8 + else: + print_func = print_card_16 + + model = self.model + if model.reject_cards: + bdf_file.write('$REJECT_CARDS\n') + for reject_card in model.reject_cards: + try: + bdf_file.write(print_func(reject_card)) + except RuntimeError: + if len(reject_card) > 0: + line0 = reject_card[0].upper() + if line0.startswith('ADAPT'): + for line in reject_card: + assert isinstance(line, str), line + bdf_file.write(line+'\n') + continue + for field in reject_card: + if field is not None and '=' in field: + raise SyntaxError('cannot reject equal signed ' + 'cards\ncard=%s\n' % reject_card) + raise + + if model.reject_lines: + bdf_file.write('$REJECT_LINES\n') + for reject_lines in model.reject_lines: + if isinstance(reject_lines, (list, tuple)): + for reject in reject_lines: + reject2 = reject.rstrip() + if reject2: + bdf_file.write('%s\n' % reject2) + elif isinstance(reject_lines, str): + reject2 = reject_lines.rstrip() + if reject2: + bdf_file.write('%s\n' % reject2) + else: + raise TypeError(reject_lines) + def _write_rigid_elements(self, bdf_file: TextIOLike, size: int=8, is_double: bool=False, is_long_ids: Optional[bool]=None) -> None: @@ -483,7 +532,6 @@ def _write_nonstructural_mass(self, bdf_file: TextIOLike, bdf_file.write(model.nsml.write(size=size)) bdf_file.write(model.nsml1.write(size=size)) - def _write_masses(self, bdf_file: TextIOLike, size: int=8, is_double: bool=False, is_long_ids: Optional[bool]=None) -> None: diff --git a/pyNastran/dev/bdf_vectorized3/cards/base_card.py b/pyNastran/dev/bdf_vectorized3/cards/base_card.py index b28646b92..d164856ab 100644 --- a/pyNastran/dev/bdf_vectorized3/cards/base_card.py +++ b/pyNastran/dev/bdf_vectorized3/cards/base_card.py @@ -3,7 +3,7 @@ from io import StringIO from typing import Callable, Optional, Any, TYPE_CHECKING import numpy as np -from pyNastran.bdf.field_writer_8 import print_card_8 # , print_float_8, print_field_8 +from pyNastran.dev.bdf_vectorized3.utils import print_card_8 # , print_float_8, print_field_8 from pyNastran.bdf.field_writer_16 import print_card_16 # , print_scientific_16, print_field_16 #from pyNastran.bdf.field_writer_double import print_scientific_double #from pyNastran.bdf.bdf_interface.assign_type import ( diff --git a/pyNastran/dev/bdf_vectorized3/cards/constraints.py b/pyNastran/dev/bdf_vectorized3/cards/constraints.py index f0d556076..f0de454c9 100644 --- a/pyNastran/dev/bdf_vectorized3/cards/constraints.py +++ b/pyNastran/dev/bdf_vectorized3/cards/constraints.py @@ -11,15 +11,17 @@ from pyNastran.bdf.bdf_interface.assign_type import ( integer, integer_or_blank, double, double_or_blank, components_or_blank) -from pyNastran.bdf.field_writer_8 import print_card_8 +#from pyNastran.bdf.field_writer_8 import print_card_8 from pyNastran.bdf.field_writer_16 import print_card_16 # print_float_16 #from pyNastran.bdf.field_writer_double import print_scientific_double +from pyNastran.dev.bdf_vectorized3.cards.base_card import get_print_card_8_16 from pyNastran.dev.bdf_vectorized3.bdf_interface.geom_check import geom_check from pyNastran.dev.bdf_vectorized3.cards.write_utils import array_default_str, array_str, array_default_int -from pyNastran.dev.bdf_vectorized3.utils import cast_int_array +from pyNastran.dev.bdf_vectorized3.utils import cast_int_array, print_card_8 if TYPE_CHECKING: # pragma: no cover from pyNastran.bdf.bdf_interface.bdf_card import BDFCard + from pyNastran.dev.bdf_vectorized3.types import TextIOLike from pyNastran.dev.bdf_vectorized3.bdf import BDF @@ -147,12 +149,12 @@ def _save(self, spc_id, node_id, components, enforced): self.enforced = enforced self.n = nspcs - def write(self, size: int=8) -> str: + def write_file(self, bdf_file: TextIOLike, + size: int=8, is_double: bool=False, + write_card_header: bool=False) -> None: if len(self.spc_id) == 0: - return '' - lines = [] - if size == 8: - print_card = print_card_8 + return + print_card = get_print_card_8_16(size) spc_str = array_str(self.spc_id, size=size) node_str = array_str(self.node_id, size=size) @@ -162,12 +164,12 @@ def write(self, size: int=8) -> str: if no_enforced: for spc_id, node_id, components in zip(spc_str, node_str, components_str): msg = 'SPC %8s%8s%8s\n' % (spc_id, node_id, components) - lines.append(msg) + bdf_file.write(msg) else: for spc_id, node_id, components, enforced in zip(spc_str, node_str, components_str, self.enforced): list_fields = ['SPC', spc_id, node_id, components, enforced] - lines.append(print_card(list_fields)) - return ''.join(lines) + bdf_file.write(print_card(list_fields)) + return def geom_check(self, missing: dict[str, np.ndarray]): nid = self.model.grid.node_id @@ -291,12 +293,12 @@ def _save(self, spc_id, node_id, components, nnodes): def inode(self) -> np.ndarray: return make_idim(self.n, self.nnodes) - def write(self, size: int=8) -> str: + def write_file(self, bdf_file: TextIOLike, + size: int=8, is_double: bool=False, + write_card_header: bool=False) -> None: if len(self.spc_id) == 0: - return '' - lines = [] - if size == 8: - print_card = print_card_8 + return + print_card = get_print_card_8_16(size) spc_str = array_str(self.spc_id, size=size) #node_str = array_str(self.node_id, size=size) @@ -307,8 +309,8 @@ def write(self, size: int=8) -> str: nodes = self.node_id[inode0 : inode1].tolist() assert len(nodes) > 0, nodes list_fields = ['SPC1', spc_id, components] + nodes - lines.append(print_card(list_fields)) - return ''.join(lines) + bdf_file.write(print_card(list_fields)) + return def geom_check(self, missing: dict[str, np.ndarray]): nid = self.model.grid.node_id @@ -413,12 +415,12 @@ def parse_cards(self): #assert len(self.mpc_id) == len(self.coefficients) self.cards = [] - def write(self, size: int=8) -> str: + def write_file(self, bdf_file: TextIOLike, + size: int=8, is_double: bool=False, + write_card_header: bool=False) -> None: if len(self.mpc_id) == 0: - return '' - lines = [] - if size == 8: - print_card = print_card_8 + return + print_card = get_print_card_8_16(size) mpc_str = array_str(self.mpc_id, size=size) node_str = array_str(self.node_id, size=size) @@ -436,8 +438,8 @@ def write(self, size: int=8) -> str: if i % 2 == 1 and i > 0: list_fields.append(None) list_fields.append(None) - lines.append(print_card(list_fields)) - return ''.join(lines) + bdf_file.write(print_card(list_fields)) + return def geom_check(self, missing: dict[str, np.ndarray]): nid = self.model.grid.node_id @@ -560,10 +562,13 @@ def nspcs(self): def nspcs(self): return self.nsids - def write(self, size: int=8) -> str: + def write_file(self, bdf_file: TextIOLike, + size: int=8, is_double: bool = False, + write_card_header: bool=False) -> None: if len(self.spc_id) == 0: - return '' - lines = [] + return + print_card = get_print_card_8_16(size) + spc_ids = array_str(self.spc_ids, size=size) for spc_id, idim in zip(self.spc_id, self.idim): idim0, idim1 = idim @@ -571,13 +576,13 @@ def write(self, size: int=8) -> str: spc_idsi = spc_ids[idim0:idim1].tolist() assert len(spc_idsi) > 0, self.idim list_fields = ['SPCADD', spc_id] + spc_idsi - lines.append(print_card_8(list_fields)) - return ''.join(lines) + bdf_file.write(print_card(list_fields)) + return def get_spcs_by_spc_id(self) -> dict[int, SPCs]: model = self.model """""" - uspc_ids = np.unique(self.spc_id) + #uspc_ids = np.unique(self.spc_id) spc_by_spc_id = defaultdict(list) #for spc_id in uspc_ids: #spc_by_spc_id[spc_id] = [] @@ -593,7 +598,7 @@ def get_spcs_by_spc_id(self) -> dict[int, SPCs]: continue spci = spc.slice_card_by_index(i) spc_by_spc_id[uspc_id].append(spci) - return spc_by_spc_id + return dict(spc_by_spc_id) def get_reduced_spcs(self, #resolve_load_card: bool=False, @@ -653,22 +658,23 @@ def nmpcs(self): def is_small_field(self): return max(self.mpc_id.max(), self.mpc_ids.max()) < 99_999_999 - def write(self, size: int=8) -> str: + def write_file(self, bdf_file: TextIOLike, + size: int=8, is_double: bool=False, + write_card_header: bool=False) -> str: if len(self.mpc_id) == 0: - return '' + return if size == 8 and self.is_small_field: print_card = print_card_8 else: print_card = print_card_16 #self.get_reduced_spcs() - lines = [] mpc_ids = array_str(self.mpc_ids, size=size) for mpc_id, idim in zip(self.mpc_id, self.idim): idim0, idim1 = idim mpc_idsi = mpc_ids[idim0:idim1].tolist() list_fields = ['MPCADD', mpc_id] + mpc_idsi - lines.append(print_card(list_fields)) - return ''.join(lines) + bdf_file.write(print_card(list_fields)) + return def geom_check(self, missing: dict[str, np.ndarray]): mpc_id = np.unique(self.model.mpc.mpc_id) diff --git a/pyNastran/dev/bdf_vectorized3/cards/grid.py b/pyNastran/dev/bdf_vectorized3/cards/grid.py index 76cee1dd7..3a86b5df3 100644 --- a/pyNastran/dev/bdf_vectorized3/cards/grid.py +++ b/pyNastran/dev/bdf_vectorized3/cards/grid.py @@ -580,9 +580,9 @@ def sort(self) -> None: uids_sorted = np.unique(ids_sorted) if not np.array_equal(uarg, iarg): - print(iarg.tolist()) - print('-> ', ids_sorted.tolist()) - print('--> ', uids_sorted.tolist()) + #print(iarg.tolist()) + #print('-> ', ids_sorted.tolist()) + #print('--> ', uids_sorted.tolist()) assert (iarg - uarg).sum() == 0, (iarg - uarg).sum() #if len(iarg) == len(uarg): ## if the lengths are the same, we can use dumb sorting diff --git a/pyNastran/dev/bdf_vectorized3/test/all_tests.py b/pyNastran/dev/bdf_vectorized3/test/all_tests.py index d9f118bf7..03185c2ae 100644 --- a/pyNastran/dev/bdf_vectorized3/test/all_tests.py +++ b/pyNastran/dev/bdf_vectorized3/test/all_tests.py @@ -10,7 +10,7 @@ # good from pyNastran.dev.bdf_vectorized3.cards.test.test_vector_dmig import * from pyNastran.dev.bdf_vectorized3.cards.test.test_vector_bars import * -from pyNastran.dev.bdf_vectorized3.cards.test.test_vector_coords import * +#from pyNastran.dev.bdf_vectorized3.cards.test.test_vector_coords import * from pyNastran.dev.bdf_vectorized3.cards.test.test_vector_shells import TestShells from pyNastran.dev.bdf_vectorized3.cards.test.test_vector_solids import * diff --git a/pyNastran/dev/bdf_vectorized3/test/test_bdf.py b/pyNastran/dev/bdf_vectorized3/test/test_bdf.py index c1810b0fa..9ba229e04 100644 --- a/pyNastran/dev/bdf_vectorized3/test/test_bdf.py +++ b/pyNastran/dev/bdf_vectorized3/test/test_bdf.py @@ -39,7 +39,7 @@ ) from pyNastran.bdf.subcase import Subcase from pyNastran.bdf.test.compare import compare_card_count -from pyNastran.bdf.bdf import BDF as BDF_old, read_bdf as read_bdf_old +from pyNastran.bdf.bdf import BDF as BDF_old #, read_bdf as read_bdf_old from pyNastran.dev.bdf_vectorized3.bdf import BDF as BDFv, read_bdf as read_bdfv, map_version BDFs = Union[BDF_old, BDFv] @@ -423,6 +423,7 @@ def run_and_compare_fems( name: str='', run_nominal: bool=True): """runs two fem models and compares them""" + run_nominal = False if skip_cards is None: skip_cards = [] assert isinstance(bdf_model, str) and os.path.exists(bdf_model), f'{bdf_model!r} doesnt exist\n%s' % print_bad_path(bdf_model) diff --git a/pyNastran/dev/bdf_vectorized3/utils.py b/pyNastran/dev/bdf_vectorized3/utils.py index 668694150..bc5de56c1 100644 --- a/pyNastran/dev/bdf_vectorized3/utils.py +++ b/pyNastran/dev/bdf_vectorized3/utils.py @@ -1,4 +1,12 @@ +import sys +import warnings +from typing import Union + import numpy as np +from numpy import float32, float64 +from pyNastran.dev.bdf_vectorized3.bdf_interface.fast_float_print import get_float_format # print_float_8, +from pyNastran.bdf.field_writer_8 import print_float_8 +from pyNastran.bdf.bdf_interface.assign_type import double_from_str def hstack_msg(mylist, msg: str, min_size=0) -> np.ndarray: if isinstance(mylist, list) and len(mylist) == 0: @@ -19,3 +27,104 @@ def cast_int_array(list_ints: list[int]) -> np.ndarray: return np.array(list_ints, dtype='int32') except OverflowError: return np.array(list_ints, dtype='int64') + +def print_card_8(fields: list[Union[int, float, str, None]]) -> str: + """ + Prints a nastran-style card with 8-character width fields. + + Parameters + ---------- + fields : list[int/float/str/None] + all the fields in the BDF card (no trailing Nones) + + Returns + ------- + card : str + string representation of the card in small field format + + .. note:: An internal field value of None or '' will be treated as + a blank field + .. note:: A small field format follows the 8-8-8-8-8-8-8-8 = 80 + format where the first 8 is the card name or + blank (continuation). The last 8-character field indicates + an optional continuation, but because it's a left-justified + unnecessary field, print_card doesn't use it. + + .. code-block:: python + + >>> fields = ['DUMMY', 1, 2, 3, None, 4, 5, 6, 7, 8.] + >>> print_card_8(fields) + DUMMY 1 2 3 4 5 6 7 + 8. + + """ + try: + out = '%-8s' % fields[0] + except Exception: + warnings.warn("ERROR! fields=%s" % fields) + sys.stdout.flush() + raise + + for i in range(1, len(fields)): + field = fields[i] + try: + out += print_field_8(field) + except Exception: + warnings.warn("bad fields = %s" % fields) + raise + if i % 8 == 0: # allow 1+8 fields per line + out = out.rstrip(' ') + if out[-1] == '\n': # empty line + out += '+' + out += '\n ' + out = out.rstrip(' \n+') + '\n' # removes blank lines at the end of cards + return out + +def print_field_8(value: Union[int, float, str, None]) -> str: + """ + Prints a 8-character width field + + Parameters + ---------- + value : int/float/str + the value to print + + Returns + ------- + field : str + an 8-character string + + """ + assert not isinstance(value, list), value + + if isinstance(value, int): + field = '%8i' % value + elif isinstance(value, (float, float32, float64)): + field_old = print_float_8(value) + field_new = get_float_format(value) + + try: + value_old = double_from_str(field_old.strip()) + except: + raise SyntaxError(f'value={value}; field_old={field_old!r}') + + try: + value_new = double_from_str(field_new.strip()) + except: + raise SyntaxError(f'value={value}; field_new={field_new!r}') + if not value_old == value_new: + print(f'value={value}; field_old={field_old!r} field_new={field_new!r}') + + #assert value_old == value_new, f'value={value}; field_old={field_old!r} field_new={field_new!r}' + field = field_new + + elif value is None: + field = ' ' + else: + field = '%8s' % value + + if len(field) != 8: + nchars = len(field) + msg = f'field={field!r} is not 8 characters long; its {nchars}...raw_value={value!r}' + raise RuntimeError(msg) + return field