#pylint: disable=W0201,C0301,C0111
from __future__ import (nested_scopes, generators, division, absolute_import,
print_function, unicode_literals)
from six import string_types, iteritems, PY2
import copy
from datetime import date
import pyNastran
from pyNastran.op2.op2_f06_common import OP2_F06_Common
[docs]def make_stamp(Title, today=None):
if 'Title' is None:
Title = ''
#lenghts = [7, 8, 5, 5, 3, 4, 4, 6, 9, 7, 8, 8]
months = [' January', 'February', 'March', 'April', 'May', 'June',
'July', 'August', 'September', 'October', 'November', 'December']
if today is None:
today = date.today()
str_month = months[today.month - 1].upper()
str_today = '%-9s %2s, %4s' % (str_month, today.day, today.year)
else:
(month, day, year) = today
str_month = months[month - 1].upper()
str_today = '%-9s %2s, %4s' % (str_month, day, year)
str_today = str_today #.strip()
release_date = '02/08/12' # pyNastran.__releaseDate__
release_date = ''
build = 'pyNastran v%s %s' % (pyNastran.__version__, release_date)
if Title is None:
Title = ''
out = '1 %-67s %-19s %-22s PAGE %%5i\n' % (Title.strip(), str_today, build)
return out
[docs]def make_end(end_flag=False):
lines = []
lines2 = []
if end_flag:
lines = [
'', '',
'0 * * * * A N A L Y S I S S U M M A R Y T A B L E * * * *',
'0 SEID PEID PROJ VERS APRCH SEMG SEMR SEKR SELG SELR MODES DYNRED SOLLIN PVALID SOLNL LOOPID DESIGN CYCLE SENSITIVITY',
' --------------------------------------------------------------------------------------------------------------------------']
#0 0 1 1 ' ' T T T T T F F T 0 F -1 0 F
seid = 0
peid = 0
proj = 1
vers = 1
approach = ' '
SELG = 'T'
SEMG = 'T'
SEMR = 'T'
SEKR = 'T'
SELR = 'T'
MODES = 'F'
DYNRED = 'F'
SOLLIN = 'T'
PVALID = 0
SOLNL = 'F'
LOOPID = -1
CYCLE = 0
SENSITIVITY = 'F'
msg = ' %s %s %s %s %8r %s %s %s %s %s %s %s %s %s %s %s %s %s' % (
seid, peid, proj, vers, approach, SEMG, SEMR, SEKR, SELG, SELR, MODES, DYNRED, SOLLIN, PVALID, SOLNL,
LOOPID, CYCLE, SENSITIVITY)
lines.append(msg)
lines2 = [
'0SEID = SUPERELEMENT ID.',
' PEID = PRIMARY SUPERELEMENT ID OF IMAGE SUPERELEMENT.',
' PROJ = PROJECT ID NUMBER.',
' VERS = VERSION ID.',
' APRCH = BLANK FOR STRUCTURAL ANALYSIS. HEAT FOR HEAT TRANSFER ANALYSIS.',
' SEMG = STIFFNESS AND MASS MATRIX GENERATION STEP.',
' SEMR = MASS MATRIX REDUCTION STEP (INCLUDES EIGENVALUE SOLUTION FOR MODES).',
' SEKR = STIFFNESS MATRIX REDUCTION STEP.',
' SELG = LOAD MATRIX GENERATION STEP.',
' SELR = LOAD MATRIX REDUCTION STEP. ',
' MODES = T (TRUE) IF NORMAL MODES OR BUCKLING MODES CALCULATED.',
' DYNRED = T (TRUE) MEANS GENERALIZED DYNAMIC AND/OR COMPONENT MODE REDUCTION PERFORMED.',
' SOLLIN = T (TRUE) IF LINEAR SOLUTION EXISTS IN DATABASE.',
' PVALID = P-DISTRIBUTION ID OF P-VALUE FOR P-ELEMENTS',
' LOOPID = THE LAST LOOPID VALUE USED IN THE NONLINEAR ANALYSIS. USEFUL FOR RESTARTS.',
' SOLNL = T (TRUE) IF NONLINEAR SOLUTION EXISTS IN DATABASE.',
' DESIGN CYCLE = THE LAST DESIGN CYCLE (ONLY VALID IN OPTIMIZATION).',
' SENSITIVITY = SENSITIVITY MATRIX GENERATION FLAG.',
' ',
' No PARAM values were set in the Control File.'
]
lines3 = [
' ',
'1 * * * END OF JOB * * *',
' ',
' '
]
return '\n'.join(lines + lines2 + lines3)
[docs]class F06Writer(OP2_F06_Common):
def __init__(self):
OP2_F06_Common.__init__(self)
self.card_count = {}
self._found_results = set([])
self._saved_results = set(self.get_all_results())
[docs] def get_all_results(self):
all_results = ['stress', 'strain', 'element_forces', 'constraint_forces'] + self.get_table_types()
return all_results
[docs] def _clear_results(self):
self._saved_results.clear()
[docs] def add_results(self, results):
if isinstance(results, string_types):
results = [results]
all_results = self.get_all_results()
for result in results:
result = str(result)
if result not in all_results:
raise RuntimeError('%r is not a valid result to remove; all_results=%s' % (result, all_results))
if 'stress' == result:
stress_results = []
for result in all_results:
if 'stress' in result.lower():
stress_results.append(result)
#stress_results = [result if 'stress' in result.lower() for result in all_results]
self._saved_results.update(stress_results)
elif 'strain' == result:
strain_results = []
for result in all_results:
if 'strain' in result.lower():
strain_results.append(result)
#strain_results = [result if 'strain' in result.lower() for result in all_results]
self._saved_results.update(strain_results)
elif 'stress' in result.lower():
self._saved_results.add('stress')
elif 'strain' in result.lower():
self._saved_results.add('strain')
elif 'spc_forces' == result or 'mpc_forces' == result or 'constraint_forces' == result:
self._saved_results.add('constraint_forces')
elif 'force' in result.lower(): # could use more validation...
self._saved_results.add('element_forces')
# thermalLoad_VU_3D, thermalLoad_1D, thermalLoad_CONV, thermalLoad_2D_3D
self._saved_results.add(result)
[docs] def set_results(self, results):
if isinstance(results, string_types):
results = [results]
self._clear_results()
self.add_results(results)
[docs] def remove_results(self, results):
all_results = self.get_all_results()
for result in results:
if result not in all_results:
raise RuntimeError('%r is not a valid result to remove; all_results=%s' % (result, all_results))
for result in results:
if result in self._saved_results:
self._saved_results.remove(result)
#disable_set = set(results)
#self._saved_results.difference(disable_set)
#print(self._saved_results)
[docs] def make_stamp(self, Title, today):
"""If this class is inherited, the PAGE stamp may be overwritten"""
return make_stamp(Title, today)
[docs] def make_grid_point_singularity_table(self, failed):
msg = ''
if failed:
msg += '0 G R I D P O I N T S I N G U L A R I T Y T A B L E\n'
msg += '0 POINT TYPE FAILED STIFFNESS OLD USET NEW USET\n'
msg += ' ID DIRECTION RATIO EXCLUSIVE UNION EXCLUSIVE UNION\n'
for (nid, dof) in failed:
msg += ' %8s G %s 0.00E+00 B F SB SB *\n' % (nid, dof)
else:
msg += 'No constraints have been applied...\n'
page_stamp = self.make_stamp(self.Title, self.date)
msg += page_stamp % self.page_num
self.page_num += 1
return msg
[docs] def write_summary(self, f06, card_count=None):
summary_header = ' M O D E L S U M M A R Y\n\n'
summary = ''
self.cards_to_read = set([
# rigid elements
'RBAR', 'RBAR1', 'RBE1', 'RBE2', 'RBE3',
# spc/mpc constraints
'SPC', 'SPCADD', 'SPC1', 'SPCD', 'SPCAX',
'MPC', 'MPCADD',
'SUPORT', 'SUPORT1',
# aero cards
'CAERO1', 'CAERO2', 'CAERO3', 'CAERO4', 'CAERO5',
# temperature cards
'CHBDYE', 'CHBDYG', 'CHBDYP',
'CONV',
])
blocks = [
['POINTS', ['GRID', 'GRDSET', ]],
['ENTRIES', ['SPOINT']],
['ELEMENTS',
[
# these are sorted
# elements
'CONM1', 'CONM2', 'CMASS1', 'CMASS2', 'CMASS3', 'CMASS4',
# springs
'CELAS1', 'CELAS2', 'CELAS3', 'CELAS4', 'CELAS5',
# bushings
'CBUSH', 'CBUSH1D', 'CBUSH2D',
# dampers
'CDAMP1', 'CDAMP2', 'CDAMP3', 'CDAMP4', 'CDAMP5',
# bar flags
'BAROR', 'CBARAO',
# bars
'CBAR', 'CROD', 'CTUBE', 'CBEAM', 'CBEAM3', 'CONROD', 'CBEND',
# shells
'CTRIA3', 'CTRIA6', 'CTRIAR', 'CTRIAX', 'CTRIAX6',
'CQUAD4', 'CQUAD8', 'CQUADR', 'CQUADX', 'CQUAD',
# solids
'CTETRA', 'CPENTA', 'CHEXA',
# other
'CSHEAR', 'CVISC', 'CRAC2D', 'CRAC3D',
'CGAP', 'CFAST', 'RBE2', 'RBE3',
# thermal
'CHBDYP', 'CHBDYG', 'CONV',
]],
]
#print("self.card_count", self.card_count)
if card_count is None:
card_count = self.card_count
for block in blocks:
block_name, keys = block
key_count = 0
for key in sorted(keys):
try:
value = card_count[key]
summary += ' NUMBER OF %-8s %-8s = %8s\n' % (key, block_name, value)
key_count += 1
except KeyError:
pass
if key_count:
summary += ' \n'
if summary:
f06.write(summary_header)
f06.write(summary)
page_stamp = self.make_stamp(self.Title, self.date)
f06.write(page_stamp % self.page_num)
self.page_num += 1
[docs] def write_f06(self, f06_outname, is_mag_phase=False,
delete_objects=True, end_flag=False):
"""
Writes an F06 file based on the data we have stored in the object
:param self: the F06 object
:param f06_outname: the name of the F06 file to write
:param is_mag_phase: should complex data be written using Magnitude/Phase
instead of Real/Imaginary (default=False; Real/Imag)
Real objects don't use this parameter.
:param delete_objects: should objects be deleted after they're written
to reduce memory (default=True)
:param end_flag: should a dummy Nastran "END" table be made
(default=False)
"""
print("F06:")
if isinstance(f06_outname, str):
if PY2:
f06 = open(f06_outname, 'wb')
else:
f06 = open(f06_outname, 'w')
self.write_summary(f06)
else:
assert isinstance(f06_outname, file), 'type(f06_outname)= %s' % f06_outname
f06 = f06_outname
f06_outname = f06.name
print('f06_outname =', f06_outname)
page_stamp = self.make_stamp(self.Title, self.date)
if self.grid_point_weight.reference_point is not None:
print("grid_point_weight")
self.page_num = self.grid_point_weight.write_f06(f06, page_stamp, self.page_num)
assert isinstance(self.page_num, int), self.grid_point_weight.__class__.__name__
if self.oload_resultant is not None:
self.page_num = self.oload_resultant.write_f06(f06, page_stamp, self.page_num)
assert isinstance(self.page_num, int), self.oload_resultant.__class__.__name__
#is_mag_phase = False
header = [' DEFAULT \n',
'\n', '']
# eigenvalues are written first
for ikey, result in sorted(iteritems(self.eigenvalues)):
print('%-18s case=%r' % (result.__class__.__name__, ikey))
self.page_num = result.write_f06(f06, header, page_stamp,
page_num=self.page_num)
assert isinstance(self.page_num, int), 'pageNum=%r' % str(self.page_num)
if delete_objects:
del result
self.page_num += 1
# then eigenvectors
# has a special header
iSubcases = sorted(self.iSubcaseNameMap.keys())
res_keys = []
for isubcase in iSubcases:
for subtitle in self.subtitles[isubcase]:
res_keys.append((isubcase, subtitle))
#print('res_keys=%s' % res_keys)
for res_key in res_keys:
isubcase = res_key[0]
subtitle = res_key[1]
label = self.labels[(isubcase, subtitle)]
is_compressed = len(self.subtitles[isubcase]) == 1
if is_compressed:
res_key = isubcase
if res_key not in self.eigenvectors:
continue
result = self.eigenvectors[res_key]
header[0] = ' %s\n' % subtitle
header[1] = '0 SUBCASE %i\n' % (isubcase)
#header[2] = complex/nonlinear
star = ' '
if hasattr(self, 'data'):
star = '*'
res_length = 18
res_format = '%%-%is SUBCASE=%%i' % res_length
res_format_vectorized = '%%-%is SUBCASE=%%i SUBTITLE=%%s' % res_length
if is_compressed:
print(star + res_format % (result.__class__.__name__, isubcase))
else:
print(star + res_format_vectorized % (result.__class__.__name__, isubcase, subtitle))
self.page_num = result.write_f06(header, page_stamp,
self.page_num, f=f06, is_mag_phase=is_mag_phase)
assert isinstance(self.page_num, int), 'pageNum=%r' % str(self.page_num)
if delete_objects:
del result
self.page_num += 1
# finally, we writte all the other tables
# nastran puts the tables in order of the Case Control deck,
# but we're lazy so we just hardcode the order
# subcase name, subcase ID, transient word & value
header_old = [' DEFAULT \n',
'\n', ' \n']
header = copy.deepcopy(header_old)
res_types = [
self.accelerations,
self.displacements, self.displacementsPSD, self.displacementsATO, self.displacementsRMS,
self.scaledDisplacements, # ???
self.force_vectors,
self.load_vectors,
self.temperatures,
self.velocities, #self.eigenvectors,
self.mpc_forces,
self.spc_forces,
self.thermal_load_vectors,
self.strain_energy,
#------------------------------------------
# OEF - forces
# alphabetical order...
# bars
self.cbar_force,
self.cbar100_force,
# beam
self.cbend_force,
self.cbeam_force,
# alphabetical
self.celas1_force,
self.celas2_force,
self.celas3_force,
self.celas4_force,
self.conrod_force,
self.cquad4_force,
self.cquad8_force,
self.cquadr_force,
self.conrod_force,
self.crod_force,
self.cshear_force,
self.ctria3_force,
self.ctria6_force,
self.ctriar_force,
self.ctube_force,
# springs
self.celas1_force,
self.celas2_force,
self.celas3_force,
self.celas4_force,
# dampers
self.cdamp1_force,
self.cdamp2_force,
self.cdamp3_force,
self.cdamp4_force,
# other
self.cbush_force,
self.cgap_force,
self.cvisc_force,
self.chexa_pressure_force,
self.cpenta_pressure_force,
self.ctetra_pressure_force,
#------------------------------------------
# OES - strain
# 1. cbar
# 2. cbeam
# 3. crod/ctube/conrod
# springs
self.celas1_strain,
self.celas2_strain,
self.celas3_strain,
self.celas4_strain,
self.nonlinear_celas1_stress,
self.nonlinear_celas3_stress,
# bars/beams
self.cbar_strain,
self.cbeam_strain,
# plates
self.cquad4_composite_strain,
self.cquad8_composite_strain,
self.cquadr_composite_strain,
self.ctria3_composite_strain,
self.ctria6_composite_strain,
self.ctriar_composite_strain,
self.nonlinear_ctria3_strain,
self.nonlinear_cquad4_strain,
self.ctriax_strain,
# rods
self.nonlinear_crod_strain,
self.nonlinear_ctube_strain,
self.nonlinear_conrod_strain,
self.chexa_strain,
self.conrod_strain,
self.cpenta_strain,
self.cquad4_strain,
self.cquad8_strain,
self.cquadr_strain,
self.crod_strain,
self.cshear_strain,
self.ctetra_strain,
self.ctria3_strain,
self.ctria6_strain,
self.ctriar_strain,
self.ctube_strain,
# bush
self.cbush_strain,
self.nonlinear_cbush_stress,
self.cbush1d_stress_strain,
#------------------------------------------
# cbars/cbeams
self.cbar_stress,
self.nonlinear_cbeam_stress,
self.cbeam_stress,
# bush
self.cbush_stress,
# rods
self.nonlinear_crod_stress,
self.nonlinear_ctube_stress,
self.nonlinear_conrod_stress,
# shear
# OES - stress
self.celas1_stress,
self.celas2_stress,
self.celas3_stress,
self.celas4_stress,
self.chexa_stress,
self.conrod_stress,
self.cpenta_stress,
self.cquad4_stress,
self.cquad8_stress,
self.cquadr_stress,
self.crod_stress,
self.cshear_stress,
self.ctetra_stress,
self.ctria3_stress,
self.ctria6_stress,
self.ctriar_stress,
self.ctube_stress,
self.cquad4_composite_stress,
self.cquad8_composite_stress,
self.cquadr_composite_stress,
self.ctria3_composite_stress,
self.ctria6_composite_stress,
self.ctriar_composite_stress,
self.nonlinear_ctria3_stress,
self.nonlinear_cquad4_stress,
self.ctriax_stress,
self.hyperelastic_cquad4_strain,
#------------------------------------------
self.grid_point_stresses, self.grid_point_volume_stresses, self.grid_point_forces,
]
for res_key in res_keys:
#title = self.Title
isubcase = res_key[0]
subtitle = res_key[1]
label = self.labels[(isubcase, subtitle)]
is_compressed = len(self.subtitles[isubcase]) == 1
#print(self.subtitles[isubcase])
if is_compressed:
res_key = isubcase
#header[0] = ' %-127s\n' % subtitle
#header[1] = '0 %-72s SUBCASE %-15i\n' % (label, isubcase)
#header[1] = '0 %-72s SUBCASE %-15i\n' % ('',isubcase)
res_length = self._get_result_length(res_types, res_key)
if res_length == 0:
# skipped subcase; no saved results
continue
res_format = '%%-%is SUBCASE=%%i%%s' % res_length
res_format_vectorized = '%%-%is SUBCASE=%%i SUBTITLE=%%s %%s' % res_length
for res_type in res_types:
#print("res_type ", res_type)
header = ['', '']
#header[0] = ' %s\n' % subtitle
header[0] = ' %-126s\n' % subtitle
header[1] = '0 %-32s SUBCASE %-15i\n \n' % (label, isubcase)
#print("res_type = %s" % res_type)
if res_key in res_type:
#header = copy.deepcopy(headerOld) # fixes bug in case
result = res_type[res_key]
if result.nonlinear_factor is not None:
header.append('')
try:
element_name = ''
if hasattr(result, 'element_name'):
element_name = ' - ' + result.element_name
star = '*'
if hasattr(result, 'data'):
star = ' '
if is_compressed:
print(star + res_format % (result.__class__.__name__, isubcase, element_name))
else:
print(star + res_format_vectorized % (result.__class__.__name__, isubcase, subtitle, element_name))
self.page_num = result.write_f06(header, page_stamp, page_num=self.page_num, f=f06, is_mag_phase=False)
assert isinstance(self.page_num, int), 'pageNum=%r' % str(self.page_num)
except:
#print("result name = %r" % result.name())
raise
if delete_objects:
del result
self.page_num += 1
f06.write(make_end(end_flag))
f06.close()