Updatet architecture
This commit is contained in:
parent
74e58fca80
commit
1f7be09fb2
@ -3,3 +3,7 @@
|
||||
\.chg\..*$
|
||||
\.rej$
|
||||
\.conflict\~$
|
||||
.gradle
|
||||
build/
|
||||
.idea/*
|
||||
!gradle-wrapper.jar
|
||||
|
@ -1,5 +1,5 @@
|
||||
apply plugin: 'java'
|
||||
apply plugin: 'maven'
|
||||
apply plugin: 'idea'
|
||||
apply plugin: 'application'
|
||||
|
||||
|
||||
|
@ -1,33 +0,0 @@
|
||||
/*
|
||||
* To change this template, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
package inr.numass.trapping;
|
||||
|
||||
/**
|
||||
* Класс нужен исключительно чтобы сделать простой доступ к Сишным экспортам
|
||||
* @author Darksnake
|
||||
*/
|
||||
public class DoubleValue {
|
||||
private double value;
|
||||
|
||||
public DoubleValue(double value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @return the value
|
||||
*/
|
||||
public double getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param value the value to set
|
||||
*/
|
||||
public void setValue(double value) {
|
||||
this.value = value;
|
||||
}
|
||||
}
|
123
src/main/java/inr/numass/trapping/SimulationManager.java
Normal file
123
src/main/java/inr/numass/trapping/SimulationManager.java
Normal file
@ -0,0 +1,123 @@
|
||||
package inr.numass.trapping;
|
||||
|
||||
import org.apache.commons.math3.random.JDKRandomGenerator;
|
||||
import org.apache.commons.math3.random.RandomGenerator;
|
||||
|
||||
import java.io.PrintStream;
|
||||
import java.util.function.Predicate;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
/**
|
||||
* Created by darksnake on 04-Jun-16.
|
||||
*/
|
||||
public class SimulationManager {
|
||||
|
||||
RandomGenerator generator = new JDKRandomGenerator();
|
||||
Simulator simulator = new Simulator();
|
||||
private double initialE = 18000;
|
||||
private PrintStream output = System.out;
|
||||
private PrintStream statisticOutput = System.out;
|
||||
|
||||
|
||||
public SimulationManager withParameters(double bSource, double bTransport, double bPinch, double initialE, double energyRange) {
|
||||
this.simulator = new Simulator(bSource, bTransport, bPinch, initialE - energyRange);
|
||||
this.initialE = initialE;
|
||||
return this;
|
||||
}
|
||||
|
||||
public SimulationManager withOutput(PrintStream output) {
|
||||
this.output = output;
|
||||
return this;
|
||||
}
|
||||
|
||||
public SimulationManager withStatisticOutput(PrintStream statisticOutput) {
|
||||
this.statisticOutput = statisticOutput;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Симулируем пролет num электронов.
|
||||
*
|
||||
* @param num
|
||||
* @return
|
||||
*/
|
||||
public synchronized Counter simulateAll(int num) {
|
||||
Counter counter = new Counter();
|
||||
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);
|
||||
Stream.generate(() -> getRandomTheta()).limit(num).parallel()
|
||||
.forEach((theta) -> {
|
||||
Simulator.SimulationResult res = simulator.simulate(initialE, theta);
|
||||
if (reportIf.test(res)) {
|
||||
if (output != null) {
|
||||
printOne(output, res);
|
||||
}
|
||||
}
|
||||
counter.count(res);
|
||||
});
|
||||
printStatistics(counter);
|
||||
return counter;
|
||||
}
|
||||
|
||||
private double getRandomTheta() {
|
||||
double x = generator.nextDouble();
|
||||
return Math.acos(x);
|
||||
}
|
||||
|
||||
private void printStatistics(Counter counter) {
|
||||
output.printf("The total number of events is %d.%n%n", counter.count);
|
||||
|
||||
output.printf("The spectrometer acceptance angle is %g.%n", simulator.thetaPinch * 180 / Math.PI);
|
||||
output.printf("The transport reflection angle is %g.%n", simulator.thetaTransport * 180 / Math.PI);
|
||||
output.printf("The starting energy is %g.%n", initialE);
|
||||
output.printf("The lower energy boundary is %g.%n%n", simulator.Elow);
|
||||
|
||||
output.printf("The total number of ACCEPTED events is %d.%n", counter.accepted);
|
||||
output.printf("The total number of PASS events is %d.%n", counter.pass);
|
||||
output.printf("The total number of REJECTED events is %d.%n", counter.rejected);
|
||||
output.printf("The total number of LOWENERGY events is %d.%n%n", counter.lowE);
|
||||
}
|
||||
|
||||
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());
|
||||
}
|
||||
|
||||
|
||||
public static class Counter {
|
||||
int accepted = 0;
|
||||
int pass = 0;
|
||||
int rejected = 0;
|
||||
int lowE = 0;
|
||||
int count = 0;
|
||||
|
||||
public synchronized Simulator.SimulationResult count(Simulator.SimulationResult res) {
|
||||
count++;
|
||||
switch (res.state) {
|
||||
case ACCEPTED:
|
||||
accepted++;
|
||||
break;
|
||||
case LOWENERGY:
|
||||
lowE++;
|
||||
break;
|
||||
case PASS:
|
||||
pass++;
|
||||
break;
|
||||
case REJECTED:
|
||||
rejected++;
|
||||
break;
|
||||
case NONE:
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
public synchronized void reset() {
|
||||
count = 0;
|
||||
accepted = 0;
|
||||
pass = 0;
|
||||
rejected = 0;
|
||||
lowE = 0;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
@ -5,9 +5,9 @@
|
||||
package inr.numass.trapping;
|
||||
|
||||
import java.io.PrintStream;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.function.Predicate;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import org.apache.commons.math3.geometry.euclidean.threed.Rotation;
|
||||
import org.apache.commons.math3.geometry.euclidean.threed.SphericalCoordinates;
|
||||
import org.apache.commons.math3.geometry.euclidean.threed.Vector3D;
|
||||
@ -18,23 +18,28 @@ import org.apache.commons.math3.util.Pair;
|
||||
import org.apache.commons.math3.util.Precision;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Darksnake
|
||||
*/
|
||||
public class ElectronTrappingSimulator {
|
||||
public class Simulator {
|
||||
|
||||
private RandomGenerator generator;
|
||||
Scatter scatter;
|
||||
double Elow = 14000d;
|
||||
double thetaTransport = 24.107064 / 180 * Math.PI;
|
||||
double thetaPinch = 19.481097 / 180 * Math.PI;
|
||||
private Scatter scatter;
|
||||
double Elow = 14000d;//default value
|
||||
double thetaTransport = 24.107064 / 180 * Math.PI;// default value
|
||||
double thetaPinch = 19.481097 / 180 * Math.PI;// default value
|
||||
|
||||
|
||||
public ElectronTrappingSimulator() {
|
||||
public Simulator() {
|
||||
generator = new SynchronizedRandomGenerator(new MersenneTwister());
|
||||
scatter = new Scatter(generator);
|
||||
}
|
||||
|
||||
public Simulator(double Bsource, double Btransport, double Bpinch, double Elow){
|
||||
this();
|
||||
setFields(Bsource, Btransport, Bpinch);
|
||||
setElow(Elow);
|
||||
}
|
||||
|
||||
public static enum EndState {
|
||||
|
||||
ACCEPTED,//трэппинговый электрон попал в аксептанс
|
||||
@ -44,7 +49,11 @@ public class ElectronTrappingSimulator {
|
||||
NONE
|
||||
}
|
||||
|
||||
public void setFields(double Bsource, double Btransport, double Bpinch) {
|
||||
public final void setElow(double elow) {
|
||||
Elow = elow;
|
||||
}
|
||||
|
||||
public final void setFields(double Bsource, double Btransport, double Bpinch) {
|
||||
this.thetaTransport = Math.asin(Math.sqrt(Bsource / Btransport));
|
||||
this.thetaPinch = Math.asin(Math.sqrt(Bsource / Bpinch));
|
||||
}
|
||||
@ -55,20 +64,19 @@ public class ElectronTrappingSimulator {
|
||||
* Считаем, что за один проход источника происходит в среднем существенно
|
||||
* меньше одного столкновения, поэтому выход вперед или назад совершенно
|
||||
* симментричны.
|
||||
*
|
||||
*/
|
||||
public SimulaionResult simulateOne(double initEnergy, double initTheta) {
|
||||
public SimulationResult simulate(double initEnergy, double initTheta) {
|
||||
assert initEnergy > 0;
|
||||
assert initTheta > 0 && initTheta < Math.PI / 2;
|
||||
|
||||
if (initTheta < this.thetaPinch) {
|
||||
if (generator.nextBoolean()) {
|
||||
return new SimulaionResult(EndState.PASS, initEnergy, initTheta, initTheta, 0);
|
||||
return new SimulationResult(EndState.PASS, initEnergy, initTheta, initTheta, 0);
|
||||
} else {
|
||||
return new SimulaionResult(EndState.REJECTED, initEnergy, initTheta, initTheta, 0);
|
||||
return new SimulationResult(EndState.REJECTED, initEnergy, initTheta, initTheta, 0);
|
||||
}
|
||||
} else if (initTheta < this.thetaTransport) {
|
||||
return new SimulaionResult(EndState.REJECTED, initEnergy, initTheta, initTheta, 0);
|
||||
return new SimulationResult(EndState.REJECTED, initEnergy, initTheta, initTheta, 0);
|
||||
}
|
||||
|
||||
double E = initEnergy;
|
||||
@ -80,7 +88,7 @@ public class ElectronTrappingSimulator {
|
||||
|
||||
while (!stopflag) {
|
||||
colNum++;
|
||||
Pair<Double,Double> delta;
|
||||
Pair<Double, Double> delta;
|
||||
|
||||
//Вычисляем сечения и нормируем их на полное сечение
|
||||
double sigmaIon = scatter.sigmaion(E);
|
||||
@ -138,12 +146,9 @@ public class ElectronTrappingSimulator {
|
||||
state = EndState.LOWENERGY;
|
||||
}
|
||||
}
|
||||
SimulaionResult res = new SimulaionResult(state, E, theta, initTheta, colNum);
|
||||
if (state == EndState.ACCEPTED) {
|
||||
printOne(System.out, res);
|
||||
}
|
||||
return res;
|
||||
|
||||
SimulationResult res = new SimulationResult(state, E, theta, initTheta, colNum);
|
||||
return res;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -153,15 +158,15 @@ public class ElectronTrappingSimulator {
|
||||
* @param dTheta
|
||||
* @return
|
||||
*/
|
||||
double addTheta(double theta, double dTheta) {
|
||||
private double addTheta(double theta, double dTheta) {
|
||||
//Генерируем случайный фи
|
||||
double phi = generator.nextDouble()* 2 * Math.PI;
|
||||
double phi = generator.nextDouble() * 2 * Math.PI;
|
||||
//Создаем начальный вектор в сферических координатах
|
||||
SphericalCoordinates init = new SphericalCoordinates(1, 0, theta + dTheta);
|
||||
// Задаем вращение относительно оси, перпендикулярной исходному вектору
|
||||
SphericalCoordinates rotate = new SphericalCoordinates(1, 0, theta);
|
||||
// поворачиваем исходный вектор на dTheta
|
||||
Rotation rot = new Rotation(rotate.getCartesian(), phi);
|
||||
Rotation rot = new Rotation(rotate.getCartesian(), phi, null);
|
||||
|
||||
Vector3D result = rot.applyTo(init.getCartesian());
|
||||
|
||||
@ -169,24 +174,6 @@ public class ElectronTrappingSimulator {
|
||||
return Math.acos(result.getZ());
|
||||
}
|
||||
|
||||
/**
|
||||
* Симулируем пролет num электронов.
|
||||
*
|
||||
* @param E
|
||||
* @param num
|
||||
* @return
|
||||
*/
|
||||
public List<SimulaionResult> simulateAll(double E, int num) {
|
||||
System.out.printf("%nStarting sumulation with initial energy %g and %d electrons.%n%n", E, num);
|
||||
return Stream.generate(() -> getRandomTheta()).limit(num).parallel()
|
||||
.map(theta -> simulateOne(E, theta))
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
public static void printOne(PrintStream out, SimulaionResult 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());
|
||||
}
|
||||
|
||||
private double normalizeTheta(double theta) {
|
||||
double res = theta;
|
||||
if (theta < 0) {
|
||||
@ -203,24 +190,30 @@ public class ElectronTrappingSimulator {
|
||||
}
|
||||
}
|
||||
|
||||
public double getRandomTheta() {
|
||||
double x = generator.nextDouble();
|
||||
return Math.acos(x);
|
||||
public void resetDebugCounters(){
|
||||
scatter.counter.resetAll();
|
||||
}
|
||||
|
||||
public class SimulaionResult {
|
||||
public void printDebugCounters(){
|
||||
scatter.counter.print(System.out);
|
||||
}
|
||||
|
||||
public SimulaionResult(EndState state, double E, double theta, double initTheta, int collisionNumber) {
|
||||
public static class SimulationResult {
|
||||
|
||||
public SimulationResult(EndState state, double E, double theta, double initTheta, int collisionNumber) {
|
||||
this.state = state;
|
||||
this.E = E;
|
||||
this.theta = theta;
|
||||
this.initTheta = initTheta;
|
||||
this.collisionNumber = collisionNumber;
|
||||
}
|
||||
|
||||
public EndState state;
|
||||
public double E;
|
||||
public double initTheta;
|
||||
public double theta;
|
||||
public int collisionNumber;
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -1,91 +1,13 @@
|
||||
package inr.numass.trapping;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.PrintStream;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Hello world!
|
||||
*
|
||||
*/
|
||||
public class Trapping {
|
||||
|
||||
public static void main(String[] args) throws FileNotFoundException {
|
||||
PrintStream out = null;
|
||||
if ((args.length > 0) && (args[0] != null)) {
|
||||
File file = new File(args[0]);
|
||||
out = new PrintStream(file);
|
||||
} else {
|
||||
|
||||
}
|
||||
|
||||
double E = 18000d;
|
||||
System.out.println();
|
||||
ElectronTrappingSimulator simulator = new ElectronTrappingSimulator();
|
||||
simulator.setFields(0.6, 3.6, 7.2);
|
||||
|
||||
int accepted = 0;
|
||||
int pass = 0;
|
||||
int rejected = 0;
|
||||
int lowE = 0;
|
||||
|
||||
simulator.scatter.counter.resetAll();
|
||||
List<ElectronTrappingSimulator.SimulaionResult> results = simulator.simulateAll(E, (int) 1e6);
|
||||
simulator.scatter.counter.print(System.out);
|
||||
|
||||
System.out.printf("%nSimulation complete.%n%n");
|
||||
|
||||
for (ElectronTrappingSimulator.SimulaionResult res : results) {
|
||||
switch (res.state) {
|
||||
case ACCEPTED:
|
||||
// ElectronTrappingSimulator.printOne(System.out, res);
|
||||
if (out != null) {
|
||||
ElectronTrappingSimulator.printOne(out, res);
|
||||
}
|
||||
accepted++;
|
||||
break;
|
||||
case LOWENERGY:
|
||||
lowE++;
|
||||
break;
|
||||
case PASS:
|
||||
pass++;
|
||||
break;
|
||||
case REJECTED:
|
||||
rejected++;
|
||||
break;
|
||||
case NONE:
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
}
|
||||
|
||||
System.out.printf("%nThe total number of events is %d.%n%n", results.size());
|
||||
|
||||
System.out.printf("The spectrometer acceptance angle is %g.%n", simulator.thetaPinch * 180 / Math.PI);
|
||||
System.out.printf("The transport reflection angle is %g.%n", simulator.thetaTransport * 180 / Math.PI);
|
||||
System.out.printf("The starting energy is %g.%n", E);
|
||||
System.out.printf("The lower energy boundary is %g.%n%n", simulator.Elow);
|
||||
|
||||
System.out.printf("The total number of ACCEPTED events is %d.%n", accepted);
|
||||
System.out.printf("The total number of PASS events is %d.%n", pass);
|
||||
System.out.printf("The total number of REJECTED events is %d.%n", rejected);
|
||||
System.out.printf("The total number of LOWENERGY events is %d.%n%n", lowE);
|
||||
|
||||
if (out != null) {
|
||||
out.println();
|
||||
out.printf("The total number of events is %d.%n%n", results.size());
|
||||
|
||||
out.printf("The spectrometer acceptance angle is %g.%n", simulator.thetaPinch * 180 / Math.PI);
|
||||
out.printf("The transport reflection angle is %g.%n", simulator.thetaTransport * 180 / Math.PI);
|
||||
out.printf("The starting energy is %g.%n", E);
|
||||
out.printf("The lower energy boundary is %g.%n%n", simulator.Elow);
|
||||
|
||||
out.printf("The total number of ACCEPTED events is %d.%n", accepted);
|
||||
out.printf("The total number of PASS events is %d.%n", pass);
|
||||
out.printf("The total number of REJECTED events is %d.%n", rejected);
|
||||
out.printf("The total number of LOWENERGY events is %d.%n%n", lowE);
|
||||
out.close();
|
||||
}
|
||||
|
||||
// new SimulationManager().withParameters(0.6, 3.7, 7.2, 18000d, 4000).simulateAll((int) 1e6);
|
||||
new SimulationManager().withParameters(0.6, 3.7, 4.84, 14000d, 4000).simulateAll((int) 1e6);
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user