diff --git a/common-tools/cnuphys/apache/.classpath b/common-tools/cnuphys/apache/.classpath
new file mode 100644
index 0000000000..6ae56430f7
--- /dev/null
+++ b/common-tools/cnuphys/apache/.classpath
@@ -0,0 +1,6 @@
+
+
+ * This “basic” listener never requests termination on its own; the integrator will
+ * stop when the configured maximum path length {@code sMax} is reached. Specialized
+ * subclasses (e.g., z, rho, plane, cylinder) override termination checks to stop when
+ * a target condition is met within a requested accuracy.
+ *
+ * A {@code CLAS12SwimResult} encapsulates:
+ *
+ * This class is a passive data container and is not thread-safe for mutation.
+ *
+ * The value is one of the {@link CLAS12Swimmer} status constants, e.g.
+ * {@link CLAS12Swimmer#SWIM_SUCCESS}, {@link CLAS12Swimmer#SWIM_TARGET_MISSED},
+ * or {@link CLAS12Swimmer#BELOW_MIN_MOMENTUM}.
+ *
+ * The state vector {@code u} has length 6 and is interpreted as:
+ * true as required.
*/
@Override
- public boolean add(Integer wire) {
+ public boolean add(Byte wire) {
if ((wire < 0) || (wire >= _numWires)) {
System.err.println("Bad wire index on WireList add: " + wire);
}
@@ -74,7 +74,7 @@ public boolean add(Integer wire) {
@Override
public boolean remove(Object o) {
_avgWire = Double.NaN;
- return super.remove((Integer)o);
+ return super.remove((Byte)o);
}
/**
@@ -82,7 +82,7 @@ public boolean remove(Object o) {
* @param wire the 0-based wire index
* @return the repeat count
*/
- public int getCount(int wire) {
+ public int getCount(byte wire) {
return counts[wire];
}
@@ -126,7 +126,7 @@ public double averageWirePosition() {
int totalCount = 0;
double sum = 0;
- for (int wire : this) {
+ for (byte wire : this) {
sum += counts[wire]*wire;
totalCount += counts[wire];
}
@@ -152,7 +152,7 @@ public boolean hasSubset(WireList wl) {
return false;
}
- for (Integer e : wl) {
+ for (Byte e : wl) {
if (!contains(e)) {
return false;
}
diff --git a/common-tools/cnuphys/splot/.classpath b/common-tools/cnuphys/splot/.classpath
new file mode 100644
index 0000000000..748dc76710
--- /dev/null
+++ b/common-tools/cnuphys/splot/.classpath
@@ -0,0 +1,8 @@
+
+true if we crossed the boundary, in which case we should
+ * terminate and interpolate to the intersection.
+ */
+ public abstract boolean crossedBoundary(double newS, double[] newU);
+
+}
diff --git a/common-tools/cnuphys/swimmer/src/main/java/cnuphys/CLAS12Swim/CLAS12CylinderListener.java b/common-tools/cnuphys/swimmer/src/main/java/cnuphys/CLAS12Swim/CLAS12CylinderListener.java
new file mode 100644
index 0000000000..0ac98004bd
--- /dev/null
+++ b/common-tools/cnuphys/swimmer/src/main/java/cnuphys/CLAS12Swim/CLAS12CylinderListener.java
@@ -0,0 +1,57 @@
+package cnuphys.CLAS12Swim;
+
+import cnuphys.CLAS12Swim.geometry.Cylinder;
+
+/**
+ * A listener for swimming to the surface of a fixed infinite cylinder
+ */
+
+public class CLAS12CylinderListener extends CLAS12BoundaryListener {
+
+ // the target cylinder
+ private Cylinder _targetCylinder;
+
+ // starting inside or outside
+ private boolean _inside;
+
+ /**
+ * Create a CLAS12 boundary target cylinder listener, for swimming to a fixed
+ * infinite cylinder
+ *
+ * @param ivals the initial values of the swim
+ * @param targetCylinder the target infinite cylinder
+ * @param accuracy the desired accuracy (cm)
+ * @param sMax the final or max path length (cm)
+ */
+ public CLAS12CylinderListener(CLAS12Values ivals, Cylinder targetCylinder, double accuracy, double sMax) {
+ super(ivals, accuracy, sMax);
+ _targetCylinder = targetCylinder;
+ _inside = _targetCylinder.isInside(ivals.x, ivals.y, ivals.z);
+ _canMakeStraightLine = false;
+ }
+
+ @Override
+ public boolean accuracyReached(double newS, double[] newU) {
+ double dist = _targetCylinder.distance(newU[0], newU[1], newU[2]);
+ return dist < _accuracy;
+ }
+
+ @Override
+ public boolean crossedBoundary(double newS, double[] newU) {
+ boolean newInside = _targetCylinder.isInside(newU[0], newU[1], newU[2]);
+ return newInside != _inside;
+ }
+
+ /**
+ * Get the absolute distance to the target (boundary) in cm.
+ *
+ * @param newS the new path length
+ * @param newU the new state vector
+ * @return the distance to the target (boundary) in cm.
+ */
+ @Override
+ public double distanceToTarget(double newS, double[] newU) {
+ return _targetCylinder.distance(newU[0], newU[1], newU[2]);
+ }
+
+}
diff --git a/common-tools/cnuphys/swimmer/src/main/java/cnuphys/CLAS12Swim/CLAS12DOCAListener.java b/common-tools/cnuphys/swimmer/src/main/java/cnuphys/CLAS12Swim/CLAS12DOCAListener.java
new file mode 100644
index 0000000000..26d5ec7fca
--- /dev/null
+++ b/common-tools/cnuphys/swimmer/src/main/java/cnuphys/CLAS12Swim/CLAS12DOCAListener.java
@@ -0,0 +1,93 @@
+package cnuphys.CLAS12Swim;
+
+/**
+ * This is an abstract class to be extended by classes that to a distance of
+ * closest approach. The assumption is that the first doca is the only one. i.e.
+ * we are not dealing with low energy particles looping about.
+ */
+
+public abstract class CLAS12DOCAListener extends CLAS12Listener {
+
+ // the requested accuracy in cm
+ protected final double _accuracy;
+
+ // current doca
+ protected double _currentDOCA = Double.POSITIVE_INFINITY;
+
+ /**
+ * Create a CLAS12 boundary crossing listener
+ *
+ * @param ivals the initial values of the swim
+ * @param accuracy the accuracy (cm)
+ * @param sMax the final or max path length (cm)
+ */
+ public CLAS12DOCAListener(CLAS12Values ivals, double accuracy, double sMax) {
+ super(ivals, sMax);
+ _accuracy = accuracy;
+ }
+
+ /**
+ * Reset the current DOCA to infinity
+ */
+ @Override
+ public void reset() {
+ _currentDOCA = Double.POSITIVE_INFINITY;
+ }
+
+ /**
+ * Get the requested accuracy (on on difference in successive docas)in cm.
+ *
+ * @return the requested accuracy
+ */
+ public double getAccuracy() {
+ return _accuracy;
+ }
+
+ /**
+ * Get the current estimate of the doca
+ *
+ * @return the current doca
+ */
+ public double getCurrentDOCA() {
+ return _currentDOCA;
+ }
+
+ /**
+ * Called when a new step is taken in the ODE solving process.
+ *
+ * @param newS The new path length after the step.
+ * @param newU The new state vector after the step.
+ * @return A boolean indicating whether to continue (true) or stop (false) the
+ * integration.
+ */
+ @Override
+ public boolean newStep(double newS, double[] newU) {
+ accept(newS, newU);
+
+ double doca = doca(newS, newU);
+
+ if (doca > _currentDOCA) { // getting farther
+ _status = CLAS12Swimmer.SWIM_SUCCESS;
+ return false;
+ }
+
+ // have we reached the max path length?
+ if (newS >= _sMax) {
+ _status = CLAS12Swimmer.SWIM_TARGET_MISSED;
+ return false;
+ }
+
+ _currentDOCA = doca;
+ return true;
+ }
+
+ /**
+ * Get the absolute distance to the target (boundary) in cm.
+ *
+ * @param newS the new path length
+ * @param newU the new state vector
+ * @return the distance to the target (boundary) in cm.
+ */
+ public abstract double doca(double newS, double[] newU);
+
+}
diff --git a/common-tools/cnuphys/swimmer/src/main/java/cnuphys/CLAS12Swim/CLAS12Listener.java b/common-tools/cnuphys/swimmer/src/main/java/cnuphys/CLAS12Swim/CLAS12Listener.java
new file mode 100644
index 0000000000..00874d54c8
--- /dev/null
+++ b/common-tools/cnuphys/swimmer/src/main/java/cnuphys/CLAS12Swim/CLAS12Listener.java
@@ -0,0 +1,254 @@
+package cnuphys.CLAS12Swim;
+
+/**
+ * Base ODE step listener used by {@link CLAS12Swimmer} to observe integration progress
+ * and optionally terminate the swim.
+ * State vector convention
+ * The state vector {@code u} passed to and stored by this listener has length 6:
+ *
+ *
+ *
+ * Neutral particles
+ * For {@code q = 0} the swimmer can optionally bypass ODE integration and propagate in a
+ * straight line. Whether a listener can compute a straight-line intersection depends on the
+ * target geometry; this is controlled by {@link #_canMakeStraightLine}.
+ */
+
+public class CLAS12Listener implements ODEStepListener {
+
+ /**
+ * This parameter controls whether the listener can make a straight line to the
+ * target for a neutral particle. Some can, like the basic, z, and rho
+ * listeners. Some, like the cylinder, cannot-- in which case we let the full
+ * swim occur.
+ */
+ protected boolean _canMakeStraightLine = true;
+
+ protected static final double TINY = 1.0e-8; // cm
+
+ // the trajectory if cached
+ protected CLAS12Trajectory _trajectory; // the cached trajectory
+
+ // the initial values
+ protected CLAS12Values _initialVaues; // initial values
+
+ // a status, one of the CLAS12Swimmer class constants
+ protected int _status = CLAS12Swimmer.SWIM_SWIMMING;
+
+ // the final (target) or maximum path length in cm
+ protected final double _sMax;
+
+ /**
+ * Create a CLAS12 listener
+ *
+ * @param ivals the initial values of the swim
+ * @param sMax the final or max path length (cm)
+ */
+ public CLAS12Listener(CLAS12Values ivals, double sMax) {
+ _initialVaues = ivals;
+ _sMax = sMax;
+
+ _trajectory = new CLAS12Trajectory(ivals);
+ reset();
+ }
+
+ /**
+ * This parameter controls whether the listener can make a straight line to the
+ * target for a neutral particle. Some can, like the basic, z, and rho
+ * listeners. Some, like the cylinder, cannot-- in which case we let the full
+ * swim occur.
+ *
+ * @return true if the listener can make a straight line to the
+ * target for a neutral particle.
+ */
+ public boolean canMakeStraightLine() {
+ return _canMakeStraightLine;
+ }
+
+ /**
+ * Get the final (target) or maximum path length in cm
+ *
+ * @return the final (target) or maximum path length in cm
+ */
+ public double getSMax() {
+ return _sMax;
+ }
+
+ /*
+ * Basic initialization and reset
+ */
+ public void reset() {
+ _status = CLAS12Swimmer.SWIM_SWIMMING;
+ _trajectory.clear();
+ _trajectory.add(0., _initialVaues.getU());
+ }
+
+ /**
+ * Called when a new step is taken in the ODE solving process.
+ *
+ * @param newS The new path length after the step.
+ * @param newU The new state vector after the step.
+ * @return A boolean indicating whether to continue (true) or stop (false) the
+ * integration.
+ */
+ @Override
+ public boolean newStep(double newS, double[] newU) {
+
+ accept(newS, newU);
+
+ // if we are done, set the status
+ if (Math.abs(newS - _sMax) < TINY) {
+ _status = CLAS12Swimmer.SWIM_SUCCESS;
+ }
+
+ // base always continues, the solve with integrate to sMax and stop
+ return true;
+ }
+
+ /**
+ * Accept the next step.
+ *
+ * @param newS The new path length after the step.
+ * @param newU The new state vector after the step.
+ */
+ protected void accept(double newS, double[] newU) {
+ _trajectory.add(newS, newU);
+ }
+
+ /**
+ * Get the trajectory
+ *
+ * @return the trajectory
+ */
+ public CLAS12Trajectory getTrajectory() {
+ return _trajectory;
+ }
+
+ /**
+ * Get the initial values
+ *
+ * @return the initial values
+ */
+ public CLAS12Values getIvals() {
+ return _initialVaues;
+ }
+
+ /**
+ * Get the current state vector
+ *
+ * @return the current state vector
+ */
+ public double[] getU() {
+ return _trajectory.get(_trajectory.size() - 1);
+ }
+
+ /**
+ * Get the state vector at the given index
+ *
+ * @param index the index
+ * @return the state vector
+ */
+ public double[] getU(int index) {
+ return _trajectory.get(index);
+ }
+
+ /**
+ * Get the number of integration steps
+ *
+ * @return the number of integration steps
+ */
+ public int getNumStep() {
+ return _trajectory.size();
+ }
+
+ /**
+ * Get the current path length
+ *
+ * @return the current path length in cm
+ */
+ public double getS() {
+ return _trajectory.getS(_trajectory.size() - 1);
+ }
+
+ /**
+ * Get the path length at the given index
+ *
+ * @param index the index
+ * @return the path length in cm
+ */
+ public double getS(int index) {
+ return _trajectory.getS(index);
+ }
+
+ /**
+ * Get the status of the swim. The values are the CLAS12Swimmer constants:
+ * SWIM_SUCCESS or SWIM_TARGET_MISSED.
+ *
+ * @return the status
+ */
+ public int getStatus() {
+ return _status;
+ }
+
+ /**
+ * Set the status
+ *
+ * @param status the status. The values are the CLAS12Swimmer constants:
+ * SWIM_SUCCESS or SWIM_TARGET_MISSED.
+ * @see CLAS12Swimmer
+ */
+ public void setStatus(int status) {
+ _status = status;
+ }
+
+ /**
+ * Get the status of the swim as a string
+ *
+ * @return the status of the swim as a string
+ */
+ public String statusString() {
+ String s = CLAS12Swimmer.resultNames.get(_status);
+ if (s == null) {
+ s = "Unknown (" + _status + ")";
+ }
+ return s;
+ }
+
+ /**
+ * Add a second point creating a straight line. This is only used when
+ * "swimming" neutral particles. This can be overridden to stop the straight
+ * line at a target.
+ */
+ public void straightLine() {
+
+ double xo = _initialVaues.x;
+ double yo = _initialVaues.y;
+ double zo = _initialVaues.z;
+ double theta = _initialVaues.theta;
+ double phi = _initialVaues.phi;
+ double sf = _sMax;
+
+ double sintheta = Math.sin(Math.toRadians(theta));
+ double costheta = Math.cos(Math.toRadians(theta));
+ double sinphi = Math.sin(Math.toRadians(phi));
+ double cosphi = Math.cos(Math.toRadians(phi));
+
+ double xf = xo + sf * sintheta * cosphi;
+ double yf = yo + sf * sintheta * sinphi;
+ double zf = zo + sf * costheta;
+
+ _trajectory.addPoint(xf, yf, zf, theta, phi, sf);
+ _status = CLAS12Swimmer.SWIM_SUCCESS;
+
+ }
+
+}
diff --git a/common-tools/cnuphys/swimmer/src/main/java/cnuphys/CLAS12Swim/CLAS12PlaneListener.java b/common-tools/cnuphys/swimmer/src/main/java/cnuphys/CLAS12Swim/CLAS12PlaneListener.java
new file mode 100644
index 0000000000..4810c69f6c
--- /dev/null
+++ b/common-tools/cnuphys/swimmer/src/main/java/cnuphys/CLAS12Swim/CLAS12PlaneListener.java
@@ -0,0 +1,67 @@
+package cnuphys.CLAS12Swim;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+
+import cnuphys.CLAS12Swim.geometry.Plane;
+import cnuphys.magfield.MagneticFieldInitializationException;
+import cnuphys.magfield.MagneticFields;
+import cnuphys.magfield.MagneticFields.FieldType;
+
+/**
+ * A listener for swimming to the surface of a fixed infinite plane
+ */
+
+public class CLAS12PlaneListener extends CLAS12BoundaryListener {
+
+ // the target plane
+ private Plane _targetPlane;
+
+ // the starting sign. When this changes we have crossed.
+ private double _startSign;
+
+ /**
+ * Create a CLAS12 boundary target plane listener, for swimming to a fixed
+ * infinite plane
+ *
+ * @param ivals the initial values of the swim
+ * @param targetPlane the target infinite plane
+ * @param accuracy the desired accuracy (cm)
+ * @param sMax the final or max path length (cm)
+ */
+ public CLAS12PlaneListener(CLAS12Values ivals, Plane targetPlane, double accuracy, double sMax) {
+ super(ivals, accuracy, sMax);
+ _targetPlane = targetPlane;
+ _startSign = _targetPlane.sign(ivals.x, ivals.y, ivals.z);
+ _canMakeStraightLine = false;
+ }
+
+ @Override
+ public boolean crossedBoundary(double newS, double[] newU) {
+ int sign = _targetPlane.sign(newU[0], newU[1], newU[2]);
+
+ if (sign != _startSign) {
+ return true;
+ }
+ return false;
+ }
+
+ @Override
+ public boolean accuracyReached(double newS, double[] newU) {
+ double distance = _targetPlane.distance(newU[0], newU[1], newU[2]);
+ return distance < _accuracy;
+ }
+
+ /**
+ * Get the absolute distance to the target (boundary) in cm.
+ *
+ * @param newS the new path length
+ * @param newU the new state vector
+ * @return the distance to the target (boundary) in cm.
+ */
+ @Override
+ public double distanceToTarget(double newS, double[] newU) {
+ return _targetPlane.distance(newU[0], newU[1], newU[2]);
+ }
+
+}
diff --git a/common-tools/cnuphys/swimmer/src/main/java/cnuphys/CLAS12Swim/CLAS12RhoListener.java b/common-tools/cnuphys/swimmer/src/main/java/cnuphys/CLAS12Swim/CLAS12RhoListener.java
new file mode 100644
index 0000000000..b524fb35cf
--- /dev/null
+++ b/common-tools/cnuphys/swimmer/src/main/java/cnuphys/CLAS12Swim/CLAS12RhoListener.java
@@ -0,0 +1,133 @@
+package cnuphys.CLAS12Swim;
+
+import cnuphys.magfield.FastMath;
+
+/**
+ * A listener for swimming to a fixed cylindrical radius (rho).
+ */
+public class CLAS12RhoListener extends CLAS12BoundaryListener {
+
+ // the target rho (cm)
+ private double _rhoTarget;
+
+ // the starting sign. When this changes we have crossed.
+ private double _startSign;
+
+ /**
+ * Create a CLAS12 boundary target Z listener, for swimming to a fixed z
+ *
+ * @param ivals the initial values of the swim
+ * @param rhoTarget the target rho (cylindrical r) (cm)
+ * @param accuracy the desired accuracy (cm)
+ * @param sMax the final or max path length (cm)
+ */
+ public CLAS12RhoListener(CLAS12Values ivals, double rhoTarget, double accuracy, double sMax) {
+ super(ivals, accuracy, sMax);
+ _rhoTarget = rhoTarget;
+
+ double x = ivals.x;
+ double y = ivals.y;
+ _startSign = sign(Math.hypot(x, y));
+ }
+
+ @Override
+ public boolean crossedBoundary(double newS, double[] newU) {
+ int sign = sign(rho(newU));
+
+ if (sign != _startSign) {
+ return true;
+ }
+ return false;
+ }
+
+ // the rho (cylindrical r) of the state vector in cm
+ private double rho(double u[]) {
+ double x = u[0];
+ double y = u[1];
+ return FastMath.hypot(x, y);
+ }
+
+ @Override
+ public boolean accuracyReached(double newS, double[] newU) {
+ double dRho = Math.abs(rho(newU) - _rhoTarget);
+ return dRho < _accuracy;
+ }
+
+ // left or right of the target rho?
+ private int sign(double rho) {
+ return (rho < _rhoTarget) ? -1 : 1;
+ }
+
+ /**
+ * Get the absolute distance to the target (boundary) in cm.
+ *
+ * @param newS the new path length
+ * @param newU the new state vector
+ * @return the distance to the target (boundary) in cm.
+ */
+ @Override
+ public double distanceToTarget(double newS, double[] newU) {
+ return Math.abs(rho(newU) - _rhoTarget);
+ }
+
+ /**
+ * Add a second point creating a straight line to the target rho
+ */
+ @Override
+ public void straightLine() {
+
+ double u[] = _trajectory.get(_trajectory.size() - 1);
+ double s = _trajectory.getS(_trajectory.size() - 1);
+
+ double u2[] = findPoint(u[0], u[1], u[2], u[3], u[4], u[5], _rhoTarget);
+
+ double dx = u2[0] - u[0];
+ double dy = u2[1] - u[1];
+ double dz = u2[2] - u[2];
+ double ds = Math.sqrt(dx * dx + dy * dy + dz * dz);
+
+ _trajectory.add(s + ds, u2);
+ _status = CLAS12Swimmer.SWIM_SUCCESS;
+
+ }
+
+ private double[] findPoint(double x0, double y0, double z0, double tx, double ty, double tz, double rTarget) {
+ // Calculate the coefficients of the quadratic equation
+ double a = tx * tx + ty * ty;
+ double b = 2 * (x0 * tx + y0 * ty);
+ double c = x0 * x0 + y0 * y0 - rTarget * rTarget;
+
+ // Solve the quadratic equation
+ double discriminant = b * b - 4 * a * c;
+ if (discriminant < 0) {
+ return null; // No real solutions, rTarget cannot be reached
+ }
+
+ // Find the two possible values of s
+ double t1 = (-b + Math.sqrt(discriminant)) / (2 * a);
+ double t2 = (-b - Math.sqrt(discriminant)) / (2 * a);
+
+ // Choose the appropriate t (the one with the smaller positive value)
+
+ if (t1 < 0 && t2 < 0) {
+ return null;
+ }
+
+ double t;
+ if (t1 < 0) {
+ t = t2;
+ } else if (t2 < 0) {
+ t = t1;
+ } else {
+ t = Math.min(t1, t2);
+ }
+
+ // Calculate the resulting point
+ double x = x0 + tx * t;
+ double y = y0 + ty * t;
+ double z = z0 + tz * t;
+
+ return new double[] { x, y, z, tx, ty, tz };
+ }
+
+}
diff --git a/common-tools/cnuphys/swimmer/src/main/java/cnuphys/CLAS12Swim/CLAS12SphereListener.java b/common-tools/cnuphys/swimmer/src/main/java/cnuphys/CLAS12Swim/CLAS12SphereListener.java
new file mode 100644
index 0000000000..eb939adcb9
--- /dev/null
+++ b/common-tools/cnuphys/swimmer/src/main/java/cnuphys/CLAS12Swim/CLAS12SphereListener.java
@@ -0,0 +1,57 @@
+package cnuphys.CLAS12Swim;
+
+import cnuphys.CLAS12Swim.geometry.Sphere;
+
+/**
+ * A listener for swimming to the surface of a fixed sphere
+ */
+
+public class CLAS12SphereListener extends CLAS12BoundaryListener {
+
+ // the target sphere
+ private Sphere _targetSphere;
+
+ // starting inside or outside
+ private boolean _inside;
+
+ /**
+ * Create a CLAS12 boundary target sphere listener, for swimming to a fixed
+ * sphere
+ *
+ * @param ivals the initial values of the swim
+ * @param targetSphere the target infinite sphere
+ * @param accuracy the desired accuracy (cm)
+ * @param sMax the final or max path length (cm)
+ */
+ public CLAS12SphereListener(CLAS12Values ivals, Sphere targetSphere, double accuracy, double sMax) {
+ super(ivals, accuracy, sMax);
+ _targetSphere = targetSphere;
+ _inside = targetSphere.isInside(ivals.x, ivals.y, ivals.z);
+ _canMakeStraightLine = false;
+ }
+
+ @Override
+ public boolean accuracyReached(double newS, double[] newU) {
+ double dist = _targetSphere.distance(newU[0], newU[1], newU[2]);
+ return dist < _accuracy;
+ }
+
+ @Override
+ public boolean crossedBoundary(double newS, double[] newU) {
+ boolean newInside = _targetSphere.isInside(newU[0], newU[1], newU[2]);
+ return newInside != _inside;
+ }
+
+ /**
+ * Get the absolute distance to the target (boundary) in cm.
+ *
+ * @param newS the new path length
+ * @param newU the new state vector
+ * @return the distance to the target (boundary) in cm.
+ */
+ @Override
+ public double distanceToTarget(double newS, double[] newU) {
+ return _targetSphere.distance(newU[0], newU[1], newU[2]);
+ }
+
+}
diff --git a/common-tools/cnuphys/swimmer/src/main/java/cnuphys/CLAS12Swim/CLAS12SwimResult.java b/common-tools/cnuphys/swimmer/src/main/java/cnuphys/CLAS12Swim/CLAS12SwimResult.java
new file mode 100644
index 0000000000..63fc1ecfca
--- /dev/null
+++ b/common-tools/cnuphys/swimmer/src/main/java/cnuphys/CLAS12Swim/CLAS12SwimResult.java
@@ -0,0 +1,209 @@
+package cnuphys.CLAS12Swim;
+
+/**
+ * Result container returned by all {@code CLAS12Swimmer} swim operations.
+ *
+ *
+ *
+ * Termination semantics
+ * A swim may terminate because:
+ *
+ *
+ *
+ * The specific termination condition is encoded in {@link #getStatus()},
+ * and convenience predicates such as {@link #isSuccess()} are provided.
+ *
+ * State representation
+ * The final state is stored internally as:
+ *
+ *
+ *
+ * Trajectory storage
+ * Depending on how the swim was configured, the result may contain a sampled
+ * trajectory. Trajectories are typically used for visualization or debugging
+ * and may be {@code null} if not requested.
+ *
+ *
+ *
+ *
+ * The returned array is a defensive copy and may be modified by the caller. + *
+ * + * @return a copy of the final state vector + */ + public double[] getFinalU() { + double[] u = _listener.getU(); + return (u == null) ? null : u.clone(); + } + + /** + * Determine whether the swim terminated successfully. + *+ * A successful termination indicates that the swimmer reached the requested target condition + * (such as a surface, target {@code z}, target {@code ρ}, distance of closest approach, + * or maximum path length) within the specified accuracy, and without encountering an internal + * failure condition. + *
+ *+ * If this method returns {@code false}, the final state stored in this result still represents + * the particle state at the point where the swim terminated (for example, due to exceeding + * {@code sMax} or failing to converge). + *
+ * + * @return {@code true} if the swim terminated successfully; {@code false} otherwise + */ + public boolean isSuccess() { + return getStatus() == CLAS12Swimmer.SWIM_SUCCESS; + } + + /** + * Get the final rho in cm + * + * @return the final rho in cm + */ + public double getFinalRho() { + return Math.hypot(_listener.getU()[0], _listener.getU()[1]); + } + + /** + * Get the status of the swim as a string + * + * @return the status of the swim as a string + */ + public String statusString() { + int status = getStatus(); + String s = CLAS12Swimmer.resultNames.get(status); + if (s == null) { + s = "Unknown (" + status + ")"; + } + return s; + } + + /** + * Get the number of integration steps + * + * @return the number of integration steps + */ + public int getNStep() { + return _listener.getNumStep(); + } + + /** + * Get a summary of the results of the swim + */ + @Override + public String toString() { + StringBuffer sb = new StringBuffer(2000); + CLAS12Values ivalues = getInitialValues(); + CLAS12Values fvalues = getFinalValues(); + + double norm = ivalues.p / fvalues.p; // should be 1.0 + + sb.append("Swim results:\n"); + sb.append("Status: " + statusString() + "\n"); + sb.append("Initial values:\n"); + sb.append("charge = " + ivalues.q + "\n"); + sb.append(String.format("vertex = (%.4f, %.4f, %.4f) cm\n", ivalues.x, ivalues.y, ivalues.z)); + + sb.append(String.format("momentum = %.4f GeV/c\n", ivalues.p)); + sb.append(String.format("theta = %.4f deg\n", ivalues.theta)); + sb.append(String.format("phi = %.4f deg\n", ivalues.phi)); + sb.append("--------\nFinal values:\n"); + sb.append(String.format("location = (%.4f, %.4f, %.4f) cm\n", fvalues.x, fvalues.y, fvalues.z)); + sb.append(String.format("momentum = %.4f GeV/c\n", fvalues.p)); + sb.append(String.format("norm = %.4f (should be 1)\n", norm)); + sb.append(String.format("theta = %.4f deg\n", fvalues.theta)); + sb.append(String.format("phi = %.4f deg\n", fvalues.phi)); + sb.append(String.format("rho = %.4f cm\n", Math.hypot(fvalues.x, fvalues.y))); + sb.append(String.format("path length = %.4f cm\n", getPathLength())); + sb.append(String.format("number of steps = %d\n", getNStep())); + + return sb.toString(); + } + +} diff --git a/common-tools/cnuphys/swimmer/src/main/java/cnuphys/CLAS12Swim/CLAS12Swimmer.java b/common-tools/cnuphys/swimmer/src/main/java/cnuphys/CLAS12Swim/CLAS12Swimmer.java new file mode 100644 index 0000000000..2e996293f7 --- /dev/null +++ b/common-tools/cnuphys/swimmer/src/main/java/cnuphys/CLAS12Swim/CLAS12Swimmer.java @@ -0,0 +1,959 @@ +package cnuphys.CLAS12Swim; + +import java.util.Hashtable; + +import cnuphys.CLAS12Swim.geometry.Cylinder; +import cnuphys.CLAS12Swim.geometry.Plane; +import cnuphys.CLAS12Swim.geometry.Sphere; +import cnuphys.magfield.FieldProbe; +import cnuphys.magfield.RotatedCompositeProbe; + +import org.apache.commons.math3.ode.FirstOrderDifferentialEquations; +import org.apache.commons.math3.ode.events.EventHandler; +import org.apache.commons.math3.ode.sampling.StepHandler; +import org.apache.commons.math3.ode.sampling.StepInterpolator; +import org.apache.commons.math3.ode.nonstiff.DormandPrince54Integrator; + +/** + * The CLAS12 swimmer implementation, based on the Apache Commons Math 3.6.1 + * ODE solvers. + * + *Units: positions in cm, momentum in GeV/c, angles in degrees, path length in cm.
+ */ + @Override + public CLAS12SwimResult swimZ(int q, + double xo, double yo, double zo, + double p, double theta, double phi, + double zTarget, double accuracy, + double sMax, double h, double tolerance) { + + final CLAS12Values ivals = new CLAS12Values(q, xo, yo, zo, p, theta, phi); + final CLAS12ZListener listener = new CLAS12ZListener(ivals, zTarget, accuracy, sMax); + + // Momentum guard + if (p < minMomentum) { + listener.setStatus(CLAS12Swimmer.BELOW_MIN_MOMENTUM); + return new CLAS12SwimResult(listener); + } + + // Neutral shortcut + if (q == 0 && listener.canMakeStraightLine()) { + listener.straightLine(); + return new CLAS12SwimResult(listener); + } + + // Initial state y = [x,y,z, tx,ty,tz] + final double[] y = ivals.getU().clone(); + final SwimEquations ode = new SwimEquations(q, p, probe); + + final double targetMiss = accuracy; // cm + final double successTol = accuracy; // cm + + // Commons Math requires per-component tolerances. Interpret the provided "tolerance" knob + // as a position absolute tolerance in cm. + final double absPos = Math.max(1.0e-12, tolerance); // cm + final double absDir = 1.0e-10; // dimensionless + final double rel = 1.0e-12; + + final double[] absTol = new double[] { absPos, absPos, absPos, absDir, absDir, absDir }; + final double[] relTol = new double[] { rel, rel, rel, rel, rel, rel }; + + // Adaptive integrator: allow step-size growth up to maxStepSize (do NOT cap at h) + final DormandPrince54Integrator integrator = + new DormandPrince54Integrator( + Math.max(minStepSize, 1e-12), + Math.max(maxStepSize, minStepSize), + absTol, + relTol + ); + + // Use h only as an initial step-size guess + final double h0 = Math.max(minStepSize, Math.min(Math.abs(h), maxStepSize)); + integrator.setInitialStepSize(h0); + + // Record the trajectory at each accepted step + integrator.addStepHandler(new StepHandler() { + @Override + public void init(double s0, double[] y0, double sEnd) { + // no-op + } + + @Override + public void handleStep(StepInterpolator interpolator, boolean isLast) { + final double s = interpolator.getCurrentTime(); + final double[] state = interpolator.getInterpolatedState().clone(); + listener.accept(s, state); + } + }); + + // Event: stop at zTarget + final HitFlag hit = new HitFlag(); + + final EventHandler zEvent = new EventHandler() { + @Override + public void init(double s0, double[] y0, double sEnd) { } + + @Override + public double g(double s, double[] y) { + return y[2] - zTarget; + } + + @Override + public Action eventOccurred(double s, double[] y, boolean increasing) { + hit.hit = true; + return Action.STOP; + } + + @Override + public void resetState(double s, double[] y) { } + }; + + final double maxCheckInterval = Math.max(0.5, h0); + final double eventConv = Math.max(1.0e-12, targetMiss); + integrator.addEventHandler(zEvent, maxCheckInterval, eventConv, 200); + + // Integrate + double sFinal; + try { + sFinal = integrator.integrate(ode, 0.0, y, sMax, y); + } catch (Exception ex) { + listener.setStatus(CLAS12Swimmer.SWIM_TARGET_MISSED); + return new CLAS12SwimResult(listener); + } + + // Ensure final point captured even if the last step handler didn't run as expected + listener.accept(sFinal, y.clone()); + + // Status + if (hit.hit && Math.abs(listener.getU()[2] - zTarget) <= successTol) { + listener.setStatus(CLAS12Swimmer.SWIM_SUCCESS); + } else { + listener.setStatus(CLAS12Swimmer.SWIM_TARGET_MISSED); + } + + return new CLAS12SwimResult(listener); + } + + + // ------------------------------------------------------------------------- + // The rest of the interface: skeleton placeholders + // ------------------------------------------------------------------------- + + @Override + public CLAS12SwimResult swim(int q, double xo, double yo, double zo, double p, double theta, double phi, + double sMax, double h, double tolerance) { + + final CLAS12Values ivals = new CLAS12Values(q, xo, yo, zo, p, theta, phi); + final CLAS12Listener listener = new CLAS12Listener(ivals, sMax); + + // Momentum guard + if (p < minMomentum) { + listener.setStatus(CLAS12Swimmer.BELOW_MIN_MOMENTUM); + return new CLAS12SwimResult(listener); + } + + // Neutral shortcut: if permitted, do an exact straight-line propagation to sMax + if (q == 0 && listener.canMakeStraightLine()) { + listener.straightLine(); + return new CLAS12SwimResult(listener); + } + + // Initial state y0 = [x,y,z, tx,ty,tz] + final double[] y0 = ivals.getU(); + final double[] y = y0.clone(); + + final FirstOrderDifferentialEquations ode = new SwimEquations(q, p, probe); + + // Per-component tolerances + final double absPos = Math.max(1.0e-12, tolerance); // cm + final double absDir = 1.0e-10; // dimensionless + final double rel = 1.0e-12; + + final double[] absTol = new double[] { absPos, absPos, absPos, absDir, absDir, absDir }; + final double[] relTol = new double[] { rel, rel, rel, rel, rel, rel }; + + // Adaptive integrator: allow step-size growth up to maxStepSize; use h only as initial guess. + final DormandPrince54Integrator integrator = + new DormandPrince54Integrator( + Math.max(minStepSize, 1e-12), + Math.max(maxStepSize, minStepSize), + absTol, + relTol + ); + + final double h0 = Math.max(minStepSize, Math.min(Math.abs(h), maxStepSize)); + integrator.setInitialStepSize(h0); + + // Record trajectory at accepted steps + integrator.addStepHandler(new StepHandler() { + @Override + public void init(double t0, double[] y0, double t) { + // listener.reset() already added the initial point + } + + @Override + public void handleStep(StepInterpolator interpolator, boolean isLast) { + final double s = interpolator.getCurrentTime(); + final double[] state = interpolator.getInterpolatedState().clone(); + listener.accept(s, state); + } + }); + + try { + integrator.integrate(ode, 0.0, y, sMax, y); + } catch (Exception ex) { + listener.setStatus(CLAS12Swimmer.SWIM_TARGET_MISSED); + return new CLAS12SwimResult(listener); + } + + // For the basic swim, reaching sMax is considered success. + listener.setStatus(CLAS12Swimmer.SWIM_SUCCESS); + return new CLAS12SwimResult(listener); + } + + @Override + public CLAS12SwimResult swimFixed(int q, double xo, double yo, double zo, double p, double theta, double phi, + double sMax, double h) { + throw new UnsupportedOperationException("Not implemented yet (Commons Math swimmer)"); + } + + @Override + public CLAS12SwimResult swimCylinder(int q, double xo, double yo, double zo, double p, double theta, double phi, + double[] p1, double[] p2, double r, double accuracy, double sMax, double h, + double tolerance) { + Cylinder targetCylinder = new Cylinder(p1, p2, r); + return swimCylinder(q, xo, yo, zo, p, theta, phi, targetCylinder, accuracy, sMax, h, tolerance); + } + + @Override + public CLAS12SwimResult swimCylinder(int q, double xo, double yo, double zo, double p, double theta, double phi, + Cylinder targetCylinder, double accuracy, double sMax, double h, + double tolerance) { + + // If the target cylinder is centered on the z axis, this is exactly a rho swim. + if (targetCylinder.centeredOnZ()) { + return swimRho(q, xo, yo, zo, p, theta, phi, targetCylinder.radius, accuracy, sMax, h, tolerance); + } + + final CLAS12Values ivals = new CLAS12Values(q, xo, yo, zo, p, theta, phi); + final CLAS12CylinderListener listener = + new CLAS12CylinderListener(ivals, targetCylinder, accuracy, sMax); + + // Momentum guard + if (p < minMomentum) { + listener.setStatus(CLAS12Swimmer.BELOW_MIN_MOMENTUM); + return new CLAS12SwimResult(listener); + } + + // Neutral shortcut is intentionally not used here unless the cylinder reduces to rho. + // CLAS12CylinderListener disables exact straight-line handling. + + final double[] y = ivals.getU().clone(); + final SwimEquations ode = new SwimEquations(q, p, probe); + + final double targetMiss = accuracy; + final double successTol = accuracy; + + final double absPos = Math.max(1.0e-12, tolerance); + final double absDir = 1.0e-10; + final double rel = 1.0e-12; + + final double[] absTol = { absPos, absPos, absPos, absDir, absDir, absDir }; + final double[] relTol = { rel, rel, rel, rel, rel, rel }; + + final DormandPrince54Integrator integrator = + new DormandPrince54Integrator( + Math.max(minStepSize, 1.0e-12), + Math.max(maxStepSize, minStepSize), + absTol, + relTol + ); + + final double h0 = Math.max(minStepSize, Math.min(Math.abs(h), maxStepSize)); + integrator.setInitialStepSize(h0); + + integrator.addStepHandler(new StepHandler() { + @Override + public void init(double s0, double[] y0, double sEnd) { } + + @Override + public void handleStep(StepInterpolator interpolator, boolean isLast) { + final double s = interpolator.getCurrentTime(); + final double[] state = interpolator.getInterpolatedState().clone(); + listener.accept(s, state); + } + }); + + // Cylinder event: signed distance to surface = 0. + // Keep checks reasonably frequent to reduce any chance of stepping over the cylinder. + final HitFlag hit = new HitFlag(); + + final EventHandler cylinderEvent = new EventHandler() { + @Override + public void init(double s0, double[] y0, double sEnd) { } + + @Override + public double g(double s, double[] y) { + return targetCylinder.signedDistance(y[0], y[1], y[2]); + } + + @Override + public Action eventOccurred(double s, double[] y, boolean increasing) { + hit.hit = true; + return Action.STOP; + } + + @Override + public void resetState(double s, double[] y) { } + }; + + final double maxCheckInterval = Math.min(Math.max(0.5, h0), 5.0); + final double eventConv = Math.max(1.0e-12, targetMiss); + + integrator.addEventHandler(cylinderEvent, maxCheckInterval, eventConv, 200); + + double sFinal; + try { + sFinal = integrator.integrate(ode, 0.0, y, sMax, y); + } catch (Exception ex) { + listener.setStatus(CLAS12Swimmer.SWIM_TARGET_MISSED); + return new CLAS12SwimResult(listener); + } + + // Ensure final point is recorded + listener.accept(sFinal, y.clone()); + + // Status + double dist = targetCylinder.distance(listener.getU()[0], + listener.getU()[1], + listener.getU()[2]); + + if (hit.hit && dist <= successTol) { + listener.setStatus(CLAS12Swimmer.SWIM_SUCCESS); + } else { + listener.setStatus(CLAS12Swimmer.SWIM_TARGET_MISSED); + } + + return new CLAS12SwimResult(listener); + } + + @Override + public CLAS12SwimResult swimSphere(int q, double xo, double yo, double zo, double p, double theta, double phi, + double[] center, double r, double accuracy, double sMax, double h, + double tolerance) { + throw new UnsupportedOperationException("Not implemented yet (Commons Math swimmer)"); + } + + @Override + public CLAS12SwimResult swimSphere(int q, double xo, double yo, double zo, double p, double theta, double phi, + Sphere targetSphere, double accuracy, double sMax, double h, + double tolerance) { + throw new UnsupportedOperationException("Not implemented yet (Commons Math swimmer)"); + } + + @Override + public CLAS12SwimResult swimPlane(int q, double xo, double yo, double zo, double p, double theta, double phi, + double nx, double ny, double nz, double px, double py, double pz, + double accuracy, double sMax, double h, double tolerance) { + throw new UnsupportedOperationException("Not implemented yet (Commons Math swimmer)"); + } + + @Override + public CLAS12SwimResult swimPlane(int q, double xo, double yo, double zo, double p, double theta, double phi, + double[] norm, double[] point, double accuracy, double sMax, double h, + double tolerance) { + throw new UnsupportedOperationException("Not implemented yet (Commons Math swimmer)"); + } + + /** + * Swim to a fixed plane, stopping when the trajectory intersects the plane + * or when the path length {@code sMax} is reached. + * + *Units: positions in cm, momentum in GeV/c, angles in degrees.
+ */ + @Override + public CLAS12SwimResult swimPlane(int q, + double xo, double yo, double zo, + double p, double theta, double phi, + Plane plane, + double accuracy, + double sMax, + double h, + double tolerance) { + + final CLAS12Values ivals = new CLAS12Values(q, xo, yo, zo, p, theta, phi); + final CLAS12PlaneListener listener = + new CLAS12PlaneListener(ivals, plane, accuracy, sMax); + + // Momentum guard + if (p < minMomentum) { + listener.setStatus(CLAS12Swimmer.BELOW_MIN_MOMENTUM); + return new CLAS12SwimResult(listener); + } + + // Neutral shortcut + if (q == 0 && listener.canMakeStraightLine()) { + listener.straightLine(); + return new CLAS12SwimResult(listener); + } + + // Initial state y = [x,y,z, tx,ty,tz] + final double[] y = ivals.getU().clone(); + final SwimEquations ode = new SwimEquations(q, p, probe); + + final double targetMiss = accuracy; + final double successTol = accuracy; + final double absPos = Math.max(1.0e-12, tolerance); + final double absDir = 1.0e-10; + final double rel = 1.0e-12; + + final double[] absTol = { + absPos, absPos, absPos, + absDir, absDir, absDir + }; + final double[] relTol = { + rel, rel, rel, rel, rel, rel + }; + + final DormandPrince54Integrator integrator = + new DormandPrince54Integrator( + Math.max(minStepSize, 1.0e-12), + Math.max(maxStepSize, minStepSize), + absTol, + relTol + ); + + // Initial step-size guess + final double h0 = Math.max(minStepSize, Math.min(Math.abs(h), maxStepSize)); + integrator.setInitialStepSize(h0); + + // Record every accepted step (matches swimZ behavior) + integrator.addStepHandler(new StepHandler() { + @Override + public void init(double s0, double[] y0, double sEnd) { } + + @Override + public void handleStep(StepInterpolator interpolator, boolean isLast) { + final double s = interpolator.getCurrentTime(); + final double[] state = interpolator.getInterpolatedState().clone(); + listener.accept(s, state); + } + }); + + // ------------------------------------------------------------ + // Plane event: signed distance = 0 + // ------------------------------------------------------------ + final HitFlag hit = new HitFlag(); + + final EventHandler planeEvent = new EventHandler() { + + @Override + public void init(double s0, double[] y0, double sEnd) { } + + @Override + public double g(double s, double[] y) { + return plane.signedDistance(y[0], y[1], y[2]); + } + + @Override + public Action eventOccurred(double s, double[] y, boolean increasing) { + hit.hit = true; + return Action.STOP; + } + + @Override + public void resetState(double s, double[] y) { } + }; + + final double maxCheckInterval = Math.max(0.5, h0); + final double eventConv = Math.max(1.0e-12, targetMiss); + + integrator.addEventHandler(planeEvent, maxCheckInterval, eventConv, 200); + + // ------------------------------------------------------------ + // Integrate + // ------------------------------------------------------------ + double sFinal; + try { + sFinal = integrator.integrate(ode, 0.0, y, sMax, y); + } catch (Exception ex) { + listener.setStatus(CLAS12Swimmer.SWIM_TARGET_MISSED); + return new CLAS12SwimResult(listener); + } + + // Ensure final point is recorded + listener.accept(sFinal, y.clone()); + + // ------------------------------------------------------------ + // Status + // ------------------------------------------------------------ + double dist = plane.distance(listener.getU()[0], + listener.getU()[1], + listener.getU()[2]); + + if (hit.hit && dist <= successTol) { + listener.setStatus(CLAS12Swimmer.SWIM_SUCCESS); + } else { + listener.setStatus(CLAS12Swimmer.SWIM_TARGET_MISSED); + } + + return new CLAS12SwimResult(listener); + } + + /** + * Swim to a fixed target z (cm) in a given CLAS12 sector using the RotatedComposite field. + *+ * This operation is only valid when the active probe is a + * {@link RotatedCompositeProbe}. If not, it prints an error and returns {@code null}. + *
+ */ + @Override + public CLAS12SwimResult sectorSwimZ(int sector, int q, + double xo, double yo, double zo, + double p, double theta, double phi, + double zTarget, double accuracy, + double sMax, double h, double tolerance) { + + // Must use the rotated field. + if (!(probe instanceof RotatedCompositeProbe)) { + System.err.println("sectorSwimZ only valid with RotatedCompositeProbe."); + return null; + } + + final CLAS12Values ivals = new CLAS12Values(q, xo, yo, zo, p, theta, phi); + final CLAS12ZListener listener = new CLAS12ZListener(ivals, zTarget, accuracy, sMax); + + if (p < minMomentum) { + listener.setStatus(CLAS12Swimmer.BELOW_MIN_MOMENTUM); + return new CLAS12SwimResult(listener); + } + + if (q == 0 && listener.canMakeStraightLine()) { + listener.straightLine(); + return new CLAS12SwimResult(listener); + } + + final double[] y = ivals.getU().clone(); + + final SectorSwimEquations ode = + new SectorSwimEquations(sector, q, p, probe); + + final double targetMiss = accuracy; + final double successTol = accuracy; + final double absPos = Math.max(1.0e-12, tolerance); + final double absDir = 1.0e-10; + final double rel = 1.0e-12; + + final double[] absTol = { absPos, absPos, absPos, absDir, absDir, absDir }; + final double[] relTol = { rel, rel, rel, rel, rel, rel }; + + final DormandPrince54Integrator integrator = + new DormandPrince54Integrator( + Math.max(minStepSize, 1.0e-12), + Math.max(maxStepSize, minStepSize), + absTol, + relTol + ); + + final double h0 = Math.max(minStepSize, Math.min(Math.abs(h), maxStepSize)); + integrator.setInitialStepSize(h0); + + integrator.addStepHandler(new StepHandler() { + @Override + public void init(double s0, double[] y0, double sEnd) { } + + @Override + public void handleStep(StepInterpolator interpolator, boolean isLast) { + double s = interpolator.getCurrentTime(); + double[] state = interpolator.getInterpolatedState().clone(); + listener.accept(s, state); + } + }); + + final HitFlag hit = new HitFlag(); + + EventHandler zEvent = new EventHandler() { + + @Override + public void init(double s0, double[] y0, double sEnd) { } + + @Override + public double g(double s, double[] y) { + return y[2] - zTarget; + } + + @Override + public Action eventOccurred(double s, double[] y, boolean increasing) { + hit.hit = true; + return Action.STOP; + } + + @Override + public void resetState(double s, double[] y) { } + }; + + double maxCheckInterval = Math.max(0.5, h0); + double eventConv = Math.max(1.0e-12, targetMiss); + + integrator.addEventHandler(zEvent, maxCheckInterval, eventConv, 200); + + double sFinal; + + try { + sFinal = integrator.integrate(ode, 0.0, y, sMax, y); + } catch (Exception ex) { + listener.setStatus(CLAS12Swimmer.SWIM_TARGET_MISSED); + return new CLAS12SwimResult(listener); + } + + listener.accept(sFinal, y.clone()); + + if (hit.hit && Math.abs(listener.getU()[2] - zTarget) <= successTol) { + listener.setStatus(CLAS12Swimmer.SWIM_SUCCESS); + } else { + listener.setStatus(CLAS12Swimmer.SWIM_TARGET_MISSED); + } + + return new CLAS12SwimResult(listener); + } + + + @Override + public CLAS12SwimResult swimRho(int q, double xo, double yo, double zo, double p, double theta, double phi, + double rhoTarget, double accuracy, double sMax, double h, double tolerance) { + + final CLAS12Values ivals = new CLAS12Values(q, xo, yo, zo, p, theta, phi); + final CLAS12RhoListener listener = new CLAS12RhoListener(ivals, rhoTarget, accuracy, sMax); + + // Momentum guard + if (p < minMomentum) { + listener.setStatus(CLAS12Swimmer.BELOW_MIN_MOMENTUM); + return new CLAS12SwimResult(listener); + } + + // Neutral shortcut: listener can compute exact straight-line intersection with rho target + if (q == 0 && listener.canMakeStraightLine()) { + listener.straightLine(); + return new CLAS12SwimResult(listener); + } + + // Initial state y0 = [x,y,z, tx,ty,tz] + final double[] y0 = ivals.getU(); + final double[] y = y0.clone(); + + final FirstOrderDifferentialEquations ode = new SwimEquations(q, p, probe); + + final double targetMiss = accuracy; + final double absPos = Math.max(1e-12, tolerance); + final double absDir = 1e-10; + final double rel = 1e-12; + + final double[] absTol = new double[] { absPos, absPos, absPos, absDir, absDir, absDir }; + final double[] relTol = new double[] { rel, rel, rel, rel, rel, rel }; + + final DormandPrince54Integrator integrator = + new DormandPrince54Integrator( + Math.max(minStepSize, 1e-12), + Math.max(maxStepSize, minStepSize), + absTol, + relTol + ); + + final double h0 = Math.max(minStepSize, Math.min(Math.abs(h), maxStepSize)); + integrator.setInitialStepSize(h0); + + // Record trajectory at accepted steps + integrator.addStepHandler(new StepHandler() { + @Override + public void init(double t0, double[] y0, double t) { + // listener.reset() already added the initial point + } + + @Override + public void handleStep(StepInterpolator interpolator, boolean isLast) { + final double s = interpolator.getCurrentTime(); + final double[] state = interpolator.getInterpolatedState().clone(); + listener.accept(s, state); + } + }); + + // Event: rho(s) - rhoTarget = 0, where rho = sqrt(x^2 + y^2) + final HitFlag hit = new HitFlag(); + + final EventHandler rhoEventHandler = new EventHandler() { + @Override + public void init(double t0, double[] y0, double t) { + // nothing + } + + @Override + public double g(double s, double[] y) { + final double rho = Math.hypot(y[0], y[1]); + return rho - rhoTarget; + } + + @Override + public Action eventOccurred(double s, double[] y, boolean increasing) { + hit.hit = true; + return Action.STOP; + } + + @Override + public void resetState(double s, double[] y) { + // no reset + } + }; + + integrator.addEventHandler( + rhoEventHandler, + Math.max(0.5, h0), + Math.max(1e-12, targetMiss), + 200 + ); + + try { + integrator.integrate(ode, 0.0, y, sMax, y); + } catch (Exception ex) { + listener.setStatus(CLAS12Swimmer.SWIM_TARGET_MISSED); + return new CLAS12SwimResult(listener); + } + + // Decide final status + final double rhoFinal = Math.hypot(listener.getU()[0], listener.getU()[1]); + if (hit.hit && Math.abs(rhoFinal - rhoTarget) <= targetMiss) { + listener.setStatus(CLAS12Swimmer.SWIM_SUCCESS); + } else { + listener.setStatus(CLAS12Swimmer.SWIM_TARGET_MISSED); + } + + return new CLAS12SwimResult(listener); + } + + @Override + public CLAS12SwimResult swimZLine(int q, double xo, double yo, double zo, double p, double theta, double phi, + double xb, double yb, double accuracy, double sMax, double h, double tolerance) { + throw new UnsupportedOperationException("Not implemented yet (Commons Math swimmer)"); + } + + @Override + public CLAS12SwimResult swimBeamline(int q, double xo, double yo, double zo, double p, double theta, double phi, + double accuracy, double sMax, double h, double tolerance) { + throw new UnsupportedOperationException("Not implemented yet (Commons Math swimmer)"); + } + + // ------------------------------------------------------------------------- + // Internal helpers + // ------------------------------------------------------------------------- + + /** + * ODE system for Cartesian CLAS12 swimming. + * Independent variable is path length s in cm. + */ + private static final class SwimEquations implements FirstOrderDifferentialEquations { + + private final FieldProbe probe; + private final double alpha; // 1/(kG*cm) + private final float[] b = new float[3]; + + SwimEquations(int q, double p, FieldProbe probe) { + this.probe = probe; + // Curvature scale for field in kG and distance in cm. + // alpha = 1.0e-14 * q * C / p (units: 1/(kG*cm)) + this.alpha = 1.0e-14 * q * CLAS12Swimmer.C / p; + } + + @Override + public int getDimension() { + return 6; + } + + @Override + public void computeDerivatives(double s, double[] y, double[] yDot) { + double Bx = 0.0, By = 0.0, Bz = 0.0; + + if (probe != null) { + probe.field((float) y[0], (float) y[1], (float) y[2], b); + Bx = b[0]; + By = b[1]; + Bz = b[2]; + } + + // dr/ds = t + yDot[0] = y[3]; + yDot[1] = y[4]; + yDot[2] = y[5]; + + // dt/ds = alpha * (t x B) + yDot[3] = alpha * (y[4] * Bz - y[5] * By); + yDot[4] = alpha * (y[5] * Bx - y[3] * Bz); + yDot[5] = alpha * (y[3] * By - y[4] * Bx); + } + } + + /** + * Sector-aware ODE system for sector-dependent swimming with a {@link RotatedCompositeProbe}. + *+ * The independent variable is the path length {@code s} in cm. + *
+ * + *+ * This implementation tries to call a sector-aware method on the probe via reflection: + * {@code field(int sector, float x, float y, float z, float[] b)}. + * If not found (or invocation fails), it falls back to {@code probe.field(x,y,z,b)}. + *
+ */ + private static final class SectorSwimEquations implements FirstOrderDifferentialEquations { + + private final int sector; + private final FieldProbe probe; + private final double alpha; // 1/(kG*cm) + private final float[] b = new float[3]; + + + // Cached reflective call (lazy init) + private transient java.lang.reflect.Method sectorFieldMethod; + private transient boolean searched = false; + + SectorSwimEquations(int sector, int q, double p, FieldProbe probe) { + this.sector = sector; + this.probe = probe; + this.alpha = 1.0e-14 * q * CLAS12Swimmer.C / p; + } + + @Override + public int getDimension() { + return 6; + } + + @Override + public void computeDerivatives(double s, double[] y, double[] yDot) { + + double Bx = 0.0, By = 0.0, Bz = 0.0; + + if (probe != null) { + if (!searched) { + searched = true; + sectorFieldMethod = findSectorFieldMethod(probe.getClass()); + } + + boolean ok = false; + + if (sectorFieldMethod != null) { + try { + // signature: (int, float, float, float, float[]) + sectorFieldMethod.invoke(probe, sector, (float) y[0], (float) y[1], (float) y[2], b); + ok = true; + } catch (Throwable t) { + // Disable and fall back for remainder of this swim + sectorFieldMethod = null; + } + } + + if (!ok) { + probe.field((float) y[0], (float) y[1], (float) y[2], b); + } + + + Bx = b[0]; + By = b[1]; + Bz = b[2]; + } + + // dr/ds = t + yDot[0] = y[3]; + yDot[1] = y[4]; + yDot[2] = y[5]; + + // dt/ds = alpha * (t x B) + yDot[3] = alpha * (y[4] * Bz - y[5] * By); + yDot[4] = alpha * (y[5] * Bx - y[3] * Bz); + yDot[5] = alpha * (y[3] * By - y[4] * Bx); + } + + private static java.lang.reflect.Method findSectorFieldMethod(Class> cls) { + try { + return cls.getMethod("field", int.class, float.class, float.class, float.class, float[].class); + } catch (NoSuchMethodException e) { + return null; + } + } + } + + + private static final class HitFlag { + boolean hit = false; + } +} diff --git a/common-tools/cnuphys/swimmer/src/main/java/cnuphys/CLAS12Swim/CLAS12Trajectory.java b/common-tools/cnuphys/swimmer/src/main/java/cnuphys/CLAS12Swim/CLAS12Trajectory.java new file mode 100644 index 0000000000..56c7de172c --- /dev/null +++ b/common-tools/cnuphys/swimmer/src/main/java/cnuphys/CLAS12Swim/CLAS12Trajectory.java @@ -0,0 +1,191 @@ +package cnuphys.CLAS12Swim; + +import java.util.Arrays; + +import cnuphys.magfield.FieldProbe; +import cnuphys.magfield.RotatedCompositeProbe; +import cnuphys.swim.SwimTrajectory; + +@SuppressWarnings("serial") +public class CLAS12Trajectory extends SwimTrajectory { + + private double[] _s = new double[200]; + private int _sSize = 0; + + private double _bdlValue = Double.NaN; + + public CLAS12Trajectory(CLAS12Values initialValues) { + super(initialValues.toGeneratedParticleRecord(), 200); + } + + public void add(double s, double[] u) { + addS(s); + super.add(u); + _bdlValue = Double.NaN; + } + + public void replaceLastPoint(double s, double[] u) { + if (_sSize > 0) { + int index = _sSize - 1; + removePoint(index); + add(s, u); + } + } + + public void removeLastPoint() { + if (_sSize > 0) { + removePoint(_sSize - 1); + _bdlValue = Double.NaN; + } + } + + public void removePoint(int index) { + if (index >= 0 && index < _sSize) { + System.arraycopy(_s, index + 1, _s, index, _sSize - index - 1); + _sSize--; + remove(index); + _bdlValue = Double.NaN; + } + } + + public double getS(int index) { + return _s[index]; + } + + public int getSSize() { + return _sSize; + } + + public String sizeReport() { + return String.format("State vector size: %d Pathlength size: %d", size(), _sSize); + } + + @Override + public void clear() { + super.clear(); + _sSize = 0; + _bdlValue = Double.NaN; + } + + @Override + public boolean add(double[] u) { + throw new UnsupportedOperationException("Use add(s, u) instead."); + } + + @Override + public boolean add(double[] u, double s) { + throw new UnsupportedOperationException("Use add(s, u) instead."); + } + + @Override + public void add(double xo, double yo, double zo, double p, double theta, double phi) { + throw new UnsupportedOperationException("Use addPoint instead."); + } + + public void addPoint(double x, double y, double z, double theta, double phi, double s) { + double thetaRad = Math.toRadians(theta); + double phiRad = Math.toRadians(phi); + double sinTheta = Math.sin(thetaRad); + + double[] u = new double[6]; + u[0] = x; + u[1] = y; + u[2] = z; + u[3] = sinTheta * Math.cos(phiRad); + u[4] = sinTheta * Math.sin(phiRad); + u[5] = Math.cos(thetaRad); + + add(s, u); + } + + @Override + public double getR(int index) { + if ((index < 0) || (index >= size())) { + return Double.NaN; + } + + double[] v = get(index); + return Math.sqrt(v[0] * v[0] + v[1] * v[1] + v[2] * v[2]); + } + + @Override + public double getComputedBDL() { + if (Double.isNaN(_bdlValue)) { + computeBDL(FieldProbe.factory()); + } + return _bdlValue; + } + + @Override + public void computeBDL(FieldProbe probe) { + if (!(probe instanceof RotatedCompositeProbe) && Double.isNaN(_bdlValue) && size() >= 2) { + _bdlValue = 0.0; + int n = size(); + double[] dr = new double[3]; + float[] b = new float[3]; + double[] bxdl = new double[3]; + + for (int i = 0; i < n - 1; i++) { + double[] p0 = get(i); + double[] p1 = get(i + 1); + + dr[0] = p1[0] - p0[0]; + dr[1] = p1[1] - p0[1]; + dr[2] = p1[2] - p0[2]; + + float xavg = (float) ((p0[0] + p1[0]) * 0.5); + float yavg = (float) ((p0[1] + p1[1]) * 0.5); + float zavg = (float) ((p0[2] + p1[2]) * 0.5); + + probe.field(xavg, yavg, zavg, b); + cross(b, dr, bxdl); + _bdlValue += vecmag(bxdl); + } + } + } + + @Override + public void sectorComputeBDL(int sector, RotatedCompositeProbe probe) { + if (Double.isNaN(_bdlValue) && size() >= 2) { + _bdlValue = 0.0; + int n = size(); + double[] dr = new double[3]; + float[] b = new float[3]; + double[] bxdl = new double[3]; + + for (int i = 0; i < n - 1; i++) { + double[] p0 = get(i); + double[] p1 = get(i + 1); + + dr[0] = p1[0] - p0[0]; + dr[1] = p1[1] - p0[1]; + dr[2] = p1[2] - p0[2]; + + float xavg = (float) ((p0[0] + p1[0]) * 0.5); + float yavg = (float) ((p0[1] + p1[1]) * 0.5); + float zavg = (float) ((p0[2] + p1[2]) * 0.5); + + probe.field(sector, xavg, yavg, zavg, b); + cross(b, dr, bxdl); + _bdlValue += vecmag(bxdl); + } + } + } + + private void addS(double s) { + if (_sSize >= _s.length) { + _s = Arrays.copyOf(_s, _s.length * 2); + } + _s[_sSize++] = s; + } + + private static void cross(float[] a, double[] b, double[] out) { + out[0] = a[1] * b[2] - a[2] * b[1]; + out[1] = a[2] * b[0] - a[0] * b[2]; + out[2] = a[0] * b[1] - a[1] * b[0]; + } + + private static double vecmag(double[] a) { + return Math.sqrt(a[0] * a[0] + a[1] * a[1] + a[2] * a[2]); + } +} diff --git a/common-tools/cnuphys/swimmer/src/main/java/cnuphys/CLAS12Swim/CLAS12Values.java b/common-tools/cnuphys/swimmer/src/main/java/cnuphys/CLAS12Swim/CLAS12Values.java new file mode 100644 index 0000000000..a7713bef39 --- /dev/null +++ b/common-tools/cnuphys/swimmer/src/main/java/cnuphys/CLAS12Swim/CLAS12Values.java @@ -0,0 +1,155 @@ +package cnuphys.CLAS12Swim; + +import cnuphys.lund.GeneratedParticleRecord; +import cnuphys.magfield.FastMath; + +/** + * A class to hold the initial or final values for a swim. + */ +public class CLAS12Values { + + /** The integer charge */ + public final int q; + + /** The coordinate x in cm */ + public final double x; + + /** The y coordinate in cm */ + public final double y; + + /** The z coordinate of in cm */ + public final double z; + + /** The momentum in GeV/c */ + public final double p; + + /** The DIRECTIONAL polar angle in degrees, i.e. theta component of p */ + public final double theta; + + /** The azimuthal angle in degrees */ + public final double phi; + + public final double tx; + public final double ty; + public final double tz; + + /** + * Store the initial conditions of a swim + * + * @param q The integer charge + * @param xo The x coordinate of the vertex in cm + * @param yo The y coordinate of the vertex in cm + * @param zo The z coordinate of the vertex in cm + * @param p The momentum in GeV/c + * @param theta The DITECTIONAL polar angle in degrees + * @param phi The DIRECTIONAL azimuthal angle in degrees + */ + public CLAS12Values(int q, double xo, double yo, double zo, double p, double theta, double phi) { + this.q = q; + this.x = xo; + this.y = yo; + this.z = zo; + this.p = p; + this.theta = theta; + this.phi = phi; + double thetaRad = Math.toRadians(theta); + double phiRad = Math.toRadians(phi); + double sinTheta = Math.sin(thetaRad); + tx = sinTheta * Math.cos(phiRad); + ty = sinTheta * Math.sin(phiRad); + tz = Math.cos(thetaRad); + } + + /** + * Get the POSITIONAL values from a state vector. The state vector is the vector + * of that is the dependent variable in the integration. The anlges are + * positional, not the directional angles for the momentum. + * + * @param q the integer charge. Must be supplied, not part of the state vector. + * It shouldn't change, but we assume this is the original momentum, so + * we mutliply by the state vector norm of the t components, which + * should be 1 since we have magnetic field only. + * @param p the momentum in GeV/c + * @param u the state vector + */ + public CLAS12Values(int q, double p, double[] u) { + this.q = q; + x = u[0]; + y = u[1]; + z = u[2]; + + tx = u[3]; + ty = u[4]; + tz = u[5]; + + // norm should be 1 + double norm = Math.sqrt(u[3] * u[3] + u[4] * u[4] + u[5] * u[5]); + + this.p = norm * p; + + // directional theta and phi + theta = FastMath.acos2Deg(u[5]); + phi = FastMath.atan2Deg(u[4], u[3]); + } + + /** + * Get the values as a state vector used in integration + * + * @return the values as a state vector + */ + public double[] getU() { + double uo[] = new double[6]; + + double thetaRad = Math.toRadians(theta); + double phiRad = Math.toRadians(phi); + double sinTheta = Math.sin(thetaRad); + + double tx = sinTheta * Math.cos(phiRad); // px/p + double ty = sinTheta * Math.sin(phiRad); // py/p + double tz = Math.cos(thetaRad); // pz/p + + // set uf to the starting state vector + uo[0] = x; + uo[1] = y; + uo[2] = z; + uo[3] = tx; + uo[4] = ty; + uo[5] = tz; + return uo; + } + + /** + * Copy constructor + * + * @param src the source initial values + */ + public CLAS12Values(CLAS12Values src) { + this(src.q, src.x, src.y, src.z, src.p, src.theta, src.phi); + } + + @Override + public String toString() { + return String.format("Q: %d\n", q) + String.format("xo: %10.7e cm\n", x) + String.format("yo: %10.7e cm\n", y) + + String.format("zo: %10.7e cm\n", z) + String.format("p: %10.7e GeV/c\n", p) + + String.format("theta: %10.7f deg\n", theta) + String.format("phi: %10.7f deg", phi); + } + + /** + * Convert to a GeneratedParticleRecord for backwards compatibility + * + * @return a GeneratedParticleRecord corresponding to this data + */ + public GeneratedParticleRecord toGeneratedParticleRecord() { + return new GeneratedParticleRecord(q, x, y, z, p, theta, phi); + } + + /** + * A raw string for output, just numbers no units + * + * @return a raw string for output + */ + public String toStringRaw() { + return String.format("%-7.4f %-7.4f %-7.4f %-6.3f %-6.3f %-6.3f", x, y, z, p, theta, phi); + } + +} diff --git a/common-tools/cnuphys/swimmer/src/main/java/cnuphys/CLAS12Swim/CLAS12ZLineListener.java b/common-tools/cnuphys/swimmer/src/main/java/cnuphys/CLAS12Swim/CLAS12ZLineListener.java new file mode 100644 index 0000000000..914183e653 --- /dev/null +++ b/common-tools/cnuphys/swimmer/src/main/java/cnuphys/CLAS12Swim/CLAS12ZLineListener.java @@ -0,0 +1,33 @@ +package cnuphys.CLAS12Swim; + +public class CLAS12ZLineListener extends CLAS12DOCAListener { + + private double _xb; //x offset in cm + private double _yb; //y offset in cm + + /** + * Create a CLAS12 swim to an "offest beamline" listener. The offset + * beamline is a line parallel to the z-axis, but offset in the x and y + * directions by _xb and _yb. + * + * @param ivals the initial values of the swim + * @param xb the x offset (cm) + * @param yb the y offset (cm) + * @param accuracy the accuracy (cm) (on on difference in successive docas) + * @param sMax the final or max path length (cm) + */ + public CLAS12ZLineListener(CLAS12Values ivals, double xb, double yb, double accuracy, double sMax) { + super(ivals, accuracy, sMax); + _xb = xb; + _yb = yb; + } + + + @Override + public double doca(double newS, double[] newU) { + double dx = newU[0] - _xb; + double dy = newU[1] - _yb; + return Math.hypot(dx, dy); + } + +} diff --git a/common-tools/cnuphys/swimmer/src/main/java/cnuphys/CLAS12Swim/CLAS12ZListener.java b/common-tools/cnuphys/swimmer/src/main/java/cnuphys/CLAS12Swim/CLAS12ZListener.java new file mode 100644 index 0000000000..5565ee5c6a --- /dev/null +++ b/common-tools/cnuphys/swimmer/src/main/java/cnuphys/CLAS12Swim/CLAS12ZListener.java @@ -0,0 +1,118 @@ +package cnuphys.CLAS12Swim; + +/** + * A listener for swimming to a fixed value of z + */ +public class CLAS12ZListener extends CLAS12BoundaryListener { + + // the target z (cm) + private double _zTarget; + + // the starting sign. When this changes we have crossed. + private double _startSign; + + /** + * Create a CLAS12 boundary target Z listener, for swimming to a fixed z + * + * @param ivals the initial values of the swim + * @param zTarget the target z (cm) + * @param accuracy the desired accuracy (cm) + * @param sMax the final or max path length (cm) + */ + public CLAS12ZListener(CLAS12Values ivals, double zTarget, double accuracy, double sMax) { + super(ivals, accuracy, sMax); + _zTarget = zTarget; + _startSign = sign(ivals.z); + } + + @Override + public boolean crossedBoundary(double newS, double[] newU) { + double newZ = newU[2]; + int sign = sign(newZ); + + if (sign != _startSign) { + return true; + } + return false; + } + + @Override + public boolean accuracyReached(double newS, double[] newU) { + double dZ = Math.abs(newU[2] - _zTarget); + return dZ < _accuracy; + } + + // left or right of the target Z? + private int sign(double z) { + return (z < _zTarget) ? -1 : 1; + } + + /** + * Get the absolute distance to the target (boundary) in cm. + * + * @param newS the new path length + * @param newU the new state vector + * @return the distance to the target (boundary) in cm. + */ + @Override + public double distanceToTarget(double newS, double[] newU) { + return Math.abs(newU[2] - _zTarget); + } + + /** + * Add a second point creating a straight line to the target z + */ + @Override + public void straightLine() { + + double u[] = _trajectory.get(_trajectory.size() - 1); + double s = _trajectory.getS(_trajectory.size() - 1); + + double u2[] = findPoint(u[0], u[1], u[2], u[3], u[4], u[5], _zTarget); + + double dx = u2[0] - u[0]; + double dy = u2[1] - u[1]; + double dz = u2[2] - u[2]; + double ds = Math.sqrt(dx * dx + dy * dy + dz * dz); + + _trajectory.add(s + ds, u2); + _status = CLAS12Swimmer.SWIM_SUCCESS; + + } + + /** + * Finds the point along the line of velocity where the z coordinate reaches + * zTarget. + * + * @param x0 Starting x coordinate + * @param y0 Starting y coordinate + * @param z0 Starting z coordinate + * @param tx x component of the unit direction vector + * @param ty y component of the unit direction vector + * @param tz z component of the unit direction vector + * @param zTarget The target z coordinate to reach + * @return The point [x, y, z] where the z coordinate reaches zTarget, or null + * if it never reaches. + */ + private double[] findPoint(double x0, double y0, double z0, double tx, double ty, double tz, double zTarget) { + // Check if the line is parallel to the z-plane (tz = 0) + if (tz == 0) { + if (z0 == zTarget) { + // The entire line is on the plane where z = zTarget + return new double[] { x0, y0, zTarget }; + } else { + // The line will never reach zTarget + return null; + } + } + + // Calculate the parameter (s) at which z coordinate reaches zTarget + double t = (zTarget - z0) / tz; + + // Calculate the x and y coordinates at this point + double x = x0 + tx * t; + double y = y0 + ty * t; + + return new double[] { x, y, zTarget, tx, ty, tz }; + } +} diff --git a/common-tools/cnuphys/swimmer/src/main/java/cnuphys/CLAS12Swim/ICLAS12Swimmer.java b/common-tools/cnuphys/swimmer/src/main/java/cnuphys/CLAS12Swim/ICLAS12Swimmer.java new file mode 100644 index 0000000000..fb7593ad5b --- /dev/null +++ b/common-tools/cnuphys/swimmer/src/main/java/cnuphys/CLAS12Swim/ICLAS12Swimmer.java @@ -0,0 +1,369 @@ +package cnuphys.CLAS12Swim; + +import cnuphys.CLAS12Swim.geometry.Cylinder; +import cnuphys.CLAS12Swim.geometry.Plane; +import cnuphys.CLAS12Swim.geometry.Sphere; +import cnuphys.magfield.FieldProbe; + +/** + * Public API for the CLAS12 charged-particle swimmer. + *+ * A “swim” numerically propagates a charged particle through the magnetic field from an + * initial vertex and direction/momentum until a termination condition is reached + * (path length, target surface, target z, target rho/beamline, etc.). + *
+ * + *+ *
+ * If the swim starts inside the cylinder, it will terminate immediately (subject to the + * implementation’s handling of that case in {@link CLAS12SwimResult}). + *
+ * + * @param q particle charge in integer units of e + * @param xo initial x vertex position in cm + * @param yo initial y vertex position in cm + * @param zo initial z vertex position in cm + * @param p initial momentum magnitude in GeV/c + * @param theta initial polar angle in degrees + * @param phi initial azimuthal angle in degrees + * @param p1 first point on the cylinder centerline: {x,y,z} in cm + * @param p2 second point on the cylinder centerline: {x,y,z} in cm + * @param r cylinder radius in cm + * @param accuracy desired accuracy in cm for reaching the surface + * @param sMax maximum path length in cm + * @param h initial step size in cm + * @param tolerance desired tolerance; the integrator adapts step size to meet this tolerance + * @return the result of the swim + */ + CLAS12SwimResult swimCylinder(int q, double xo, double yo, double zo, double p, double theta, double phi, + double p1[], double p2[], double r, double accuracy, double sMax, double h, + double tolerance); + + /** + * Swim a particle to the surface of a target cylinder. + * The cylinder is specified by a {@link Cylinder} object (typically treated as infinite in length). + * + * @param q particle charge in integer units of e + * @param xo initial x vertex position in cm + * @param yo initial y vertex position in cm + * @param zo initial z vertex position in cm + * @param p initial momentum magnitude in GeV/c + * @param theta initial polar angle in degrees + * @param phi initial azimuthal angle in degrees + * @param targetCylinder target cylinder + * @param accuracy desired accuracy in cm for reaching the surface + * @param sMax maximum path length in cm + * @param h initial step size in cm + * @param tolerance desired tolerance; the integrator adapts step size to meet this tolerance + * @return the result of the swim + */ + CLAS12SwimResult swimCylinder(int q, double xo, double yo, double zo, double p, double theta, double phi, + Cylinder targetCylinder, double accuracy, double sMax, double h, + double tolerance); + + /** + * Swim a particle to the surface of a target sphere. + * The sphere is defined by a center point {@code center} as a {@code double[3]} in {x,y,z} cm, + * and radius {@code r} in cm. + *+ * If the swim starts inside the sphere, it will terminate immediately (subject to the + * implementation’s handling of that case in {@link CLAS12SwimResult}). + *
+ * + * @param q particle charge in integer units of e + * @param xo initial x vertex position in cm + * @param yo initial y vertex position in cm + * @param zo initial z vertex position in cm + * @param p initial momentum magnitude in GeV/c + * @param theta initial polar angle in degrees + * @param phi initial azimuthal angle in degrees + * @param center sphere center: {x,y,z} in cm + * @param r sphere radius in cm + * @param accuracy desired accuracy in cm for reaching the surface + * @param sMax maximum path length in cm + * @param h initial step size in cm + * @param tolerance desired tolerance; the integrator adapts step size to meet this tolerance + * @return the result of the swim + */ + CLAS12SwimResult swimSphere(int q, double xo, double yo, double zo, double p, double theta, double phi, + double center[], double r, double accuracy, double sMax, double h, + double tolerance); + + /** + * Swim a particle to the surface of a target sphere. + * The sphere is specified by a {@link Sphere} object. + * + * @param q particle charge in integer units of e + * @param xo initial x vertex position in cm + * @param yo initial y vertex position in cm + * @param zo initial z vertex position in cm + * @param p initial momentum magnitude in GeV/c + * @param theta initial polar angle in degrees + * @param phi initial azimuthal angle in degrees + * @param targetSphere target sphere + * @param accuracy desired accuracy in cm for reaching the surface + * @param sMax maximum path length in cm + * @param h initial step size in cm + * @param tolerance desired tolerance; the integrator adapts step size to meet this tolerance + * @return the result of the swim + */ + CLAS12SwimResult swimSphere(int q, double xo, double yo, double zo, double p, double theta, double phi, + Sphere targetSphere, double accuracy, double sMax, double h, + double tolerance); + + /** + * Swim a particle until it intersects a target plane or until {@code sMax} is reached. + * The plane is defined by the components of a normal vector and the components of a point on the plane. + * + * @param q particle charge in integer units of e + * @param xo initial x vertex position in cm + * @param yo initial y vertex position in cm + * @param zo initial z vertex position in cm + * @param p initial momentum magnitude in GeV/c + * @param theta initial polar angle in degrees + * @param phi initial azimuthal angle in degrees + * @param nx plane normal x-component + * @param ny plane normal y-component + * @param nz plane normal z-component + * @param px x-component of a point on the plane (cm) + * @param py y-component of a point on the plane (cm) + * @param pz z-component of a point on the plane (cm) + * @param accuracy desired accuracy in cm for reaching the plane + * @param sMax maximum path length in cm + * @param h initial step size in cm + * @param tolerance desired tolerance; the integrator adapts step size to meet this tolerance + * @return the result of the swim + */ + CLAS12SwimResult swimPlane(int q, double xo, double yo, double zo, double p, double theta, double phi, + double nx, double ny, double nz, double px, double py, double pz, + double accuracy, double sMax, double h, double tolerance); + + /** + * Swim a particle until it intersects a target plane or until {@code sMax} is reached. + * The plane is defined by a normal vector and a point on the plane. + * + * @param q particle charge in integer units of e + * @param xo initial x vertex position in cm + * @param yo initial y vertex position in cm + * @param zo initial z vertex position in cm + * @param p initial momentum magnitude in GeV/c + * @param theta initial polar angle in degrees + * @param phi initial azimuthal angle in degrees + * @param norm plane normal vector {nx, ny, nz} + * @param point a point on the plane {px, py, pz} in cm + * @param accuracy desired accuracy in cm for reaching the plane + * @param sMax maximum path length in cm + * @param h initial step size in cm + * @param tolerance desired tolerance; the integrator adapts step size to meet this tolerance + * @return the result of the swim + */ + CLAS12SwimResult swimPlane(int q, double xo, double yo, double zo, double p, double theta, double phi, + double norm[], double point[], double accuracy, double sMax, double h, + double tolerance); + + /** + * Swim a particle until it intersects a target plane or until {@code sMax} is reached. + * The plane is specified by a {@link Plane} object. + * + * @param q particle charge in integer units of e + * @param xo initial x vertex position in cm + * @param yo initial y vertex position in cm + * @param zo initial z vertex position in cm + * @param p initial momentum magnitude in GeV/c + * @param theta initial polar angle in degrees + * @param phi initial azimuthal angle in degrees + * @param targetPlane target plane + * @param accuracy desired accuracy in cm for reaching the plane + * @param sMax maximum path length in cm + * @param h initial step size in cm + * @param tolerance desired tolerance; the integrator adapts step size to meet this tolerance + * @return the result of the swim + */ + CLAS12SwimResult swimPlane(int q, double xo, double yo, double zo, double p, double theta, double phi, + Plane targetPlane, double accuracy, double sMax, double h, + double tolerance); + + /** + * Swim to a target {@code z} (cm) in a sector coordinate system. + *+ * Important: this is only valid if the underlying field/probe is a rotated composite + * field implementation (your {@code CLAS12Swimmer} uses {@link cnuphys.magfield.RotatedCompositeProbe} + * internally for sector coordinate transforms). + *
+ * The swim is terminated when the particle reaches {@code zTarget} or if {@code sMax} is reached. + * + * @param sector sector number in [1..6] + * @param q particle charge in integer units of e + * @param xo initial x vertex position in cm + * @param yo initial y vertex position in cm + * @param zo initial z vertex position in cm + * @param p initial momentum magnitude in GeV/c + * @param theta initial polar angle in degrees + * @param phi initial azimuthal angle in degrees + * @param zTarget target z position in cm + * @param accuracy desired accuracy in cm + * @param sMax maximum path length in cm + * @param h initial step size in cm + * @param tolerance desired tolerance; the integrator adapts step size to meet this tolerance + * @return the result of the swim + */ + CLAS12SwimResult sectorSwimZ(int sector, int q, double xo, double yo, double zo, double p, double theta, + double phi, double zTarget, double accuracy, double sMax, double h, + double tolerance); + + /** + * Swim to a target {@code z} (cm). + * The swim is terminated when the particle reaches {@code zTarget} or if {@code sMax} is reached. + * + * @param q particle charge in integer units of e + * @param xo initial x vertex position in cm + * @param yo initial y vertex position in cm + * @param zo initial z vertex position in cm + * @param p initial momentum magnitude in GeV/c + * @param theta initial polar angle in degrees + * @param phi initial azimuthal angle in degrees + * @param zTarget target z position in cm + * @param accuracy desired accuracy in cm + * @param sMax maximum path length in cm + * @param h initial step size in cm + * @param tolerance desired tolerance; the integrator adapts step size to meet this tolerance + * @return the result of the swim + */ + CLAS12SwimResult swimZ(int q, double xo, double yo, double zo, double p, double theta, double phi, + double zTarget, double accuracy, double sMax, double h, double tolerance); + + /** + * Swim to a target cylindrical radius {@code rho} (cm), i.e. to the surface of an infinite cylinder + * about the z-axis. + * The swim is terminated when the particle reaches {@code rhoTarget} or if {@code sMax} is reached. + * + * @param q particle charge in integer units of e + * @param xo initial x vertex position in cm + * @param yo initial y vertex position in cm + * @param zo initial z vertex position in cm + * @param p initial momentum magnitude in GeV/c + * @param theta initial polar angle in degrees + * @param phi initial azimuthal angle in degrees + * @param rhoTarget target rho (radius) in cm + * @param accuracy desired accuracy in cm + * @param sMax maximum path length in cm + * @param h initial step size in cm + * @param tolerance desired tolerance; the integrator adapts step size to meet this tolerance + * @return the result of the swim + */ + CLAS12SwimResult swimRho(int q, double xo, double yo, double zo, double p, double theta, double phi, + double rhoTarget, double accuracy, double sMax, double h, double tolerance); + + /** + * Swim to an "offset beamline" listener. + * The offset beamline is a line parallel to the z-axis, offset in x and y by {@code xb} and {@code yb}. + * The goal is to swim to the distance of closest approach (DOCA) to this offset line. + * Swim terminates when successive DOCA estimates differ by less than {@code accuracy}. + * + * @param q particle charge in integer units of e + * @param xo initial x vertex position in cm + * @param yo initial y vertex position in cm + * @param zo initial z vertex position in cm + * @param p initial momentum magnitude in GeV/c + * @param theta initial polar angle in degrees + * @param phi initial azimuthal angle in degrees + * @param xb beamline x offset in cm + * @param yb beamline y offset in cm + * @param accuracy desired DOCA convergence accuracy in cm + * @param sMax maximum path length in cm + * @param h initial step size in cm + * @param tolerance desired tolerance; the integrator adapts step size to meet this tolerance + * @return the result of the swim + */ + CLAS12SwimResult swimZLine(int q, double xo, double yo, double zo, double p, double theta, double phi, + double xb, double yb, double accuracy, double sMax, double h, double tolerance); + + /** + * Swim to the beamline (defined by {@code rho = 0}), i.e. find the distance of closest approach (DOCA) + * to the z-axis. + * Swim terminates when successive DOCA estimates differ by less than {@code accuracy}. + * + * @param q particle charge in integer units of e + * @param xo initial x vertex position in cm + * @param yo initial y vertex position in cm + * @param zo initial z vertex position in cm + * @param p initial momentum magnitude in GeV/c + * @param theta initial polar angle in degrees + * @param phi initial azimuthal angle in degrees + * @param accuracy desired DOCA convergence accuracy in cm + * @param sMax maximum path length in cm + * @param h initial step size in cm + * @param tolerance desired tolerance; the integrator adapts step size to meet this tolerance + * @return the result of the swim + */ + CLAS12SwimResult swimBeamline(int q, double xo, double yo, double zo, double p, double theta, double phi, + double accuracy, double sMax, double h, double tolerance); +} diff --git a/common-tools/cnuphys/swimmer/src/main/java/cnuphys/CLAS12Swim/ODEStepListener.java b/common-tools/cnuphys/swimmer/src/main/java/cnuphys/CLAS12Swim/ODEStepListener.java new file mode 100644 index 0000000000..6cbc0d0c0d --- /dev/null +++ b/common-tools/cnuphys/swimmer/src/main/java/cnuphys/CLAS12Swim/ODEStepListener.java @@ -0,0 +1,16 @@ +package cnuphys.CLAS12Swim; + +/** + * Interface for listening to steps taken by an ODE solver. + */ +public interface ODEStepListener { + /** + * Called when a new step is taken in the ODE solving process. + * + * @param newT The new independent variable after the step. + * @param newY The new state vector after the step. + * @return A boolean indicating whether to continue (true) or stop (false) the + * integration. + */ + boolean newStep(double newT, double[] newY); +} diff --git a/common-tools/cnuphys/swimmer/src/main/java/cnuphys/CLAS12Swim/geometry/Cylinder.java b/common-tools/cnuphys/swimmer/src/main/java/cnuphys/CLAS12Swim/geometry/Cylinder.java new file mode 100644 index 0000000000..0f89c9d215 --- /dev/null +++ b/common-tools/cnuphys/swimmer/src/main/java/cnuphys/CLAS12Swim/geometry/Cylinder.java @@ -0,0 +1,109 @@ +package cnuphys.CLAS12Swim.geometry; + + +/** + * An INFINITE cylinder is defined by a centerline and a radius + * @author heddle + * + */ +public class Cylinder { + + //the centerline + private Line _centerLine; + + //the radius + public double radius; + + /** + * Create a cylinder + * @param centerLine the center line + * @param radius the radius + */ + public Cylinder(Line centerLine, double radius) { + _centerLine = new Line(centerLine); + this.radius = radius; + } + + /** + * Create a cylinder + * @param p1 one point of center line as an xyz array + * @param p2 another point of center line as an xyz array + * @param radius + */ + public Cylinder(double[] p1, double[] p2, double radius) { + this(new Line(p1, p2), radius); + } + + + /** + * Get the shortest distance between the surface of this infinite cylinder and a point. + * If the value is negative, we are inside the cylinder. + * @param p a point + * @return the perpendicular distance + */ + public double signedDistance(Point p) { + double lineDist = _centerLine.distance(p); + return lineDist - radius; + } + + /** + * Set the path length of the swim + * @deprecated Use {@link Cylinder#signedDistance} instead. + * @param p a point + * @return the perpendicular distance + */ + @Deprecated + public double distance(Point p) { + double lineDist = _centerLine.distance(p); + return lineDist - radius; + } + + /** + * Get the shortest distance between the surface of this infinite cylinder and a point. + * If the value is negative, we are inside the cylinder. + * @param x the x coordinate + * @param y the y coordinate + * @param z the z coordinate + * @return the perpendicular distance + */ + public double signedDistance(double x, double y, double z) { + Point p = new Point(x, y, z); + return signedDistance(p); + } + + /** + * Get the shortest absolute distance between the surface of this infinite cylinder and a point. + * @param x the x coordinate + * @param y the y coordinate + * @param z the z coordinate + * @return the perpendicular distance + */ + public double distance(double x, double y, double z) { + Point p = new Point(x, y, z); + return Math.abs(signedDistance(p)); + } + + /** + * Is the point inside the cylinder? + * @param x the x coordinate + * @param y the y coordinate + * @param z the z coordinate + * @returntrue if the point is inside the cylinder.
+ */
+ public boolean isInside(double x, double y, double z) {
+ return signedDistance(x, y, z) < 0;
+ }
+
+ /**
+ * Is the cylinder centered on the z axis?
+ * @return true if the cylinder is centered on the z axis.
+ */
+ public boolean centeredOnZ() {
+ double x0 = _centerLine.getP0().x;
+ double y0 = _centerLine.getP0().y;
+ double x1 = _centerLine.getP1().x;
+ double y1 = _centerLine.getP1().y;
+ return (x0 == 0) && (y0 == 0) && (x1 == 0) && (y1 == 0);
+ }
+
+}
diff --git a/common-tools/cnuphys/swimmer/src/main/java/cnuphys/CLAS12Swim/geometry/Line.java b/common-tools/cnuphys/swimmer/src/main/java/cnuphys/CLAS12Swim/geometry/Line.java
new file mode 100644
index 0000000000..ebb96780c8
--- /dev/null
+++ b/common-tools/cnuphys/swimmer/src/main/java/cnuphys/CLAS12Swim/geometry/Line.java
@@ -0,0 +1,157 @@
+package cnuphys.CLAS12Swim.geometry;
+
+/**
+ * 3D line of the form p(t) = po + t*dp where p(t) is a point on the line, po is
+ * one point and dp = (p1-po) where p1 is another point. If this is an infinite
+ * line, the t = [-infinity, infinity]. If this is a directed segment, t = [0,
+ * 1]
+ *
+ * @author heddle
+ *
+ */
+public class Line {
+
+ private Point _po; // "start" point on the line
+ private Vector _dp; // segment from start to end
+ private double _dpLen; // length of start to end segment
+
+ /**
+ * Create a line from two points on the line. If this is a directed line
+ * segment, the line will go from po to p1.
+ *
+ * @param po one point
+ * @param p1 the other point
+ */
+ public Line(Point po, Point p1) {
+ _po = new Point(po);
+ _dp = new Vector(Point.difference(p1, po));
+ _dpLen = _dp.length();
+ }
+
+ /**
+ * Create a line from two ponts passed as arrays
+ * @param p1 one point as an xyz array
+ * @param p2 another point as an xyz array
+ */
+ public Line(double[] p1, double[] p2) {
+ this(new Point(p1), new Point(p2));
+ }
+
+ /**
+ * Copy constructor
+ * @param line the line to copy
+ */
+ public Line(Line line) {
+ _po = new Point(line._po);
+ _dp = new Vector(line._dp);
+ _dpLen = line._dpLen;
+ }
+
+ /**
+ * Create a line from the origing in the direction of a vector
+ * @param v the vector
+ */
+ public Line(Vector v) {
+ this(new Point(0,0,0), new Point(v.x, v.y, v.z));
+ }
+
+ /**
+ * Get the po "start" point. This is just an arbitrary point on an infinite
+ * line, but the starting point if this is a directed line segment
+ *
+ * @return the "starting" point.
+ */
+ public Point getP0() {
+ return _po;
+ }
+
+ /**
+ * Get the p1-po "dP" segment
+ *
+ * @return dP = p1 - po
+ */
+ public Vector getDelP() {
+ return _dp;
+ }
+
+ /**
+ * Get the p1 "end" point. This is just an arbitrary point on an infinite line,
+ * but the end point if this is a directed line segment
+ *
+ * @return the "end" point.
+ */
+ public Point getP1() {
+ return new Point(_po.x + _dp.x, _po.y + _dp.y, _po.z + _dp.z);
+ }
+
+ /**
+ * Get a point on the line
+ *
+ * @param t the t parameter. If this is a directed line segment, t should be
+ * restricted to [0, 1]
+ * @return a point on the line
+ */
+ public Point getP(double t) {
+ Point p = new Point();
+ getP(t, p);
+ return p;
+ }
+
+ /**
+ * Get a point on the line (in place)
+ *
+ * @param t the t parameter. If this is a directed line segment, t should be
+ * restricted to [0, 1]
+ * @param p upon return, a point on the line
+ */
+ public void getP(double t, Point p) {
+ p.x = _po.x + t * _dp.x;
+ p.y = _po.y + t * _dp.y;
+ p.z = _po.z + t * _dp.z;
+ }
+
+ /**
+ * Get the shortest distance between this line (as an infinite line) and a point
+ *
+ * @param p a point
+ * @return the perpendicular distance
+ */
+ public double distance(Point p) {
+ Vector ap = new Vector(Point.difference(p, _po));
+ Vector c = Vector.cross(ap, _dp);
+ return c.length() / _dpLen;
+ }
+
+ /**
+ * Find the point on the line closest to the given point
+ * @param p the given point
+ * @return the point on the line closest to the given point
+ */
+ public Point closestPointOnLine(Point p) {
+ Point pointVec = p.subtract(_po);
+ double t = pointVec.dot(_dp) / _dp.dot(_dp);
+ return _po.add(_dp.scale(t));
+ }
+
+
+
+ /**
+ * Get a String representation
+ *
+ * @return a String representation of the Line
+ */
+ @Override
+ public String toString() {
+ return "Line from " + getP0() + " to " + getP1();
+ }
+
+ /**
+ * Get the center of the line
+ *
+ * @return the center of the line
+ */
+ public Point getCenter() {
+ return getP(0.5);
+ }
+
+}
\ No newline at end of file
diff --git a/common-tools/cnuphys/swimmer/src/main/java/cnuphys/CLAS12Swim/geometry/Plane.java b/common-tools/cnuphys/swimmer/src/main/java/cnuphys/CLAS12Swim/geometry/Plane.java
new file mode 100644
index 0000000000..623ec5873b
--- /dev/null
+++ b/common-tools/cnuphys/swimmer/src/main/java/cnuphys/CLAS12Swim/geometry/Plane.java
@@ -0,0 +1,325 @@
+package cnuphys.CLAS12Swim.geometry;
+
+/**
+ * A plane is defined by the equation (r - ro).norm = 0 Where r is an arbitrary
+ * point on the plane, ro is a given point on the plane and norm is the normal
+ * to the plane
+ *
+ * @author heddle
+ *
+ */
+public class Plane {
+
+ /** Effectively zero */
+ private static final double TINY = 1.0e-20;
+
+ // for the form ax + by + cz = d;
+ public final double a;
+ public final double b;
+ public final double c;
+ public final double d;
+
+ private double _denom = Double.NaN;
+
+ /**
+ * Create a plane from a normal vector and a point on the plane
+ *
+ * @param norm the normal vector
+ * @param p0 a point in the plane
+ * @return the plane that contains p and its normal is norm
+ */
+ public Plane(Vector anorm, Point p0) {
+ // lets make it a unit vector
+ Vector norm = anorm.unitVector();
+ a = norm.x; // A
+ b = norm.y; // B
+ c = norm.z; // C
+ d = a * p0.x + b * p0.y + c * p0.z; // D
+ }
+
+ /**
+ * Create a plane from the coefficients of the equation ax + by + cz = d
+ *
+ * @param a the a coefficient
+ * @param b the b coefficient
+ * @param c the c coefficient
+ * @param d the d coefficient
+ */
+ public Plane(double a, double b, double c, double d) {
+ this.a = a;
+ this.b = b;
+ this.c = c;
+ this.d = d;
+ }
+
+ /**
+ * Create a plane from the normal vector in an array of doubles and a point in
+ * the plane in an array, both (x, y, z)
+ *
+ * @param norm the normal
+ * @param point the point in the plane
+ */
+ public Plane(double norm[], double point[]) {
+
+ this(new Vector(norm[0], norm[1], norm[2]), new Point(point[0], point[1], point[2]));
+ }
+
+ /**
+ * Create a plane from a normal vector and a point on the plane
+ *
+ * @param nx x component of normal vector
+ * @param ny y component of normal vector
+ * @param nz z component of normal vector
+ * @param px x component of point on plane
+ * @param py y component of point on plane
+ * @param pz z component of point on plane
+ */
+ public Plane(double nx, double ny, double nz, double px, double py, double pz) {
+
+ this(new Vector(nx, ny, nz), new Point(px, py, pz));
+ }
+
+ /**
+ * Create a line from two points and then get the intersection with the plane
+ *
+ * @param p1 one point
+ * @param p2 another point
+ * @param p will hold the intersection, NaNs if no intersection
+ * @return the t parameter. If NaN it means the line is parallel to the plane.
+ * If t [0,1] then the segment intersects the plane. If t outside [0, 1]
+ * the infinite line intersects the plane, but not the segment
+ */
+ public double interpolate(Point p1, Point p2, Point p) {
+ Line line = new Line(p1, p2);
+ return lineIntersection(line, p);
+ }
+
+ /**
+ * Distance from a point to the plane
+ *
+ * @param x the x coordinate
+ * @param y the y coordinate
+ * @param z the z coordinate
+ * @return the signed distance (indicates which side you are on where norm
+ * defines positive side)
+ */
+ public double distance(double x, double y, double z) {
+ return Math.abs(signedDistance(x, y, z));
+ }
+
+ /**
+ * Signed distance from a point to the plane
+ *
+ * @param x the x coordinate
+ * @param y the y coordinate
+ * @param z the z coordinate
+ * @return the signed distance (indicates which side you are on where norm
+ * defines positive side)
+ */
+ public double signedDistance(double x, double y, double z) {
+ if (Double.isNaN(_denom)) {
+ _denom = Math.sqrt(a * a + b * b + c * c);
+ }
+ return (a * x + b * y + c * z - d) / _denom;
+ }
+
+ /**
+ * Compute the intersection of an infinite line with the plane
+ *
+ * @param line the line
+ * @param intersection will hold the point of intersection
+ * @return the t parameter. If NaN it means the line is parallel to the plane.
+ * If t [0,1] then the segment intersects the plane. If t outside [0, 1]
+ * the infinite line intersects the plane, but not the segment
+ */
+ public double lineIntersection(Line line, Point intersection) {
+ // Direction vector of the line
+ Vector lineDir = line.getDelP();
+
+ Point p0 = line.getP0();
+
+ // Check if the line is parallel to the plane
+ double dotProduct = a * lineDir.x + b * lineDir.y + c * lineDir.z;
+ if (Math.abs(dotProduct) < TINY) {
+ System.err.println("The line is parallel to the plane in Plane.findLinePlaneIntersection.");
+ return Double.NaN;
+ }
+
+ // Parameter t in the parametric line equation
+ double t = (d - a * p0.x - b * p0.y - c * p0.z) / dotProduct;
+
+ line.getP(t, intersection);
+ return t;
+ }
+
+ /**
+ * Get whether the point is to the left, right or (exactly) on the plane
+ *
+ * @param x the x coordinate
+ * @param y the y coordinate
+ * @param z the z coordinate
+ * @return +1 if to the left, -1 if to the right, 0 if on the plane
+ */
+ public int sign(double x, double y, double z) {
+ double result = a * x + b * y + c * z;
+
+ if (result > d) {
+ return +1;
+ } else if (result < d) {
+ return -1;
+ } else {
+ return 0;
+ }
+ }
+
+ /**
+ * Create a plane of constant azimuthal angle phi
+ *
+ * @param phi the azimuthal angle in degrees
+ * @return the plane of constant phi
+ */
+ public static Plane constantPhiPlane(double phi) {
+ phi = Math.toRadians(phi);
+
+ double cphi = Math.cos(phi);
+ double sphi = Math.sin(phi);
+
+ // point in the plane
+ Point p = new Point(cphi, sphi, 0);
+
+ // normal
+ Vector norm = new Vector(sphi, -cphi, 0);
+
+ return new Plane(norm, p);
+ }
+
+ @Override
+ public String toString() {
+ String pstr = String.format("abcd = [%10.6G, %10.6G, %10.6G, %10.6G]", a, b, c, d);
+ return pstr;
+ }
+
+ // is the value essentially 0?
+ private boolean tiny(double v) {
+ return Math.abs(v) < TINY;
+ }
+
+ /**
+ * Find some coordinates suitable for drawing the plane as a Quad in 3D
+ *
+ * @param scale an arbitrary big number, a couple times bigger than the drawing
+ * extent
+ * @return the jogl coordinates for drawing a Quad
+ */
+ public float[] planeQuadCoordinates(float scale) {
+
+ int[] i1 = { -1, -1, 1, 1 };
+ int[] i2 = { -1, 1, 1, -1 };
+
+ if (tiny(a) && tiny(b) && tiny(c)) {
+ return null;
+ }
+
+ float[] coords = new float[12];
+
+ if (tiny(b) && tiny(c)) { // constant x plane
+ float fx = (float) (d / a);
+ for (int k = 0; k < 4; k++) {
+ int j = 3 * k;
+
+ float y = scale * i1[k];
+ float z = scale * i2[k];
+
+ coords[j] = fx;
+ coords[j + 1] = y;
+ coords[j + 2] = z;
+ }
+
+ } else if (tiny(a) && tiny(c)) { // constant y plane
+ float fy = (float) (d / b);
+ for (int k = 0; k < 4; k++) {
+ int j = 3 * k;
+
+ float x = scale * i1[k];
+ float z = scale * i2[k];
+
+ coords[j] = x;
+ coords[j + 1] = fy;
+ coords[j + 2] = z;
+ }
+ } else if (tiny(a) && tiny(b)) { // constant z plane
+ float fz = (float) (d / c);
+ for (int k = 0; k < 4; k++) {
+ int j = 3 * k;
+
+ float x = scale * i1[k];
+ float y = scale * i2[k];
+
+ coords[j] = x;
+ coords[j + 1] = y;
+ coords[j + 2] = fz;
+ }
+ }
+
+ else if (tiny(a)) {
+ for (int k = 0; k < 4; k++) {
+ int j = 3 * k;
+
+ float x = scale * i1[k];
+ float y = scale * i2[k];
+ float z = (float) ((d - b * y) / c);
+
+ coords[j] = x;
+ coords[j + 1] = y;
+ coords[j + 2] = z;
+ }
+ }
+
+ else if (tiny(b)) {
+ for (int k = 0; k < 4; k++) {
+ int j = 3 * k;
+
+ float x = scale * i1[k];
+ float y = scale * i2[k];
+ float z = (float) ((d - a * x) / c);
+
+ coords[j] = x;
+ coords[j + 1] = y;
+ coords[j + 2] = z;
+ }
+
+ }
+
+ else if (tiny(c)) {
+ for (int k = 0; k < 4; k++) {
+ int j = 3 * k;
+
+ float x = scale * i1[k];
+ float z = scale * i2[k];
+ float y = (float) ((d - a * x) / b);
+
+ coords[j] = x;
+ coords[j + 1] = y;
+ coords[j + 2] = z;
+ }
+
+ }
+
+ else { // general case, no small constants
+ for (int k = 0; k < 4; k++) {
+ int j = 3 * k;
+
+ float x = scale * i1[k];
+ float y = scale * i2[k];
+ float z = (float) ((d - a * x - b * y) / c);
+
+ coords[j] = x;
+ coords[j + 1] = y;
+ coords[j + 2] = z;
+ }
+ }
+
+ return coords;
+ }
+
+}
\ No newline at end of file
diff --git a/common-tools/cnuphys/swimmer/src/main/java/cnuphys/CLAS12Swim/geometry/Point.java b/common-tools/cnuphys/swimmer/src/main/java/cnuphys/CLAS12Swim/geometry/Point.java
new file mode 100644
index 0000000000..00bad9c3f7
--- /dev/null
+++ b/common-tools/cnuphys/swimmer/src/main/java/cnuphys/CLAS12Swim/geometry/Point.java
@@ -0,0 +1,186 @@
+package cnuphys.CLAS12Swim.geometry;
+
+public class Point {
+
+ /** x component */
+ public double x;
+ /** y component */
+ public double y;
+ /** z component */
+ public double z;
+
+ /**
+ * Create a point at the origin
+ */
+ public Point() {
+ this(0, 0, 0);
+ }
+
+ /**
+ * Copy constructor
+ *
+ * @param p the point to copy
+ */
+ public Point(Point p) {
+ this(p.x, p.y, p.z);
+ }
+
+ /**
+ * Create a point
+ *
+ * @param x the x coordinate
+ * @param y the y coordinate
+ * @param z the z coordinate
+ */
+ public Point(double x, double y, double z) {
+ this.x = x;
+ this.y = y;
+ this.z = z;
+ }
+
+ /**
+ * Create a point from an xyz array
+ * @param p the point as an xyz array
+ */
+ public Point(double[] p) {
+ this(p[0], p[1], p[2]);
+ }
+
+ /**
+ * Set the components of the point (vector)
+ *
+ * @param x the x component
+ * @param y the y component
+ * @param z the z component
+ */
+ public void set(double x, double y, double z) {
+ this.x = x;
+ this.y = y;
+ this.z = z;
+ }
+
+ /**
+ * Set the components of the point (vector)
+ * @param p the point to use to set (e.g., copy)
+ */
+ public void set(Point p) {
+ this.x = p.x;
+ this.y = p.y;
+ this.z = p.z;
+ }
+
+ /**
+ * Get the difference between two points
+ *
+ * @param a one point
+ * @param b the other point
+ * @return the difference between two points a - b
+ */
+ public static Point difference(Point a, Point b) {
+ return new Point(a.x - b.x, a.y - b.y, a.z - b.z);
+ }
+
+ /**
+ * Method to subtract another point from this point
+ *
+ * @param other the point to subtract
+ * @return the difference between this point and the other point
+ */
+ public Point subtract(Point other) {
+ return new Point(x - other.x, y - other.y, z - other.z);
+ }
+
+ /**
+ * Get the in-place difference between two points
+ *
+ * @param a one point
+ * @param b the other point
+ * @param c upon return the difference between two points a - b
+ */
+ public static void difference(Point a, Point b, Point c) {
+ c.set(a.x - b.x, a.y - b.y, a.z - b.z);
+ }
+
+ /**
+ * The dot product of this "vector" with another vector
+ *
+ * @param v the other vector or point
+ * @return the dot product
+ */
+ public double dot(Point v) {
+ return x * v.x + y * v.y + z * v.z;
+ }
+
+ /**
+ * The dot product of two vectors or points
+ *
+ * @param a one vector or point
+ * @param b the other vector or point
+ * @return the dot product
+ */
+ public static double dot(Point a, Point b) {
+ return a.dot(b);
+ }
+
+ /**
+ * Get a string representation of the Point
+ *
+ * @return a String representation
+ */
+ @Override
+ public String toString() {
+ return String.format("(%-10.6f, %-10.6f, %-10.6f)", x, y, z);
+ }
+
+ /**
+ * Compute the distance to another point
+ * @param x the x coordinate of the other point
+ * @param y the y coordinate of the other point
+ * @param z the z coordinate of the other point
+ * @return the distance between the points
+ */
+ public double distance(double x, double y, double z) {
+ double dx = x - this.x;
+ double dy = y - this.y;
+ double dz = z - this.z;
+ return Math.sqrt(dx*dx + dy*dy + dz*dz);
+ }
+
+ /**
+ * Compute the distance to another point
+ * @param p the other point
+ * @return the distance between the points
+ */
+ public double distance(Point p) {
+ return distance(p.x, p.y, p.z);
+ }
+
+ /** Method to calculate distance between two points
+ *
+ * @param p1 one point
+ * @param p2 the other point
+ * @return the distance between the two points
+ */
+ public static double distance(Point p1, Point p2) {
+ return p1.distance(p2);
+ }
+
+ /**
+ * Add another point to this point (i.e., vector addition)
+ * @param other the other point
+ * @return the sum of the two points
+ */
+ public Point add(Point other) {
+ return new Point(x + other.x, y + other.y, z + other.z);
+ }
+
+ /**
+ * Scale this point by a scalar
+ * @param scalar the scalar multiplier
+ * @return the scaled point
+ */
+ public Point scale(double scalar) {
+ return new Point(x * scalar, y * scalar, z * scalar);
+ }
+
+}
\ No newline at end of file
diff --git a/common-tools/cnuphys/swimmer/src/main/java/cnuphys/CLAS12Swim/geometry/Sphere.java b/common-tools/cnuphys/swimmer/src/main/java/cnuphys/CLAS12Swim/geometry/Sphere.java
new file mode 100644
index 0000000000..c7ecff95ab
--- /dev/null
+++ b/common-tools/cnuphys/swimmer/src/main/java/cnuphys/CLAS12Swim/geometry/Sphere.java
@@ -0,0 +1,155 @@
+package cnuphys.CLAS12Swim.geometry;
+
+/**
+ * A sphere centered at an arbitrary point
+ *
+ * @author heddle
+ *
+ */
+public class Sphere {
+
+ // the center
+ private Point _center;
+
+ // the radius
+ private double _radius;
+
+ /**
+ * Create a sphere
+ *
+ * @param center the center of the sphere
+ * @param radius the radius of the sphere
+ */
+ public Sphere(Point center, double radius) {
+ _center = new Point(center);
+ _radius = radius;
+ }
+
+ /**
+ * Create a sphere
+ *
+ * @param center the center of the sphere as an xyz array
+ * @param radius the radius of the sphere
+ */
+ public Sphere(double[] center, double radius) {
+ this(new Point(center[0], center[1], center[2]), radius);
+ }
+
+ /**
+ * Create a sphere centered on the origin
+ *
+ * @param radius the radius of the sphere
+ */
+ public Sphere(double radius) {
+ this(new Point(0, 0, 0), radius);
+ }
+
+ /**
+ * Get the radius of the sphere
+ *
+ * @return the radius of the sphere
+ */
+ public double getRadius() {
+ return _radius;
+ }
+
+ /**
+ * Get the shortest distance between the surface of this sphere and a point. If
+ * the value is negative, we are inside the sphere.
+ *
+ * @param p a point
+ * @return the distance to the sphere
+ */
+ public double signedDistance(Point p) {
+ double centDist = _center.distance(p);
+ return centDist - _radius;
+ }
+
+ /**
+ * Get the shortest distance between the surface of this sphere and a point. If
+ * the value is negative, we are inside the sphere.
+ *
+ * @param x the x coordinate
+ * @param y the y coordinate
+ * @param z the z coordinate
+ * @return the distance to the sphere
+ */
+ public double signedDistance(double x, double y, double z) {
+ Point p = new Point(x, y, z);
+ return signedDistance(p);
+ }
+
+ /**
+ * Get the shortest absolute distance between the surface of this infinite cylinder and a point.
+ * @param x the x coordinate
+ * @param y the y coordinate
+ * @param z the z coordinate
+ * @return the perpendicular distance
+ */
+ public double distance(double x, double y, double z) {
+ Point p = new Point(x, y, z);
+ return Math.abs(signedDistance(p));
+ }
+
+ /**
+ * Is the point inside the sphere?
+ * @param x the x coordinate
+ * @param y the y coordinate
+ * @param z the z coordinate
+ * @return true if the point is inside the sphere.
+ */
+ public boolean isInside(double x, double y, double z) {
+ return signedDistance(x, y, z) < 0;
+ }
+
+ /**
+ * Check whether a segment intersects the sphere
+ *
+ * @param x1 x coordinate of one end of segment
+ * @param y1 y coordinate of one end of segment
+ * @param z1 z coordinate of one end of segment
+ * @param x2 x coordinate of other end of segment
+ * @param y2 y coordinate of other end of segment
+ * @param z2 z coordinate of other end of segment
+ * @return true if the segment intersects the sphere
+ */
+ public boolean segmentIntersects(double x1, double y1, double z1, double x2, double y2, double z2) {
+ return (distToSegment(0, 0, 0, x1, y1, z1, x2, y2, z2) < _radius);
+ }
+
+ /**
+ * The closest distance of a line segment to a point
+ *
+ * @param px x coordinate of point
+ * @param py y coordinate of point
+ * @param pz z coordinate of point
+ * @param x1 x coordinate of one end of segment
+ * @param y1 y coordinate of one end of segment
+ * @param z1 z coordinate of one end of segment
+ * @param x2 x coordinate of other end of segment
+ * @param y2 y coordinate of other end of segment
+ * @param z2 z coordinate of other end of segment
+ * @return the closest distance of the segment to point p
+ */
+ private double distToSegment(double px, double py, double pz, double x1, double y1, double z1, double x2, double y2,
+ double z2) {
+
+ double line_dist = distSq(x1, y1, z1, x2, y2, z2);
+ if (line_dist == 0) {
+ return distSq(px, py, pz, x1, y1, z1);
+ }
+ double t = ((px - x1) * (x2 - x1) + (py - y1) * (y2 - y1) + (pz - z1) * (z2 - z1)) / line_dist;
+ t = Math.max(0, Math.min(1, t));
+ return Math.sqrt(distSq(px, py, pz, x1 + t * (x2 - x1), y1 + t * (y2 - y1), z1 + t * (z2 - z1)));
+ }
+
+ // the square of the distance between two points
+ private double distSq(double x1, double y1, double z1, double x2, double y2, double z2) {
+ double dx = x2 - x1;
+ double dy = y2 - y1;
+ double dz = z2 - z1;
+ return dx * dx + dy * dy + dz * dz;
+
+ }
+
+}
diff --git a/common-tools/cnuphys/swimmer/src/main/java/cnuphys/CLAS12Swim/geometry/Vector.java b/common-tools/cnuphys/swimmer/src/main/java/cnuphys/CLAS12Swim/geometry/Vector.java
new file mode 100644
index 0000000000..8c00dfbd4d
--- /dev/null
+++ b/common-tools/cnuphys/swimmer/src/main/java/cnuphys/CLAS12Swim/geometry/Vector.java
@@ -0,0 +1,142 @@
+package cnuphys.CLAS12Swim.geometry;
+
+/**
+ * Ordinary 3D vector
+ *
+ * @author heddle
+ *
+ */
+public class Vector extends Point {
+
+ /** Effectively zero */
+ private static final double TINY = 1.0e-20;
+
+
+ /**
+ * Create a new vector with a zero components
+ */
+ public Vector() {
+ }
+
+ /**
+ * Create a Vector from a point
+ *
+ * @param p the point
+ */
+ public Vector(Point p) {
+ this(p.x, p.y, p.z);
+ }
+
+ /**
+ * Create a vector
+ *
+ * @param x the x coordinate
+ * @param y the y coordinate
+ * @param z the z coordinate
+ */
+ public Vector(double x, double y, double z) {
+ super(x, y, z);
+ }
+
+ /**
+ * The square of the length of the vector
+ *
+ * @return the square of the length of the vector
+ */
+ public double lengthSquared() {
+ return x * x + y * y + z * z;
+ }
+
+ /**
+ * The length of the vector
+ *
+ * @return the length of the vector
+ */
+ public double length() {
+ return Math.sqrt(lengthSquared());
+ }
+
+ /**
+ * The cross product of two vectors
+ *
+ * @param a one vector
+ * @param b other vector
+ * @return c = a x b
+ */
+ public static Vector cross(Vector a, Vector b) {
+ Vector c = new Vector();
+ cross(a, b, c);
+ return c;
+ }
+
+ /**
+ * The in-place cross product of two vectors
+ *
+ * @param a one vector
+ * @param b other vector
+ * @param c on return c = a x b
+ */
+ public static void cross(Vector a, Vector b, Vector c) {
+ c.x = a.y * b.z - a.z * b.y;
+ c.y = a.z * b.x - a.x * b.z;
+ c.z = a.x * b.y - a.y * b.x;
+ }
+
+
+ /**
+ * Get a unit vector in the same direction as this
+ *
+ * @return a unit vector
+ */
+ public Vector unitVector() {
+ double len = length();
+ if (len < TINY) {
+ return null;
+ }
+
+ return new Vector(x / len, y / len, z / len);
+ }
+
+ /**
+ * Multiplies each element of a vector by a scalar.
+ *
+ * @param vector The vector to be multiplied.
+ * @param scalar The scalar value for multiplication.
+ * @return The resulting vector after multiplication.
+ */
+ public static double[] scalarMultiply(double[] vector, double scalar) {
+ double[] result = new double[vector.length];
+ for (int i = 0; i < vector.length; i++) {
+ result[i] = vector[i] * scalar;
+ }
+ return result;
+ }
+
+ /**
+ * Adds multiple vectors together element-wise.
+ *
+ * @param vectors An array of vectors to be added.
+ * @return The resulting vector after addition.
+ */
+ public static double[] addVectors(double[]... vectors) {
+ if (vectors.length == 0) {
+ throw new IllegalArgumentException("At least one vector is required for addition.");
+ }
+
+ int length = vectors[0].length;
+ for (double[] vector : vectors) {
+ if (vector.length != length) {
+ throw new IllegalArgumentException("All vectors must be of the same length.");
+ }
+ }
+
+ double[] result = new double[length];
+ for (double[] vector : vectors) {
+ for (int i = 0; i < length; i++) {
+ result[i] += vector[i];
+ }
+ }
+ return result;
+ }
+
+}
\ No newline at end of file
diff --git a/common-tools/cnuphys/swimmer/src/main/java/cnuphys/adaptiveSwim/AAdaptiveStopper.java b/common-tools/cnuphys/swimmer/src/main/java/cnuphys/adaptiveSwim/AAdaptiveStopper.java
index 5247f34619..515469dc15 100644
--- a/common-tools/cnuphys/swimmer/src/main/java/cnuphys/adaptiveSwim/AAdaptiveStopper.java
+++ b/common-tools/cnuphys/swimmer/src/main/java/cnuphys/adaptiveSwim/AAdaptiveStopper.java
@@ -1,103 +1,100 @@
package cnuphys.adaptiveSwim;
-import cnuphys.swim.SwimTrajectory;
-
public abstract class AAdaptiveStopper implements IAdaptiveStopper {
-
+
//the max step size
protected static final double _THEMAXSTEP = 0.5; // meters
// the current max step size, which varies with proximity
//to a target
private double _maxStep = _THEMAXSTEP; // meters
-
protected final double _accuracy;
- protected double _s; //current path length meters
- protected final double _sf; //max pathlength meters
- protected final int _dim; //dimension of our system
- protected double[] _u; //current state vector
-
+
//last step size used
protected double _hLast = Double.NaN;
- //optional trajectory
- protected SwimTrajectory _trajectory;
+ //pathlength cutoff
+ protected double _sMax;
+
+ //swimming result
+ protected AdaptiveSwimResult _result;
+
+ //for specifying distance to a boundary
+ protected double _del = Double.NaN;
+
/**
* Create an stopper
- * @param u0 the initial state vector
- * @param sf the maximum value of the pathlength in meters
+ * @param sMax the maximum value of the pathlength in meters
* @param accuracy the required accuracy in meters
- * @param trajectory an optional trajectory
+ * @param result holds the results, its u statevector should have been initialized
+ * to the starting vector
*/
- public AAdaptiveStopper(double[] u0, final double sf, final double accuracy, SwimTrajectory trajectory) {
- _dim = u0.length;
- _s = 0;
- _sf = sf;
+ public AAdaptiveStopper(final double sMax, final double accuracy, AdaptiveSwimResult result) {
+ _sMax = sMax;
_accuracy = accuracy;
- _u = new double[_dim];
- copy(u0, _u);
- _trajectory = trajectory;
-
- if (_trajectory != null) {
- _trajectory.add(_u, 0);
+ _result = result;
+ if (_result.shouldUpdateTrajectory()) {
+ _result.getTrajectory().add(result.getU(), 0);
}
}
-
+
/**
* Get the current path length
* @return the current path length in meters
*/
@Override
public double getS() {
- return _s;
+ return _result.getS();
}
/**
- * Get the current state vector
+ * Get the current state vector from the result object
* @return the current state vector
*/
@Override
public double[] getU() {
- return _u;
+ return _result.getU();
}
/**
- * Accept a new integration step
+ * Accept a new integration step. This is also where the step is optionally added to the
+ * trajectory.
* @param snew the new value of s in meters
* @param unew the new state vector
*/
protected void accept(double snew, double[] unew) {
- copy(unew, _u);
- _s = snew;
-
+
+ _result.setU(unew);
+ _result.setS(snew);
+
//add to trajectory?
- if (_trajectory != null) {
- _trajectory.add(_u, _s);
+ if (_result.shouldUpdateTrajectory()) {
+ _result.getTrajectory().add(unew, snew);
}
}
-
+
/**
- * Get the max or final value of the path length in meters
+ * Get the max value of the path length in meters
* @return the max or final value of the path length
*/
@Override
public double getSmax() {
- return _sf;
+ return _sMax;
}
-
+
/**
* Copy a state vector
* @param uSrc the source
* @param uDest the destination
*/
protected void copy(double uSrc[], double[] uDest) {
- System.arraycopy(uSrc, 0, uDest, 0, _dim);
+ System.arraycopy(uSrc, 0, uDest, 0, AdaptiveSwimmer.DIM);
}
/**
* Get the max step size. This can vary with conditions, primarily
- * with the proximity to a target
+ * with the proximity to a target
* @return the current max step in meters
*/
@Override
@@ -113,4 +110,23 @@ protected void setMaxStep(double maxStep) {
_maxStep = Math.min(_THEMAXSTEP, Math.max(AdaptiveSwimUtilities.MIN_STEPSIZE, Math.abs(maxStep)));
}
+ @Override
+ public double getNewStepSize(double h) {
+ //_del should have been set by the stopper
+
+ if (Double.isNaN(_del)) {
+ System.err.println("in getNewStepSize, _del is NaN. That's rarely a good sign.");
+ return Math.max(AdaptiveSwimUtilities.MIN_STEPSIZE, h/2);
+ }
+
+ double newH = Math.min(h/2, _del / 5);
+ return Math.max(AdaptiveSwimUtilities.MIN_STEPSIZE, newH);
+ }
+
+ @Override
+ public AdaptiveSwimResult getResult() {
+ return _result;
+ }
+
+
}
diff --git a/common-tools/cnuphys/swimmer/src/main/java/cnuphys/adaptiveSwim/ASignChangeStopper.java b/common-tools/cnuphys/swimmer/src/main/java/cnuphys/adaptiveSwim/ASignChangeStopper.java
new file mode 100644
index 0000000000..e581dce6c3
--- /dev/null
+++ b/common-tools/cnuphys/swimmer/src/main/java/cnuphys/adaptiveSwim/ASignChangeStopper.java
@@ -0,0 +1,77 @@
+package cnuphys.adaptiveSwim;
+
+import cnuphys.adaptiveSwim.geometry.AGeometric;
+
+public abstract class ASignChangeStopper extends AAdaptiveStopper {
+
+ protected AGeometric _target;
+ protected int _startSign; //call start side "left" arbitrarily
+
+ protected AdaptiveSwimIntersection _intersection;
+
+
+ /**
+ * Sign change stopper (does check max path length)
+ * @param sfMax the maximum value of the path length in meters
+ * @param target the target geometric
+ * @param result holds the results, its u statevector should have been initialized
+ * to the starting vector
+ */
+ public ASignChangeStopper(final double sMax, AGeometric target, AdaptiveSwimResult result) {
+ super(sMax, 0, result);
+ _target = target;
+
+ _intersection = result.getIntersection();
+ }
+
+ /**
+ * For doing things like setting the initial sign and distance
+ */
+ @Override
+ public void initialize() {
+ _startSign = sign(_result.getS(), _result.getU());
+ }
+
+ @Override
+ public boolean stopIntegration(double snew, double[] unew) {
+
+
+ //if sign changed we have success
+ int newSign = sign(snew, unew);
+ if (newSign != _startSign) {
+ //point is on "right" and will be last point accepted
+
+ if (_intersection != null) {
+ _intersection.setRight(unew, snew);
+ }
+
+ accept(snew, unew);
+ _result.setStatus(AdaptiveSwimmer.SWIM_SUCCESS);
+ return true;
+ }
+
+ //stop and accept new data. We exceeded smax and didn't hit the target
+ if (snew > _sMax) {
+ _result.setStatus(AdaptiveSwimmer.SWIM_TARGET_MISSED);
+ return true;
+ }
+
+ //point is on "left"
+
+ if (_intersection != null) {
+ _intersection.setLeft(unew, snew);
+ }
+ accept(snew, unew);
+ return false;
+ }
+
+
+ /**
+ * Compute the sign based on the actual geometric object
+ * @param snew the new value of the pathlength
+ * @param unew the new state vector
+ * @return the "which side am I on" sign
+ */
+ public abstract int sign(double snew, double[] unew);
+
+}
diff --git a/common-tools/cnuphys/swimmer/src/main/java/cnuphys/adaptiveSwim/AdaptiveCylinderStopper.java b/common-tools/cnuphys/swimmer/src/main/java/cnuphys/adaptiveSwim/AdaptiveCylinderStopper.java
index 173875d7ce..59ee98ff13 100644
--- a/common-tools/cnuphys/swimmer/src/main/java/cnuphys/adaptiveSwim/AdaptiveCylinderStopper.java
+++ b/common-tools/cnuphys/swimmer/src/main/java/cnuphys/adaptiveSwim/AdaptiveCylinderStopper.java
@@ -1,99 +1,89 @@
package cnuphys.adaptiveSwim;
import cnuphys.adaptiveSwim.geometry.Cylinder;
-import cnuphys.swim.SwimTrajectory;
public class AdaptiveCylinderStopper extends AAdaptiveStopper {
-
+
//the target cylinder
private Cylinder _targetCylinder;
-
+
+ //the newest distance to the cylinder
+ private double _prevDist;
+
//the newest distance to the cylinder
- private double _distance;
-
- //cache whether we have passed smax
- private boolean _passedSmax;
-
- //cache whether we have crossed the boundary
- private boolean _crossedBoundary;
+ private double _newDist;
//the start sign of the distance
private double _startSign;
-
+
/**
* Cylinder stopper (does check max path length)
- * @param u0 initial state vector
- * @param sf the maximum value of the path length in meters
+ * @param sMax the maximum value of the path length in meters
* @param targetCylinder the target cylinder
* @param accuracy the accuracy in meters
- * @param trajectory optional swim trajectory (can be null)
+ * @param result holds the results, its u statevector should have been initialized
+ * to the starting vector
*/
- public AdaptiveCylinderStopper(final double[] u0, final double sf, Cylinder targetCylinder, double accuracy, SwimTrajectory trajectory) {
- super(u0, sf, accuracy, trajectory);
+ public AdaptiveCylinderStopper(double sMax, Cylinder targetCylinder, double accuracy, AdaptiveSwimResult result) {
+ super(sMax, accuracy, result);
_targetCylinder = targetCylinder;
- _distance = _targetCylinder.distance(u0[0], u0[1], u0[2]);
- _startSign = Math.signum(_distance);
}
-
+
+
+ /**
+ * For doing things like setting the initial sign and distance
+ */
+ @Override
+ public void initialize() {
+ double u[] = _result.getU();
+ _prevDist = _targetCylinder.signedDistance(u[0], u[1], u[2]);
+ _newDist = _prevDist;
+
+ _startSign = sign();
+ }
+
@Override
public boolean stopIntegration(double snew, double[] unew) {
-
//a negative distance means we are inside the cylinder
- double newDist = _targetCylinder.distance(unew[0], unew[1], unew[2]);
- double newSign = Math.signum(newDist);
- newDist = Math.abs(newDist);
+ _newDist = _targetCylinder.signedDistance(unew[0], unew[1], unew[2]);
- // within accuracy?
- if (newDist < _accuracy) {
- _distance = newDist;
+ // within accuracy? Accept and stop
+ if (Math.abs(_newDist) < _accuracy) {
accept(snew, unew);
+ _result.setStatus(AdaptiveSwimmer.SWIM_SUCCESS);
return true;
}
-
- //if we crossed the boundary (don't accept, reset)
- _crossedBoundary = newSign != _startSign;
- if (_crossedBoundary) {
+
+ //stop but don't accept new data. We crossed the target boundary
+ if (sign() != _startSign) {
+ _result.setStatus(AdaptiveSwimmer.SWIM_CROSSED_BOUNDARY);
+
+ //use prev distance to calculate next step
+ _del = Math.abs(_prevDist);
return true;
}
- _passedSmax = (snew > _sf);
- //if exceeded max path length accept and stop
- if (_passedSmax) {
- _distance = newDist;
+
+ //stop and accept new data. We exceeded smax and didn't hit the target
+ if (snew > _sMax) {
accept(snew, unew);
+ _result.setStatus(AdaptiveSwimmer.SWIM_TARGET_MISSED);
return true;
}
//accept new data and continue
- _distance = newDist;
accept(snew, unew);
+ _prevDist = _newDist;
return false;
}
- /**
- * Get the current value of the distance (positive definite)
- * @return the current value of distance
- */
- public double getDistance() {
- return _distance;
- }
- /**
- * Did we cross the boundary?
- * @return true if we crossed the boundary
- */
- public boolean crossedBoundary() {
- return _crossedBoundary;
- }
- /**
- * Did we pas the max path length?
- * @return true if we crossed the boundary
- */
- public boolean passedSmax() {
- return _passedSmax;
+ //get the sign based on the current signed distance
+ private int sign() {
+ return (_newDist < 0) ? -1 : 1;
}
diff --git a/common-tools/cnuphys/swimmer/src/main/java/cnuphys/adaptiveSwim/AdaptiveDefaultStopper.java b/common-tools/cnuphys/swimmer/src/main/java/cnuphys/adaptiveSwim/AdaptiveDefaultStopper.java
index 9780676833..508dfccecb 100644
--- a/common-tools/cnuphys/swimmer/src/main/java/cnuphys/adaptiveSwim/AdaptiveDefaultStopper.java
+++ b/common-tools/cnuphys/swimmer/src/main/java/cnuphys/adaptiveSwim/AdaptiveDefaultStopper.java
@@ -1,32 +1,47 @@
package cnuphys.adaptiveSwim;
-import cnuphys.swim.SwimTrajectory;
public class AdaptiveDefaultStopper extends AAdaptiveStopper {
- private static final double TOL = 1.0e-5; //meters
-
- private double _sCutoff;
-
/**
- * Rho stopper (does check max path length)
- * @param u0 initial state vector
- * @param sf final path length meters
- * @param trajectory optional trajectory
+ * Default stopper simply checks pathlength. If the max pathlength is exceeded
+ * we stop.
+ * @param sMax max path length meters
+ * @param result holds the results, its u statevector should have been initialized
+ * to the starting vector
*/
- public AdaptiveDefaultStopper(final double[] u0, final double sf, SwimTrajectory trajectory) {
- super(u0, sf, Double.NaN, trajectory);
- _sCutoff = sf - TOL;
+ public AdaptiveDefaultStopper(final double sMax, AdaptiveSwimResult result) {
+ super(sMax, Double.NaN, result);
}
-
+ /**
+ * For doing things like setting the initial sign and distance
+ */
+ @Override
+ public void initialize() {
+ //do nothing
+ }
+
+
@Override
public boolean stopIntegration(double snew, double[] unew) {
-
+ //the point that exceeds _sMax will also be accepted
accept(snew, unew);
-
- // within tolerance?
- return (snew > _sCutoff);
+
+ if (snew > _sMax) {
+ _result.setStatus(AdaptiveSwimmer.SWIM_SUCCESS);
+ return true;
+ }
+
+ return false;
+ }
+
+
+ @Override
+ public double getNewStepSize(double h) {
+ // should not be called
+ System.err.println("getNewStepSize should not have been called for the defaultStopper.");
+ return 0;
}
-
+
}
\ No newline at end of file
diff --git a/common-tools/cnuphys/swimmer/src/main/java/cnuphys/adaptiveSwim/AdaptiveLineStopper.java b/common-tools/cnuphys/swimmer/src/main/java/cnuphys/adaptiveSwim/AdaptiveLineStopper.java
deleted file mode 100644
index 79f7c9309c..0000000000
--- a/common-tools/cnuphys/swimmer/src/main/java/cnuphys/adaptiveSwim/AdaptiveLineStopper.java
+++ /dev/null
@@ -1,73 +0,0 @@
-package cnuphys.adaptiveSwim;
-
-
-import cnuphys.adaptiveSwim.geometry.Line;
-import cnuphys.swim.SwimTrajectory;
-
-public class AdaptiveLineStopper extends AAdaptiveStopper {
-
- //the target cylinder
- private Line _targetLine;
-
- //the newest distance to the cylinder
- private double _newDist;
-
-
- /**
- * Line stopper (does check max path length)
- * @param u0 initial state vector
- * @param sf the maximum value of the path length in meters
- * @param targetLine the target line
- * @param accuracy the accuracy in meters
- * @param trajectory optional swim trajectory (can be null)
- */
- public AdaptiveLineStopper(final double[] u0, final double sf, Line targetLine, double accuracy, SwimTrajectory trajectory) {
- super(u0, sf, accuracy, trajectory);
- _targetLine = targetLine;
- }
-
-
- @Override
- public boolean stopIntegration(double snew, double[] unew) {
-
- //a negative distance means we are inside the cylinder
- //we don't care so take abs val
- _newDist = _targetLine.distance(unew[0], unew[1], unew[2]);
-
- // within accuracy?
- //note this could also result with s > smax
- if (_newDist < _accuracy) {
- accept(snew, unew);
- return true;
- }
-
- //stop and don't accept new data. We exceeded smax
- if (snew > _sf) {
- return true;
- }
-
- //accept new data and continue
- accept(snew, unew);
- return false;
- }
-
-
- /**
- * Accept a new integration step
- * @param snew the new value of s in meters
- * @param unew the new state vector
- */
- @Override
- protected void accept(double snew, double[] unew) {
- super.accept(snew, unew);
-
- //do not take a step that might leap us over the cylinder
- //this is necessary because there is no crossover "side" for a cylinder
- //like for a plane or fixed z,rho
-
- double newMaxStep = Math.min(_THEMAXSTEP, Math.max(AdaptiveSwimUtilities.MIN_STEPSIZE, _newDist/5));
-
- setMaxStep(newMaxStep);
- }
-
-}
\ No newline at end of file
diff --git a/common-tools/cnuphys/swimmer/src/main/java/cnuphys/adaptiveSwim/AdaptivePlaneStopper.java b/common-tools/cnuphys/swimmer/src/main/java/cnuphys/adaptiveSwim/AdaptivePlaneStopper.java
index 38b3d31fd5..7cc98a70a4 100644
--- a/common-tools/cnuphys/swimmer/src/main/java/cnuphys/adaptiveSwim/AdaptivePlaneStopper.java
+++ b/common-tools/cnuphys/swimmer/src/main/java/cnuphys/adaptiveSwim/AdaptivePlaneStopper.java
@@ -1,7 +1,6 @@
package cnuphys.adaptiveSwim;
import cnuphys.adaptiveSwim.geometry.Plane;
-import cnuphys.swim.SwimTrajectory;
/**
* Stopper for swimming to a plane
@@ -11,62 +10,89 @@
public class AdaptivePlaneStopper extends AAdaptiveStopper {
//the plane you want to swim to
- private Plane _targetPlane;
+ protected Plane _targetPlane;
+
+ //previous distance to the plane
+ protected double _prevDist;
+
+ //the newest distance to the plane
+ protected double _newDist;
//is the starting rho bigger or smaller than the target
- private int _startSign;
-
+ protected int _startSign;
+
/**
- * Rho stopper (does check max path length)
- * @param u0 initial state vector
- * @param sf the maximum value of the path length in meters
+ * Plane stopper (does check max path length)
+ * @param sMax the maximum value of the path length in meters
* @param targetPlane the target plane
* @param accuracy the accuracy in meters
- * @param trajectory optional swim trajectory (can be null)
+ * @param result holds the results, its u statevector should have been initialized
+ * to the starting vector
*/
- public AdaptivePlaneStopper(final double[] u0, final double sf, Plane targetPlane, double accuracy, SwimTrajectory trajectory) {
- super(u0, sf, accuracy, trajectory);
+ public AdaptivePlaneStopper(double sMax, Plane targetPlane, double accuracy, AdaptiveSwimResult result) {
+ super(sMax, accuracy, result);
_targetPlane = targetPlane;
- _startSign = sign(signedDistance(u0));
}
+ /**
+ * For doing things like setting the initial sign and distance
+ */
+ @Override
+ public void initialize() {
+ _prevDist = signedDistance(_result.getU());
+ _newDist = _prevDist;
+ _startSign = sign();
+ }
+
+
/**
* Get the signed distance from a state vector to a point on the target plane
* @param u the state vector
* @return the signed distance from a state vector to a point on the target plane in meters
*/
- private double signedDistance(double u[]) {
+ protected double signedDistance(double u[]) {
return _targetPlane.signedDistance(u[0], u[1], u[2]);
}
-
+
@Override
public boolean stopIntegration(double snew, double[] unew) {
-
- double newSignedDist = signedDistance(unew);
- // within accuracy?
- //note this could also result with s > smax
- if (Math.abs(newSignedDist) < _accuracy) {
+ _newDist = signedDistance(unew);
+
+ //stop but don't accept new data. We crossed the target boundary
+ if (sign() != _startSign) {
+ _result.setStatus(AdaptiveSwimmer.SWIM_CROSSED_BOUNDARY);
+ _del = Math.abs(_prevDist)/2;
+ return true;
+ }
+
+
+ // within accuracy? Accept and stop
+ if (Math.abs(_newDist) < _accuracy) {
accept(snew, unew);
+ _result.setStatus(AdaptiveSwimmer.SWIM_SUCCESS);
return true;
}
- //stop and don't accept new data. We crossed the boundary or exceeded smax
- if ((snew > _sf) || (sign(newSignedDist) != _startSign)) {
+ //stop and accept new data. We exceeded smax and didn't hit the target
+ if (snew > _sMax) {
+ accept(snew, unew);
+ _result.setStatus(AdaptiveSwimmer.SWIM_TARGET_MISSED);
return true;
}
-
+
//accept new data and continue
accept(snew, unew);
+ _prevDist = _newDist;
return false;
}
-
-
- //get the sign based on the signed distance
- private int sign(double dist) {
- return ((dist < 0) ? -1 : 1);
+
+
+ //get the sign based on the current signed distance
+ protected int sign() {
+ return (_newDist < 0) ? -1 : 1;
}
-
+
}
\ No newline at end of file
diff --git a/common-tools/cnuphys/swimmer/src/main/java/cnuphys/adaptiveSwim/AdaptiveRhoStopper.java b/common-tools/cnuphys/swimmer/src/main/java/cnuphys/adaptiveSwim/AdaptiveRhoStopper.java
index cf1363f60a..941839f5f0 100644
--- a/common-tools/cnuphys/swimmer/src/main/java/cnuphys/adaptiveSwim/AdaptiveRhoStopper.java
+++ b/common-tools/cnuphys/swimmer/src/main/java/cnuphys/adaptiveSwim/AdaptiveRhoStopper.java
@@ -1,8 +1,5 @@
package cnuphys.adaptiveSwim;
-import cnuphys.magfield.FastMath;
-import cnuphys.swim.SwimTrajectory;
-
/**
* Stopper for swimming to a fixed cylindrical cs radius (rho) value
* @author heddle
@@ -16,94 +13,77 @@ public class AdaptiveRhoStopper extends AAdaptiveStopper {
//is the starting rho bigger or smaller than the target
private int _startSign;
-
- //the current rho
- private double _rho;
-
- //cache whether we have crossed the boundary
- private boolean _crossedBoundary;
-
- //cache whether we have passed smax
- private boolean _passedSmax;
+ //new value
+ private double _newRho;
+ private double _prevRho;
/**
* Rho stopper (does check max path length)
- * @param u0 initial state vector
- * @param sf the maximum value of the path length in meters
+ * @param sMax the maximum value of the path length in meters
* @param targetRho stopping rho in meters
* @param accuracy the accuracy in meters
- * @param trajectory optional swim trajectory (can be null)
+ * @param result holds the results, its u statevector should have been initialized
+ * to the starting vector
*/
- public AdaptiveRhoStopper(final double[] u0, final double sf, final double targetRho, double accuracy, SwimTrajectory trajectory) {
- super(u0, sf, accuracy, trajectory);
+ public AdaptiveRhoStopper(final double sMax, final double targetRho, double accuracy, AdaptiveSwimResult result) {
+ super(sMax, accuracy, result);
_targetRho = targetRho;
- _rho = FastMath.hypot(u0[0], u0[1]);
- _startSign = sign(_rho);
}
-
+
+ /**
+ * For doing things like setting the initial sign and distance
+ */
+ @Override
+ public void initialize() {
+ _prevRho = getRho(_result.getU());
+ _newRho = _prevRho;
+ _startSign = sign();
+ }
+
+ //just get the rho coordinate
+ private double getRho(double u[]) {
+ return Math.hypot(u[0], u[1]);
+ }
+
@Override
public boolean stopIntegration(double snew, double[] unew) {
-
- double newRho = Math.hypot(unew[0], unew[1]);
+
+ _newRho = getRho(unew);
// within accuracy?
- if (Math.abs(newRho - _targetRho) < _accuracy) {
- _rho = newRho;
+ if (Math.abs(_newRho - _targetRho) < _accuracy) {
accept(snew, unew);
+ _result.setStatus(AdaptiveSwimmer.SWIM_SUCCESS);
return true;
}
-
- //if we crossed the boundary (don't accept, reset)
- _crossedBoundary = sign(newRho) != _startSign;
- if (_crossedBoundary) {
+
+ //top but don't accept new data. We crossed the target boundary
+ if (sign() != _startSign) {
+ _result.setStatus(AdaptiveSwimmer.SWIM_CROSSED_BOUNDARY);
+
+ //use the previous rho to calculate new stepsize
+ _del = Math.abs(_prevRho - _targetRho);
return true;
}
-
- _passedSmax = (snew > _sf);
- //if exceeded max path length accept and stop
- if (_passedSmax) {
- _rho = newRho;
+
+ //stop and accept new data. We exceeded smax and didn't hit the target
+ if (snew > _sMax) {
accept(snew, unew);
+ _result.setStatus(AdaptiveSwimmer.SWIM_TARGET_MISSED);
return true;
}
-
- //accept new data and continue
- _rho = newRho;
+
+ //not there yet-- accept new data and continue
accept(snew, unew);
+ _prevRho = _newRho;
return false;
}
-
- /**
- * Get the current value of rho
- * @return the current value of rho
- */
- public double getRho() {
- return _rho;
- }
-
-
+
//get the sign based on the current rho
- private int sign(double currentRho) {
- return ((currentRho < _targetRho) ? -1 : 1);
- }
-
- /**
- * Did we cross the boundary?
- * @return true if we crossed the boundary
- */
- public boolean crossedBoundary() {
- return _crossedBoundary;
- }
-
- /**
- * Did we pas the max path length?
- * @return true if we crossed the boundary
- */
- public boolean passedSmax() {
- return _passedSmax;
+ private int sign() {
+ return ((_newRho < _targetRho) ? -1 : 1);
}
-
}
\ No newline at end of file
diff --git a/common-tools/cnuphys/swimmer/src/main/java/cnuphys/adaptiveSwim/AdaptiveSStopper.java b/common-tools/cnuphys/swimmer/src/main/java/cnuphys/adaptiveSwim/AdaptiveSStopper.java
deleted file mode 100644
index 3f9740dd82..0000000000
--- a/common-tools/cnuphys/swimmer/src/main/java/cnuphys/adaptiveSwim/AdaptiveSStopper.java
+++ /dev/null
@@ -1,48 +0,0 @@
-package cnuphys.adaptiveSwim;
-
-import cnuphys.swim.SwimTrajectory;
-
-/**
- * For when we want to swim a precise path length
- * @author heddle
- *
- */
-public class AdaptiveSStopper extends AAdaptiveStopper {
-
- //the desired accuracy
- private double _accuracy;
-
- /**
- * Pathlength stopper
- * @param u0 initial state vector
- * @param sf final path length meters
- * @param accuracy the accuracy
- * @param trajectory optional trajectory
- */
- public AdaptiveSStopper(final double[] u0, final double sf, double accuracy, SwimTrajectory trajectory) {
- super(u0, sf, Double.NaN, trajectory);
- _accuracy = accuracy;
- }
-
-
- @Override
- public boolean stopIntegration(double snew, double[] unew) {
-
-
- // within accuracy? Accept and stop
- if (Math.abs(snew - _s) < _accuracy) {
- accept(snew, unew);
- return true;
- }
-
- //stop and don't accept new data. We crossed the boundary
- if (snew > _sf) {
- return true;
- }
-
- //accept new data and continue
- accept(snew, unew);
- return false;
- }
-
-}
diff --git a/common-tools/cnuphys/swimmer/src/main/java/cnuphys/adaptiveSwim/AdaptiveSphereStopper.java b/common-tools/cnuphys/swimmer/src/main/java/cnuphys/adaptiveSwim/AdaptiveSphereStopper.java
index b165f203a2..59372e9057 100644
--- a/common-tools/cnuphys/swimmer/src/main/java/cnuphys/adaptiveSwim/AdaptiveSphereStopper.java
+++ b/common-tools/cnuphys/swimmer/src/main/java/cnuphys/adaptiveSwim/AdaptiveSphereStopper.java
@@ -1,74 +1,118 @@
package cnuphys.adaptiveSwim;
+
import cnuphys.adaptiveSwim.geometry.Sphere;
-import cnuphys.swim.SwimTrajectory;
public class AdaptiveSphereStopper extends AAdaptiveStopper {
-
- //the target cylinder
+
private Sphere _targetSphere;
-
- //the newest distance to the cylinder
+
+ //the newest distance to the sphere
+ private double _prevDist;
+
+ //the newest distance to the sphere
private double _newDist;
-
-
+
+ //the start sign of the distance
+ private double _startSign;
+
/**
- * Cylinder stopper (does check max path length)
- * @param u0 initial state vector
- * @param sf the maximum value of the path length in meters
- * @param targetSphere the target sphere
+ * Sphere stopper (does check max path length)
+ * @param sMax the maximum value of the path length in meters
+ * @param targetSphere the target cylinder
* @param accuracy the accuracy in meters
- * @param trajectory optional swim trajectory (can be null)
+ * @param result holds the results, its u statevector should have been initialized
+ * to the starting vector
*/
- public AdaptiveSphereStopper(final double[] u0, final double sf, Sphere targetSphere, double accuracy, SwimTrajectory trajectory) {
- super(u0, sf, accuracy, trajectory);
+ public AdaptiveSphereStopper(double sMax, Sphere targetSphere, double accuracy, AdaptiveSwimResult result) {
+ super(sMax, accuracy, result);
_targetSphere = targetSphere;
-
}
-
+
+ /**
+ * Sphere stopper (does check max path length)
+ * This assumes a sphere centered on the origin
+ * @param sMax the maximum value of the path length in meters
+ * @param targetSphere the target cylinder
+ * @param accuracy the accuracy in meters
+ * @param result holds the results, its u statevector should have been initialized
+ * to the starting vector
+ */
+ public AdaptiveSphereStopper(double sMax, double radius, double accuracy, AdaptiveSwimResult result) {
+ this(sMax, new Sphere(radius), accuracy, result);
+ }
+
+ /**
+ * For doing things like setting the initial sign and distance
+ */
+ @Override
+ public void initialize() {
+ double u[] = _result.getU();
+ _prevDist = _targetSphere.signedDistance(u[0], u[1], u[2]);
+ _newDist = _prevDist;
+
+ _startSign = sign();
+ }
+
@Override
public boolean stopIntegration(double snew, double[] unew) {
-
//a negative distance means we are inside the cylinder
- //we don't care so take abs val
- _newDist = Math.abs(_targetSphere.distance(unew[0], unew[1], unew[2]));
+ _newDist = _targetSphere.signedDistance(unew[0], unew[1], unew[2]);
- // within accuracy?
- //note this could also result with s > smax
- if (_newDist < _accuracy) {
+ // within accuracy? Accept and stop
+ if (Math.abs(_newDist) < _accuracy) {
accept(snew, unew);
+ _result.setStatus(AdaptiveSwimmer.SWIM_SUCCESS);
return true;
}
- //stop and don't accept new data. We exceeded smax
- if (snew > _sf) {
+ //stop but don't accept new data. We crossed the target boundary
+ if (sign() != _startSign) {
+ _result.setStatus(AdaptiveSwimmer.SWIM_CROSSED_BOUNDARY);
+
+ //use prev distance to calculate next step
+ _del = Math.abs(_prevDist);
return true;
}
-
+
+
+ //stop and accept new data. We exceeded smax and didn't hit the target
+ if (snew > _sMax) {
+ accept(snew, unew);
+ _result.setStatus(AdaptiveSwimmer.SWIM_TARGET_MISSED);
+ return true;
+ }
+
+ //see if we jumped over the sphere but intersect it
+ //only relevant if we started outside
+ //if so, treat as sign change
+ if (_startSign > 0) {
+ if (_targetSphere.segmentIntersects(unew[0], unew[1], unew[2], _result.getU()[0],
+ _result.getU()[1], _result.getU()[2])) {
+
+ System.out.println("JUMPED OVER SPHERE");
+ _result.setStatus(AdaptiveSwimmer.SWIM_CROSSED_BOUNDARY);
+
+ //use prev distance to calculate next step
+ _del = Math.abs(_prevDist);
+ return true;
+ }
+ }
//accept new data and continue
accept(snew, unew);
+ _prevDist = _newDist;
return false;
}
- /**
- * Accept a new integration step
- * @param snew the new value of s in meters
- * @param unew the new state vector
- */
- @Override
- protected void accept(double snew, double[] unew) {
- super.accept(snew, unew);
-
- //do not take a step that might leap us over the sphere
- //this is necessary because there is no crossover "side" for a cylinder
- //like for a plane or fixed z,rho
-
- double newMaxStep = Math.min(_THEMAXSTEP, Math.max(AdaptiveSwimUtilities.MIN_STEPSIZE, _newDist/5));
-
- setMaxStep(newMaxStep);
+
+ //get the sign based on the current signed distance
+ private int sign() {
+ return (_newDist < 0) ? -1 : 1;
}
-}
+
+
+}
\ No newline at end of file
diff --git a/common-tools/cnuphys/swimmer/src/main/java/cnuphys/adaptiveSwim/AdaptiveStepResult.java b/common-tools/cnuphys/swimmer/src/main/java/cnuphys/adaptiveSwim/AdaptiveStepResult.java
index 0a6af072b2..be01dfd66e 100644
--- a/common-tools/cnuphys/swimmer/src/main/java/cnuphys/adaptiveSwim/AdaptiveStepResult.java
+++ b/common-tools/cnuphys/swimmer/src/main/java/cnuphys/adaptiveSwim/AdaptiveStepResult.java
@@ -5,21 +5,38 @@ public class AdaptiveStepResult {
//new stepsize
private double _hNew;
- //new value of independent variable
+ //new value of independent variable,
+ //might be pathlength or z
private double _sNew;
+ /**
+ * Get the new stepsize
+ * @return the new stepsize
+ */
public double getHNew() {
return _hNew;
}
+ /**
+ * Set the new stepsize
+ * @param hNew the new stepsize
+ */
public void setHNew(double hNew) {
_hNew = hNew;
}
+ /**
+ * Get the new pathlength
+ * @return the new pathlength
+ */
public double getSNew() {
return _sNew;
}
+ /**
+ * et the new pathlength
+ * @param sNew the new pathlength
+ */
public void setSNew(double sNew) {
_sNew = sNew;
}
diff --git a/common-tools/cnuphys/swimmer/src/main/java/cnuphys/adaptiveSwim/AdaptiveSwimIntersection.java b/common-tools/cnuphys/swimmer/src/main/java/cnuphys/adaptiveSwim/AdaptiveSwimIntersection.java
new file mode 100644
index 0000000000..368e23fbb8
--- /dev/null
+++ b/common-tools/cnuphys/swimmer/src/main/java/cnuphys/adaptiveSwim/AdaptiveSwimIntersection.java
@@ -0,0 +1,169 @@
+package cnuphys.adaptiveSwim;
+
+import cnuphys.adaptiveSwim.geometry.AGeometric;
+import cnuphys.adaptiveSwim.geometry.Point;
+
+/**
+ * This is used to hold information about the intersection with a
+ * boundary, for example the intersection of the plane in a swim-to-plane
+ * method
+ * @author heddle
+ *
+ */
+public class AdaptiveSwimIntersection {
+
+ //closest we get on the "left"
+ //the original side is always called "left"
+ private Point _left = new Point();
+ private double _sLeft;
+
+ private double _txLeft;
+ private double _tyLeft;
+ private double _tzLeft;
+
+ //closest we get on the "right"
+ private Point _right = new Point();
+ private double _sRight;
+
+ private double _txRight;
+ private double _tyRight;
+ private double _tzRight;
+
+
+
+ //The estimate of the xyz intersection
+ private Point _intersection = new Point();
+
+ //interpolated s and t's
+ private double _s;
+ private double _tx;
+ private double _ty;
+ private double _tz;
+
+ //distance from intersection point to object (should be very small)
+ private double _distance = Double.NaN;
+
+
+ public AdaptiveSwimIntersection() {
+ }
+
+
+ /**
+ * Set the next left (staring side) point
+ * @param u the state vector
+ * @param s the path length
+ */
+ public void setLeft(double u[], double s) {
+ _left.set(u[0], u[1], u[2]);
+ _sLeft = s;
+ _txLeft = u[3];
+ _tyLeft = u[4];
+ _tzLeft = u[5];
+ }
+
+ /**
+ * See what should be the only "far side" point
+ * @param u the state vector
+ * @param s the path length
+ */
+ public void setRight(double u[], double s) {
+ _right.set(u[0], u[1], u[2]);
+ _sRight = s;
+ _txRight = u[3];
+ _tyRight = u[4];
+ _tzRight = u[5];
+ }
+
+ /**
+ * Reset the parameters so the object can be reused in another swim.
+ */
+ public void reset() {
+ _left.set(Double.NaN, Double.NaN, Double.NaN);
+ _right.set(Double.NaN, Double.NaN, Double.NaN);
+ _intersection.set(Double.NaN, Double.NaN, Double.NaN);
+ _distance = Double.NaN;
+
+ }
+
+ /**
+ * Get the point on the "left" side of the intersection
+ * @return the point on the "left" side of the intersection
+ */
+ public Point getLeft() {
+ return _left;
+ }
+
+ /**
+ * Get the point on the "right" side of the intersection
+ * @return the point on the "right" side of the intersection
+ */
+ public Point getRight() {
+ return _right;
+ }
+
+
+ /**
+ * Compute and store the interpolation ad distance from the object.
+ * Note that if the intersection is successful, the distance should be zero!
+ * @param geom the object (e.g., plane) that is being intersected.
+ */
+ public void computeIntersection(AGeometric geom) {
+ double t = geom.interpolate(_left, _right, _intersection);
+ _s = _sLeft + t * (_sRight - _sLeft);
+ _tx = _txLeft + t * (_txRight - _txLeft);
+ _ty = _tyLeft + t * (_tyRight - _tyLeft);
+ _tz = _tzLeft + t * (_tzRight - _tzLeft);
+
+ _distance = geom.distance(_intersection);
+ }
+
+ /**
+ * Get the intersection distance. Note that if the intersection
+ * is successful, the distance should be zero! This assumes
+ * a call to computeIntersection has been made at the end
+ * of a swim.
+ * @return the intersection distance
+ */
+ public double getIntersectDistance() {
+ return _distance;
+ }
+
+ /**
+ * Get the intersection distance. This assumes
+ * a call to computeIntersection has been made at the end
+ * of a swim.
+ * @return the intersection point
+ */
+ public Point getIntersectionPoint() {
+ return _intersection;
+ }
+
+ /**
+ * Set a u based on interpolated values
+ * @param u the state vector to fill
+ */
+ public void setU(double u[]) {
+ u[0] = _intersection.x;
+ u[1] = _intersection.y;
+ u[2] = _intersection.z;
+ u[3] = _tx;
+ u[4] = _ty;
+ u[5] = _tz;
+ }
+
+ /**
+ * Get the interpolated pathlength
+ * @return the pathlength
+ */
+ public double getS() {
+ return _s;
+ }
+
+ @Override
+ public String toString() {
+ String istr = _intersection.toString();
+ return String.format(" int: %s D: %-6.2e",
+ istr, _distance);
+ }
+
+}
diff --git a/common-tools/cnuphys/swimmer/src/main/java/cnuphys/adaptiveSwim/AdaptiveSwimResult.java b/common-tools/cnuphys/swimmer/src/main/java/cnuphys/adaptiveSwim/AdaptiveSwimResult.java
index 7cb72f000a..ccd85e3a30 100644
--- a/common-tools/cnuphys/swimmer/src/main/java/cnuphys/adaptiveSwim/AdaptiveSwimResult.java
+++ b/common-tools/cnuphys/swimmer/src/main/java/cnuphys/adaptiveSwim/AdaptiveSwimResult.java
@@ -2,51 +2,119 @@
import java.io.PrintStream;
-import cnuphys.adaptiveSwim.test.InitialValues;
+import cnuphys.adaptiveSwim.geometry.AGeometric;
+import cnuphys.adaptiveSwim.geometry.Point;
import cnuphys.magfield.FastMath;
import cnuphys.swim.SwimTrajectory;
public class AdaptiveSwimResult {
-
- //the final state vector
- private double[] _uf;
-
+
+ //the current state vector
+ private final double[] _u;
+
//the number of integration steps
private int _nStep;
-
- //the final path length
- private double _finalS;
-
- //a status, one of the class constants
+
+ //the current path length
+ private double _s;
+
+ //a status, one of the AdaptiveSwimmer class constants
private int _status;
-
+
//optionally holds a trajectory of [x, y, z, tx, ty, tz] (coords in meters)
private SwimTrajectory _trajectory;
-
- //the initial values
+
+ //the initial values in the usual variables
+ //x, y, z, p, theta, phi
private InitialValues _initialValues;
-
+
+ //some stoppers (e.g. plane) will use this when they interpolate to an intersection
+ private AdaptiveSwimIntersection _intersection;
+
+ //whether a trajectory is created
+ private boolean _saveTrajectory;
+
+ //this can be used to pause updating the trajectory
+ private boolean _updateTrajectory;
+
+
/**
* Create a container for the swim results for default of 6D state vector
* @param saveTrajectory if true, we will save the trajectory
*/
public AdaptiveSwimResult(boolean saveTrajectory) {
- this(6, saveTrajectory);
+ _u = new double[AdaptiveSwimmer.DIM];
+ _saveTrajectory = saveTrajectory;
+ reset();
}
/**
- * Create a container for the swim results
- * @param dim the dimension of the system (probably 6)
- * @param saveTrajectory if true, we will save the trajectory
+ * Reset so that the object can be reused.
*/
- public AdaptiveSwimResult(int dim, boolean saveTrajectory) {
- _uf = new double[dim];
-
- if (saveTrajectory) {
+ public void reset() {
+
+ for (int i = 0; i < AdaptiveSwimmer.DIM; i++) {
+ _u[i] = Double.NaN;
+ }
+
+ if (_saveTrajectory) {
_trajectory = new SwimTrajectory();
+ _updateTrajectory = true;
}
+ else {
+ _trajectory = null;
+ _updateTrajectory = false;
+ }
+
+ _nStep = 0;
+ _s = 0;
+ _status = AdaptiveSwimmer.SWIM_SWIMMING;
+
+ if (_initialValues != null) {
+ _initialValues.charge = 0;
+ _initialValues.xo = Double.NaN;
+ _initialValues.yo = Double.NaN;
+ _initialValues.zo = Double.NaN;
+ _initialValues.p = Double.NaN;
+ _initialValues.theta = Double.NaN;
+ _initialValues.phi = Double.NaN;
+ }
+
+ if (_intersection != null) {
+ _intersection.reset();
+ }
+
+ }
+
+ /**
+ * Checks whether a trajectory should be updated
+ * (by a stopper). Two things must be true, the _updateTrajectory
+ * should be true (updating not pause) and we actually have a trajectory
+ * object.
+ * @return true if the trajectory should be updated by a stopper
+ */
+ public boolean shouldUpdateTrajectory() {
+ return _updateTrajectory && (_trajectory != null);
}
-
+
+
+ /**
+ * Get the flag which tells us that updating is "on".
+ * @return true if updating is active
+ */
+ public boolean getUpdateTrajectory() {
+ return _updateTrajectory;
+ }
+
+ /**
+ * Set whether updating is active. This can be used
+ * to pause updating.
+ * @param update the new value of the flag.
+ */
+ public void setUpdateTrajectory(boolean update) {
+ _updateTrajectory = update;
+ }
+
/**
* Does this result hold a trajectory?
* @return true if there is a trajectory
@@ -54,7 +122,7 @@ public AdaptiveSwimResult(int dim, boolean saveTrajectory) {
public boolean hasTrajectory() {
return _trajectory != null;
}
-
+
/**
* Get the trajectory
* @return the trajectory (might be null
@@ -62,18 +130,31 @@ public boolean hasTrajectory() {
public SwimTrajectory getTrajectory() {
return _trajectory;
}
-
+
+ /**
+ * Get the current state vector,[x, y, x, px/p, py/p, pz/p]
+ * where x, y, z are in meters.
+ * To get the augmented, assume the trajectory was created, use
+ * getLastTrajectoryPoint.
+ * @return the current state vector, always with six elements.
+ */
+ public double[] getU() {
+ return _u;
+ }
+
/**
- * Get the final state vector, usually [x, y, x, px/p, py/p, pz/p]
- * where x, y, z are in meters. This final vector is never augmented.
+ * Get the current state (i.e., last) vector,[x, y, x, px/p, py/p, pz/p]
+ * where x, y, z are in meters.
* To get the augmented, assume the trajectory was created, use
* getLastTrajectoryPoint.
- * @return the final state vector, always with six elements.
+ * @deprecated Use {@link AdaptiveSwimResult#getU} instead.
+ * @return the current state vector, always with six elements.
*/
+ @Deprecated
public double[] getUf() {
- return _uf;
+ return _u;
}
-
+
/**
* Gets the last trajectory point if the trajectory was saved.
* This should be augmented with pathlength and bdl in indices 6 and 7.
@@ -82,7 +163,7 @@ public double[] getUf() {
*/
public double[] getLastTrajectoryPoint() {
if (_trajectory == null) {
- return getUf();
+ return getU();
}
else {
//augmented
@@ -91,15 +172,16 @@ public double[] getLastTrajectoryPoint() {
}
/**
- * Set the final state vector, usually [x, y, x, px/p, py/p, pz/p]
+ * Set the current state vector, usually [x, y, x, px/p, py/p, pz/p]
* where x, y, z are in meters
- * @param uf the final state vector
+ * @param u the new current state vector
*/
- public void setUf(double[] uf) {
- _uf = uf;
+ public void setU(double[] u) {
+ for (int i = 0; i < AdaptiveSwimmer.DIM; i++) {
+ _u[i] = u[i];
+ }
}
-
/**
* Get the number of steps of the swim
* @return the number of steps
@@ -119,20 +201,39 @@ public void setNStep(int nStep) {
/**
- * Get the final path length of the swim
- * @return the final path length in meters
+ * Get the path length of the swim
+ * @return the path length in meters
*/
- public double getFinalS() {
- return _finalS;
+ public double getS() {
+ return _s;
}
+ /**
+ * Get the path length of the swim
+ * @deprecated Use {@link AdaptiveSwimResult#getS} instead.
+ * @return the path length in meters
+ */
+ @Deprecated
+ public double getFinalS() {
+ return _s;
+ }
/**
- * Set the final path length of the swim
- * @param finalS the final path length in meters
+ * Set the path length of the swim
+ * @param s the path length in meters
*/
- public void setFinalS(double finalS) {
- _finalS = finalS;
+ public void setS(double s) {
+ _s = s;
+ }
+
+ /**
+ * Set the path length of the swim
+ * @deprecated Use {@link AdaptiveSwimResult#setS} instead.
+ * @param s the path length in meters
+ */
+ @Deprecated
+ public void setFinalS(double s) {
+ _s = s;
}
/**
@@ -142,7 +243,7 @@ public void setFinalS(double finalS) {
public void setStatus(int status) {
_status = status;
}
-
+
/**
* Get the status of the swim
* @return the status
@@ -150,7 +251,15 @@ public void setStatus(int status) {
public int getStatus() {
return _status;
}
-
+
+ /**
+ * Get the final value of rho
+ * @return the final value of rho
+ */
+ public double getFinalRho() {
+ return Math.hypot(_u[0], _u[1]);
+ }
+
/**
* Set the initial values
* @param q The integer charge
@@ -173,56 +282,26 @@ public void setInitialValues(int q, double xo, double yo, double zo, double p, d
_initialValues.theta = theta;
_initialValues.phi = phi;
}
-
-
-
+
+
+
/**
* A string containing the initial valies
* @return
*/
public String initialValuesString() {
InitialValues v = _initialValues;
-
+
if (v == null) {
return "";
}
-
+
String s = String.format("charge = %d\nvertex = [%-10.7f, %-10.7f, %-10.7f] m\np = %-10.7f GeV/c\ntheta = %-10.7f deg\nphi = %-10.7f deg\n-------\n", v.charge, v.xo, v.yo, v.zo, v.p, v.theta, v.phi);
-
+
return "\n-----------\nInitial values:\n" + s;
}
-
- /**
- * Set the initial values
- * @param iv the source
- */
- public void setInitialValies(InitialValues iv) {
- _initialValues = new InitialValues(iv);
- }
-
- /**
- * Used to compare to old swimmer
- * @param traj trajectory (probably from old swimmer)
- */
- public void setTrajectory(SwimTrajectory traj) {
- _trajectory = traj;
-
- _nStep = traj.size();
-
- double last[] = traj.lastElement();
- for (int i = 0; i < 6; i++) {
- _uf[i] = last[i];
- }
-
- if (last.length > 6) {
- _finalS = last[6];
- }
- }
-
-
-
/**
* Get the initial values
* @return the initial values
@@ -230,8 +309,8 @@ public void setTrajectory(SwimTrajectory traj) {
public InitialValues getInitialValues() {
return _initialValues;
}
-
-
+
+
/**
* Print the result to a print stream, such as System.out.
* Do not print the trajectory.
@@ -242,7 +321,7 @@ public void printOut(PrintStream ps, String message) {
printOut(ps, message, false);
}
-
+
/**
* Print the result to a print stream, such as System.out
* @param ps the print stream
@@ -252,20 +331,20 @@ public void printOut(PrintStream ps, String message) {
public void printOut(PrintStream ps, String message, boolean printTrajectory) {
ps.println("\n" + message);
ps.println(toString());
-
-
+
+
if (printTrajectory && hasTrajectory()) {
_trajectory.print(ps);
}
}
-
+
@Override
public String toString() {
StringBuffer sb = new StringBuffer(1024);
sb.append(locationString());
sb.append(momentumString());
sb.append(infoString());
-
+
if (hasTrajectory()) {
sb.append("\nBDL: "+ _trajectory.getComputedBDL());
}
@@ -275,42 +354,28 @@ public String toString() {
return initialValuesString() + sb.toString();
}
-
- /**
- * A final location string
- * @return a location string
- */
- public String finalLocationString() {
- double x = _uf[0];
- double y = _uf[1];
- double z = _uf[2];
- double rho = Math.hypot(x, y);
- double phi = Math.toDegrees(Math.atan2(y, x));
- return String.format("[x,y,z] = [%8.5f, %8.5f, %8.5f] cm [phi,rho] = [%8.5f deg, %8.5f cm] S = %8.5f cm",
- 100*x, 100*y, 100*z, phi, 100*rho, 100*getFinalS());
-
- }
-
+
+
//the location
private String locationString() {
- double x = _uf[0];
- double y = _uf[1];
- double z = _uf[2];
+ double x = _u[0];
+ double y = _u[1];
+ double z = _u[2];
double r = Math.sqrt(x*x + y*y + z*z);
-
+
double rho = Math.hypot(x, y);
double phi = Math.toDegrees(Math.atan2(y, x));
-
+
return String.format("R = [%10.7f, %10.7f, %10.7f] |R| = %10.7f m\n", x, y, z, r) +
String.format("[phi, rho, z] = [%10.7f, %10.7f, %10.7f]\n", phi, rho, z);
}
-
+
//the momentum string
private String momentumString() {
- double tx = _uf[3];
- double ty = _uf[4];
- double tz = _uf[5];
+ double tx = _u[3];
+ double ty = _u[4];
+ double tz = _u[5];
double norm = Math.sqrt(tx * tx + ty * ty + tz * tz);
if (_initialValues != null) {
@@ -318,7 +383,7 @@ private String momentumString() {
double py = _initialValues.p * ty;
double pz = _initialValues.p * tz;
- return String.format("Initial sector: %d Final sector: %d\n", getInitialSector(), getFinalSector())
+ return String.format("Initial sector: %d Final sector: %d\n", getInitialSector(), getSector())
+ String.format("P = [%10.7e, %10.7e, %10.7e] |P| = %10.7e\n", px, py, pz, _initialValues.p)
+ String.format("norm (should be 1): %9.7f\n", norm);
} else {
@@ -326,28 +391,28 @@ private String momentumString() {
+ String.format("norm (should be 1): %9.7f\n", norm);
}
}
-
+
private String infoString() {
-
- return "#steps = " + _nStep + " (has traj: " + hasTrajectory() + ") status: " + _status +
- String.format(" pathlength = %10.7f m\n", _finalS);
+
+ return "#steps = " + _nStep + " (has traj: " + hasTrajectory() + ") status: " + _status +
+ String.format(" pathlength = %10.7f m\n", _s);
}
-
+
/**
* Get the final sector of the swim
* @return the final CLAS sector [1..6]
*/
- public int getFinalSector() {
- double x = _uf[0];
- double y = _uf[1];
-
+ public int getSector() {
+ double x = _u[0];
+ double y = _u[1];
+
double phi = Math.toDegrees(Math.atan2(y, x));
return AdaptiveSwimUtilities.getSector(phi);
}
-
+
/**
* Get the initial sector of the swim
- * @return the final CLAS sector [1..6], or
+ * @return the final CLAS sector [1..6], or
* -1 if the initial values were not cached
*/
public int getInitialSector() {
@@ -356,60 +421,43 @@ public int getInitialSector() {
}
double x = _initialValues.xo;
double y = _initialValues.yo;
-
+
double phi = Math.toDegrees(Math.atan2(y, x));
return AdaptiveSwimUtilities.getSector(phi);
}
/**
- * get the final theta in degrees
- * @return the final theta in degrees
+ * get the final directional theta in degrees
+ * @return the final directional theta in degrees
*/
- public double getFinalTheta() {
- double x = _uf[0];
- double y = _uf[1];
- double z = _uf[2];
- double r = Math.sqrt(x*x + y*y + z*z);
-
- if (r < 1.0e-10) {
- return 0;
- }
-
- return Math.toDegrees(Math.acos(z/r));
+ public double getTheta() {
+ double theta = FastMath.acos2Deg(_u[5]);
+ return theta;
}
-
+
/**
* get the final rho in meters
* @return the final rho in meters
*/
- public double getFinalRho() {
- double x = _uf[0];
- double y = _uf[1];
- return Math.sqrt(x*x + y*y);
+ public double getRho() {
+ double x = _u[0];
+ double y = _u[1];
+ return Math.hypot(x, y);
}
-
- /**
- * get the final phi in degrees
- * @return the final phi in degrees
- */
- public double getFinalPhi() {
- double x = _uf[0];
- double y = _uf[1];
- return Math.toDegrees(Math.atan2(y, x));
- }
-
/**
- * Used for testing z swim.
- * @param zTarg the target z (m)
- * @return the signed difference zFinal - zTarg
+ * get the final directional phi in degrees
+ * @return the final directional phi in degrees
*/
- public double finalDeltaZ(double zTarg) {
- return _uf[2] - zTarg;
+ public double getPhi() {
+ double phi = FastMath.atan2Deg(_u[4], _u[3]);
+ return phi;
+
}
-
+
+
/**
* Get the "initial values" that allows a retrace. This is used mostly
* for testing. Assumes the initial values have been set,
@@ -418,16 +466,16 @@ public double finalDeltaZ(double zTarg) {
public InitialValues retrace() {
InitialValues iv = getInitialValues();
InitialValues revIv= new InitialValues();
- double uf[] = getUf();
-
+ double uf[] = getU();
+
double txf = uf[3];
double tyf = uf[4];
double tzf = uf[5];
-
+
txf *= -1;
tyf *= -1;
tzf *= -1;
-
+
revIv.charge = -iv.charge;
revIv.p = iv.p;
revIv.xo = uf[0];
@@ -435,10 +483,10 @@ public InitialValues retrace() {
revIv.zo = uf[2];
revIv.theta = FastMath.acos2Deg(tzf);
revIv.phi = FastMath.atan2Deg(tyf, txf);
-
+
return revIv;
}
-
+
/**
* Get the Euclidean distance between the last point of two results.
* Used for comparisons.
@@ -446,18 +494,70 @@ public InitialValues retrace() {
* @return the Euclidean distance between the last points.
*/
public double delDifference(AdaptiveSwimResult res) {
-
+
double u[] = this.getLastTrajectoryPoint();
double v[] = res.getLastTrajectoryPoint();
-
+
double sum = 0;
for (int i = 0 ; i < 3; i++) {
double del = v[i] - u[i];
sum += del*del;
}
-
-
+
+
return Math.sqrt(sum);
-
+
+ }
+
+ /**
+ * Compute the intersection of the left and right
+ * points with a geometric object using a linear interpolation.
+ * @param geom the object, such as a plane
+ */
+ public void computeIntersection(AGeometric geom) {
+ getIntersection().computeIntersection(geom);
+ }
+
+ /**
+ * Get the distance to the plane (should be 0)
+ * @return the distance to the plane in m
+ */
+ public double getIntersectDistance() {
+ return getIntersection().getIntersectDistance();
+ }
+
+ /**
+ * Get the intersection (interpolated) point on the plane.
+ * @return the intersection on the plane.
+ */
+ public Point getIntersectionPoint() {
+ return getIntersection().getIntersectionPoint();
+ }
+
+ /**
+ * Not all swim methods use this. It is fr those (e.g. planes) that
+ * want an estimate of the intersection. This will create the object
+ * if necessary.
+ * @return the intersection object
+ */
+ public AdaptiveSwimIntersection getIntersection() {
+ if (_intersection == null) {
+ _intersection = new AdaptiveSwimIntersection();
+ }
+ return _intersection;
}
+
+ /**
+ * Get the status of the swim as a string
+ * @return the status of the swim as a string
+ */
+ public String statusString() {
+ String s = AdaptiveSwimmer.resultNames.get(_status);
+ if (s == null) {
+ s = "Unknown (" + _status + ")";
+ }
+ return s;
+ }
+
+
}
diff --git a/common-tools/cnuphys/swimmer/src/main/java/cnuphys/adaptiveSwim/AdaptiveSwimUtilities.java b/common-tools/cnuphys/swimmer/src/main/java/cnuphys/adaptiveSwim/AdaptiveSwimUtilities.java
index 90343f1d83..8202015028 100644
--- a/common-tools/cnuphys/swimmer/src/main/java/cnuphys/adaptiveSwim/AdaptiveSwimUtilities.java
+++ b/common-tools/cnuphys/swimmer/src/main/java/cnuphys/adaptiveSwim/AdaptiveSwimUtilities.java
@@ -4,200 +4,143 @@
import cnuphys.rk4.IDerivative;
public class AdaptiveSwimUtilities {
-
- public enum DebugLevel {OFF, ON, VERBOSE};
-
- //the debul level
- private static DebugLevel _debugLevel = DebugLevel.OFF;
-
- //tolerance when swimmimg to a max path length
-// public static final double SMAX_TOLERANCE = 1.0e-4; //meters
//step size limits in meters
public static final double MIN_STEPSIZE = 1.0e-8; // meters
-
+
//maximum number of integration steps
- public static int MAX_NUMSTEP = 2000;
-
-
+ public static final int MAX_NUMSTEP = 2000;
+
+ //limit warning prints
+ private static int _warningCount = 0;
+
+
/**
- * Basic adaptive step size driver that tries to integrate from s = 0 to s = sf,
- * where sf is in the stopper object. Often this will terminate because the stopper
- * stops the integration before sf is reached.
- *
+ * Basic adaptive step size driver that tries to swim until a stop condition
+ * is met.
+ *
* @param h the step size at the start
* @param deriv the derivative computer (interface). This is where the
* problem specificity resides.
- * @param stopper will be used to exit the
- * integration early because some condition has been
- * reached.
+ * @param stopper will be used to exit the swimming
* @param advancer takes the next single step
* @param eps tolerance (e.g., 1.0e-6)
- * @param uf will hold final state vector
- *
* @return the number of steps used.
* @throw AdaptiveSwimException
*/
public static int driver(double h, IDerivative deriv, IAdaptiveStopper stopper,
- IAdaptiveAdvance advancer, double eps, double uf[]) throws AdaptiveSwimException {
-
- // get the dimensionality of the problem. e.g, 6 if u = (x, y, z, tx, ty, tz)
- double[] u0 = stopper.getU();
- int nDim = u0.length;
-
-
+ IAdaptiveAdvance advancer, double eps) throws AdaptiveSwimException {
+
+
+ //workspace
// ut is the running value of the state vector,
- // typically [x, y, z, tx, ty, tz]
- double ut[] = new double[nDim];
-
+ // [x, y, z, tx, ty, tz]
+ double _ut[] = new double[AdaptiveSwimmer.DIM];
+
//du is for derivatives
- double du[] = new double[nDim];
+ double _du[] = new double[AdaptiveSwimmer.DIM];
+
+
+ double _unew[] = new double[AdaptiveSwimmer.DIM];
+
+
+ //init the new value to be the same as the curent value
+ System.arraycopy(stopper.getU(), 0, _unew, 0, AdaptiveSwimmer.DIM);
- //init the final value to be the same as the start value
- System.arraycopy(u0, 0, uf, 0, nDim);
-
//track the number of steps
int nstep = 0;
-
+
+ double snew = stopper.getS();
+
AdaptiveStepResult result = new AdaptiveStepResult();
-
- //keep taking single steps until we reach the upper limit
+
+ //keep taking single steps until we reach the upper limit
//or the stopper stops us
while (nstep < MAX_NUMSTEP) {
- System.arraycopy(uf, 0, ut, 0, nDim);
+ System.arraycopy(_unew, 0, _ut, 0, AdaptiveSwimmer.DIM);
//compute derivs at current step
- deriv.derivative(stopper.getS(), ut, du);
- advancer.advance(stopper.getS(), ut, du, h, deriv, uf, eps, result);
-
+ deriv.derivative(stopper.getS(), _ut, _du);
+ advancer.advance(stopper.getS(), _ut, _du, h, deriv, _unew, eps, result);
+
double hnew = result.getHNew();
-
+
h = Math.max(MIN_STEPSIZE, Math.min(stopper.getMaxStepSize(), hnew));
- double snew = result.getSNew();
-
+ snew = result.getSNew();
+
nstep++;
-
+
//will the stopper terminate?
- if (stopper.stopIntegration(snew, uf)) {
+ if (stopper.stopIntegration(snew, _unew)) {
return nstep;
- }
-
- }
-
- return nstep;
- }
-
- /**
- * Take a single step using basic fourth order RK
- *
- * @param s the independent variable
- * @param u the current state vector
- * @param du the current derivatives
- * @param h the step size
- * @param deriv can compute the rhs of the diffy q
- * @param uf the state vector after the step
- */
- public static void singleRK4Step(final double s, double[] u, double[] du, final double h, IDerivative deriv, double[] uf) {
-
- int nDim = u.length;
-
- // note that du (input) is k1
- double k1[] = du; // the current derivatives
-
- double k2[] = new double[nDim];
- double k3[] = new double[nDim];
- double k4[] = new double[nDim];
- double utemp[] = new double[nDim];
-
- double hh = h * 0.5; // half step
- double h6 = h / 6.0;
-
- // advance t to mid point
- double sMid = s + hh;
+ }
- // first step: initial derivs to midpoint
- for (int i = 0; i < nDim; i++) {
- utemp[i] = u[i] + hh * k1[i];
}
- deriv.derivative(sMid, utemp, k2);
- // 2nd step (like 1st, but use midpoint just computed derivs dyt)
- for (int i = 0; i < nDim; i++) {
- utemp[i] = u[i] + hh * k2[i];
+ if (_warningCount < 4) {
+ System.err.println("In the adaptive swimmer, the step count reached the max limit of " + MAX_NUMSTEP +
+ " which usually indicates bad stopper logic.");
+ System.err.println(" snew = " + snew);
+ System.err.println(String.format("ut = (%11.7f, %11.7f, %11.7f)", _ut[0], _ut[1], _ut[2]));
+ _warningCount++;
}
- deriv.derivative(sMid, utemp, k3);
- // third (full) step
- for (int i = 0; i < nDim; i++) {
- utemp[i] = u[i] + h * k3[i];
- }
- deriv.derivative(s + h, utemp, k4);
+ return nstep;
+ }
- for (int i = 0; i < nDim; i++) {
- uf[i] = u[i] + h6 * (k1[i] + 2 * k2[i] + 2 * k3[i] + k4[i]);
- }
- }
-
-
/**
* Take a single step using a Butcher tableau
- *
+ *
* @param s the independent variable
- * @param u the current state vector
+ * @param u0 the current state vector
* @param du the current derivatives
* @param h the step size
* @param deriv can compute the rhs of the diffy q
* @param uf the state vector after the step (output)
+ * uf cannot be the same as u0
* @param error the error estimate (output)
* @param tableau the Butcher tableau
*/
- public static void singleButcherStep(double s, double[] u, double[] du, double h, IDerivative deriv, double[] uf,
- double[] error, ButcherTableau tableau) {
-
- int nDim = u.length;
- int numStage = tableau.getNumStage();
+ public static void singleButcherStep(double s, double[] u0, double[] du, double h, IDerivative deriv, double[] uf,
+ double[] error, ButcherTableau tableau, double k[][], double[] utemp) {
- double utemp[] = new double[nDim];
- double k[][] = new double[numStage + 1][];
- k[0] = null; // not used
+ int numStage = tableau.getNumStage();
// k1 is just h*du
- k[1] = new double[nDim];
- for (int i = 0; i < nDim; i++) {
+ for (int i = 0; i < AdaptiveSwimmer.DIM; i++) {
k[1][i] = h * du[i];
}
// fill the numStage k vectors
for (int stage = 2; stage <= numStage; stage++) {
- k[stage] =new double[nDim];
double ts = s + tableau.c(stage);
- for (int i = 0; i < nDim; i++) {
- utemp[i] = u[i];
+ for (int i = 0; i < AdaptiveSwimmer.DIM; i++) {
+ utemp[i] = u0[i];
for (int ss = 1; ss < stage; ss++) {
utemp[i] += tableau.a(stage, ss) * k[ss][i];
}
}
deriv.derivative(ts, utemp, k[stage]);
- for (int i = 0; i < nDim; i++) {
+ for (int i = 0; i < AdaptiveSwimmer.DIM; i++) {
k[stage][i] *= h;
}
}
-
- for (int i = 0; i < nDim; i++) {
+
+ for (int i = 0; i < AdaptiveSwimmer.DIM; i++) {
double sum = 0.0;
for (int stage = 1; stage <= numStage; stage++) {
sum += tableau.b(stage) * k[stage][i];
}
- uf[i] = u[i] + sum;
+ uf[i] = u0[i] + sum;
}
// compute error?
if (tableau.isAugmented() && (error != null)) {
// absolute error
- for (int i = 0; i < nDim; i++) {
+ for (int i = 0; i < AdaptiveSwimmer.DIM; i++) {
error[i] = 0.0;
// error diff 4th and 5th order
for (int stage = 1; stage <= numStage; stage++) {
@@ -205,48 +148,14 @@ public static void singleButcherStep(double s, double[] u, double[] du, double h
}
}
- // relative error
- // for (int i = 0; i < nDim; i++) {
- // double sum = 0.0;
- // for (int s = 1; s <= numStage; s++) {
- // sum += tableau.bstar(s)*k[s][i];
- // }
- // double ystar = y[i] + sum;
- // error[i] = relativeDiff(yout[i], ystar);
- // }
-
- // for (int i = 0; i < nDim; i++) {
- // System.out.print(String.format("[%-12.5e] ", error[i]));
- // }
- // System.out.println();
-
}
}
-
- /**
- * Set the debug level
- * @param level the new debug level
- */
- public static void setDebugLevel(DebugLevel level) {
- _debugLevel = level;
- }
-
-
- /**
- * Set the maximum number of steps beyond which an error occurs
- * @param maxSteps the maximum number of steps. Default is 2000.
- */
- public static void setMaxNumberSteps(int maxSteps) {
- MAX_NUMSTEP = maxSteps;
- }
-
-
/**
* Get the sector [1..6] from the phi value
- *
+ *
* @param phi the value of phi in degrees
* @return the sector [1..6]
*/
@@ -278,5 +187,26 @@ public static int getSector(double phi) {
return 1;
}
+ /**
+ * Get just the x y z location of the state vector in cm
+ * @param u the state vector
+ * @return the x y z location of the state vector in cm
+ */
+ public static String uStringXYZ(double u[]) {
+ return String.format("(%11.8f, %11.8f, %11.8f) cm", 100*u[0], 100*u[1], 100*u[2]);
+ }
+
+ /**
+ * Get just the x y z location of the state vector in cm
+ * with a prepended message
+ * @param u the state vector
+ * @return the x y z location of the state vector in cm
+ * with a prepended message
+ */
+ public static String uStringXYZ(String message, double u[]) {
+ return message + " " + uStringXYZ(u);
+ }
+
+
}
diff --git a/common-tools/cnuphys/swimmer/src/main/java/cnuphys/adaptiveSwim/AdaptiveSwimmer.java b/common-tools/cnuphys/swimmer/src/main/java/cnuphys/adaptiveSwim/AdaptiveSwimmer.java
index 7e6c45894b..22560180d7 100644
--- a/common-tools/cnuphys/swimmer/src/main/java/cnuphys/adaptiveSwim/AdaptiveSwimmer.java
+++ b/common-tools/cnuphys/swimmer/src/main/java/cnuphys/adaptiveSwim/AdaptiveSwimmer.java
@@ -1,56 +1,85 @@
package cnuphys.adaptiveSwim;
+import java.util.Hashtable;
+
import cnuphys.adaptiveSwim.geometry.Cylinder;
-import cnuphys.adaptiveSwim.geometry.Line;
import cnuphys.adaptiveSwim.geometry.Plane;
import cnuphys.adaptiveSwim.geometry.Sphere;
import cnuphys.lund.GeneratedParticleRecord;
-import cnuphys.magfield.FastMath;
import cnuphys.magfield.FieldProbe;
import cnuphys.magfield.IMagField;
import cnuphys.magfield.MagneticField;
import cnuphys.magfield.RotatedCompositeProbe;
import cnuphys.rk4.ButcherTableau;
-import cnuphys.swim.DefaultDerivative;
-import cnuphys.swim.SectorDerivative;
import cnuphys.swim.SwimTrajectory;
/**
- * A swimmer for adaptive stepsize integrators. These swimmers are not thread safe. Every thread that needs an
- * AdaptiveSwimmer should create its own.
- *
+ * A swimmer for adaptive stepsize integrators. These swimmers are not thread
+ * safe. Every thread that needs an AdaptiveSwimmer should create its own.
+ *
* @author heddle
*
*/
public class AdaptiveSwimmer {
-
- //result status values
+
+ //dimensionality of our swimming
+ public static final int DIM = 6;
+
+
+ /** currently swimming */
+ public static final int SWIM_SWIMMING = 88;
+
+
/** The swim was a success */
public static final int SWIM_SUCCESS = 0;
-
- /** A target, such as a target rho or z, was not reached
- * before the swim was stopped for some other reason
- */
- public static final int SWIM_TARGET_MISSED = -1;
-
+
+ // Speed of light in m/s
+ public static final double C = 299792458.0; // m/s
+
/**
- * A swim was requested for a particle with extremely low
- * momentum
+ * A target, such as a target rho or z, was not reached before the swim was
+ * stopped for some other reason
*/
+ public static final int SWIM_TARGET_MISSED = -1;
+
+ /** A swim was requested for a particle with extremely low momentum */
public static final int SWIM_BELOW_MIN_P = -2;
-
+
+ /** A swim was requested exceeded the max number of tries */
+ public static final int SWIM_EXCEED_MAX_TRIES = -3;
+
+ /** A swim crossed a boundary, need to back up and reduce h */
+ public static final int SWIM_CROSSED_BOUNDARY = -4;
+
+ /** A swim was requested for a neutral particle */
+ public static final int SWIM_NEUTRAL_PARTICLE = 10;
+
+ public static final Hashtabletrue if we should stop now.
@@ -21,23 +21,42 @@ public interface IAdaptiveStopper {
* @return the current independent variable
*/
public double getS();
-
+
/**
* Get the current value of the state vector
* @return the current value of the state vector
*/
public double[] getU();
-
+
/**
* Get the max or final value of the independent variable
* @return the max or final value of the independent variable
*/
public double getSmax();
-
+
/**
* Get the max step size. This can vary with conditions, primarily
- * with the proximity to a target
+ * with the proximity to a target
* @return the current max step in meters
*/
public double getMaxStepSize();
+
+ /**
+ * Get a new step size, probably because we crossed a boundary
+ * @param h the old step size
+ * @return the new (smaller) step size
+ */
+ public double getNewStepSize(double h);
+
+ /**
+ * For doing things like setting the initial sign and distance
+ */
+ public void initialize();
+
+ /**
+ * Get the result object
+ * @return the result object
+ */
+ public AdaptiveSwimResult getResult();
+
}
diff --git a/common-tools/cnuphys/swimmer/src/main/java/cnuphys/adaptiveSwim/InitialValues.java b/common-tools/cnuphys/swimmer/src/main/java/cnuphys/adaptiveSwim/InitialValues.java
new file mode 100644
index 0000000000..42c25f9374
--- /dev/null
+++ b/common-tools/cnuphys/swimmer/src/main/java/cnuphys/adaptiveSwim/InitialValues.java
@@ -0,0 +1,77 @@
+package cnuphys.adaptiveSwim;
+
+/**
+ * Hold the initial values of a swim
+ *
+ * @author heddle
+ *
+ */
+public class InitialValues {
+
+ /** The integer charge */
+ public int charge;
+
+ /** The coordinate x of the vertex in meters */
+ public double xo;
+
+ /** The y coordinate of the vertex in meters */
+ public double yo;
+
+ /** The z coordinate of the vertex in meters */
+ public double zo;
+
+ /** The momentum in GeV/c */
+ public double p;
+
+ /** The polar angle in degrees */
+ public double theta;
+
+ /** The azimuthal angle in degrees */
+ public double phi;
+
+ public InitialValues() {
+ }
+
+ public String toStringRaw() {
+ return String.format("%-7.4f %-7.4f %-7.4f %-6.3f %-6.3f %-6.3f", xo, yo, zo, p, theta, phi);
+ }
+
+ /**
+ * Store the initial conditions of a swim
+ *
+ * @param charge The integer charge
+ * @param xo The x coordinate of the vertex in meters
+ * @param yo The y coordinate of the vertex in meters
+ * @param zo The z coordinate of the vertex in meters
+ * @param p The momentum in GeV/c
+ * @param theta The polar angle in degrees
+ * @param phi The azimuthal angle in degrees
+ */
+ public InitialValues(int charge, double xo, double yo, double zo, double p, double theta, double phi) {
+ this.charge = charge;
+ this.xo = xo;
+ this.yo = yo;
+ this.zo = zo;
+ this.p = p;
+ this.theta = theta;
+ this.phi = phi;
+ }
+
+ /**
+ * Copy constructor
+ *
+ * @param src the source initial values
+ */
+ public InitialValues(InitialValues src) {
+ this(src.charge, src.xo, src.yo, src.zo, src.p, src.theta, src.phi);
+ }
+
+ @Override
+ public String toString() {
+ return String.format("Q: %d\n", charge) + String.format("xo: %10.7e m\n", xo)
+ + String.format("yo: %10.7e m\n", yo) + String.format("zo: %10.7e m\n", zo)
+ + String.format("p: %10.7e GeV/c\n", p) + String.format("theta: %10.7f deg\n", theta)
+ + String.format("phi: %10.7f deg", phi);
+ }
+
+}
diff --git a/common-tools/cnuphys/swimmer/src/main/java/cnuphys/adaptiveSwim/PlaneSignChangeStopper.java b/common-tools/cnuphys/swimmer/src/main/java/cnuphys/adaptiveSwim/PlaneSignChangeStopper.java
new file mode 100644
index 0000000000..ebc0f5ff8b
--- /dev/null
+++ b/common-tools/cnuphys/swimmer/src/main/java/cnuphys/adaptiveSwim/PlaneSignChangeStopper.java
@@ -0,0 +1,29 @@
+package cnuphys.adaptiveSwim;
+
+import cnuphys.adaptiveSwim.geometry.Plane;
+
+
+public class PlaneSignChangeStopper extends ASignChangeStopper {
+
+
+ /**
+ * Sign change stopper (does check max path length)
+ * @param sfMax the maximum value of the path length in meters
+ * @param targetPlane the target plane
+ * @param result holds the results, its u statevector should have been initialized
+ * to the starting vector
+ */
+ public PlaneSignChangeStopper(final double sMax, Plane targetPlane, AdaptiveSwimResult result) {
+ super(sMax, targetPlane, result);
+ }
+
+
+ @Override
+ public int sign(double snew, double[] unew) {
+ Plane _targetPlane = (Plane)_target;
+ double signedDistance = _targetPlane.signedDistance(unew[0], unew[1], unew[2]);
+ return (signedDistance < 0) ? -1 : 1;
+ }
+
+
+}
diff --git a/common-tools/cnuphys/swimmer/src/main/java/cnuphys/adaptiveSwim/RK4HalfStepAdvance.java b/common-tools/cnuphys/swimmer/src/main/java/cnuphys/adaptiveSwim/RK4HalfStepAdvance.java
deleted file mode 100644
index 5e076c034d..0000000000
--- a/common-tools/cnuphys/swimmer/src/main/java/cnuphys/adaptiveSwim/RK4HalfStepAdvance.java
+++ /dev/null
@@ -1,118 +0,0 @@
-package cnuphys.adaptiveSwim;
-
-import cnuphys.rk4.IDerivative;
-
-/**
- * This is a 4th order RungeKutta advancer
- * @author heddle
- *
- */
-public class RK4HalfStepAdvance implements IAdaptiveAdvance {
-
- //a safety fudge factor
- private static final double _safety = 0.9;
-
- //power used when the step should grow
- private static final double _pgrow = -0.20;
-
- //power used when the step should shrink
- private static final double _pshrink = -0.25;
-
- //for error control
- private static final double _errControl = 1.89e-4;
-
- //to make a cirrection that gives us 5th order accuracy
- private static final double _correctFifth = 1. / 15;
-
- //a tiny number
- private static final double _tiny = 1.0e-14;
-
- //the dimension of the problem (length of state vector)
- private int _nDim;
-
- //some work arrays
-// private double _usave[];
-// private double _dusave[];
- private double _utemp[];
- private double _dutemp[];
- private double _uscale[];
-
-
- /**
- * Create a RK4 half stepper
- * @param nDim the dimension of the problem (length of state vector)
- */
- public RK4HalfStepAdvance(int nDim) {
- _nDim = nDim;
- _utemp = new double[_nDim];
- _dutemp = new double[_nDim];
- _uscale = new double[_nDim];
- }
-
- @Override
- public void advance(double s, double[] u, double[] du, double h, IDerivative deriv, double[] uf, double eps,
- AdaptiveStepResult result) {
-
- boolean done = false;
-
-
- while (!done) {
-
- // almost relative error, but with safety when values of u are small
- for (int i = 0; i < _nDim; i++) {
- _uscale[i] = Math.abs(u[i]) + Math.abs(h * du[i]) + _tiny;
- }
-
- // advance two half steps after which uf will hold the value of
- // which, if our steps size is acceptable, this will be our result
- double h2 = h / 2;
- double smid = s + h2;
- AdaptiveSwimUtilities.singleRK4Step(s, u, du, h2, deriv, _utemp);
- deriv.derivative(smid, _utemp, _dutemp);
- AdaptiveSwimUtilities.singleRK4Step(smid, _utemp, _dutemp, h2, deriv, uf);
-
- // take the full step
- AdaptiveSwimUtilities.singleRK4Step(s, u, du, h, deriv, _utemp);
-
- // compute the maximum error
- double errMax = 0;
- for (int i = 0; i < _nDim; i++) {
- //set utemp to be the difference between the two step solution and the one step
- _utemp[i] = uf[i] - _utemp[i];
- errMax = Math.max(errMax, Math.abs(_utemp[i] / _uscale[i]));
- }
-
- // scale based on tolerance in eps
- errMax = errMax / eps;
-
- if (errMax > 1) {
- //get smaller h, then try again since done = false
-
- double shrinkFact = _safety * Math.pow(errMax, _pshrink);
-
- //no more than a factor of 4
- shrinkFact = Math.max(shrinkFact, 0.25);
- h = h * shrinkFact;
- } else { // can grow
- double hnew;
- if (errMax > _errControl) {
- double growFact = _safety * Math.pow(errMax, _pgrow);
- hnew = h * growFact;
- } else {
- hnew = 5 * h;
- }
-
- result.setHNew(hnew);
- result.setSNew(s + h); //step we actually took
- done = true;
- }
-
- } // !done
-
- // mop up 5th order truncation error
- //so result is actually 5th order
- for (int i = 0; i < _nDim; i++) {
- uf[i] = uf[i] + _utemp[i] * _correctFifth;
- }
- } // end advance
-}
diff --git a/common-tools/cnuphys/swimmer/src/main/java/cnuphys/adaptiveSwim/SwimType.java b/common-tools/cnuphys/swimmer/src/main/java/cnuphys/adaptiveSwim/SwimType.java
new file mode 100644
index 0000000000..15d8017f6a
--- /dev/null
+++ b/common-tools/cnuphys/swimmer/src/main/java/cnuphys/adaptiveSwim/SwimType.java
@@ -0,0 +1,5 @@
+package cnuphys.adaptiveSwim;
+
+public enum SwimType {
+MCSWIM, RECONSWIM
+}
diff --git a/common-tools/cnuphys/swimmer/src/main/java/cnuphys/adaptiveSwim/geometry/AGeometric.java b/common-tools/cnuphys/swimmer/src/main/java/cnuphys/adaptiveSwim/geometry/AGeometric.java
new file mode 100644
index 0000000000..6388d55f1e
--- /dev/null
+++ b/common-tools/cnuphys/swimmer/src/main/java/cnuphys/adaptiveSwim/geometry/AGeometric.java
@@ -0,0 +1,89 @@
+package cnuphys.adaptiveSwim.geometry;
+
+/**
+ * For objects that we might use in stoppers, such as planes.
+ * @author heddle
+ *
+ */
+public abstract class AGeometric {
+
+ /**
+ * Often we have geomtric objects centered on the origin
+ */
+ protected static final Point _origin = new Point(0, 0, 0);
+
+ /**
+ * Signed distance from a point to the object
+ *
+ * @param x the x coordinate
+ * @param y the y coordinate
+ * @param z the z coordinate
+ * @return the signed distance (indicates which side you are on)
+ */
+ public abstract double signedDistance(double x, double y, double z);
+
+ /**
+ * Create a line from two points and then get the intersection with the object
+ * @param p1 one point
+ * @param p2 another point
+ * @param p will hold the intersection, NaNs if no intersection
+ * @return the t parameter. If NaN it means the line is parallel to the object.
+ * If t [0,1] then the segment intersects the object. If t outside [0, 1]
+ * the infinite line intersects the object, but not the segment
+ */
+ public abstract double interpolate(Point p1, Point p2, Point p);
+
+
+ /**
+ * Distance from a point to the object
+ *
+ * @param x the x coordinate
+ * @param y the y coordinate
+ * @param z the z coordinate
+ * @return the distance to the object
+ */
+ public double distance(double x, double y, double z) {
+ return Math.abs(signedDistance(x, y, z));
+ }
+
+ /**
+ * Distance from a point to the object
+ *
+ * @param p the point in question
+ * @return the distance to the plane
+ */
+ public double distance(Point p) {
+ return distance(p.x, p.y, p.z);
+ }
+
+ /**
+ * Distance from a point to the plane
+ *
+ * @param u the point in question u[0]=x, u[1]=y, u[2]=z
+ * @return the distance to the plane
+ */
+ public double distance(double[] u) {
+ return distance(u[0], u[1], u[2]);
+ }
+
+ /**
+ * Signed distance from a point to the plane
+ *
+ * @param u the point in question u[0]=x, u[1]=y, u[2]=z
+ * @return the signed distance to the plane
+ */
+ public double signedDistance(double[] u) {
+ return signedDistance(u[0], u[1], u[2]);
+ }
+
+ /**
+ * Signed distance from a point to the object
+ *
+ * @param p the point in question
+ * @return the signed distance (indicates which side you are on)
+ */
+ public double signedDistance(Point p) {
+ return signedDistance(p.x, p.y, p.z);
+ }
+
+}
diff --git a/common-tools/cnuphys/swimmer/src/main/java/cnuphys/adaptiveSwim/geometry/Cylinder.java b/common-tools/cnuphys/swimmer/src/main/java/cnuphys/adaptiveSwim/geometry/Cylinder.java
index 4f57a28cf2..9e550a69f9 100644
--- a/common-tools/cnuphys/swimmer/src/main/java/cnuphys/adaptiveSwim/geometry/Cylinder.java
+++ b/common-tools/cnuphys/swimmer/src/main/java/cnuphys/adaptiveSwim/geometry/Cylinder.java
@@ -1,7 +1,8 @@
package cnuphys.adaptiveSwim.geometry;
+
/**
- * A cylinder is defined by a centerline and a radius
+ * An INFINITE cylinder is defined by a centerline and a radius
* @author heddle
*
*/
@@ -9,10 +10,10 @@ public class Cylinder {
//the centerline
private Line _centerLine;
-
+
//the radius
- private double _radius;
-
+ public double radius;
+
/**
* Create a cylinder
* @param centerLine the center line
@@ -20,9 +21,9 @@ public class Cylinder {
*/
public Cylinder(Line centerLine, double radius) {
_centerLine = new Line(centerLine);
- _radius = radius;
+ this.radius = radius;
}
-
+
/**
* Create a cylinder
* @param p1 one point of center line as an xyz array
@@ -40,11 +41,23 @@ public Cylinder(double[] p1, double[] p2, double radius) {
* @param p a point
* @return the perpendicular distance
*/
+ public double signedDistance(Point p) {
+ double lineDist = _centerLine.distance(p);
+ return lineDist - radius;
+ }
+
+ /**
+ * Set the path length of the swim
+ * @deprecated Use {@link Cylinder#signedDistance} instead.
+ * @param p a point
+ * @return the perpendicular distance
+ */
+ @Deprecated
public double distance(Point p) {
double lineDist = _centerLine.distance(p);
- return lineDist - _radius;
+ return lineDist - radius;
}
-
+
/**
* Get the shortest distance between the surface of this infinite cylinder and a point.
* If the value is negative, we are inside the cylinder.
@@ -53,9 +66,44 @@ public double distance(Point p) {
* @param z the z coordinate
* @return the perpendicular distance
*/
+ public double signedDistance(double x, double y, double z) {
+ Point p = new Point(x, y, z);
+ return signedDistance(p);
+ }
+
+ /**
+ * Get the shortest absolute distance between the surface of this infinite cylinder and a point.
+ * @param x the x coordinate
+ * @param y the y coordinate
+ * @param z the z coordinate
+ * @return the perpendicular distance
+ */
public double distance(double x, double y, double z) {
Point p = new Point(x, y, z);
- return distance(p);
+ return Math.abs(signedDistance(p));
+ }
+
+ /**
+ * Is the point inside the cylinder?
+ * @param x the x coordinate
+ * @param y the y coordinate
+ * @param z the z coordinate
+ * @return true if the point is inside the cylinder.
+ */
+ public boolean isInside(double x, double y, double z) {
+ return signedDistance(x, y, z) < 0;
+ }
+
+ /**
+ * Is the cylinder centered on the z axis?
+ * @return true if the cylinder is centered on the z axis.
+ */
+ public boolean centeredOnZ() {
+ double x0 = _centerLine.getP0().x;
+ double y0 = _centerLine.getP0().y;
+ double x1 = _centerLine.getP1().x;
+ double y1 = _centerLine.getP1().y;
+ return (x0 == 0) && (y0 == 0) && (x1 == 0) && (y1 == 0);
}
}
diff --git a/common-tools/cnuphys/swimmer/src/main/java/cnuphys/adaptiveSwim/geometry/Line.java b/common-tools/cnuphys/swimmer/src/main/java/cnuphys/adaptiveSwim/geometry/Line.java
index db5b69b409..6002a5fbe0 100644
--- a/common-tools/cnuphys/swimmer/src/main/java/cnuphys/adaptiveSwim/geometry/Line.java
+++ b/common-tools/cnuphys/swimmer/src/main/java/cnuphys/adaptiveSwim/geometry/Line.java
@@ -199,34 +199,4 @@ public Point getCenter() {
return getP(0.5);
}
- // testing
- public static void main(String arg[]) {
- Point p1 = new Point(0, 0, 0);
- Point p2 = new Point(1, 1, 0);
-
- Line line = new Line(p1, p2);
-
- Point p = new Point(-10, 10, 5);
-
- System.out.println(p.toString() + " distance = " + line.distance(p) + " on line: " + line.pointOnLine(p));
-
- p.set(999., 999., 0.001);
- System.out.println(
- p.toString() + " distance = " + line.distance(p) + " on line: " + line.pointOnLine(p, 0.01));
-
-
- Point p3 = new Point(0, 0, 0);
- Point p4 = new Point(0, 0, 1);
-
- Line zaxis = new Line(p3, p4);
-
- System.out.println("Created a line corresponding to the z axis");
- System.out.println("Should be 0: " + zaxis.distance(0, 0, 99));
- System.out.println("Should be 100: " + zaxis.distance(-100, 0, 99));
-
- double d = zaxis.distance(-10, 10, -999);
- System.out.println("Should be 200: " + (d*d));
-
- }
-
}
\ No newline at end of file
diff --git a/common-tools/cnuphys/swimmer/src/main/java/cnuphys/adaptiveSwim/geometry/Plane.java b/common-tools/cnuphys/swimmer/src/main/java/cnuphys/adaptiveSwim/geometry/Plane.java
index 516aa93a6c..77a8766bab 100644
--- a/common-tools/cnuphys/swimmer/src/main/java/cnuphys/adaptiveSwim/geometry/Plane.java
+++ b/common-tools/cnuphys/swimmer/src/main/java/cnuphys/adaptiveSwim/geometry/Plane.java
@@ -1,14 +1,15 @@
package cnuphys.adaptiveSwim.geometry;
+
/**
* A plane is defined by the equation (r - ro).norm = 0 Where r is an arbitrary
* point on the plane, ro is a given point on the plane and norm is the normal
* to the plane
- *
+ *
* @author heddle
*
*/
-public class Plane {
+public class Plane extends AGeometric {
// unit vector normal to plane
public final Vector norm;
@@ -26,7 +27,7 @@ public class Plane {
/**
* Create a plane from a normal vector and a point on the plane
- *
+ *
* @param norm the normal vector
* @param p a point in the plane
* @return the plane that contains p and its normal is norm
@@ -40,7 +41,7 @@ public Plane(Vector anorm, Point p) {
c = norm.z; // C
d = a * p0.x + b * p0.y + c * p0.z; // D
}
-
+
/**
* Create a plane from the normal vector in an array of doubles and
* a point in the plane in an array, both (x, y, z)
@@ -48,54 +49,89 @@ public Plane(Vector anorm, Point p) {
* @param point the point in the plane
*/
public Plane(double norm[], double point[]) {
-
- this(new Vector(norm[0], norm[1], norm[2]),
+
+ this(new Vector(norm[0], norm[1], norm[2]),
new Point(point[0], point[1], point[2]));
}
/**
- * Distance from a point to the plane
- *
- * @param p the point in question
- * @return the distance to the plane
+ * Create a plane from a normal vector and a point on the plane
+ * @param nx x component of normal vector
+ * @param ny y component of normal vector
+ * @param nz z component of normal vector
+ * @param px x component of point on plane
+ * @param py y component of point on plane
+ * @param pz z component of point on plane
*/
- public double distance(Point p) {
- return distance(p.x, p.y, p.z);
+ public Plane(double nx, double ny, double nz, double px, double py, double pz) {
+
+ this(new Vector(nx, ny, nz),
+ new Point(px, py, pz));
}
/**
- * Distance from a point to the plane
- *
- * @param x the x coordinate
- * @param y the y coordinate
- * @param z the z coordinate
- * @return the distance to the plane
+ * Create a line from two points and then get the intersection with the plane
+ * @param p1 one point
+ * @param p2 another point
+ * @param p will hold the intersection, NaNs if no intersection
+ * @return the t parameter. If NaN it means the line is parallel to the plane.
+ * If t [0,1] then the segment intersects the plane. If t outside [0, 1]
+ * the infinite line intersects the plane, but not the segment
*/
- public double distance(double x, double y, double z) {
- return Math.abs(signedDistance(x, y, z));
+ @Override
+ public double interpolate(Point p1, Point p2, Point p) {
+ Line line = new Line(p1, p2);
+ return lineIntersection(line, p);
}
/**
- * Signed distance from a point to the plane
- *
- * @param p the point in question
- * @return the signed distance (indicates which side you are on where norm
- * defines positive side)
+ * Get the intersection of a line segment with the plane
+ *
+ * @param u1 the first point of the line segment
+ * @param u2 the second point of the line segment
+ * @param uInter will hold the intersection, NaNs if no intersection
+ * @return the t parameter. If NaN it means the line is parallel to the plane.
*/
- public double signedDistance(Point p) {
- return signedDistance(p.x, p.y, p.z);
+ public double lineSegmentPlaneIntersection(double u1[], double u2[], double uInter[]) {
+
+ double dx = u2[0] - u1[0];
+ double dy = u2[1] - u1[1];
+ double dz = u2[2] - u1[2];
+
+ double denominator = a * dx + b * dy + c * dz;
+
+ // Check if line is parallel to the plane
+ if (Math.abs(denominator) < Constants.TINY) {
+
+ for (int i = 0; i < uInter.length; i++) {
+ uInter[i] = Double.NaN;
+ }
+ return Double.NaN;
+ }
+
+ double t = (d - a * u1[0] - b * u1[1] - c * u1[2]) / denominator;
+
+ // Check if the intersection point lies within the line segment
+ if (t >= 0 && t <= 1) {
+ for (int i = 0; i < uInter.length; i++) {
+ uInter[i] = u1[i] + t * (u2[i] - u1[i]);
+ }
+ }
+
+ return t;
}
/**
* Signed distance from a point to the plane
- *
+ *
* @param x the x coordinate
* @param y the y coordinate
* @param z the z coordinate
* @return the signed distance (indicates which side you are on where norm
* defines positive side)
*/
+ @Override
public double signedDistance(double x, double y, double z) {
if (Double.isNaN(_denom)) {
_denom = Math.sqrt(a * a + b * b + c * c);
@@ -105,11 +141,11 @@ public double signedDistance(double x, double y, double z) {
/**
* Compute the intersection of an infinite line with the plane
- *
+ *
* @param line the line
* @param intersection will hold the point of intersection
* @return the t parameter. If NaN it means the line is parallel to the plane.
- * If t [0,1] then the segment intersects the line. If t outside [0, 1]
+ * If t [0,1] then the segment intersects the plane. If t outside [0, 1]
* the infinite line intersects the plane, but not the segment
*/
public double lineIntersection(Line line, Point intersection) {
@@ -139,7 +175,7 @@ public double lineIntersection(Line line, Point intersection) {
}
/**
- *
+ *
* @param line the line
* @param intersection will hold the point of intersection
* @param lineType one of the Constants INFINITE or SEGMENT
@@ -162,9 +198,28 @@ public double lineIntersection(Line line, Point intersection, int lineType) {
return t;
}
+ /**
+ * Get whether the point is to the left, right or (exactly) on the plane
+ * @param x the x coordinate
+ * @param y the y coordinate
+ * @param z the z coordinate
+ * @return +1 if to the left, -1 if to the right, 0 if on the plane
+ */
+ public int sign(double x, double y, double z) {
+ double result = a * x + b * y + c * z;
+
+ if (result > d) {
+ return +1;
+ } else if (result < d) {
+ return -1;
+ } else {
+ return 0;
+ }
+ }
+
/**
* Create a plane of constant azimuthal angle phi
- *
+ *
* @param phi the azimuthal angle in degrees
* @return the plane of constant phi
*/
@@ -189,66 +244,6 @@ public String toString() {
return pstr + " p = " + p0 + " norm = " + norm;
}
- /**
- * Obtain the line resulting from the intersection of this plane and another
- * plane
- *
- * @param plane the other plane
- * @return line formed by the intersection
- */
- public Line planeIntersection(Plane plane) {
- Vector s = Vector.cross(norm, plane.norm);
-
- if (s.length() < Constants.TINY) {
- return null;
- }
-
- // need to find one point
- Point p0 = new Point();
-
- // try setting z to 0
- double ans[] = solve(a, b, d, plane.a, plane.b, plane.d);
- if (ans != null) {
- p0.set(ans[0], ans[1], 0);
- } else {// try setting y to 0
- ans = solve(a, c, d, plane.a, plane.c, plane.d);
- if (ans != null) {
- p0.set(ans[0], 0, ans[1]);
- } else {// try setting x to 0
- ans = solve(b, c, d, plane.b, plane.c, plane.d);
- if (ans != null) {
- p0.set(0, ans[0], ans[1]);
- } else {// toast
- return null;
- }
-
- }
-
- }
-
- Point p1 = new Point(p0.x + s.x, p0.y + s.y, p0.z + s.z);
- return new Line(p0, p1);
- }
-
- // solve simultaneous
- // a1x + b1y = d1
- // a2x + b2y = d2
- // by Cramer's rule
- private double[] solve(double a1, double b1, double d1, double a2, double b2, double d2) {
- double deter = a1 * b2 - a2 * b1;
- if (tiny(deter)) {
- return null;
- }
-
- double ans[] = new double[2];
-
- double deterx = d1 * b2 - d2 * b1;
- double detery = a1 * d2 - a2 * d1;
- ans[0] = deterx / deter;
- ans[1] = detery / deter;
- return ans;
- }
-
// is the value essentially 0?
private boolean tiny(double v) {
return Math.abs(v) < Constants.TINY;
@@ -256,7 +251,7 @@ private boolean tiny(double v) {
/**
* Find some coordinates suitable for drawing the plane as a Quad in 3D
- *
+ *
* @param scale an arbitrary big number, a couple times bigger than the drawing
* extent
* @return the jogl coordinates for drawing a Quad
@@ -272,8 +267,6 @@ public float[] planeQuadCoordinates(float scale) {
float[] coords = new float[12];
- // another point in the plane
- Point p1 = new Point();
if (tiny(b) && tiny(c)) { // constant x plane
float fx = (float) (d / a);
@@ -357,7 +350,7 @@ else if (tiny(c)) {
}
}
-
+
else { //general case, no small constants
for (int k = 0; k < 4; k++) {
int j = 3 * k;
@@ -374,71 +367,5 @@ else if (tiny(c)) {
return coords;
}
-
- private static void valCheck(Plane p, float[] coords, int index) {
- int j = 3*index;
- double x = coords[j];
- double y = coords[j+1];
- double z = coords[j+2];
- double val = p.a*x + p.b*y + p.c*z - p.d;
- System.out.println(String.format(" coord check [%d] (%-9.5f, %-9.5f, %-9.5f) val = %-9.5f (should be 0)",
- index, x, y, z, val));
- }
-
- public static void main(String arg[]) {
-// Plane p = constantPhiPlane(30);
-
- Point zero = new Point(0, 0, 0);
- Vector nn = new Vector(0, 0, 1);
- Plane zp = new Plane(nn, zero);
-
- float coords[] = zp.planeQuadCoordinates(1000);
- for (int i = 0; i < 4; i++) {
- Plane.valCheck(zp, coords, i);
- }
-
- System.out.println();
-
- Point p = new Point(1, 1, 1);
- Vector norm = new Vector(1, 1, 1);
-
- Plane plane = new Plane(norm, p);
-
- System.out.println("Init plane: " + plane);
-
- System.out.println("should be 0: " + plane.distance(p));
-
- coords = plane.planeQuadCoordinates(1000);
- for (int i = 0; i < 4; i++) {
- Plane.valCheck(plane, coords, i);
- }
-
- Point po = new Point(2, 4, -7);
- Point p1 = new Point(0, 2, 5);
- Point intersection = new Point();
- System.out.println("distance to ((2, 4, -7)): " + plane.distance(po));
-
- Line line = new Line(po, p1);
- double t = plane.lineIntersection(line, intersection);
- System.out.println(" t = " + t + " intersect: " + intersection);
-
- double phi = -210;
- plane = constantPhiPlane(phi);
- System.out.println("constant phi plane phi = " + phi);
- t = plane.lineIntersection(line, intersection);
- System.out.println(" t = " + t + " intersect: " + intersection + " phicheck = "
- + Math.toDegrees(Math.atan2(intersection.y, intersection.x)));
-
- coords = plane.planeQuadCoordinates(1000);
- for (int i = 0; i < 4; i++) {
- Plane.valCheck(plane, coords, i);
- }
-
-
- // intersection of two phi planes should be z axis
- Plane pp1 = constantPhiPlane(57);
- Plane pp2 = constantPhiPlane(99);
- System.out.println("Intersection of two phi planes: " + pp1.planeIntersection(pp2));
- }
}
\ No newline at end of file
diff --git a/common-tools/cnuphys/swimmer/src/main/java/cnuphys/adaptiveSwim/geometry/Point.java b/common-tools/cnuphys/swimmer/src/main/java/cnuphys/adaptiveSwim/geometry/Point.java
index c09dea761d..8bfac3b0b1 100644
--- a/common-tools/cnuphys/swimmer/src/main/java/cnuphys/adaptiveSwim/geometry/Point.java
+++ b/common-tools/cnuphys/swimmer/src/main/java/cnuphys/adaptiveSwim/geometry/Point.java
@@ -109,7 +109,7 @@ public static double dot(Point a, Point b) {
*/
@Override
public String toString() {
- return String.format("(%10.6G, %10.6G, %10.6G)", x, y, z);
+ return String.format("(%-10.6f, %-10.6f, %-10.6f)", x, y, z);
}
/**
diff --git a/common-tools/cnuphys/swimmer/src/main/java/cnuphys/adaptiveSwim/geometry/Sphere.java b/common-tools/cnuphys/swimmer/src/main/java/cnuphys/adaptiveSwim/geometry/Sphere.java
index bc5c9877ee..aec054659b 100644
--- a/common-tools/cnuphys/swimmer/src/main/java/cnuphys/adaptiveSwim/geometry/Sphere.java
+++ b/common-tools/cnuphys/swimmer/src/main/java/cnuphys/adaptiveSwim/geometry/Sphere.java
@@ -2,20 +2,21 @@
/**
* A sphere centered at an arbitrary point
+ *
* @author heddle
*
*/
-public class Sphere {
-
+public class Sphere extends AGeometric {
- //the center
+ // the center
private Point _center;
-
- //the radius
+
+ // the radius
private double _radius;
-
+
/**
* Create a sphere
+ *
* @param center the center of the sphere
* @param radius the radius of the sphere
*/
@@ -23,30 +24,140 @@ public Sphere(Point center, double radius) {
_center = new Point(center);
_radius = radius;
}
-
/**
- * Get the shortest distance between the surface of this sphere and a point.
- * If the value is negative, we are inside the sphere.
+ * Create a sphere
+ *
+ * @param center the center of the sphere as an xyz array
+ * @param radius the radius of the sphere
+ */
+ public Sphere(double[] center, double radius) {
+ this(new Point(center[0], center[1], center[2]), radius);
+ }
+
+ /**
+ * Create a sphere centered on the origin
+ *
+ * @param radius the radius of the sphere
+ */
+ public Sphere(double radius) {
+ this(_origin, radius);
+ }
+
+ /**
+ * Get the radius of the sphere
+ *
+ * @return the radius of the sphere
+ */
+ public double getRadius() {
+ return _radius;
+ }
+
+ /**
+ * Get the shortest distance between the surface of this sphere and a point. If
+ * the value is negative, we are inside the sphere.
+ *
* @param p a point
* @return the distance to the sphere
*/
- public double distance(Point p) {
+ @Override
+ public double signedDistance(Point p) {
double centDist = _center.distance(p);
return centDist - _radius;
}
-
+
/**
- * Get the shortest distance between the surface of this sphere and a point.
- * If the value is negative, we are inside the sphere.
+ * Get the shortest distance between the surface of this sphere and a point. If
+ * the value is negative, we are inside the sphere.
+ *
* @param x the x coordinate
* @param y the y coordinate
* @param z the z coordinate
* @return the distance to the sphere
*/
+ @Override
+ public double signedDistance(double x, double y, double z) {
+ Point p = new Point(x, y, z);
+ return signedDistance(p);
+ }
+
+ /**
+ * Get the shortest absolute distance between the surface of this infinite cylinder and a point.
+ * @param x the x coordinate
+ * @param y the y coordinate
+ * @param z the z coordinate
+ * @return the perpendicular distance
+ */
+ @Override
public double distance(double x, double y, double z) {
Point p = new Point(x, y, z);
- return distance(p);
+ return Math.abs(signedDistance(p));
+ }
+
+ /**
+ * Is the point inside the sphere?
+ * @param x the x coordinate
+ * @param y the y coordinate
+ * @param z the z coordinate
+ * @return true if the point is inside the sphere.
+ */
+ public boolean isInside(double x, double y, double z) {
+ return signedDistance(x, y, z) < 0;
+ }
+
+ @Override
+ public double interpolate(Point p1, Point p2, Point p) {
+ throw new UnsupportedOperationException("[interpolate] Not implemented yet for a Sphere object.");
+ }
+
+ /**
+ * Check whether a segment intersects the sphere
+ *
+ * @param x1 x coordinate of one end of segment
+ * @param y1 y coordinate of one end of segment
+ * @param z1 z coordinate of one end of segment
+ * @param x2 x coordinate of other end of segment
+ * @param y2 y coordinate of other end of segment
+ * @param z2 z coordinate of other end of segment
+ * @return true if the segment intersects the sphere
+ */
+ public boolean segmentIntersects(double x1, double y1, double z1, double x2, double y2, double z2) {
+ return (distToSegment(0, 0, 0, x1, y1, z1, x2, y2, z2) < _radius);
+ }
+
+ /**
+ * The closest distance of a line segment to a point
+ *
+ * @param px x coordinate of point
+ * @param py y coordinate of point
+ * @param pz z coordinate of point
+ * @param x1 x coordinate of one end of segment
+ * @param y1 y coordinate of one end of segment
+ * @param z1 z coordinate of one end of segment
+ * @param x2 x coordinate of other end of segment
+ * @param y2 y coordinate of other end of segment
+ * @param z2 z coordinate of other end of segment
+ * @return the closest distance of the segment to point p
+ */
+ private double distToSegment(double px, double py, double pz, double x1, double y1, double z1, double x2, double y2,
+ double z2) {
+
+ double line_dist = distSq(x1, y1, z1, x2, y2, z2);
+ if (line_dist == 0) {
+ return distSq(px, py, pz, x1, y1, z1);
+ }
+ double t = ((px - x1) * (x2 - x1) + (py - y1) * (y2 - y1) + (pz - z1) * (z2 - z1)) / line_dist;
+ t = Math.max(0, Math.min(1, t));
+ return Math.sqrt(distSq(px, py, pz, x1 + t * (x2 - x1), y1 + t * (y2 - y1), z1 + t * (z2 - z1)));
+ }
+
+ // the square of the distance between two points
+ private double distSq(double x1, double y1, double z1, double x2, double y2, double z2) {
+ double dx = x2 - x1;
+ double dy = y2 - y1;
+ double dz = z2 - z1;
+ return dx * dx + dy * dy + dz * dz;
+
}
}
diff --git a/common-tools/cnuphys/swimmer/src/main/java/cnuphys/adaptiveSwim/test/AdaptiveBeamlineSwimTest.java b/common-tools/cnuphys/swimmer/src/main/java/cnuphys/adaptiveSwim/test/AdaptiveBeamlineSwimTest.java
deleted file mode 100644
index 8eb2d2615c..0000000000
--- a/common-tools/cnuphys/swimmer/src/main/java/cnuphys/adaptiveSwim/test/AdaptiveBeamlineSwimTest.java
+++ /dev/null
@@ -1,234 +0,0 @@
-package cnuphys.adaptiveSwim.test;
-
-import java.util.Random;
-
-import cnuphys.adaptiveSwim.AdaptiveSwimException;
-import cnuphys.adaptiveSwim.AdaptiveSwimResult;
-import cnuphys.adaptiveSwim.AdaptiveSwimmer;
-import cnuphys.magfield.MagneticFields;
-import cnuphys.magfield.MagneticFields.FieldType;
-import cnuphys.rk4.RungeKuttaException;
-import cnuphys.swim.SwimTrajectory;
-import cnuphys.swim.Swimmer;
-
-public class AdaptiveBeamlineSwimTest {
-
- //usual small number cutoff
- private static final double SMALL = 1.0e-8;
-
- public static void beamLineTest() {
- double accuracy = 5e-3; // m
- double eps = 1.0e-5;
- double zTarg = 5; // m
-
- LineTestPlotGrid plotGrid = new LineTestPlotGrid(zTarg, accuracy, eps);
- plotGrid.setVisible(true);
-
- long seed = 37552875;
- Random rand = new Random(seed);
- // int num = 62500;
- int num = 100;
- int n0 = 0;
-
-
- System.out.println("TEST swimming to the beam line");
- MagneticFields.getInstance().setActiveField(FieldType.COMPOSITE);
-
- double maxPathLength = 8; // m
-
-
- double stepsizeAdaptive = 0.01; // starting
-
- Swimmer swimmer = new Swimmer();
- AdaptiveSwimmer adaptiveSwimmer = new AdaptiveSwimmer();
- AdaptiveSwimResult oldResult = new AdaptiveSwimResult(false);
- AdaptiveSwimResult newResult = new AdaptiveSwimResult(true);
-
- //ranges of variables
-
- double xoMin = -0.1;
- double xoMax = 0.1;
- double yoMin = -0.1;
- double yoMax = 0.1;
- double zoMin = 0;
- double zoMax = 0;
- double pMin = 5.0;
- double pMax = 8.0;
- double thetaMin = 20.0;
- double thetaMax = 35.0;
-
- double phiMin = 0;
- double phiMax = 360;
-
-
- double hdata[] = new double[3];
-
- //for the path length differences
- double sDiffSum = 0;
- double worstSDiff = 0;
- int worstSIndex = -1;
-
- //final z diff
- double zDiffSum = 0;
- double worstZDiff = 0;
- int worstZIndex = -1;
-
- //final pos diff
- double rDiffSum = 0;
- double worstRDiff = 0;
- int worstRIndex = -1;
-
- //final phi diff
- double phiDiffSum = 0;
- double worstPhiDiff = 0;
- int worstPhiIndex = -1;
-
- //final bdl diff
- double bdlDiffSum = 0;
- double worstBdlDiff = 0;
- int worstBdlIndex = -1;
-
-
- SwimTrajectory traj = null;
-
- for (int i = n0; i < num; i++) {
-
- if (((i+1) % 1000) == 0) {
- System.out.println((i+1) + "/" + num);
- }
-
- double xo = randVal(rand, xoMin, xoMax);
- double yo = randVal(rand, yoMin, yoMax);
- double zo = randVal(rand, zoMin, zoMax);
- double p = randVal(rand, pMin, pMax);
- double theta = randVal(rand, thetaMin, thetaMax);
- double phi = randVal(rand, phiMin, phiMax);
-
- int charge = randCharge(rand);
-
- //use each swimmer to swim forwad, the reverse and swim backward
-
- //old swimmer
- try {
- traj = swimmer.swim(charge, xo, yo, zo, p, theta, phi, zTarg, accuracy, maxPathLength, stepsizeAdaptive, Swimmer.CLAS_Tolerance, hdata);
- traj.computeBDL(swimmer.getProbe());
- oldResult.setTrajectory(traj);
- //cause this old swimmer does not call init
- oldResult.setInitialValues(charge, xo, yo, zo, p, theta, phi);
- } catch (RungeKuttaException e) {
- e.printStackTrace();
- }
-
-
- //new swimmer
- try {
- adaptiveSwimmer.swimZ(charge, xo, yo, zo, p, theta, phi, zTarg, accuracy, maxPathLength, stepsizeAdaptive, eps, newResult);
- newResult.getTrajectory().computeBDL(swimmer.getProbe());
- } catch (AdaptiveSwimException e) {
- e.printStackTrace();
- }
-
- AdaptiveResultDiff diff = new AdaptiveResultDiff(oldResult, newResult);
-
- plotGrid.update(diff);
-
- boolean newWorst = false;
-
- //path length diff
- double sdiff = diff.getFinalAbsSDiff();
- sDiffSum += sdiff;
-
- if (sdiff > worstSDiff) {
- newWorst = true;
- worstSDiff = sdiff;
- worstSIndex = i;
- }
-
- //final z diff
- double zdiff = diff.getFinalAbsZDiff();
- zDiffSum += zdiff;
-
- if (zdiff > worstZDiff) {
- newWorst = true;
- worstZDiff = zdiff;
- worstZIndex = i;
- }
-
- //final position diff
- double rdiff = diff.getFinalAbsPositionDiff();
- rDiffSum += rdiff;
-
- if (rdiff > worstRDiff) {
- newWorst = true;
- worstRDiff = rdiff;
- worstRIndex = i;
-
- }
-
- //phi diff
- double phiDiff = Math.abs(diff.getFinalPhiDiff());
- phiDiffSum += phiDiff;
-
- if (phiDiff > worstPhiDiff) {
- newWorst = true;
- worstPhiDiff = phiDiff;
- worstPhiIndex = i;
-
- }
-
- //bdl diff
- double bdlDiff = Math.abs(diff.getBDLDiff());
- bdlDiffSum += bdlDiff;
-
- if (bdlDiff > worstBdlDiff) {
- newWorst = true;
- worstBdlDiff = bdlDiff;
- worstBdlIndex = i;
-
- }
-
-
- if (newWorst) {
- System.out.println("INDEX: " + i);
- oldResult.printOut(System.out, " new worst sector Z test (old)");
- newResult.printOut(System.out, " new worst sector Z test (new)");
- }
-
- }
-
-
- //print last
-
- System.out.println("Avg sdiff: " + (sDiffSum/num) + " worst: " + worstSDiff + " at index: " + worstSIndex);
- System.out.println("Avg zdiff: " + (zDiffSum/num) + " worst: " + worstZDiff + " at index: " + worstZIndex);
- System.out.println("Avg rdiff: " + (rDiffSum/num) + " worst: " + worstRDiff + " at index: " + worstRIndex);
- System.out.println("Avg phidiff: " + (phiDiffSum/num) + " worst: " + worstPhiDiff + " at index: " + worstPhiIndex);
- System.out.println("Avg bdldiff: " + (bdlDiffSum/num) + " worst: " + worstBdlDiff + " at index: " + worstBdlIndex);
-
- System.out.println("Done with z-test");
- }
-
-
- //used to generate a random number in a range
- private static double randVal(Random rand, double vmin, double vmax) {
- double del = vmax - vmin;
-
- if (Math.abs(del) < SMALL) {
- return vmin;
- } else {
- return vmin + del * rand.nextDouble();
- }
- }
-
- private static int randCharge(Random rand) {
- double v = rand.nextDouble();
- return (v < 0.5) ? -1 : 1;
- }
-
-
- //get a random sector 1..6
- private static int randSector(Random rand) {
- return rand.nextInt(6) + 1;
- }
-
-}
diff --git a/common-tools/cnuphys/swimmer/src/main/java/cnuphys/adaptiveSwim/test/AdaptiveResultDiff.java b/common-tools/cnuphys/swimmer/src/main/java/cnuphys/adaptiveSwim/test/AdaptiveResultDiff.java
deleted file mode 100644
index fa53193abc..0000000000
--- a/common-tools/cnuphys/swimmer/src/main/java/cnuphys/adaptiveSwim/test/AdaptiveResultDiff.java
+++ /dev/null
@@ -1,137 +0,0 @@
-package cnuphys.adaptiveSwim.test;
-
-import cnuphys.adaptiveSwim.AdaptiveSwimResult;
-
-public class AdaptiveResultDiff {
-
- /**
- * Used for debugging, to compare the difference between two swims
- */
-
- //the two results
- public AdaptiveSwimResult result1;
- public AdaptiveSwimResult result2;
-
- private double _diff[] = new double[6];
-
- //final absolute position and momentum (actually t) differences
- private double _finalAbsRDiff;
- private double _finalAbsPDiff;
-
- //diff in final path length
- private double _sDiff;
-
- public AdaptiveResultDiff(AdaptiveSwimResult res1, AdaptiveSwimResult res2) {
- result1 = res1;
- result2 = res2;
-
- _sDiff = result2.getFinalS() - result1.getFinalS();
-
- double uf1[] = res1.getUf();
- double uf2[] = res2.getUf();
-
- for (int i = 0; i < 6; i++) {
- _diff[i] = uf2[i] - uf1[i];
-
- if (i < 3) {
- _finalAbsRDiff += (_diff[i] * _diff[i]);
- } else {
- _finalAbsPDiff += (_diff[i] * _diff[i]);
- }
- }
-
- _finalAbsRDiff = Math.sqrt(_finalAbsRDiff);
- _finalAbsPDiff = Math.sqrt(_finalAbsPDiff);
- }
-
- /**
- * Get the signed difference between the final path lengths (2-1)
- *
- * @return the signed difference between the final path lengths
- */
- public double getFinalSDiff() {
- return _sDiff;
- }
-
- /**
- * Get the absolute difference between the final path lengths (2-1)
- *
- * @return the signed difference between the final path lengths
- */
- public double getFinalAbsSDiff() {
- return Math.abs(_sDiff);
- }
- /**
- * Get the signed difference in the final state vectors 2 - 1
- *
- * @return the signed difference in the final state vectors
- */
- public double[] getDiff() {
- return _diff;
- }
-
- public double getFinalAbsPositionDiff() {
- return _finalAbsRDiff;
- }
-
- public double getFinalAbsMomentumDiff() {
- return _finalAbsPDiff;
- }
-
- /**
- * Get the signed final difference in z, z2 - z1
- * @return the signed final difference in z
- */
- public double getFinalXDiff() {
- return _diff[0];
- }
-
- /**
- * Get the signed final difference in z, z2 - z1
- * @return the signed final difference in z
- */
- public double getFinalYDiff() {
- return _diff[1];
- }
-
- /**
- * Get the signed final difference in z, z2 - z1
- * @return the signed final difference in z
- */
- public double getFinalZDiff() {
- return _diff[2];
- }
-
- /**
- * Get the signed final difference in z, z2 - z1
- * @return the signed final difference in z
- */
- public double getFinalAbsZDiff() {
- return Math.abs(_diff[2]);
- }
-
- /**
- * Get the signed final difference in theta, 2 - 1
- * @return the signed final difference in theta (degrees)
- */
- public double getFinalThetaDiff() {
- return result2.getFinalTheta() - result1.getFinalTheta();
- }
-
- /**
- * Get the signed final difference in theta, 2 - 1
- * @return the signed final difference in theta (degrees)
- */
- public double getFinalPhiDiff() {
- return result2.getFinalPhi() - result1.getFinalPhi();
- }
-
- /**
- * Get the signed difference in BDL
- * @return the signed difference in BDL
- */
- public double getBDLDiff() {
- return result2.getTrajectory().getComputedBDL() - result1.getTrajectory().getComputedBDL();
- }
-
-}
diff --git a/common-tools/cnuphys/swimmer/src/main/java/cnuphys/adaptiveSwim/test/AdaptiveSectorSwimTest.java b/common-tools/cnuphys/swimmer/src/main/java/cnuphys/adaptiveSwim/test/AdaptiveSectorSwimTest.java
deleted file mode 100644
index 27bdd6fa42..0000000000
--- a/common-tools/cnuphys/swimmer/src/main/java/cnuphys/adaptiveSwim/test/AdaptiveSectorSwimTest.java
+++ /dev/null
@@ -1,238 +0,0 @@
-package cnuphys.adaptiveSwim.test;
-
-import java.util.Random;
-
-import cnuphys.adaptiveSwim.AdaptiveSwimException;
-import cnuphys.adaptiveSwim.AdaptiveSwimResult;
-import cnuphys.adaptiveSwim.AdaptiveSwimmer;
-import cnuphys.magfield.MagneticFields;
-import cnuphys.magfield.MagneticFields.FieldType;
-import cnuphys.magfield.RotatedCompositeProbe;
-import cnuphys.rk4.RungeKuttaException;
-import cnuphys.swim.SwimTrajectory;
-import cnuphys.swim.Swimmer;
-
-public class AdaptiveSectorSwimTest {
-
- //usual small number cutoff
- private static final double SMALL = 1.0e-8;
-
-
- //test swim to fixed z
- public static void zTest() {
-
- double accuracy = 5e-3; // m
- double eps = 1.0e-5;
- double zTarg = 5; // m
- ZTestPlotGrid plotGrid = new ZTestPlotGrid(zTarg, accuracy, eps);
- plotGrid.setVisible(true);
-
- long seed = 37552875;
- Random rand = new Random(seed);
- int num = 100000;
- int n0 = 0;
-
-
- System.out.println("TEST swimming to a fixed z");
- MagneticFields.getInstance().setActiveField(FieldType.COMPOSITEROTATED);
-
- double maxPathLength = 8; // m
-
-
- double stepsizeAdaptive = 0.01; // starting
-
- Swimmer swimmer = new Swimmer();
- AdaptiveSwimmer adaptiveSwimmer = new AdaptiveSwimmer();
- AdaptiveSwimResult oldResult = new AdaptiveSwimResult(false);
- AdaptiveSwimResult newResult = new AdaptiveSwimResult(true);
-
-//ranges of variables
-
- double xoMin = 0;
- double xoMax = 0;
- double yoMin = 0;
- double yoMax = 0;
- double zoMin = 0;
- double zoMax = 0;
- double pMin = 5.0;
- double pMax = 8.0;
- double thetaMin = 20.0;
- double thetaMax = 35.0;
-
- double phiMin =-20;
- double phiMax = 20;
-
-
- int sector = 0;
-
-
- double hdata[] = new double[3];
-
- //for the path length differences
- double sDiffSum = 0;
- double worstSDiff = 0;
- int worstSIndex = -1;
-
- //final z diff
- double zDiffSum = 0;
- double worstZDiff = 0;
- int worstZIndex = -1;
-
- //final pos diff
- double rDiffSum = 0;
- double worstRDiff = 0;
- int worstRIndex = -1;
-
- //final phi diff
- double phiDiffSum = 0;
- double worstPhiDiff = 0;
- int worstPhiIndex = -1;
-
- //final bdl diff
- double bdlDiffSum = 0;
- double worstBdlDiff = 0;
- int worstBdlIndex = -1;
-
-
- SwimTrajectory traj = null;
-
- for (int i = n0; i < num; i++) {
-
- if (((i+1) % 1000) == 0) {
- System.out.println((i+1) + "/" + num);
- }
-
- double xo = randVal(rand, xoMin, xoMax);
- double yo = randVal(rand, yoMin, yoMax);
- double zo = randVal(rand, zoMin, zoMax);
- double p = randVal(rand, pMin, pMax);
- double theta = randVal(rand, thetaMin, thetaMax);
- double phi = randVal(rand, phiMin, phiMax);
-
- sector = randSector(rand);
- int charge = randCharge(rand);
-
-
-
- //old swimmer
- try {
- traj = swimmer.sectorSwim(sector, charge, xo, yo, zo, p, theta, phi, zTarg, accuracy, maxPathLength, stepsizeAdaptive, Swimmer.CLAS_Tolerance, hdata);
- traj.sectorComputeBDL(sector, (RotatedCompositeProbe)(swimmer.getProbe()));
- oldResult.setTrajectory(traj);
- //cause this old swimmer does not call init
- oldResult.setInitialValues(charge, xo, yo, zo, p, theta, phi);
- } catch (RungeKuttaException e) {
- e.printStackTrace();
- }
-
-
- //new swimmer
- try {
- adaptiveSwimmer.sectorSwimZ(sector, charge, xo, yo, zo, p, theta, phi, zTarg, accuracy, maxPathLength, stepsizeAdaptive, eps, newResult);
- newResult.getTrajectory().sectorComputeBDL(sector, (RotatedCompositeProbe)(swimmer.getProbe()));
- } catch (AdaptiveSwimException e) {
- e.printStackTrace();
- }
-
- AdaptiveResultDiff diff = new AdaptiveResultDiff(oldResult, newResult);
-
- plotGrid.update(diff);
-
- boolean newWorst = false;
-
- //path length diff
- double sdiff = diff.getFinalAbsSDiff();
- sDiffSum += sdiff;
-
- if (sdiff > worstSDiff) {
- newWorst = true;
- worstSDiff = sdiff;
- worstSIndex = i;
- }
-
- //final z diff
- double zdiff = diff.getFinalAbsZDiff();
- zDiffSum += zdiff;
-
- if (zdiff > worstZDiff) {
- newWorst = true;
- worstZDiff = zdiff;
- worstZIndex = i;
- }
-
- //final position diff
- double rdiff = diff.getFinalAbsPositionDiff();
- rDiffSum += rdiff;
-
- if (rdiff > worstRDiff) {
- newWorst = true;
- worstRDiff = rdiff;
- worstRIndex = i;
-
- }
-
- //phi diff
- double phiDiff = Math.abs(diff.getFinalPhiDiff());
- phiDiffSum += phiDiff;
-
- if (phiDiff > worstPhiDiff) {
- newWorst = true;
- worstPhiDiff = phiDiff;
- worstPhiIndex = i;
-
- }
-
- //bdl diff
- double bdlDiff = Math.abs(diff.getBDLDiff());
- bdlDiffSum += bdlDiff;
-
- if (bdlDiff > worstBdlDiff) {
- newWorst = true;
- worstBdlDiff = bdlDiff;
- worstBdlIndex = i;
-
- }
-
-
- if (newWorst) {
- System.out.println("INDEX: " + i);
- oldResult.printOut(System.out, " new worst sector Z test (old)");
- newResult.printOut(System.out, " new worst sector Z test (new)");
- }
-
- }
-
-
- //print last
-
- System.out.println("Avg sdiff: " + (sDiffSum/num) + " worst: " + worstSDiff + " at index: " + worstSIndex);
- System.out.println("Avg zdiff: " + (zDiffSum/num) + " worst: " + worstZDiff + " at index: " + worstZIndex);
- System.out.println("Avg rdiff: " + (rDiffSum/num) + " worst: " + worstRDiff + " at index: " + worstRIndex);
- System.out.println("Avg phidiff: " + (phiDiffSum/num) + " worst: " + worstPhiDiff + " at index: " + worstPhiIndex);
- System.out.println("Avg bdldiff: " + (bdlDiffSum/num) + " worst: " + worstBdlDiff + " at index: " + worstBdlIndex);
-
- System.out.println("Done with z-test");
- }
-
- //used to generate a random number in a range
- private static double randVal(Random rand, double vmin, double vmax) {
- double del = vmax - vmin;
-
- if (Math.abs(del) < SMALL) {
- return vmin;
- } else {
- return vmin + del * rand.nextDouble();
- }
- }
-
- private static int randCharge(Random rand) {
- double v = rand.nextDouble();
- return (v < 0.5) ? -1 : 1;
- }
-
-
- //get a random sector 1..6
- private static int randSector(Random rand) {
- return rand.nextInt(6) + 1;
- }
-}
diff --git a/common-tools/cnuphys/swimmer/src/main/java/cnuphys/adaptiveSwim/test/AdaptiveTests.java b/common-tools/cnuphys/swimmer/src/main/java/cnuphys/adaptiveSwim/test/AdaptiveTests.java
deleted file mode 100644
index 93dfe1ebea..0000000000
--- a/common-tools/cnuphys/swimmer/src/main/java/cnuphys/adaptiveSwim/test/AdaptiveTests.java
+++ /dev/null
@@ -1,698 +0,0 @@
-package cnuphys.adaptiveSwim.test;
-
-import java.util.Random;
-
-import cnuphys.adaptiveSwim.AdaptiveSwimException;
-import cnuphys.adaptiveSwim.AdaptiveSwimResult;
-import cnuphys.adaptiveSwim.AdaptiveSwimmer;
-import cnuphys.adaptiveSwim.geometry.Cylinder;
-import cnuphys.adaptiveSwim.geometry.Line;
-import cnuphys.adaptiveSwim.geometry.Plane;
-import cnuphys.adaptiveSwim.geometry.Point;
-import cnuphys.adaptiveSwim.geometry.Vector;
-import cnuphys.magfield.FastMath;
-import cnuphys.magfield.MagneticFields;
-import cnuphys.magfield.MagneticFields.FieldType;
-import cnuphys.rk4.RungeKuttaException;
-import cnuphys.swim.SwimTrajectory;
-import cnuphys.swim.Swimmer;
-
-public class AdaptiveTests {
-
- /** Test the basic swim to a final pathlength */
- public static void noStopperTest() {
-
- // test basic pathlength swimmer to be used by ced
-
- MagneticFields.getInstance().setActiveField(FieldType.COMPOSITE);
- AdaptiveSwimmer adaptiveSwimmer = new AdaptiveSwimmer();
-
- double stepsizeAdaptive = 0.01; // starting
- double xo = 0;
- double yo = 0;
- double zo = 0;
- int Q = 1;
- double maxPathLength = 5.;
- double theta = 15;
- double phi = 0;
- double p = 2;
- double eps = 1.0e-6;
-
- AdaptiveSwimResult result = new AdaptiveSwimResult(true);
-
- try {
- adaptiveSwimmer.swim(Q, xo, yo, zo, p, theta, phi, maxPathLength, stepsizeAdaptive, eps, result);
- result.printOut(System.out, "Base S Swimmer");
- } catch (AdaptiveSwimException e) {
- e.printStackTrace();
- }
-
- }
-
-
- /** Test the swim to a line */
- public static void lineTest() {
- Line targetLine = new Line(new Point(1, 0, 0), new Point(1, 0, 1));
-
- MagneticFields.getInstance().setActiveField(FieldType.TORUS);
- AdaptiveSwimmer adaptiveSwimmer = new AdaptiveSwimmer();
-
- double stepsizeAdaptive = 0.01; // starting
- double xo = 0;
- double yo = 0;
- double zo = 0;
- int Q = 1;
- double maxPathLength = 8.;
- double theta = 25;
- double phi = 0;
- double p = 1;
- double eps = 1.0e-6;
- double accuracy = 1.0e-5; //m
-
- AdaptiveSwimResult result = new AdaptiveSwimResult(true);
-
- try {
- adaptiveSwimmer.swimLine(Q, xo, yo, zo, p, theta, phi, targetLine, accuracy, maxPathLength, stepsizeAdaptive, eps, result);
- result.printOut(System.out, "Line Test");
- } catch (AdaptiveSwimException e) {
- e.printStackTrace();
- }
-
- }
-
-
- /** Test retracing a swim */
- public static void retraceTest() {
-
- long seed = 9459363;
- Random rand = new Random(seed);
- int num = 10000;
-// num = 1;
- int n0 = 0;
-
- int status[] = new int[num];
-
- InitialValues[] ivals = InitialValues.getInitialValues(rand, num, -1, false, 0., 0., 0., 0., 0., 0., 0.5, 5.0, 10., 25., -30., 30.);
-
- MagneticFields.getInstance().setActiveField(FieldType.COMPOSITE);
- AdaptiveSwimmer adaptiveSwimmer = new AdaptiveSwimmer();
- AdaptiveSwimResult result = new AdaptiveSwimResult(true);
-
- double stepsizeAdaptive = 0.01; // starting
-
- double maxPathLength = 8; // m
- double accuracy = 1e-5; // m
- double eps = 1.0e-6;
-
-
- // create a plane last layer reg 3
- double r = 5.3092; // m
- double x1 = r * Math.sin(Math.toRadians(25));
- double y1 = 0;
- double z1 = r * Math.cos(Math.toRadians(25));
- Point p1 = new Point(x1, y1, z1);
- Vector v = new Vector(-x1, 0, -z1);
- Plane plane = new Plane(v, p1);
-
- int goodCount = 0;
-
- try {
-
- InitialValues iv = null;
- double[] uf = null;
-
- double sum = 0;
- double drMax = 0;
- int iMax = -1;
-
- for (int i = n0; i < num; i++) {
- iv = ivals[i];
- result.setInitialValies(iv);
-
- adaptiveSwimmer.swimPlane(iv.charge, iv.xo, iv.yo, iv.zo, iv.p, iv.theta, iv.phi, plane, accuracy,
- maxPathLength, stepsizeAdaptive, eps, result);
-
-
- uf = result.getUf();
- status[i] = result.getStatus();
- if (status[i] == AdaptiveSwimmer.SWIM_SUCCESS) {
- goodCount++;
- //try to swim back
-
- InitialValues revIv = result.retrace();
-
-
-// adaptiveSwimmer.swimZ(revIv.charge, revIv.xo, revIv.yo, revIv.zo, revIv.p, revIv.theta, revIv.phi, zTarg, accuracy, maxPathLength, stepsizeAdaptive, eps, result);
-// adaptiveSwimmer.swim(revIv.charge, revIv.xo, revIv.yo, revIv.zo, revIv.p, revIv.theta, revIv.phi, result.getFinalS(), stepsizeAdaptive, eps, result);
- adaptiveSwimmer.swimS(revIv.charge, revIv.xo, revIv.yo, revIv.zo, revIv.p, revIv.theta, revIv.phi, accuracy, result.getFinalS(), stepsizeAdaptive, eps, result);
-
- double dr = FastMath.sqrt(uf[0]*uf[0] + uf[1]*uf[1] + uf[2]*uf[2]);
-
- if (i == 711) {
- System.out.println("BACKWARD " + revIv);
- result.printOut(System.out, "Retrace swim", true);
- System.out.println("dr = " + dr);
- }
-
- sum += dr;
-
- if (dr > drMax) {
- drMax = dr;
- iMax = i;
- }
- }
- else {
- // System.out.println("Bad swim to plane for i = " + i + " final pathlength = " + result.getFinalS());
- }
- } //for
-
- System.out.println("average dr = " + (sum/goodCount) + " max dr: " + drMax + " at i = " + iMax );
-
- } catch (AdaptiveSwimException e) {
- e.printStackTrace();
- }
-
-
-
-
- }
-
- //ztest for time
- public static void TIMEzTest() {
- long seed = 9479365;
- Random rand = new Random(seed);
- int num = 100000;
- int n0 = 0;
-
- //the initial values
- InitialValues[] ivals = InitialValues.getInitialValues(rand, num, 1, true,
- -0.05, -0.05, -0.05, //vertex mins
- 0.05, 0.05, 0.05, //vertex max
- 5, 8.0, //momentum range
- 20., 35., //theta range
- 0., 360. //phi range
- );
-
- System.out.println("TEST swimming to a fixed z");
- MagneticFields.getInstance().setActiveField(FieldType.COMPOSITE);
-
- double maxPathLength = 8; // m
- double accuracy = 5e-3; // m
- double zTarg = 5; // m
- double eps = 1.0e-5;
- long time;
-
- double stepsizeAdaptive = 0.01; // starting
-
- Swimmer swimmer = new Swimmer();
- AdaptiveSwimmer adaptiveSwimmer = new AdaptiveSwimmer();
- AdaptiveSwimResult oldResult = new AdaptiveSwimResult(false);
- AdaptiveSwimResult newResult = new AdaptiveSwimResult(false);
-
-
- double hdata[] = new double[3];
-
- InitialValues iv = null;
- time = System.currentTimeMillis();
-
- SwimTrajectory traj = null;
-
- //old swimmer
- for (int i = n0; i < num; i++) {
- iv = ivals[i];
-
- try {
- traj = swimmer.swim(iv.charge, iv.xo, iv.yo, iv.zo, iv.p, iv.theta, iv.phi, zTarg, accuracy, maxPathLength, stepsizeAdaptive,
- Swimmer.CLAS_Tolerance, hdata);
- } catch (RungeKuttaException e) {
- e.printStackTrace();
- }
-
- //cause this old swimmer does not call init
- oldResult.setInitialValues(iv.charge, iv.xo, iv.yo, iv.zo, iv.p, iv.theta, iv.phi);
-
- }
-
- traj.computeBDL(swimmer.getProbe());
- oldResult.setTrajectory(traj);
- time = System.currentTimeMillis() - time;
- oldResult.printOut(System.out, "Z test (old)");
- System.out.println(
- String.format("[OLD] Adaptive time: %-7.3f",
- (time) / 1000.));
-
- time = System.currentTimeMillis();
- //new swimmer
- for (int i = n0; i < num; i++) {
- iv = ivals[i];
-
- try {
- adaptiveSwimmer.swimZ(iv.charge, iv.xo, iv.yo, iv.zo, iv.p, iv.theta, iv.phi, zTarg, accuracy,
- maxPathLength, stepsizeAdaptive, eps, newResult);
- } catch (AdaptiveSwimException e) {
- e.printStackTrace();
- }
-
- }
-
- time = System.currentTimeMillis() - time;
- newResult.printOut(System.out, "Z test (new)");
- System.out.println(
- String.format("[NEW] Adaptive time: %-7.3f",
- (time) / 1000.));
-
- System.out.println("Done with z-test");
- }
-
-
- //test swim to fixed z
- public static void xxxxxxzTest() {
- long seed = 9479365;
- Random rand = new Random(seed);
- int num = 100;
- int n0 = 0;
-
-
- System.out.println("TEST swimming to a fixed z");
- MagneticFields.getInstance().setActiveField(FieldType.COMPOSITE);
-
- double maxPathLength = 8; // m
- double accuracy = 5e-3; // m
- double zTarg = 5; // m
- double eps = 1.0e-5;
-
- double stepsizeAdaptive = 0.01; // starting
-
- Swimmer swimmer = new Swimmer();
- AdaptiveSwimmer adaptiveSwimmer = new AdaptiveSwimmer();
- AdaptiveSwimResult oldResult = new AdaptiveSwimResult(false);
- AdaptiveSwimResult newResult = new AdaptiveSwimResult(false);
-
-
- double hdata[] = new double[3];
-
- SwimTrajectory traj = null;
-
- InitialValues iv = new InitialValues();
-
- for (int i = n0; i < num; i++) {
- InitialValues.randomInitVal(rand, iv, 1, true,
- -0.05, -0.05, -0.05, //vertex mins
- 0.05, 0.05, 0.05, //vertex max
- 5, 8.0, //momentum range
- 20., 35., //theta range
- 0., 360. //phi range
- );
-
- //old swimmer
- try {
- traj = swimmer.swim(iv.charge, iv.xo, iv.yo, iv.zo, iv.p, iv.theta, iv.phi, zTarg, accuracy, maxPathLength, stepsizeAdaptive,
- Swimmer.CLAS_Tolerance, hdata);
- } catch (RungeKuttaException e) {
- e.printStackTrace();
- }
-
- //cause this old swimmer does not call init
- oldResult.setInitialValues(iv.charge, iv.xo, iv.yo, iv.zo, iv.p, iv.theta, iv.phi);
-
- //new swimmer
- try {
- adaptiveSwimmer.swimZ(iv.charge, iv.xo, iv.yo, iv.zo, iv.p, iv.theta, iv.phi, zTarg, accuracy,
- maxPathLength, stepsizeAdaptive, eps, newResult);
- } catch (AdaptiveSwimException e) {
- e.printStackTrace();
- }
-
- }
-
-
- //print last
- traj.computeBDL(swimmer.getProbe());
- oldResult.setTrajectory(traj);
- oldResult.printOut(System.out, "Z test (old)");
-
-
- newResult.printOut(System.out, "Z test (new)");
-
- System.out.println("Done with z-test");
- }
-
- /** Test swimming to a fixed rho */
- public static void rhoTest() {
-
- long seed = 9459363;
- Random rand = new Random(seed);
- int num = 100000;
-// num = 1;
- int n0 = 0;
-
- InitialValues[] ivals = InitialValues.getInitialValues(rand, num, 1, true, 0., 0., 0., 0., 0., 0., 0.25, 1.0, 40., 70., 0., 360.);
-
- System.out.println("TEST swimming to a fixed rho");
- MagneticFields.getInstance().setActiveField(FieldType.SOLENOID);
-
- double stepsizeAdaptive = 0.01; // starting
-
- double maxPathLength = 3; // m
- double accuracy = 5e-3; // m
- double rhoTarg = 0.30; // m
- double eps = 1.0e-6;
-
- AdaptiveSwimResult oldResult = new AdaptiveSwimResult(false);
- AdaptiveSwimResult newResult = new AdaptiveSwimResult(false);
-
- // generate some random initial conditions
-
- int adaptStatus[] = new int[num];
-
- long time;
- double rhof;
- double sum;
- double delMax;
- Swimmer swimmer = new Swimmer();
- AdaptiveSwimmer adaptiveSwimmer = new AdaptiveSwimmer();
- int badStatusCount;
-
- int nsMax = 0;
-
- long nStepTotal = 0;
-
-// adaptive step
- try {
-
- sum = 0;
- badStatusCount = 0;
- delMax = Double.NEGATIVE_INFINITY;
- time = System.currentTimeMillis();
-
- InitialValues iv = null;
- for (int i = n0; i < num; i++) {
- iv = ivals[i];
-
- swimmer.swimRho(iv.charge, iv.xo, iv.yo, iv.zo, iv.p, iv.theta, iv.phi, rhoTarg, accuracy,
- maxPathLength, stepsizeAdaptive, Swimmer.CLAS_Tolerance, oldResult);
-
- //cause this old swimmer does not call init
- oldResult.setInitialValues(iv.charge, iv.xo, iv.yo, iv.zo, iv.p, iv.theta, iv.phi);
-
- rhof = Math.hypot(oldResult.getUf()[0], oldResult.getUf()[1]);
- double dd = Math.abs(rhoTarg - rhof);
- delMax = Math.max(delMax, dd);
-
- adaptStatus[i] = oldResult.getStatus();
- nStepTotal += oldResult.getNStep();
-
-
- nsMax = Math.max(nsMax, oldResult.getNStep());
-
- if (oldResult.getStatus() != AdaptiveSwimmer.SWIM_SUCCESS) {
- badStatusCount += 1;
- }
- else {
- sum += dd;
- }
- }
-
- time = System.currentTimeMillis() - time;
- oldResult.printOut(System.out, "Rho test (old)");
- System.out.println(
- String.format("Adaptive time: %-7.3f avg good delta = %-9.5f max delta = %-9.5f badStatCnt = %d",
- (time) / 1000., sum / (num - badStatusCount), delMax, badStatusCount));
- System.out.println("Adaptive Avg NS = " + (int) (((double) nStepTotal) / num) + " MAX NS: " + nsMax + "\n");
-
- } catch (RungeKuttaException e) {
- e.printStackTrace();
- System.exit(1);
- }
-
- // NEW adaptive step no traj
- try {
- nsMax = 0;
- sum = 0;
- badStatusCount = 0;
- delMax = Double.NEGATIVE_INFINITY;
- nStepTotal = 0;
-
- time = System.currentTimeMillis();
-
- InitialValues iv = null;
- for (int i = n0; i < num; i++) {
- iv = ivals[i];
-
- adaptiveSwimmer.swimRho(iv.charge, iv.xo, iv.yo, iv.zo, iv.p, iv.theta, iv.phi, rhoTarg, accuracy,
- maxPathLength, stepsizeAdaptive, eps, newResult);
-
- rhof = Math.hypot(newResult.getUf()[0], newResult.getUf()[1]);
- double dd = Math.abs(rhoTarg - rhof);
- delMax = Math.max(delMax, dd);
-
-
- if (newResult.getStatus() != adaptStatus[i]) {
- System.out.println("Adaptive v. NEW Adaptive Status differs for i = " + i + " adaptiveStat = "
- + adaptStatus[i] + " NEW adaptive status = " + newResult.getStatus());
- }
-
- nStepTotal += newResult.getNStep();
- nsMax = Math.max(nsMax, newResult.getNStep());
-
- if (newResult.getStatus() != AdaptiveSwimmer.SWIM_SUCCESS) {
- badStatusCount += 1;
- }
- else {
- sum += dd;
- }
- }
-
- time = System.currentTimeMillis() - time;
- newResult.printOut(System.out, "Rho test (new)");
- System.out.println(
- String.format("NEW Adaptive time: %-7.3f avg good delta = %-9.5f max delta = %-9.5f badStatCnt = %d",
- (time) / 1000., sum / (num - badStatusCount), delMax, badStatusCount));
- System.out.println("NEW Adaptive Avg NS = " + (int) (((double) nStepTotal) / num) + " MAX NS: " + nsMax + "\n");
-
- } catch (AdaptiveSwimException e) {
- e.printStackTrace();
- }
- }
-
- /**
- * Test swim to a plane
- */
- public static void planeTest() {
-
- System.out.println("swim to a plane");
-
- long seed = 9459363;
- Random rand = new Random(seed);
- int num = 1000;
-// num = 1;
- int n0 = 0;
-
- int status[] = new int[num];
- InitialValues[] ivals = InitialValues.getInitialValues(rand, num, -1, false, 0., 0., 0., 0., 0., 0., 0.5, 5.0, 10., 25., -30., 30.);
-
- MagneticFields.getInstance().setActiveField(FieldType.COMPOSITE);
- AdaptiveSwimmer adaptiveSwimmer = new AdaptiveSwimmer();
- AdaptiveSwimResult result = new AdaptiveSwimResult(true);
-
- double stepsizeAdaptive = 0.01; // starting
-
- double maxPathLength = 8; // m
- double accuracy = 1e-4; // m
- double eps = 1.0e-6;
-
-
- // create a plane last layer reg 3
- double r = 5.3092; // m
- double x1 = r * Math.sin(Math.toRadians(25));
- double y1 = 0;
- double z1 = r * Math.cos(Math.toRadians(25));
- Point p1 = new Point(x1, y1, z1);
- Vector v = new Vector(-x1, 0, -z1);
- Plane plane = new Plane(v, p1);
-
-
- try {
-
- InitialValues iv = null;
- double[] uf = null;
-
- for (int i = n0; i < num; i++) {
- iv = ivals[i];
-
-// if (i == 54) {
-// System.out.println();
-// System.out.println(iv);
-// }
-
- adaptiveSwimmer.swimPlane(iv.charge, iv.xo, iv.yo, iv.zo, iv.p, iv.theta, iv.phi, plane, accuracy,
- maxPathLength, stepsizeAdaptive, eps, result);
-
- uf = result.getUf();
- status[i] = result.getStatus();
- if (status[i] == AdaptiveSwimmer.SWIM_SUCCESS) {
-
- }
- else {
- System.out.println("Bad swim to plane for i = " + i + " final pathlength = " + result.getFinalS());
- }
-
-
- }
-
- result.printOut(System.out, "Swim to plane");
- System.out.println(String.format("Distance to plane: %-8.6f m" , Math.abs(plane.distance(uf[0], uf[1], uf[2]))));
- } catch (AdaptiveSwimException e) {
- e.printStackTrace();
- }
- }
-
- /** Test swimming to a cylinder */
- public static void sphereTest() {
-
- }
-
- /** Test swimming to a cylinder */
- public static void cylinderTest() {
-
- System.out.println("Cylinder around z axis should give us same result as rho swim.");
-
-
- long seed = 9459363;
- Random rand = new Random(seed);
- int num = 10000;
- // num = 1;
- int n0 = 0;
-
- InitialValues[] ivals = InitialValues.getInitialValues(rand, num, 1, true, 0., 0., 0., 0., 0., 0., 0.25, 1.0, 40., 70., 0., 360.);
-
- System.out.println("TEST swimming to a fixed rho");
- MagneticFields.getInstance().setActiveField(FieldType.SOLENOID);
-
- double stepsizeAdaptive = 0.01; // starting
-
- double maxPathLength = 3; // m
- double accuracy = 5e-3; // m
- double rhoTarg = 0.30; // m
- double eps = 1.0e-6;
-
- Cylinder targCyl = new Cylinder(new Line(new Point(0, 0, 0), new Point(0, 0, 1)), rhoTarg);
-
- AdaptiveSwimResult rResult = new AdaptiveSwimResult(true);
- AdaptiveSwimResult cResult = new AdaptiveSwimResult(true);
-
- // generate some random initial conditions
-
- int adaptStatus[] = new int[num];
-
- long time;
- double rhof;
- double sum;
- double delMax;
- AdaptiveSwimmer adaptiveSwimmer = new AdaptiveSwimmer();
- int badStatusCount;
-
- int nsMax = 0;
-
- long nStepTotal = 0;
-
-
- // rho swim
- try {
- nsMax = 0;
- sum = 0;
- badStatusCount = 0;
- delMax = Double.NEGATIVE_INFINITY;
- nStepTotal = 0;
-
- time = System.currentTimeMillis();
-
- InitialValues iv = null;
- for (int i = n0; i < num; i++) {
- iv = ivals[i];
-
- adaptiveSwimmer.swimRho(iv.charge, iv.xo, iv.yo, iv.zo, iv.p, iv.theta, iv.phi, rhoTarg, accuracy,
- maxPathLength, stepsizeAdaptive, eps, rResult);
-
- rhof = Math.hypot(rResult.getUf()[0], rResult.getUf()[1]);
- double dd = Math.abs(rhoTarg - rhof);
- delMax = Math.max(delMax, dd);
- sum += dd;
-
- adaptStatus[i] = rResult.getStatus();
-
- nStepTotal += rResult.getNStep();
- nsMax = Math.max(nsMax, rResult.getNStep());
-
- if (rResult.getStatus() != 0) {
- badStatusCount += 1;
- }
- }
-
- time = System.currentTimeMillis() - time;
-
- rResult.printOut(System.out, "Fixed rho in cylinder test");
-
- rResult.getTrajectory().print(System.out);
- System.out.println(
- String.format("Rho time: %-7.3f avg delta = %-9.5f max delta = %-9.5f badStatCnt = %d",
- (time) / 1000., sum / num, delMax, badStatusCount));
- System.out.println("Rho Avg NS = " + (int) (((double) nStepTotal) / num) + " MAX NS: " + nsMax + "\n");
-
- } catch (AdaptiveSwimException e) {
- e.printStackTrace();
- }
-
-
- //cylinder swim
- try {
- nsMax = 0;
- sum = 0;
- badStatusCount = 0;
- delMax = Double.NEGATIVE_INFINITY;
- nStepTotal = 0;
-
- time = System.currentTimeMillis();
-
- InitialValues iv = null;
- for (int i = n0; i < num; i++) {
- iv = ivals[i];
-
- adaptiveSwimmer.swimCylinder(iv.charge, iv.xo, iv.yo, iv.zo, iv.p, iv.theta, iv.phi, targCyl, accuracy,
- maxPathLength, stepsizeAdaptive, eps, cResult);
-
- double dd = targCyl.distance(cResult.getUf()[0], cResult.getUf()[1], cResult.getUf()[2]);
- dd = Math.abs(dd); //cyl dist can be neag if inside
- delMax = Math.max(delMax, dd);
- sum += dd;
-
- if (cResult.getStatus() != adaptStatus[i]) {
- System.out.println("Rho v. Cylinder Status differs for i = " + i + " rho statust = "
- + adaptStatus[i] + " cylinder status = " + cResult.getStatus());
- }
-
- nStepTotal += cResult.getNStep();
- nsMax = Math.max(nsMax, cResult.getNStep());
-
- if (cResult.getStatus() != 0) {
- badStatusCount += 1;
- }
- }
-
- time = System.currentTimeMillis() - time;
-
- cResult.printOut(System.out, "Fixed rho in cylinder test");
- cResult.getTrajectory().print(System.out);
-
- System.out.println(
- String.format("Cylinder time: %-7.3f avg delta = %-9.5f max delta = %-9.5f badStatCnt = %d",
- (time) / 1000., sum / num, delMax, badStatusCount));
- System.out.println("Cylinder Avg NS = " + (int) (((double) nStepTotal) / num) + " MAX NS: " + nsMax + "\n");
-
- } catch (AdaptiveSwimException e) {
- e.printStackTrace();
- }
-
- }
-
-}
diff --git a/common-tools/cnuphys/swimmer/src/main/java/cnuphys/adaptiveSwim/test/InitialValues.java b/common-tools/cnuphys/swimmer/src/main/java/cnuphys/adaptiveSwim/test/InitialValues.java
deleted file mode 100644
index 2e5884c842..0000000000
--- a/common-tools/cnuphys/swimmer/src/main/java/cnuphys/adaptiveSwim/test/InitialValues.java
+++ /dev/null
@@ -1,174 +0,0 @@
-package cnuphys.adaptiveSwim.test;
-
-import java.util.Random;
-
-/**
- * Hold the initial values of a swim
- * @author heddle
- *
- */
-public class InitialValues {
-
- //usual small number cutoff
- private static final double SMALL = 1.0e-8;
-
-
- /** The integer charge */
- public int charge;
-
- /** The coordinate x of the vertex in meters */
- public double xo;
-
- /** The y coordinate of the vertex in meters */
- public double yo;
-
- /** The z coordinate of the vertex in meters */
- public double zo;
-
- /** The momentum in GeV/c */
- public double p;
-
- /** The polar angle in degrees */
- public double theta;
-
- /** The azimuthal angle in degrees */
- public double phi;
-
- public InitialValues() {
-
- }
-
-
- public String toStringRaw() {
- return String.format("%-7.4f %-7.4f %-7.4f %-6.3f %-6.3f %-6.3f", xo, yo, zo, p, theta, phi);
- }
-
- /**
- * Store the initial conditions of a swim
- * @param charge The integer charge
- * @param xo The x coordinate of the vertex in meters
- * @param yo The y coordinate of the vertex in meters
- * @param zo The z coordinate of the vertex in meters
- * @param p The momentum in GeV/c
- * @param theta The polar angle in degrees
- * @param phi The azimuthal angle in degrees
- */
- public InitialValues(int charge, double xo, double yo, double zo, double p, double theta, double phi) {
- this.charge = charge;
- this.xo = xo;
- this.yo = yo;
- this.zo = zo;
- this.p = p;
- this.theta = theta;
- this.phi = phi;
- }
-
- /**
- * Copy constructor
- * @param src the source initial values
- */
- public InitialValues(InitialValues src) {
- this(src.charge, src.xo, src.yo, src.zo, src.p, src.theta, src.phi);
- }
-
- @Override
- public String toString() {
- return
- String.format("Q: %d\n", charge) +
- String.format("xo: %10.7e m\n", xo) +
- String.format("yo: %10.7e m\n", yo) +
- String.format("zo: %10.7e m\n", zo) +
- String.format("p: %10.7e GeV/c\n", p) +
- String.format("theta: %10.7f deg\n", theta) +
- String.format("phi: %10.7f deg", phi);
- }
-
-
- /**
- * For setting up an array of initial values for testing. In cases where the difference between
- * a min val and a max val is < SMALL, the min val is used and the variable is no
- * randomized.
- * @param rand and random number generator
- * @param num the number to create
- * @param charge the integer charge
- * @param randCharge if true the charge will be 1 or -1 randomly
- * @param xmin minimum value of the x coordinate in meters
- * @param xmax maximum value of the x coordinate in meters
- * @param ymin minimum value of the y coordinate in meters
- * @param ymax maximum value of the y coordinate in meters
- * @param zmin minimum value of the z coordinate in meters
- * @param zmax maximum value of the z coordinate in meters
- * @param pmin minimum value of the momentum in GeV/c
- * @param pmax maximum value of the momentum in GeV/c
- * @param thetamin minimum value of the polar angle in degrees
- * @param thetamax maximum value of the polar angle in degrees
- * @param phimin minimum value of the azimuthal angle in degrees
- * @param phimax maximum value of the azimuthal angle in degrees
- * @return an array of initial values
- */
- public static InitialValues[] getInitialValues(Random rand, int num, int charge, boolean randCharge, double xmin, double xmax,
- double ymin, double ymax, double zmin, double zmax, double pmin, double pmax, double thetamin,
- double thetamax, double phimin, double phimax) {
-
- InitialValues[] initVals = new InitialValues[num];
-
- for (int i = 0; i < num; i++) {
- initVals[i] = new InitialValues();
- randomInitVal(rand, initVals[i], charge, randCharge, xmin, xmax, ymin, ymax, zmin, zmax, pmin, pmax,
- thetamin, thetamax, phimin, phimax);
- }
-
- return initVals;
- }
-
- /**
- * For setting up an array of initial values for testing. In cases where the difference between
- * a min val and a max val is < SMALL, the min val is used and the variable is no
- * randomized.
- * @param rand and random number generator
- * @param initVal the object to fill with random values
- * @param charge the integer charge
- * @param randCharge if true the charge will be 1 or -1 randomly
- * @param xmin minimum value of the x coordinate in meters
- * @param xmax maximum value of the x coordinate in meters
- * @param ymin minimum value of the y coordinate in meters
- * @param ymax maximum value of the y coordinate in meters
- * @param zmin minimum value of the z coordinate in meters
- * @param zmax maximum value of the z coordinate in meters
- * @param pmin minimum value of the momentum in GeV/c
- * @param pmax maximum value of the momentum in GeV/c
- * @param thetamin minimum value of the polar angle in degrees
- * @param thetamax maximum value of the polar angle in degrees
- * @param phimin minimum value of the azimuthal angle in degrees
- * @param phimax maximum value of the azimuthal angle in degrees
- */
- public static void randomInitVal(Random rand, InitialValues initVal, int charge, boolean randCharge, double xmin,
- double xmax, double ymin, double ymax, double zmin, double zmax, double pmin, double pmax, double thetamin,
- double thetamax, double phimin, double phimax) {
-
- if (randCharge) {
- initVal.charge = (rand.nextBoolean() ? -1 : 1);
- } else {
- initVal.charge = charge;
- }
-
- initVal.xo = randVal(rand, xmin, xmax);
- initVal.yo = randVal(rand, ymin, ymax);
- initVal.zo = randVal(rand, zmin, zmax);
- initVal.p = randVal(rand, pmin, pmax);
- initVal.theta = randVal(rand, thetamin, thetamax);
- initVal.phi = randVal(rand, phimin, phimax);
- }
-
- //used to generate a random number in a range
- private static double randVal(Random rand, double vmin, double vmax) {
- double del = vmax - vmin;
-
- if (Math.abs(del) < SMALL) {
- return vmin;
- } else {
- return vmin + del * rand.nextDouble();
- }
- }
-
-}
diff --git a/common-tools/cnuphys/swimmer/src/main/java/cnuphys/adaptiveSwim/test/LineTestPlotGrid.java b/common-tools/cnuphys/swimmer/src/main/java/cnuphys/adaptiveSwim/test/LineTestPlotGrid.java
deleted file mode 100644
index 33bce4e887..0000000000
--- a/common-tools/cnuphys/swimmer/src/main/java/cnuphys/adaptiveSwim/test/LineTestPlotGrid.java
+++ /dev/null
@@ -1,234 +0,0 @@
-package cnuphys.adaptiveSwim.test;
-
-import java.awt.Color;
-
-import cnuphys.adaptiveSwim.AdaptiveSwimResult;
-import cnuphys.splot.fit.FitType;
-import cnuphys.splot.pdata.DataSet;
-import cnuphys.splot.pdata.DataSetException;
-import cnuphys.splot.pdata.HistoData;
-import cnuphys.splot.plot.PlotCanvas;
-import cnuphys.splot.plot.PlotGridDialog;
-import cnuphys.splot.plot.PlotParameters;
-import cnuphys.splot.plot.UnicodeSupport;
-import cnuphys.splot.plot.VerticalLine;
-import cnuphys.splot.style.LineStyle;
-
-
-public class LineTestPlotGrid extends PlotGridDialog {
-
- private static int _numRow = 3;
- private static int _numCol = 3;
- private static int _width = 400;
- private static int _height = 400;
-
- private PlotCanvas[][] _canvases;
- private DataSet[][] _dataSets;
-
- private double _accuracy;
- private double _epsilon;
- private double _zTarg;
-
- public LineTestPlotGrid(double zTarg, double accuracy, double epsilon) {
- super(null, "Swimmer Z Test Plots", false, _numRow, _numCol, _numCol * _width, _numRow * _height);
-
- _zTarg = zTarg;
- _accuracy = accuracy;
- _epsilon = epsilon;
-
- _canvases = new PlotCanvas[_numRow][_numCol];
- _dataSets = new DataSet[_numRow][_numCol];
-
- // add the plots
-
- for (int row = 0; row < _numRow; row++) {
- for (int col = 0; col < _numCol; col++) {
- try {
- _dataSets[row][col] = createDataSet(row, col);
- _canvases[row][col] = new PlotCanvas(_dataSets[row][col], getPlotTitle(row, col),
- getXAxisLabel(row, col), getYAxisLabel(row, col));
-
- setPreferences(_canvases[row][col], row, col);
-
- _plotGrid.addPlotCanvas(_canvases[row][col]);
- } catch (DataSetException e) {
- e.printStackTrace();
- return;
- }
- }
- }
- }
-
- /**
- * Update the plots
- *
- * @param diff
- */
- public void update(AdaptiveResultDiff diff) {
- try {
- _dataSets[0][0].add(diff.getFinalXDiff());
- _dataSets[0][1].add(diff.getFinalYDiff());
- _dataSets[0][2].add(diff.getFinalZDiff());
- _dataSets[1][0].add(diff.getFinalSDiff());
- _dataSets[1][1].add(diff.getFinalThetaDiff());
- _dataSets[1][2].add(diff.getFinalPhiDiff());
-
- AdaptiveSwimResult oldSwimRes = diff.result1;
- AdaptiveSwimResult newSwimRes = diff.result2;
-
- _dataSets[2][0].add(oldSwimRes.finalDeltaZ(_zTarg));
- _dataSets[2][1].add(newSwimRes.finalDeltaZ(_zTarg));
- _dataSets[2][2].add(100.0*diff.getBDLDiff()/(diff.result1.getTrajectory().getComputedBDL()));
- } catch (DataSetException e) {
- e.printStackTrace();
- }
- }
-
- // set the preferences
- public void setPreferences(PlotCanvas canvas, int row, int col) {
-
- DataSet ds = canvas.getDataSet();
- PlotParameters params = canvas.getParameters();
-
- params.setTitleFont(_titleFont);
- params.setAxesFont(_axesFont);
- params.setStatusFont(_statusFont);
- params.setStatusFont(_legendFont);
- params.setLegendLineLength(40);
-
- params.setExtraStrings(String.format(
- "Accuracy %-6.2gm", _accuracy),
- String.format("Epsilon %-6.2gm", _epsilon));
-
- params.addPlotLine(new VerticalLine(canvas, 0));
-
- VerticalLine vline = (new VerticalLine(canvas, 0));
- vline.getStyle().setBorderColor(Color.red);
- vline.getStyle().setFitLineWidth(1.5f);
- vline.getStyle().setFitLineStyle(LineStyle.DOT);
- params.addPlotLine(vline);
-
- ds.getCurveStyle(0).setFillColor(new Color(196, 196, 196, 64));
- ds.getCurveStyle(0).setFitLineColor(Color.red);
- ds.getCurveStyle(0).setFitLineWidth(2);
- ds.getCurve(0).getFit().setFitType(FitType.GAUSSIANS);
-
- params.setMinExponentY(6);
- params.setNumDecimalY(0);
-
- params.setMinExponentX(4);
- params.setNumDecimalX(3);
-
- }
-
- // create the datasets
- private DataSet createDataSet(int row, int col) throws DataSetException {
-
- if (row == 0) {
- if (col == 0) {
- HistoData hd = new HistoData("", -0.02, 0.02, 50);
- return new DataSet(hd);
- } else if (col == 1) {
- HistoData hd = new HistoData("", -0.02, 0.02, 50);
- return new DataSet(hd);
- } else if (col == 2) {
- HistoData hd = new HistoData("", -0.02, 0.02, 50);
- return new DataSet(hd);
- }
- } else if (row == 1) {
- if (col == 0) {
- HistoData hd = new HistoData("", -0.02, 0.02, 50);
- return new DataSet(hd);
- }
- else if (col == 1) {
- HistoData hd = new HistoData("", -0.01, 0.01, 50);
- return new DataSet(hd);
- } else if (col == 2) {
- HistoData hd = new HistoData("", -0.02, 0.02, 50);
- return new DataSet(hd);
- }
- } else if (row == 2) {
- if (col == 0) {
- HistoData hd = new HistoData("", -0.01, 0.01, 50);
- return new DataSet(hd);
- } else if (col == 1) {
- HistoData hd = new HistoData("", -0.01, 0.01, 50);
- return new DataSet(hd);
- } else if (col == 2) {
- HistoData hd = new HistoData("", -2, 2, 50);
- return new DataSet(hd);
- }
- }
-
- return null;
- }
-
- protected String getPlotTitle(int row, int col) {
-
- if (row == 0) {
- if (col == 0) {
- return "Final X Difference";
- } else if (col == 1) {
- return "Final Y Difference";
- } else if (col == 2) {
- return "Final Z Difference";
- }
- } else if (row == 1) {
- if (col == 0) {
- return "Final S Difference";
- }
- else if (col == 1) {
- return "Final " + UnicodeSupport.SMALL_THETA + " Difference (deg)";
- } else if (col == 2) {
- return "Final " + UnicodeSupport.SMALL_PHI + " Difference (deg)";
- }
- } else if (row == 2) {
- if (col == 0) {
- return "Z - Ztarg (Old Swimmer)";
- } else if (col == 1) {
- return "Z - Ztarg (New Swimmer)";
- }
- else if (col == 2) {
- return "BDL Difference";
- }
- }
-
- return null;
- }
-
- protected String getXAxisLabel(int row, int col) {
- if (row == 0) {
- if (col == 0) {
- return "Final X Difference (m)";
- } else if (col == 1) {
- return "Final Y Difference (m)";
- } else if (col == 2) {
- return "Final Z Difference (m)";
- }
- } else if (row == 1) {
- if (col == 0) {
- return "Final S Difference (m)";
- }
- else if (col == 1) {
- return "Final " + UnicodeSupport.SMALL_THETA + " Difference (deg)";
- } else if (col == 2) {
- return "Final " + UnicodeSupport.SMALL_PHI + " Difference (deg)";
- }
- } else if (row == 2) {
- if (col == 0) {
- return "Z - Ztarg (Old Swimmer) m";
- } else if (col == 1) {
- return "Z - Ztarg (New Swimmer) m";
- } else if (col == 2) {
- return "BDL % Difference";
- }
- }
-
- return "???";
- }
-
- protected String getYAxisLabel(int row, int col) {
- return "Counts";
- }
-
-}
diff --git a/common-tools/cnuphys/swimmer/src/main/java/cnuphys/adaptiveSwim/test/ZTestPlotGrid.java b/common-tools/cnuphys/swimmer/src/main/java/cnuphys/adaptiveSwim/test/ZTestPlotGrid.java
deleted file mode 100644
index 8f4fb074ff..0000000000
--- a/common-tools/cnuphys/swimmer/src/main/java/cnuphys/adaptiveSwim/test/ZTestPlotGrid.java
+++ /dev/null
@@ -1,233 +0,0 @@
-package cnuphys.adaptiveSwim.test;
-
-import java.awt.Color;
-
-import cnuphys.adaptiveSwim.AdaptiveSwimResult;
-import cnuphys.splot.fit.FitType;
-import cnuphys.splot.pdata.DataSet;
-import cnuphys.splot.pdata.DataSetException;
-import cnuphys.splot.pdata.HistoData;
-import cnuphys.splot.plot.PlotCanvas;
-import cnuphys.splot.plot.PlotGridDialog;
-import cnuphys.splot.plot.PlotParameters;
-import cnuphys.splot.plot.UnicodeSupport;
-import cnuphys.splot.plot.VerticalLine;
-import cnuphys.splot.style.LineStyle;
-
-public class ZTestPlotGrid extends PlotGridDialog {
-
- private static int _numRow = 3;
- private static int _numCol = 3;
- private static int _width = 400;
- private static int _height = 400;
-
- private PlotCanvas[][] _canvases;
- private DataSet[][] _dataSets;
-
- private double _accuracy;
- private double _epsilon;
- private double _zTarg;
-
- public ZTestPlotGrid(double zTarg, double accuracy, double epsilon) {
- super(null, "Swimmer Z Test Plots", false, _numRow, _numCol, _numCol * _width, _numRow * _height);
-
- _zTarg = zTarg;
- _accuracy = accuracy;
- _epsilon = epsilon;
-
- _canvases = new PlotCanvas[_numRow][_numCol];
- _dataSets = new DataSet[_numRow][_numCol];
-
- // add the plots
-
- for (int row = 0; row < _numRow; row++) {
- for (int col = 0; col < _numCol; col++) {
- try {
- _dataSets[row][col] = createDataSet(row, col);
- _canvases[row][col] = new PlotCanvas(_dataSets[row][col], getPlotTitle(row, col),
- getXAxisLabel(row, col), getYAxisLabel(row, col));
-
- setPreferences(_canvases[row][col], row, col);
-
- _plotGrid.addPlotCanvas(_canvases[row][col]);
- } catch (DataSetException e) {
- e.printStackTrace();
- return;
- }
- }
- }
- }
-
- /**
- * Update the plots
- *
- * @param diff
- */
- public void update(AdaptiveResultDiff diff) {
- try {
- _dataSets[0][0].add(diff.getFinalXDiff());
- _dataSets[0][1].add(diff.getFinalYDiff());
- _dataSets[0][2].add(diff.getFinalZDiff());
- _dataSets[1][0].add(diff.getFinalSDiff());
- _dataSets[1][1].add(diff.getFinalThetaDiff());
- _dataSets[1][2].add(diff.getFinalPhiDiff());
-
- AdaptiveSwimResult oldSwimRes = diff.result1;
- AdaptiveSwimResult newSwimRes = diff.result2;
-
- _dataSets[2][0].add(oldSwimRes.finalDeltaZ(_zTarg));
- _dataSets[2][1].add(newSwimRes.finalDeltaZ(_zTarg));
- _dataSets[2][2].add(100.0*diff.getBDLDiff()/(diff.result1.getTrajectory().getComputedBDL()));
- } catch (DataSetException e) {
- e.printStackTrace();
- }
- }
-
- // set the preferences
- public void setPreferences(PlotCanvas canvas, int row, int col) {
-
- DataSet ds = canvas.getDataSet();
- PlotParameters params = canvas.getParameters();
-
- params.setTitleFont(_titleFont);
- params.setAxesFont(_axesFont);
- params.setStatusFont(_statusFont);
- params.setStatusFont(_legendFont);
- params.setLegendLineLength(40);
-
- params.setExtraStrings(String.format(
- "Accuracy %-6.2gm", _accuracy),
- String.format("Epsilon %-6.2gm", _epsilon));
-
- params.addPlotLine(new VerticalLine(canvas, 0));
-
- VerticalLine vline = (new VerticalLine(canvas, 0));
- vline.getStyle().setBorderColor(Color.red);
- vline.getStyle().setFitLineWidth(1.5f);
- vline.getStyle().setFitLineStyle(LineStyle.DOT);
- params.addPlotLine(vline);
-
- ds.getCurveStyle(0).setFillColor(new Color(196, 196, 196, 64));
- ds.getCurveStyle(0).setFitLineColor(Color.red);
- ds.getCurveStyle(0).setFitLineWidth(2);
- ds.getCurve(0).getFit().setFitType(FitType.GAUSSIANS);
-
- params.setMinExponentY(6);
- params.setNumDecimalY(0);
-
- params.setMinExponentX(4);
- params.setNumDecimalX(3);
-
- }
-
- // create the datasets
- private DataSet createDataSet(int row, int col) throws DataSetException {
-
- if (row == 0) {
- if (col == 0) {
- HistoData hd = new HistoData("", -0.02, 0.02, 50);
- return new DataSet(hd);
- } else if (col == 1) {
- HistoData hd = new HistoData("", -0.02, 0.02, 50);
- return new DataSet(hd);
- } else if (col == 2) {
- HistoData hd = new HistoData("", -0.02, 0.02, 50);
- return new DataSet(hd);
- }
- } else if (row == 1) {
- if (col == 0) {
- HistoData hd = new HistoData("", -0.02, 0.02, 50);
- return new DataSet(hd);
- }
- else if (col == 1) {
- HistoData hd = new HistoData("", -0.01, 0.01, 50);
- return new DataSet(hd);
- } else if (col == 2) {
- HistoData hd = new HistoData("", -0.02, 0.02, 50);
- return new DataSet(hd);
- }
- } else if (row == 2) {
- if (col == 0) {
- HistoData hd = new HistoData("", -0.01, 0.01, 50);
- return new DataSet(hd);
- } else if (col == 1) {
- HistoData hd = new HistoData("", -0.01, 0.01, 50);
- return new DataSet(hd);
- } else if (col == 2) {
- HistoData hd = new HistoData("", -0.25, 0.25, 50);
- return new DataSet(hd);
- }
- }
-
- return null;
- }
-
- protected String getPlotTitle(int row, int col) {
-
- if (row == 0) {
- if (col == 0) {
- return "Final X Difference";
- } else if (col == 1) {
- return "Final Y Difference";
- } else if (col == 2) {
- return "Final Z Difference";
- }
- } else if (row == 1) {
- if (col == 0) {
- return "Final S Difference";
- }
- else if (col == 1) {
- return "Final " + UnicodeSupport.SMALL_THETA + " Difference (deg)";
- } else if (col == 2) {
- return "Final " + UnicodeSupport.SMALL_PHI + " Difference (deg)";
- }
- } else if (row == 2) {
- if (col == 0) {
- return "Z - Ztarg (Old Swimmer)";
- } else if (col == 1) {
- return "Z - Ztarg (New Swimmer)";
- }
- else if (col == 2) {
- return "BDL Difference";
- }
- }
-
- return null;
- }
-
- protected String getXAxisLabel(int row, int col) {
- if (row == 0) {
- if (col == 0) {
- return "Final X Difference (m)";
- } else if (col == 1) {
- return "Final Y Difference (m)";
- } else if (col == 2) {
- return "Final Z Difference (m)";
- }
- } else if (row == 1) {
- if (col == 0) {
- return "Final S Difference (m)";
- }
- else if (col == 1) {
- return "Final " + UnicodeSupport.SMALL_THETA + " Difference (deg)";
- } else if (col == 2) {
- return "Final " + UnicodeSupport.SMALL_PHI + " Difference (deg)";
- }
- } else if (row == 2) {
- if (col == 0) {
- return "Z - Ztarg (Old Swimmer) m";
- } else if (col == 1) {
- return "Z - Ztarg (New Swimmer) m";
- } else if (col == 2) {
- return "BDL % Difference";
- }
- }
-
- return "???";
- }
-
- protected String getYAxisLabel(int row, int col) {
- return "Counts";
- }
-
-}
diff --git a/common-tools/cnuphys/swimmer/src/main/java/cnuphys/bin/.classpath b/common-tools/cnuphys/swimmer/src/main/java/cnuphys/bin/.classpath
new file mode 100644
index 0000000000..163eb81815
--- /dev/null
+++ b/common-tools/cnuphys/swimmer/src/main/java/cnuphys/bin/.classpath
@@ -0,0 +1,12 @@
+
+null
*/
@@ -748,10 +748,10 @@ public LundId get(int id, int charge) {
return unknownNeutral;
}
}
-
+
/**
* Finds an LundId object based on the given particle id. Uses a binary search.
- *
+ *
* @param id the id to look for
* @return the object if found, or null
*/
@@ -772,7 +772,7 @@ public LundId get(int id) {
/**
* Finds an LundId object based on the given particle id. Uses a binary search.
- *
+ *
* @param id the id to look for. This is rounded. This method is to support
* GEMC.
* @return the object if found, or null
@@ -784,7 +784,7 @@ public LundId get(double id) {
/**
* Get the list of lundIds
- *
+ *
* @return the list of lundIds
*/
public ArrayListtrue make line color datker, else make it
@@ -1024,7 +1024,7 @@ public static void setStyle(int lundId, Color lineColor) {
/**
* Main program for testing
- *
+ *
* @param arg command arguments ignored.
*/
public static void main(String arg[]) {
diff --git a/common-tools/cnuphys/swimmer/src/main/java/cnuphys/lund/LundTrackDialog.java b/common-tools/cnuphys/swimmer/src/main/java/cnuphys/lund/LundTrackDialog.java
index 10d277f545..0313bb44c9 100644
--- a/common-tools/cnuphys/swimmer/src/main/java/cnuphys/lund/LundTrackDialog.java
+++ b/common-tools/cnuphys/swimmer/src/main/java/cnuphys/lund/LundTrackDialog.java
@@ -25,125 +25,140 @@
import javax.swing.border.Border;
import javax.swing.border.TitledBorder;
-import cnuphys.adaptiveSwim.AdaptiveSwimException;
-import cnuphys.adaptiveSwim.AdaptiveSwimResult;
-import cnuphys.adaptiveSwim.AdaptiveSwimmer;
-import cnuphys.magfield.FastMath;
+import cnuphys.CLAS12Swim.CLAS12SwimResult;
+import cnuphys.CLAS12Swim.CLAS12Swimmer;
+import cnuphys.CLAS12Swim.ICLAS12Swimmer;
import cnuphys.swim.SwimTrajectory;
import cnuphys.swim.Swimming;
-import cnuphys.swimZ.SwimZResult;
+/**
+ * A dialog for configuring and executing particle swimming within the CLAS12 environment.
+ * It allows users to select particles, set initial kinematic conditions, choose
+ * integration algorithms, and select the specific swimmer implementation.
+ */
@SuppressWarnings("serial")
public class LundTrackDialog extends JDialog {
+
+ /**
+ * Enum defining the available swimming algorithms.
+ */
+ public enum SWIM_ALGORITHM {
+ /** Standard integration until sMax is reached. */
+ STANDARD,
+ /** Integration until a specific Z coordinate is reached. */
+ FIXEDZ,
+ /** Integration until a specific radial distance (rho) is reached. */
+ FIXEDRHO
+ }
- public enum SWIM_ALGORITHM {STANDARD, FIXEDZ, FIXEDS, FIXEDRHO}
-
+ /** The currently selected swimming algorithm. */
private SWIM_ALGORITHM _algorithm = SWIM_ALGORITHM.STANDARD;
-
+
+ /** Response code for cancelation. */
private static final int CANCEL_RESPONSE = 1;
- // combo box for selecting the particle
+ /** Combo box for selecting the particle type. */
private LundComboBox _lundComboBox;
-
- // for selecting energy
- // private JTextField _energyTextField;
-
- // text field for gamma
+
+ /** Text field displaying relativistic gamma. */
private JTextField _relativisticGamma;
-
- // text field for beta
+
+ /** Text field displaying relativistic beta. */
private JTextField _relativisticBeta;
-
- // text field for total energy
+
+ /** Text field displaying total energy. */
private JTextField _totalEnergyTextField;
-
- // text field for momentum
+
+ /** Text field for entering momentum magnitude. */
private JTextField _momentumTextField;
-
- // text field for mass
+
+ /** Text field displaying particle mass. */
private JTextField _massTextField;
-
- // starts the swimming
+
+ /** Button to trigger the swim operation. */
private JButton _swimButton;
-
- // text field for x vertex
+
+ /** Text field for vertex X coordinate. */
private JTextField _vertexX;
-
- // text field for y vertex
+
+ /** Text field for vertex Y coordinate. */
private JTextField _vertexY;
-
- // text field for z vertex
+
+ /** Text field for vertex Z coordinate. */
private JTextField _vertexZ;
-
- // text field for initial theta
+
+ /** Text field for initial polar angle theta. */
private JTextField _theta;
-
- // text field for initial phi
+
+ /** Text field for initial azimuthal angle phi. */
private JTextField _phi;
- // use standard cutoff
+ /** Radio button for standard algorithm selection. */
private JRadioButton _standardRB;
-
- // fixed z cutoff
- private JRadioButton _fixedZRB;
- // fixed s (pathlength) cutoff
- private JRadioButton _fixedSRB;
+ /** Radio button for Fixed Z algorithm selection. */
+ private JRadioButton _fixedZRB;
- // fixed z cutoff
+ /** Radio button for Fixed Rho algorithm selection. */
private JRadioButton _fixedRhoRB;
-
- // fixed Rho value
+
+ /** Text field for the target radial value in Fixed Rho. */
private JTextField _fixedRho;
-
-
- // fixed Z value
- private JTextField _fixedZ;
+ /** Text field for the target Z value in Fixed Z. */
+ private JTextField _fixedZ;
- // fixed S (pathlength) value
- private JTextField _fixedS;
+ /** Text field for the maximum path length. */
+ private JTextField _sMax;
-
- // accuracy in fixed z
+ /** Text field for integration accuracy (microns). */
private JTextField _accuracy;
- // old (and default_ momentum in GeV/c
+ /** Stores the previously valid momentum to handle parsing errors. */
private double _oldMomentum = 2.0;
- // only need one swimmer
-
- // unicode strings
+ /** Unicode string for Greek letter Beta. */
public static final String SMALL_BETA = "\u03B2";
+ /** Unicode string for Greek letter Gamma. */
public static final String SMALL_GAMMA = "\u03B3";
+ /** Unicode string for Greek letter Theta. */
public static final String SMALL_THETA = "\u03B8";
+ /** Unicode string for Greek letter Phi. */
public static final String SMALL_PHI = "\u03C6";
+ /** Unicode string for squared superscript. */
public static final String SUPER2 = "\u00B2";
+ /** Unicode string for Greek letter Rho. */
public static final String SMALL_RHO = "\u03C1";
- // usual relativistic quantities
+ /** Calculated relativistic gamma. */
private double _gamma;
+ /** Calculated relativistic beta. */
private double _beta;
- private double _energy; // total energy
+ /** Calculated total energy. */
+ private double _energy;
- // for labels
+ /** Label for Relativistic Gamma. */
private static final String RELGAMMA = "Relativistic " + SMALL_GAMMA;
+ /** Label for Relativistic Beta. */
private static final String RELBETA = "Relativistic " + SMALL_BETA;
+ /** Label for Total Energy. */
private static final String TOTENERGY = "Total Energy";
+ /** Label for Momentum. */
private static final String MOMENTUMMAG = "Momentum";
+ /** Label for Mass. */
private static final String MASS = "Mass";
- // singleton
+ /** Singleton instance of the dialog. */
private static LundTrackDialog instance;
/**
- * Create a dialog used to swim a particle
+ * Private constructor for the LundTrackDialog singleton.
+ * Initializes UI components and window listeners.
*/
private LundTrackDialog() {
setTitle("Swim a Particle");
setModal(false);
- // close is like a cancel
WindowAdapter wa = new WindowAdapter() {
@Override
public void windowClosing(WindowEvent we) {
@@ -156,12 +171,13 @@ public void windowClosing(WindowEvent we) {
pack();
centerComponent(this);
}
-
- //create the algorithm buttons
+
+ /**
+ * Creates and configures the radio buttons for algorithm selection.
+ * @param bg The ButtonGroup to which the radio buttons are added.
+ */
private void createAlgorithmButtons(ButtonGroup bg) {
-
ActionListener al = new ActionListener() {
-
@Override
public void actionPerformed(ActionEvent e) {
if (_standardRB.isSelected()) {
@@ -173,72 +189,59 @@ else if (_fixedZRB.isSelected()) {
else if (_fixedRhoRB.isSelected()) {
_algorithm = SWIM_ALGORITHM.FIXEDRHO;
}
- else if (_fixedSRB.isSelected()) {
- _algorithm = SWIM_ALGORITHM.FIXEDS;
- }
-
-
fixState();
}
-
};
-
+
_standardRB = new JRadioButton("Standard");
_fixedZRB = new JRadioButton("Fixed Z");
- _fixedSRB = new JRadioButton("Fixed S");
-
_fixedRhoRB = new JRadioButton("Fixed " + SMALL_RHO);
-
-
+
_standardRB.setSelected((_algorithm == SWIM_ALGORITHM.STANDARD));
_fixedZRB.setSelected((_algorithm == SWIM_ALGORITHM.FIXEDZ));
- _fixedSRB.setSelected((_algorithm == SWIM_ALGORITHM.FIXEDS));
_fixedRhoRB.setSelected((_algorithm == SWIM_ALGORITHM.FIXEDRHO));
-
+
_standardRB.addActionListener(al);
_fixedZRB.addActionListener(al);
- _fixedSRB.addActionListener(al);
_fixedRhoRB.addActionListener(al);
-
+
bg.add(_standardRB);
bg.add(_fixedZRB);
- bg.add(_fixedSRB);
bg.add(_fixedRhoRB);
-
+
fixState();
}
-
-
- //fix the state of the dialog
+
+ /**
+ * Updates the enabled state of coordinate text fields based on
+ * the selected algorithm.
+ */
private void fixState() {
_fixedZ.setEnabled(_fixedZRB.isSelected());
_fixedRho.setEnabled(_fixedRhoRB.isSelected());
- _fixedS.setEnabled(_fixedSRB.isSelected());
}
/**
- * Access to the dialog singleton
- *
- * @return the dialog (set visible)
+ * Returns the singleton instance of the LundTrackDialog.
+ * @return The LundTrackDialog instance, made visible.
*/
public static LundTrackDialog getInstance() {
if (instance == null) {
instance = new LundTrackDialog();
}
-
instance.setVisible(true);
return instance;
}
- // add all the widgets
+ /**
+ * Orchestrates the addition of all UI subpanels to the dialog.
+ */
private void addComponents() {
setLayout(new BorderLayout(6, 6));
-
Box box = Box.createVerticalBox();
box.add(Box.createVerticalStrut(6));
ActionListener al = new ActionListener() {
-
@Override
public void actionPerformed(ActionEvent arg0) {
selectedParticle();
@@ -249,26 +252,20 @@ public void actionPerformed(ActionEvent arg0) {
_lundComboBox.addActionListener(al);
box.add(paddedPanel(20, 6, _lundComboBox));
- // add the energy selection panel
box.add(Box.createVerticalStrut(6));
box.add(energyPanel());
- // add the direction selection panel
box.add(Box.createVerticalStrut(6));
box.add(initConditionsPanel());
- // add the vertex selection panel
box.add(Box.createVerticalStrut(6));
box.add(vertexPanel());
- // integration cutoff panel
box.add(Box.createVerticalStrut(6));
box.add(cutoffPanel());
- // the swim button
_swimButton = new JButton("Swim");
_swimButton.addActionListener(new ActionListener() {
-
@Override
public void actionPerformed(ActionEvent e) {
setMomentum();
@@ -279,113 +276,72 @@ public void actionPerformed(ActionEvent e) {
add(box, BorderLayout.CENTER);
add(paddedPanel(50, 6, _swimButton), BorderLayout.SOUTH);
- // padding
add(Box.createHorizontalStrut(4), BorderLayout.EAST);
add(Box.createHorizontalStrut(4), BorderLayout.WEST);
- selectedParticle(); // selects the default
+ selectedParticle();
}
/**
- * Swim the particle
+ * Executes the swimming process using the configured particle, kinematics,
+ * algorithm, and swimmer implementation.
*/
private void doCommonSwim() {
+ ICLAS12Swimmer swimmer = new CLAS12Swimmer();
- //use the AdaptiveSwimmer exclusively
- AdaptiveSwimmer swimmer = new AdaptiveSwimmer();
-
- try {
- LundId lid = _lundComboBox.getSelectedId();
-
- // note xo, yo, zo converted to meters
- double xo = Double.parseDouble(_vertexX.getText()) / 100.;
- double yo = Double.parseDouble(_vertexY.getText()) / 100.;
- double zo = Double.parseDouble(_vertexZ.getText()) / 100.;
- double momentum = Double.parseDouble(_momentumTextField.getText());
- double theta = Double.parseDouble(_theta.getText());
- double phi = Double.parseDouble(_phi.getText());
-
- double stepSize = 1e-5; // m
- double maxPathLen = 8.0; // m
-
- double eps = 1.0e-6;
-
- AdaptiveSwimResult result = new AdaptiveSwimResult(true);
- SwimTrajectory traj = null;
-
- String prompt = "";
-
- switch (_algorithm) {
-
- case STANDARD:
- swimmer.swim(lid.getCharge(), xo, yo, zo, momentum, theta, phi, maxPathLen, stepSize, eps, result);
- prompt = "RESULT from standard swim:\n";
- break;
-
- case FIXEDZ:
- // convert accuracy from microns to meters
- double accuracy = Double.parseDouble(_accuracy.getText()) / 1.0e6;
- double ztarget = Double.parseDouble(_fixedZ.getText()) / 100; // meters
- swimmer.swimZ(lid.getCharge(), xo, yo, zo, momentum, theta, phi, ztarget, accuracy, maxPathLen,
- stepSize, eps, result);
- prompt = "RESULT from fixed Z swim:\n";
- break;
-
- case FIXEDS:
- // convert accuracy from microns to meters
- accuracy = Double.parseDouble(_accuracy.getText()) / 1.0e6;
- double targetS = Double.parseDouble(_fixedS.getText()) / 100; // meters
- swimmer.swimS(lid.getCharge(), xo, yo, zo, momentum, theta, phi, accuracy, targetS,
- stepSize, eps, result);
- prompt = "RESULT from fixed S swim:\n";
- break;
-
-
- case FIXEDRHO:
- // convert accuracy from microns to meters
- accuracy = Double.parseDouble(_accuracy.getText()) / 1.0e6;
- double rhotarget = Double.parseDouble(_fixedRho.getText()) / 100; // meters
-
-
- // .swimRho(charge[i], xo[i], yo[i], zo[i], p, theta[i], phi[i], rho, accuracy, sMax, stepSize, eps, result);
-
- swimmer.swimRho(lid.getCharge(), xo, yo, zo, momentum, theta, phi, rhotarget, accuracy, maxPathLen, stepSize, eps, result);
- prompt = "RESULT from fixed Rho swim:\n";
- break;
- } //switch
-
- traj = result.getTrajectory();
- if (traj != null) {
- traj = result.getTrajectory();
- traj.setLundId(lid);
- traj.computeBDL(swimmer.getProbe());
-
- result.printOut(System.out, prompt + result);
- Swimming.addMCTrajectory(traj);
- }
+ CLAS12SwimResult result = null;
+ LundId lid = _lundComboBox.getSelectedId();
+ double xo = Double.parseDouble(_vertexX.getText());
+ double yo = Double.parseDouble(_vertexY.getText());
+ double zo = Double.parseDouble(_vertexZ.getText());
+ double momentum = Double.parseDouble(_momentumTextField.getText());
+ double theta = Double.parseDouble(_theta.getText());
+ double phi = Double.parseDouble(_phi.getText());
+
+ double stepSize = 1e-4;
+ double sMax = Double.parseDouble(_sMax.getText());
+
+ double tolerance = 1.0e-6;
+ SwimTrajectory traj = null;
+
+ switch (_algorithm) {
+ case STANDARD:
+ result = swimmer.swim(lid.getCharge(), xo, yo, zo, momentum, theta, phi, sMax, stepSize, tolerance);
+ break;
+ case FIXEDZ:
+ double accuracy = Double.parseDouble(_accuracy.getText()) / 1.0e4;
+ double ztarget = Double.parseDouble(_fixedZ.getText());
+ result = swimmer.swimZ(lid.getCharge(), xo, yo, zo, momentum, theta, phi, ztarget, accuracy, sMax, stepSize,
+ tolerance);
+ break;
+ case FIXEDRHO:
+ accuracy = Double.parseDouble(_accuracy.getText()) / 1.0e4;
+ double rhotarget = Double.parseDouble(_fixedRho.getText());
+ result = swimmer.swimRho(lid.getCharge(), xo, yo, zo, momentum, theta, phi, rhotarget, accuracy, sMax, stepSize,
+ tolerance);
+ break;
+ }
+
+ if (result != null) {
+ traj = result.getTrajectory();
+ traj.setLundId(lid);
+ traj.computeBDL(swimmer.getProbe());
+ Swimming.addMCTrajectory(traj);
+ System.out.println(result.toString());
}
- catch (AdaptiveSwimException e) {
- e.printStackTrace();
- }
-
-
}
-
-
/**
- * Create a Box that has a prompt, text field, and unit string
- *
- * @param prompt
- * @param tf
- * @param units
- * @param promptWidth
- * @return a Box holding a labeled text field
+ * Utility method to create a horizontally aligned box with a prompt, text field, and units.
+ * @param prompt The label text.
+ * @param tf The JTextField component.
+ * @param units The unit label text.
+ * @param promptWidth Fixed width for the prompt label.
+ * @return A Box containing the labeled components.
*/
private Box labeledTextField(String prompt, JTextField tf, String units, final int promptWidth) {
Box box = Box.createHorizontalBox();
-
JLabel plabel = new JLabel(prompt) {
@Override
public Dimension getPreferredSize() {
@@ -403,129 +359,112 @@ public Dimension getPreferredSize() {
box.add(Box.createHorizontalStrut(6));
box.add(new JLabel(units));
}
-
return box;
}
/**
- * A new particle was selected
+ * Handles particle selection changes.
*/
private void selectedParticle() {
- // System.err.println("Selected particle: " +
- // _lundComboBox.getSelectedId());
setMomentum();
}
/**
- * Create the panel for setting the vertex
- *
- * @return the panel holding the vertex pane
+ * Creates the subpanel for configuring the track vertex.
+ * @return A JPanel with vertex coordinate fields.
*/
private JPanel vertexPanel() {
JPanel panel = new JPanel();
Box box = Box.createVerticalBox();
-
_vertexX = new JTextField(8);
_vertexY = new JTextField(8);
_vertexZ = new JTextField(8);
-
_vertexX.setText("0.0");
_vertexY.setText("0.0");
_vertexZ.setText("0.0");
-
box.add(labeledTextField("X:", _vertexX, "cm", 20));
box.add(Box.createVerticalStrut(5));
box.add(labeledTextField("Y:", _vertexY, "cm", 20));
box.add(Box.createVerticalStrut(5));
box.add(labeledTextField("Z:", _vertexZ, "cm", 20));
box.add(Box.createVerticalStrut(5));
-
panel.add(box);
panel.setBorder(new CommonBorder("Track Vertex"));
return panel;
}
- // initial conditions
+ /**
+ * Creates the subpanel for initial momentum and direction.
+ * @return A JPanel with momentum, theta, and phi fields.
+ */
private JPanel initConditionsPanel() {
JPanel panel = new JPanel();
Box box = Box.createVerticalBox();
_momentumTextField = new JTextField(8);
_momentumTextField.setEditable(true);
-
_momentumTextField.setText("" + String.format("%-9.5f", _oldMomentum));
_momentumTextField.addActionListener(new ActionListener() {
-
@Override
public void actionPerformed(ActionEvent arg0) {
setMomentum();
}
});
-
box.add(labeledTextField(MOMENTUMMAG, _momentumTextField, "GeV/c", -1));
-
_theta = new JTextField(8);
_phi = new JTextField(8);
-
_theta.setText("15.0");
_phi.setText("0.0");
-
box.add(labeledTextField(SMALL_THETA, _theta, "deg", 20));
box.add(Box.createVerticalStrut(5));
box.add(labeledTextField(SMALL_PHI, _phi, "deg", 20));
box.add(Box.createVerticalStrut(5));
-
panel.add(box);
panel.setBorder(new CommonBorder("Initial Momentum and Direction"));
return panel;
}
- // create the cutoff panel
+ /**
+ * Creates the subpanel for integration cutoff controls.
+ * @return A JPanel with cutoff and accuracy settings.
+ */
private JPanel cutoffPanel() {
-
_fixedZ = new JTextField(8);
- _fixedS = new JTextField(8);
_fixedRho = new JTextField(8);
-
+ _sMax = new JTextField(8);
_accuracy = new JTextField(8);
-
_fixedRho.setText("100.0");
- _fixedS.setText("29.990");
_fixedZ.setText("575.0");
-
+ _sMax.setText("800.0");
_accuracy.setText("10");
-
-
JPanel panel = new JPanel();
Box box = Box.createVerticalBox();
box.add(cutoffType());
-
box.add(Box.createVerticalStrut(5));
box.add(labeledTextField(" Stopping Z", _fixedZ, "cm", -1));
box.add(Box.createVerticalStrut(5));
- box.add(labeledTextField(" Stopping S", _fixedS, "cm", -1));
- box.add(Box.createVerticalStrut(5));
box.add(labeledTextField(" Stopping " + SMALL_RHO, _fixedRho, "cm", -1));
box.add(Box.createVerticalStrut(5));
+ box.add(labeledTextField(" Smax", _sMax, "cm", -1));
+ box.add(Box.createVerticalStrut(5));
box.add(labeledTextField(" Accuracy", _accuracy, "microns", -1));
box.add(Box.createVerticalStrut(5));
-
panel.add(box);
panel.setBorder(new CommonBorder("Integration Controls"));
return panel;
}
+ /**
+ * Creates the component for selecting the algorithm type.
+ * @return A JPanel containing algorithm radio buttons.
+ */
private JPanel cutoffType() {
-
ButtonGroup bg = new ButtonGroup();
-
createAlgorithmButtons(bg);
JPanel spanel = new JPanel();
spanel.setLayout(new FlowLayout(FlowLayout.LEFT, 6, 0));
spanel.add(_standardRB);
spanel.add(_fixedZRB);
- spanel.add(_fixedSRB);
spanel.add(_fixedRhoRB);
-
JPanel panel = new JPanel();
panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS));
panel.add(spanel);
@@ -533,25 +472,20 @@ private JPanel cutoffType() {
}
/**
- * Create the panel that allows the user to select the energy
- *
- * @return the panel for selecting the energy.
+ * Creates the subpanel for displaying particle energy and mass information.
+ * @return A JPanel with particle kinematic information.
*/
private JPanel energyPanel() {
JPanel panel = new JPanel();
-
Box box = Box.createVerticalBox();
-
_massTextField = new JTextField(8);
_relativisticGamma = new JTextField(8);
_relativisticBeta = new JTextField(8);
_totalEnergyTextField = new JTextField(8);
-
disable(_massTextField);
disable(_relativisticGamma);
disable(_relativisticBeta);
disable(_totalEnergyTextField);
-
box.add(Box.createVerticalStrut(5));
box.add(labeledTextField(MASS, _massTextField, " GeV/c" + SUPER2, -1));
box.add(Box.createVerticalStrut(5));
@@ -561,22 +495,25 @@ private JPanel energyPanel() {
box.add(Box.createVerticalStrut(5));
box.add(labeledTextField(TOTENERGY, _totalEnergyTextField, " GeV", -1));
box.add(Box.createVerticalStrut(5));
- box.add(Box.createVerticalStrut(5));
-
panel.add(box);
panel.setBorder(new CommonBorder("Particle Energy"));
return panel;
}
+ /**
+ * Disables a text field and styles it as read-only.
+ * @param tf The JTextField to disable.
+ */
private void disable(JTextField tf) {
tf.setEditable(false);
tf.setBackground(Color.black);
tf.setForeground(Color.cyan);
}
- // set the momentum
+ /**
+ * Calculates and updates relativistic values based on the current momentum.
+ */
private void setMomentum() {
-
double momentum = 0.0;
try {
momentum = Double.parseDouble(_momentumTextField.getText());
@@ -585,40 +522,36 @@ private void setMomentum() {
_momentumTextField.setText("" + String.format("%-9.5f", _oldMomentum));
return;
}
-
_oldMomentum = momentum;
LundId lid = _lundComboBox.getSelectedId();
- // mass GeV
double mass = lid.getMass();
-
_energy = Math.sqrt(momentum * momentum + mass * mass);
-
_gamma = _energy / mass;
_beta = Math.sqrt(1.0 - 1.0 / (_gamma * _gamma));
-
_relativisticGamma.setText(String.format("%-9.5f", _gamma));
_relativisticBeta.setText(String.format("%-13.9f", _beta));
_massTextField.setText(String.format("%-10.6f", mass));
_totalEnergyTextField.setText(String.format("%-9.5f", _energy));
}
- // user has hit ok or cancel
+ /**
+ * Closes the dialog.
+ * @param reason Integer code indicating why the dialog is closing.
+ */
private void doClose(int reason) {
setVisible(false);
}
/**
- * Create a nice padded panel.
- *
- * @param hpad the pixel pad on the left and right
- * @param vpad the pixel pad on the top and bottom
- * @param component the main component placed in the center.
- * @return the padded panel
+ * Creates a padded JPanel around a component.
+ * @param hpad Horizontal padding.
+ * @param vpad Vertical padding.
+ * @param component The centered component.
+ * @return The padded JPanel.
*/
public static JPanel paddedPanel(int hpad, int vpad, Component component) {
JPanel panel = new JPanel();
panel.setLayout(new BorderLayout());
-
if (hpad > 0) {
panel.add(Box.createHorizontalStrut(hpad), BorderLayout.WEST);
panel.add(Box.createHorizontalStrut(hpad), BorderLayout.EAST);
@@ -627,60 +560,53 @@ public static JPanel paddedPanel(int hpad, int vpad, Component component) {
panel.add(Box.createVerticalStrut(vpad), BorderLayout.NORTH);
panel.add(Box.createVerticalStrut(vpad), BorderLayout.SOUTH);
}
-
panel.add(component, BorderLayout.CENTER);
return panel;
}
/**
- * Center a component.
- *
- * @param component The Component to center.
- * @param dh offset from horizontal center.
- * @param dv offset from vertical center.
+ * Centers a component on the screen.
+ * @param component The component to center.
*/
public static void centerComponent(Component component) {
-
- if (component == null)
- return;
-
+ if (component == null) return;
try {
Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
Dimension componentSize = component.getSize();
- if (componentSize.height > screenSize.height) {
- componentSize.height = screenSize.height;
- }
- if (componentSize.width > screenSize.width) {
- componentSize.width = screenSize.width;
- }
-
+ if (componentSize.height > screenSize.height) componentSize.height = screenSize.height;
+ if (componentSize.width > screenSize.width) componentSize.width = screenSize.width;
int x = ((screenSize.width - componentSize.width) / 2);
int y = ((screenSize.height - componentSize.height) / 2);
-
component.setLocation(x, y);
-
} catch (Exception e) {
component.setLocation(200, 200);
e.printStackTrace();
}
}
- // for a nice border
+ /**
+ * A custom titled border for dialog subpanels.
+ */
public class CommonBorder extends TitledBorder {
-
+ /** Default etched border. */
public Border etched = BorderFactory.createEtchedBorder();
+ /** Default font for the title. */
public Font font = new Font("SandSerif", Font.PLAIN, 9);
-
+
+ /** Default constructor. */
public CommonBorder() {
super(BorderFactory.createEtchedBorder());
setTitleColor(Color.blue);
setTitleFont(font);
}
-
+
+ /**
+ * Constructor with a specific title.
+ * @param title The border title.
+ */
public CommonBorder(String title) {
this();
setTitle(title);
}
}
-
-}
\ No newline at end of file
+}
diff --git a/common-tools/cnuphys/swimmer/src/main/java/cnuphys/lund/TrajectoryRowData.java b/common-tools/cnuphys/swimmer/src/main/java/cnuphys/lund/TrajectoryRowData.java
index 38aa715375..d455ddbc40 100644
--- a/common-tools/cnuphys/swimmer/src/main/java/cnuphys/lund/TrajectoryRowData.java
+++ b/common-tools/cnuphys/swimmer/src/main/java/cnuphys/lund/TrajectoryRowData.java
@@ -1,7 +1,13 @@
package cnuphys.lund;
+import cnuphys.adaptiveSwim.SwimType;
+
public class TrajectoryRowData {
+ /**
+ * Contains all the data needed to swim a particle
+ */
+
protected int trackId; //track id
// the lund id
@@ -30,6 +36,9 @@ public class TrajectoryRowData {
// source
protected String source;
+
+ // MC or reconstructed-event trajectory
+ protected TrajectoryType trajectoryType;
/**
* Create a data row for display in the table.
@@ -50,7 +59,7 @@ public class TrajectoryRowData {
* the initial azimuthal angle (degrees)
*/
public TrajectoryRowData(int trackId, LundId lundId, double xo, double yo, double zo, double p, double theta, double phi,
- int status, String source) {
+ int status, String source, TrajectoryType trajectoryType) {
super();
this.trackId = trackId;
this.lundId = lundId;
@@ -62,11 +71,38 @@ public TrajectoryRowData(int trackId, LundId lundId, double xo, double yo, doubl
this.phi = phi;
this.status = status;
this.source = source;
+ this.trajectoryType = trajectoryType;
if (lundId == null) {
lundId = LundSupport.getInstance().get(0);
}
}
+
+ /**
+ * Compatibility constructor for callers using the legacy adaptive-swimmer enum.
+ */
+ public TrajectoryRowData(int trackId, LundId lundId, double xo, double yo, double zo, double p, double theta,
+ double phi, int status, String source, SwimType swimType) {
+ this(trackId, lundId, xo, yo, zo, p, theta, phi, status, source,
+ swimType == SwimType.MCSWIM ? TrajectoryType.MC : TrajectoryType.RECON);
+ }
+
+ /**
+ * Get whether this row represents an MC or reconstructed trajectory.
+ *
+ * @return the trajectory source type
+ */
+ public TrajectoryType getTrajectoryType() {
+ return trajectoryType;
+ }
+
+ /**
+ * Get the swim type, either MC or REC
+ * @return the swim type
+ */
+ public SwimType getSwimType() {
+ return trajectoryType == TrajectoryType.MC ? SwimType.MCSWIM : SwimType.RECONSWIM;
+ }
/**
* Get the track id
diff --git a/common-tools/cnuphys/swimmer/src/main/java/cnuphys/lund/TrajectoryTable.java b/common-tools/cnuphys/swimmer/src/main/java/cnuphys/lund/TrajectoryTable.java
index 774c970328..8b66113257 100644
--- a/common-tools/cnuphys/swimmer/src/main/java/cnuphys/lund/TrajectoryTable.java
+++ b/common-tools/cnuphys/swimmer/src/main/java/cnuphys/lund/TrajectoryTable.java
@@ -6,10 +6,11 @@
import javax.swing.JScrollPane;
import javax.swing.JTable;
+import javax.swing.WindowConstants;
import javax.swing.table.TableColumn;
public class TrajectoryTable extends JTable {
-
+
// a scroll pane for this table
private JScrollPane _scrollPane;
@@ -36,7 +37,7 @@ public TrajectoryTable() {
/**
* Get the trajectory data model.
- *
+ *
* @return the trajectory data model.
*/
public TrajectoryTableModel getTrajectoryModel() {
@@ -68,13 +69,13 @@ public JScrollPane getScrollPane() {
/**
* main program for testing.
- *
+ *
* @param args
*/
public static void main(String[] args) {
javax.swing.JFrame testFrame = new javax.swing.JFrame("test frame");
java.awt.Container cp = testFrame.getContentPane();
- testFrame.setDefaultCloseOperation(javax.swing.JFrame.EXIT_ON_CLOSE);
+ testFrame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
cp.setLayout(new BorderLayout(4, 0));
diff --git a/common-tools/cnuphys/swimmer/src/main/java/cnuphys/lund/TrajectoryTableModel.java b/common-tools/cnuphys/swimmer/src/main/java/cnuphys/lund/TrajectoryTableModel.java
index 1b3ad8079f..1d8eec8712 100644
--- a/common-tools/cnuphys/swimmer/src/main/java/cnuphys/lund/TrajectoryTableModel.java
+++ b/common-tools/cnuphys/swimmer/src/main/java/cnuphys/lund/TrajectoryTableModel.java
@@ -1,6 +1,7 @@
package cnuphys.lund;
-import java.util.Vector;
+import java.util.ArrayList;
+import java.util.List;
import javax.swing.table.DefaultTableModel;
@@ -34,7 +35,7 @@ public class TrajectoryTableModel extends DefaultTableModel {
};
// the model data
- protected Vectornull.
diff --git a/common-tools/cnuphys/swimmer/src/main/java/cnuphys/rk4/ButcherTableau.java b/common-tools/cnuphys/swimmer/src/main/java/cnuphys/rk4/ButcherTableau.java
index 5db3d6f895..16166f1717 100644
--- a/common-tools/cnuphys/swimmer/src/main/java/cnuphys/rk4/ButcherTableau.java
+++ b/common-tools/cnuphys/swimmer/src/main/java/cnuphys/rk4/ButcherTableau.java
@@ -2,26 +2,8 @@
public class ButcherTableau {
- public static ButcherTableau RK4 = new ButcherTableau("RK4", false, makeRow(0.), makeRow(1. / 2., 1. / 2.),
- makeRow(1. / 2., 0, 1. / 2), makeRow(1., 0, 0, 1.), makeRow(1. / 6., 1. / 3., 1. / 3., 1. / 6.) // the
- // b's
- );
-
- public static ButcherTableau RULE38 = new ButcherTableau("RULE38", false, makeRow(0.), makeRow(1. / 3., 1. / 3.),
- makeRow(2. / 3., -1. / 3., 1.), makeRow(1., 1., -1., 1.), makeRow(1. / 8., 3. / 8., 3. / 8., 1. / 8.) // the
- // b's
- );
-
- public static ButcherTableau FEHLBERG_ORDER5 = new ButcherTableau("FEHLBERG_ORDER5", true, makeRow(0.),
- makeRow(1. / 4., 1. / 4.), makeRow(3. / 8., 3. / 32., 9. / 32.),
- makeRow(12. / 13, 1932. / 2197, -7200. / 2197., 7296. / 2197.),
- makeRow(1., 439. / 216., -8., 3680. / 513., -845. / 4104.),
- makeRow(1. / 2., -8. / 27., 2., -3544. / 2565, 1859. / 4104., -11. / 40.),
- makeRow(16. / 135., 0., 6656. / 12825., 28561. / 56430., -9. / 50., 2. / 55.), // b's
- makeRow(25. / 216., 0., 1408. / 2565., 2197. / 4104., -1. / 5., 0.) // bstars's
- );
- public static ButcherTableau DORMAND_PRINCE = new ButcherTableau("DORMAND_PRINCE", true, makeRow(0.),
+ public static final ButcherTableau DORMAND_PRINCE = new ButcherTableau("DORMAND_PRINCE", true, makeRow(0.),
makeRow(1. / 5., 1. / 5.), makeRow(3. / 10., 3. / 40., 9. / 40.),
makeRow(4. / 5., 44. / 45., -56. / 15, 32. / 9.),
makeRow(8. / 9., 19372. / 6561., -25360. / 2187., 64448. / 6561., -212. / 729.),
@@ -31,10 +13,10 @@ public class ButcherTableau {
makeRow(35. / 384., 0, 500. / 1113., 125. / 192., -2187. / 6784., 11. / 84., 0) // bstars's
);
- public static ButcherTableau CASH_KARP = new ButcherTableau("CASH_KARP", true, makeRow(0.),
- makeRow(1. / 5., 1. / 5.),
+ public static final ButcherTableau CASH_KARP = new ButcherTableau("CASH_KARP", true, makeRow(0.),
+ makeRow(1. / 5., 1. / 5.),
makeRow(3. / 10., 3. / 40., 9. / 40.),
- makeRow(3. / 5, 3. / 10., -9. / 10., 6. / 5.),
+ makeRow(3. / 5, 3. / 10., -9. / 10., 6. / 5.),
makeRow(1., -11. / 54., 5. / 2., -70. / 27., 35. / 27.),
makeRow(7. / 8., 1631. / 55296., 175. / 512., 575. / 13824., 44275. / 110592., 253. / 4096.),
makeRow(37. / 378., 0, 250. / 621., 125. / 594., 0., 512. / 1771.), // b's
@@ -47,12 +29,10 @@ public class ButcherTableau {
private double c[];
private boolean _augmented;
private double bdiff[];
- private String _name;
private int s; // number of stages
private ButcherTableau(String name, boolean augmented, double[]... rows) {
- _name = name;
_augmented = augmented;
if (augmented) {
s = rows.length - 2;
@@ -106,7 +86,7 @@ private ButcherTableau(String name, boolean augmented, double[]... rows) {
/**
* Get the number of stages
- *
+ *
* @return the number of stages
*/
public int getNumStage() {
@@ -149,45 +129,4 @@ private double asum(int index) {
}
return sum;
}
-
- private void printSumStr(int index) {
- double sum = asum(index);
- double c = c(index);
- double diff = Math.abs(sum - c);
- System.out.println("consistency sum check [" + index + "] sum: " + sum + " c: " + c + " diff: " + diff + " "
- + ((Math.abs(diff) < 1.0e-15) ? "PASS" : "FAIL"));
- }
-
- public void report() {
- System.out.println("=============");
- System.out.println(_name);
- System.out.println("augmented: " + isAugmented());
- System.out.println("s = " + getNumStage());
-
- int s = getNumStage();
- for (int row = 2; row <= s; row++) {
- for (int col = 1; col < row; col++) {
- printVal(row, col);
- }
- System.out.println();
- }
-
- for (int i = 2; i <= s; i++) {
- printSumStr(i);
- }
-
- }
-
- private void printVal(int i, int j) {
- String s = String.format("a[%d][%d] = %-12.5f ", i, j, a[i][j]);
- System.out.print(s);
- }
-
- public static void main(String arg[]) {
- RK4.report();
- RULE38.report();
- FEHLBERG_ORDER5.report();
- DORMAND_PRINCE.report();
- CASH_KARP.report();
- }
}
diff --git a/common-tools/cnuphys/swimmer/src/main/java/cnuphys/rk4/RkTest.java b/common-tools/cnuphys/swimmer/src/main/java/cnuphys/rk4/RkTest.java
deleted file mode 100644
index 0fd048169d..0000000000
--- a/common-tools/cnuphys/swimmer/src/main/java/cnuphys/rk4/RkTest.java
+++ /dev/null
@@ -1,126 +0,0 @@
-package cnuphys.rk4;
-
-public class RkTest {
-
- //used to get good timing
- private static int ITERATIONS = 100;
-
-
- // a testing function for y'' = y
- public static IDerivative CoshLike = new IDerivative() {
-
- @Override
- public void derivative(double t, double[] y, double[] dydt) {
- dydt[0] = y[1];
- dydt[1] = y[0];
- }
-
- };
-
- /**
- * Test the uniform step size
- * @param yo
- * initial values. Probably something like (xo, yo, zo, vxo, vyo,
- * vzo).
- * @param to
- * the initial value of the independent variable, e.g., time.
- * @param tf
- * the maximum value of the independent variable.
- * @param deriv
- * the derivative computer (interface). This is where the problem
- * specificity resides.
- * @param stopper
- * if not null will be used to exit the integration
- * early because some condition has been reached.
- * @param listener
- * listens for each step
- * @param answer
- */
- public static void TestUniform(double yo[],
- double to,
- double tf,
- double h,
- IDerivative deriv,
- IStopper stopper,
- IRkListener listener,
- double answer[]) {
-
- RungeKutta rk = new RungeKutta();
-
- for (int i = 1; i <= ITERATIONS; i++) {
- rk.uniformStep(yo, to, tf, h, deriv, stopper, listener);
- }
-
- }
-
- public static void test() {
- System.err.println("Testing Coshlike function");
- testCoshLike(0.01);
- testCoshLike(0.001);
- testCoshLike(0.0001);
- testCoshLike(0.00001);
-
- }
-
- private static void testCoshLike(double h) {
-
- double to = 0;
- double tf = 2.0;
- double yo[] = {1, 0};
- double result[] = new double[2];
- double answer[] = {Math.cosh(2), Math.sinh(2)};
- double diff[] = new double[result.length];
-
- IRkListener listener = new IRkListener() {
-
- @Override
- public void nextStep(double newT, double[] newY, double h) {
- result[0] = newY[0];
- result[1] = newY[1];
- }
-
- };
-
- long startTime = System.nanoTime();
- TestUniform(yo, to, tf, h, CoshLike, null, listener, answer);
- long estimatedTime = System.nanoTime() - startTime;
- double time = (1.0e-9*estimatedTime)/ITERATIONS;
-
- for (int i = 0; i < result.length; i++) {
- diff[i] = answer[i] - result[i];
- }
-
- System.err.println("\n-----------\nh = " + h);
- System.err.println("time: " + time);
- System.err.println(vStr("Result", result));
- System.err.println(vStr("Answer", answer));
- System.err.println(vStr(" Diff", diff));
-
- }
-
- private static String vStr(String name, double v[]) {
- StringBuffer sb = new StringBuffer(256);
- sb.append(name + ": [");
-
-
- int len = v.length;
- int lm1 = len-1;
-
- for (int i = 0; i < len; i++) {
- sb.append(v[i]);
- if (i < lm1) {
- sb.append(", ");
- }
- }
-
-
- sb.append("]");
-
- return sb.toString();
- }
-
- public static void main(String arg[]) {
- test();
- }
-
-}
diff --git a/common-tools/cnuphys/swimmer/src/main/java/cnuphys/rk4/RungeKutta.java b/common-tools/cnuphys/swimmer/src/main/java/cnuphys/rk4/RungeKutta.java
index d1fb8ca365..d439fe9e85 100644
--- a/common-tools/cnuphys/swimmer/src/main/java/cnuphys/rk4/RungeKutta.java
+++ b/common-tools/cnuphys/swimmer/src/main/java/cnuphys/rk4/RungeKutta.java
@@ -1,14 +1,13 @@
package cnuphys.rk4;
-import java.util.ArrayDeque;
import java.util.List;
/**
* Static methods for Runge-Kutta 4 integration, including a constant stepsize
* method and an adaptive stepsize method.
- *
+ *
* @author heddle
- *
+ *
*/
public class RungeKutta {
@@ -17,7 +16,7 @@ public class RungeKutta {
public static double DEFMINSTEPSIZE = 1.0e-5;
public static double DEFMAXSTEPSIZE = 0.4;
-
+
private double _minStepSize = DEFMINSTEPSIZE;
private double _maxStepSize = DEFMAXSTEPSIZE;
@@ -34,15 +33,15 @@ public RungeKutta() {
/**
* Driver that uses the RungeKutta advance with a uniform step size. (i.e.,
* this does NOT use an adaptive step size.)
- *
+ *
* This version stores each step into the arrays t[] and y[][]. An
* alternative does not store the results but instead uses an IRk4Listener
* to notify the listener that the next step has been advanced.
- *
+ *
* A very typical case is a 2nd order ODE converted to a 1st order where the
* dependent variables are x, y, z, vx, vy, vz and the independent variable
* is time.
- *
+ *
* @param yo
* initial values. Probably something like (xo, yo, zo, vxo, vyo,
* vzo).
@@ -97,7 +96,7 @@ public int uniformStep(double yo[],
@Override
public void nextStep(double tNext, double yNext[], double h) {
-
+
if (step < t.length) {
t[step] = tNext;
for (int i = 0; i < nDim; i++) {
@@ -113,20 +112,20 @@ public void nextStep(double tNext, double yNext[], double h) {
return uniformStep(yo, to, tf, h, deriv, stopper, listener);
}
-
+
/**
* Integrator that uses the standard RK4 advance with a uniform step size.
* (i.e., this does NOT use an adaptive step size.)
- *
+ *
* This version uses an IRk4Listener to notify the listener that the next
* step has been advanced.
- *
+ *
* A very typical case is a 2nd order ODE converted to a 1st order where the
* dependent variables are x, y, z, vx, vy, vz and the independent variable
* is time.
- *
+ *
* @param yo
* initial values. Probably something like (xo, yo, zo, vxo, vyo,
* vzo).
@@ -159,14 +158,14 @@ public int uniformStep(double yo[],
/**
* Integrator that uses the RungeKutta advance with a Butcher Tableau and
* constant stepsize. (i.e., this does NOT use an adaptive step size.)
- *
+ *
* This version uses an IRk4Listener to notify the listener that the next
* step has been advanced.
- *
+ *
* A very typical case is a 2nd order ODE converted to a 1st order where the
* dependent variables are x, y, z, vx, vy, vz and the independent variable
* is time.
- *
+ *
* @param yo
* initial values. Probably something like (xo, yo, zo, vxo, vyo,
* vzo).
@@ -203,14 +202,14 @@ public int uniformStep(double yo[],
/**
* Integrator that uses the RungeKutta advance with a Butcher Tableau and
* adaptive stepsize and a tolerance vector.
- *
+ *
* This version uses an IRk4Listener to notify the listener that the next
* step has been advanced.
- *
+ *
* A very typical case is a 2nd order ODE converted to a 1st order where the
* dependent variables are x, y, z, vx, vy, vz and the independent variable
* is time.
- *
+ *
* @param yo
* initial values. Probably something like (xo, yo, zo, vxo, vyo,
* vzo).
@@ -273,20 +272,20 @@ public void nextStep(double tNext, double yNext[], double h) {
return adaptiveStep(yo, to, tf, h, deriv, stopper, listener, tableau, relTolerance, hdata);
}
-
+
/**
* Integrator that uses the RungeKutta advance with a Butcher Tableau and
* adaptive stepsize
- *
+ *
* This version uses an IRk4Listener to notify the listener that the next
* step has been advanced.
- *
+ *
* A very typical case is a 2nd order ODE converted to a 1st order where the
* dependent variables are x, y, z, vx, vy, vz and the independent variable
* is time.
- *
+ *
* @param yo
* initial values. Probably something like (xo, yo, zo, vxo, vyo,
* vzo).
@@ -329,14 +328,14 @@ public int adaptiveStep(double yo[], double to, double tf, double h, IDerivative
/**
* Integrator that uses the RungeKutta advance with a Butcher Tableau and
* adaptive stepsize
- *
+ *
* This version uses an IRk4Listener to notify the listener that the next
* step has been advanced.
- *
+ *
* A very typical case is a 2nd order ODE converted to a 1st order where the
* dependent variables are x, y, z, vx, vy, vz and the independent variable
* is time.
- *
+ *
* @param yo
* initial values. Probably something like (xo, yo, zo, vxo, vyo,
* vzo).
@@ -383,14 +382,14 @@ public int adaptiveStep(double yo[], double yf[], double to, double tf, double h
* Integrator that uses the RungeKutta advance with a Butcher Tableau and
* adaptive stepsize. This uses an desired absolute error relative to some
* scale (of max values of the dependent variables)
- *
+ *
* This version uses an IRk4Listener to notify the listener that the next
* step has been advanced.
- *
+ *
* A very typical case is a 2nd order ODE converted to a 1st order where the
* dependent variables are x, y, z, vx, vy, vz and the independent variable
* is time.
- *
+ *
* @param yo
* initial values. Probably something like (xo, yo, zo, vxo, vyo,
* vzo).
@@ -450,14 +449,14 @@ public void nextStep(double tNext, double yNext[], double h) {
* Integrator that uses the RungeKutta advance with a Butcher Tableau and
* adaptive stepsize. This uses an desired absolute error relative to some
* scale (of max values of the dependent variables)
- *
+ *
* This version uses an IRk4Listener to notify the listener that the next step
* has been advanced.
- *
+ *
* A very typical case is a 2nd order ODE converted to a 1st order where the
* dependent variables are x, y, z, vx, vy, vz and the independent variable
* is time.
- *
+ *
* @param yo
* initial values. Probably something like (xo, yo, zo, vxo, vyo,
* vzo).
@@ -503,7 +502,6 @@ public int adaptiveStep(double yo[],
double yscale[],
double hdata[]) throws RungeKuttaException {
- // ButcherTableauAdvance advancer = new ButcherTableauAdvance(tableau);
// use a simple half-step advance
IAdvance advancer = new HalfStepAdvance();
return driver(yo, to, tf, h, deriv, stopper, listener, advancer, eps, yscale, hdata);
@@ -513,24 +511,20 @@ public int adaptiveStep(double yo[],
private double[] copy(double v[]) {
double w[] = new double[v.length];
System.arraycopy(v, 0, w, 0, v.length);
-
- // for (int i = 0; i < v.length; i++) {
- // w[i] = v[i];
- // }
return w;
}
/**
* Driver that uses the RungeKutta advance with a uniform step size. (I.e.,
* this does NOT use an adaptive step size.)
- *
+ *
* This version uses an IRk4Listener to notify the listener that the next
* step has been advanced.
- *
+ *
* A very typical case is a 2nd order ODE converted to a 1st order where the
* dependent variables are x, y, z, vx, vy, vz and the independent variable
* is time.
- *
+ *
* @param yo
* initial values. Probably something like (xo, yo, zo, vxo, vyo,
* vzo).
@@ -597,14 +591,14 @@ private int driver(double yo[],
/**
* Driver that uses the RungeKutta advance with an adaptive step size
- *
+ *
* This version uses an IRk4Listener to notify the listener that the next
* step has been advanced.
- *
+ *
* A very typical case is a 2nd order ODE converted to a 1st order where the
* dependent variables are x, y, z, vx, vy, vz and the independent variable
* is time.
- *
+ *
* @param yo
* initial values. Probably something like (xo, yo, zo, vxo, vyo,
* vzo).
@@ -747,22 +741,22 @@ private int driver(double yo[],
}
return nstep;
}
-
+
/**
* Driver that uses the RungeKutta advance with an adaptive step size
- *
+ *
* This version uses an IRk4Listener to notify the listener that the next
* step has been advanced.
- *
+ *
* A very typical case is a 2nd order ODE converted to a 1st order where the
* dependent variables are x, y, z, vx, vy, vz and the independent variable
* is time.
- *
+ *
* @param uo
* initial values. Probably something like (xo, yo, zo, vxo, vyo,
* vzo).
- * @param uf space to hold the final values
+ * @param uf space to hold the final values
* @param to
* the initial value of the independent variable, e.g., time.
* @param tf
@@ -819,7 +813,7 @@ private int driver(double uo[],
// yf is the current value of the state vector,
// typically [x, y, z, vx, vy, vz] and derivative
-
+
double yt[] = new double[nDim];
double yt2[] = new double[nDim];
@@ -835,7 +829,7 @@ private int driver(double uo[],
while (t < tf) {
// use derivs at previous t
deriv.derivative(t, yt, dydt);
-
+
advancer.advance(t, yt, dydt, h, deriv, yt2, error);
boolean decreaseStep = false;
@@ -843,7 +837,7 @@ private int driver(double uo[],
decreaseStep = error[i] > relTolerance[i];
// System.err.println("error " + error[i] + " reltol: " +
// relTolerance[i] + " dec: " + decreaseStep);
- if (decreaseStep) {
+ if (decreaseStep) {
break;
}
}
@@ -905,14 +899,14 @@ private int driver(double uo[],
* Driver that uses the RungeKutta advance with an adaptive step size. This
* uses an desired absolute error relative to some scale (of max values of
* the dependent variables)
- *
+ *
* This version uses an IRk4Listener to notify the listener that the next
* step has been advanced.
- *
+ *
* A very typical case is a 2nd order ODE converted to a 1st order where the
* dependent variables are x, y, z, vx, vy, vz and the independent variable
* is time.
- *
+ *
* @param yo
* initial values. Probably something like (xo, yo, zo, vxo, vyo,
* vzo).
@@ -1156,7 +1150,7 @@ public void advance(double t,
// compute absolute errors
for (int i = 0; i < ndim; i++) {
error[i] = Math.abs(yfull[i] - yout[i]);
-
+
// if (error[i] > 1.0e-10) {
// error[i] /= Math.max(Math.abs(yfull[i]), Math.abs(yout[i]));
// }
@@ -1268,7 +1262,7 @@ public boolean computesError() {
/**
* Set the maximum step size
- *
+ *
* @param maxSS
* the maximum stepsize is whatever units you are using
*/
@@ -1278,7 +1272,7 @@ public void setMaxStepSize(double maxSS) {
/**
* Set the minimum step size
- *
+ *
* @param maxSS
* the minimum stepsize is whatever units you are using
*/
@@ -1288,16 +1282,16 @@ public void setMinStepSize(double minSS) {
/**
* Get the maximum step size
- *
+ *
* @return the maximum stepsize is whatever units you are using
*/
public double getMaxStepSize() {
return _maxStepSize;
}
-
+
/**
* Get the minimum step size
- *
+ *
* @return the minimum stepsize is whatever units you are using
*/
public double getMinStepSize() {
diff --git a/common-tools/cnuphys/swimmer/src/main/java/cnuphys/swim/BeamLineStopper.java b/common-tools/cnuphys/swimmer/src/main/java/cnuphys/swim/BeamLineStopper.java
index 22bc18daf2..2f08c148ef 100644
--- a/common-tools/cnuphys/swimmer/src/main/java/cnuphys/swim/BeamLineStopper.java
+++ b/common-tools/cnuphys/swimmer/src/main/java/cnuphys/swim/BeamLineStopper.java
@@ -8,8 +8,8 @@ public class BeamLineStopper implements IStopper {
private double _xB;
private double _yB;
-
-
+
+
double min = Double.POSITIVE_INFINITY;
public BeamLineStopper(double xB, double yB) {
// DC reconstruction units are cm. Swim units are m. Hence scale by
@@ -22,8 +22,9 @@ public BeamLineStopper(double xB, double yB) {
public boolean stopIntegration(double t, double[] y) {
double r = Math.sqrt((_xB-y[0]* 100.) * (_xB-y[0]* 100.) + (_yB-y[1]* 100.) * (_yB-y[1]* 100.));
- if(rtrue if we should show MC tracks
*/
public boolean showMonteCarloTracks() {
@@ -254,7 +136,7 @@ public boolean showMonteCarloTracks() {
/**
* Check whether we should showreconstructed tracks
- *
+ *
* @return true if we should show MC tracks
*/
public boolean showReconstructedTracks() {
diff --git a/common-tools/cnuphys/swimmer/src/main/java/cnuphys/swim/SwimTrajectory.java b/common-tools/cnuphys/swimmer/src/main/java/cnuphys/swim/SwimTrajectory.java
index 0abc9171be..634af17f7f 100644
--- a/common-tools/cnuphys/swimmer/src/main/java/cnuphys/swim/SwimTrajectory.java
+++ b/common-tools/cnuphys/swimmer/src/main/java/cnuphys/swim/SwimTrajectory.java
@@ -1,7 +1,6 @@
package cnuphys.swim;
import java.io.PrintStream;
-import java.io.Serializable;
import java.util.ArrayList;
import cnuphys.adaptiveSwim.AdaptiveSwimUtilities;
@@ -16,34 +15,30 @@
* is a collection of state vectors. A state vector is the six component vector:
*
- *
+ *
* @author heddle
*
*/
@@ -50,19 +49,19 @@ public class SwimZ {
// create a do nothing stopper for now
private IStopper _stopper = new DefaultStopper();
-
+
//need an integrator
private RungeKuttaZ _rk4 = new RungeKuttaZ();
//storage for values of independent variable z
- private ArrayListtrue if the torus was included in the swimming
- */
- public boolean includeTorus() {
- return _includeTorus;
- }
-
- /**
- * Set whether we included the torus
- *
- * @param incTorus the value of the flag
- * @return this object for chaining
- */
- public TestTrajectories setIncludeTorus(boolean incTorus) {
- _includeTorus = incTorus;
- return this;
- }
-
- /**
- * Set whether we included the solenoid
- *
- * @param incSolenoid the value of the flag
- */
- public TestTrajectories setIncludeSolenoid(boolean incSolenoid) {
- _includeSolenoid = incSolenoid;
- return this;
- }
-
- /**
- * Was the solenoid used
- *
- * @return true if the solenoid was included in the swimming
- */
- public boolean includeSolenoid() {
- return _includeSolenoid;
- }
-
- /**
- * Get the number of summaries
- *
- * @return the number of summaries
- */
- public int size() {
- return summaries.size();
- }
-}
diff --git a/common-tools/cnuphys/swimmer/src/main/java/cnuphys/swimtest/ThreadTest.java b/common-tools/cnuphys/swimmer/src/main/java/cnuphys/swimtest/ThreadTest.java
deleted file mode 100644
index 5212ec77e6..0000000000
--- a/common-tools/cnuphys/swimmer/src/main/java/cnuphys/swimtest/ThreadTest.java
+++ /dev/null
@@ -1,87 +0,0 @@
-package cnuphys.swimtest;
-
-import java.util.Random;
-
-import cnuphys.magfield.MagneticFields;
-import cnuphys.magfield.MagneticFields.FieldType;
-import cnuphys.rk4.RungeKuttaException;
-import cnuphys.swim.SwimTrajectory;
-import cnuphys.swim.Swimmer;
-
-public class ThreadTest {
-
-
- //test many points on different threads
- public static void threadTest(final int num, final int numThread) {
-
- SwimTest.memoryReport("staring thread test");
-
- MagneticFields.getInstance().setActiveField(FieldType.COMPOSITE);
-
-
-
- Runnable runnable = new Runnable() {
-
- @Override
- public void run() {
- System.err.println("Starting thread " + Thread.currentThread().getName());
- Swimmer swimmer = new Swimmer();
- long seed = 5347632765L;
-
- Random rand = new Random(seed);
-
- double hdata[] = new double[3];
-
- long time = System.currentTimeMillis();
- double pTot = 1.0;
- double theta = 15;
- double phi = 0;
- double z = 411.0 / 100.;
- double accuracy = 10 / 1.0e6;
- double stepSize = 0.01;
- int charge = -1;
-
- for (int i = 0; i < num; i++) {
-
- if ((i % 20) == 0) {
- System.err.println(Thread.currentThread().getName() + "[" + i + "]");
- }
-
- double x0 = (-40. + 20 * rand.nextDouble()) / 100.;
- double y0 = (10. + 40. * rand.nextDouble()) / 100.;
- double z0 = (180 + 40 * rand.nextDouble()) / 100.;
-
- SwimTrajectory traj;
- try {
- traj = swimmer.swim(charge, x0, y0, z0, pTot, theta, phi, z, accuracy, 10, 10, stepSize,
- Swimmer.CLAS_Tolerance, hdata);
-
- if (i == 0) {
- double lastY[] = traj.lastElement();
- SwimTest.printVect(lastY, "Thread " + Thread.currentThread().getName() + " first ");
- }
- if (i == (num-1)) {
- double lastY[] = traj.lastElement();
- SwimTest.printVect(lastY, "Thread " + Thread.currentThread().getName() + " last ");
- }
- } catch (RungeKuttaException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
-
- }
-
- System.err.println("Thread " + Thread.currentThread().getName() + " ending millis: "
- + (System.currentTimeMillis() - time));
-
-
-
- }
- };
-
- for (int i = 0; i < numThread; i++) {
- Thread thread = new Thread(runnable);
- thread.start();
- }
- }
-}
diff --git a/common-tools/swim-tools/src/main/java/org/jlab/clas/swimtools/Swim.java b/common-tools/swim-tools/src/main/java/org/jlab/clas/swimtools/Swim.java
index 66897dc346..32fc4183bf 100644
--- a/common-tools/swim-tools/src/main/java/org/jlab/clas/swimtools/Swim.java
+++ b/common-tools/swim-tools/src/main/java/org/jlab/clas/swimtools/Swim.java
@@ -330,7 +330,7 @@ public double[] SwimToPlaneTiltSecSysBdlXZPlane(int sector, double z_cm) {
}
if (szr != null) {
- double bdl = szr.sectorGetBDLXZPlane(sector, PC.RCF_z.getProbe());
+ double bdl = szr.sectorGetBDL(sector, PC.RCF_z.getProbe());
double pathLength = szr.getPathLength(); // already in cm
SwimZStateVector last = szr.last();
@@ -1428,4 +1428,4 @@ public double[] SwimToDCA(SwimTrajectory trk2) { //use for both traj to get doca
}
-}
\ No newline at end of file
+}