package org.openpixi.pixi.physics.grid;
import org.openpixi.pixi.physics.Debug;
import org.openpixi.pixi.physics.particles.Particle;
public class CloudInCell implements InterpolatorAlgorithm {
@Override
public void interpolateToGrid(Particle p, Grid g, double tstep) {
/**X index of the grid point that is left from or at the x position of the particle*/
int i;
/**Y index of the grid point that is below or at the y position of the particle*/
int j;
/**Normalized distance to the left cell boundary*/
double a;
/**Normalized distance to the right cell boundary*/
double b;
/**Normalized distance to the lower cell boundary*/
double c;
/**Normalized distance to the upper cell boundary*/
double d;
a = p.getX() / g.getCellWidth();
i = (int) Math.floor(a);
a -= i;
b = 1 - a;
c = p.getY() / g.getCellHeight();
j = (int) Math.floor(c);
c -= j;
d = 1 - c;
//The Jx-field is located in the middle of the left cell boundary.
//This means that the Jx-field-grid is shifted upwards by half a cell height.
//The adjustments are made to calculate the distance to the shifted grid. The
//only changes to be made are in the vertical plane. All changes are reversed
//after the calculation.
if( c < 0.5 ){
j -= 1;
c += 0.5;
d -= 0.5;
g.addJx(i, j, p.getCharge() * p.getVx() * b * d);
g.addJx(i, j + 1, p.getCharge() * p.getVx() * b * c);
g.addJx(i + 1, j + 1, p.getCharge() * p.getVx() * a * c);
g.addJx(i + 1, j, p.getCharge() * p.getVx() * a * d);
c -= 0.5;
d += 0.5;
j += 1;
} else {
c -= 0.5;
d += 0.5;
g.addJx(i, j, p.getCharge() * p.getVx() * b * d);
g.addJx(i, j + 1, p.getCharge() * p.getVx() * b * c);
g.addJx(i + 1, j + 1, p.getCharge() * p.getVx() * a * c);
g.addJx(i + 1, j, p.getCharge() * p.getVx() * a * d);
c += 0.5;
d -= 0.5;
}
//The Jy-field is located in the middle of the lower cell boundary.
//This means that the Jy-field-grid is shifted to the right by half a cell width.
//The adjustments are made to calculate the distance to the shifted grid. The
//only changes to be made are in the horizontal plane.
if( a < 0.5 ){
i -= 1;
a += 0.5;
b -= 0.5;
g.addJy(i, j, p.getCharge() * p.getVy() * b * d);
g.addJy(i, j + 1, p.getCharge() * p.getVy() * b * c);
g.addJy(i + 1, j + 1, p.getCharge() * p.getVy() * a * c);
g.addJy(i + 1, j, p.getCharge() * p.getVy() * a * d);
//No need to return the values to their previous state because they are
//not going to be used anymore.
} else {
a -= 0.5;
b += 0.5;
g.addJy(i, j, p.getCharge() * p.getVy() * b * d);
g.addJy(i, j + 1, p.getCharge() * p.getVy() * b * c);
g.addJy(i + 1, j + 1, p.getCharge() * p.getVy() * a * c);
g.addJy(i + 1, j, p.getCharge() * p.getVy() * a * d);
//No need to return the values to their previous state because they are
//not going to be used anymore.
}
}
@Override
public void interpolateChargedensity(Particle p, Grid g) {
/**X index of the grid point that is left from or at the x position of the particle*/
int i;
/**Y index of the grid point that is below or at the y position of the particle*/
int j;
/**Normalized distance to the left cell boundary*/
double a;
/**Normalized distance to the right cell boundary*/
double b;
/**Normalized distance to the lower cell boundary*/
double c;
/**Normalized distance to the upper cell boundary*/
double d;
//DELETED THE SHIFT
//The -0.5 is there to shift the grid
//a = p.getX() / g.getCellWidth() - 0.5;
a = p.getX() /g.getCellWidth();
i = (int) Math.floor(a);
a -= i;
b = 1 - a;
//The -0.5 is there to shift the grid
//c = p.getY() / g.getCellHeight() - 0.5;
c = p.getY() / g.getCellHeight();
j = (int) Math.floor(c);
c -= j;
d = 1 - c;
//Assign a portion of the charge to the four surrounding points depending on
//the distance.
g.addRho( (i + g.getNumCellsX())%g.getNumCellsX(), (j + g.getNumCellsY())%g.getNumCellsY(), p.getCharge() * b * d);
g.addRho( (i + g.getNumCellsX())%g.getNumCellsX(), (j + 1 + g.getNumCellsY())%g.getNumCellsY(), p.getCharge() * b * c);
g.addRho( (i + 1 + g.getNumCellsX())%g.getNumCellsX(), (j + 1 + g.getNumCellsY())%g.getNumCellsY(), p.getCharge() * a * c);
g.addRho( (i + 1 + g.getNumCellsX())%g.getNumCellsX(), (j + g.getNumCellsY())%g.getNumCellsY(), p.getCharge() * a * d);
}
@Override
public void interpolateToParticle(Particle p, Grid g) {
int xCellPosition = (int) Math.floor(p.getX() / g.getCellWidth());
int yCellPosition = (int) Math.floor(p.getY() / g.getCellHeight());
int xCellPosition2 = xCellPosition + 1;
int yCellPosition2 = yCellPosition + 1;
if (Debug.asserts) {
// Assert conditions for interpolation
assert xCellPosition2 * g.getCellWidth() > p.getX() : p.getX();
assert p.getX() > (xCellPosition2 - 1) * g.getCellWidth() : p.getX();
assert yCellPosition2 * g.getCellHeight() > p.getY() : p.getY();
assert p.getY() > (yCellPosition2 - 1) * g.getCellHeight() : p.getY();
}
//Adaption since the electric field is stored in the edges of the cells
if(p.getX()/g.getCellWidth()-xCellPosition<0.5)
{
xCellPosition--;
xCellPosition2--;
}
p.setEx((g.getEx( (xCellPosition + g.getNumCellsX())%g.getNumCellsX(), (yCellPosition + g.getNumCellsY())%g.getNumCellsY() ) *
((xCellPosition+1.5) * g.getCellWidth() - p.getX()) *
(yCellPosition2 * g.getCellHeight() - p.getY()) +
g.getEx( (xCellPosition + 1 + g.getNumCellsX())%g.getNumCellsX(), (yCellPosition + g.getNumCellsY())%g.getNumCellsY() ) *
(p.getX() - (xCellPosition2 - 0.5) * g.getCellWidth()) *
(yCellPosition2 * g.getCellHeight() - p.getY()) +
g.getEx( (xCellPosition + g.getNumCellsX())%g.getNumCellsX(), (yCellPosition + 1 + g.getNumCellsY())%g.getNumCellsY() ) *
((xCellPosition+1.5) * g.getCellWidth() - p.getX()) *
(p.getY() - (yCellPosition2 - 1) * g.getCellHeight()) +
g.getEx( (xCellPosition + 1 + g.getNumCellsX())%g.getNumCellsX(), (yCellPosition + 1 + g.getNumCellsY())%g.getNumCellsY() ) *
(p.getX() - (xCellPosition2 - 0.5) * g.getCellWidth()) *
(p.getY() - (yCellPosition2 - 1) * g.getCellHeight())) /
(g.getCellWidth() * g.getCellHeight()));
if(p.getX()/g.getCellWidth() - xCellPosition >1)
{
xCellPosition++;
xCellPosition2++;
}
//redo the adaption for the x-component
if(p.getY()/g.getCellHeight()-yCellPosition <0.5)
{
yCellPosition--;
yCellPosition2--;
}
p.setEy((g.getEy( (xCellPosition + g.getNumCellsX())%g.getNumCellsX(), (yCellPosition + g.getNumCellsY())%g.getNumCellsY() ) *
(xCellPosition2 * g.getCellWidth() - p.getX()) *
((yCellPosition2+0.5) * g.getCellHeight() - p.getY()) +
g.getEy( (xCellPosition + 1 + g.getNumCellsX())%g.getNumCellsX(), (yCellPosition + g.getNumCellsY())%g.getNumCellsY() ) *
(p.getX() - (xCellPosition2 - 1) * g.getCellWidth()) *
((yCellPosition2+0.5) * g.getCellHeight() - p.getY()) +
g.getEy( (xCellPosition + g.getNumCellsX())%g.getNumCellsX(), (yCellPosition + 1 + g.getNumCellsY())%g.getNumCellsY() ) *
(xCellPosition2 * g.getCellWidth() - p.getX()) *
(p.getY() - (yCellPosition2 - 0.5) * g.getCellHeight()) +
g.getEy( (xCellPosition + 1 + g.getNumCellsX())%g.getNumCellsX(), (yCellPosition + 1 + g.getNumCellsY())%g.getNumCellsY() ) *
(p.getX() - (xCellPosition2 - 1) * g.getCellWidth()) *
(p.getY() - (yCellPosition2 - 0.5) * g.getCellHeight())) /
(g.getCellWidth() * g.getCellHeight()));
/*System.out.println("position:");System.out.println(p.getX());System.out.println(p.getY());
System.out.println(xCellPosition);System.out.println(yCellPosition);System.out.println(":");System.out.println(g.getEy(xCellPosition, yCellPosition));
System.out.println(xCellPosition+1);System.out.println(yCellPosition);System.out.println(":");System.out.println(g.getEy(xCellPosition+1, yCellPosition));
System.out.println(xCellPosition);System.out.println(yCellPosition+1);System.out.println(":");System.out.println(g.getEy(xCellPosition, yCellPosition+1));
System.out.println(xCellPosition+1);System.out.println(yCellPosition+1);System.out.println(":");System.out.println(g.getEy(xCellPosition+1, yCellPosition+1));
*/
//adapt the values of x/y CellPosition (2) since the B-field is located in the middle of the grid
if(p.getX()/g.getCellWidth()-xCellPosition<0.5)
{
xCellPosition--;
xCellPosition2--;
}
p.setBz((g.getBz( (xCellPosition + g.getNumCellsX())%g.getNumCellsX(), (yCellPosition + g.getNumCellsY())%g.getNumCellsY() ) *
((xCellPosition2+0.5) * g.getCellWidth() - p.getX()) *
((yCellPosition2+0.5) * g.getCellHeight() - p.getY()) +
g.getBz( (xCellPosition + 1 + g.getNumCellsX())%g.getNumCellsX(), (yCellPosition + g.getNumCellsY())%g.getNumCellsY() ) *
(p.getX() - (xCellPosition2 - 0.5) * g.getCellWidth()) *
((yCellPosition2+0.5) * g.getCellHeight() - p.getY()) +
g.getBz( (xCellPosition + g.getNumCellsX())%g.getNumCellsX(), (yCellPosition + 1 + g.getNumCellsY())%g.getNumCellsY() ) *
((xCellPosition2+0.5) * g.getCellWidth() - p.getX()) *
(p.getY() - (yCellPosition2 - 0.5) * g.getCellHeight()) +
g.getBz( (xCellPosition + 1 + g.getNumCellsX())%g.getNumCellsX(), (yCellPosition + 1 + g.getNumCellsY())%g.getNumCellsY() ) *
(p.getX() - (xCellPosition2 -0.5) * g.getCellWidth()) *
(p.getY() - (yCellPosition2 -0.5) * g.getCellHeight())) /
(g.getCellWidth() * g.getCellHeight()));
//p.setBz(0);
}
//@Override
public void interpolateToParticle_oldmaster(Particle p, Grid g) {
/**X index of the grid point that is left from or at the x position of the particle*/
int i;
/**Y index of the grid point that is below or at the y position of the particle*/
int j;
/**Normalized distance to the left cell boundary*/
double a;
/**Normalized distance to the right cell boundary*/
double b;
/**Normalized distance to the lower cell boundary*/
double c;
/**Normalized distance to the upper cell boundary*/
double d;
a = p.getX() / g.getCellWidth();
i = (int) Math.floor(a);
a -= i;
b = 1 - a;
c = p.getY() / g.getCellHeight();
j = (int) Math.floor(c);
c -= j;
d = 1 - c;
//Bz as given by the FDTD field solver is defined half a timestep ahead of particle
//time. Therefore we have to average over the old Bz (that is half a timestep behind)
//and the current Bz. The magnetic field is located at the grid points.
//No adjustments to the grid are necessary.
p.setBz((formFactor(
g.getBzo(i, j), g.getBzo(i, j+1), g.getBzo(i+1, j+1), g.getBzo(i+1, j),
a, b, c, d) +
formFactor(g.getBz(i, j), g.getBz(i, j+1), g.getBz(i+1, j+1), g.getBz(i+1, j),
a, b, c, d)) / 2);
//The Ex-field is located in the middle of the left cell boundary.
//This means that the Ex-field-grid is shifted upwards by half a cell height.
//The adjustments are made to calculate the distance to the shifted grid. The
//only changes to be made are in the vertical plane. All changes are reversed
//after the calculation.
if( c < 0.5 ){
j -= 1;
c += 0.5;
d -= 0.5;
p.setEx(formFactor(
g.getEx(i, j), g.getEx(i, j+1), g.getEx(i+1, j+1), g.getEx(i+1, j),
a, b, c, d));
c -= 0.5;
d += 0.5;
j += 1;
} else {
c -= 0.5;
d += 0.5;
p.setEx(formFactor(
g.getEx(i, j), g.getEx(i, j+1), g.getEx(i+1, j+1), g.getEx(i+1, j),
a, b, c, d));
c += 0.5;
d -= 0.5;
}
//The Ey-field is located in the middle of the lower cell boundary.
//This means that the Ey-field-grid is shifted to the right by half a cell width.
//The adjustments are made to calculate the distance to the shifted grid. The
//only changes to be made are in the horizontal plane.
if( a < 0.5 ){
i -= 1;
a += 0.5;
b -= 0.5;
p.setEy(formFactor(
g.getEy(i, j), g.getEy(i, j+1), g.getEy(i+1, j+1), g.getEy(i+1, j),
a, b, c, d));
//No need to return the values to their previous state because they are
//not going to be used anymore.
} else {
a -= 0.5;
b += 0.5;
p.setEy(formFactor(
g.getEy(i, j), g.getEy(i, j+1), g.getEy(i+1, j+1), g.getEy(i+1, j),
a, b, c, d));
//No need to return the values to their previous state because they are
//not going to be used anymore.
}
}
/**Defines how grid values are weighted. Characteristic of interpolation algorithm.
* <p>This is linear interpolation.</p>
* @param A value at the lower left grid point
* @param B value at the upper left grid point
* @param C value at the upper right grid point
* @param D value at the lower right grid point
* @param a normalized distance to the left cell boundary
* @param b normalized distance to the right cell boundary
* @param c normalized distance to the lower cell boundary
* @param d normalized distance to the upper cell boundary
* @return Total value at the particle position
*/
private double formFactor(double A, double B, double C, double D,
double a, double b, double c, double d){
return A*b*d + B*b*c + C*a*c + D*a*d;
}
}