def test_write_4(self): """tests basic op2 writing""" log = get_logger(log=None, level='info', encoding='utf-8') folder = os.path.join(MODEL_PATH, 'sol_101_elements') op2_filename = os.path.join(folder, 'static_solid_shell_bar.op2') op2_filename_debug = os.path.join(folder, 'static_solid_shell_bar.debug.out') op2_filename_out = os.path.join(folder, 'static_solid_shell_bar_out.op2') op2_filename_debug_out = os.path.join( folder, 'static_solid_shell_bar_out.debug.out') #debug_file = 'solid_bending.debug.out' model = os.path.splitext(op2_filename)[0] #debug_file = model + '.debug.out' op2 = read_op2_geom(op2_filename, debug_file=op2_filename_debug, log=log) op2w = OP2Writer(op2) op2w.write_op2(op2_filename_out, obj=op2) #, is_mag_phase=False) op2b = read_op2_geom(op2_filename_out, debug_file=op2_filename_debug_out, log=log) op2.assert_op2_equal(op2b, skip_results=[ 'params', ], stop_on_failure=True, debug=False)
def test_thermal_1(self): """tests basic op2 thermal writing""" log = get_logger(log=None, level='info', encoding='utf-8') folder = os.path.join(MODEL_PATH, 'elements') op2_filename = os.path.join(folder, 'time_thermal_elements.op2') op2_filename_debug = os.path.join(folder, 'time_thermal_elements.debug.out') op2_filename_out = os.path.join(folder, 'time_thermal_elements_out.op2') op2_filename_debug_out = os.path.join( folder, 'time_thermal_elements.debug.out') #debug_file = 'solid_bending.debug.out' model = os.path.splitext(op2_filename)[0] #debug_file = model + '.debug.out' exclude_results = [ 'chbdye_thermal_load', 'chexa_thermal_load', ] op2 = read_op2_geom(op2_filename, debug_file=op2_filename_debug, exclude_results=exclude_results, log=log) op2w = OP2Writer(op2) op2w.write_op2(op2_filename_out, obj=op2) #, is_mag_phase=False) op2b = read_op2_geom(op2_filename_out, debug_file=op2_filename_debug_out, log=log) op2.assert_op2_equal(op2b, skip_results=[ 'params', ], stop_on_failure=True, debug=False)
def test_write_elements_2(self): """tests basic op2 writing""" log = get_logger(log=None, level='info', encoding='utf-8') folder = os.path.join(MODEL_PATH, 'elements') op2_filename = os.path.join(folder, 'freq_elements2.op2') op2_filename_debug = os.path.join(folder, 'freq_elements2.debug.out') op2_filename_out = os.path.join(folder, 'freq_elements_out2.op2') op2_filename_debug_out = os.path.join(folder, 'freq_elements_out2.debug.out') model = os.path.splitext(op2_filename)[0] exclude_results = [ 'ctria6_force', 'ctriar_force', 'cshear_force', 'cvisc_force', 'modal_contribution.cshear_stress', ] op2 = read_op2_geom(op2_filename, debug_file=op2_filename_debug, exclude_results=exclude_results, log=log) op2w = OP2Writer(op2) op2w.write_op2(op2_filename_out, obj=op2) #, is_mag_phase=False) op2b = read_op2_geom(op2_filename_out, debug_file=op2_filename_debug_out, log=log)
def test_write_elements_5(self): """tests basic op2 writing""" log = get_logger(log=None, level='info', encoding='utf-8') folder = os.path.join(MODEL_PATH, 'elements') op2_filename = os.path.join(folder, 'time_elements.op2') op2_filename_debug = os.path.join(folder, 'time_elements.debug.out') op2_filename_out = os.path.join(folder, 'time_elements_out.op2') op2_filename_debug_out = os.path.join(folder, 'time_elements_out.debug.out') model = os.path.splitext(op2_filename)[0] exclude_results = [ 'cshear_force', 'cvisc_force', 'cshear_stress', 'grid_point_forces', '*strain_energy', ] op2 = read_op2_geom(op2_filename, debug_file=op2_filename_debug, exclude_results=exclude_results, log=log) op2w = OP2Writer(op2) op2w.write_op2(op2_filename_out, obj=op2) #, is_mag_phase=False) op2b = read_op2_geom(op2_filename_out, debug_file=op2_filename_debug_out, log=log) op2.assert_op2_equal(op2b, skip_results=[ 'params', ], stop_on_failure=True, debug=False)
def test_write_elements_4(self): """tests basic op2 writing""" folder = os.path.join(MODEL_PATH, 'elements') op2_filename = os.path.join(folder, 'modes_complex_elements.op2') op2_filename_debug = os.path.join(folder, 'modes_complex_elements.debug.out') op2_filename_out = os.path.join(folder, 'modes_complex_elements_out.op2') op2_filename_debug_out = os.path.join( folder, 'modes_complex_elements_out.debug.out') model = os.path.splitext(op2_filename)[0] exclude_results = [ 'ctria6_force', 'ctriar_force', 'cshear_force', 'cvisc_force', 'cshear_stress', #'*strain_energy', ] op2 = read_op2_geom(op2_filename, debug_file=op2_filename_debug, exclude_results=exclude_results) op2w = OP2Writer(op2) op2w.write_op2(op2_filename_out, obj=op2) #, is_mag_phase=False) op2b = read_op2_geom(op2_filename_out, debug_file=op2_filename_debug_out) op2.assert_op2_equal(op2b, skip_results=[ 'params', ], stop_on_failure=True, debug=False)
def test_write_6(self): """tests basic op2 writing""" folder = os.path.join(MODEL_PATH, 'sol_101_elements') op2_filename = os.path.join(folder, 'transient_solid_shell_bar.op2') op2_filename_debug = os.path.join( folder, 'transient_solid_shell_bar.debug.out') op2_filename_out = os.path.join(folder, 'transient_solid_shell_bar_out.op2') op2_filename_debug_out = os.path.join( folder, 'transient_solid_shell_bar_out.debug.out') #debug_file = 'solid_bending.debug.out' model = os.path.splitext(op2_filename)[0] #debug_file = model + '.debug.out' op2 = read_op2_geom(op2_filename, debug_file=op2_filename_debug) op2w = OP2Writer(op2) op2w.write_op2(op2_filename_out, obj=op2) #, is_mag_phase=False) op2b = read_op2_geom(op2_filename_out, debug_file=op2_filename_debug_out) op2.assert_op2_equal(op2b, skip_results=[ 'params', ], stop_on_failure=True, debug=False)
def test_write_2(self): """tests basic op2 writing""" log = get_logger(log=None, level='info', encoding='utf-8') folder = os.path.join(MODEL_PATH, 'solid_bending') op2_filename = os.path.join(folder, 'solid_bending.op2') op2_filename_debug = os.path.join(folder, 'solid_bending.debug.out') op2_filename_out = os.path.join(folder, 'solid_bending_out.op2') op2_filename_debug_out = os.path.join(folder, 'solid_bending_out.debug.out') #debug_file = 'solid_bending.debug.out' model = os.path.splitext(op2_filename)[0] #debug_file = model + '.debug.out' op2 = read_op2(op2_filename, debug_file=op2_filename_debug, log=log) op2w = OP2Writer(op2) op2w.write_op2(op2_filename_out, obj=op2) #, is_mag_phase=False) op2b = read_op2_geom(op2_filename_out, debug_file=op2_filename_debug_out, log=log) assert op2 == op2b
def test_write_1(self): """tests basic op2 writing""" folder = os.path.join(MODEL_PATH, 'solid_bending') op2_filename = os.path.join(folder, 'solid_bending.op2') op2_filename_debug = os.path.join(folder, 'solid_bending.debug.out') op2_filename_out = os.path.join(folder, 'solid_bending_out.op2') op2_filename_debug_out = os.path.join(folder, 'solid_bending_out.debug.out') #debug_file = 'solid_bending.debug.out' model = os.path.splitext(op2_filename)[0] #debug_file = model + '.debug.out' op2 = read_op2_geom(op2_filename, debug_file=op2_filename_debug, include_results='displacements') op2w = OP2Writer(op2) op2w.write_op2(op2_filename_out, obj=op2) #, is_mag_phase=False) op2b = read_op2_geom(op2_filename_out, debug_file=op2_filename_debug_out) assert op2 == op2b
def test_thermal_2(self): """tests basic op2 thermal writing""" folder = os.path.join(MODEL_PATH, 'other') op2_filename = os.path.join(folder, 'hd15306.op2') op2_filename_debug = os.path.join(folder, 'hd15306.debug.out') op2_filename_out = os.path.join(folder, 'hd15306_out.op2') op2_filename_debug_out = os.path.join(folder, 'hd15306.debug.out') #debug_file = 'solid_bending.debug.out' model = os.path.splitext(op2_filename)[0] #debug_file = model + '.debug.out' exclude_results = [ 'chbdyg_thermal_load', 'crod_thermal_load', 'cquad4_thermal_load', #'chbdye_thermal_load', #'chexa_thermal_load', ] op2 = read_op2_geom( op2_filename, debug_file=op2_filename_debug, exclude_results=exclude_results, debug=True, #include_results='eigenvectors', #include_results=['crod_stress', 'cbar_stress'], #include_results=['crod_force', 'cbar_force'], #include_results='element_forces', #include_results='stress', ) str(op2.get_op2_stats(short=True)) op2w = OP2Writer(op2) op2w.write_op2(op2_filename_out, obj=op2) #, is_mag_phase=False) op2b = read_op2_geom(op2_filename_out, debug_file=op2_filename_debug_out) op2.assert_op2_equal(op2b, skip_results=[ 'params', ], stop_on_failure=True, debug=False)
def test_write_5(self): """tests basic op2 writing""" folder = os.path.join(MODEL_PATH, 'sol_101_elements') op2_filename = os.path.join(folder, 'mode_solid_shell_bar.op2') op2_filename_debug = os.path.join(folder, 'mode_solid_shell_bar.debug.out') op2_filename_out = os.path.join(folder, 'mode_solid_shell_bar_out.op2') op2_filename_debug_out = os.path.join( folder, 'mode_solid_shell_bar_out.debug.out') #debug_file = 'solid_bending.debug.out' model = os.path.splitext(op2_filename)[0] #debug_file = model + '.debug.out' exclude_results = [ #'*_strain_energy', ] op2 = read_op2_geom( op2_filename, debug_file=op2_filename_debug, exclude_results=exclude_results, #include_results='eigenvectors', #include_results=['crod_stress', 'cbar_stress'], #include_results=['crod_force', 'cbar_force'], #include_results='element_forces', #include_results='stress', ) op2w = OP2Writer(op2) op2w.write_op2( op2_filename_out, obj=op2, ) #is_mag_phase=False) op2b = read_op2_geom(op2_filename_out, debug_file=op2_filename_debug_out) op2.assert_op2_equal(op2b, skip_results=[ 'params', ], stop_on_failure=True, debug=False)
def test_write_elements_1(self): """tests basic op2 writing""" folder = os.path.join(MODEL_PATH, 'elements') op2_filename = os.path.join(folder, 'freq_elements.op2') op2_filename_debug = os.path.join(folder, 'freq_elements.debug.out') op2_filename_out = os.path.join(folder, 'freq_elements_out.op2') op2_filename_debug_out = os.path.join(folder, 'freq_elements_out.debug.out') model = os.path.splitext(op2_filename)[0] op2 = read_op2_geom(op2_filename, debug_file=op2_filename_debug) op2w = OP2Writer(op2) op2w.write_op2(op2_filename_out, obj=op2) #, is_mag_phase=False) op2b = read_op2_geom(op2_filename_out, debug_file=op2_filename_debug_out) op2.assert_op2_equal(op2b, skip_results=[ 'params', ], stop_on_failure=True, debug=False)
def run_op2(op2_filename: str, make_geom: bool = False, write_bdf: bool = False, read_bdf: Optional[bool] = None, write_f06: bool = True, write_op2: bool = False, write_hdf5: bool = True, is_mag_phase: bool = False, is_sort2: bool = False, is_nx: Optional[bool] = None, delete_f06: bool = False, build_pandas: bool = True, subcases: Optional[str] = None, exclude: Optional[str] = None, short_stats: bool = False, compare: bool = True, debug: bool = False, log: Any = None, binary_debug: bool = False, quiet: bool = False, stop_on_failure: bool = True, dev: bool = False, xref_safe: bool = False, post: Any = None, load_as_h5: bool = False) -> Tuple[OP2, bool]: """ Runs an OP2 Parameters ---------- op2_filename : str path of file to test make_geom : bool; default=False should the GEOMx, EPT, MPT, DYNAMIC, DIT, etc. tables be read write_bdf : bool; default=False should a BDF be written based on the geometry tables write_f06 : bool; default=True should an F06 be written based on the results write_op2 : bool; default=False should an OP2 be written based on the results is_mag_phase : bool; default=False False : write real/imag results True : write mag/phase results For static results, does nothing is_sort2 : bool; default=False False : writes "transient" data is SORT1 True : writes "transient" data is SORT2 is_nx : bool; default=None True : use NX Nastran False : use MSC Nastran None : guess delete_f06 : bool; default=False deletes the F06 (assumes write_f06 is True) subcases : List[int, ...]; default=None limits subcases to specified values; default=None -> no limiting exclude : List[str, ...]; default=None limits result types; (remove what's listed) short_stats : bool; default=False print a short version of the op2 stats compare : bool True : compares vectorized result to slow vectorized result False : doesn't run slow vectorized result debug : bool; default=False debug flag for OP2 log : logger; default=None a custom logger None : use debug binary_debug : bool; default=False creates a very cryptic developer debug file showing exactly what was parsed quiet : bool; default=False don't write debug messages stop_on_failure : bool; default=True is this used??? dev : bool; default=False flag that is used by op2_test.py to ignore certain errors False : crash on errors True : don't crash Returns ------- op2 : OP2() the op2 object is_passed : bool did the test pass """ assert build_pandas in [True, False] if read_bdf is None: read_bdf = write_bdf op2 = None op2_nv = None if subcases is None: subcases = [] if exclude is None: exclude = [] if isinstance(is_sort2, bool): sort_methods = [is_sort2] else: sort_methods = is_sort2 assert '.op2' in op2_filename.lower( ), 'op2_filename=%s is not an OP2' % op2_filename is_passed = False fname_base = os.path.splitext(op2_filename)[0] bdf_filename = fname_base + '.test_op2.bdf' if isinstance(subcases, str): if '_' in subcases: subcases = [int(i) for i in subcases.split('_')] else: subcases = [int(subcases)] debug_file = None model = os.path.splitext(op2_filename)[0] if binary_debug or write_op2: debug_file = model + '.debug.out' #print('debug_file = %r' % debug_file, os.getcwd()) if make_geom: op2 = OP2Geom(debug=debug, log=log) op2_nv = OP2Geom(debug=debug, log=log, debug_file=debug_file) op2_bdf = OP2Geom(debug=debug, log=log) if is_nx is None: pass elif is_nx: op2.set_as_nx() op2_nv.set_as_nx() op2_bdf.set_as_nx() else: op2.set_as_msc() op2_nv.set_as_msc() op2_bdf.set_as_msc() if post is not None: op2.post = -4 op2_nv.post = -4 op2_bdf.post = -4 if load_as_h5 and IS_HDF5: # you can't open the same h5 file twice op2.load_as_h5 = load_as_h5 #op2_nv.load_as_h5 = load_as_h5 #op2_bdf.load_as_h5 = load_as_h5 op2_bdf.set_error_storage(nparse_errors=0, stop_on_parsing_error=True, nxref_errors=0, stop_on_xref_error=True) else: op2 = OP2(debug=debug, log=log) # have to double write this until ??? op2_nv = OP2(debug=debug, log=log, debug_file=debug_file) if is_nx is None: pass elif is_nx: print('set as nx') op2.set_as_nx() op2_nv.set_as_nx() else: op2.set_as_msc() op2_nv.set_as_msc() if post is not None: op2.post = -4 op2_nv.post = -4 if load_as_h5 and IS_HDF5: # you can't open the same h5 file twice op2.load_as_h5 = load_as_h5 #op2_nv.load_as_h5 = load_as_h5 op2_bdf = None op2_nv.use_vector = False if not quiet: op2.log.debug('subcases = %s' % subcases) op2.set_subcases(subcases) op2_nv.set_subcases(subcases) op2.remove_results(exclude) op2_nv.remove_results(exclude) try: #op2.read_bdf(op2.bdf_filename, includeDir=None, xref=False) if compare: op2_nv.read_op2(op2_filename) op2.read_op2(op2_filename) #if not make_geom: # TODO: enable this... #op2.save() #op2a.get_op2_stats() op2.get_op2_stats() op2.get_op2_stats(short=True) op2.object_attributes() op2.object_methods() if not quiet: print("---stats for %s---" % op2_filename) print(op2.get_op2_stats(short=short_stats)) op2.print_subcase_key() write_op2_as_bdf(op2, op2_bdf, bdf_filename, write_bdf, make_geom, read_bdf, dev, xref_safe=xref_safe) if compare: assert op2 == op2_nv if IS_HDF5 and write_hdf5: from pyNastran.op2.op2_interface.hdf5_interface import load_op2_from_hdf5_filename h5_filename = model + '.test_op2.h5' op2.export_hdf5_filename(h5_filename) load_op2_from_hdf5_filename(h5_filename, log=op2.log) if write_f06: for is_sort2 in sort_methods: op2.write_f06(model + '.test_op2.f06', is_mag_phase=is_mag_phase, is_sort1=not is_sort2, quiet=quiet, repr_check=True) if delete_f06: try: os.remove(model + '.test_op2.f06') except: pass # we put it down here so we don't blame the dataframe for real errors if IS_PANDAS and build_pandas: op2.build_dataframe() #if compare: #op2_nv.build_dataframe() if write_op2: model = os.path.splitext(op2_filename)[0] op2_filename2 = model + '.test_op2.op2' op2w = OP2Writer(op2) total_case_count = op2w.write_op2( op2_filename2, obj=op2, #is_mag_phase=is_mag_phase, endian=b'<') if total_case_count > 0: #print('------------------------------') op2a = OP2(debug_file='debug.out', log=log) op2a.use_vector = False op2a.read_op2(op2_filename2) os.remove(op2_filename2) #read_op2(op2_filename2) if delete_f06: try: os.remove(op2_filename2) except: pass #table_names_f06 = parse_table_names_from_F06(op2.f06FileName) #table_names_op2 = op2.getTableNamesFromOP2() #print("subcases = ", op2.subcases) #if table_names_f06 != table_names_op2: #msg = 'table_names_f06=%s table_names_op2=%s' % (table_names_f06, table_names_op2) #raise RuntimeError(msg) #op2.case_control_deck.sol = op2.sol #print(op2.case_control_deck.get_op2_data()) #print(op2.case_control_deck.get_op2_data()) is_passed = True except MemoryError: raise except KeyboardInterrupt: sys.stdout.flush() print_exc(file=sys.stdout) sys.stderr.write('**file=%s\n' % op2_filename) sys.exit('keyboard stop...') #except SortCodeError: # inherits from Runtime; comment this #is_passed = True #except RuntimeError: # the op2 is bad, not my fault; comment this #is_passed = True #if stop_on_failure: #raise #else: #is_passed = True #except RuntimeError: #pass #except ValueError: #pass #except IndexError: #pass #except FortranMarkerError: #pass except IOError: # missing file; this block should be uncommented #if stop_on_failure: #raise if not dev: raise is_passed = True #except UnicodeDecodeError: # this block should be commented #is_passed = True #except NotImplementedError: # this block should be commented #is_passed = True except FatalError: # this block should be commented #if stop_on_failure: #raise if not dev: raise is_passed = True #except KeyError: # this block should be commented #is_passed = True #except DeviceCodeError: # this block should be commented #is_passed = True #except AssertionError: # this block should be commented #is_passed = True #except RuntimeError: #invalid analysis code; this block should be commented #is_passed = True #except ValueError: # this block should be commented #is_passed = True #except NotImplementedError: # this block should be commented #is_passed = True #except FortranMarkerError: # this block should be commented #is_passed = True except DuplicateIDsError: if not dev: raise is_passed = True except SystemExit: #print_exc(file=sys.stdout) #sys.exit('stopping on sys.exit') raise #except NameError: # variable isnt defined # if stop_on_failure: # raise # else: # is_passed = True #except IndexError: # this block should be commented #is_passed = True #except SyntaxError: #Param Parse; this block should be commented #if stop_on_failure: #raise #is_passed = True except: #print(e) if stop_on_failure: raise else: print_exc(file=sys.stdout) is_passed = False return op2, is_passed
def save_load_deck(model, xref='standard', punch=True, run_remove_unused=True, run_convert=True, run_renumber=True, run_mirror=True, run_save_load=True, run_quality=True, write_saves=True, run_save_load_hdf5=True, run_mass_properties=True, run_loads=True, run_test_bdf=True, run_op2_writer=True, run_op2_reader=True): """writes, re-reads, saves an obj, loads an obj, and returns the deck""" model.set_error_storage(nparse_errors=0, stop_on_parsing_error=True, nxref_errors=0, stop_on_xref_error=True) model.validate() model.pop_parse_errors() model.pop_xref_errors() bdf_file = StringIO() model.write_bdf(bdf_file, size=8, close=False) bdf_file.seek(0) model.write_bdf(bdf_file, size=16, close=False) bdf_file.seek(0) model.write_bdf(bdf_file, size=16, is_double=True, close=False) bdf_file.seek(0) if write_saves and model.save_file_structure: bdf_filenames = { 0: 'junk.bdf', } model.write_bdfs(bdf_filenames) os.remove('junk.bdf') if run_remove_unused: remove_unused(model) if run_convert: units_to = ['m', 'kg', 's'] units = ['ft', 'lbm', 's'] convert(model, units_to, units) model2 = BDF(log=model.log) #print(bdf_file.getvalue()) model2.read_bdf(bdf_file, punch=punch, xref=False) _cross_reference(model2, xref) model2.pop_parse_errors() model2.get_bdf_stats() model2.write_bdf('model2.bdf') if run_test_bdf: folder = '' log_error = get_logger(log=None, level='error', encoding='utf-8') test_bdf(folder, 'model2.bdf', stop_on_failure=True, punch=punch, quiet=True, log=log_error) nelements = len(model2.elements) + len(model2.masses) nnodes = len(model2.nodes) + len(model2.spoints) + len(model2.epoints) _run_mass_properties(model2, nnodes, nelements, run_mass_properties=run_mass_properties) _run_loads(model2, nelements, run_loads=run_loads) if run_save_load: model2.save(obj_filename='model.obj', unxref=True) model3 = BDF(debug=False, log=model.log, mode='msc') model3.load(obj_filename='model.obj') os.remove('model.obj') else: model2.uncross_reference() model3 = model2 if run_save_load_hdf5 and IS_H5PY: model2.export_hdf5_filename('test.h5') model4 = BDF(log=model2.log) model4.load_hdf5_filename('test.h5') model4.validate() bdf_stream = StringIO() model4.write_bdf(bdf_stream, encoding=None, size=8, is_double=False, interspersed=False, enddata=None, write_header=True, close=True) for key, unused_value in model2.card_count.items(): if key == 'ENDDATA': continue if key not in model4.card_count: msg = 'key=%r was not loaded to hdf5\nexpected=%s\nactual=%s' % ( key, model2.card_count, model4.card_count) #raise RuntimeError(msg) model.log.error(msg) cross_reference(model3, xref) if run_renumber: renumber('model2.bdf', model.log) if run_mirror: # we put this under renumber to prevent modifying an # existing model to prevent breaking tests # # shouldn't have any effect model2.bdf model_mirrored = bdf_mirror('model2.bdf', plane='xz', log=model.log)[0] model_mirrored.write_bdf('mirrored2.bdf') read_bdf('mirrored2.bdf', log=model.log) os.remove('mirrored2.bdf') os.remove('model2.bdf') if model.elements and run_quality: element_quality(model) if run_op2_writer: op2_geom_model = attach_op2_results_to_bdf(model, op2_model=None) from pyNastran.op2.dev.op2_writer import OP2Writer from pyNastran.op2.op2_geom import read_op2_geom table_name = 'OUGV1' node_gridtype = np.zeros((10, 2), dtype='int32') node_gridtype[:, 0] = np.arange(1, 11) data = np.zeros((1, 10, 6), dtype='float32') isubcase = 1 disp = RealDisplacementArray.add_static_case(table_name, node_gridtype, data, isubcase, is_sort1=True) op2_geom_model.displacements[isubcase] = disp op2w = OP2Writer() op2_filename = 'spike.op2' op2w.write_op2(op2_filename, obj=op2_geom_model, post=-1, endian=b'<', skips=None, nastran_format='nx') if run_op2_reader: op2r = read_op2_geom(op2_filename, log=op2_geom_model.log, xref=False) else: frame = inspect.currentframe() call_frame = inspect.getouterframes(frame, 2) op2_geom_model.log.warning('skipping op2 reader for %s' % call_frame[1][3]) return model3