#!/usr/bin/python
# -*- coding: utf-8 -*-
# Created by Burak ER
from yade.deformableelementsutils import *;

O=Omega()

## Create deformable elements internal materials and interaction element material

try:
	mat=LinIsoRayleighDampElastMat(label='aluminiummaterial');
except NameError:
	print("\n[93mDid you compile yade with cmake option -DENABLE_FEMLIKE=1 ?[0m\n")
	import sys
	sys.exit()

intermat=LinCohesiveStiffPropDampElastMat(label='intermat')

intermat.youngmodulus=70e11;

mat.density=2700;

mat.youngmodulus=70e9

O.materials.append(intermat)

O.materials.append(mat)

## Generate deformable element mesh from GMSH2 format

mesh=tetrahedral_mesh_generator('model.msh',Lin4NodeTetra,'aluminiummaterial',Lin4NodeTetra_Lin4NodeTetra_InteractionElement,'intermat')

## Define the body boundary force

# x position limits of bodies that are subject to the force
force_tail_body_lowerlimit=-1.01;

force_tail_body_upperlimit=-0.9999;

# Angular frequency of the force
amplitude=1000;

period=(1e-4)

omega=2*pi/period;

applicationperiod=period/2;

## Define the fixed boundary

# x position limits of bodies that are subject to the fixed boundary

fixed_tail_body_lowerlimit=0.99;

fixed_tail_body_upperlimit=1.01;


def getinitialpos():
	positions=[];
	for body in O.bodies:
		positions.append(body.state.pos)
	return positions

def getboundarybodies():
	bdy=[];
	for body in O.bodies:
			if(body.shape.dispIndex==12):
				if(body.state.pos[0]<fixed_tail_body_upperlimit):
					if(body.state.pos[0]>fixed_tail_body_lowerlimit):
						bdy.append(body.id)
	return bdy
						
def getforcebodies():
	bdy=[];
	for body in O.bodies:
			if(body.shape.dispIndex==12):
				if(body.state.pos[0]<force_tail_body_upperlimit):
					if(body.state.pos[0]>force_tail_body_lowerlimit):
						if(O.time<applicationperiod):
							bdy.append(body.id)	
	return bdy						

initialpositions=getinitialpos();

forcebodies=getforcebodies();

boundarybodies=getboundarybodies();


## definition of functions
def fixboundaryelements():
	for i in boundarybodies:
		O.forces.addF(i,-O.forces.f(i))
		O.forces.addT(i,-O.forces.m(i))

def applyforcetoelements():
	for i in forcebodies:
		if(O.time<applicationperiod):
#			print 'apply force @'+str(O.time)
			O.forces.addF(i,-1*O.forces.f(i));
	
			O.forces.addF(i,Vector3(sin(omega*O.time)*amplitude,0,0));
#			plot.addData(force=O.forces.f(i));

def addplot():
	plot.addData(force=O.forces.f(forcebodies[1])[0],pos=(O.bodies[forcebodies[1]].state.pos[0]-initialpositions[forcebodies[1]][0]),vel=O.bodies[forcebodies[1]].state.vel[0],t=O.time,time=O.time,tm=O.time)
		
for i in forcebodies:
	O.bodies[i].state.pos+=Vector3(0,0,0.05);

## Adaptive integration engine initialization: we have given the engines in ordered, they are runned sequentally for every substep of the integrator

#integratoreng=RungeKuttaCashKarp54Integrator([	## Resets forces and momenta the act on bodies
#						ForceResetter(),	
#						## Apply internal force to the deformable elements and internal force of the interaction element	 
#						FEInternalForceEngine([If2_Lin4NodeTetra_LinIsoRayleighDampElast(),If2_2xLin4NodeTetra_LinCohesiveStiffPropDampElastMat()]),
#						PyRunner(virtPeriod=1e-99,command='applyforcetoelements()'),
#
#])
# Integration tolerances of the RungeKuttaCashKarp54Integrator
#~ 
#~ integratoreng.rel_err=1e-6;
#~ 
#~ integratoreng.abs_err=1e-6;

# We use only the integrator engine

# Time step determines the exiting period of the integrator since the integrator performs one step from current_time to current_time+dt; using many substeps for any value of dt; then stops. 

O.dt=1e-8;

O.engines=[
	ForceResetter(),	
	## Apply internal force to the deformable elements and internal force of the interaction element	 
	FEInternalForceEngine([If2_Lin4NodeTetra_LinIsoRayleighDampElast(),If2_2xLin4NodeTetra_LinCohesiveStiffPropDampElastMat()]),
	PyRunner(iterPeriod=1,command='applyforcetoelements()'),
	NewtonIntegrator(damping=0,gravity=[0,0,0]),
#	    ## Plotting data: adds plots after one step of the integrator engine
	PyRunner(iterPeriod=1,command='addplot()')


];
#Tolerances can be set for the optimum accuracy


from yade import plot

plot.plots={'t':'vel','time':'pos','tm':'force'}
plot.plot(subPlots=True)

try:
	from yade import qt
	qt.View()
	qt.Controller()
except ImportError: pass

