from abaqus import *
from abaqusConstants import *
import part
import material
import section
import assembly
import regionToolset
import math

# PARAMETERS
L = 80.0
r_mid = 10.5
strand_width = 1.0
n_wave = 3
n_circ = 12
amp_angle = 15       # degree
segments = 100

# CREATE STRAND PART USING 3D POLYLINE
def create_strand_part(name, phase):
    p = mdb.models['Model-1'].Part(name=name, dimensionality=THREE_D, type=DEFORMABLE_BODY)
    points = []
    for i in range(segments+1):
        z = L * i / segments
        theta = math.radians(amp_angle * math.sin(2*math.pi*n_wave*z/L + phase))
        x = r_mid * math.cos(theta)
        y = r_mid * math.sin(theta)
        points.append((x, y, z))
    # create 3D Wire as polyline
    p.WirePolyLine(points=points, mergeType=IMPRINT, meshable=ON)
    return p

# CREATE STRANDS
strand1 = create_strand_part('Strand1', 0)
strand2 = create_strand_part('Strand2', math.pi)

# MATERIAL AND BEAM SECTION
mdb.models['Model-1'].Material(name='Nitinol')
mdb.models['Model-1'].materials['Nitinol'].Elastic(table=((300000.0, 0.33), ))  # modify as needed
mdb.models['Model-1'].materials['Nitinol'].Density(table=((6450.0, ), ))

# Beam section with square cross-section using RectangularProfile
mdb.models['Model-1'].RectangularProfile(name='SquareProfile', a=strand_width, b=strand_width)
mdb.models['Model-1'].BeamSection(name='BeamSection', profile='SquareProfile', material='Nitinol', integration=DURING_ANALYSIS)

# ASSIGN BEAM SECTION TO STRANDS
for p in [strand1, strand2]:
    region = regionToolset.Region(edges=p.edges)
    p.SectionAssignment(region=region, sectionName='BeamSection')

# ASSEMBLY
a = mdb.models['Model-1'].rootAssembly
a.DatumCsysByDefault(CARTESIAN)

strand_instances = []
for p in [strand1, strand2]:
    inst = a.Instance(name=p.name+'_inst', part=p, dependent=ON)
    strand_instances.append(inst)

# CIRCULAR PATTERN AROUND Z-AXIS
angle_step = 360.0 / n_circ
pattern_instances = []
for i in range(n_circ):
    for inst in strand_instances:
        name = '{}_rot{}'.format(inst.name, i)
        new_inst = a.Instance(name=name, part=inst.part, dependent=ON)
        a.rotate(instanceList=(new_inst.name,), axisPoint=(0,0,0), axisDirection=(0,0,1), angle=angle_step*i)
        pattern_instances.append(new_inst)

# SAVE MODEL
mdb.saveAs(pathName='CCS_Strands_Abaqus.cae')
print("Abaqus model generated successfully.")