public abstract class State {
double t;
double x;
double vx;
public State(double t, double x, double vx) {
this.t=t;
this.x=x;
this.vx=vx;
}
}
public class Estado extends State{
public Estado(double t, double x, double vx) {
super(t, x, vx);
}
}
public class Estado1 extends State{
double y;
double vy;
public Estado1(double t, double x, double y, double vx, double vy) {
super(t, x, vx);
this.y=y;
this.vy=vy;
}
}
public interface RK {
abstract public void resolver(State e);
}
public abstract class RungeKutta implements RK{
double h;
RungeKutta(double h){
this.h=h;
}
public void resolver(State e){
//variables auxiliares
double k1, k2, k3, k4;
double l1, l2, l3, l4;
double q1, q2, q3, q4;
double m1, m2, m3, m4;
//condiciones iniciales
double x=e.x;
double v=e.vx;
double t=e.t;
k1=h*v;
l1=h*f(x, v, t);
k2=h*(v+l1/2);
l2=h*f(x+k1/2, v+l1/2, t+h/2);
k3=h*(v+l2/2);
l3=h*f(x+k2/2, v+l2/2, t+h/2);
k4=h*(v+l3);
l4=h*f(x+k3, v+l3, t+h);
//nuevo estado del sistema
x+=(k1+2*k2+2*k3+k4)/6;
v+=(l1+2*l2+2*l3+l4)/6;
//cambia el estado de la partícula
e.x=x;
e.vx=v;
e.t=t+h;
}
abstract public double f(double x, double v, double t);
}
public abstract class RungeKutta1 implements RK{
double h;
RungeKutta1(double h){
this.h=h;
}
public void resolver(State e){
//variables auxiliares
double k1, k2, k3, k4;
double l1, l2, l3, l4;
double q1, q2, q3, q4;
double m1, m2, m3, m4;
//estado inicial
double x=e.x;
double y=((Estado1)e).y;
double vx=e.vx;
double vy=((Estado1)e).vy;
double t=e.t;
k1=h*vx;
l1=h*f(x, y, vx, vy, t);
q1=h*vy;
m1=h*g(x, y, vx, vy, t);
k2=h*(vx+l1/2);
l2=h*f(x+k1/2, y+q1/2, vx+l1/2, vy+m1/2, t+h/2);
q2=h*(vy+m1/2);
m2=h*g(x+k1/2, y+q1/2, vx+l1/2, vy+m1/2, t+h/2);
k3=h*(vx+l2/2);
l3=h*f(x+k2/2, y+q2/2, vx+l2/2, vy+m2/2, t+h/2);
q3=h*(vy+m2/2);
m3=h*g(x+k2/2, y+q2/2, vx+l2/2, vy+m2/2, t+h/2);
k4=h*(vx+l3);
l4=h*f(x+k3, y+q3, vx+l3, vy+m3, t+h);
q4=h*(vy+m3);
m4=h*g(x+k3, y+q3, vx+l3, vy+m3, t+h);
x+=(k1+2*k2+2*k3+k4)/6;
vx+=(l1+2*l2+2*l3+l4)/6;
y+=(q1+2*q2+2*q3+q4)/6;
vy+=(m1+2*m2+2*m3+m4)/6;
t+=h;
//estado final
e.x=x;
((Estado1)e).y=y;
e.vx=vx;
((Estado1)e).vy=vy;
e.t=t;
}
abstract public double f(double x, double y, double vx, double vy, double t);
abstract public double g(double x, double y, double vx, double vy, double t);
}
public class Sistema extends RungeKutta{
double xCM;
double mInercia;
double M;
final double lonVarilla=1.0;
final double m=10.0;
double mu;
double xMasa;
public Sistema(double mu, double mInercia, double posCM, double xMasa, double M, double h){
super(h);
this.mu=mu;
this.mInercia=mInercia;
this.xCM=posCM;
this.M=M;
this.xMasa=xMasa;
}
public double f(double x, double v, double t){ // x es ángulo, v es velocidad angular
double seno=Math.sin(x);
double coseno=Math.cos(x);
double A=mInercia+(m+M)*(xCM*xCM*seno*seno-mu*lonVarilla* xCM*seno*coseno+(lonVarilla-xCM)*(lonVarilla-xCM)*coseno*coseno);
double B=(m+M)*(-xCM*xCM*seno*coseno+mu*lonVarilla* xCM*coseno*coseno+(lonVarilla-xCM)*(lonVarilla-xCM)*seno*coseno);
double C=m*9.8*lonVarilla*seno/2+M*9.8*xMasa*seno- mu*(m+M)*9.8*lonVarilla*coseno;
return ((B*v*v+C)/A);
}
public double fuerza_X(double x, double v){
double Fx=(m+M)*(mu*9.8+(-mu*xCM*Math.sin(x)+(lonVarilla-xCM) *Math.cos(x))*f(x, v, 0.0)-(mu*xCM*Math.cos(x)+(lonVarilla-xCM)*Math.sin(x))*v*v);
return Fx;
}
public double fuerza_Y(double x, double vx){
double temp=9.8-xCM*(f(x, vx, 0.0)*Math.sin(x)+vx*vx*Math.cos(x));
return ((m+M)*temp);
}
}
public class Sistema1 extends RungeKutta1{
double xCM;
double mInercia;
double M;
final double lonVarilla=1.0;
final double m=10.0;
double mu;
double xMasa;
public Sistema1(double mu, double mInercia, double posCM, double xMasa, double M, double h){
super(h);
this.mu=mu;
this.mInercia=mInercia;
this.xCM=posCM;
this.M=M;
this.xMasa=xMasa;
}
public double g(double x, double y, double vx, double vy, double t){
return (-mu*fuerza_Y(x, vx)/(m+M));
}
public double f(double x, double y, double vx, double vy, double t){
double seno=Math.sin(x);
double coseno=Math.cos(x);
double A=mInercia+(m+M)*xCM*xCM*(seno-mu*coseno)*seno;
double B=-(m+M)*xCM*xCM*(seno-mu*coseno)*coseno;
double C=m*9.8*lonVarilla*seno/2+M*9.8*xMasa*seno- mu*(m+M)*9.8*xCM*coseno;
return ((B*vx*vx+C)/A);
}
public double fuerza_Y(double x, double vx){
double temp=9.8-xCM*(f(x, 0.0, vx, 0.0, 0.0)*Math.sin(x)+vx*vx*Math.cos(x));
return ((m+M)*temp);
}
}
public class MiCanvas extends Canvas {
//parámetros
final double lonVarilla=1.0;
final double masaVarilla=10.0;
double masa=50.0;
//intervalo de tiempo
final double dt=0.0005;
double mu;
//objeto sistema
RK sistema;
double angInicial=Math.PI/6;
double xMasa, xMaximo;
double xCM, mInercia;
State estado=new Estado(0.0, angInicial, 0.0);
int tipo=0;
double xExtremo=lonVarilla*Math.sin(angInicial);
void setNuevo(int ang, double muEst, double muDin, double masa){
this.angInicial=ang*Math.PI/180;
this.mu=muDin;
this.masa=masa;
tipo=0;
xMasa=-1.0;
xExtremo=lonVarilla*Math.sin(angInicial);
estado=new Estado(0.0, angInicial, 0.0);
if(masa<=0.0){
if(angInicial>=Math.atan(2*muEst)){
mInercia=masaVarilla*lonVarilla*lonVarilla/12;
xCM=lonVarilla/2;
sistema=new Sistema(mu, mInercia, xCM, 0.0, 0.0, dt);
estado=new Estado(0.0, angInicial, 0.0);
tipo=1;
}else{
tipo=3;
repaint();
return;
}
} else{
xMaximo=(muEst*(masa+masaVarilla)*Math.cos(angInicial) -masaVarilla*Math.sin(angInicial)/2)*lonVarilla/(masa*Math.sin(angInicial));
estado=new Estado(0.0, angInicial, 0.0);
if(xMaximo>lonVarilla){
xMaximo=lonVarilla;
}else{
xCM=(masa*xMaximo+masaVarilla*lonVarilla/2)/(masa+masaVarilla);
mInercia=masaVarilla*lonVarilla*lonVarilla/12+masaVarilla* (lonVarilla/2-xCM)*(lonVarilla/2-xCM)+masa*(xCM-xMaximo)*(xCM-xMaximo);
sistema=new Sistema(mu, mInercia, xCM, xMaximo, masa, dt);
estado=new Estado(0.0, angInicial, 0.0);
}
}
xMasa=0.0;
}
void mover(){
switch(tipo){
case 0:
xMasa+=0.005;
if(xMasa>xMaximo){
if(xMaximo==lonVarilla){
xMasa=lonVarilla;
parent.hilo.putMsg(Hilo.PAUSE);
}else{
xMasa=xMaximo;
tipo=1;
}
}
break;
case 1:
sistema.resolver(estado);
xExtremo=lonVarilla*Math.sin(estado.x);
double fX=((Sistema)sistema).fuerza_X(estado.x, estado.vx);
if(fX<0){
double fY=((Sistema)sistema).fuerza_Y(estado.x, estado.vx);
sistema=new Sistema1(mu, mInercia, xCM, xMaximo, masa, dt);
double x0=(lonVarilla-xCM)*Math.sin(estado.x);
double vx0=(lonVarilla-xCM)*Math.cos(estado.x)*estado.vx;
estado=new Estado1(estado.t, estado.x, x0, estado.vx, vx0);
fY=((Sistema1)sistema).fuerza_Y(estado.x, estado.vx);
tipo=2;
}
break;
case 2:
sistema.resolver((Estado1)estado);
xExtremo=((Estado1)estado).y+xCM*Math.sin(estado.x);
double vPunta=((Estado1)estado).vy+estado.vx*xCM*Math.cos(estado.x);
double dist=((Estado1)estado).y-(lonVarilla-xCM)*Math.sin(estado.x);
if(dist<0){
parent.hilo.putMsg(Hilo.PAUSE);
System.out.println("vuelve a tocar");
}
if(estado.x>Math.PI/2){
estado.x=Math.PI/2;
parent.hilo.putMsg(Hilo.PAUSE);
}
if(vPunta<0){
parent.hilo.putMsg(Hilo.PAUSE);
System.out.println("se para");
}
break;
case 3:
break;
default:
break;
}
}
}
|