Fixed propagation procedure
This commit is contained in:
parent
38f26f93c5
commit
5b6f642c56
@ -17,6 +17,10 @@ tasks.withType(JavaCompile) {
|
|||||||
options.encoding = 'UTF-8'
|
options.encoding = 'UTF-8'
|
||||||
}
|
}
|
||||||
|
|
||||||
|
tasks.withType(JavaExec){
|
||||||
|
enableAssertions = true
|
||||||
|
}
|
||||||
|
|
||||||
repositories {
|
repositories {
|
||||||
mavenCentral()
|
mavenCentral()
|
||||||
}
|
}
|
||||||
|
BIN
gradle/wrapper/gradle-wrapper.jar
vendored
BIN
gradle/wrapper/gradle-wrapper.jar
vendored
Binary file not shown.
4
gradle/wrapper/gradle-wrapper.properties
vendored
4
gradle/wrapper/gradle-wrapper.properties
vendored
@ -1,6 +1,6 @@
|
|||||||
#Sun May 08 12:57:40 MSK 2016
|
#Tue Jun 14 13:15:55 MSK 2016
|
||||||
distributionBase=GRADLE_USER_HOME
|
distributionBase=GRADLE_USER_HOME
|
||||||
distributionPath=wrapper/dists
|
distributionPath=wrapper/dists
|
||||||
zipStoreBase=GRADLE_USER_HOME
|
zipStoreBase=GRADLE_USER_HOME
|
||||||
zipStorePath=wrapper/dists
|
zipStorePath=wrapper/dists
|
||||||
distributionUrl=https\://services.gradle.org/distributions/gradle-2.13-bin.zip
|
distributionUrl=https\://services.gradle.org/distributions/gradle-2.14-bin.zip
|
||||||
|
@ -108,6 +108,7 @@ public class SimulationManager {
|
|||||||
Counter counter = new Counter();
|
Counter counter = new Counter();
|
||||||
Predicate<Simulator.SimulationResult> reportIf = (res) -> res.state == Simulator.EndState.ACCEPTED;
|
Predicate<Simulator.SimulationResult> reportIf = (res) -> res.state == Simulator.EndState.ACCEPTED;
|
||||||
System.out.printf("%nStarting sumulation with initial energy %g and %d electrons.%n%n", initialE, num);
|
System.out.printf("%nStarting sumulation with initial energy %g and %d electrons.%n%n", initialE, num);
|
||||||
|
output.printf("%s\t%s\t%s\t%s\t%s\t%s%n", "E", "theta", "theta_start", "colNum", "L", "state");
|
||||||
Stream.generate(() -> getRandomTheta()).limit(num).parallel()
|
Stream.generate(() -> getRandomTheta()).limit(num).parallel()
|
||||||
.forEach((theta) -> {
|
.forEach((theta) -> {
|
||||||
double initZ = (generator.nextDouble() - 0.5) * Simulator.SOURCE_LENGTH;
|
double initZ = (generator.nextDouble() - 0.5) * Simulator.SOURCE_LENGTH;
|
||||||
@ -144,7 +145,7 @@ public class SimulationManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void printOne(PrintStream out, Simulator.SimulationResult res) {
|
private void printOne(PrintStream out, Simulator.SimulationResult res) {
|
||||||
out.printf("%g\t%g\t%g\t%d\t%s%n", res.E, res.theta * 180 / Math.PI, res.initTheta * 180 / Math.PI, res.collisionNumber, res.state.toString());
|
out.printf("%g\t%g\t%g\t%d\t%g\t%s%n", res.E, res.theta * 180 / Math.PI, res.initTheta * 180 / Math.PI, res.collisionNumber, res.l, res.state.toString());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -45,7 +45,7 @@ public class Simulator {
|
|||||||
setELow(Elow);
|
setELow(Elow);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static enum EndState {
|
public enum EndState {
|
||||||
|
|
||||||
ACCEPTED,//трэппинговый электрон попал в аксептанс
|
ACCEPTED,//трэппинговый электрон попал в аксептанс
|
||||||
REJECTED,//трэппинговый электрон вылетел через заднюю пробку
|
REJECTED,//трэппинговый электрон вылетел через заднюю пробку
|
||||||
@ -64,14 +64,30 @@ public class Simulator {
|
|||||||
this.thetaPinch = Math.asin(Math.sqrt(Bsource / Bpinch));
|
this.thetaPinch = Math.asin(Math.sqrt(Bsource / Bpinch));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set gas density in 1/m^3
|
||||||
|
*
|
||||||
|
* @param gasDensity
|
||||||
|
*/
|
||||||
public void setGasDensity(double gasDensity) {
|
public void setGasDensity(double gasDensity) {
|
||||||
this.gasDensity = gasDensity;
|
this.gasDensity = gasDensity;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Longitudal magnetic field distribution
|
||||||
|
*
|
||||||
|
* @param magneticField
|
||||||
|
*/
|
||||||
public void setFieldFunc(UnivariateFunction magneticField) {
|
public void setFieldFunc(UnivariateFunction magneticField) {
|
||||||
this.magneticField = magneticField;
|
this.magneticField = magneticField;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Perform scattering in the given position
|
||||||
|
*
|
||||||
|
* @param pos
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
private State scatter(State pos) {
|
private State scatter(State pos) {
|
||||||
//Вычисляем сечения и нормируем их на полное сечение
|
//Вычисляем сечения и нормируем их на полное сечение
|
||||||
double sigmaIon = scatter.sigmaion(pos.e);
|
double sigmaIon = scatter.sigmaion(pos.e);
|
||||||
@ -116,13 +132,13 @@ public class Simulator {
|
|||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
private double freePath(double e) {
|
private double freePath(double e) {
|
||||||
//FIXME double cross-section calculation
|
//FIXME redundant cross-section calculation
|
||||||
//All cross-sections are in m^2
|
//All cross-sections are in m^2
|
||||||
return new ExponentialDistribution(generator, 1 / scatter.sigmaTotal(e) / gasDensity).sample();
|
return new ExponentialDistribution(generator, 1d / scatter.sigmaTotal(e) / gasDensity).sample();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Calculate propagated position
|
* Calculate propagated position before scattering
|
||||||
*
|
*
|
||||||
* @param deltaL
|
* @param deltaL
|
||||||
* @return z shift and reflection counter
|
* @return z shift and reflection counter
|
||||||
@ -131,23 +147,27 @@ public class Simulator {
|
|||||||
// if magnetic field not defined, consider it to be uniform and equal bSource
|
// if magnetic field not defined, consider it to be uniform and equal bSource
|
||||||
if (magneticField == null) {
|
if (magneticField == null) {
|
||||||
double deltaZ = deltaL * cos(pos.theta); // direction already included in cos(theta)
|
double deltaZ = deltaL * cos(pos.theta); // direction already included in cos(theta)
|
||||||
|
double z0 = pos.z;
|
||||||
|
pos.addZ(deltaZ);
|
||||||
|
pos.l += abs(pos.z - z0) / cos(pos.theta);
|
||||||
|
|
||||||
//if we are crossing source boundary, check for end condition
|
// //if we are crossing source boundary, check for end condition
|
||||||
if(abs(deltaZ + pos.z)>SOURCE_LENGTH/2d) {
|
// while (abs(deltaZ + pos.z) > SOURCE_LENGTH / 2d && !pos.isFinished()) {
|
||||||
checkEndState(pos);
|
//
|
||||||
}
|
// pos.checkEndState();
|
||||||
|
// }
|
||||||
// if track is finished apply boundary position
|
//
|
||||||
if (pos.isFinished()) {
|
// // if track is finished apply boundary position
|
||||||
// remembering old z to correctly calculate total l
|
// if (pos.isFinished()) {
|
||||||
double oldz = pos.z;
|
// // remembering old z to correctly calculate total l
|
||||||
pos.z = pos.direction() * SOURCE_LENGTH / 2d;
|
// double oldz = pos.z;
|
||||||
pos.l += (pos.z - oldz)/cos(pos.theta);
|
// pos.z = pos.direction() * SOURCE_LENGTH / 2d;
|
||||||
} else {
|
// pos.l += (pos.z - oldz) / cos(pos.theta);
|
||||||
//else just add z
|
// } else {
|
||||||
pos.l += deltaL;
|
// //else just add z
|
||||||
pos.addZ(deltaZ);
|
// pos.l += deltaL;
|
||||||
}
|
// pos.addZ(deltaZ);
|
||||||
|
// }
|
||||||
|
|
||||||
return pos;
|
return pos;
|
||||||
} else {
|
} else {
|
||||||
@ -161,31 +181,45 @@ public class Simulator {
|
|||||||
double b = field(pos.z);
|
double b = field(pos.z);
|
||||||
|
|
||||||
double root = 1 - sin2 * b / bSource;
|
double root = 1 - sin2 * b / bSource;
|
||||||
// change direction in case of reflection. Loss of precision here?
|
//preliminary reflection
|
||||||
if (root < 0) {
|
if (root < 0) {
|
||||||
//flip direction
|
|
||||||
pos.flip();
|
pos.flip();
|
||||||
// check if end state occured
|
|
||||||
checkEndState(pos);
|
|
||||||
// finish if it does
|
|
||||||
if(pos.isFinished()){
|
|
||||||
return pos;
|
|
||||||
} else {
|
|
||||||
// move in reversed direction
|
|
||||||
pos.z += pos.direction() * delta * sqrt(-root);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// move
|
|
||||||
pos.z += pos.direction() * delta * sqrt(root);
|
|
||||||
}
|
}
|
||||||
|
pos.addZ(pos.direction() * delta * sqrt(abs(root)));
|
||||||
|
// // change direction in case of reflection. Loss of precision here?
|
||||||
|
// if (root < 0) {
|
||||||
|
// // check if end state occurred. seem to never happen since it is reflection case
|
||||||
|
// pos.checkEndState();
|
||||||
|
// // finish if it does
|
||||||
|
// if (pos.isFinished()) {
|
||||||
|
// //TODO check if it happens
|
||||||
|
// return pos;
|
||||||
|
// } else {
|
||||||
|
// //flip direction
|
||||||
|
// pos.flip();
|
||||||
|
// // move in reversed direction
|
||||||
|
// pos.z += pos.direction() * delta * sqrt(-root);
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// } else {
|
||||||
|
// // move forward
|
||||||
|
// pos.z += pos.direction() * delta * sqrt(root);
|
||||||
|
// //check if it is exit case
|
||||||
|
// if (abs(pos.z) > SOURCE_LENGTH / 2d) {
|
||||||
|
// // check if electron is out
|
||||||
|
// pos.checkEndState();
|
||||||
|
// // finish if it is
|
||||||
|
// if (pos.isFinished()) {
|
||||||
|
// return pos;
|
||||||
|
// }
|
||||||
|
// // PENDING no need to apply reflection, it is applied automatically when root < 0
|
||||||
|
// pos.z = signum(pos.z) * SOURCE_LENGTH / 2d;
|
||||||
|
// if (signum(pos.z) == pos.direction()) {
|
||||||
|
// pos.flip();
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
//normalize in case reflection is beyound the source
|
|
||||||
if (abs(pos.z) > SOURCE_LENGTH / 2d) {
|
|
||||||
pos.z = signum(pos.z) * SOURCE_LENGTH / 2d;
|
|
||||||
if(signum(pos.z)== pos.direction()){
|
|
||||||
pos.flip();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
curL += delta;
|
curL += delta;
|
||||||
pos.l += delta;
|
pos.l += delta;
|
||||||
@ -194,30 +228,6 @@ public class Simulator {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Check if this position is an end state and apply it if necessary
|
|
||||||
*
|
|
||||||
* @param pos
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
private State checkEndState(State pos) {
|
|
||||||
//accepted by spectrometer
|
|
||||||
if (pos.theta < thetaPinch) {
|
|
||||||
if (pos.colNum == 0) {
|
|
||||||
//counting pass electrons
|
|
||||||
pos.setEndState(EndState.PASS);
|
|
||||||
} else {
|
|
||||||
pos.setEndState(EndState.ACCEPTED);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//through the rear magnetic pinch
|
|
||||||
if (pos.theta >= PI - thetaTransport) {
|
|
||||||
pos.setEndState(EndState.REJECTED);
|
|
||||||
}
|
|
||||||
return pos;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Magnetic field in the z point
|
* Magnetic field in the z point
|
||||||
*
|
*
|
||||||
@ -246,11 +256,12 @@ public class Simulator {
|
|||||||
while (!pos.isFinished()) {
|
while (!pos.isFinished()) {
|
||||||
double dl = freePath(pos.e); // path to next scattering
|
double dl = freePath(pos.e); // path to next scattering
|
||||||
// propagate to next scattering position
|
// propagate to next scattering position
|
||||||
propagate(pos,dl);
|
propagate(pos, dl);
|
||||||
|
|
||||||
if (!pos.isFinished()) {
|
if (!pos.isFinished()) {
|
||||||
// perform scatter
|
// perform scatter
|
||||||
scatter(pos);
|
scatter(pos);
|
||||||
|
// increase collision number
|
||||||
pos.colNum++;
|
pos.colNum++;
|
||||||
if (pos.e < eLow) {
|
if (pos.e < eLow) {
|
||||||
//Если энергия стала слишком маленькой
|
//Если энергия стала слишком маленькой
|
||||||
@ -363,20 +374,53 @@ public class Simulator {
|
|||||||
*/
|
*/
|
||||||
double addZ(double dZ) {
|
double addZ(double dZ) {
|
||||||
this.z += dZ;
|
this.z += dZ;
|
||||||
while (abs(this.z) > SOURCE_LENGTH / 2d) {
|
while (abs(this.z) > SOURCE_LENGTH / 2d && !isFinished()) {
|
||||||
|
checkEndState();
|
||||||
|
if (!isFinished()) {
|
||||||
|
flip();
|
||||||
|
}
|
||||||
// reflecting from back wall
|
// reflecting from back wall
|
||||||
if (z < 0) {
|
if (z < 0) {
|
||||||
// reflecting from rear pinch
|
if (isFinished()) {
|
||||||
z = -SOURCE_LENGTH - z;
|
z = -SOURCE_LENGTH / 2d;
|
||||||
|
} else {
|
||||||
|
// reflecting from rear pinch
|
||||||
|
z = -SOURCE_LENGTH - z;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
// reflecting from forward transport magnet
|
if (isFinished()) {
|
||||||
z = SOURCE_LENGTH - z;
|
z = SOURCE_LENGTH / 2d;
|
||||||
|
} else {
|
||||||
|
// reflecting from forward transport magnet
|
||||||
|
z = SOURCE_LENGTH - z;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
flip();
|
|
||||||
}
|
}
|
||||||
return z;
|
return z;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if this position is an end state and apply it if necessary. Does not check z position.
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
private void checkEndState() {
|
||||||
|
//accepted by spectrometer
|
||||||
|
if (theta < thetaPinch) {
|
||||||
|
if (colNum == 0) {
|
||||||
|
//counting pass electrons
|
||||||
|
setEndState(EndState.PASS);
|
||||||
|
} else {
|
||||||
|
setEndState(EndState.ACCEPTED);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//through the rear magnetic pinch
|
||||||
|
if (theta >= PI - thetaTransport) {
|
||||||
|
setEndState(EndState.REJECTED);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Reverse electron direction
|
* Reverse electron direction
|
||||||
*/
|
*/
|
||||||
@ -406,9 +450,8 @@ public class Simulator {
|
|||||||
if (theta > PI / 2) {
|
if (theta > PI / 2) {
|
||||||
newTheta = PI - newTheta;
|
newTheta = PI - newTheta;
|
||||||
}
|
}
|
||||||
if (Double.isNaN(newTheta)) {
|
|
||||||
throw new Error();
|
assert !Double.isNaN(newTheta);
|
||||||
}
|
|
||||||
return newTheta;
|
return newTheta;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -437,13 +480,13 @@ public class Simulator {
|
|||||||
|
|
||||||
double newtheta = acos(result.getZ());
|
double newtheta = acos(result.getZ());
|
||||||
|
|
||||||
//следим чтобы угол был от 0 до Pi
|
// //следим чтобы угол был от 0 до Pi
|
||||||
if (newtheta < 0) {
|
// if (newtheta < 0) {
|
||||||
newtheta = -newtheta;
|
// newtheta = -newtheta;
|
||||||
}
|
// }
|
||||||
if (newtheta > Math.PI) {
|
// if (newtheta > Math.PI) {
|
||||||
newtheta = 2 * Math.PI - newtheta;
|
// newtheta = 2 * Math.PI - newtheta;
|
||||||
}
|
// }
|
||||||
|
|
||||||
//change back to virtual angles
|
//change back to virtual angles
|
||||||
if (magneticField == null) {
|
if (magneticField == null) {
|
||||||
@ -455,9 +498,7 @@ public class Simulator {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Double.isNaN(theta)) {
|
assert !Double.isNaN(theta);
|
||||||
throw new Error();
|
|
||||||
}
|
|
||||||
|
|
||||||
return theta;
|
return theta;
|
||||||
}
|
}
|
||||||
|
@ -16,10 +16,10 @@ public class Trapping {
|
|||||||
System.out.printf("Starting at %s%n%n", startTime.toString());
|
System.out.printf("Starting at %s%n%n", startTime.toString());
|
||||||
new SimulationManager()
|
new SimulationManager()
|
||||||
.withParameters(0.6, 3.7, 4.84, 18000d, 4000)
|
.withParameters(0.6, 3.7, 4.84, 18000d, 4000)
|
||||||
// .withOutputFile("D:\\Work\\Numass\\trapping\\trap 18, pinch 100A, fields.out")
|
.withOutputFile("D:\\Work\\Numass\\trapping\\trap 18, pinch 100A.out")
|
||||||
// .withFieldMap(z, b)
|
// .withFieldMap(z, b)
|
||||||
// .withDensity(5e20)
|
// .withDensity(5e20)
|
||||||
.simulateAll((int) 1e4);
|
.simulateAll((int) 1e6);
|
||||||
Instant finishTime = Instant.now();
|
Instant finishTime = Instant.now();
|
||||||
System.out.printf("%nFinished at %s%n", finishTime.toString());
|
System.out.printf("%nFinished at %s%n", finishTime.toString());
|
||||||
System.out.printf("Calculation took %s%n", Duration.between(startTime,finishTime).toString());
|
System.out.printf("Calculation took %s%n", Duration.between(startTime,finishTime).toString());
|
||||||
|
Loading…
Reference in New Issue
Block a user