midas-civil 0.1.4__py3-none-any.whl → 0.1.6__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/__init__.py +5 -0
- midas_civil/_boundary.py +11 -1
- midas_civil/_element.py +186 -7
- midas_civil/_group.py +23 -2
- midas_civil/_load.py +49 -23
- midas_civil/_mapi.py +18 -5
- midas_civil/_model.py +6 -0
- midas_civil/_movingload.py +1431 -0
- midas_civil/_node.py +20 -5
- midas_civil/_result.py +3 -3
- midas_civil/_result_extract.py +17 -9
- midas_civil/_section.py +137 -3
- midas_civil/_settlement.py +160 -0
- midas_civil/_temperature.py +262 -1
- midas_civil/_tendon.py +839 -56
- midas_civil/_thickness.py +1 -1
- midas_civil/_view.py +5 -0
- {midas_civil-0.1.4.dist-info → midas_civil-0.1.6.dist-info}/METADATA +1 -1
- midas_civil-0.1.6.dist-info/RECORD +27 -0
- midas_civil-0.1.4.dist-info/RECORD +0 -25
- {midas_civil-0.1.4.dist-info → midas_civil-0.1.6.dist-info}/WHEEL +0 -0
- {midas_civil-0.1.4.dist-info → midas_civil-0.1.6.dist-info}/licenses/LICENSE +0 -0
- {midas_civil-0.1.4.dist-info → midas_civil-0.1.6.dist-info}/top_level.txt +0 -0
midas_civil/__init__.py
CHANGED
midas_civil/_boundary.py
CHANGED
|
@@ -10,6 +10,16 @@ def convList(item):
|
|
|
10
10
|
return item
|
|
11
11
|
|
|
12
12
|
|
|
13
|
+
# ----- Extend for list of nodes/elems -----
|
|
14
|
+
|
|
15
|
+
def _ADD_Support(self):
|
|
16
|
+
if isinstance(self.NODE,int):
|
|
17
|
+
Boundary.Support.sups.append(self)
|
|
18
|
+
elif isinstance(self.NODE,list):
|
|
19
|
+
for nID in self.NODE:
|
|
20
|
+
Boundary.Support(nID,self.CONST,self.GROUP)
|
|
21
|
+
|
|
22
|
+
|
|
13
23
|
class Boundary:
|
|
14
24
|
|
|
15
25
|
@classmethod
|
|
@@ -67,7 +77,7 @@ class Boundary:
|
|
|
67
77
|
self.CONST = string
|
|
68
78
|
self.GROUP = group
|
|
69
79
|
self.ID = len(Boundary.Support.sups) + 1
|
|
70
|
-
|
|
80
|
+
_ADD_Support(self)
|
|
71
81
|
|
|
72
82
|
@classmethod
|
|
73
83
|
def json(cls):
|
midas_civil/_element.py
CHANGED
|
@@ -1,9 +1,15 @@
|
|
|
1
1
|
from ._mapi import *
|
|
2
2
|
from ._node import *
|
|
3
3
|
from ._group import _add_elem_2_stGroup
|
|
4
|
+
from ._group import _add_node_2_stGroup
|
|
4
5
|
|
|
5
6
|
import numpy as np
|
|
6
7
|
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
|
|
7
13
|
def _ADD(self):
|
|
8
14
|
"""
|
|
9
15
|
Adds an element to the main list. If the ID is 0, it auto-increments.
|
|
@@ -32,13 +38,17 @@ def _ADD(self):
|
|
|
32
38
|
Element.ids.append(int(self.ID))
|
|
33
39
|
|
|
34
40
|
# ------------ Group assignment -----------------------
|
|
35
|
-
if self._GROUP ==
|
|
41
|
+
if self._GROUP == "" :
|
|
36
42
|
pass
|
|
37
43
|
elif isinstance(self._GROUP, list):
|
|
38
44
|
for gpName in self._GROUP:
|
|
39
45
|
_add_elem_2_stGroup(self.ID,gpName)
|
|
46
|
+
for nd in self.NODE:
|
|
47
|
+
_add_node_2_stGroup(nd,gpName)
|
|
40
48
|
elif isinstance(self._GROUP, str):
|
|
41
49
|
_add_elem_2_stGroup(self.ID,self._GROUP)
|
|
50
|
+
for nd in self.NODE:
|
|
51
|
+
_add_node_2_stGroup(nd,self._GROUP)
|
|
42
52
|
|
|
43
53
|
|
|
44
54
|
|
|
@@ -117,17 +127,17 @@ def _JS2Obj(id, js):
|
|
|
117
127
|
t_limit = js.get('T_LIMIT')
|
|
118
128
|
|
|
119
129
|
if elem_type == 'BEAM':
|
|
120
|
-
Element.Beam(args['node'][0], args['node'][1], args['mat'], args['sect'], args['angle'], args['id'])
|
|
130
|
+
Element.Beam(args['node'][0], args['node'][1], args['mat'], args['sect'], args['angle'], '', args['id'])
|
|
121
131
|
elif elem_type == 'TRUSS':
|
|
122
|
-
Element.Truss(args['node'][0], args['node'][1], args['mat'], args['sect'], args['angle'],
|
|
132
|
+
Element.Truss(args['node'][0], args['node'][1], args['mat'], args['sect'], args['angle'],'', args['id'])
|
|
123
133
|
elif elem_type == 'PLATE':
|
|
124
|
-
Element.Plate(args['node'], args['stype'], args['mat'], args['sect'], args['angle'], args['id'])
|
|
134
|
+
Element.Plate(args['node'], args['stype'], args['mat'], args['sect'], args['angle'], '', args['id'])
|
|
125
135
|
elif elem_type == 'TENSTR':
|
|
126
|
-
Element.Tension(args['node'][0], args['node'][1], args['stype'], args['mat'], args['sect'], args['angle'], args['id'], non_len, cable_type, tens, t_limit)
|
|
136
|
+
Element.Tension(args['node'][0], args['node'][1], args['stype'], args['mat'], args['sect'], args['angle'], '', args['id'], non_len, cable_type, tens, t_limit)
|
|
127
137
|
elif elem_type == 'COMPTR':
|
|
128
|
-
Element.Compression(args['node'][0], args['node'][1], args['stype'], args['mat'], args['sect'], args['angle'], args['id'], tens, t_limit, non_len)
|
|
138
|
+
Element.Compression(args['node'][0], args['node'][1], args['stype'], args['mat'], args['sect'], args['angle'], '', args['id'], tens, t_limit, non_len)
|
|
129
139
|
elif elem_type == 'SOLID':
|
|
130
|
-
Element.Solid(nodes=args['node'], mat=args['mat'], sect=args['sect'], id=args['id'])
|
|
140
|
+
Element.Solid(nodes=args['node'], mat=args['mat'], sect=args['sect'],group='', id=args['id'])
|
|
131
141
|
|
|
132
142
|
|
|
133
143
|
class _common:
|
|
@@ -516,10 +526,179 @@ class Element:
|
|
|
516
526
|
_ADD(self)
|
|
517
527
|
|
|
518
528
|
|
|
529
|
+
#-----------------------------------------------Stiffness Scale Factor------------------------------
|
|
519
530
|
|
|
531
|
+
class StiffnessScaleFactor:
|
|
532
|
+
|
|
533
|
+
data = []
|
|
534
|
+
|
|
535
|
+
def __init__(self,
|
|
536
|
+
element_id,
|
|
537
|
+
area_sf: float = 1.0,
|
|
538
|
+
asy_sf: float = 1.0,
|
|
539
|
+
asz_sf: float = 1.0,
|
|
540
|
+
ixx_sf: float = 1.0,
|
|
541
|
+
iyy_sf: float = 1.0,
|
|
542
|
+
izz_sf: float = 1.0,
|
|
543
|
+
wgt_sf: float = 1.0,
|
|
544
|
+
group: str = "",
|
|
545
|
+
id: int = None):
|
|
546
|
+
"""
|
|
547
|
+
element_id: Element ID(s) where scale factor is applied (can be int or list)
|
|
548
|
+
area_sf: Cross-sectional area scale factor
|
|
549
|
+
asy_sf: Effective Shear Area scale factor (y-axis)
|
|
550
|
+
asz_sf: Effective Shear Area scale factor (z-axis)
|
|
551
|
+
ixx_sf: Torsional Resistance scale factor (x-axis)
|
|
552
|
+
iyy_sf: Area Moment of Inertia scale factor (y-axis)
|
|
553
|
+
izz_sf: Area Moment of Inertia scale factor (z-axis)
|
|
554
|
+
wgt_sf: Weight scale factor
|
|
555
|
+
group: Group name (default "")
|
|
556
|
+
id: Scale factor ID (optional, auto-assigned if None)
|
|
557
|
+
|
|
558
|
+
Examples:
|
|
559
|
+
StiffnessScaleFactor(908, area_sf=0.5, asy_sf=0.6, asz_sf=0.7,
|
|
560
|
+
ixx_sf=0.8, iyy_sf=0.8, izz_sf=0.9, wgt_sf=0.95)
|
|
561
|
+
|
|
562
|
+
"""
|
|
563
|
+
|
|
564
|
+
# Check if group exists, create if not
|
|
565
|
+
if group != "":
|
|
566
|
+
chk = 0
|
|
567
|
+
a = [v['NAME'] for v in Group.Boundary.json()["Assign"].values()]
|
|
568
|
+
if group in a:
|
|
569
|
+
chk = 1
|
|
570
|
+
if chk == 0:
|
|
571
|
+
Group.Boundary(group)
|
|
572
|
+
|
|
573
|
+
# Handle element_id as single int or list
|
|
574
|
+
if isinstance(element_id, (list, tuple)):
|
|
575
|
+
self.ELEMENT_IDS = list(element_id)
|
|
576
|
+
else:
|
|
577
|
+
self.ELEMENT_IDS = [element_id]
|
|
578
|
+
|
|
579
|
+
self.AREA_SF = area_sf
|
|
580
|
+
self.ASY_SF = asy_sf
|
|
581
|
+
self.ASZ_SF = asz_sf
|
|
582
|
+
self.IXX_SF = ixx_sf
|
|
583
|
+
self.IYY_SF = iyy_sf
|
|
584
|
+
self.IZZ_SF = izz_sf
|
|
585
|
+
self.WGT_SF = wgt_sf
|
|
586
|
+
self.GROUP_NAME = group
|
|
587
|
+
|
|
588
|
+
# Auto-assign ID if not provided
|
|
589
|
+
if id is None:
|
|
590
|
+
self.ID = len(Element.StiffnessScaleFactor.data) + 1
|
|
591
|
+
else:
|
|
592
|
+
self.ID = id
|
|
593
|
+
|
|
594
|
+
# Add to static list
|
|
595
|
+
Element.StiffnessScaleFactor.data.append(self)
|
|
596
|
+
|
|
597
|
+
@classmethod
|
|
598
|
+
def json(cls):
|
|
599
|
+
"""
|
|
600
|
+
Converts StiffnessScaleFactor data to JSON format
|
|
601
|
+
"""
|
|
602
|
+
json_data = {"Assign": {}}
|
|
603
|
+
|
|
604
|
+
for scale_factor in cls.data:
|
|
605
|
+
# Create scale factor item
|
|
606
|
+
scale_factor_item = {
|
|
607
|
+
"ID": scale_factor.ID,
|
|
608
|
+
"AREA_SF": scale_factor.AREA_SF,
|
|
609
|
+
"ASY_SF": scale_factor.ASY_SF,
|
|
610
|
+
"ASZ_SF": scale_factor.ASZ_SF,
|
|
611
|
+
"IXX_SF": scale_factor.IXX_SF,
|
|
612
|
+
"IYY_SF": scale_factor.IYY_SF,
|
|
613
|
+
"IZZ_SF": scale_factor.IZZ_SF,
|
|
614
|
+
"WGT_SF": scale_factor.WGT_SF,
|
|
615
|
+
"GROUP_NAME": scale_factor.GROUP_NAME
|
|
616
|
+
}
|
|
617
|
+
|
|
618
|
+
# Assign to each element ID
|
|
619
|
+
for element_id in scale_factor.ELEMENT_IDS:
|
|
620
|
+
if str(element_id) not in json_data["Assign"]:
|
|
621
|
+
json_data["Assign"][str(element_id)] = {"ITEMS": []}
|
|
622
|
+
|
|
623
|
+
json_data["Assign"][str(element_id)]["ITEMS"].append(scale_factor_item)
|
|
624
|
+
|
|
625
|
+
return json_data
|
|
626
|
+
|
|
627
|
+
@classmethod
|
|
628
|
+
def create(cls):
|
|
629
|
+
"""
|
|
630
|
+
Sends all StiffnessScaleFactor data to the API
|
|
631
|
+
"""
|
|
632
|
+
MidasAPI("PUT", "/db/essf", cls.json())
|
|
633
|
+
|
|
634
|
+
@classmethod
|
|
635
|
+
def get(cls):
|
|
636
|
+
"""
|
|
637
|
+
Retrieves StiffnessScaleFactor data from the API
|
|
638
|
+
"""
|
|
639
|
+
return MidasAPI("GET", "/db/essf")
|
|
640
|
+
|
|
641
|
+
@classmethod
|
|
642
|
+
def sync(cls):
|
|
643
|
+
"""
|
|
644
|
+
Updates the StiffnessScaleFactor class with data from the API
|
|
645
|
+
"""
|
|
646
|
+
cls.data = []
|
|
647
|
+
response = cls.get()
|
|
648
|
+
|
|
649
|
+
if response != {'message': ''}:
|
|
650
|
+
processed_ids = set() # To avoid duplicate processing
|
|
651
|
+
|
|
652
|
+
for element_data in response.get("ESSF", {}).items():
|
|
653
|
+
for item in element_data.get("ITEMS", []):
|
|
654
|
+
scale_factor_id = item.get("ID", 1)
|
|
655
|
+
|
|
656
|
+
# Skip if already processed (for multi-element scale factors)
|
|
657
|
+
if scale_factor_id in processed_ids:
|
|
658
|
+
continue
|
|
659
|
+
|
|
660
|
+
# Find all elements with the same scale factor ID
|
|
661
|
+
element_ids = []
|
|
662
|
+
for eid, edata in response.get("ESSF", {}).items():
|
|
663
|
+
for eitem in edata.get("ITEMS", []):
|
|
664
|
+
if eitem.get("ID") == scale_factor_id:
|
|
665
|
+
element_ids.append(int(eid))
|
|
666
|
+
|
|
667
|
+
# Create StiffnessScaleFactor object
|
|
668
|
+
Element.StiffnessScaleFactor(
|
|
669
|
+
element_id=element_ids if len(element_ids) > 1 else element_ids[0],
|
|
670
|
+
area_sf=item.get("AREA_SF", 1.0),
|
|
671
|
+
asy_sf=item.get("ASY_SF", 1.0),
|
|
672
|
+
asz_sf=item.get("ASZ_SF", 1.0),
|
|
673
|
+
ixx_sf=item.get("IXX_SF", 1.0),
|
|
674
|
+
iyy_sf=item.get("IYY_SF", 1.0),
|
|
675
|
+
izz_sf=item.get("IZZ_SF", 1.0),
|
|
676
|
+
wgt_sf=item.get("WGT_SF", 1.0),
|
|
677
|
+
group=item.get("GROUP_NAME", ""),
|
|
678
|
+
id=scale_factor_id
|
|
679
|
+
)
|
|
680
|
+
|
|
681
|
+
processed_ids.add(scale_factor_id)
|
|
682
|
+
|
|
683
|
+
@classmethod
|
|
684
|
+
def delete(cls):
|
|
685
|
+
"""
|
|
686
|
+
Deletes all stiffness scale factors from the database and resets the class.
|
|
687
|
+
"""
|
|
688
|
+
cls.data = []
|
|
689
|
+
return MidasAPI("DELETE", "/db/essf")
|
|
520
690
|
|
|
521
691
|
|
|
522
692
|
|
|
523
693
|
|
|
694
|
+
# ---- GET ELEMENT OBJECT FROM ID ----------
|
|
524
695
|
|
|
696
|
+
def elemByID(elemID:int) -> Element:
|
|
697
|
+
''' Return Element object with the input ID '''
|
|
698
|
+
for elem in Element.elements:
|
|
699
|
+
if elem.ID == elemID:
|
|
700
|
+
return elem
|
|
701
|
+
|
|
702
|
+
print(f'There is no element with ID {elemID}')
|
|
703
|
+
return None
|
|
525
704
|
|
midas_civil/_group.py
CHANGED
|
@@ -3,8 +3,30 @@ from ._mapi import *
|
|
|
3
3
|
|
|
4
4
|
|
|
5
5
|
|
|
6
|
+
|
|
7
|
+
|
|
6
8
|
# ----------- HELPER FUNCTION -----------
|
|
7
|
-
# --------
|
|
9
|
+
# -------- RETRIEVE NODE / ELEMENT FROM STRUCTURE GROUP -------
|
|
10
|
+
|
|
11
|
+
def nodesInGroup(groupName:str) -> list | int:
|
|
12
|
+
''' Returns Node ID list in a Structure Group '''
|
|
13
|
+
for i in Group.Structure.Groups:
|
|
14
|
+
if i.NAME == groupName:
|
|
15
|
+
return i.NLIST
|
|
16
|
+
print('⚠️ Structure group not found !')
|
|
17
|
+
return []
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
def elemsInGroup(groupName:str) -> list:
|
|
21
|
+
''' Returns Element ID list in a Structure Group '''
|
|
22
|
+
for i in Group.Structure.Groups:
|
|
23
|
+
if i.NAME == groupName:
|
|
24
|
+
return i.ELIST
|
|
25
|
+
print('⚠️ Structure group not found !')
|
|
26
|
+
return []
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
# -------- ADD ELEMENT TO STRUCTURE GROUP -------
|
|
8
30
|
|
|
9
31
|
def _add_elem_2_stGroup(elemID,groupName):
|
|
10
32
|
up = 0
|
|
@@ -19,7 +41,6 @@ def _add_elem_2_stGroup(elemID,groupName):
|
|
|
19
41
|
|
|
20
42
|
|
|
21
43
|
def _add_node_2_stGroup(nodeID,groupName):
|
|
22
|
-
up = 0
|
|
23
44
|
if groupName in Group.Structure._names:
|
|
24
45
|
for i in Group.Structure.Groups:
|
|
25
46
|
if i.NAME == groupName:
|
midas_civil/_load.py
CHANGED
|
@@ -2,6 +2,28 @@ from ._mapi import *
|
|
|
2
2
|
from ._model import *
|
|
3
3
|
from ._group import *
|
|
4
4
|
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
# ----- Extend for list of nodes/elems -----
|
|
8
|
+
|
|
9
|
+
def _ADD_NodalLoad(self):
|
|
10
|
+
if isinstance(self.NODE,int):
|
|
11
|
+
Load.Nodal.data.append(self)
|
|
12
|
+
elif isinstance(self.NODE,list):
|
|
13
|
+
for nID in self.NODE:
|
|
14
|
+
Load.Nodal(nID,self.LCN,self.LDGR,self.FX,self.FY,self.FZ,self.MX,self.MY,self.MZ,self.ID)
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
def _ADD_BeamLoad(self):
|
|
18
|
+
if isinstance(self.ELEMENT,int):
|
|
19
|
+
Load.Beam.data.append(self)
|
|
20
|
+
elif isinstance(self.ELEMENT,list):
|
|
21
|
+
for eID in self.ELEMENT:
|
|
22
|
+
Load.Beam(eID,self.LCN,self.LDGR,self.VALUE,self.DIRECTION,self.ID,self.D,self.P,self.CMD,self.TYPE,self.USE_ECCEN,self.USE_PROJECTION,
|
|
23
|
+
self.ECCEN_DIR,self.ECCEN_TYPE,self.IECC,self.JECC,self.USE_H,self.I_H,self.J_H)
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
|
|
5
27
|
#11 Class to define Load Cases:
|
|
6
28
|
class Load_Case:
|
|
7
29
|
"""Type symbol (Refer Static Load Case section in the Onine API Manual, Load Case names.
|
|
@@ -177,7 +199,9 @@ class Load:
|
|
|
177
199
|
self.MZ = MZ
|
|
178
200
|
if id == "": id = len(Load.Nodal.data) + 1
|
|
179
201
|
self.ID = id
|
|
180
|
-
|
|
202
|
+
|
|
203
|
+
_ADD_NodalLoad(self)
|
|
204
|
+
# Load.Nodal.data.append(self)
|
|
181
205
|
|
|
182
206
|
@classmethod
|
|
183
207
|
def json(cls):
|
|
@@ -228,9 +252,9 @@ class Load:
|
|
|
228
252
|
#19 Class to define Beam Loads:
|
|
229
253
|
class Beam:
|
|
230
254
|
data = []
|
|
231
|
-
def __init__(self, element
|
|
255
|
+
def __init__(self, element, load_case: str, load_group: str = "", value: float=0, direction: str = "GZ",
|
|
232
256
|
id = "", D = [0, 1, 0, 0], P = [0, 0, 0, 0], cmd = "BEAM", typ = "UNILOAD", use_ecc = False, use_proj = False,
|
|
233
|
-
eccn_dir = "LZ", eccn_type = 1, ieccn = 0, jeccn = 0
|
|
257
|
+
eccn_dir = "LZ", eccn_type = 1, ieccn = 0, jeccn = 0, adnl_h = False, adnl_h_i = 0, adnl_h_j = 0):
|
|
234
258
|
"""
|
|
235
259
|
element: Element Number
|
|
236
260
|
load_case (str): Load case name
|
|
@@ -276,7 +300,7 @@ class Load:
|
|
|
276
300
|
if cmd not in ("BEAM", "LINE", "TYPICAL"): cmd = "BEAM"
|
|
277
301
|
if typ not in ("CONLOAD", "CONMOMENT", "UNILOAD", "UNIMOMENT","PRESSURE"): typ = "UNILOAD"
|
|
278
302
|
if use_ecc == False:
|
|
279
|
-
if ieccn != 0 or jeccn != 0
|
|
303
|
+
if ieccn != 0 or jeccn != 0: use_ecc = True
|
|
280
304
|
self.ELEMENT = element
|
|
281
305
|
self.LCN = load_case
|
|
282
306
|
self.LDGR = load_group
|
|
@@ -289,7 +313,7 @@ class Load:
|
|
|
289
313
|
self.ECCEN_TYPE = eccn_type
|
|
290
314
|
self.ECCEN_DIR = eccn_dir
|
|
291
315
|
self.IECC = ieccn
|
|
292
|
-
if jeccn == 0
|
|
316
|
+
if jeccn == 0:
|
|
293
317
|
self.JECC = 0
|
|
294
318
|
self.USE_JECC = False
|
|
295
319
|
else:
|
|
@@ -299,7 +323,7 @@ class Load:
|
|
|
299
323
|
self.P = P
|
|
300
324
|
self.USE_H = adnl_h
|
|
301
325
|
self.I_H = adnl_h_i
|
|
302
|
-
if adnl_h == 0
|
|
326
|
+
if adnl_h == 0:
|
|
303
327
|
self.USE_JH = False
|
|
304
328
|
self.J_H = 0
|
|
305
329
|
else:
|
|
@@ -309,7 +333,8 @@ class Load:
|
|
|
309
333
|
if id == "":
|
|
310
334
|
id = len(Load.Beam.data) + 1
|
|
311
335
|
self.ID = id
|
|
312
|
-
|
|
336
|
+
_ADD_BeamLoad(self)
|
|
337
|
+
# Load.Beam.data.append(self)
|
|
313
338
|
|
|
314
339
|
@classmethod
|
|
315
340
|
def json(cls):
|
|
@@ -368,23 +393,23 @@ class Load:
|
|
|
368
393
|
for i in a['BMLD'].keys():
|
|
369
394
|
for j in range(len(a['BMLD'][i]['ITEMS'])):
|
|
370
395
|
if a['BMLD'][i]['ITEMS'][j]['USE_ECCEN'] == True and a['BMLD'][i]['ITEMS'][j]['USE_ADDITIONAL'] == True:
|
|
371
|
-
Load.Beam(i,a['BMLD'][i]['ITEMS'][j]['LCNAME'], a['BMLD'][i]['ITEMS'][j]['
|
|
396
|
+
Load.Beam(i,a['BMLD'][i]['ITEMS'][j]['LCNAME'], a['BMLD'][i]['ITEMS'][j]['GROUP_NAME'], a['BMLD'][i]['ITEMS'][j]['P'][0],
|
|
372
397
|
a['BMLD'][i]['ITEMS'][j]['DIRECTION'], a['BMLD'][i]['ITEMS'][j]['ID'], a['BMLD'][i]['ITEMS'][j]['D'], a['BMLD'][i]['ITEMS'][j]['P'],
|
|
373
398
|
a['BMLD'][i]['ITEMS'][j]['CMD'], a['BMLD'][i]['ITEMS'][j]['TYPE'], a['BMLD'][i]['ITEMS'][j]['USE_ECCEN'], a['BMLD'][i]['ITEMS'][j]['USE_PROJECTION'],
|
|
374
399
|
a['BMLD'][i]['ITEMS'][j]['ECCEN_DIR'], a['BMLD'][i]['ITEMS'][j]['ECCEN_TYPE'], a['BMLD'][i]['ITEMS'][j]['I_END'], a['BMLD'][i]['ITEMS'][j]['J_END'],
|
|
375
400
|
a['BMLD'][i]['ITEMS'][j]['USE_ADDITIONAL'], a['BMLD'][i]['ITEMS'][j]['ADDITIONAL_I_END'], a['BMLD'][i]['ITEMS'][j]['ADDITIONAL_J_END'])
|
|
376
401
|
elif a['BMLD'][i]['ITEMS'][j]['USE_ECCEN'] == False and a['BMLD'][i]['ITEMS'][j]['USE_ADDITIONAL'] == True:
|
|
377
|
-
Load.Beam(i,a['BMLD'][i]['ITEMS'][j]['LCNAME'], a['BMLD'][i]['ITEMS'][j]['
|
|
402
|
+
Load.Beam(i,a['BMLD'][i]['ITEMS'][j]['LCNAME'], a['BMLD'][i]['ITEMS'][j]['GROUP_NAME'], a['BMLD'][i]['ITEMS'][j]['P'][0],
|
|
378
403
|
a['BMLD'][i]['ITEMS'][j]['DIRECTION'], a['BMLD'][i]['ITEMS'][j]['ID'], a['BMLD'][i]['ITEMS'][j]['D'], a['BMLD'][i]['ITEMS'][j]['P'],
|
|
379
404
|
a['BMLD'][i]['ITEMS'][j]['CMD'], a['BMLD'][i]['ITEMS'][j]['TYPE'], a['BMLD'][i]['ITEMS'][j]['USE_ECCEN'], a['BMLD'][i]['ITEMS'][j]['USE_PROJECTION'],
|
|
380
405
|
adnl_h = a['BMLD'][i]['ITEMS'][j]['USE_ADDITIONAL'], adnl_h_i = a['BMLD'][i]['ITEMS'][j]['ADDITIONAL_I_END'], adnl_h_j = a['BMLD'][i]['ITEMS'][j]['ADDITIONAL_J_END'])
|
|
381
406
|
elif a['BMLD'][i]['ITEMS'][j]['USE_ECCEN'] == True and a['BMLD'][i]['ITEMS'][j]['USE_ADDITIONAL'] == False:
|
|
382
|
-
Load.Beam(i,a['BMLD'][i]['ITEMS'][j]['LCNAME'], a['BMLD'][i]['ITEMS'][j]['
|
|
407
|
+
Load.Beam(i,a['BMLD'][i]['ITEMS'][j]['LCNAME'], a['BMLD'][i]['ITEMS'][j]['GROUP_NAME'], a['BMLD'][i]['ITEMS'][j]['P'][0],
|
|
383
408
|
a['BMLD'][i]['ITEMS'][j]['DIRECTION'], a['BMLD'][i]['ITEMS'][j]['ID'], a['BMLD'][i]['ITEMS'][j]['D'], a['BMLD'][i]['ITEMS'][j]['P'],
|
|
384
409
|
a['BMLD'][i]['ITEMS'][j]['CMD'], a['BMLD'][i]['ITEMS'][j]['TYPE'], a['BMLD'][i]['ITEMS'][j]['USE_ECCEN'], a['BMLD'][i]['ITEMS'][j]['USE_PROJECTION'],
|
|
385
410
|
a['BMLD'][i]['ITEMS'][j]['ECCEN_DIR'], a['BMLD'][i]['ITEMS'][j]['ECCEN_TYPE'], a['BMLD'][i]['ITEMS'][j]['I_END'], a['BMLD'][i]['ITEMS'][j]['J_END'])
|
|
386
411
|
else:
|
|
387
|
-
Load.Beam(i,a['BMLD'][i]['ITEMS'][j]['LCNAME'], a['BMLD'][i]['ITEMS'][j]['
|
|
412
|
+
Load.Beam(i,a['BMLD'][i]['ITEMS'][j]['LCNAME'], a['BMLD'][i]['ITEMS'][j]['GROUP_NAME'],a['BMLD'][i]['ITEMS'][j]['P'][0],
|
|
388
413
|
a['BMLD'][i]['ITEMS'][j]['DIRECTION'], a['BMLD'][i]['ITEMS'][j]['ID'], a['BMLD'][i]['ITEMS'][j]['D'], a['BMLD'][i]['ITEMS'][j]['P'],
|
|
389
414
|
a['BMLD'][i]['ITEMS'][j]['CMD'], a['BMLD'][i]['ITEMS'][j]['TYPE'], a['BMLD'][i]['ITEMS'][j]['USE_ECCEN'], a['BMLD'][i]['ITEMS'][j]['USE_PROJECTION'])
|
|
390
415
|
|
|
@@ -521,12 +546,13 @@ class Load:
|
|
|
521
546
|
|
|
522
547
|
class NodalMass:
|
|
523
548
|
"""Creates nodal mass and converts to JSON format.
|
|
524
|
-
Example: NodalMass(1.5, 2.0, 3.0, 0.1, 0.2, 0.3)
|
|
549
|
+
Example: NodalMass(1, 1.5, 2.0, 3.0, 0.1, 0.2, 0.3)
|
|
525
550
|
"""
|
|
526
551
|
data = []
|
|
527
|
-
|
|
528
|
-
def __init__(self, mX, mY=0, mZ=0, rmX=0, rmY=0, rmZ=0):
|
|
552
|
+
|
|
553
|
+
def __init__(self, node_id, mX, mY=0, mZ=0, rmX=0, rmY=0, rmZ=0):
|
|
529
554
|
"""
|
|
555
|
+
node_id (int): Node ID where the mass is applied (Required)
|
|
530
556
|
mX (float): Translational Lumped Mass in GCS X-direction (Required)
|
|
531
557
|
mY (float): Translational Lumped Mass in GCS Y-direction. Defaults to 0
|
|
532
558
|
mZ (float): Translational Lumped Mass in GCS Z-direction. Defaults to 0
|
|
@@ -534,6 +560,7 @@ class Load:
|
|
|
534
560
|
rmY (float): Rotational Mass Moment of Inertia about GCS Y-axis. Defaults to 0
|
|
535
561
|
rmZ (float): Rotational Mass Moment of Inertia about GCS Z-axis. Defaults to 0
|
|
536
562
|
"""
|
|
563
|
+
self.NODE_ID = node_id
|
|
537
564
|
self.MX = mX
|
|
538
565
|
self.MY = mY
|
|
539
566
|
self.MZ = mZ
|
|
@@ -547,10 +574,8 @@ class Load:
|
|
|
547
574
|
def json(cls):
|
|
548
575
|
json_data = {"Assign": {}}
|
|
549
576
|
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
mass_obj = cls.data[-1] # Get the most recent mass object
|
|
553
|
-
json_data["Assign"]["1"] = {
|
|
577
|
+
for mass_obj in cls.data:
|
|
578
|
+
json_data["Assign"][mass_obj.NODE_ID] = {
|
|
554
579
|
"mX": mass_obj.MX,
|
|
555
580
|
"mY": mass_obj.MY,
|
|
556
581
|
"mZ": mass_obj.MZ,
|
|
@@ -567,23 +592,24 @@ class Load:
|
|
|
567
592
|
|
|
568
593
|
@classmethod
|
|
569
594
|
def get(cls):
|
|
570
|
-
|
|
595
|
+
MidasAPI("GET", "/db/nmas")
|
|
571
596
|
|
|
572
597
|
@classmethod
|
|
573
598
|
def delete(cls):
|
|
574
599
|
cls.data = []
|
|
575
|
-
|
|
600
|
+
MidasAPI("DELETE", "/db/nmas")
|
|
576
601
|
|
|
577
602
|
@classmethod
|
|
578
603
|
def sync(cls):
|
|
579
604
|
cls.data = []
|
|
580
605
|
response = cls.get()
|
|
581
606
|
|
|
582
|
-
if response != {'message': ''}:
|
|
607
|
+
if response and response != {'message': ''}:
|
|
583
608
|
nmas_data = response.get('NMAS', {})
|
|
584
|
-
|
|
585
|
-
|
|
609
|
+
|
|
610
|
+
for node_id, item_data in nmas_data.items():
|
|
586
611
|
Load.NodalMass(
|
|
612
|
+
node_id=int(node_id),
|
|
587
613
|
mX=item_data.get('mX'),
|
|
588
614
|
mY=item_data.get('mY'),
|
|
589
615
|
mZ=item_data.get('mZ'),
|
midas_civil/_mapi.py
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import requests
|
|
2
2
|
import sys
|
|
3
|
+
import winreg
|
|
3
4
|
|
|
4
5
|
|
|
5
6
|
def Midas_help():
|
|
@@ -8,6 +9,8 @@ def Midas_help():
|
|
|
8
9
|
print("| HELP MANUAL : https://midas-rnd.github.io/midasapi-python/ |")
|
|
9
10
|
print("---"*22,"\n")
|
|
10
11
|
|
|
12
|
+
|
|
13
|
+
|
|
11
14
|
class MAPI_PRODUCT:
|
|
12
15
|
product = "civil"
|
|
13
16
|
|
|
@@ -19,16 +22,26 @@ class MAPI_PRODUCT:
|
|
|
19
22
|
|
|
20
23
|
class MAPI_KEY:
|
|
21
24
|
"""MAPI key from Civil NX.\n\nEg: MAPI_Key("eadsfjaks568wqehhf.ajkgj345")"""
|
|
22
|
-
data =
|
|
25
|
+
data = ""
|
|
23
26
|
|
|
24
27
|
def __init__(self, mapi_key:str):
|
|
25
|
-
MAPI_KEY.data =
|
|
26
|
-
self.KEY = mapi_key
|
|
27
|
-
MAPI_KEY.data.append(self.KEY)
|
|
28
|
+
MAPI_KEY.data = mapi_key
|
|
28
29
|
|
|
29
30
|
@classmethod
|
|
30
31
|
def get_key(cls):
|
|
31
|
-
|
|
32
|
+
if MAPI_KEY.data == "":
|
|
33
|
+
try:
|
|
34
|
+
key_path = r"Software\\MIDAS\\CVLwNX_US\\CONNECTION"
|
|
35
|
+
registry_key = winreg.OpenKey(winreg.HKEY_CURRENT_USER, key_path, 0, winreg.KEY_READ)
|
|
36
|
+
value = winreg.QueryValueEx(registry_key, "Key")
|
|
37
|
+
my_key = value[0]
|
|
38
|
+
print(' 🔑 MAPI KEY is not defined. MAPI-KEY is taken from Registry entry.')
|
|
39
|
+
MAPI_KEY(my_key)
|
|
40
|
+
except:
|
|
41
|
+
print(f"🔑 MAPI KEY is not defined. Click on Apps > API Settings to copy the MAPI Key.")
|
|
42
|
+
sys.exit(0)
|
|
43
|
+
else:
|
|
44
|
+
my_key = MAPI_KEY.data
|
|
32
45
|
return my_key
|
|
33
46
|
#---------------------------------------------------------------------------------------------------------------
|
|
34
47
|
|
midas_civil/_model.py
CHANGED
|
@@ -10,6 +10,9 @@ from ._section import *
|
|
|
10
10
|
from ._material import *
|
|
11
11
|
from ._thickness import *
|
|
12
12
|
|
|
13
|
+
from ._tendon import *
|
|
14
|
+
from ._result import *
|
|
15
|
+
|
|
13
16
|
class Model:
|
|
14
17
|
|
|
15
18
|
#4 Function to check analysis status & perform analysis if not analyzed
|
|
@@ -238,6 +241,9 @@ class Model:
|
|
|
238
241
|
Group.create()
|
|
239
242
|
Boundary.create()
|
|
240
243
|
Load.create()
|
|
244
|
+
Tendon.create()
|
|
245
|
+
|
|
246
|
+
LoadCombination.create()
|
|
241
247
|
|
|
242
248
|
|
|
243
249
|
|