# -*- encoding=utf-8 -*-
# 2021 J.Kozicki, A.Gladky, K.Thoeni "Implementation of high-precision computation capabilities into the dynamic simulation framework YADE" (to be submitted)
# The script is tested with yade_2021.01a
from yade import plot, qt, math

# initialize all floating point variables with Real(arg) to avoid precision loss
from yade.math import toHP1 as Real
# after release yade_2021.01a math.toHP1 has an alias Real, same with radiansHP1

### set parameters ###
L = Real('0.1')  # length [m]
n = 4  # number of nodes for the length [-]
r = L / 100  # radius [m]
g = Real('9.81')  # gravity
inclination = math.radiansHP1(20)  # Initial inclination of rods [degrees]
color = [1, 0.5, 0]  # Define a color for bodies

O.dt = Real('1e-05')  # time step
damp = Real('1e-1')  # damping. It is interesting to examine  damp = 0

O.engines = [  # define engines, main functions for simulation
    ForceResetter(),
    InsertionSortCollider([Bo1_Sphere_Aabb()],
                          label='ISCollider', avoidSelfInteractionMask=True),
    InteractionLoop(
        [Ig2_Sphere_Sphere_ScGeom6D()],
        [Ip2_CohFrictMat_CohFrictMat_CohFrictPhys(
            setCohesionNow=True, setCohesionOnNewContacts=False)],
        [Law2_ScGeom6D_CohFrictPhys_CohesionMoment()]
    ),
    NewtonIntegrator(gravity=(0, -g, 0), damping=damp, label='newton'),
]

# define material:
O.materials.append(
        CohFrictMat(
                young=1e5,
                poisson=0,
                density=1e1,
                frictionAngle=math.radiansHP1(0),
                normalCohesion=1e7,
                shearCohesion=1e7,
                momentRotationLaw=False,
                label='mat'
        )
)

# create spheres
nodeIds = []
for i in range(0, n):
	nodeIds.append(
	        O.bodies.append(
	                sphere(
	                        [i * L / n * math.cos(inclination), i * L / n * math.sin(inclination), 0],
	                        r,
	                        wire=False,
	                        fixed=False,
	                        material='mat',
	                        color=color
	                )
	        )
	)

# create rods
for i, j in zip(nodeIds[:-1], nodeIds[1:]):
	inter = createInteraction(i, j)
	inter.phys.unp = -(O.bodies[j].state.pos - O.bodies[i].state.pos).norm() + O.bodies[i].shape.radius + O.bodies[j].shape.radius

O.bodies[0].dynamic = False  # set a fixed upper node
qt.View()  # create a GUI view
Gl1_Sphere.stripes = True  # mark spheres with stripes
rr = qt.Renderer()  # get instance of the renderer
rr.intrAllWire = True  # draw wires
rr.intrPhys = True  # draw the normal forces between the spheres.
