midas-civil 1.0.3__tar.gz → 1.0.5__tar.gz
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-1.0.3 → midas_civil-1.0.5}/PKG-INFO +1 -1
- {midas_civil-1.0.3 → midas_civil-1.0.5}/midas_civil/__init__.py +17 -11
- midas_civil-1.0.5/midas_civil/_analysiscontrol.py +585 -0
- {midas_civil-1.0.3 → midas_civil-1.0.5}/midas_civil/_element.py +81 -17
- {midas_civil-1.0.3 → midas_civil-1.0.5}/midas_civil/_group.py +3 -3
- {midas_civil-1.0.3 → midas_civil-1.0.5}/midas_civil/_mapi.py +28 -7
- {midas_civil-1.0.3 → midas_civil-1.0.5}/midas_civil/_model.py +1 -0
- midas_civil-1.0.5/midas_civil/_node.py +292 -0
- midas_civil-1.0.5/midas_civil/_section/__init__.py +361 -0
- midas_civil-1.0.5/midas_civil/_section/_compositeSS.py +283 -0
- midas_civil-1.0.5/midas_civil/_section/_dbSecSS.py +43 -0
- midas_civil-1.0.5/midas_civil/_section/_offsetSS.py +53 -0
- midas_civil-1.0.5/midas_civil/_section/_pscSS.py +425 -0
- midas_civil-1.0.5/midas_civil/_section/_unSupp.py +58 -0
- {midas_civil-1.0.3 → midas_civil-1.0.5}/midas_civil.egg-info/PKG-INFO +1 -1
- {midas_civil-1.0.3 → midas_civil-1.0.5}/midas_civil.egg-info/SOURCES.txt +8 -2
- {midas_civil-1.0.3 → midas_civil-1.0.5}/setup.py +1 -1
- midas_civil-1.0.3/midas_civil/_node.py +0 -183
- midas_civil-1.0.3/midas_civil/_section.py +0 -994
- {midas_civil-1.0.3 → midas_civil-1.0.5}/LICENSE +0 -0
- {midas_civil-1.0.3 → midas_civil-1.0.5}/README.md +0 -0
- {midas_civil-1.0.3 → midas_civil-1.0.5}/midas_civil/_boundary.py +0 -0
- {midas_civil-1.0.3 → midas_civil-1.0.5}/midas_civil/_construction.py +0 -0
- {midas_civil-1.0.3 → midas_civil-1.0.5}/midas_civil/_construction_backup.py +0 -0
- {midas_civil-1.0.3 → midas_civil-1.0.5}/midas_civil/_load.py +0 -0
- {midas_civil-1.0.3 → midas_civil-1.0.5}/midas_civil/_material.py +0 -0
- {midas_civil-1.0.3 → midas_civil-1.0.5}/midas_civil/_movingload.py +0 -0
- {midas_civil-1.0.3 → midas_civil-1.0.5}/midas_civil/_result copy.py +0 -0
- {midas_civil-1.0.3 → midas_civil-1.0.5}/midas_civil/_result.py +0 -0
- {midas_civil-1.0.3 → midas_civil-1.0.5}/midas_civil/_result_extract.py +0 -0
- {midas_civil-1.0.3 → midas_civil-1.0.5}/midas_civil/_settlement.py +0 -0
- {midas_civil-1.0.3 → midas_civil-1.0.5}/midas_civil/_temperature.py +0 -0
- {midas_civil-1.0.3 → midas_civil-1.0.5}/midas_civil/_tendon.py +0 -0
- {midas_civil-1.0.3 → midas_civil-1.0.5}/midas_civil/_thickness.py +0 -0
- {midas_civil-1.0.3 → midas_civil-1.0.5}/midas_civil/_utils.py +0 -0
- {midas_civil-1.0.3 → midas_civil-1.0.5}/midas_civil/_view.py +0 -0
- {midas_civil-1.0.3 → midas_civil-1.0.5}/midas_civil.egg-info/dependency_links.txt +0 -0
- {midas_civil-1.0.3 → midas_civil-1.0.5}/midas_civil.egg-info/requires.txt +0 -0
- {midas_civil-1.0.3 → midas_civil-1.0.5}/midas_civil.egg-info/top_level.txt +0 -0
- {midas_civil-1.0.3 → midas_civil-1.0.5}/setup.cfg +0 -0
|
@@ -1,22 +1,24 @@
|
|
|
1
1
|
import requests
|
|
2
|
-
|
|
2
|
+
from ._mapi import *
|
|
3
|
+
_version_ = "1.0.5"
|
|
3
4
|
|
|
4
5
|
|
|
5
6
|
print('')
|
|
6
7
|
print('*'*20,' MIDAS CIVIL-NX PYTHON LIBRARY v',_version_,' 🐍 ','*'*20)
|
|
7
8
|
print('')
|
|
8
9
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
10
|
+
if NX.version_check:
|
|
11
|
+
resp = requests.get("https://pypi.org/pypi/midas_civil/json").json()
|
|
12
|
+
latest_ver = resp["info"]["version"]
|
|
13
|
+
if _version_ != latest_ver:
|
|
14
|
+
print(
|
|
15
|
+
f"⚠️ Warning: You are using v{_version_}, "
|
|
16
|
+
f"but the latest available version is v{latest_ver}.\n"
|
|
17
|
+
f" Run 'pip install midas_civil --upgrade' to update."
|
|
18
|
+
)
|
|
19
|
+
print("-"*85)
|
|
20
|
+
|
|
18
21
|
|
|
19
|
-
from ._mapi import *
|
|
20
22
|
from ._model import *
|
|
21
23
|
from ._boundary import *
|
|
22
24
|
from ._utils import *
|
|
@@ -28,6 +30,8 @@ from ._result import *
|
|
|
28
30
|
|
|
29
31
|
#--- TESTING IMPORTS ---
|
|
30
32
|
from ._material import *
|
|
33
|
+
|
|
34
|
+
# from ._section import *
|
|
31
35
|
from ._section import *
|
|
32
36
|
|
|
33
37
|
from ._result_extract import *
|
|
@@ -40,4 +44,6 @@ from ._view import *
|
|
|
40
44
|
|
|
41
45
|
from ._movingload import*
|
|
42
46
|
from ._settlement import*
|
|
47
|
+
from ._analysiscontrol import*
|
|
48
|
+
|
|
43
49
|
|
|
@@ -0,0 +1,585 @@
|
|
|
1
|
+
from ._mapi import *
|
|
2
|
+
#--------------------------------------------------------------------------------------------------
|
|
3
|
+
|
|
4
|
+
class AnalysisControl:
|
|
5
|
+
|
|
6
|
+
class MainControlData:
|
|
7
|
+
|
|
8
|
+
data = []
|
|
9
|
+
|
|
10
|
+
def __init__(self,
|
|
11
|
+
ardc: bool = True,
|
|
12
|
+
anrc: bool = True,
|
|
13
|
+
iter: int = 20,
|
|
14
|
+
tol: float = 0.001,
|
|
15
|
+
csecf: bool = False,
|
|
16
|
+
trs: bool = True,
|
|
17
|
+
crbar: bool = False,
|
|
18
|
+
bmstress: bool = False,
|
|
19
|
+
clats: bool = False):
|
|
20
|
+
"""
|
|
21
|
+
Main Control Data constructor for analysis control settings.
|
|
22
|
+
|
|
23
|
+
Parameters:
|
|
24
|
+
ardc: Auto Rotational DOF Constraint for Truss/Plane Stress/Solid Elements (default True)
|
|
25
|
+
|
|
26
|
+
anrc: Auto Normal Rotation Constraint for Plate Elements (default True)
|
|
27
|
+
|
|
28
|
+
iter: Number of Iterations/Load Case (default 20)
|
|
29
|
+
|
|
30
|
+
tol: Convergence Tolerance (default 0.001)
|
|
31
|
+
|
|
32
|
+
csecf: Consider Section Stiffness Scale Factor for Stress Calculation (default False)
|
|
33
|
+
|
|
34
|
+
trs: Transfer Reactions of Slave Node to the Master Node (default True)
|
|
35
|
+
|
|
36
|
+
crbar: Consider Reinforcement for Section Stiffness Calculation (default False)
|
|
37
|
+
|
|
38
|
+
bmstress: Calculate Equivalent Beam Stresses (Von-Mises and Max-Shear) (default False)
|
|
39
|
+
|
|
40
|
+
clats: Change Local Axis of Tapered Section for Force/Stress Calculation (default False)
|
|
41
|
+
|
|
42
|
+
Examples:
|
|
43
|
+
# Basic control data with required parameters
|
|
44
|
+
MainControlData(iter=20, tol=0.001)
|
|
45
|
+
|
|
46
|
+
# with multiple options enabled
|
|
47
|
+
MainControlData(
|
|
48
|
+
ardc=True, anrc=True, iter=30, tol=0.0005,
|
|
49
|
+
trs=True, bmstress=True
|
|
50
|
+
)
|
|
51
|
+
"""
|
|
52
|
+
|
|
53
|
+
# Validate required parameters
|
|
54
|
+
if iter is None:
|
|
55
|
+
raise ValueError("iter (Number of Iterations) is required")
|
|
56
|
+
if tol is None:
|
|
57
|
+
raise ValueError("tol (Convergence Tolerance) is required")
|
|
58
|
+
|
|
59
|
+
# ID is always 1
|
|
60
|
+
self.ID = 1
|
|
61
|
+
|
|
62
|
+
# Set parameters
|
|
63
|
+
self.ARDC = ardc
|
|
64
|
+
self.ANRC = anrc
|
|
65
|
+
self.ITER = iter
|
|
66
|
+
self.TOL = tol
|
|
67
|
+
self.CSECF = csecf
|
|
68
|
+
self.TRS = trs
|
|
69
|
+
self.CRBAR = crbar
|
|
70
|
+
self.BMSTRESS = bmstress
|
|
71
|
+
self.CLATS = clats
|
|
72
|
+
|
|
73
|
+
# Add to static list
|
|
74
|
+
AnalysisControl.MainControlData.data.append(self)
|
|
75
|
+
|
|
76
|
+
# Automatically execute the data when instance is created
|
|
77
|
+
self._execute()
|
|
78
|
+
|
|
79
|
+
def _execute(self):
|
|
80
|
+
"""
|
|
81
|
+
Automatically sends the MainControlData to the analysis system when created
|
|
82
|
+
"""
|
|
83
|
+
json_data = {"Assign": {}}
|
|
84
|
+
|
|
85
|
+
control_data = {
|
|
86
|
+
"ARDC": self.ARDC,
|
|
87
|
+
"ANRC": self.ANRC,
|
|
88
|
+
"ITER": self.ITER,
|
|
89
|
+
"TOL": self.TOL,
|
|
90
|
+
"CSECF": self.CSECF,
|
|
91
|
+
"TRS": self.TRS,
|
|
92
|
+
"CRBAR": self.CRBAR,
|
|
93
|
+
"BMSTRESS": self.BMSTRESS,
|
|
94
|
+
"CLATS": self.CLATS
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
json_data["Assign"][str(self.ID)] = control_data
|
|
98
|
+
|
|
99
|
+
MidasAPI("PUT", "/db/actl", json_data)
|
|
100
|
+
|
|
101
|
+
class PDelta:
|
|
102
|
+
"""Create P-Delta Analysis Control Object in Python"""
|
|
103
|
+
data = []
|
|
104
|
+
|
|
105
|
+
def __init__(self,
|
|
106
|
+
iter: int = 5,
|
|
107
|
+
tol: float = 0.00001,
|
|
108
|
+
load_case_data: list = None):
|
|
109
|
+
"""
|
|
110
|
+
P-Delta Analysis Control constructor for geometric nonlinear analysis settings.
|
|
111
|
+
|
|
112
|
+
Parameters:
|
|
113
|
+
iter: Number of Iterations (default 5)
|
|
114
|
+
|
|
115
|
+
tol: Convergence Tolerance (default 0.00001)
|
|
116
|
+
|
|
117
|
+
load_case_data: Load Cases with Scale Factors (required)
|
|
118
|
+
- List of load cases and their corresponding scale factors for P-Delta analysis
|
|
119
|
+
- Format: [["LC1", factor1], ["LC2", factor2], ...]
|
|
120
|
+
|
|
121
|
+
Example:
|
|
122
|
+
|
|
123
|
+
PDelta(iter=5, load_case_data=[["DL", 1.0]])
|
|
124
|
+
|
|
125
|
+
"""
|
|
126
|
+
|
|
127
|
+
# Validate required parameters
|
|
128
|
+
if iter is None:
|
|
129
|
+
raise ValueError("iter (Number of Iterations) is required")
|
|
130
|
+
if load_case_data is None or len(load_case_data) == 0:
|
|
131
|
+
raise ValueError("load_case_data (Load Cases) is required")
|
|
132
|
+
|
|
133
|
+
# Validate load case data format
|
|
134
|
+
for i, case in enumerate(load_case_data):
|
|
135
|
+
if not isinstance(case, list) or len(case) != 2:
|
|
136
|
+
raise ValueError(f"load_case_data[{i}] must be a list with 2 elements [name, factor]")
|
|
137
|
+
if not isinstance(case[0], str):
|
|
138
|
+
raise ValueError(f"load_case_data[{i}][0] (load case name) must be a string")
|
|
139
|
+
if not isinstance(case[1], (int, float)):
|
|
140
|
+
raise ValueError(f"load_case_data[{i}][1] (scale factor) must be a number")
|
|
141
|
+
|
|
142
|
+
# ID is always 1
|
|
143
|
+
self.ID = 1
|
|
144
|
+
|
|
145
|
+
# Set parameters
|
|
146
|
+
self.ITER = iter
|
|
147
|
+
self.TOL = tol
|
|
148
|
+
self.LOAD_CASE_DATA = load_case_data
|
|
149
|
+
|
|
150
|
+
# Add to static list
|
|
151
|
+
AnalysisControl.PDelta.data.append(self)
|
|
152
|
+
|
|
153
|
+
# Automatically execute the data when instance is created
|
|
154
|
+
self._execute()
|
|
155
|
+
|
|
156
|
+
def _execute(self):
|
|
157
|
+
"""
|
|
158
|
+
Automatically sends the P-Delta Analysis Control to the analysis system when created
|
|
159
|
+
"""
|
|
160
|
+
json_data = {"Assign": {}}
|
|
161
|
+
|
|
162
|
+
# Convert load case data to required format
|
|
163
|
+
pdel_cases = []
|
|
164
|
+
for case_name, factor in self.LOAD_CASE_DATA:
|
|
165
|
+
pdel_cases.append({
|
|
166
|
+
"LCNAME": case_name,
|
|
167
|
+
"FACTOR": factor
|
|
168
|
+
})
|
|
169
|
+
|
|
170
|
+
control_data = {
|
|
171
|
+
"ITER": self.ITER,
|
|
172
|
+
"TOL": self.TOL,
|
|
173
|
+
"PDEL_CASES": pdel_cases
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
json_data["Assign"][str(self.ID)] = control_data
|
|
177
|
+
|
|
178
|
+
MidasAPI("PUT", "/db/pdel", json_data)
|
|
179
|
+
|
|
180
|
+
class Buckling:
|
|
181
|
+
"""Create Buckling Analysis Control Object in Python"""
|
|
182
|
+
data = []
|
|
183
|
+
|
|
184
|
+
def __init__(self,
|
|
185
|
+
mode_num: int = None,
|
|
186
|
+
opt_positive: bool = True,
|
|
187
|
+
load_factor_from: float = 0,
|
|
188
|
+
load_factor_to: float = 0,
|
|
189
|
+
opt_sturm_seq: bool = False,
|
|
190
|
+
opt_consider_axial_only: bool = False,
|
|
191
|
+
load_case_data: list = None):
|
|
192
|
+
"""
|
|
193
|
+
Buckling Analysis Control constructor for eigenvalue buckling analysis settings.
|
|
194
|
+
|
|
195
|
+
Parameters:
|
|
196
|
+
mode_num: Number of Modes (required)
|
|
197
|
+
|
|
198
|
+
opt_positive: Load Factor Range Type (default True)
|
|
199
|
+
|
|
200
|
+
load_factor_from: Search From (default 0)
|
|
201
|
+
- Lower bound for load factor search range
|
|
202
|
+
- Only used when opt_positive is False (Search mode)
|
|
203
|
+
|
|
204
|
+
load_factor_to: Search To (default 0)
|
|
205
|
+
- Upper bound for load factor search range
|
|
206
|
+
- Only used when opt_positive is False (Search mode)
|
|
207
|
+
|
|
208
|
+
opt_sturm_seq: Check Sturm Sequence (default False)
|
|
209
|
+
|
|
210
|
+
opt_consider_axial_only: Frame Geometric Stiffness Option (default False)
|
|
211
|
+
|
|
212
|
+
load_case_data: Load Cases with Scale Factors and Types (required)
|
|
213
|
+
- List of load cases with their scale factors and load types
|
|
214
|
+
- Format: [["LC1", factor1, load_type1], ["LC2", factor2, load_type2], ...]
|
|
215
|
+
- Load case name (string), scale factor (number), load type (integer)
|
|
216
|
+
- Load Type: 0=Variable, 1=Constant
|
|
217
|
+
|
|
218
|
+
|
|
219
|
+
Examples:
|
|
220
|
+
Buckling(
|
|
221
|
+
mode_num=8, opt_positive=False,
|
|
222
|
+
load_factor_from=-2.0, load_factor_to=5.0,
|
|
223
|
+
opt_consider_axial_only=True,
|
|
224
|
+
load_case_data=[["Gravity", 1.0, 1], ["Lateral", 1.0, 0]]
|
|
225
|
+
)
|
|
226
|
+
"""
|
|
227
|
+
|
|
228
|
+
# Validate required parameters
|
|
229
|
+
if mode_num is None:
|
|
230
|
+
raise ValueError("mode_num (Number of Modes) is required")
|
|
231
|
+
if load_case_data is None or len(load_case_data) == 0:
|
|
232
|
+
raise ValueError("load_case_data (Load Cases) is required")
|
|
233
|
+
|
|
234
|
+
# Validate load case data format
|
|
235
|
+
for i, case in enumerate(load_case_data):
|
|
236
|
+
if not isinstance(case, list) or len(case) != 3:
|
|
237
|
+
raise ValueError(f"load_case_data[{i}] must be a list with 3 elements [name, factor, load_type]")
|
|
238
|
+
if not isinstance(case[0], str):
|
|
239
|
+
raise ValueError(f"load_case_data[{i}][0] (load case name) must be a string")
|
|
240
|
+
if not isinstance(case[1], (int, float)):
|
|
241
|
+
raise ValueError(f"load_case_data[{i}][1] (scale factor) must be a number")
|
|
242
|
+
if not isinstance(case[2], int) or case[2] not in [0, 1]:
|
|
243
|
+
raise ValueError(f"load_case_data[{i}][2] (load type) must be 0 (Variable) or 1 (Constant)")
|
|
244
|
+
|
|
245
|
+
# ID is always 1
|
|
246
|
+
self.ID = 1
|
|
247
|
+
|
|
248
|
+
# Set parameters
|
|
249
|
+
self.MODE_NUM = mode_num
|
|
250
|
+
self.OPT_POSITIVE = opt_positive
|
|
251
|
+
self.LOAD_FACTOR_FROM = load_factor_from
|
|
252
|
+
self.LOAD_FACTOR_TO = load_factor_to
|
|
253
|
+
self.OPT_STURM_SEQ = opt_sturm_seq
|
|
254
|
+
self.OPT_CONSIDER_AXIAL_ONLY = opt_consider_axial_only
|
|
255
|
+
self.LOAD_CASE_DATA = load_case_data
|
|
256
|
+
|
|
257
|
+
# Add to static list
|
|
258
|
+
AnalysisControl.Buckling.data.append(self)
|
|
259
|
+
|
|
260
|
+
# Automatically execute the data when instance is created
|
|
261
|
+
self._execute()
|
|
262
|
+
|
|
263
|
+
def _execute(self):
|
|
264
|
+
"""
|
|
265
|
+
Automatically sends the Buckling Analysis Control to the analysis system when created
|
|
266
|
+
"""
|
|
267
|
+
json_data = {"Assign": {}}
|
|
268
|
+
|
|
269
|
+
# Convert load case data to required format
|
|
270
|
+
items = []
|
|
271
|
+
for case_name, factor, load_type in self.LOAD_CASE_DATA:
|
|
272
|
+
items.append({
|
|
273
|
+
"LCNAME": case_name,
|
|
274
|
+
"FACTOR": factor,
|
|
275
|
+
"LOAD_TYPE": load_type
|
|
276
|
+
})
|
|
277
|
+
|
|
278
|
+
control_data = {
|
|
279
|
+
"MODE_NUM": self.MODE_NUM,
|
|
280
|
+
"OPT_POSITIVE": self.OPT_POSITIVE,
|
|
281
|
+
"OPT_CONSIDER_AXIAL_ONLY": self.OPT_CONSIDER_AXIAL_ONLY,
|
|
282
|
+
"LOAD_FACTOR_FROM": self.LOAD_FACTOR_FROM,
|
|
283
|
+
"LOAD_FACTOR_TO": self.LOAD_FACTOR_TO,
|
|
284
|
+
"OPT_STURM_SEQ": self.OPT_STURM_SEQ,
|
|
285
|
+
"ITEMS": items
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
json_data["Assign"][str(self.ID)] = control_data
|
|
289
|
+
|
|
290
|
+
MidasAPI("PUT", "/db/buck", json_data)
|
|
291
|
+
|
|
292
|
+
|
|
293
|
+
class EigenValue:
|
|
294
|
+
"""Create Eigen Vector Analysis Control Object in Python"""
|
|
295
|
+
data = []
|
|
296
|
+
|
|
297
|
+
def __init__(self,
|
|
298
|
+
analysis_type: str = None,
|
|
299
|
+
# EIGEN specific parameters
|
|
300
|
+
ifreq: int = 1,
|
|
301
|
+
iiter: int = 20,
|
|
302
|
+
idim: int = 1,
|
|
303
|
+
tol: float = 0,
|
|
304
|
+
# LANCZOS specific parameters
|
|
305
|
+
frequency_range: list = None,
|
|
306
|
+
bstrum: bool = False,
|
|
307
|
+
bminmax: bool = None,
|
|
308
|
+
frmin: float = None,
|
|
309
|
+
frmax: float = None,
|
|
310
|
+
# RITZ specific parameters
|
|
311
|
+
bincnl: bool = False,
|
|
312
|
+
ignum: int = None,
|
|
313
|
+
load_vector: list = None,
|
|
314
|
+
vritz: list = None):
|
|
315
|
+
"""
|
|
316
|
+
Eigen Vector Analysis Control
|
|
317
|
+
|
|
318
|
+
Parameters:
|
|
319
|
+
analysis_type: Type of Analysis (required)
|
|
320
|
+
- "EIGEN": Subspace Iteration
|
|
321
|
+
- "LANCZOS": Lanczos
|
|
322
|
+
- "RITZ": Ritz Vectors
|
|
323
|
+
|
|
324
|
+
# For EIGEN:
|
|
325
|
+
ifreq: Number of Frequencies (required for EIGEN)
|
|
326
|
+
iiter: Number of Iterations (required for EIGEN)
|
|
327
|
+
idim: Subspace Dimension (default 0, optional for EIGEN)
|
|
328
|
+
tol: Convergence Tolerance (default 0, optional for EIGEN)
|
|
329
|
+
|
|
330
|
+
# For LANCZOS :
|
|
331
|
+
frequency_range: Frequency Range [frmin, frmax] (optional for LANCZOS)
|
|
332
|
+
- If provided, automatically sets bMINMAX=True
|
|
333
|
+
- Format: [min_freq, max_freq]
|
|
334
|
+
bstrum: Sturm Sequence Check (default False, optional for LANCZOS)
|
|
335
|
+
|
|
336
|
+
# For RITZ type only:
|
|
337
|
+
bincnl: Include GL-link Force Vectors (default False, optional for RITZ)
|
|
338
|
+
ignum: Number of Generations for Each GL-link Force (required for RITZ)
|
|
339
|
+
load_vector: Load Cases in simple format (required for RITZ)
|
|
340
|
+
- Format: [["case_or_acc", nog], ...]
|
|
341
|
+
- For ground acceleration: ["ACCX"/"ACCY"/"ACCZ", nog]
|
|
342
|
+
- For load case: ["case_name", nog]
|
|
343
|
+
|
|
344
|
+
Examples:
|
|
345
|
+
# EIGEN analysis
|
|
346
|
+
EigenValue(
|
|
347
|
+
analysis_type="EIGEN",
|
|
348
|
+
ifreq=10,
|
|
349
|
+
iiter=20,
|
|
350
|
+
idim=1,
|
|
351
|
+
tol=1e-10
|
|
352
|
+
)
|
|
353
|
+
|
|
354
|
+
# LANCZOS analysis
|
|
355
|
+
EigenValue(
|
|
356
|
+
analysis_type="LANCZOS",
|
|
357
|
+
ifreq=15,
|
|
358
|
+
frequency_range=[0, 1600], # Automatically sets bMINMAX=True
|
|
359
|
+
bstrum=True
|
|
360
|
+
)
|
|
361
|
+
|
|
362
|
+
# RITZ analysis
|
|
363
|
+
EigenValue(
|
|
364
|
+
analysis_type="RITZ",
|
|
365
|
+
bincnl=False,
|
|
366
|
+
ignum=1,
|
|
367
|
+
load_vector=[["DL", 1], ["ACCX", 1]] # Simple format
|
|
368
|
+
)
|
|
369
|
+
"""
|
|
370
|
+
|
|
371
|
+
# Validate required parameters
|
|
372
|
+
if analysis_type is None:
|
|
373
|
+
raise ValueError("analysis_type is required")
|
|
374
|
+
if analysis_type not in ["EIGEN", "LANCZOS", "RITZ"]:
|
|
375
|
+
raise ValueError("analysis_type must be 'EIGEN', 'LANCZOS', or 'RITZ'")
|
|
376
|
+
|
|
377
|
+
# Validate type-specific required parameters
|
|
378
|
+
if analysis_type in ["EIGEN"]:
|
|
379
|
+
if ifreq is None:
|
|
380
|
+
raise ValueError("ifreq (Number of Frequencies) is required for EIGEN")
|
|
381
|
+
if iiter is None:
|
|
382
|
+
raise ValueError("iiter (Number of Iterations) is required for EIGEN")
|
|
383
|
+
|
|
384
|
+
# Handle LANCZOS parameters
|
|
385
|
+
if analysis_type == "LANCZOS":
|
|
386
|
+
# Handle new frequency_range format
|
|
387
|
+
if frequency_range is not None:
|
|
388
|
+
if not isinstance(frequency_range, list) or len(frequency_range) != 2:
|
|
389
|
+
raise ValueError("frequency_range must be a list with exactly 2 elements [frmin, frmax]")
|
|
390
|
+
if frequency_range[0] >= frequency_range[1]:
|
|
391
|
+
raise ValueError("frmin must be less than frmax in frequency_range")
|
|
392
|
+
|
|
393
|
+
# Automatically set parameters
|
|
394
|
+
bminmax = True
|
|
395
|
+
frmin = frequency_range[0]
|
|
396
|
+
frmax = frequency_range[1]
|
|
397
|
+
else:
|
|
398
|
+
# Use legacy parameters or defaults
|
|
399
|
+
if bminmax is None:
|
|
400
|
+
bminmax = False
|
|
401
|
+
if bminmax and (frmin is None or frmax is None):
|
|
402
|
+
raise ValueError("frmin and frmax are required when bminmax is True for LANCZOS")
|
|
403
|
+
if frmin is not None and frmax is not None and frmin >= frmax:
|
|
404
|
+
raise ValueError("frmin must be less than frmax")
|
|
405
|
+
|
|
406
|
+
# Handle RITZ parameters
|
|
407
|
+
if analysis_type == "RITZ":
|
|
408
|
+
if ignum is None:
|
|
409
|
+
raise ValueError("ignum (Number of Generations) is required for RITZ")
|
|
410
|
+
|
|
411
|
+
# Handle new load_vector format
|
|
412
|
+
if load_vector is not None:
|
|
413
|
+
if not isinstance(load_vector, list) or len(load_vector) == 0:
|
|
414
|
+
raise ValueError("load_vector must be a non-empty list")
|
|
415
|
+
|
|
416
|
+
# Convert load_vector to vritz format
|
|
417
|
+
vritz = []
|
|
418
|
+
ground_acc_types = ["ACCX", "ACCY", "ACCZ"]
|
|
419
|
+
|
|
420
|
+
for i, item in enumerate(load_vector):
|
|
421
|
+
if not isinstance(item, list) or len(item) != 2:
|
|
422
|
+
raise ValueError(f"load_vector[{i}] must be a list with exactly 2 elements [name, nog]")
|
|
423
|
+
|
|
424
|
+
name, nog = item
|
|
425
|
+
if not isinstance(name, str):
|
|
426
|
+
raise ValueError(f"load_vector[{i}][0] (name) must be a string")
|
|
427
|
+
if not isinstance(nog, int) or nog <= 0:
|
|
428
|
+
raise ValueError(f"load_vector[{i}][1] (nog) must be a positive integer")
|
|
429
|
+
|
|
430
|
+
# Determine if it's ground acceleration or case
|
|
431
|
+
if name in ground_acc_types:
|
|
432
|
+
vritz.append({
|
|
433
|
+
"KIND": "GROUND",
|
|
434
|
+
"GROUND": name,
|
|
435
|
+
"iNOG": nog
|
|
436
|
+
})
|
|
437
|
+
else:
|
|
438
|
+
vritz.append({
|
|
439
|
+
"KIND": "CASE",
|
|
440
|
+
"CASE": name,
|
|
441
|
+
"iNOG": nog
|
|
442
|
+
})
|
|
443
|
+
|
|
444
|
+
# Use legacy vritz if provided and load_vector is not
|
|
445
|
+
elif vritz is not None:
|
|
446
|
+
if not isinstance(vritz, list) or len(vritz) == 0:
|
|
447
|
+
raise ValueError("vritz (Load Cases) must be a non-empty list")
|
|
448
|
+
|
|
449
|
+
# Validate legacy vritz format
|
|
450
|
+
for i, case in enumerate(vritz):
|
|
451
|
+
if not isinstance(case, dict):
|
|
452
|
+
raise ValueError(f"vritz[{i}] must be a dictionary")
|
|
453
|
+
if "KIND" not in case:
|
|
454
|
+
raise ValueError(f"vritz[{i}] must have 'KIND' key")
|
|
455
|
+
if case["KIND"] not in ["CASE", "GROUND"]:
|
|
456
|
+
raise ValueError(f"vritz[{i}]['KIND'] must be 'CASE' or 'GROUND'")
|
|
457
|
+
|
|
458
|
+
if case["KIND"] == "GROUND":
|
|
459
|
+
if "GROUND" not in case or case["GROUND"] not in ["ACCX", "ACCY", "ACCZ"]:
|
|
460
|
+
raise ValueError(f"vritz[{i}] with KIND='GROUND' must have GROUND='ACCX'/'ACCY'/'ACCZ'")
|
|
461
|
+
elif case["KIND"] == "CASE":
|
|
462
|
+
if "CASE" not in case:
|
|
463
|
+
raise ValueError(f"vritz[{i}] with KIND='CASE' must have 'CASE' key")
|
|
464
|
+
|
|
465
|
+
if "iNOG" not in case:
|
|
466
|
+
raise ValueError(f"vritz[{i}] must have 'iNOG' key")
|
|
467
|
+
else:
|
|
468
|
+
raise ValueError("Either load_vector or vritz is required for RITZ analysis")
|
|
469
|
+
|
|
470
|
+
# ID is always 1
|
|
471
|
+
self.ID = 1
|
|
472
|
+
|
|
473
|
+
# Set parameters
|
|
474
|
+
self.TYPE = analysis_type
|
|
475
|
+
self.iFREQ = ifreq
|
|
476
|
+
self.iITER = iiter
|
|
477
|
+
self.iDIM = idim
|
|
478
|
+
self.TOL = tol
|
|
479
|
+
self.bMINMAX = bminmax
|
|
480
|
+
self.FRMIN = frmin
|
|
481
|
+
self.FRMAX = frmax
|
|
482
|
+
self.bSTRUM = bstrum
|
|
483
|
+
self.bINCNL = bincnl
|
|
484
|
+
self.iGNUM = ignum
|
|
485
|
+
self.vRITZ = vritz
|
|
486
|
+
|
|
487
|
+
# Add to static list
|
|
488
|
+
AnalysisControl.EigenValue.data.append(self)
|
|
489
|
+
|
|
490
|
+
# Automatically execute the data when instance is created
|
|
491
|
+
self._execute()
|
|
492
|
+
|
|
493
|
+
def _execute(self):
|
|
494
|
+
"""
|
|
495
|
+
Automatically sends the Eigen Vector Analysis Control to the analysis system when created
|
|
496
|
+
"""
|
|
497
|
+
json_data = {"Assign": {}}
|
|
498
|
+
|
|
499
|
+
control_data = {"TYPE": self.TYPE}
|
|
500
|
+
|
|
501
|
+
if self.TYPE in ["EIGEN", "LANCZOS"]:
|
|
502
|
+
control_data.update({
|
|
503
|
+
"iFREQ": self.iFREQ,
|
|
504
|
+
"iITER": self.iITER,
|
|
505
|
+
"iDIM": self.iDIM,
|
|
506
|
+
"TOL": self.TOL
|
|
507
|
+
})
|
|
508
|
+
|
|
509
|
+
if self.TYPE == "LANCZOS":
|
|
510
|
+
control_data.update({
|
|
511
|
+
"bMINMAX": self.bMINMAX,
|
|
512
|
+
"FRMIN": self.FRMIN,
|
|
513
|
+
"FRMAX": self.FRMAX,
|
|
514
|
+
"bSTRUM": self.bSTRUM
|
|
515
|
+
})
|
|
516
|
+
|
|
517
|
+
elif self.TYPE == "RITZ":
|
|
518
|
+
control_data.update({
|
|
519
|
+
"bINCNL": self.bINCNL,
|
|
520
|
+
"iGNUM": self.iGNUM,
|
|
521
|
+
"vRITZ": self.vRITZ
|
|
522
|
+
})
|
|
523
|
+
|
|
524
|
+
json_data["Assign"][str(self.ID)] = control_data
|
|
525
|
+
|
|
526
|
+
MidasAPI("PUT", "/db/eigv", json_data)
|
|
527
|
+
|
|
528
|
+
class Settlement:
|
|
529
|
+
|
|
530
|
+
data = []
|
|
531
|
+
|
|
532
|
+
def __init__(self,
|
|
533
|
+
concurrent_calc: bool = True,
|
|
534
|
+
concurrent_link: bool = True):
|
|
535
|
+
"""
|
|
536
|
+
Settlement Analysis Control constructor for settlement analysis settings.
|
|
537
|
+
|
|
538
|
+
Parameters:
|
|
539
|
+
concurrent_calc: Plate Concurrent Force (default True, optional)
|
|
540
|
+
- Active: true
|
|
541
|
+
- Inactive: false
|
|
542
|
+
|
|
543
|
+
concurrent_link: Elastic / General Links Concurrent Force (default True, optional)
|
|
544
|
+
- Active: true
|
|
545
|
+
- Inactive: false
|
|
546
|
+
|
|
547
|
+
Examples:
|
|
548
|
+
# with both Optional value
|
|
549
|
+
Settlement()
|
|
550
|
+
|
|
551
|
+
#without Optional value
|
|
552
|
+
Settlement(
|
|
553
|
+
concurrent_calc=True,
|
|
554
|
+
concurrent_link=False
|
|
555
|
+
)
|
|
556
|
+
|
|
557
|
+
"""
|
|
558
|
+
|
|
559
|
+
# ID is always 1
|
|
560
|
+
self.ID = 1
|
|
561
|
+
|
|
562
|
+
# Set parameters
|
|
563
|
+
self.CONCURRENT_CALC = concurrent_calc
|
|
564
|
+
self.CONCURRENT_LINK = concurrent_link
|
|
565
|
+
|
|
566
|
+
# Add to static list
|
|
567
|
+
AnalysisControl.Settlement.data.append(self)
|
|
568
|
+
|
|
569
|
+
# Automatically execute the data when instance is created
|
|
570
|
+
self._execute()
|
|
571
|
+
|
|
572
|
+
def _execute(self):
|
|
573
|
+
"""
|
|
574
|
+
Automatically sends the Settlement Analysis Control to the analysis system when created
|
|
575
|
+
"""
|
|
576
|
+
json_data = {"Assign": {}}
|
|
577
|
+
|
|
578
|
+
control_data = {
|
|
579
|
+
"CONCURRENT_CALC": self.CONCURRENT_CALC,
|
|
580
|
+
"CONCURRENT_LINK": self.CONCURRENT_LINK
|
|
581
|
+
}
|
|
582
|
+
|
|
583
|
+
json_data["Assign"][str(self.ID)] = control_data
|
|
584
|
+
|
|
585
|
+
MidasAPI("PUT", "/db/smct", json_data)
|