New iteration

This commit is contained in:
Alexander Nozik 2016-06-10 23:02:36 +03:00
parent 88b0cd1c02
commit 38f26f93c5
4 changed files with 119 additions and 103 deletions

View File

@ -18,7 +18,7 @@ tasks.withType(JavaCompile) {
} }
repositories { repositories {
mavencentral() mavenCentral()
} }
dependencies { dependencies {

View File

@ -7,7 +7,7 @@ import org.apache.commons.math3.random.JDKRandomGenerator;
import org.apache.commons.math3.random.RandomGenerator; import org.apache.commons.math3.random.RandomGenerator;
import org.apache.commons.math3.random.SynchronizedRandomGenerator; import org.apache.commons.math3.random.SynchronizedRandomGenerator;
import java.io.PrintStream; import java.io.*;
import java.util.Map; import java.util.Map;
import java.util.function.Function; import java.util.function.Function;
import java.util.function.Predicate; import java.util.function.Predicate;
@ -31,6 +31,16 @@ public class SimulationManager {
return this; return this;
} }
public SimulationManager withOutputFile(String fileName) throws IOException {
File outputFile = new File(fileName);
if (!outputFile.exists()) {
outputFile.getParentFile().mkdirs();
outputFile.createNewFile();
}
this.output = new PrintStream(new FileOutputStream(outputFile));
return this;
}
/** /**
* Select output for accepted events * Select output for accepted events
* *
@ -100,7 +110,7 @@ public class SimulationManager {
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);
Stream.generate(() -> getRandomTheta()).limit(num).parallel() Stream.generate(() -> getRandomTheta()).limit(num).parallel()
.forEach((theta) -> { .forEach((theta) -> {
double initZ = (generator.nextDouble()-1) * Simulator.SOURCE_LENGTH; double initZ = (generator.nextDouble() - 0.5) * Simulator.SOURCE_LENGTH;
Simulator.SimulationResult res = simulator.simulate(initialE, theta, initZ); Simulator.SimulationResult res = simulator.simulate(initialE, theta, initZ);
if (reportIf.test(res)) { if (reportIf.test(res)) {
if (output != null) { if (output != null) {

View File

@ -11,7 +11,6 @@ import org.apache.commons.math3.geometry.euclidean.threed.SphericalCoordinates;
import org.apache.commons.math3.geometry.euclidean.threed.Vector3D; import org.apache.commons.math3.geometry.euclidean.threed.Vector3D;
import org.apache.commons.math3.random.JDKRandomGenerator; import org.apache.commons.math3.random.JDKRandomGenerator;
import org.apache.commons.math3.random.RandomGenerator; import org.apache.commons.math3.random.RandomGenerator;
import org.apache.commons.math3.util.DoubleArray;
import org.apache.commons.math3.util.Pair; import org.apache.commons.math3.util.Pair;
import org.apache.commons.math3.util.Precision; import org.apache.commons.math3.util.Precision;
@ -23,7 +22,7 @@ import static org.apache.commons.math3.util.FastMath.*;
public class Simulator { public class Simulator {
public static final double SOURCE_LENGTH = 3d; public static final double SOURCE_LENGTH = 3d;
private static final double DELTA_L = 0.1; //step for deltaZ calculation private static final double DELTA_L = 0.1; //step for propagate calculation
private RandomGenerator generator; private RandomGenerator generator;
private Scatter scatter; private Scatter scatter;
@ -123,64 +122,104 @@ public class Simulator {
} }
/** /**
* @param position * Calculate propagated position
* @param dl
* @return
*/
private State propagate(State position, double dl, double dz) {
//increase l
position.l += dl;
position.addZ(dz);
return position;
}
/**
* calculate z coordinate change with known path length. Does not change position.
* *
* @param deltaL * @param deltaL
* @return z shift and reflection counter * @return z shift and reflection counter
*/ */
private Pair<Double, Integer> deltaZ(State position, double deltaL) { private State propagate(State pos, double deltaL) {
// 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
int direction = position.isForward() ? 1 : -1;
if (magneticField == null) { if (magneticField == null) {
double deltaZ = direction * deltaL * cos(position.theta); double deltaZ = deltaL * cos(pos.theta); // direction already included in cos(theta)
int reflectionCounter = (int) (deltaZ / SOURCE_LENGTH);
double curZ = normalizeZ(position.z + deltaZ); //if we are crossing source boundary, check for end condition
return new Pair<>(curZ - position.z, reflectionCounter); if(abs(deltaZ + pos.z)>SOURCE_LENGTH/2d) {
checkEndState(pos);
}
// if track is finished apply boundary position
if (pos.isFinished()) {
// remembering old z to correctly calculate total l
double oldz = pos.z;
pos.z = pos.direction() * SOURCE_LENGTH / 2d;
pos.l += (pos.z - oldz)/cos(pos.theta);
} else {
//else just add z
pos.l += deltaL;
pos.addZ(deltaZ);
}
return pos;
} else { } else {
int reflect = 0;
double curZ = position.z;
double curL = 0; double curL = 0;
double sin2 = sin(pos.theta) * sin(pos.theta);
while (curL <= deltaL - 0.01 && !pos.isFinished()) {
//an l step
double delta = min(deltaL - curL, DELTA_L);
double sin2 = sin(position.theta) * sin(position.theta); double b = field(pos.z);
while (curL <= deltaL) {
double delta = DELTA_L; //min(deltaL - curL, DELTA_L);
double b = field(curZ);
//TODO check this!
double root = 1 - sin2 * b / bSource; double root = 1 - sin2 * b / bSource;
// change direction in case of reflection. Loss of precision here? // change direction in case of reflection. Loss of precision here?
if (root < 0) { if (root < 0) {
direction = -direction; //flip direction
root = -root; pos.flip();
reflect++; // 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);
} }
curZ += direction * delta * sqrt(root); //normalize in case reflection is beyound the source
if (abs(pos.z) > SOURCE_LENGTH / 2d) {
curZ = normalizeZ(curZ); pos.z = signum(pos.z) * SOURCE_LENGTH / 2d;
if(signum(pos.z)== pos.direction()){
pos.flip();
}
}
curL += delta; curL += delta;
pos.l += delta;
} }
return new Pair<>(curZ - position.z, reflect); return pos;
} }
} }
/** /**
* Magnetic field with reflection taken into account * 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
* *
* @param z * @param z
* @return * @return
@ -193,19 +232,6 @@ public class Simulator {
} }
} }
private double normalizeZ(double z) {
while ((abs(z) > SOURCE_LENGTH / 2)) {
if (z < 0) {
// reflecting from rear pinch
z += SOURCE_LENGTH / 2d;
} else {
// reflecting from forward transport magnet
z -= SOURCE_LENGTH / 2d;
}
}
return z;
}
/** /**
* Симулируем один пробег электрона от начального значения и до вылетания из * Симулируем один пробег электрона от начального значения и до вылетания из
* иточника или до того момента, как энергия становится меньше eLow. * иточника или до того момента, как энергия становится меньше eLow.
@ -216,52 +242,24 @@ public class Simulator {
assert abs(initZ) <= SOURCE_LENGTH / 2d; assert abs(initZ) <= SOURCE_LENGTH / 2d;
State pos = new State(initEnergy, initTheta, initZ); State pos = new State(initEnergy, initTheta, initZ);
EndState endState = EndState.NONE;
boolean stopflag = false;
while (!stopflag) {
while (!pos.isFinished()) {
double dl = freePath(pos.e); // path to next scattering double dl = freePath(pos.e); // path to next scattering
Pair<Double, Integer> dzCalc = deltaZ(pos, dl); // propagate to next scattering position
double dz = dzCalc.getFirst();// z coordinate to next scattering propagate(pos,dl);
int reflections = dzCalc.getSecond();
//if no scattering on current source pass if (!pos.isFinished()) {
if (reflections > 0) {
//accepted by spectrometer
if (pos.theta < thetaPinch) {
stopflag = true;
if (pos.colNum == 0) {
//counting pass electrons
endState = EndState.PASS;
} else {
endState = EndState.ACCEPTED;
}
}
//through the rear magnetic pinch
if (pos.theta >= PI - thetaTransport) {
stopflag = true;
endState = EndState.REJECTED;
}
}
if (!stopflag) {
// perform scatter // perform scatter
propagate(pos, dl, dz);
pos.colNum++;
scatter(pos); scatter(pos);
pos.colNum++;
if (pos.e < eLow) { if (pos.e < eLow) {
//Если энергия стала слишком маленькой //Если энергия стала слишком маленькой
stopflag = true; pos.setEndState(EndState.LOWENERGY);
endState = EndState.LOWENERGY; }
} }
} }
} SimulationResult res = new SimulationResult(pos.endState, pos.e, pos.theta, initTheta, pos.colNum, pos.l);
SimulationResult res = new SimulationResult(endState, pos.e, pos.theta, initTheta, pos.colNum, pos.l);
return res; return res;
} }
@ -330,6 +328,8 @@ public class Simulator {
*/ */
double z; double z;
EndState endState = EndState.NONE;
/** /**
* @param dE * @param dE
* @return resulting E * @return resulting E
@ -343,6 +343,18 @@ public class Simulator {
return theta <= Math.PI / 2; return theta <= Math.PI / 2;
} }
double direction() {
return isForward() ? 1 : -1;
}
boolean isFinished() {
return this.endState != EndState.NONE;
}
void setEndState(EndState state) {
this.endState = state;
}
/** /**
* add Z and calculate direction change * add Z and calculate direction change
* *
@ -354,12 +366,13 @@ public class Simulator {
while (abs(this.z) > SOURCE_LENGTH / 2d) { while (abs(this.z) > SOURCE_LENGTH / 2d) {
// reflecting from back wall // reflecting from back wall
if (z < 0) { if (z < 0) {
z += SOURCE_LENGTH / 2d; // reflecting from rear pinch
flip(); z = -SOURCE_LENGTH - z;
} else { } else {
z -= SOURCE_LENGTH / 2d; // reflecting from forward transport magnet
flip(); z = SOURCE_LENGTH - z;
} }
flip();
} }
return z; return z;
} }
@ -400,6 +413,7 @@ public class Simulator {
} }
} }
/** /**
* Сложение вектора с учетом случайно распределения по фи * Сложение вектора с учетом случайно распределения по фи
* *

View File

@ -8,16 +8,7 @@ import java.time.Instant;
public class Trapping { public class Trapping {
public static void main(String[] args) throws IOException { public static void main(String[] args) throws IOException {
// new SimulationManager().withParameters(0.6, 3.7, 7.2, 18000d, 4000).simulateAll((int) 1e6); // new SimulationManager().withParameters(0.6, 3.7, 7.2, 18000d, 4000).simulateAll((int) 1e6);
double[] z = {-1.736, -1.27, -0.754, -0.238, 0.278, 0.794, 1.31, 1.776};
// -0.236 3.70754
// 0.23 0.62786
// 0.746 0.60474
// 1.262 0.60325
// 1.778 0.60333
// 2.294 0.60503
// 2.81 0.6285
// 3.276 3.70478
double[] z = {-0.236, 0.23, 0.746, 1.262, 1.778, 2.294, 2.81, 3.276};
double[] b = {3.70754, 0.62786, 0.60474, 0.60325, 0.60333, 0.60503, 0.6285, 3.70478}; double[] b = {3.70754, 0.62786, 0.60474, 0.60325, 0.60333, 0.60503, 0.6285, 3.70478};
System.out.println("Press any key to start..."); System.out.println("Press any key to start...");
System.in.read(); System.in.read();
@ -25,9 +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")
// .withFieldMap(z, b) // .withFieldMap(z, b)
// .withDensity(5e20) // .withDensity(5e20)
.simulateAll((int) 1e5); .simulateAll((int) 1e4);
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());