import org.apache.commons.math3.ode.FirstOrderDifferentialEquations
import org.apache.commons.math3.ode.nonstiff.ClassicalRungeKuttaIntegrator
import org.apache.commons.math3.ode.ContinuousOutputModel

import gendomain.*

class duffing implements FirstOrderDifferentialEquations{

	Closure f;
	double a,b,d;

	duffing(double a, double b, double d, Closure f) {
		this.f = f;
		this.a = a;
		this.b = b;
		this.d = d;
 	}

	int getDimension() {
		return 2;
	}

	void computeDerivatives(double t, double[] y, double[] yDot) {
		yDot[0] = y[1]
		yDot[1] = -d*y[1]-a*y[0]-b*y[0]*y[0]*y[0]+f(t)
	}

}

double dt=0.01
CRK = new ClassicalRungeKuttaIntegrator(dt)
gamma=7.5
omega=1.0
f={gamma*cos(omega*it)}

ode = new duffing(0.0,1.0,0.05,f);
double[] y = [3.0, 4.0]; // initial state

tracker = new ContinuousOutputModel()

CRK.addStepHandler(tracker);

double tot=250.0*PI
CRK.integrate(ode, 0.0, y, tot, y);
u=[]
v=[]
(0..tot/dt).each{
	tracker.setInterpolatedTime(it*dt)
	res=tracker.getInterpolatedState()
	u.add(res[0])
	v.add(res[1])
	//println it*dt+" "+res[0]+" "+res[1]
}

thePlot.clear()
//thePlot.addFunction(new plotfunction(dt,u as double[]))
thePlot.addFunction(new plotfunction(u as double[],v as double[]))
thePlot.setAutoColor(true)
thePlot.setMarker(false)
thePlot.show()

theDomain=theUniverse.GENDomain()

aNode=new Node(1,0.0)
aNode.setNumDOFs_Steps(2,u.size())
theDomain.putNode(aNode)
(0..<u.size()).each{
	udof = [u[it], v[it]] as double[]
	theDomain.updateNodes(udof, it) 
}



theUniverse.getGENDomain(1).ColorNodesDEF=Color.blue
theUniverse.getGENDomain(1).fillNodes=false

if(theUniverse.getGENDomain(2)!=null){
	theUniverse.getGENDomain(2).ColorNodesDEF=Color.red
	theUniverse.getGENDomain(2).fillNodes=false
}

theGP.stop()
theGP.set_size(-4,4,-6,6)
theGP.trace=true
theGP.nodeScale=100
theGP.plotDeform(1, 1.0, 0,u.size(),10)
//theGP.plotDeform(1, 1.0, 100)