From 44847ed5670537f351b31221b2d482a61d98998c Mon Sep 17 00:00:00 2001 From: Mitchell Tesch Date: Wed, 13 Mar 2024 18:15:29 +1000 Subject: [PATCH] fix of database edit link prop methods --- .gitignore | 8 +- examples/PyTABS_LinkSpringProp/excel_index.py | 30 ++++ examples/PyTABS_LinkSpringProp/main.py | 138 ++++++++++++++---- src/pytabs/database_tables.py | 13 +- src/pytabs/properties/prop_link.py | 9 +- 5 files changed, 162 insertions(+), 36 deletions(-) create mode 100644 examples/PyTABS_LinkSpringProp/excel_index.py diff --git a/.gitignore b/.gitignore index 7ec585d..2778c7a 100644 --- a/.gitignore +++ b/.gitignore @@ -229,4 +229,10 @@ fabric.properties .idea/httpRequests # Android studio 3.1+ serialized cache file -.idea/caches/build_file_checksums.ser \ No newline at end of file +.idea/caches/build_file_checksums.ser + + + + +# Specific example files +examples/PyTABS_LinkSpringProp/XX-XX-CA-ST-Perimeter Wall P-Y Curves-240308.xlsx \ No newline at end of file diff --git a/examples/PyTABS_LinkSpringProp/excel_index.py b/examples/PyTABS_LinkSpringProp/excel_index.py new file mode 100644 index 0000000..f799ddc --- /dev/null +++ b/examples/PyTABS_LinkSpringProp/excel_index.py @@ -0,0 +1,30 @@ +# Workbook indexing of multi-linear elastic links + +WB_FILE = 'XX-XX-CA-ST-Perimeter Wall P-Y Curves-240308.xlsx' +WB_SHEET = 'SUMMARY' +TABLE_RANGES = {'PW_GA_NESW_3.5_2.5': 'C62', + 'PW_HF_NESW_3.5_-3.5': 'C84', + 'PW_MS_NESW_3.5_-4.5': 'C107', + 'PW_MS_W_3.5_-2': 'C130', + 'PW_TA_NE_-2.5_-4': 'C153', + 'PW_TA_NE_-4_-6': 'C175', + 'PW_TA_NE_-8_-9': 'C197', + 'PW_TA_NE_-9_-10': 'C219', + 'PW_TA_NE_-10_-11': 'C241', + 'PW_TA_NE_-12_': 'C263', + 'PW_TA_S_-5.5_-6': 'C286', + 'PW_TA_S_-8_-9': 'C309', + 'PW_TA_S_-9_-10': 'C332', + 'PW_TA_S_-10_-11': 'C355', + 'PW_TA_S_-11_-12': 'C377', + 'PW_TA_S_-12_-13': 'C399', + 'PW_TA_S_-13_': 'C421', + 'PW_TA_W_-2.5_-3.5': 'C444', + 'PW_TA_W_-3.5_-4.5': 'C467', + 'PW_TA_W_-4.5_-6': 'C490', + 'PW_TA_W_-8_-9': 'C512', + 'PW_TA_W_-9_-10': 'C534', + 'PW_TA_W_-10_-11.5': 'C556', + 'PW_TA_NEW_-6_-8': 'C577', + 'PW_TA_S_-6_-8': 'C598', + } diff --git a/examples/PyTABS_LinkSpringProp/main.py b/examples/PyTABS_LinkSpringProp/main.py index 3e3f12b..24806a6 100644 --- a/examples/PyTABS_LinkSpringProp/main.py +++ b/examples/PyTABS_LinkSpringProp/main.py @@ -1,42 +1,130 @@ import pytabs +import xlwings as xw +import excel_index as wb_index + +UNIDIRECTIONAL_SUFFIX = 'U' +BIDIRECTIONAL_SUFFIX = 'B' +CORNER_SUFFIX = 'C' + +TRIB_LENGTH = 1.2 +TRIB_AREA = 1.2 + + + def main(): + input_data = extract_excel_inputs() + # substantiate pyTABS EtabsModel etabs_model = pytabs.EtabsModel() - + # set model units # etabs_model.set_present_units(etabs_model.eUnits.kN_m_C) - # etabs_model.property.link.set_multi_linear_elastic(name='TestLinkProp', - # dof=[True, False, False, False, False, False], - # is_fixed=[False, True, False, False, False, False], - # nonlinear=[True, False, False, False, False, False], - # ke=[0., 0., 0., 0., 0., 0.], - # ce=[0., 0., 0., 0., 0., 0.], - # dj2=100., dj3=200.) - - # etabs_model.property.link.set_spring_data(name='TestLinkProp', length=1.2, area=1.5) - - # etabs_model.property.link.set_multi_linear_points(name='TestLinkProp', - # dof=etabs_model.property.link.eLinkDof.U1, - # action_values=[-1000., -500., 0., 100., 600., 1000], - # displacement_values=[-0.5, -0.4, 0., 0.2, 0.6, 0.8], - # hysteresis_type=etabs_model.property.link.eLinkHysteresisType.KINEMATIC) - + for prop_data in input_data: + prop_base_name = prop_data['name'] + + prop_set = [{'name': f'{prop_base_name}_{UNIDIRECTIONAL_SUFFIX}', + 'dof': [False, False, True, False, False, False], + 'ml_axes': [etabs_model.property.link.eLinkDof.U3], + 'force_values': [0.] + prop_data['force_values'], + 'delta_values': [-.0001] + prop_data['delta_values'], + }, + {'name': f'{prop_base_name}_{BIDIRECTIONAL_SUFFIX}', + 'dof': [False, False, True, False, False, False], + 'ml_axes': [etabs_model.property.link.eLinkDof.U3], + 'force_values': uni_to_bidirectional(prop_data['force_values']), + 'delta_values': uni_to_bidirectional(prop_data['delta_values']), + }, + {'name': f'{prop_base_name}_{UNIDIRECTIONAL_SUFFIX}_{CORNER_SUFFIX}', + 'dof': [False, True, True, False, False, False], + 'ml_axes': [etabs_model.property.link.eLinkDof.U2, + etabs_model.property.link.eLinkDof.U3], + 'force_values': [0.] + prop_data['force_values'], + 'delta_values': [-.0001] + prop_data['delta_values'], + }, + {'name': f'{prop_base_name}_{BIDIRECTIONAL_SUFFIX}_{CORNER_SUFFIX}', + 'dof': [False, True, True, False, False, False], + 'ml_axes': [etabs_model.property.link.eLinkDof.U2, + etabs_model.property.link.eLinkDof.U3], + 'force_values': uni_to_bidirectional(prop_data['force_values']), + 'delta_values': uni_to_bidirectional(prop_data['delta_values']), + }, + ] + + # create each property in the prop set + for prop in prop_set: + # create multi linear elastic link property + etabs_model.property.link.set_multi_linear_elastic(name=prop['name'], + dof=prop['dof'], + is_fixed=[False, False, False, False, False, False], + nonlinear=prop['dof'], + ke=[0., 0., 0., 0., 0., 0.], + ce=[0., 0., 0., 0., 0., 0.], + dj2=0., dj3=0.) + + # provide spring data to link property + etabs_model.property.link.set_spring_data(name=prop['name'], length=TRIB_LENGTH, area=TRIB_AREA) + + # populate multi linear points data to link property for each axis + for axis in prop['ml_axes']: + etabs_model.property.link.set_multi_linear_points(name=prop['name'], + dof=axis, + action_values=prop['force_values'], + displacement_values=prop['delta_values']) - # etabs_model.property.line_spring.set_line_spring_prop(name='TestLineSpringProp', - # stiffness=[1., 2., 3., 4.], - # nonlinear_option_2=etabs_model.property.line_spring.eSpringNonlinearOption.LINEAR, - # nonlinear_option_3=etabs_model.property.line_spring.eSpringNonlinearOption.COMPRESSION_ONLY) - - # print(etabs_model.property.line_spring.get_line_spring_prop('TestLineSpringProp')) + # create line spring property for link assignment + etabs_model.property.line_spring.set_line_spring_prop(name=prop['name'], + stiffness=[0., 0., 0., 0.], + nonlinear_option_2=etabs_model.property.line_spring.eSpringNonlinearOption.LINEAR, + nonlinear_option_3=etabs_model.property.line_spring.eSpringNonlinearOption.LINEAR) + + # get database table for link to line spring association + db_line_spring_table = etabs_model.database_tables.get_table_details('Spring Property Definitions - Line Springs') + # get table data array for edit + table_array = etabs_model.database_tables.get_table_data_array(table=db_line_spring_table, edit_mode=True) - table = etabs_model.database_tables.get_table_details('Spring Property Definitions - Line Springs') + # edit table data array for all PW properties + new_table_data = [] + for record in table_array.table_data: + new_record = list(record) + if record[0].startswith('PW'): + new_record[1] = 'Link' + new_record[8] = record[0] + new_table_data.append(new_record) + + # write data + etabs_model.database_tables.set_table_data_array_edit(table=db_line_spring_table, + field_keys=table_array.fields_included, + table_data=new_table_data) - table_data_array = etabs_model.database_tables.get_table_data_array(table, edit_mode=True) + # apply data write + db_edit_log = etabs_model.database_tables.apply_table_edits(True) + print(db_edit_log['import_log']) + etabs_model.database_tables.discard_table_edits() print('') +def uni_to_bidirectional(values): + return [-v for v in values][:0:-1] + values + +def extract_excel_inputs(): + wb = xw.Book(wb_index.WB_FILE) + sheet = wb.sheets(wb_index.WB_SHEET) + input_data = [] + for table_name, start_cell in wb_index.TABLE_RANGES.items(): + raw_data = sheet.range(start_cell).options(expand = 'table').value + delta_values = [] + force_values = [] + for delta, force in raw_data: + delta_values.append(round(delta, 6)) + force_values.append(round(force, 6)) + input_data.append({'name': table_name, + 'delta_values': delta_values, + 'force_values': force_values}) + return input_data + + if __name__ == '__main__': main() \ No newline at end of file diff --git a/src/pytabs/database_tables.py b/src/pytabs/database_tables.py index a01dd9e..df1e5a0 100644 --- a/src/pytabs/database_tables.py +++ b/src/pytabs/database_tables.py @@ -191,12 +191,12 @@ def get_table_data_array(self, table: DbTable, edit_mode: bool = False, def set_table_data_array_edit(self, table: DbTable, field_keys: list[str], table_data: list[list]) -> None: table_version = int() - num_records = len(table(table_data)) + num_records = len(table_data) records = [item for record in table_data for item in record] - [ret, _table_version, + [ret, _table_version, _field_keys_out, _table_data] = self.database_tables.SetTableForEditingArray(table.table_key, table_version, field_keys, num_records, records) - handle(ret) + handle(ret) def apply_table_edits(self, log_import: bool = False) -> DbEditLog: num_fatal_errors = int() @@ -204,9 +204,10 @@ def apply_table_edits(self, log_import: bool = False) -> DbEditLog: num_warn_msgs = int() num_info_msgs = int() import_log = str() - handle(self.database_tables.ApplyEditedTables(log_import, num_fatal_errors, num_error_msgs, - num_warn_msgs, num_info_msgs, - import_log)) + [ret, num_fatal_errors, num_error_msgs, + num_warn_msgs, num_info_msgs, import_log] = self.database_tables.ApplyEditedTables(log_import, num_fatal_errors, num_error_msgs, + num_warn_msgs, num_info_msgs, import_log) + return {'num_fatal_errors': num_fatal_errors, 'num_error_msgs': num_error_msgs, 'num_warn_msgs': num_warn_msgs, diff --git a/src/pytabs/properties/prop_link.py b/src/pytabs/properties/prop_link.py index 4d9ea51..54b71ce 100644 --- a/src/pytabs/properties/prop_link.py +++ b/src/pytabs/properties/prop_link.py @@ -63,14 +63,15 @@ def set_multi_linear_plastic(self, name: str, dof: list[bool], is_fixed: list[bo handle(ret) def set_multi_linear_points(self, name, dof: eLinkDof, action_values: list[float], - displacement_values: list[float], hysteresis_type: eLinkHysteresisType, + displacement_values: list[float], + hysteresis_type: eLinkHysteresisType = eLinkHysteresisType.KINEMATIC, alpha_1: int = 0, alpha_2: int = 0, beta_1: int = 0, beta_2: int = 0, eta: int = 0) -> None: number_points = min(len(action_values), len(displacement_values)) - [ret, _action_values, _displacement_values] = self.prop_link.SetMultiLinearPoints(name, dof, number_points, + [ret, _action_values, _displacement_values] = self.prop_link.SetMultiLinearPoints(name, dof.value, number_points, action_values, displacement_values, - hysteresis_type, alpha_1, alpha_2, - beta_1, beta_2, eta) + hysteresis_type.value, alpha_1, + alpha_2, beta_1, beta_2, eta) handle(ret) def set_spring_data(self, name, length: float, area: float) -> None: