midas-civil 0.0.7__py3-none-any.whl → 0.0.9__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/_boundary.py CHANGED
@@ -11,7 +11,6 @@ def convList(item):
11
11
 
12
12
 
13
13
 
14
-
15
14
  class Boundary:
16
15
 
17
16
  @classmethod
@@ -20,6 +19,8 @@ class Boundary:
20
19
  if cls.Support.sups!=[]: cls.Support.create()
21
20
  if cls.ElasticLink.links!=[]: cls.ElasticLink.create()
22
21
  if cls.RigidLink.links!=[]: cls.RigidLink.create()
22
+ if cls.MLFC.func!=[]: cls.RigidLink.create()
23
+ if cls.PointSpring.springs!=[]: cls.PointSpring.create()
23
24
 
24
25
 
25
26
  @classmethod
@@ -28,6 +29,8 @@ class Boundary:
28
29
  cls.Support.delete()
29
30
  cls.ElasticLink.delete()
30
31
  cls.RigidLink.delete()
32
+ cls.MLFC.delete()
33
+ cls.PointSpring.delete()
31
34
 
32
35
  @classmethod
33
36
  def sync(cls):
@@ -35,8 +38,8 @@ class Boundary:
35
38
  cls.Support.sync()
36
39
  cls.ElasticLink.sync()
37
40
  cls.RigidLink.sync()
38
-
39
-
41
+ cls.MLFC.sync()
42
+ cls.PointSpring.delete()
40
43
 
41
44
 
42
45
  class Support:
@@ -506,10 +509,33 @@ class Boundary:
506
509
  #---------------------------------------------------------------------------------------------------------------
507
510
 
508
511
  class MLFC:
512
+
509
513
  func = []
510
514
  _id = []
511
515
 
512
- def __init__(self,name,type:str='FORCE',symm:bool=True,data:list=[[0,0],[1,1]],id=None):
516
+ def __init__(self, name:str, type:str='FORCE', symm:bool=True, data:list=[[0,0],[1,1]], id:int=None):
517
+ """
518
+ Force-Deformation Function constructor.
519
+
520
+ Parameters:
521
+ name (str): The name for the Force-Deformation Function.
522
+ type (str, optional): Type of function, either "FORCE" or "MOMENT". Defaults to "FORCE".
523
+ symm (bool, optional): Defines if the function is symmetric (True) or unsymmetric (False). Defaults to True.
524
+ data (list[list[float]], optional): A list of [X, Y] coordinate pairs defining the function curve. Required.
525
+ - For "FORCE" type: X is displacement, Y is force.
526
+ - For "MOMENT" type: X is rotation in radians, Y is moment.
527
+ Defaults to [[0,0],[1,1]].
528
+ id (int, optional): The function ID. If not provided, it will be auto-assigned.
529
+
530
+ Examples:
531
+ ```python
532
+ # Create a symmetric force vs. displacement function
533
+ Boundary.MLFC(name="MyForceFunction", type="FORCE", symm=True, data=[[0,0], [0.1, 100], [0.2, 150]])
534
+
535
+ # Create an unsymmetric moment vs. rotation function with a specific ID
536
+ Boundary.MLFC(name="MyMomentFunction", type="MOMENT", symm=False, data=[[0,0], [0.01, 500], [0.02, 750]], id=5)
537
+ ```
538
+ """
513
539
  self.NAME = name
514
540
  self.TYPE = type
515
541
  self.SYMM = symm
@@ -534,6 +560,7 @@ class Boundary:
534
560
 
535
561
  @classmethod
536
562
  def json(cls):
563
+
537
564
  json = {"Assign": {}}
538
565
  for fn in cls.func:
539
566
  json["Assign"][fn.ID]={
@@ -550,22 +577,20 @@ class Boundary:
550
577
  @classmethod
551
578
  def create(cls):
552
579
  """
553
- Sends all FUNC data to Midas API.
580
+ Sends all FUNC data.
554
581
  """
555
582
  MidasAPI("PUT", "/db/MLFC", cls.json())
556
583
 
557
584
  @classmethod
558
585
  def get(cls):
559
586
  """
560
- Retrieves data from Midas API.
587
+ Retrieves data.
561
588
  """
562
589
  return MidasAPI("GET", "/db/MLFC")
563
590
 
564
591
  @classmethod
565
592
  def sync(cls):
566
- """
567
- Updates the class with data from the Midas API.
568
- """
593
+
569
594
  cls.links = []
570
595
  a = cls.get()
571
596
  if a != {'message': ''}:
@@ -584,4 +609,217 @@ class Boundary:
584
609
  Deletes all func from the database and resets the class.
585
610
  """
586
611
  cls.links = []
587
- return MidasAPI("DELETE", "/db/MLFC")
612
+ return MidasAPI("DELETE", "/db/MLFC")
613
+
614
+ #--------------------------------------------------------------------------------------------------------------------------------------
615
+
616
+
617
+ class PointSpring:
618
+ """Create Point Spring Object in Python"""
619
+ springs = []
620
+
621
+ def __init__(self,
622
+ node: int,
623
+ spring_type: str = "LINEAR",
624
+ group: str = "",
625
+ id: int = None,
626
+ stiffness: list = None,
627
+ fixed_option: list = None,
628
+ damping: list = None,
629
+ direction: str = "Dx+",
630
+ normal_vector: list = None,
631
+ function_id: int = 1):
632
+ """
633
+ Point Spring constructor.
634
+
635
+ Parameters:
636
+ node: Node ID where spring is applied
637
+ spring_type: Type of spring ("LINEAR", "COMP", "TENS", "MULTI")
638
+ group: Group name (default "")
639
+ id: Spring ID (optional, auto-assigned if None)
640
+ stiffness: Spring stiffness values [SDx, SDy, SDz, SRx, SRy, SRz] or single value for COMP/TENS
641
+ fixed_option: Fixed option array [Boolean, 6] for LINEAR type
642
+ damping: Damping values [Cx, Cy, Cz, CRx, CRy, CRz] (if provided, damping is enabled)
643
+ direction: Direction string ("Dx+", "Dx-", "Dy+", "Dy-", "Dz+", "Dz-", "Vector")
644
+ normal_vector: Normal vector [x, y, z] when direction is "Vector"
645
+ function_id: Function ID for MULTI type
646
+
647
+ Examples:
648
+ # Linear spring
649
+ PointSpring(1, "LINEAR", "Group1", stiffness=[1000, 1000, 1000, 100, 100, 100])
650
+
651
+ # Compression only spring
652
+ PointSpring(2, "COMP", "Group2", stiffness=5000, direction="Dz+")
653
+
654
+ # Tension only spring with vector direction
655
+ PointSpring(3, "TENS", "Group3", stiffness=3000, direction="Vector", normal_vector=[0, -1, -1])
656
+
657
+ # Multi-linear spring
658
+ PointSpring(4, "MULTI", "Group4", direction="Dz+", function_id=1)
659
+ """
660
+
661
+ # Check if group exists, create if not
662
+ if group != "":
663
+ chk = 0
664
+ a = [v['NAME'] for v in Group.Boundary.json()["Assign"].values()]
665
+ if group in a:
666
+ chk = 1
667
+ if chk == 0:
668
+ Group.Boundary(group)
669
+
670
+ # Validate spring type
671
+ valid_types = ["LINEAR", "COMP", "TENS", "MULTI"]
672
+ if spring_type not in valid_types:
673
+ spring_type = "LINEAR"
674
+
675
+ self.NODE = node
676
+ self.TYPE = spring_type
677
+ self.GROUP_NAME = group
678
+
679
+ # Convert direction string to integer
680
+ direction_map = {
681
+ "Dx+": 0, "Dx-": 1, "Dy+": 2, "Dy-": 3,
682
+ "Dz+": 4, "Dz-": 5, "Vector": 6
683
+ }
684
+ self.DIR = direction_map.get(direction, 0)
685
+
686
+ # Auto-assign ID if not provided
687
+ if id is None:
688
+ self.ID = len(Boundary.PointSpring.springs) + 1
689
+ else:
690
+ self.ID = id
691
+
692
+ # Type-specific parameters
693
+ if spring_type == "LINEAR":
694
+ self.SDR = stiffness if stiffness else [0, 0, 0, 0, 0, 0]
695
+ self.F_S = fixed_option if fixed_option else [False] * 6
696
+ # Damping logic: if damping values provided, enable damping
697
+ self.DAMPING = damping is not None and any(d != 0 for d in damping) if damping else False
698
+ self.Cr = damping if damping else [0, 0, 0, 0, 0, 0]
699
+
700
+ elif spring_type in ["COMP", "TENS"]:
701
+ self.STIFF = stiffness if stiffness else 0
702
+ self.DV = normal_vector if normal_vector else [0, 0, 0]
703
+
704
+ elif spring_type == "MULTI":
705
+ self.DV = normal_vector if normal_vector else [0, 0, 0]
706
+ self.FUNCTION = function_id
707
+
708
+ # Add to static list
709
+ Boundary.PointSpring.springs.append(self)
710
+
711
+ @classmethod
712
+ def json(cls):
713
+ """
714
+ Converts PointSpring data to JSON format for API submission.
715
+ """
716
+ json_data = {"Assign": {}}
717
+
718
+ for spring in cls.springs:
719
+ spring_data = {
720
+ "ID": spring.ID,
721
+ "TYPE": spring.TYPE,
722
+ "GROUP_NAME": spring.GROUP_NAME
723
+ }
724
+
725
+ # Add type-specific parameters
726
+ if spring.TYPE == "LINEAR":
727
+ spring_data["SDR"] = spring.SDR
728
+ spring_data["F_S"] = spring.F_S
729
+ spring_data["DAMPING"] = spring.DAMPING
730
+ if spring.DAMPING:
731
+ spring_data["Cr"] = spring.Cr
732
+
733
+ elif spring.TYPE in ["COMP", "TENS"]:
734
+ spring_data["STIFF"] = spring.STIFF
735
+ spring_data["DIR"] = spring.DIR
736
+ spring_data["DV"] = spring.DV
737
+
738
+ elif spring.TYPE == "MULTI":
739
+ spring_data["DIR"] = spring.DIR
740
+ spring_data["DV"] = spring.DV
741
+ spring_data["FUNCTION"] = spring.FUNCTION
742
+
743
+ json_data["Assign"][spring.NODE] = {"ITEMS": [spring_data]}
744
+
745
+ return json_data
746
+
747
+ @classmethod
748
+ def create(cls):
749
+ """
750
+ Sends all PointSpring data
751
+ """
752
+ MidasAPI("PUT", "/db/nspr", cls.json())
753
+
754
+ @classmethod
755
+ def get(cls):
756
+ """
757
+ Retrieves PointSpring data
758
+ """
759
+ return MidasAPI("GET", "/db/nspr")
760
+
761
+ @classmethod
762
+ def sync(cls):
763
+ """
764
+ Updates the PointSpring class with data
765
+ """
766
+ cls.springs = []
767
+ a = cls.get()
768
+
769
+ if a != {'message': ''}:
770
+ for node_id, node_data in a.get("NSPR", {}).items():
771
+ for item in node_data.get("ITEMS"):
772
+ spring_type = item.get("TYPE")
773
+ group_name = item.get("GROUP_NAME")
774
+ spring_id = item.get("ID", 1)
775
+
776
+ # Extract type-specific parameters
777
+ if spring_type == "LINEAR":
778
+ stiffness = item.get("SDR")
779
+ fixed_option = item.get("F_S")
780
+ damping = item.get("Cr") if item.get("DAMPING", False) else None
781
+
782
+ # Convert direction back to string
783
+ dir_map = {0: "Dx+", 1: "Dx-", 2: "Dy+", 3: "Dy-", 4: "Dz+", 5: "Dz-", 6: "Vector"}
784
+ direction_str = dir_map.get(0, "Dx+") # Default for LINEAR
785
+
786
+ Boundary.PointSpring(
787
+ int(node_id), spring_type, group_name, spring_id,
788
+ stiffness, fixed_option, damping, direction_str
789
+ )
790
+
791
+ elif spring_type in ["COMP", "TENS"]:
792
+ stiffness = item.get("STIFF")
793
+ direction_int = item.get("DIR")
794
+ normal_vector = item.get("DV")
795
+
796
+ # Convert direction back to string
797
+ dir_map = {0: "Dx+", 1: "Dx-", 2: "Dy+", 3: "Dy-", 4: "Dz+", 5: "Dz-", 6: "Vector"}
798
+ direction_str = dir_map.get(direction_int, "Dx+")
799
+
800
+ Boundary.PointSpring(
801
+ int(node_id), spring_type, group_name, spring_id,
802
+ stiffness, None, None, direction_str, normal_vector
803
+ )
804
+
805
+ elif spring_type == "MULTI":
806
+ direction_int = item.get("DIR")
807
+ normal_vector = item.get("DV")
808
+ function_id = item.get("FUNCTION")
809
+
810
+ # Convert direction back to string
811
+ dir_map = {0: "Dx+", 1: "Dx-", 2: "Dy+", 3: "Dy-", 4: "Dz+", 5: "Dz-", 6: "Vector"}
812
+ direction_str = dir_map.get(direction_int, "Dx+")
813
+
814
+ Boundary.PointSpring(
815
+ int(node_id), spring_type, group_name, spring_id,
816
+ None, None, None, direction_str, normal_vector, function_id
817
+ )
818
+
819
+ @classmethod
820
+ def delete(cls):
821
+ """
822
+ Deletes all point springs from the database and resets the class.
823
+ """
824
+ cls.springs = []
825
+ return MidasAPI("DELETE", "/db/nspr")