# encoding: utf-8
# 2010 © Bruno Chareyre <bruno.chareyre@grenoble-inp.fr>

'''
Motion of a "sinusoidal" beam made of cylinders. The test checks the position and velocity of the free end of the bending beam subjected to gravitational load. It is similar to scripts/test/chained-cylinder-spring.py but with less elements. positions and velocity are compared during the transient oscillations, only positions are compared for the larger time since residual velocity is compiler-dependent (see https://lists.launchpad.net/yade-dev/msg06178.html).
'''

from builtins import range
import unittest
import random
from yade.wrapper import *
from yade._customConverters import *
from yade.gridpfacet import *
from math import *
from minieigen import *

class TestCohesiveChain(unittest.TestCase):
	# prefix test names with PBC:
	def setUp(self):
		O.reset();
		young=1.0e3
		poisson=5
		density=2.60e3
		frictionAngle=radians(30)
		O.materials.append(CohFrictMat(young=young,poisson=poisson,density=density,frictionAngle=frictionAngle,normalCohesion=1e13,shearCohesion=1e13,momentRotationLaw=True))
		O.dt=1e-3
		O.engines=[
			ForceResetter(),
			InsertionSortCollider([
			Bo1_ChainedCylinder_Aabb(),
			Bo1_Sphere_Aabb()]),
		InteractionLoop(
			[Ig2_ChainedCylinder_ChainedCylinder_ScGeom6D(),Ig2_Sphere_ChainedCylinder_CylScGeom()],
			[Ip2_CohFrictMat_CohFrictMat_CohFrictPhys(setCohesionNow=True,setCohesionOnNewContacts=True)],
			[Law2_ScGeom6D_CohFrictPhys_CohesionMoment()]),
		## Apply gravity
		## Motion equation
		NewtonIntegrator(damping=0.15,gravity=[0,-9.81,0])
		]
		#Generate a spiral
		Ne=10
		for i in range(0, Ne):
			omeg=95.0/float(Ne); hy=0.05; hz=0.07;
			px=float(i)*(omeg/60.0); py=sin(float(i)*omeg)*hy; pz=cos(float(i)*omeg)*hz;
			px2=float(i+1.)*(omeg/60.0); py2=sin(float(i+1.)*omeg)*hy; pz2=cos(float(i+1.)*omeg)*hz;
			chainedCylinder(begin=Vector3(pz,py,px), radius=0.005,end=Vector3(pz2,py2,px2),color=Vector3(0.6,0.5,0.5))
		O.bodies[Ne-1].state.blockedDOFs='xyzXYZ'
	def testMotion(self):
		"CohesiveChain: velocity/positions tested in transient dynamics and equilibrium state"
		#target values
		tv1=-0.790576599652;tp1=-0.0483370740415;tv2=-0.000494271551993;tp2=-0.0611987315415;
		tolerance = 10e-3
		O.run(100,True)
		v1=O.bodies[0].state.vel[1];p1=O.bodies[0].state.pos[1]
		#print v1,p1
		O.run(10000,True)
		v2=O.bodies[0].state.vel[1];p2=O.bodies[0].state.pos[1]
		self.assertTrue(abs(tv1-v1)<abs(tolerance*tv1) and abs(tp1-p1)<abs(tolerance*tp1))
		self.assertTrue(abs(tp2-p2)<abs(tolerance*tp2))
		#self.assertTrue(abs(tv2-v2)<abs(tolerance*tv2) and abs(tp2-p2)<abs(tolerance*tp2)) #velocity comparison disabled, see comment above
