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/_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 != 0 or eccn_type != 1: eccn_type = 0
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
+ )