From 0f2f95bd0c67c0942a27d3e3d83dc652854762c6 Mon Sep 17 00:00:00 2001 From: Artem Lunev Date: Fri, 11 Jun 2021 21:07:47 +0200 Subject: [PATCH] 1.91FM_01 Better error handling in SearchTask: now instead of freezing on nonsensical values, an exception is thrown by the assign() method in ThermalProperties if the numeric properties in the ParameterVector do not pass the validate() check, and is handled by setting the status of the task to failed and breaking the main loop of the search. Better handling of very small pulses where calculations could previously start with a pulse width = 0 (less than the grid time step) Better calculation of the maximum temperature rise for the heating curves (baseline correction) --- pom.xml | 2 +- .../java/pulse/input/ExperimentalData.java | 22 ++++++++----------- src/main/java/pulse/math/ParameterVector.java | 10 +++++++++ .../pulse/problem/laser/DiscretePulse.java | 2 +- .../solvers/ImplicitLinearisedSolver.java | 1 + .../statements/ClassicalProblem2D.java | 3 ++- .../problem/statements/CoreShellProblem.java | 3 ++- .../problem/statements/DiathermicMedium.java | 3 ++- .../problem/statements/NonlinearProblem.java | 4 +++- .../statements/ParticipatingMedium.java | 3 ++- .../statements/PenetrationProblem.java | 3 ++- .../pulse/problem/statements/Problem.java | 11 ++++++++-- src/main/java/pulse/search/Optimisable.java | 4 +++- src/main/java/pulse/tasks/SearchTask.java | 18 +++++++++++---- src/main/java/pulse/ui/Launcher.java | 6 ++--- .../ui/components/panels/ProblemToolbar.java | 9 ++++---- src/main/resources/NumericProperty.xml | 6 ++--- src/main/resources/Version.txt | 2 +- 18 files changed, 72 insertions(+), 40 deletions(-) diff --git a/pom.xml b/pom.xml index 2151e49..53dd7b1 100644 --- a/pom.xml +++ b/pom.xml @@ -3,7 +3,7 @@ kotik-coder PULsE - 1.91FM + 1.91FM_01 PULsE Processing Unit for Laser flash Experiments diff --git a/src/main/java/pulse/input/ExperimentalData.java b/src/main/java/pulse/input/ExperimentalData.java index 9ae0d8a..8af9294 100644 --- a/src/main/java/pulse/input/ExperimentalData.java +++ b/src/main/java/pulse/input/ExperimentalData.java @@ -157,8 +157,8 @@ public List runningAverage(int reductionFactor) { List crudeAverage = new ArrayList<>(count / reductionFactor); - int start = indexRange.getLowerBound(); - int end = indexRange.getUpperBound(); + int start = indexRange.getLowerBound(); + int end = indexRange.getUpperBound(); int step = (end - start) / (count / reductionFactor); double av = 0; @@ -193,9 +193,9 @@ public List runningAverage(int reductionFactor) { * @see pulse.problem.statements.Problem.estimateSignalRange(ExperimentalData) */ - public double maxAdjustedSignal() { + public Point2D maxAdjustedSignal() { var degraded = runningAverage(REDUCTION_FACTOR); - return (max(degraded, pointComparator)).getY(); + return max(degraded, pointComparator); } /** @@ -217,18 +217,14 @@ public double maxAdjustedSignal() { */ public double halfRiseTime() { - var degraded = runningAverage(REDUCTION_FACTOR); - double max = (max(degraded, pointComparator)).getY(); - var baseline = new FlatBaseline(); + var degraded = runningAverage(REDUCTION_FACTOR); + var max = (max(degraded, pointComparator)); + var baseline = new FlatBaseline(); baseline.fitTo(this); - double halfMax = (max + baseline.valueAt(0)) / 2.0; - - int cutoffIndex = degraded.size() - 1; - - for(int i = cutoffIndex; i > 0 && degraded.get(i).getY() < halfMax; i--) - cutoffIndex--; + double halfMax = (max.getY() + baseline.valueAt(0)) / 2.0; + int cutoffIndex = degraded.indexOf(max); degraded = degraded.subList(0, cutoffIndex); int index = IndexRange.closestLeft(halfMax, diff --git a/src/main/java/pulse/math/ParameterVector.java b/src/main/java/pulse/math/ParameterVector.java index d815ab4..e8e4266 100644 --- a/src/main/java/pulse/math/ParameterVector.java +++ b/src/main/java/pulse/math/ParameterVector.java @@ -5,6 +5,7 @@ import pulse.math.linear.Vector; import pulse.math.transforms.Transformable; +import pulse.properties.NumericProperties; import pulse.properties.NumericPropertyKeyword; /** @@ -214,6 +215,15 @@ public String toString() { sb.append(" Values: " + super.toString()); return sb.toString(); } + + public boolean validate() { + for(int i = 0; i < this.dimension(); i++) { + if( !NumericProperties.derive(this.getIndex(i), inverseTransform(i)).validate() ) { + return false; + } + } + return true; + } public Segment[] getBounds() { return bounds; diff --git a/src/main/java/pulse/problem/laser/DiscretePulse.java b/src/main/java/pulse/problem/laser/DiscretePulse.java index 68c88e4..d3d511d 100644 --- a/src/main/java/pulse/problem/laser/DiscretePulse.java +++ b/src/main/java/pulse/problem/laser/DiscretePulse.java @@ -70,7 +70,7 @@ public double laserPowerAt(double time) { public void recalculate() { final double width = ((Number) pulse.getPulseWidth().getValue()).doubleValue(); - discretePulseWidth = grid.gridTime(width, timeFactor); + discretePulseWidth = Math.max( grid.gridTime(width, timeFactor), grid.getTimeStep() ); } /** diff --git a/src/main/java/pulse/problem/schemes/solvers/ImplicitLinearisedSolver.java b/src/main/java/pulse/problem/schemes/solvers/ImplicitLinearisedSolver.java index ad19bf8..a24f47a 100644 --- a/src/main/java/pulse/problem/schemes/solvers/ImplicitLinearisedSolver.java +++ b/src/main/java/pulse/problem/schemes/solvers/ImplicitLinearisedSolver.java @@ -116,6 +116,7 @@ public double evalRightBoundary(final int m, final double alphaN, final double b return (HH * getPreviousSolution()[N] + 2. * tau * betaN) / (2 * Bi1HTAU + HH - 2. * tau * (alphaN - 1)); } + @Override public DifferenceScheme copy() { var grid = getGrid(); diff --git a/src/main/java/pulse/problem/statements/ClassicalProblem2D.java b/src/main/java/pulse/problem/statements/ClassicalProblem2D.java index 143c01b..73a7c10 100644 --- a/src/main/java/pulse/problem/statements/ClassicalProblem2D.java +++ b/src/main/java/pulse/problem/statements/ClassicalProblem2D.java @@ -14,6 +14,7 @@ import pulse.problem.schemes.DifferenceScheme; import pulse.problem.schemes.Grid; import pulse.problem.schemes.Grid2D; +import pulse.problem.schemes.solvers.SolverException; import pulse.problem.statements.model.ExtendedThermalProperties; import pulse.problem.statements.model.ThermalProperties; import pulse.properties.Flag; @@ -102,7 +103,7 @@ public void optimisationVector(ParameterVector output, List flags) { } @Override - public void assign(ParameterVector params) { + public void assign(ParameterVector params) throws SolverException { super.assign(params); var properties = (ExtendedThermalProperties) getProperties(); diff --git a/src/main/java/pulse/problem/statements/CoreShellProblem.java b/src/main/java/pulse/problem/statements/CoreShellProblem.java index 85335c7..b30f53d 100644 --- a/src/main/java/pulse/problem/statements/CoreShellProblem.java +++ b/src/main/java/pulse/problem/statements/CoreShellProblem.java @@ -14,6 +14,7 @@ import pulse.math.transforms.InvDiamTransform; import pulse.math.transforms.InvLenSqTransform; import pulse.math.transforms.InvLenTransform; +import pulse.problem.schemes.solvers.SolverException; import pulse.problem.statements.model.ExtendedThermalProperties; import pulse.properties.Flag; import pulse.properties.NumericProperty; @@ -139,7 +140,7 @@ public void optimisationVector(ParameterVector output, List flags) { } @Override - public void assign(ParameterVector params) { + public void assign(ParameterVector params) throws SolverException { super.assign(params); for (int i = 0, size = params.dimension(); i < size; i++) { diff --git a/src/main/java/pulse/problem/statements/DiathermicMedium.java b/src/main/java/pulse/problem/statements/DiathermicMedium.java index f2516f9..ee2e31a 100644 --- a/src/main/java/pulse/problem/statements/DiathermicMedium.java +++ b/src/main/java/pulse/problem/statements/DiathermicMedium.java @@ -11,6 +11,7 @@ import pulse.math.transforms.AtanhTransform; import pulse.problem.schemes.DifferenceScheme; import pulse.problem.schemes.solvers.ImplicitDiathermicSolver; +import pulse.problem.schemes.solvers.SolverException; import pulse.problem.statements.model.DiathermicProperties; import pulse.problem.statements.model.ThermalProperties; import pulse.properties.Flag; @@ -80,7 +81,7 @@ public void optimisationVector(ParameterVector output, List flags) { } @Override - public void assign(ParameterVector params) { + public void assign(ParameterVector params) throws SolverException { super.assign(params); var properties = (DiathermicProperties) this.getProperties(); diff --git a/src/main/java/pulse/problem/statements/NonlinearProblem.java b/src/main/java/pulse/problem/statements/NonlinearProblem.java index 5dc7fec..1b0f7b1 100644 --- a/src/main/java/pulse/problem/statements/NonlinearProblem.java +++ b/src/main/java/pulse/problem/statements/NonlinearProblem.java @@ -17,6 +17,7 @@ import pulse.math.transforms.AtanhTransform; import pulse.problem.schemes.DifferenceScheme; import pulse.problem.schemes.ImplicitScheme; +import pulse.problem.schemes.solvers.SolverException; import pulse.properties.Flag; import pulse.properties.NumericProperty; import pulse.properties.Property; @@ -96,11 +97,12 @@ public void optimisationVector(ParameterVector output, List flags) { * * @param params the optimisation vector, containing a similar set of parameters * to this {@code Problem} + * @throws SolverException * @see listedTypes() */ @Override - public void assign(ParameterVector params) { + public void assign(ParameterVector params) throws SolverException { super.assign(params); var p = getProperties(); diff --git a/src/main/java/pulse/problem/statements/ParticipatingMedium.java b/src/main/java/pulse/problem/statements/ParticipatingMedium.java index e35947c..155f68e 100644 --- a/src/main/java/pulse/problem/statements/ParticipatingMedium.java +++ b/src/main/java/pulse/problem/statements/ParticipatingMedium.java @@ -12,6 +12,7 @@ import pulse.math.transforms.Transformable; import pulse.problem.schemes.DifferenceScheme; import pulse.problem.schemes.solvers.MixedCoupledSolver; +import pulse.problem.schemes.solvers.SolverException; import pulse.problem.statements.model.ThermalProperties; import pulse.problem.statements.model.ThermoOpticalProperties; import pulse.properties.Flag; @@ -85,7 +86,7 @@ public void optimisationVector(ParameterVector output, List flags) { } @Override - public void assign(ParameterVector params) { + public void assign(ParameterVector params) throws SolverException { super.assign(params); var properties = (ThermoOpticalProperties)getProperties(); diff --git a/src/main/java/pulse/problem/statements/PenetrationProblem.java b/src/main/java/pulse/problem/statements/PenetrationProblem.java index d2e9633..20361b6 100644 --- a/src/main/java/pulse/problem/statements/PenetrationProblem.java +++ b/src/main/java/pulse/problem/statements/PenetrationProblem.java @@ -10,6 +10,7 @@ import pulse.math.Segment; import pulse.problem.schemes.DifferenceScheme; import pulse.problem.schemes.solvers.ImplicitTranslucentSolver; +import pulse.problem.schemes.solvers.SolverException; import pulse.problem.statements.model.AbsorptionModel; import pulse.problem.statements.model.BeerLambertAbsorption; import pulse.properties.Flag; @@ -94,7 +95,7 @@ public void optimisationVector(ParameterVector output, List flags) { } @Override - public void assign(ParameterVector params) { + public void assign(ParameterVector params) throws SolverException { super.assign(params); double value; diff --git a/src/main/java/pulse/problem/statements/Problem.java b/src/main/java/pulse/problem/statements/Problem.java index fa15018..6990cb5 100644 --- a/src/main/java/pulse/problem/statements/Problem.java +++ b/src/main/java/pulse/problem/statements/Problem.java @@ -24,6 +24,7 @@ import pulse.problem.schemes.DifferenceScheme; import pulse.problem.schemes.Grid; import pulse.problem.schemes.solvers.Solver; +import pulse.problem.schemes.solvers.SolverException; import pulse.problem.statements.model.ThermalProperties; import pulse.properties.Flag; import pulse.properties.NumericProperty; @@ -199,7 +200,8 @@ public void retrieveData(ExperimentalData c) { */ public void estimateSignalRange(ExperimentalData c) { - final double signalHeight = c.maxAdjustedSignal() - baseline.valueAt(0); + var maxPoint = c.maxAdjustedSignal(); + final double signalHeight = maxPoint.getY() - baseline.valueAt(maxPoint.getX()); properties.setMaximumTemperature(derive(MAXTEMP, signalHeight)); } @@ -279,7 +281,12 @@ protected void setHeatLossParameter(ParameterVector output, int i, double Bi) { */ @Override - public void assign(ParameterVector params) { + public void assign(ParameterVector params) throws SolverException { + + if(!params.validate()) { + throw new SolverException("Parameter values not sensible"); + } + baseline.assign(params); for (int i = 0, size = params.dimension(); i < size; i++) { diff --git a/src/main/java/pulse/search/Optimisable.java b/src/main/java/pulse/search/Optimisable.java index 7909db1..5512f3a 100644 --- a/src/main/java/pulse/search/Optimisable.java +++ b/src/main/java/pulse/search/Optimisable.java @@ -3,6 +3,7 @@ import java.util.List; import pulse.math.ParameterVector; +import pulse.problem.schemes.solvers.SolverException; import pulse.properties.Flag; /** @@ -20,10 +21,11 @@ public interface Optimisable { * * @param params the optimisation vector, containing a similar set of parameters * to this {@code Problem} + * @throws SolverException if {@code params} contains invalid parameter values * @see pulse.util.PropertyHolder.listedTypes() */ - public void assign(ParameterVector params); + public void assign(ParameterVector params) throws SolverException; /** * Calculates the vector argument defined on Rn diff --git a/src/main/java/pulse/tasks/SearchTask.java b/src/main/java/pulse/tasks/SearchTask.java index eb1aa8c..f6077cd 100644 --- a/src/main/java/pulse/tasks/SearchTask.java +++ b/src/main/java/pulse/tasks/SearchTask.java @@ -48,6 +48,7 @@ import pulse.tasks.listeners.TaskRepositoryEvent; import pulse.tasks.logs.CorrelationLogEntry; import pulse.tasks.logs.DataLogEntry; +import pulse.tasks.logs.Details; import pulse.tasks.logs.Log; import pulse.tasks.logs.LogEntry; import pulse.tasks.logs.StateEntry; @@ -217,7 +218,14 @@ public ParameterVector searchVector() { */ public void assign(ParameterVector searchParameters) { - current.getProblem().assign(searchParameters); + try { + current.getProblem().assign(searchParameters); + } catch (SolverException e) { + var status = FAILED; + status.setDetails(Details.PARAMETER_VALUES_NOT_SENSIBLE); + setStatus(status); + e.printStackTrace(); + } curve.getRange().assign(searchParameters); } @@ -282,7 +290,7 @@ public void run() { outer: do { bufferFutures.clear(); - + for (var i = 0; i < bufferSize; i++) { if (current.getStatus() != IN_PROGRESS) @@ -291,12 +299,14 @@ public void run() { int iter = 0; try { - for (boolean finished = false; !finished && iter < maxIterations; iter++) - finished = optimiser.iteration(this); + for (boolean finished = false; !finished && iter < maxIterations; iter++) { + finished = optimiser.iteration(this); + } } catch (SolverException e) { setStatus(FAILED); System.err.println(this + " failed during execution. Details: "); e.printStackTrace(); + break outer; } if(iter >= maxIterations) { diff --git a/src/main/java/pulse/ui/Launcher.java b/src/main/java/pulse/ui/Launcher.java index 137b207..f352873 100644 --- a/src/main/java/pulse/ui/Launcher.java +++ b/src/main/java/pulse/ui/Launcher.java @@ -37,7 +37,8 @@ public class Launcher { private final static boolean DEBUG = false; private Launcher() { - arrangeErrorOutput(); + if(!DEBUG) + arrangeErrorOutput(); arrangeMessages(); } @@ -82,9 +83,6 @@ private static void splashScreen() { } private void arrangeErrorOutput() { - if (DEBUG) - return; - String path = Launcher.class.getProtectionDomain().getCodeSource().getLocation().getPath(); String decodedPath = ""; // diff --git a/src/main/java/pulse/ui/components/panels/ProblemToolbar.java b/src/main/java/pulse/ui/components/panels/ProblemToolbar.java index f619a64..fb1191a 100644 --- a/src/main/java/pulse/ui/components/panels/ProblemToolbar.java +++ b/src/main/java/pulse/ui/components/panels/ProblemToolbar.java @@ -57,12 +57,13 @@ private void addListeners() { // simulate btn listener btnSimulate.addActionListener((ActionEvent e) -> { + if (instance.getSelectedTask() == null) + instance.selectFirstTask(); + var t = instance.getSelectedTask(); - - if (t == null) - return; - + var calc = t.getCurrentCalculation(); + t.checkProblems(true); var status = t.getCurrentCalculation().getStatus(); diff --git a/src/main/resources/NumericProperty.xml b/src/main/resources/NumericProperty.xml index 941230b..a4158e4 100644 --- a/src/main/resources/NumericProperty.xml +++ b/src/main/resources/NumericProperty.xml @@ -346,7 +346,7 @@ abbreviation="<i>t</i><sub>lim</sub>" auto-adjustable="true" descriptor="End time, <i>t</i><sub>lim</sub> (s)" - dimensionfactor="1.0" keyword="TIME_LIMIT" maximum="20.0" + dimensionfactor="1.0" keyword="TIME_LIMIT" maximum="100.0" minimum="1.0E-6" value="1.0" primitive-type="double" discreet="true" default-search-variable="false" />