Origami creases

#############################################################################################################################
# Created by Ning An
# 2019/12
# Created in Abaqus Version 2017

# Function for modeling origami fold creases using Pin and Torsional Springs
# mdb: model database
# NameModel: A string with the name of your model
# NameSet1 & NameSet2: A string with the name of your two edge sets joined by the crease.
# axis: A number with the axis of torsion. The value of 0, 1, and 2 indicates x, y, and z-axis, respectively.
# Dof: A number with the rotational degree of freedom. The value of 4, 5, and 6 indicates rotation along x, y, and z-axis, respectively.
# NameDatum: A string with the name of local datum
# k_node_pair: A float number with the stiffness assigned to each pair of nodes. 


from abaqusConstants import *
from interaction import *


def sort_node_list(node_list,axis):
    """ Sorting a node list along a selected axis """
    node_list.sort(key=lambda node_list: node_list.coordinates[axis], reverse=False)


def ori_crease(mdb, NameModel, NameSet1, NameSet2, axis, Dof, NameDatum, k_node_pair):
    """Modeling origami fold crease using Pin and Torsional Spring"""
    nodes_Set1 = mdb.models[NameModel].rootAssembly.sets[NameSet1].nodes
    nodes_Set2 = mdb.models[NameModel].rootAssembly.sets[NameSet2].nodes

    nodes_Set1_List = list(nodes_Set1)
    nodes_Set2_List = list(nodes_Set2)
    sort_node_list(nodes_Set1_List, axis)
    sort_node_list(nodes_Set2_List, axis)

    repConst=0
    numNodes = len(nodes_Set1)
    for i in range(numNodes):
        n1 = nodes_Set1_List[i]
        n2 = nodes_Set2_List[i]
        nodes_Set1_mask = nodes_Set1.sequenceFromLabels(labels = (n1.label, ))
        nodes_Set2_mask = nodes_Set2.sequenceFromLabels(labels = (n2.label, ))
        nodes_Set1_region = mdb.models[NameModel].rootAssembly.Set(name = NameSet1 + '_' + str(repConst), nodes = nodes_Set1_mask)
        nodes_Set1_region = mdb.models[NameModel].rootAssembly.Set(name = NameSet2 + '_' + str(repConst), nodes = nodes_Set2_mask)

        mdb.models[NameModel].rootAssembly.engineeringFeatures.TwoPointSpringDashpot(
            axis=FIXED_DOF, 
            name='Spring-' + NameSet1 + '_' + NameSet2 + '_' + str(repConst), 
            regionPairs=((mdb.models[NameModel].rootAssembly.sets[NameSet1 + '_' + str(repConst)], 
                          mdb.models[NameModel].rootAssembly.sets[NameSet2 + '_' + str(repConst)]), ), 
            springBehavior=ON, 
            springStiffness=k_node_pair, 
            dashpotBehavior=OFF, 
            dashpotCoefficient=0.0,
            dof1=Dof, 
            dof2=Dof,
            orientation=mdb.models[NameModel].rootAssembly.datums[mdb.models[NameModel].rootAssembly.features[NameDatum].id])

        mdb.models[NameModel].MultipointConstraint(
            name='Pin-' + NameSet1 + '_' + NameSet2 + '_' + str(repConst), 
            controlPoint=mdb.models[NameModel].rootAssembly.sets[NameSet1 + '_' + str(repConst)], 
            surface=mdb.models[NameModel].rootAssembly.sets[NameSet2 + '_' + str(repConst)], 
            csys=mdb.models[NameModel].rootAssembly.datums[mdb.models[NameModel].rootAssembly.features[NameDatum].id], 
            mpcType=PIN_MPC, 
            userMode=DOF_MODE_MPC, 
            userType=0)
        repConst = repConst+1
####################################################################################################################################