# -*- encoding=utf-8 -*-
from builtins import range
from yade import plot, qt

#### define parameters for the net
# wire diameter
d = 2.7 / 1000.
# particle radius
radius = d * 4.
# define piecewise linear stress-strain curve [Pa]
strainStressValues = [(0.0019230769, 2.5e8), (0.0192, 3.2195e8), (0.05, 3.8292e8), (0.15, 5.1219e8), (0.25, 5.5854e8), (0.3, 5.6585e8), (0.35, 5.6585e8)]

# elastic material properties
particleVolume = 4. / 3. * pow(radius, 3) * pi
particleMass = 3.9 / 1000.
density = particleMass / particleVolume
young = strainStressValues[0][1] / strainStressValues[0][0]
poisson = 0.3

#### material definition
netMat = O.materials.append(
        WireMat(
                young=young,
                poisson=poisson,
                frictionAngle=radians(30),
                density=density,
                isDoubleTwist=True,
                diameter=d,
                strainStressValues=strainStressValues,
                lambdaEps=0.4,
                lambdak=0.66
        )
)
wireMat = O.materials.append(
        WireMat(
                young=young,
                poisson=poisson,
                frictionAngle=radians(30),
                density=density,
                isDoubleTwist=False,
                diameter=3.4 / 1000,
                strainStressValues=strainStressValues
        )
)

blocMat = O.materials.append(FrictMat(young=60e3, poisson=0.15, frictionAngle=radians(30), density=44.5 / ((4. / 3. * pi * 0.02**3) * 1576.)))

#### define parameters for the net packing
# mesh geometry
mos = 0.08
a = 0.04
b = 0.04
# wire diameter
d = 2.7 / 1000.
# net dimension
cornerCoord = [0, 0, 0]
Lx = 2.
Ly = 2.
# properties of particles
kw = {'color': [0, 1, 0], 'wire': True, 'highlight': False, 'fixed': False, 'material': netMat}

##### create packing for net
[netpack, lx, ly] = hexaNet(radius=radius, cornerCoord=cornerCoord, xLength=Lx, yLength=Ly, mos=mos, a=a, b=b, startAtCorner=True, isSymmetric=False, **kw)
O.bodies.append(netpack)

#### get bodies for single wire at the boundary in y-direction and change properties
bb = uniaxialTestFeatures(axis=0)
negIds, posIds = bb['negIds'], bb['posIds']

for id in negIds:
	O.bodies[id].material = O.materials[wireMat]
	O.bodies[id].shape.color = [0, 0, 1]
for id in posIds:
	O.bodies[id].material = O.materials[wireMat]
	O.bodies[id].shape.color = [0, 0, 1]

#### define engines to create link
interactionRadius = 2.8  # value has to be adjusted according to the particle size of the net and the mesh opening size of the net (check always if links are created)
O.engines = [
        ForceResetter(),
        InsertionSortCollider([Bo1_Sphere_Aabb(aabbEnlargeFactor=interactionRadius, label='aabb')]),
        InteractionLoop(
                [Ig2_Sphere_Sphere_ScGeom(interactionDetectionFactor=interactionRadius, label='Ig2ssGeom')],
                [Ip2_WireMat_WireMat_WirePhys(linkThresholdIteration=1, label='wire_wire'),
                 Ip2_FrictMat_FrictMat_FrictPhys(label='block_wire')],
                [Law2_ScGeom_WirePhys_WirePM(linkThresholdIteration=1, label='Law_1'),
                 Law2_ScGeom_FrictPhys_CundallStrack(label='Law_2')]
        ),
        NewtonIntegrator(damping=0.),
]

#### define additional vertical interactions at the boundary for boundary wire
for i in range(24)[1::2]:  # odd - start at second item and take every second item
	createInteraction(negIds[i], negIds[i + 1])
del posIds[1]
posIds.append(1)
for i in range(25)[::2]:  # even  - start at the beginning at take every second item
	createInteraction(posIds[i], posIds[i + 1])

#### time step definition for first time step to create links
O.step()

##### delete horizontal interactions for corner particles
bb = uniaxialTestFeatures(axis=1)
negIds, posIds, axis, crossSectionArea = bb['negIds'], bb['posIds'], bb['axis'], bb['area']

##### delete some interactions
O.interactions.erase(0, 50)
O.interactions.erase(0, 51)
O.interactions.erase(1, 1250)
O.interactions.erase(1, 1251)

#### time step definition for deleting some links which have been created by the Ig2 functor
O.step()

#### initializes now the interaction detection factor
aabb.aabbEnlargeFactor = -1.
Ig2ssGeom.interactionDetectionFactor = -1.

#### define boundary conditions
fixedIds = negIds
movingIds = posIds

for id in fixedIds:
	O.bodies[id].shape.color = [1, 0, 0]
	O.bodies[id].state.blockedDOFs = 'xyzXYZ'
for id in movingIds:
	O.bodies[id].shape.color = [1, 0, 0]
	O.bodies[id].state.blockedDOFs = 'xyzXYZ'

#### import block as a sphere after net has been created
bloc = O.bodies.append(sphere([1.0, 1.0, 0.65], radius=0.15, wire=False, highlight=False, color=[1, 1, 0], material=blocMat))
O.bodies[bloc].state.isDamped = False  # switch damping off since free fall under gravity

#### plot some results
plot.plots = {'t': ['vz', None, ('f_unbal', 'g--')]}
#plot.liveInterval=2.
plot.plot(noShow=False, subPlots=False)


def addPlotData():
	plot.addData(t=O.time, vz=-O.bodies[bloc].state.vel[2], f_unbal=unbalancedForce(useMaxForce=False))


#### define engines for simulation
v = qt.Controller()
v = qt.View()
rr = qt.Renderer()
rr.intrAllWire = True
O.engines = [
        ForceResetter(),
        InsertionSortCollider([Bo1_Sphere_Aabb(label='aabb')]),
        InteractionLoop(
                [Ig2_Sphere_Sphere_ScGeom(label='Ig2ssGeom')],
                [Ip2_WireMat_WireMat_WirePhys(label='wire_wire'),
                 Ip2_FrictMat_FrictMat_FrictPhys(label='block_wire')],
                [Law2_ScGeom_WirePhys_WirePM(label='Law_1'), Law2_ScGeom_FrictPhys_CundallStrack(label='Law_2')]
        ),
        NewtonIntegrator(damping=0.2, gravity=[0, 0, -9.81], label='NewtonGravity'),
        PyRunner(initRun=True, iterPeriod=100, command='addPlotData()'),
]

#### time step definition for simulation
## critical time step proposed by Bertrand
kn = 16115042  # stiffness of single wire from code, has to be changed if you change the stress-strain curve for the wire
O.dt = 0.2 * sqrt(particleMass / (2. * kn))

O.run(200000)
