/*************************************************************************
*  Copyright (C) 2008 by Jerome Duriez                                   *
*  jerome.duriez@hmg.inpg.fr                                             *
*                                                                        *
*  This program is free software; it is licensed under the terms of the  *
*  GNU General Public License v2 or later. See file LICENSE for details. *
*************************************************************************/

#include<pkg/dem/KinemC__Engine.hpp>

namespace yade { // Cannot have #include directive inside.

YADE_PLUGIN((KinemCTDEngine)(KinemCNDEngine)(KinemCNLEngine)(KinemCNSEngine));

void KinemCTDEngine::action()
{
	KinemSimpleShearBox::getBoxes_Dt();


	scene->forces.sync();
	Real current_NormalForce=(scene->forces.getForce(id_topbox)).y();
	KinemSimpleShearBox::computeScontact();
	current_sigma=current_NormalForce/(1000.0*Scontact);	// so we have the current value of sigma, in kPa

	if( ((compSpeed > 0) && (current_sigma < targetSigma)) || ((compSpeed < 0) && (current_sigma > targetSigma)) )
	{
		if(temoin!=0) temoin=0;
		
		letMove(0.0,-compSpeed*dt);
	}
	else if (temoin==0)
	{
		stopMovement();
		string f;
		if (compSpeed > 0)
			f="Sigmax_";
		else
			f="Sigmin_";

		Omega::instance().saveSimulation(Key + f +boost::lexical_cast<string> (floor(targetSigma)) + "kPaReached.xml");
		temoin=1;
	}

	
	for(unsigned int j=0;j<sigma_save.size();j++)
	{
		if( (  ( (compSpeed>0)&&(current_sigma > sigma_save[j]) ) || ((compSpeed<0)&&(current_sigma < sigma_save[j])) ) && (temoin_save[j]==0))
		{
			stopMovement();
			Omega::instance().saveSimulation(Key + "SigInt_" +boost::lexical_cast<string> (floor(current_sigma)) + "kPareached.xml");
			temoin_save[j]=1;
		}
	}

}

void KinemCNDEngine::action()
{
	KinemSimpleShearBox::getBoxes_Dt();

	if( ((shearSpeed > 0) && (gamma<=gammalim)) || ((shearSpeed < 0) /*&& (gamma>=gammalim)*/ ) )
	{
		if(temoinfin!=0)
			temoinfin=0;
		letMove(shearSpeed * dt,0);
		gamma+=shearSpeed * dt;
	}
	else
	{
		stopMovement();
		if(temoinfin==0)
		{
			Omega::instance().saveSimulation(Key + "endShear.xml");
			temoinfin=1;
		}
	}

	for(unsigned int j=0;j<gamma_save.size();j++)
	{
		if ( ( ( (shearSpeed>0)&&(gamma > gamma_save[j]) ) || ((shearSpeed<0)&&(gamma < gamma_save[j])) ) && (temoin_save[j]==0) )
		{
			stopMovement();		// reset of all the speeds before the save
			Omega::instance().saveSimulation(Key+"_"+boost::lexical_cast<string> (floor(gamma*1000)) + "mmsheared.xml");
			temoin_save[j]=1;
		}
	}
	
}

void KinemCNLEngine::action()
{
	if(LOG)	cout << "debut applyCondi du CNCEngine !!" << endl;
	KinemSimpleShearBox::getBoxes_Dt();
	
	if(LOG)	cout << "gamma = " << boost::lexical_cast<string>(gamma) << "  et gammalim = " << boost::lexical_cast<string>(gammalim) << endl;
	if(gamma<=gammalim)
	{
		if(LOG)	cout << "Je suis bien dans la partie gamma < gammalim" << endl;
		if(temoin==0)

		{
			if(LOG) cout << "Je veux maintenir la Force a f0 = : " << f0 << endl; 
			temoin=1;
		}
		computeDY(0.0);
		
		letMove(shearSpeed*dt,deltaH);
		gamma+=shearSpeed * dt;

	}
	else if (temoin<2)
	{
		stopMovement();
		it_stop=scene->iter;
		cout << "Shear stopped : gammaLim reached at it "<< it_stop << endl;
		temoin=2;
	}
	else if (temoin==2 && (scene->iter==(it_stop+5000)) )
	{
		Omega::instance().saveSimulation(Key + "endShear" +boost::lexical_cast<string> ( scene->iter ) + ".xml");
		Omega::instance().pause();
	}

	for(unsigned int j=0;j<gamma_save.size();j++)
	{
		if ((gamma > gamma_save[j]) && (temoin_save[j]==0))
		{
			stopMovement();		// reset of all the speeds before the save
			Omega::instance().saveSimulation(Key+"_"+boost::lexical_cast<string> (floor(gamma*1000)) +"_" +boost::lexical_cast<string> (floor(gamma*10000)-10*floor(gamma*1000))+ "mmsheared.xml");
			temoin_save[j]=1;
		}
	}
}

void KinemCNSEngine::action()
{
	if(LOG) cerr << "debut applyCondi !!" << endl;
	KinemSimpleShearBox::getBoxes_Dt();
	
	if(gamma<=gammalim)
	{
		computeDY(KnC);
		letMove(shearSpeed * dt,deltaH);
		gamma+=shearSpeed * dt;
		if(temoin==0)
		{
			temoin=1;
		}
	}
	else if (temoin<2)
	{
		stopMovement();
		it_stop=scene->iter;
		cout << "Cisaillement arrete : gammaLim atteint a l'iteration "<< it_stop << endl;
		temoin=2;
	}
	else if (temoin==2 && (scene->iter==(it_stop+5000)) )
	{
		Omega::instance().saveSimulation(Key + "finCis" +boost::lexical_cast<string> (scene->iter ) + ".xml");
		Omega::instance().pause();
	}
}

} // namespace yade

