midas-civil 0.0.9__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/__init__.py +2 -3
- midas_civil/_boundary.py +8 -2
- midas_civil/_construction.py +385 -381
- midas_civil/_construction_backup.py +415 -0
- midas_civil/_group.py +1 -1
- midas_civil/_load.py +325 -2
- midas_civil/_model.py +38 -0
- midas_civil/_result copy.py +488 -0
- midas_civil/_result.py +30 -363
- midas_civil/_result_extract.py +58 -1
- midas_civil/_temperature.py +353 -0
- {midas_civil-0.0.9.dist-info → midas_civil-0.1.0.dist-info}/METADATA +1 -1
- midas_civil-0.1.0.dist-info/RECORD +23 -0
- midas_civil-0.0.9.dist-info/RECORD +0 -20
- {midas_civil-0.0.9.dist-info → midas_civil-0.1.0.dist-info}/WHEEL +0 -0
- {midas_civil-0.0.9.dist-info → midas_civil-0.1.0.dist-info}/licenses/LICENSE +0 -0
- {midas_civil-0.0.9.dist-info → midas_civil-0.1.0.dist-info}/top_level.txt +0 -0
midas_civil/_load.py
CHANGED
|
@@ -122,6 +122,11 @@ class Load:
|
|
|
122
122
|
def get():
|
|
123
123
|
return MidasAPI("GET","/db/BODF")
|
|
124
124
|
|
|
125
|
+
@classmethod
|
|
126
|
+
def delete(cls):
|
|
127
|
+
cls.data=[]
|
|
128
|
+
return MidasAPI("DELETE","/db/BODF")
|
|
129
|
+
|
|
125
130
|
@staticmethod
|
|
126
131
|
def sync():
|
|
127
132
|
a = Load.SW.get()
|
|
@@ -264,7 +269,8 @@ class Load:
|
|
|
264
269
|
D = (D + [0] * 4)[:4]
|
|
265
270
|
P = (P + [0] * 4)[:4]
|
|
266
271
|
if P == [0, 0, 0, 0]: P = [value, value, 0, 0]
|
|
267
|
-
if eccn_type
|
|
272
|
+
if eccn_type not in (0, 1):
|
|
273
|
+
eccn_type = 1
|
|
268
274
|
if direction not in ("GX", "GY", "GZ", "LX", "LY", "LZ"): direction = "GZ"
|
|
269
275
|
if eccn_dir not in ("GX", "GY", "GZ", "LX", "LY", "LZ"): eccn_dir = "LY"
|
|
270
276
|
if cmd not in ("BEAM", "LINE", "TYPICAL"): cmd = "BEAM"
|
|
@@ -381,4 +387,321 @@ class Load:
|
|
|
381
387
|
Load.Beam(i,a['BMLD'][i]['ITEMS'][j]['LCNAME'], a['BMLD'][i]['ITEMS'][j]['P'][0], a['BMLD'][i]['ITEMS'][j]['GROUP_NAME'],
|
|
382
388
|
a['BMLD'][i]['ITEMS'][j]['DIRECTION'], a['BMLD'][i]['ITEMS'][j]['ID'], a['BMLD'][i]['ITEMS'][j]['D'], a['BMLD'][i]['ITEMS'][j]['P'],
|
|
383
389
|
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'])
|
|
384
|
-
|
|
390
|
+
|
|
391
|
+
|
|
392
|
+
#-------------------------------- Load to Mass ------------------------------------------------------------
|
|
393
|
+
|
|
394
|
+
#20 Class to add Load to Mass:
|
|
395
|
+
class LoadToMass:
|
|
396
|
+
"""Creates load to mass conversion and converts to JSON format.
|
|
397
|
+
Example: LoadToMass("Z", ["DL", "LL"], [1.0, 0.5])
|
|
398
|
+
"""
|
|
399
|
+
data = []
|
|
400
|
+
|
|
401
|
+
def __init__(self, dir, load_case, load_factor=None, nodal_load=True, beam_load=True,
|
|
402
|
+
floor_load=True, pressure=True, gravity=9.806):
|
|
403
|
+
"""
|
|
404
|
+
dir (str): Mass Direction - "X", "Y", "Z", "XY", "YZ", "XZ", "XYZ"
|
|
405
|
+
load_case (list): List of load case names
|
|
406
|
+
load_factor (list, optional): List of scale factors corresponding to load cases.
|
|
407
|
+
If None or shorter than load_case, remaining factors default to 1.0
|
|
408
|
+
nodal_load (bool): Include nodal loads. Defaults to True
|
|
409
|
+
beam_load (bool): Include beam loads. Defaults to True
|
|
410
|
+
floor_load (bool): Include floor loads. Defaults to True
|
|
411
|
+
pressure (bool): Include pressure loads. Defaults to True
|
|
412
|
+
gravity (float): Gravity acceleration. Defaults to 9.806
|
|
413
|
+
"""
|
|
414
|
+
|
|
415
|
+
# Validate direction
|
|
416
|
+
valid_directions = ["X", "Y", "Z", "XY", "YZ", "XZ", "XYZ"]
|
|
417
|
+
if dir not in valid_directions:
|
|
418
|
+
dir = "XYZ" # Default to XYZ if invalid
|
|
419
|
+
|
|
420
|
+
# Ensure load_case is a list
|
|
421
|
+
if not isinstance(load_case, list):
|
|
422
|
+
load_case = [load_case]
|
|
423
|
+
|
|
424
|
+
# Handle load_factor - ensure it matches load_case length
|
|
425
|
+
if load_factor is None:
|
|
426
|
+
load_factor = [1.0] * len(load_case)
|
|
427
|
+
elif not isinstance(load_factor, list):
|
|
428
|
+
load_factor = [load_factor]
|
|
429
|
+
|
|
430
|
+
# Pad load_factor with 1.0 if shorter than load_case
|
|
431
|
+
while len(load_factor) < len(load_case):
|
|
432
|
+
load_factor.append(1.0)
|
|
433
|
+
|
|
434
|
+
# Check if load cases exist - give warning if not
|
|
435
|
+
for case in load_case:
|
|
436
|
+
chk = 0
|
|
437
|
+
for i in Load_Case.cases:
|
|
438
|
+
if case in i.NAME:
|
|
439
|
+
chk = 1
|
|
440
|
+
if chk == 0:
|
|
441
|
+
print(f"Warning: Load case '{case}' does not exist!")
|
|
442
|
+
|
|
443
|
+
self.DIR = dir
|
|
444
|
+
self.LOAD_CASE = load_case
|
|
445
|
+
self.LOAD_FACTOR = load_factor
|
|
446
|
+
self.NODAL = nodal_load
|
|
447
|
+
self.BEAM = beam_load
|
|
448
|
+
self.FLOOR = floor_load
|
|
449
|
+
self.PRESSURE = pressure
|
|
450
|
+
self.GRAVITY = gravity
|
|
451
|
+
|
|
452
|
+
Load.LoadToMass.data.append(self)
|
|
453
|
+
|
|
454
|
+
@classmethod
|
|
455
|
+
def json(cls):
|
|
456
|
+
json_data = {"Assign": {}}
|
|
457
|
+
|
|
458
|
+
for load_obj in enumerate(cls.data):
|
|
459
|
+
# Create vLC array with load case names and factors
|
|
460
|
+
vlc_array = []
|
|
461
|
+
for i, case_name in enumerate(load_obj.LOAD_CASE):
|
|
462
|
+
vlc_array.append({
|
|
463
|
+
"LCNAME": case_name,
|
|
464
|
+
"FACTOR": load_obj.LOAD_FACTOR[i]
|
|
465
|
+
})
|
|
466
|
+
|
|
467
|
+
json_data["Assign"]["1"] = {
|
|
468
|
+
"DIR": load_obj.DIR,
|
|
469
|
+
"bNODAL": load_obj.NODAL,
|
|
470
|
+
"bBEAM": load_obj.BEAM,
|
|
471
|
+
"bFLOOR": load_obj.FLOOR,
|
|
472
|
+
"bPRES": load_obj.PRESSURE,
|
|
473
|
+
"GRAV": load_obj.GRAVITY,
|
|
474
|
+
"vLC": vlc_array
|
|
475
|
+
}
|
|
476
|
+
|
|
477
|
+
return json_data
|
|
478
|
+
|
|
479
|
+
@classmethod
|
|
480
|
+
def create(cls):
|
|
481
|
+
return MidasAPI("PUT", "/db/ltom", cls.json())
|
|
482
|
+
|
|
483
|
+
@classmethod
|
|
484
|
+
def get(cls):
|
|
485
|
+
return MidasAPI("GET", "/db/ltom")
|
|
486
|
+
|
|
487
|
+
@classmethod
|
|
488
|
+
def delete(cls):
|
|
489
|
+
cls.data = []
|
|
490
|
+
return MidasAPI("DELETE", "/db/ltom")
|
|
491
|
+
|
|
492
|
+
@classmethod
|
|
493
|
+
def sync(cls):
|
|
494
|
+
cls.data = []
|
|
495
|
+
response = cls.get()
|
|
496
|
+
|
|
497
|
+
if response != {'message': ''}:
|
|
498
|
+
for key, item_data in response.get('LTOM', {}).items():
|
|
499
|
+
# Extract load cases and factors from vLC array
|
|
500
|
+
load_cases = []
|
|
501
|
+
load_factors = []
|
|
502
|
+
|
|
503
|
+
for lc_item in item_data.get('vLC'):
|
|
504
|
+
load_cases.append(lc_item.get('LCNAME'))
|
|
505
|
+
load_factors.append(lc_item.get('FACTOR'))
|
|
506
|
+
|
|
507
|
+
# Create LoadToMass object
|
|
508
|
+
Load.LoadToMass(
|
|
509
|
+
dir=item_data.get('DIR'),
|
|
510
|
+
load_case=load_cases,
|
|
511
|
+
load_factor=load_factors,
|
|
512
|
+
nodal_load=item_data.get('bNODAL'),
|
|
513
|
+
beam_load=item_data.get('bBEAM'),
|
|
514
|
+
floor_load=item_data.get('bFLOOR'),
|
|
515
|
+
pressure=item_data.get('bPRES'),
|
|
516
|
+
gravity=item_data.get('GRAV')
|
|
517
|
+
)
|
|
518
|
+
|
|
519
|
+
#-----------------------------------------------------------NodalMass-----------------
|
|
520
|
+
#21NodalMass
|
|
521
|
+
|
|
522
|
+
class NodalMass:
|
|
523
|
+
"""Creates nodal mass and converts to JSON format.
|
|
524
|
+
Example: NodalMass(1.5, 2.0, 3.0, 0.1, 0.2, 0.3)
|
|
525
|
+
"""
|
|
526
|
+
data = []
|
|
527
|
+
|
|
528
|
+
def __init__(self, mX, mY=0, mZ=0, rmX=0, rmY=0, rmZ=0):
|
|
529
|
+
"""
|
|
530
|
+
mX (float): Translational Lumped Mass in GCS X-direction (Required)
|
|
531
|
+
mY (float): Translational Lumped Mass in GCS Y-direction. Defaults to 0
|
|
532
|
+
mZ (float): Translational Lumped Mass in GCS Z-direction. Defaults to 0
|
|
533
|
+
rmX (float): Rotational Mass Moment of Inertia about GCS X-axis. Defaults to 0
|
|
534
|
+
rmY (float): Rotational Mass Moment of Inertia about GCS Y-axis. Defaults to 0
|
|
535
|
+
rmZ (float): Rotational Mass Moment of Inertia about GCS Z-axis. Defaults to 0
|
|
536
|
+
"""
|
|
537
|
+
self.MX = mX
|
|
538
|
+
self.MY = mY
|
|
539
|
+
self.MZ = mZ
|
|
540
|
+
self.RMX = rmX
|
|
541
|
+
self.RMY = rmY
|
|
542
|
+
self.RMZ = rmZ
|
|
543
|
+
|
|
544
|
+
Load.NodalMass.data.append(self)
|
|
545
|
+
|
|
546
|
+
@classmethod
|
|
547
|
+
def json(cls):
|
|
548
|
+
json_data = {"Assign": {}}
|
|
549
|
+
|
|
550
|
+
# Use the last added mass data (or first if only one exists)
|
|
551
|
+
if cls.data:
|
|
552
|
+
mass_obj = cls.data[-1] # Get the most recent mass object
|
|
553
|
+
json_data["Assign"]["1"] = {
|
|
554
|
+
"mX": mass_obj.MX,
|
|
555
|
+
"mY": mass_obj.MY,
|
|
556
|
+
"mZ": mass_obj.MZ,
|
|
557
|
+
"rmX": mass_obj.RMX,
|
|
558
|
+
"rmY": mass_obj.RMY,
|
|
559
|
+
"rmZ": mass_obj.RMZ
|
|
560
|
+
}
|
|
561
|
+
|
|
562
|
+
return json_data
|
|
563
|
+
|
|
564
|
+
@classmethod
|
|
565
|
+
def create(cls):
|
|
566
|
+
return MidasAPI("PUT", "/db/nmas", cls.json())
|
|
567
|
+
|
|
568
|
+
@classmethod
|
|
569
|
+
def get(cls):
|
|
570
|
+
return MidasAPI("GET", "/db/nmas")
|
|
571
|
+
|
|
572
|
+
@classmethod
|
|
573
|
+
def delete(cls):
|
|
574
|
+
cls.data = []
|
|
575
|
+
return MidasAPI("DELETE", "/db/nmas")
|
|
576
|
+
|
|
577
|
+
@classmethod
|
|
578
|
+
def sync(cls):
|
|
579
|
+
cls.data = []
|
|
580
|
+
response = cls.get()
|
|
581
|
+
|
|
582
|
+
if response != {'message': ''}:
|
|
583
|
+
nmas_data = response.get('NMAS', {})
|
|
584
|
+
if "1" in nmas_data:
|
|
585
|
+
item_data = nmas_data["1"]
|
|
586
|
+
Load.NodalMass(
|
|
587
|
+
mX=item_data.get('mX'),
|
|
588
|
+
mY=item_data.get('mY'),
|
|
589
|
+
mZ=item_data.get('mZ'),
|
|
590
|
+
rmX=item_data.get('rmX'),
|
|
591
|
+
rmY=item_data.get('rmY'),
|
|
592
|
+
rmZ=item_data.get('rmZ')
|
|
593
|
+
)
|
|
594
|
+
|
|
595
|
+
#-----------------------------------------------------------Specified Displacement-------------------------------------------------
|
|
596
|
+
class SpDisp:
|
|
597
|
+
"""Creates specified displacement loads and converts to JSON format.
|
|
598
|
+
Example: SpDisp(10, "LL", "Group1", [1.5, 1.5, 1.5, 1.5, 0.5, 0.5])
|
|
599
|
+
"""
|
|
600
|
+
data = []
|
|
601
|
+
|
|
602
|
+
def __init__(self, node, load_case, load_group="", values=[0, 0, 0, 0, 0, 0], id=""):
|
|
603
|
+
"""
|
|
604
|
+
node (int): Node number (Required)
|
|
605
|
+
load_case (str): Load case name (Required)
|
|
606
|
+
load_group (str, optional): Load group name. Defaults to ""
|
|
607
|
+
values (list): Displacement values [Dx, Dy, Dz, Rx, Ry, Rz]. Defaults to [0, 0, 0, 0, 0, 0]
|
|
608
|
+
id (str, optional): Load ID. Defaults to auto-generated
|
|
609
|
+
"""
|
|
610
|
+
|
|
611
|
+
# Check if load case exists - give warning if not
|
|
612
|
+
chk = 0
|
|
613
|
+
for i in Load_Case.cases:
|
|
614
|
+
if load_case in i.NAME:
|
|
615
|
+
chk = 1
|
|
616
|
+
if chk == 0:
|
|
617
|
+
print(f"Warning: Load case '{load_case}' does not exist!")
|
|
618
|
+
|
|
619
|
+
# Check if load group exists and create if specified
|
|
620
|
+
if load_group != "":
|
|
621
|
+
chk = 0
|
|
622
|
+
a = [v['NAME'] for v in Group.Load.json()["Assign"].values()]
|
|
623
|
+
if load_group in a:
|
|
624
|
+
chk = 1
|
|
625
|
+
if chk == 0:
|
|
626
|
+
print(f"Warning: Load group '{load_group}' does not exist!")
|
|
627
|
+
|
|
628
|
+
# Ensure values is a list of 6 elements [Dx, Dy, Dz, Rx, Ry, Rz]
|
|
629
|
+
if not isinstance(values, list):
|
|
630
|
+
values = [0, 0, 0, 0, 0, 0]
|
|
631
|
+
|
|
632
|
+
# Pad or truncate to exactly 6 values
|
|
633
|
+
values = (values + [0] * 6)[:6]
|
|
634
|
+
|
|
635
|
+
self.NODE = node
|
|
636
|
+
self.LCN = load_case
|
|
637
|
+
self.LDGR = load_group
|
|
638
|
+
self.VALUES = values
|
|
639
|
+
|
|
640
|
+
if id == "":
|
|
641
|
+
id = len(Load.SpDisp.data) + 1
|
|
642
|
+
self.ID = id
|
|
643
|
+
|
|
644
|
+
Load.SpDisp.data.append(self)
|
|
645
|
+
|
|
646
|
+
@classmethod
|
|
647
|
+
def json(cls):
|
|
648
|
+
json_data = {"Assign": {}}
|
|
649
|
+
|
|
650
|
+
for i in cls.data:
|
|
651
|
+
if i.NODE not in list(json_data["Assign"].keys()):
|
|
652
|
+
json_data["Assign"][i.NODE] = {"ITEMS": []}
|
|
653
|
+
|
|
654
|
+
# Create VALUES array with OPT_FLAG logic
|
|
655
|
+
values_array = []
|
|
656
|
+
displacement_labels = ["Dx", "Dy", "Dz", "Rx", "Ry", "Rz"]
|
|
657
|
+
|
|
658
|
+
for idx, value in enumerate(i.VALUES):
|
|
659
|
+
values_array.append({
|
|
660
|
+
"OPT_FLAG": value != 0, # True if value > 0, False if value = 0
|
|
661
|
+
"DISPLACEMENT": float(value)
|
|
662
|
+
})
|
|
663
|
+
|
|
664
|
+
json_data["Assign"][i.NODE]["ITEMS"].append({
|
|
665
|
+
"ID": i.ID,
|
|
666
|
+
"LCNAME": i.LCN,
|
|
667
|
+
"GROUP_NAME": i.LDGR,
|
|
668
|
+
"VALUES": values_array
|
|
669
|
+
})
|
|
670
|
+
|
|
671
|
+
return json_data
|
|
672
|
+
|
|
673
|
+
@classmethod
|
|
674
|
+
def create(cls):
|
|
675
|
+
return MidasAPI("PUT", "/db/sdsp", cls.json())
|
|
676
|
+
|
|
677
|
+
@classmethod
|
|
678
|
+
def get(cls):
|
|
679
|
+
return MidasAPI("GET", "/db/sdsp")
|
|
680
|
+
|
|
681
|
+
@classmethod
|
|
682
|
+
def delete(cls):
|
|
683
|
+
cls.data = []
|
|
684
|
+
return MidasAPI("DELETE", "/db/sdsp")
|
|
685
|
+
|
|
686
|
+
@classmethod
|
|
687
|
+
def sync(cls):
|
|
688
|
+
cls.data = []
|
|
689
|
+
response = cls.get()
|
|
690
|
+
|
|
691
|
+
if response != {'message': ''}:
|
|
692
|
+
for node_key in response['SDSP'].keys():
|
|
693
|
+
for j in range(len(response['SDSP'][node_key]['ITEMS'])):
|
|
694
|
+
item = response['SDSP'][node_key]['ITEMS'][j]
|
|
695
|
+
|
|
696
|
+
# Extract displacement values from VALUES array
|
|
697
|
+
values = []
|
|
698
|
+
for val_item in item.get('VALUES', []):
|
|
699
|
+
values.append(val_item.get('DISPLACEMENT', 0))
|
|
700
|
+
|
|
701
|
+
Load.SpDisp(
|
|
702
|
+
int(node_key),
|
|
703
|
+
item['LCNAME'],
|
|
704
|
+
item['GROUP_NAME'],
|
|
705
|
+
values,
|
|
706
|
+
item['ID']
|
|
707
|
+
)
|
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
|
|