# encoding: utf-8

# example of use JCFpm classes : Law2_ScGeom_JCFpmPhys_JointedCohesiveFrictionalPM...
# a cubic rock massif, containing a rock joint with ~ 31 deg. dip angle. At one time, the mechanical properties of the joint are degraded, triggering a smooth sliding


# definition of a predicate for use of randomDensePack() function

from __future__ import print_function
from past.builtins import execfile
from yade import pack
dimModele = 10.0
pred = pack.inAlignedBox((0,0,0),(dimModele,dimModele,dimModele))


# the packing of spheres :

def mat(): return JCFpmMat(type=1,young=1e8,poisson=0.3,frictionAngle=radians(30),density=3000,tensileStrength=1e6,cohesion=1e6,jointNormalStiffness=1e7,jointShearStiffness=1e7,jointCohesion=1e6,jointFrictionAngle=radians(20),jointDilationAngle=0.0)
nSpheres = 3000.0
poros=0.13
rMeanSpheres = dimModele * pow(3.0/4.0*(1-poros)/(pi*nSpheres),1.0/3.0)
print('')
print('Creating a cubic sample of spheres (may take some time and cause warnings)')
print('')
# maybe using seed=?? will fix the problem.
sp = pack.randomDensePack(pred,radius=rMeanSpheres,rRelFuzz=0.3,memoizeDb='/tmp/gts-triax-packings.sqlite',returnSpherePack=True)
sp.toSimulation(color=(0.9,0.8,0.6),wire=False,material=mat)
print('')
print('Sample created !')


# Definition of the facets for joint's geometry

import gts
# joint with ~ 31 deg. dip angle
v1 = gts.Vertex(0 , 0 , 0.8*dimModele)
v2 = gts.Vertex(0 , dimModele , 0.8*dimModele )
v3 = gts.Vertex(dimModele , dimModele , 0.2*dimModele)
v4 = gts.Vertex(dimModele , 0 , 0.2*dimModele)

e1 = gts.Edge(v1,v2)
e2 = gts.Edge(v2,v4)
e3 = gts.Edge(v4,v1)
f1 = gts.Face(e1,e2,e3)

e4 = gts.Edge(v4,v3)
e5 = gts.Edge(v3,v2)
f2 = gts.Face(e2,e4,e5)

s1 = gts.Surface()
s1.add(f1)
s1.add(f2)

facet = gtsSurface2Facets(s1,wire = False,material=mat)
O.bodies.append(facet)

yade.qt.View()
yade.qt.Controller()

O.saveTmp()
# identification of spheres onJoint, and so on:
execfile('identifBis.py')
dim=utils.aabbExtrema()
xsup=dim[1][0]
yinf=dim[0][1]
ysup=dim[1][1]
zinf=dim[0][2]
zsup=dim[1][2]

e=2.5*rMeanSpheres

refPoint=None

for o in O.bodies:
	if isinstance(o.shape,Sphere):
		o.shape.color=(0.9,0.8,0.6)
		## to fix boundary particles on ground
		if o.state.pos[2]<(zinf+2*e) :
			o.state.blockedDOFs+='xyz'
			o.shape.color=(1,1,1)

	## to identify indicator on top
	## FIXME - should always find something.
	if o.state.pos[2]>(zsup-e) and o.state.pos[0]>(xsup-e) and o.state.pos[1]>((yinf+ysup-e)/2.0) and o.state.pos[1]<((yinf+ysup+e)/2) : 
		print("indicator on top: "+str(o.id))
		refPoint=o.id

if refPoint:
	O.bodies[refPoint].shape.highlight=True
else:
	print("ERROR: could not find 'indicator on top' in the randomly generated sample. Try again, or fix this script.")
	input("Press Enter to continue...")

#### Engines definition
O.engines=[
	ForceResetter(),
	InsertionSortCollider([Bo1_Sphere_Aabb(),]),
	InteractionLoop(
		[Ig2_Sphere_Sphere_ScGeom()],
#		[Ip2_JCFpmMat_JCFpmMat_JCFpmPhys(cohesiveTresholdIteration=1,alpha=0.3,tensileStrength=1e6,cohesion=1e6,jointNormalStiffness=1e7,jointShearStiffness=1e7,jointCohesion=1e6,jointFrictionAngle=radians(20),jointDilationAngle=0.0)],
		[Ip2_JCFpmMat_JCFpmMat_JCFpmPhys(cohesiveTresholdIteration=1)],
		[Law2_ScGeom_JCFpmPhys_JointedCohesiveFrictionalPM(smoothJoint=True)]
	),
	GlobalStiffnessTimeStepper(timestepSafetyCoefficient=0.8),
	PyRunner(iterPeriod=1000,initRun=False,command='jointStrengthDegradation()'),
	PyRunner(iterPeriod=10,initRun=True,command='dataCollector()'),
	NewtonIntegrator(damping=0.7,gravity=(0.,0.,-10.)),

]

#### dataCollector
from yade import plot
plot.plots={'iterations':'v','x':'z'}

def dataCollector():
	R=O.bodies[refPoint]
	plot.addData(v=R.state.vel[2],z=R.state.pos[2],x=R.state.pos[0],iterations=O.iter,t=O.realtime)

#### joint strength degradation
stableIter=1000
stableVel=0.001
degrade=True
def jointStrengthDegradation():
	global degrade
	if degrade and O.iter>=stableIter and abs(O.bodies[refPoint].state.vel[2])<stableVel :
		print('Equilibrium reached \nJoint cohesion canceled now !', ' | iteration=', O.iter)
		degrade=False
	for i in O.interactions:
		if i.phys.isOnJoint : 
			if i.phys.isCohesive:
				i.phys.isCohesive=False
				i.phys.FnMax=0.
				i.phys.FsMax=0.

print('Seeking after an initial equilibrium state')
print('')
O.run(10000)
plot.plot()# note the straight trajectory (z(x) plot)during sliding step (before free fall) despite the discretization of joint plane with spheres
