midas-civil 0.0.1__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 ADDED
@@ -0,0 +1,352 @@
1
+ from ._mapi import *
2
+
3
+ from ._node import *
4
+ from ._element import *
5
+ from ._group import *
6
+ from ._load import *
7
+ from ._boundary import *
8
+
9
+ from ._section import *
10
+ from ._material import *
11
+ from ._thickness import *
12
+
13
+ class Model:
14
+
15
+ #4 Function to check analysis status & perform analysis if not analyzed
16
+ @staticmethod
17
+ def analyse():
18
+ """Checkes whether a model is analyzed or not and then performs analysis if required."""
19
+ r = (MidasAPI("POST","/post/TABLE",{"Argument": {"TABLE_NAME": "Reaction(Global)","TABLE_TYPE": "REACTIONG",}}))
20
+ if 'error' in r.keys():
21
+ MidasAPI("POST","/doc/SAVE",{"Argument":{}})
22
+ MidasAPI("POST","/doc/ANAL",{"Assign":{}})
23
+
24
+ #9 Function to remove duplicate nodes and elements from Node & Element classes\
25
+ @staticmethod
26
+ def merge_nodes(tolerance = 0):
27
+ """This functions removes duplicate nodes defined in the Node Class and modifies Element class accordingly. \nSample: remove_duplicate()"""
28
+ a=[]
29
+ b=[]
30
+ node_json = Node.json()
31
+ elem_json = Element.json()
32
+ node_di = node_json["Assign"]
33
+ elem_di = elem_json["Assign"]
34
+ for i in list(node_di.keys()):
35
+ for j in list(node_di.keys()):
36
+ if list(node_di.keys()).index(j) > list(node_di.keys()).index(i):
37
+ if (node_di[i]["X"] >= node_di[j]["X"] - tolerance and node_di[i]["X"] <= node_di[j]["X"] + tolerance):
38
+ if (node_di[i]["Y"] >= node_di[j]["Y"] - tolerance and node_di[i]["Y"] <= node_di[j]["Y"] + tolerance):
39
+ if (node_di[i]["Z"] >= node_di[j]["Z"] - tolerance and node_di[i]["Z"] <= node_di[j]["Z"] + tolerance):
40
+ a.append(i)
41
+ b.append(j)
42
+ for i in range(len(a)):
43
+ for j in range(len(b)):
44
+ if a[i] == b[j]:
45
+ a[i] = a[j]
46
+ for k in elem_di.keys():
47
+ for i in range(len(a)):
48
+ if elem_di[k]['NODE'][0] == b[i]: elem_di[k]['NODE'][0] = a[i]
49
+ if elem_di[k]['NODE'][1] == b[i]: elem_di[k]['NODE'][1] = a[i]
50
+ try:
51
+ if elem_di[k]['NODE'][3] == b[i]: elem_di[k]['NODE'][3] = a[i]
52
+ except: pass
53
+ try:
54
+ if elem_di[k]['NODE'][4] == b[i]: elem_di[k]['NODE'][4] = a[i]
55
+ except: pass
56
+
57
+ if len(b)>0:
58
+ for i in range(len(b)):
59
+ if b[i] in node_di: del node_di[b[i]]
60
+ Node.nodes = []
61
+ Node.ids = []
62
+ for i in node_di.keys():
63
+ Node(node_di[i]['X'], node_di[i]['Y'], node_di[i]['Z'], i)
64
+ Element.elements = []
65
+ Element.ids = []
66
+ for i in elem_di.keys():
67
+ Element(elem_di[i], i)
68
+
69
+ @staticmethod
70
+ def units(force = "KN",length = "M", heat = "BTU", temp = "C"):
71
+ """force --> KN, N, KFG, TONF, LFB, KIPS ||
72
+ \ndist --> M, CM, MM, FT, IN ||
73
+ \nheat --> CAL, KCAL, J, KJ, BTU ||
74
+ \ntemp --> C, F
75
+ \nDefault --> KN, M, BTU, C"""
76
+ if temp not in ["C","F"]:
77
+ temp="C"
78
+ if force not in ["KN", "N", "KGF", "TONF", "LBF", "KIPS"]:
79
+ force = "KN"
80
+ if length not in ["M", "CM", "MM", "FT", "IN"]:
81
+ dist = "M"
82
+ if heat not in ["CAL", "KCAL", "J", "KJ", "BTU"]:
83
+ heat = "BTU"
84
+ unit={"Assign":{
85
+ 1:{
86
+ "FORCE":force,
87
+ "DIST":length,
88
+ "HEAT":heat,
89
+ "TEMPER":temp
90
+ }
91
+ }}
92
+ MidasAPI("PUT","/db/UNIT",unit)
93
+
94
+ @staticmethod
95
+ def select(crit_1 = "X", crit_2 = 0, crit_3 = 0, st = 'a', en = 'a', tolerance = 0):
96
+ """Get list of nodes/elements as required.\n
97
+ crit_1 (=> Along: "X", "Y", "Z". OR, IN: "XY", "YZ", "ZX". OR "USM"),\n
98
+ crit_2 (=> With Ordinate value: Y value, X value, X Value, Z value, X value, Y value. OR Material ID),\n
99
+ crit_3 (=> At Ordinate 2 value: Z value, Z value, Y value, 0, 0, 0. OR Section ID),\n
100
+ starting ordinate, end ordinate, tolerance, node dictionary, element dictionary.\n
101
+ Sample: get_select("Y", 0, 2) for selecting all nodes and elements parallel Y axis with X ordinate as 0 and Z ordinate as 2."""
102
+ output = {'NODE':[], 'ELEM':[]}
103
+ ok = 0
104
+ no = Node.json()
105
+ el = Element.json()
106
+ if crit_1 == "USM":
107
+ materials = Material.json()
108
+ sections = Section.json()
109
+ elements = el
110
+ k = list(elements.keys())[0]
111
+ mat_nos = list((materials["Assign"].keys()))
112
+ sect_nos = list((sections["Assign"].keys()))
113
+ elem = {}
114
+ for m in mat_nos:
115
+ elem[int(m)] = {}
116
+ for s in sect_nos:
117
+ elem[int(m)][int(s)] = []
118
+ for e in elements[k].keys(): elem[((elements[k][e]['MATL']))][((elements[k][e]['SECT']))].append(int(e))
119
+ output['ELEM'] = elem[crit_2][crit_3]
120
+ ok = 1
121
+ elif no != "" and el != "":
122
+ n_key = list(no.keys())[0]
123
+ e_key = list(el.keys())[0]
124
+ if n_key == "Assign": no["Assign"] = {str(key):value for key,value in no["Assign"].items()}
125
+ if e_key == "Assign": el["Assign"] = {str(key):value for key,value in el["Assign"].items()}
126
+ if crit_1 == "X":
127
+ cr2 = "Y"
128
+ cr3 = "Z"
129
+ ok = 1
130
+ if crit_1 == "Y":
131
+ cr2 = "X"
132
+ cr3 = "Z"
133
+ ok = 1
134
+ if crit_1 == "Z":
135
+ cr2 = "X"
136
+ cr3 = "Y"
137
+ ok = 1
138
+ if crit_1 == "XY" or crit_1 == "YX":
139
+ cr2 = "Z"
140
+ ok = 1
141
+ if crit_1 == "YZ" or crit_1 == "ZY":
142
+ cr2 = "X"
143
+ ok = 1
144
+ if crit_1 == "ZX" or crit_1 == "XZ":
145
+ cr2 = "Y"
146
+ ok = 1
147
+ if len(crit_1) == 1 and ok == 1:
148
+ if st == 'a': st = min([v[crit_1] for v in no[n_key].values()])
149
+ if en == 'a': en = max([v[crit_1] for v in no[n_key].values()])
150
+ for n in no[n_key].keys():
151
+ curr = no[n_key][n]
152
+ if curr[cr2] >= crit_2 - tolerance and curr[cr2] <= crit_2 + tolerance:
153
+ if curr[cr3] >= crit_3 - tolerance and curr[cr3] <= crit_3 + tolerance:
154
+ if curr[crit_1] >= st and curr[crit_1] <= en: output['NODE'].append(int(n))
155
+ for e in el[e_key].keys():
156
+ curr_0 = no[n_key][str(el[e_key][e]['NODE'][0])]
157
+ curr_1 = no[n_key][str(el[e_key][e]['NODE'][1])]
158
+ if curr_0[cr2] == curr_1[cr2] and curr_0[cr3] == curr_1[cr3]:
159
+ if curr_0[cr2] >= crit_2 - tolerance and curr_0[cr2] <= crit_2 + tolerance:
160
+ if curr_0[cr3] >= crit_3 - tolerance and curr_0[cr3] <= crit_3 + tolerance:
161
+ if curr_1[cr2] >= crit_2 - tolerance and curr_1[cr2] <= crit_2 + tolerance:
162
+ if curr_1[cr3] >= crit_3 - tolerance and curr_1[cr3] <= crit_3 + tolerance:
163
+ if curr_0[crit_1] >= st and curr_0[crit_1] <= en and curr_1[crit_1] >= st and curr_1[crit_1] <= en:
164
+ output['ELEM'].append(int(e))
165
+ if len(crit_1) == 2 and ok == 1:
166
+ if st == 'a': st = min(min([v[crit_1[0]] for v in no[n_key].values()]), min([v[crit_1[1]] for v in no[n_key].values()]))
167
+ if en == 'a': en = max(max([v[crit_1[0]] for v in no[n_key].values()]), max([v[crit_1[1]] for v in no[n_key].values()]))
168
+ for n in no[n_key].keys():
169
+ curr = no[n_key][n]
170
+ if curr[cr2] >= crit_2 - tolerance and curr[cr2] <= crit_2 + tolerance:
171
+ if curr[crit_1[0]] >= st and curr[crit_1[1]] >= st and curr[crit_1[0]] <= en and curr[crit_1[1]] <= en: output['NODE'].append(int(n))
172
+ for e in el[e_key].keys():
173
+ curr_0 = no[n_key][str(el[e_key][e]['NODE'][0])]
174
+ curr_1 = no[n_key][str(el[e_key][e]['NODE'][1])]
175
+ if curr_0[cr2] == curr_1[cr2]:
176
+ if curr_0[cr2] >= crit_2 - tolerance and curr_0[cr2] <= crit_2 + tolerance:
177
+ if curr_1[cr2] >= crit_2 - tolerance and curr_1[cr2] <= crit_2 + tolerance:
178
+ if curr_0[crit_1[0]] >= st and curr_0[crit_1[0]] <= en and curr_1[crit_1[0]] >= st and curr_1[crit_1[0]] <= en:
179
+ if curr_0[crit_1[1]] >= st and curr_0[crit_1[1]] <= en and curr_1[crit_1[1]] >= st and curr_1[crit_1[1]] <= en:
180
+ output['ELEM'].append(int(e))
181
+ if ok != 1: output = "Incorrect input. Please check the syntax!"
182
+ return output
183
+
184
+
185
+
186
+ @staticmethod
187
+ def _create2(request = "update", set = 1, force = "KN", length = "M", heat = "BTU", temp = "C"):
188
+ """request["update" to update a model, "call" to get details of existing model], \nforce[Optional], length[Optional], heat[Optional], temp[Optional].
189
+ \nSample: model() to update/create model. model("call") to get details of existing model and update classes.\n
190
+ set = 1 => Functions that don't need to call data from connected model file.\n
191
+ set = 2 => Functions that may need to call data from connected model file."""
192
+ Model.units(force, length, heat, temp)
193
+ if MAPI_KEY.data == []: print(f"Enter the MAPI key using the MAPI_KEY command.")
194
+ if MAPI_KEY.data != []:
195
+ if set == 1:
196
+ if request == "update" or request == "create" or request == "PUT":
197
+ if Node.json() != {"Assign":{}}: Node.create()
198
+ if Element.json() != {"Assign":{}}: Element.create()
199
+ if Section.json() != {"Assign":{}}: Section.create()
200
+ if Group.json_BG() != {"Assign":{}}: Group.create_BG()
201
+ if Group.json_LG() != {"Assign":{}}: Group.create_LG()
202
+ if Group.json_TG() != {"Assign":{}}: Group.create_TG()
203
+ if Material.json() != {"Assign":{}}: Material.create()
204
+ if request == "call" or request == "GET":
205
+ Node.sync()
206
+ Element.sync()
207
+ Section.sync()
208
+ Group.sync()
209
+ Material.sync()
210
+ if set == 2:
211
+ if request == "update" or request == "create" or request == "PUT":
212
+ if Node.json() != {"Assign":{}}: Node.create()
213
+ if Element.json() != {"Assign":{}}: Element.create()
214
+ if Section.json() != {"Assign":{}}: Section.create()
215
+ if Group.json_BG() != {"Assign":{}}: Group.create_BG()
216
+ if Group.json_LG() != {"Assign":{}}: Group.create_LG()
217
+ if Group.json_TG() != {"Assign":{}}: Group.create_TG()
218
+ if Material.json() != {"Assign":{}}: Material.create()
219
+ if Group.json_SG() != {"Assign":{}}: Group.create_SG()
220
+ if request == "call" or request == "GET":
221
+ Node.update_class()
222
+ Element.update_class()
223
+ Section.update_class()
224
+ Group.update_class()
225
+ Material.update_class()
226
+
227
+
228
+
229
+
230
+ @staticmethod
231
+ def create():
232
+ """Create Material, Section, Node, Elements, Groups and Boundary."""
233
+ if Material.mats!=[]: Material.createAll()
234
+ if Section.sect!=[]: Section.create()
235
+ if Thickness.thick!=[]: Thickness.create()
236
+ if Node.nodes!=[]: Node.create()
237
+ if Element.elements!=[] : Element.create()
238
+ Group.create()
239
+ Boundary.create()
240
+ Load.create()
241
+
242
+
243
+
244
+
245
+
246
+ @staticmethod
247
+ def clear():
248
+ Node.delete()
249
+ Element.delete()
250
+ Load_Case.delete()
251
+ Group.delete()
252
+ Material.deleteAll()
253
+ Section.delete()
254
+ Boundary.delete()
255
+
256
+ @staticmethod
257
+ def type(strc_type=0,mass_type=1,gravity:float=0,mass_dir=1):
258
+ """Structure Type option
259
+ --------------------------------
260
+
261
+ Structure Type:
262
+ 0 = 3D
263
+ 1 = X-Z Plane
264
+ 2 = Y-Z Plane
265
+ 3 = X-Y Plane
266
+ 4 = Constraint RZ
267
+
268
+ Mass Type:
269
+ 1 = Lumped Mass
270
+ 2 = Consistent Mass
271
+
272
+ Gravity Acceleration (g) = 9.81 m/s^2
273
+
274
+ Mass Direction(Structure Mass type):
275
+ 1 = Convert to X, Y, Z
276
+ 2 = Convert to X, Y
277
+ 3 = Convert to Z
278
+ """
279
+
280
+ js = {"Assign": {
281
+ "1":{}}}
282
+
283
+
284
+ js["Assign"]["1"]["STYP"] = strc_type
285
+
286
+ js["Assign"]["1"]["MASS"] = mass_type
287
+
288
+ if mass_dir==0:
289
+ js["Assign"]["1"]["bSELFWEIGHT"] = False
290
+ else:
291
+ js["Assign"]["1"]["bSELFWEIGHT"] = True
292
+ js["Assign"]["1"]["SMASS"] = mass_dir
293
+
294
+ if gravity!=0:
295
+ js["Assign"]["1"]["GRAV"] = gravity
296
+
297
+
298
+ MidasAPI("PUT","/db/STYP",js)
299
+
300
+ @staticmethod
301
+ def save(location=""):
302
+ """Saves the model\nFor the first save, provide location - \nModel.save("D:\\model2.mcb")"""
303
+ if location=="":
304
+ MidasAPI("POST","/doc/SAVE",{"Argument":{}})
305
+ else:
306
+ MidasAPI("POST","/doc/SAVEAS",{"Argument":str(location)})#Dumy location
307
+
308
+ @staticmethod
309
+ def saveAs(location=""):
310
+ """Saves the model at location provided"""
311
+ MidasAPI("POST","/doc/SAVE",{"Argument":str(location)})
312
+
313
+ @staticmethod
314
+ def open(location=""):
315
+ """Open Civil NX model file \n Model.open("D:\\model.mcb")"""
316
+ MidasAPI("POST","/doc/OPEN",{"Argument":str(location)})
317
+
318
+ @staticmethod
319
+ def new():
320
+ """Creates a new model"""
321
+ MidasAPI("POST","/doc/NEW",{"Argument":{}})
322
+
323
+ @staticmethod
324
+ def info(project_name="",revision="",user="",title=""):
325
+ """Enter Project information"""
326
+
327
+ js = {"Assign": {
328
+ "1":{}}}
329
+
330
+ if project_name+revision+user+title=="":
331
+ return MidasAPI("GET","/db/PJCF",{})
332
+ else:
333
+ if project_name!="":
334
+ js["Assign"]["1"]["PROJECT"] = project_name
335
+ if revision!="":
336
+ js["Assign"]["1"]["REVISION"] = revision
337
+ if user!="":
338
+ js["Assign"]["1"]["USER"] = user
339
+ if title!="":
340
+ js["Assign"]["1"]["TITLE"] = title
341
+
342
+
343
+ MidasAPI("PUT","/db/PJCF",js)
344
+
345
+
346
+
347
+
348
+
349
+
350
+
351
+
352
+
midas_civil/_node.py ADDED
@@ -0,0 +1,146 @@
1
+
2
+ from ._mapi import *
3
+ from ._utils import *
4
+ from math import hypot
5
+
6
+
7
+
8
+
9
+ def dist_tol(a,b):
10
+ return hypot((a.X-b.X),(a.Y-b.Y),(a.Z-b.Z)) < 0.00001 #TOLERANCE BUILT IN (UNIT INDEP)
11
+
12
+ def cell(point,size=1): #SIZE OF GRID
13
+ return (int(point.X//size),int(point.Y//size),int(point.Z//size))
14
+
15
+ #-- NEW SYSTEM
16
+
17
+ #5 Class to create nodes
18
+ class Node:
19
+ """X ordinate, Y ordinate, Z ordinate, Node ID (optional). \nSample: Node(1,0,5)"""
20
+ nodes = []
21
+ ids = []
22
+ Grid ={}
23
+ def __init__(self,x,y,z,id=0,merge=1):
24
+
25
+
26
+ #----------------- ORIGINAL -----------------------
27
+
28
+ if Node.ids == []:
29
+ node_count = 1
30
+ else:
31
+ node_count = max(Node.ids)+1
32
+
33
+
34
+ self.X = x
35
+ self.Y = y
36
+ self.Z = z
37
+
38
+ if id == 0 : self.ID = node_count
39
+ if id != 0 : self.ID = id
40
+
41
+ #REPLACE - No merge check
42
+ if id in Node.ids:
43
+ index=Node.ids.index(id)
44
+ n_orig = Node.nodes[index]
45
+ loc_orig = str(cell(n_orig))
46
+ Node.Grid[loc_orig].remove(n_orig)
47
+
48
+ loc_new = str(cell(self))
49
+
50
+ zz_add_to_dict(Node.Grid,loc_new,self)
51
+ Node.nodes[index]=self
52
+
53
+
54
+ #CREATE NEW - Merge Check based on input
55
+ else:
56
+ cell_loc = str(cell(self))
57
+
58
+ if cell_loc in Node.Grid:
59
+ if merge == 1:
60
+ chk=0 #OPTIONAL
61
+ for node in Node.Grid[cell_loc]:
62
+ if dist_tol(self,node):
63
+ chk=1
64
+ self.ID=node.ID
65
+ if chk==0:
66
+ Node.nodes.append(self)
67
+ Node.ids.append(self.ID)
68
+ Node.Grid[cell_loc].append(self)
69
+ else:
70
+ Node.nodes.append(self)
71
+ Node.ids.append(self.ID)
72
+ Node.Grid[cell_loc].append(self)
73
+ else:
74
+ Node.Grid[cell_loc]=[]
75
+ Node.nodes.append(self)
76
+ Node.ids.append(self.ID)
77
+ Node.Grid[cell_loc].append(self)
78
+
79
+
80
+
81
+ @classmethod
82
+ def json(cls):
83
+ json = {"Assign":{}}
84
+ for i in cls.nodes:
85
+ json["Assign"][i.ID]={"X":i.X,"Y":i.Y,"Z":i.Z}
86
+ return json
87
+
88
+ @staticmethod
89
+ def create():
90
+ MidasAPI("PUT","/db/NODE",Node.json())
91
+
92
+ @staticmethod
93
+ def get():
94
+ return MidasAPI("GET","/db/NODE")
95
+
96
+ @staticmethod
97
+ def sync():
98
+ a = Node.get()
99
+ if a != {'message': ''}:
100
+ if list(a['NODE'].keys()) != []:
101
+ Node.nodes = []
102
+ Node.ids=[]
103
+ for j in a['NODE'].keys():
104
+ Node(round(a['NODE'][j]['X'],6), round(a['NODE'][j]['Y'],6), round(a['NODE'][j]['Z'],6),int(j),0)
105
+
106
+ @staticmethod
107
+ def delete2(nodes_list):
108
+ if type(nodes_list)!=list:
109
+ nodes_list = [nodes_list]
110
+ url_add = arr2csv(nodes_list)
111
+
112
+ MidasAPI("DELETE",f"/db/NODE/{url_add}")
113
+
114
+
115
+ @staticmethod
116
+ def delete3(*args):
117
+ try:
118
+ args2=sFlatten(args)
119
+ url_add = arr2csv(args2)
120
+ MidasAPI("DELETE",f"/db/NODE/{url_add}")
121
+ except:
122
+ MidasAPI("DELETE",f"/db/NODE/")
123
+ Node.nodes=[]
124
+ Node.ids=[]
125
+
126
+ @staticmethod
127
+ def delete():
128
+ MidasAPI("DELETE","/db/NODE/")
129
+ Node.nodes=[]
130
+ Node.ids=[]
131
+ Node.Grid={}
132
+
133
+
134
+
135
+
136
+
137
+
138
+
139
+
140
+
141
+
142
+
143
+
144
+
145
+
146
+