diff --git a/msgpi/ms/beam.py b/msgpi/ms/beam.py index bdf24cc..45225a4 100644 --- a/msgpi/ms/beam.py +++ b/msgpi/ms/beam.py @@ -213,6 +213,9 @@ def __init__(self): #: `{sid: BeamProperty object, ...}` self.sections = {} + # {section name: template name, ...} + self.section_templates = {} + self.frames = {} #: Local frames self.distrloads = [] #: Distribution loads self.timefunctions = [] #: Time functions @@ -258,6 +261,10 @@ def summary(self): print('\nMember B.C.') + print('\nSection templates') + for sn, st in self.section_templates.items(): + print(f'{sn}: {st}') + print('\nSectional properties') for sid, bp in self.sections.items(): print('Section', sid) @@ -279,28 +286,6 @@ def summary(self): - def echo(self): - """Print the beam data. - """ - print('') - print('Key Point Coordinates') - print('='*40) - for pid, coords in self.points.items(): - print('point {pid:4d}: {xyz[0]:16.6e} {xyz[1]:16.6e} {xyz[2]:16.6e}'.format(pid=pid, xyz=coords)) - print('') - print('Member Definition') - print('='*40) - for mid, bs in self.segments.items(): - print( - 'member {mid:4d}: {pids[0]:4d} {pids[1]:4d} {cs[0]:4d} {cs[1]:4d} {frm:4d} {ndiv:4d} {curv:4d}'.format( - mid=mid, pids=bs.points, cs=bs.css, frm=bs.frame_id, ndiv=bs.num_divisions, curv=bs.curv_id - ) - ) - print('') - - - - def printResults(self): for i, step in enumerate(self.results_steps): print('step', i+1) diff --git a/msgpi/ms/beam2.py b/msgpi/ms/beam2.py deleted file mode 100644 index 0007eaf..0000000 --- a/msgpi/ms/beam2.py +++ /dev/null @@ -1,15 +0,0 @@ -import numpy as np -import msgpi.sg as sg - - -class Beam(object): - """[summary] - - Parameters - ---------- - object : [type] - [description] - """ - - def __init(self): - self.name = '' diff --git a/msgpi/ms/blade.py b/msgpi/ms/blade.py new file mode 100644 index 0000000..842c9cd --- /dev/null +++ b/msgpi/ms/blade.py @@ -0,0 +1,195 @@ +import numpy as np +import pprint +import msgpi.sg as sg + + +class BladeSegment(object): + """Class for a blade segment. + """ + + def __init__(self): + #: list of ints: Point labels. + #: `[beginning point, ending point]` + self.points = [] + #: list of lists of floats: Coordinates of beginning and ending points. + #: `[[x1, x2, x3], [x1, x2, x3]]` + self.coords = [] + #: list of ints: Cross-section labels. + #: `[beginning, ending]` + self.css = [] + + # {local coord: section name, ...} + self.sections = {} + + #: float: Rotation around a1. + self.rotate_a1 = 0.0 + #: float: Twist. + self.twist = 0.0 + # self.dihedral = 0. + # self.sweep = 0. + #: int: Local frame id. + self.local_frame_id = 0 + #: int: Frame id + self.frame_id = 0 + #: int: Curvature id + self.curv_id = 0 + + #: int: Number of division of the segment. + self.num_divisions = 1 + + #: dict: Parameter distributions + #: `{name: [beginning value, ending value], ...}` + self.cs_parameters = {} + + def summary(self): + print(' points:', self.points) + print(' coords:', self.coords) + print(' cs names:', self.css) + print(' cs templates:', self.cs_template) + print(' cs parameters:', self.cs_parameters) + + def calcLengthSq(self): + """Calculate the square of the segment length. + + Returns + ------- + float + Squred length of the segment. + """ + return ((np.array(self.coords[0]) - np.array(self.coords[1]))**2).sum() + + + + + + + + + +class Blade(object): + """Class for a rotor blade. + + """ + + def __init__(self): + #: str: Name of the beam. + self.name = '' + + # Design + + #: dict of {int, list of floats}: Key point id and coordinates. + #: `{ptid: [x1, x2, x3], ...}` + self.points = {} + + #: dict of {int, msgpi.ms.beam.BeamSegment}: Beam segments + #: `{bsid: BeamSegment object, ...}` + self.segments = {} + + #: dict of {int, msgpi.sg.BeamProperty}: Effective properties of cross-sections. + #: `{sid: BeamProperty object, ...}` + self.sections = {} + + # {section name: msgpi.sg.CrossSection, ...} + self.section_database = {} + + self.frames = {} #: Local frames + self.distrloads = [] #: Distribution loads + self.timefunctions = [] #: Time functions + self.initcurvatures = [] #: Initial curvatures + + self.functions = {} #: Functions + self.distributions = {} #: Distributions + + + + + def summary(self): + pp = pprint.PrettyPrinter(indent=4, compact=False) + + print('\nAnalysis') + print('analysis type:', self.analysis_type) + print('max iteration:', self.max_iteration) + print('number of steps:', self.num_steps) + if self.analysis_type != 0: + print('angular velocity:', self.angular_velocity) + print('time function:', self.av_tf) + print('linear velocity:', self.linear_velocity) + print('time function:', self.lv_tf) + if self.analysis_type == 3: + print('number of eigen results:', self.num_eigens) + + print('\nPoints') + # pp.pprint(self.points) + for pid, coords in self.points.items(): + print(f'{pid}: ( {coords[0]} , {coords[1]} , {coords[2]} )') + + print('\nSegments') + for k, v in self.segments.items(): + print('segment', k) + v.summary() + + print('\nSection templates') + for sn, st in self.section_templates.items(): + print(f'{sn}: {st}') + + print('\nSectional properties') + for sid, bp in self.sections.items(): + print('Section', sid) + print('Compliance') + pp.pprint(bp.cmpl_t) + if self.analysis_type != 0: + print('Mass') + pp.pprint(bp.mass) + print('') + + print('\nDistributions') + pp.pprint(self.distributions) + + print('\nFunctions') + # pp.pprint(self.functions) + for k, v in self.functions.items(): + print(k, ':', v) + + + + + def findPtCoordByName(self, name): + """Find key point coordinates by point id. + + Parameters + ---------- + name : int + Point id. + + Returns + ------- + list of floats + Point coordinates. + """ + for i, c in self.points.items(): + if i == name: + return c + return None + + + + + def findSectionByName(self, name): + """Find sectional properties by section id. + + Parameters + ---------- + name : int + Section id. + + Returns + ------- + msgpi.sg.MaterialSection + Sectional properties. + """ + for i, s in self.sections.items(): + if s.name == name: + return i + return 0 + + diff --git a/msgpi/ms/prebeam.py b/msgpi/ms/prebeam.py index 26a361c..a4a39ef 100644 --- a/msgpi/ms/prebeam.py +++ b/msgpi/ms/prebeam.py @@ -582,6 +582,9 @@ def preBeam2(fn_beam): bs.cs_template.append(fn_cs_template) bs.css.append(cs_name) + if not cs_name in beam.section_templates.keys(): + beam.section_templates[cs_name] = fn_cs_template + # Ending station xe_stop = xe_sgm.find('end') pn = xe_stop.find('location').text.strip() @@ -597,6 +600,10 @@ def preBeam2(fn_beam): bs.cs_template.append(fn_cs_template) bs.css.append(cs_name) + if not cs_name in beam.section_templates.keys(): + beam.section_templates[cs_name] = fn_cs_template + + # Cross-section parameters for xe_param in xe_sgm.findall('parameter'): name = xe_param.find('name').text.strip() diff --git a/msgpi/sg.py b/msgpi/sg.py index 13cf0c2..91a3893 100644 --- a/msgpi/sg.py +++ b/msgpi/sg.py @@ -948,61 +948,22 @@ def writeGmshMsh(self, fo, nid_begin=1, eid_begin=1, loc=[0, 0, 0], *args, **kwa -def calcOffsetBeamProperty(sg, offset_x2, offset_x3): - sg_off = copy.deepcopy(sg) - # Offset mass matrix - mm_o = np.asarray(sg_off.mass_mc) - if (offset_x2 != sg_off.mass_center[1]) or (offset_x3 != sg_off.mass_center[2]): - # mm_c = np.asarray(self.mass_mc) - mu = mm_o[0, 0] - mi_c = mm_o[3:, 3:] +class CrossSection(object): + """A simple class for cross-sections - x2 = sg_off.mass_center[1] - offset_x2 - x3 = sg_off.mass_center[2] - offset_x3 - r_tilde = np.array([ - [0, -x3, x2], - [x3, 0, 0], - [-x2, 0, 0] - ]) - - mm_o[:3, 3:] = mu * r_tilde.T - mm_o[3:, :3] = mu * r_tilde - - # I_o = I_c + m * r_tilde.r_tilde^T - mm_o[3:, 3:] = mm_o[3:, 3:] + mu * np.dot(r_tilde, r_tilde.T) - sg_off.mass_origin = mm_o - sg_off.mass_center[1] -= offset_x2 - sg_off.mass_center[2] -= offset_x3 - - - # Offset stiffness and compliance - trfm_4 = np.eye(4) - trfm_6 = np.eye(6) - - trfm_4[2, 0] = offset_x3 - trfm_4[3, 0] = -offset_x2 - - trfm_6[4, 0] = offset_x3 - trfm_6[5, 0] = -offset_x2 - trfm_6[3, 1] = -offset_x3 - trfm_6[3, 2] = offset_x2 - - cmp_4 = np.asarray(sg_off.compliance) - cmp_6 = np.asarray(sg_off.compliance_refined) - - sg_off.compliance = np.dot(trfm_4.T, np.dot(cmp_4, trfm_4)) - sg_off.compliance_refined = np.dot(trfm_6.T, np.dot(cmp_6, trfm_6)) + """ - sg_off.stiffness = np.linalg.inv(sg_off.compliance) - sg_off.stiffness_refined = np.linalg.inv(sg_off.compliance_refined) + def __init__(self, name): + self.name = name + self.template = "" - sg_off.tension_center[1] -= offset_x2 - sg_off.tension_center[2] -= offset_x3 + self.sg = None - sg_off.shear_center[1] -= offset_x2 - sg_off.shear_center[2] -= offset_x3 + self.params = {} + self.props = {} - return sg_off + def summary(self): + print(f'cross-section: {self.name}') diff --git a/tests/test_prebeam/test_prebeam_1.py b/tests/test_prebeam/test_prebeam_1.py new file mode 100644 index 0000000..f797ff1 --- /dev/null +++ b/tests/test_prebeam/test_prebeam_1.py @@ -0,0 +1,5 @@ +import msgpi.ms.prebeam as prebeam + +beam = prebeam.preBeam2('uh60a_blade.xml') + +beam.summary() diff --git a/tests/test_prebeam/uh60a_blade.xml b/tests/test_prebeam/uh60a_blade.xml index 8587dfd..9efcc75 100644 --- a/tests/test_prebeam/uh60a_blade.xml +++ b/tests/test_prebeam/uh60a_blade.xml @@ -15,8 +15,15 @@ 0.9 0 0 + + + p1 @@ -38,6 +45,8 @@ + + p2