midas-civil 0.0.8__py3-none-any.whl → 0.1.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of midas-civil might be problematic. Click here for more details.

midas_civil/_model.py CHANGED
@@ -341,6 +341,44 @@ class Model:
341
341
 
342
342
 
343
343
  MidasAPI("PUT","/db/PJCF",js)
344
+
345
+ @staticmethod
346
+ def exportJSON(location=""):
347
+ """Export the model data as JSON file
348
+ Model.exportJSON('D:\\model.json')"""
349
+ if location.endswith('.json'):
350
+ MidasAPI("POST","/doc/EXPORT",{"Argument":str(location)})
351
+ else:
352
+ print('⚠️ Location data in exportJSON is missing file extension')
353
+
354
+ @staticmethod
355
+ def exportMCT(location=""):
356
+ """Export the model data as MCT file
357
+ Model.exportMCT('D:\\model.mct')"""
358
+ if location.endswith('.mct'):
359
+ MidasAPI("POST","/doc/EXPORTMXT",{"Argument":str(location)})
360
+ else:
361
+ print('⚠️ Location data in exportMCT is missing file extension')
362
+
363
+
364
+ @staticmethod
365
+ def importJSON(location=""):
366
+ """Import JSON data file in MIDAS CIVIL NX
367
+ Model.importJSON('D:\\model.json')"""
368
+ if location.endswith('.json'):
369
+ MidasAPI("POST","/doc/IMPORT",{"Argument":str(location)})
370
+ else:
371
+ print('⚠️ Location data in importJSON is missing file extension')
372
+
373
+ @staticmethod
374
+ def importMCT(location=""):
375
+ """Import MCT data file in MIDAS CIVIL NX
376
+ Model.importMCT('D:\\model.mct')"""
377
+ if location.endswith('.mct'):
378
+ MidasAPI("POST","/doc/IMPORTMXT",{"Argument":str(location)})
379
+ else:
380
+ print('⚠️ Location data in importMCT is missing file extension')
381
+
344
382
 
345
383
 
346
384
 
@@ -0,0 +1,488 @@
1
+ from ._mapi import *
2
+ from ._model import *
3
+
4
+
5
+ #28 Class to generate load combinations
6
+ class Load_Combination:
7
+ data = []
8
+ valid = ["General", "Steel", "Concrete", "SRC", "Composite Steel Girder", "Seismic", "All"]
9
+ com_map = {
10
+ "General": "/db/LCOM-GEN",
11
+ "Steel": "/db/LCOM-STEEL",
12
+ "Concrete": "/db/LCOM-CONC",
13
+ "SRC": "/db/LCOM-SRC",
14
+ "Composite Steel Girder": "/db/LCOM-STLCOMP",
15
+ "Seismic": "/db/LCOM-SEISMIC"
16
+ }
17
+ def __init__(self, name, case, classification = "General", active = "ACTIVE", typ = "Add", id = 0, desc = ""):
18
+ """Name, List of tuple of load cases & factors, classification, active, type. \n
19
+ Sample: Load_Combination('LCB1', [('Dead Load(CS)',1.5), ('Temperature(ST)',0.9)], 'General', 'Active', 'Add')"""
20
+ if not isinstance(case, list):
21
+ print("case should be a list that contains tuple of load cases & factors.\nEg: [('Load1(ST)', 1.5), ('Load2(ST)',0.9)]")
22
+ return
23
+ for i in case:
24
+ if not isinstance(i, tuple):
25
+ print(f"{i} is not a tuple. case should be a list that contains tuple of load cases & factors.\nEg: [('Load1(ST)', 1.5), ('Load2(ST)',0.9)]")
26
+ return
27
+ if not isinstance(i[0], str):
28
+ print(f"{i[0]} is not a string. case should be a list that contains tuple of load cases & factors.\nEg: [('Load1(ST)', 1.5), ('Load2(ST)',0.9)]")
29
+ return
30
+ if i[0][-1] != ")":
31
+ print(f"Load case type is not mentioned for {i[0]}. case should be a list that contains tuple of load cases & factors.\nEg: [('Load1(ST)', 1.5), ('Load2(ST)',0.9)]")
32
+ return
33
+ if not isinstance(i[1],(int, float)):
34
+ print(f"{i[1]} is not a number. case should be a list that contains tuple of load cases & factors.\nEg: [('Load1(ST)', 1.5), ('Load2(ST)',0.9)]")
35
+ return
36
+
37
+ if classification not in Load_Combination.valid[:-1]:
38
+ print(f'"{classification}" is not a valid input. It is changed to "General".')
39
+ classification = "General"
40
+
41
+ if classification in ["General", "Seismic"]:
42
+ if active not in ["ACTIVE", "INACTIVE"]: active = "ACTIVE"
43
+ if classification in ["Steel", "Concrete", "SRC", "Composite Steel Girder"]:
44
+ if active not in ["STRENGTH", "SERVICE", "INACTIVE"]: active = "STRENGTH"
45
+
46
+ typ_map = {"Add": 0, "Envelope": 1, "ABS": 2, "SRSS": 3, 0:0, 1:1, 2:2, 3:3}
47
+ if typ not in list(typ_map.keys()): typ = "Add"
48
+ if classification not in ["General", "Seismic"] and typ_map.get(typ) == 2: typ = "Add"
49
+
50
+ if id == 0 and len(Load_Combination.data) == 0:
51
+ id = 1
52
+ elif id == 0 and len(Load_Combination.data) != 0:
53
+ id = max([i.ID for i in Load_Combination.data]) + 1
54
+ elif id != 0 and id in [i.ID for i in Load_Combination.data]:
55
+ if classification in [i.CLS for i in Load_Combination.data if i.ID == id]:
56
+ print(f"ID {id} is already defined. Existing combination would be replaced.")
57
+
58
+
59
+ combo = []
60
+ valid_anl = ["ST", "CS", "MV", "SM", "RS", "TH", "CB", "CBC", "CBS", "CBR", "CBSC", "CBSM"] #Need to figure out for all combination types
61
+ for i in case:
62
+ a = i[0].rsplit('(', 1)[1].rstrip(')')
63
+ if a in valid_anl:
64
+ combo.append({
65
+ "ANAL": a,
66
+ "LCNAME":i[0].rsplit('(', 1)[0],
67
+ "FACTOR": i[1]
68
+ })
69
+ self.NAME = name
70
+ self.CASE = combo
71
+ self.CLS = classification
72
+ self.ACT = active
73
+ self.TYPE = typ_map.get(typ)
74
+ self.ID = id
75
+ self.DESC = desc
76
+ Load_Combination.data.append(self)
77
+
78
+ @classmethod
79
+ def json(cls, classification = "All"):
80
+ if len(Load_Combination.data) == 0:
81
+ print("No Load Combinations defined! Define the load combination using the 'Load_Combination' class before making json file.")
82
+ return
83
+ if classification not in Load_Combination.valid:
84
+ print(f'"{classification}" is not a valid input. It is changed to "General".')
85
+ classification = "General"
86
+ json = {k:{'Assign':{}} for k in Load_Combination.valid[:-1]}
87
+ for i in Load_Combination.data:
88
+ if i.CLS == classification or classification == "All":
89
+ json[i.CLS]['Assign'][i.ID] = {
90
+ "NAME": i.NAME,
91
+ "ACTIVE": i.ACT,
92
+ "iTYPE": i.TYPE,
93
+ "DESC": i.DESC,
94
+ "vCOMB":i.CASE
95
+ }
96
+ json = {k:v for k,v in json.items() if v != {'Assign':{}}}
97
+ return json
98
+
99
+ @classmethod
100
+ def get(cls, classification = "All"):
101
+ if classification not in Load_Combination.valid:
102
+ print(f'"{classification}" is not a valid input. It is changed to "General".')
103
+ classification = "General"
104
+ combos = {k:{} for k in Load_Combination.valid[:-1]}
105
+ for i in Load_Combination.valid[:-1]:
106
+ if classification == i or classification == "All":
107
+ combos[i] = MidasAPI("GET",Load_Combination.com_map.get(i))
108
+ json = {k:v for k,v in combos.items() if v != {'message':''}}
109
+ return json
110
+
111
+ @classmethod
112
+ def create(cls, classification = "All"):
113
+ if len(Load_Combination.data) == 0:
114
+ print("No Load Combinations defined! Define the load combination using the 'Load_Combination' class before creating these in the model.")
115
+ return
116
+ if classification not in Load_Combination.valid:
117
+ print(f'"{classification}" is not a valid input. It is changed to "General".')
118
+ classification = "General"
119
+ json = Load_Combination.json(classification)
120
+ for i in Load_Combination.valid[:-1]:
121
+ if classification == i or classification == "All":
122
+ if i in list(json.keys()):
123
+ a = list(json[i]['Assign'].keys())
124
+ b=""
125
+ for j in range(len(a)):
126
+ b += str(a[j]) + ","
127
+ if b != "": b = "/" + b[:-1]
128
+ MidasAPI("DELETE", Load_Combination.com_map.get(i) + b) #Delete existing combination if any
129
+ MidasAPI("PUT", Load_Combination.com_map.get(i), json[i]) #Create new combination
130
+
131
+ @classmethod
132
+ def sync(cls, classification = "All"):
133
+ json = Load_Combination.get(classification)
134
+ if json != {}:
135
+ keys = list(json.keys())
136
+ for i in keys:
137
+ for k,v in json[i][Load_Combination.com_map.get(i)[4:]].items():
138
+ c = []
139
+ for j in range(len(v['vCOMB'])):
140
+ c.append((v['vCOMB'][j]['LCNAME'] + "("+ v['vCOMB'][j]['ANAL'] + ")", v['vCOMB'][j]['FACTOR']))
141
+ Load_Combination(v['NAME'], c, i, v['ACTIVE'], v['iTYPE'], int(k), v['DESC'])
142
+
143
+ @classmethod
144
+ def delete(cls, classification = "All", ids = []):
145
+ json = Load_Combination.call_json(classification)
146
+ a = ""
147
+ for i in range(len(ids)):
148
+ a += str(ids[i]) + ","
149
+ a = "/" + a[:-1]
150
+ if json == {}:
151
+ print("No load combinations are defined to delete. Def")
152
+ for i in list(json.keys()):
153
+ MidasAPI("DELETE",Load_Combination.com_map.get(i) + a)
154
+ #---------------------------------------------------------------------------------------------------------------
155
+
156
+
157
+ #29 Beam result table (IMCOMPLETE)
158
+ class Beam_Result_Table:
159
+ force_input_data = []
160
+ stress_input_data = []
161
+
162
+ def __init__(self, table_of = "FORCE", elem = [], case = [], cs = False, stage = [], step = [], location = "i"):
163
+ if table_of in ["FORCE", "STRESS"]:
164
+ self.TAB = table_of
165
+ else:
166
+ print(f"Please enter 'FORCE' or 'STRESS' as string in capital. {table_of} is not a vaild input.")
167
+ return
168
+ Element.update_class()
169
+ if elem != []:
170
+ a = [i.ID for i in Element.elements if i.ID in elem and i.TYPE == "BEAM"]
171
+ b = [i for i in elem if i not in a]
172
+ elem = a
173
+ if b != []: print(f"The element/s {b} are not defined in the model. These would be skipped.")
174
+ if elem == []:
175
+ print(f"Since no valid elements were provided, table is generated for all defined beam elements.")
176
+ elem = [i.ID for i in Element.elements if i.TYPE == "BEAM"]
177
+ self.ELEM = elem
178
+ Load_Case.update_class()
179
+ Load_Combination.update_class()
180
+ ca = Load_Case.make_json()
181
+ co = Load_Combination.make_json()
182
+ if case == [] and cs == False:
183
+ print(f"Since no load cases/combinations are provided for output, results are tabulated for all static load cases.")
184
+ for i in ca["Assign"]:
185
+ case.append(ca["Assign"][i]["NAME"]+"(ST)")
186
+ if case != []:
187
+ for i in range(len(case)):
188
+ if case[i][-1] != ")":
189
+ case[i]+="(ST)"
190
+ self.CASE = case
191
+ if location not in ["i", "1/4", "2/4", "3/4", "j"]:
192
+ print(f'{location} not in ["i", "1/4", "2/4", "3/4", "j"]. Output is tablulated for "i" location.')
193
+ location = "i"
194
+ self.LOC = location
195
+ if table_of == "FORCE":
196
+ Beam_Result_Table.force_input_data.append(self)
197
+ elif table_of == "STRESS":
198
+ Beam_Result_Table.stress_input_data.append(self)
199
+
200
+ @classmethod
201
+ def make_json(cls, json_of = "FORCE"):
202
+ Model.analyse()
203
+ if json_of == "FORCE":1
204
+
205
+ #---------------------------------------------------------------------------------------------------------------
206
+
207
+ #Function to get stress table JSON output, just the DATA list.
208
+ def stress_tab(elem, case):
209
+ """Element list. Sample stress_tab([3,5], "Self-Weight(ST)"). Returns Cb1 to Cb4 for list of entered elements"""
210
+ if elem == None: elem = list(MidasAPI("GET","/db/ELEM")['ELEM'].keys())
211
+ if case == None:
212
+ a = MidasAPI("GET","/db/STLD")['STLD']
213
+ for i in range(max(list(a.keys()))):
214
+ if a[i]['TYPE'] not in ['CS']: case.append(str(a[i]["NAME"])+"(ST)")
215
+ stress = {"Argument": {
216
+ "TABLE_NAME": "BeamStress",
217
+ "TABLE_TYPE": "BEAMSTRESS",
218
+ "UNIT": {
219
+ "FORCE": "N",
220
+ "DIST": "mm"
221
+ },
222
+ "STYLES": {
223
+ "FORMAT": "Fixed",
224
+ "PLACE": 12
225
+ },
226
+ "COMPONENTS": [
227
+ "Elem",
228
+ "Load",
229
+ "Part",
230
+ "Cb1(-y+z)",
231
+ "Cb2(+y+z)",
232
+ "Cb3(+y-z)",
233
+ "Cb4(-y-z)"
234
+ ],
235
+ "NODE_ELEMS": {
236
+ "KEYS": [
237
+ int(item) for item in elem
238
+ ]
239
+ },
240
+ "LOAD_CASE_NAMES": case,
241
+ "PARTS": [
242
+ "PartI",
243
+ "Part1/4",
244
+ "Part2/4",
245
+ "Part3/4",
246
+ "PartJ"
247
+ ]
248
+ }}
249
+ raw = (MidasAPI("POST","/post/TABLE",stress)['BeamStress']['DATA'])
250
+ return(raw)
251
+ #---------------------------------------------------------------------------------------------------------------
252
+ #Function to call max beam stress results
253
+ def max_beam_stress(elem, case):
254
+ """Element list. Sample: max_beam_stress([10,18,5], "Self-Weight(ST)") to get maximum stress among these 3 elements.
255
+ Enter max_beam_stress([],[]) to get maximum stress in the entire structure for the first static load case."""
256
+ db = 0
257
+ if elem == None: elem = list(MidasAPI("GET","/db/ELEM")['ELEM'].keys())
258
+ if case == None:
259
+ for i in range(max(list(MidasAPI("GET","/db/STLD")['STLD'].keys()))):
260
+ case.append(str(MidasAPI("GET","/db/STLD")['STLD'][i]["NAME"])+"(ST)")
261
+ if type(elem == list):
262
+ for i in range(len(elem)):
263
+ if type(elem[i])!= int: db+=1
264
+ if db == 0:
265
+ raw = stress_tab(elem, case)
266
+ current_stress = float(0)
267
+ for i in range(len(raw)):
268
+ max_stress = max(current_stress, float(raw[i][4]),float(raw[i][5]),float(raw[i][6]),float(raw[i][7]))
269
+ current_stress = max_stress
270
+ return(current_stress)
271
+ if db!= 0: print("Enter list of element ID (list of integers only!)")
272
+ if type(elem)!= list: print("Enter list of element ID (list of integers only!) or leave it empty for max stress in structure.")
273
+ #---------------------------------------------------------------------------------------------------------------
274
+ #Function to call min beam stress results
275
+ def min_beam_stress(elem, case):
276
+ """Element list, Load case name or combination. Sample: min_beam_stress([10,18,5], ["Self-Weight(ST)"]) to get minimum stress among these 3 elements.
277
+ Enter min_beam_stress([],[]) to get minimum stress in the entire structure for the first static load case."""
278
+ db = 0
279
+ if elem == None: elem = list(MidasAPI("GET","/db/ELEM")['ELEM'].keys())
280
+ if case == None:
281
+ for i in range(max(list(MidasAPI("GET","/db/STLD")['STLD'].keys()))):
282
+ case.append(str(MidasAPI("GET","/db/STLD")['STLD'][i]["NAME"])+"(ST)")
283
+ if type(elem == list):
284
+ for i in range(len(elem)):
285
+ if type(elem[i])!= int: db+=1
286
+ if db == 0:
287
+ raw = stress_tab(elem, case)
288
+ current_stress = float(0)
289
+ for i in range(len(raw)):
290
+ min_stress = min(current_stress, float(raw[i][4]),float(raw[i][5]),float(raw[i][6]),float(raw[i][7]))
291
+ current_stress = min_stress
292
+ return(current_stress)
293
+ if db!= 0: print("Enter list of element ID (list of integers only!)")
294
+ if type(elem)!= list: print("Enter list of element ID (list of integers only!) or leave it empty for min stress in structure.")
295
+ #---------------------------------------------------------------------------------------------------------------
296
+ #Function to get force table JSON output, just the DATA list.
297
+ def force_tab(elem, case):
298
+ """Element list. Sample force_tab([23,5]). Returns element forces for list of entered elements"""
299
+ if elem == None: elem = list(MidasAPI("GET","/db/ELEM")['ELEM'].keys())
300
+ if case == None:
301
+ for i in range(max(list(MidasAPI("GET","/db/STLD")['STLD'].keys()))):
302
+ case.append(str(MidasAPI("GET","/db/STLD")['STLD'][i]["NAME"])+"(ST)")
303
+ force = {
304
+ "Argument": {
305
+ "TABLE_NAME": "BeamForce",
306
+ "TABLE_TYPE": "BEAMFORCE",
307
+ "EXPORT_PATH": "C:\\MIDAS\\Result\\Output.JSON",
308
+ "UNIT": {
309
+ "FORCE": "kN",
310
+ "DIST": "m"
311
+ },
312
+ "STYLES": {
313
+ "FORMAT": "Fixed",
314
+ "PLACE": 12
315
+ },
316
+ "COMPONENTS": [
317
+ "Elem",
318
+ "Load",
319
+ "Part",
320
+ "Axial",
321
+ "Shear-y",
322
+ "Shear-z",
323
+ "Torsion",
324
+ "Moment-y",
325
+ "Moment-z",
326
+ "Bi-Moment",
327
+ "T-Moment",
328
+ "W-Moment"
329
+ ],
330
+ "NODE_ELEMS": {
331
+ "KEYS": [
332
+ int(item) for item in elem
333
+ ]
334
+ },
335
+ "LOAD_CASE_NAMES": case,
336
+ "PARTS": [
337
+ "PartI",
338
+ "Part1/4",
339
+ "Part2/4",
340
+ "Part3/4",
341
+ "PartJ"
342
+ ]
343
+ }
344
+ }
345
+ raw = (MidasAPI("POST","/post/TABLE",force)['BeamForce']['DATA'])
346
+ return(raw)
347
+ #---------------------------------------------------------------------------------------------------------------
348
+ #Function to call beam force results
349
+ def beam_force(req = 3, elem = [], case = [], loc = 1):
350
+ """Request, Element list, Case list, Location. Sample: beam_force(elem=[10,18,5], case ="Self-Weight(ST)") to get forces at I end in these 3 elements.
351
+ req = (1 --> Maximum force)(2 --> Minimum force)(3 --> Forces for all elements at requested location).
352
+ loc = (1 --> i-end)(2 --> Part1/2)(3 --> Part2/4)(4 --> Part3/4)(5 --> j end)
353
+ Enter beam_force() to get forces at I end in all elements for all load cases."""
354
+ db = 0
355
+ dir = {"Axial":float(0),
356
+ "Shear-y":float(0),
357
+ "Shear-z":float(0),
358
+ "Torsion":float(0),
359
+ "Moment-y":float(0),
360
+ "Moment-z":float(0),
361
+ "Bi-Moment":float(0),
362
+ "T-Moment":float(0),
363
+ "W-Moment":float(0)}
364
+ dir_2 = {
365
+ "Axial":[],
366
+ "Shear-y":[],
367
+ "Shear-z":[],
368
+ "Torsion":[],
369
+ "Moment-y":[],
370
+ "Moment-z":[],
371
+ "Bi-Moment":[],
372
+ "T-Moment":[],
373
+ "W-Moment":[]}
374
+ if elem == []: elem = [int(item) for item in list(MidasAPI("GET","/db/ELEM")['ELEM'].keys())]
375
+ if case == []:
376
+ a = MidasAPI("GET","/db/STLD")['STLD']
377
+ for i in range(int(max(list(a.keys())))):
378
+ if a[str(i+1)]['TYPE'] not in ['CS']: case.append(str(a[str(i+1)]["NAME"])+"(ST)")
379
+ if type(elem == list):
380
+ for i in range(len(elem)):
381
+ if type(elem[i])!= int: db+=1
382
+ if (db == 0):
383
+ raw = force_tab(elem, case)
384
+ for i in range(len(raw)):
385
+ if req == 1:
386
+ dir["Axial"] = max(dir["Axial"], float(raw[i][4]))
387
+ dir["Shear-y"] = max(dir["Shear-y"],float(raw[i][5]))
388
+ dir["Shear-z"] = max(dir["Shear-z"],float(raw[i][6]))
389
+ dir["Torsion"] = max(dir["Torsion"],float(raw[i][7]))
390
+ dir["Moment-y"] = max(dir["Moment-y"],float(raw[i][8]))
391
+ dir["Moment-z"] = max(dir["Moment-z"],float(raw[i][9]))
392
+ if len(raw[0])>10:
393
+ dir["Bi-Moment"] = max(dir["Bi-Moment"],float(raw[i][10]))
394
+ dir["T-Moment"] = max(dir["T-Moment"],float(raw[i][11]))
395
+ dir["W-Moment"] = max(dir["W-Moment"],float(raw[i][12]))
396
+ if req == 2:
397
+ dir["Axial"] = min(dir["Axial"], float(raw[i][4]))
398
+ dir["Shear-y"] = min(dir["Shear-y"],float(raw[i][5]))
399
+ dir["Shear-z"] = min(dir["Shear-z"],float(raw[i][6]))
400
+ dir["Torsion"] = min(dir["Torsion"],float(raw[i][7]))
401
+ dir["Moment-y"] = min(dir["Moment-y"],float(raw[i][8]))
402
+ dir["Moment-z"] = min(dir["Moment-z"],float(raw[i][9]))
403
+ if len(raw[0])>10:
404
+ dir["Bi-Moment"] = min(dir["Bi-Moment"],float(raw[i][10]))
405
+ dir["T-Moment"] = min(dir["T-Moment"],float(raw[i][11]))
406
+ dir["W-Moment"] = min(dir["W-Moment"],float(raw[i][12]))
407
+ if (loc == int(raw[i][0]) and req == 3):
408
+ dir_2["Axial"].append(float(raw[i][4]))
409
+ dir_2["Shear-y"].append(float(raw[i][5]))
410
+ dir_2["Shear-z"].append(float(raw[i][6]))
411
+ dir_2["Torsion"].append(float(raw[i][7]))
412
+ dir_2["Moment-y"].append(float(raw[i][8]))
413
+ dir_2["Moment-z"].append(float(raw[i][9]))
414
+ if len(raw[0])>10:
415
+ dir_2["Bi-Moment"].append(float(raw[i][10]))
416
+ dir_2["T-Moment"].append(float(raw[i][11]))
417
+ dir_2["W-Moment"].append(float(raw[i][12]))
418
+ loc += 5
419
+ if req != 3: return(dir)
420
+ if req == 3: return(dir_2)
421
+ if db!= 0: print("Enter list of element ID (list of integers only!)")
422
+ if type(elem)!= list: print("Enter list of element ID (list of integers only!) or leave it empty for max force in structure.")
423
+ #---------------------------------------------------------------------------------------------------------------
424
+ #Function to get summary of maximum & minimum forces for each unique section & element
425
+ def force_summary(mat = 1, sec = 1, elem = [], case = []):
426
+ """Request type (1 for overall summary, 2 for required material & section, 3 for list of elements). Sample:
427
+ force_summary() for overall max & min forces for each type of unique material & section used in the software.
428
+ force_summary(2, mat = [1,4], sec = [1,2]) for max & min force for (material 1 + section 1), (material 1 + section 2), (material 4 + section 1) and (material 4 + section 2).
429
+ force_summary(3, elem = [1,2,3,4]) for max & min force summary for unique material & section property combination among elements 1, 2, 3 & 4."""
430
+ analyze()
431
+ if elem == []:
432
+ li = get_select("USM", mat, sec)
433
+ else:
434
+ li = elem
435
+ res = {}
436
+ for i in li:
437
+ a = beam_force(1,i,case)
438
+ b = beam_force(2,i,case)
439
+ res[i] = {"max":a,"min":b}
440
+ return(res)
441
+ #---------------------------------------------------------------------------------------------------------------
442
+ #Function to get summary of maximum & minimum stresses for each unique section & element
443
+ def stress_summary(req = 1, mat = [], sec = [], elem = [], case = []):
444
+ """Request type (1 for overall summary, 2 for required material & section, 3 for list of elements). Sample:
445
+ stress_summary() for overall max & min stress for each type of unique material & section used in the software.
446
+ stress_summary(2, mat = [1,4], sec = [1,2]) for max & min stress for (material 1 + section 1), (material 1 + section 2), (material 4 + section 1) and (material 4 + section 2).
447
+ stress_summary(3, elem = [1,2,3,4]) for max & min stress summary for unique material & section property combination among elements 1, 2, 3 & 4."""
448
+ analyze()
449
+ if elem == []:
450
+ li = get_select("USM", mat, sec)
451
+ else:
452
+ li = elem
453
+ res = {}
454
+ for i in li:
455
+ a = stress_tab(elem, case)
456
+ max_str= {"top": 0,"bot": 0} #Empty dictionary to store max top stress results based on materil ID and section ID
457
+ min_str = {"top": 0,"bot": 0} #Empty dictionary to store min top stress results based on materil ID and section ID
458
+ for i in range(len(a)):
459
+ max_str["top"] = max(max_str["top"],float(a[i][4]),float(a[i][5]))
460
+ max_str["bot"] = max(max_str["bot"],float(a[i][6]),float(a[i][7]))
461
+ min_str["top"] = min(min_str["top"],float(a[i][4]),float(a[i][5]))
462
+ min_str["bot"] = min(min_str["bot"],float(a[i][6]),float(a[i][7]))
463
+ res[i] = ({"max":max_str,"min":min_str})
464
+ return(res)
465
+ #---------------------------------------------------------------------------------------------------------------
466
+ #Function to get section properties of the specific ID
467
+ def sect_prop(id=[]):
468
+ """List of section ID. Sample: Enter Sect_prop[3,4] for properties of section ID 4 & 5.
469
+ Enter sect_prop() for properties of all defined sections."""
470
+ dir = {}
471
+ units("N",length="MM")
472
+ sect = MidasAPI("GET","/ope/SECTPROP")
473
+ if id == []: a = list(sect['SECTPROP'].keys())
474
+ if (id != [] and type(id)!= int): a = [str(e) for e in id]
475
+ if type(id) == int: a = [str(id)]
476
+ for i in a:
477
+ if i in sect['SECTPROP'].keys():
478
+ dir.update({int(i):{"Area":None , "Iy":None, "Iz":None, "Yl":None, "Yr":None, "Zt":None, "Zb":None,
479
+ "Y1":None, "Z1":None, "Y2":None, "Z2":None, "Y3":None, "Z3":None, "Y4":None, "Z4":None}})
480
+ data = [float(sect['SECTPROP'][i]['DATA'][0][1])]
481
+ for j in list(range(4,10))+list(range(16,24)):
482
+ data.append(float(sect['SECTPROP'][i]['DATA'][j][1]))
483
+ for idx, key in enumerate(dir[int(i)]):
484
+ dir[int(i)][key] = data[idx]
485
+ elif i not in sect['SECTPROP'].keys(): print ("Section id", i, "is not defined in connected model.")
486
+ units()
487
+ return(dir)
488
+ #---------------------------------------------------------------------------------------------------------------