private static void computeBeliefBoundaries( Double hFFPos, Double hFFSpeed, Double hfFFTargetPos, Double hFFCreationTime) { double currentTime = System.nanoTime() / SEC_NANOSEC_FACTOR; double[] minBoundaries = new double[1]; double[] maxBoundaries = new double[1]; double startTime = 0.0; if (hfFFTargetPos != 0.0) { if (hFFCreationTime > hInit) { startTime = hFFCreationTime; hFFPosMin = hFFPos; hFFPosMax = hFFPos; hFFSpeedMin = hFFSpeed; hFFSpeedMax = hFFSpeed; } else { if (hFFCreationTime <= hLastTime) { startTime = hLastTime; } else if (hFFCreationTime > hLastTime) { startTime = hFFCreationTime; hFFPosMin = hFFPos; hFFPosMax = hFFPos; hFFSpeedMin = hFFSpeed; hFFSpeedMax = hFFSpeed; } } // ---------------------- knowledge evaluation -------------------------------- double accMin = Database.getAcceleration( hFFSpeedMin, hFFPosMin, Database.lTorques, 0.0, 1.0, Database.lMass); double accMax = Database.getAcceleration( hFFSpeedMax, hFFPosMax, Database.lTorques, 1.0, 0.0, Database.lMass); FirstOrderIntegrator integrator = new MidpointIntegrator(1); integrator.setMaxEvaluations((int) TIMEPERIOD); FirstOrderDifferentialEquations f = new Derivation(); // ------------- min ---------------------- minBoundaries[0] = accMin; integrator.integrate(f, startTime, minBoundaries, currentTime, minBoundaries); hFFSpeedMin += minBoundaries[0]; integrator.integrate(f, startTime, minBoundaries, currentTime, minBoundaries); hFFPosMin += minBoundaries[0]; // ------------- max ---------------------- maxBoundaries[0] = accMax; integrator.integrate(f, startTime, maxBoundaries, currentTime, maxBoundaries); hFFSpeedMax += maxBoundaries[0]; integrator.integrate(f, startTime, maxBoundaries, currentTime, maxBoundaries); hFFPosMax += maxBoundaries[0]; } if (hFFSpeedMax > 200) hFFSpeedMax = 200.0; if (hFFSpeedMin < 0.0) hFFSpeedMin = 0.0; if (hFFPosMin < 0.0) hFFPosMin = 0.0; hLastTime = currentTime; hInit = hFFCreationTime; }
@Test public void testEventsScheduling() { FirstOrderDifferentialEquations sincos = new FirstOrderDifferentialEquations() { public int getDimension() { return 2; } public void computeDerivatives(double t, double[] y, double[] yDot) { yDot[0] = y[1]; yDot[1] = -y[0]; } }; SchedulingChecker sinChecker = new SchedulingChecker(0); // events at 0, PI, 2PI ... SchedulingChecker cosChecker = new SchedulingChecker(1); // events at PI/2, 3PI/2, 5PI/2 ... FirstOrderIntegrator integ = new DormandPrince853Integrator(0.001, 1.0, 1.0e-12, 0.0); integ.addEventHandler(sinChecker, 0.01, 1.0e-7, 100); integ.addStepHandler(sinChecker); integ.addEventHandler(cosChecker, 0.01, 1.0e-7, 100); integ.addStepHandler(cosChecker); double t0 = 0.5; double[] y0 = new double[] {FastMath.sin(t0), FastMath.cos(t0)}; double t = 10.0; double[] y = new double[2]; integ.integrate(sincos, t0, y0, t, y); }
@Test public void testVariableSteps() throws DimensionMismatchException, NumberIsTooSmallException, MaxCountExceededException, NoBracketingException { final TestProblem3 pb = new TestProblem3(0.9); double minStep = 0; double maxStep = pb.getFinalTime() - pb.getInitialTime(); double scalAbsoluteTolerance = 1.0e-8; double scalRelativeTolerance = scalAbsoluteTolerance; FirstOrderIntegrator integ = new DormandPrince853Integrator( minStep, maxStep, scalAbsoluteTolerance, scalRelativeTolerance); integ.addStepHandler(new VariableHandler()); double stopTime = integ.integrate( pb, pb.getInitialTime(), pb.getInitialState(), pb.getFinalTime(), new double[pb.getDimension()]); Assert.assertEquals(pb.getFinalTime(), stopTime, 1.0e-10); Assert.assertEquals("Dormand-Prince 8 (5, 3)", integ.getName()); }
@Test public void testKepler() throws DimensionMismatchException, NumberIsTooSmallException, MaxCountExceededException, NoBracketingException { final TestProblem3 pb = new TestProblem3(0.9); double minStep = 0; double maxStep = pb.getFinalTime() - pb.getInitialTime(); double scalAbsoluteTolerance = 1.0e-8; double scalRelativeTolerance = scalAbsoluteTolerance; FirstOrderIntegrator integ = new DormandPrince853Integrator( minStep, maxStep, scalAbsoluteTolerance, scalRelativeTolerance); integ.addStepHandler(new KeplerHandler(pb)); integ.integrate( pb, pb.getInitialTime(), pb.getInitialState(), pb.getFinalTime(), new double[pb.getDimension()]); Assert.assertEquals(integ.getEvaluations(), pb.getCalls()); Assert.assertTrue(pb.getCalls() < 3300); }
@Test public void testEvents() throws DimensionMismatchException, NumberIsTooSmallException, MaxCountExceededException, NoBracketingException { TestProblem4 pb = new TestProblem4(); double minStep = 0; double maxStep = pb.getFinalTime() - pb.getInitialTime(); double scalAbsoluteTolerance = 1.0e-9; double scalRelativeTolerance = 0.01 * scalAbsoluteTolerance; FirstOrderIntegrator integ = new DormandPrince853Integrator( minStep, maxStep, scalAbsoluteTolerance, scalRelativeTolerance); TestProblemHandler handler = new TestProblemHandler(pb, integ); integ.addStepHandler(handler); EventHandler[] functions = pb.getEventsHandlers(); double convergence = 1.0e-8 * maxStep; for (int l = 0; l < functions.length; ++l) { integ.addEventHandler(functions[l], Double.POSITIVE_INFINITY, convergence, 1000); } Assert.assertEquals(functions.length, integ.getEventHandlers().size()); integ.integrate( pb, pb.getInitialTime(), pb.getInitialState(), pb.getFinalTime(), new double[pb.getDimension()]); Assert.assertEquals(0, handler.getMaximalValueError(), 2.1e-7); Assert.assertEquals(0, handler.getMaximalTimeError(), convergence); Assert.assertEquals(12.0, handler.getLastTime(), convergence); integ.clearEventHandlers(); Assert.assertEquals(0, integ.getEventHandlers().size()); }
@Test public void testBackward() throws DimensionMismatchException, NumberIsTooSmallException, MaxCountExceededException, NoBracketingException { TestProblem5 pb = new TestProblem5(); double minStep = 0; double maxStep = pb.getFinalTime() - pb.getInitialTime(); double scalAbsoluteTolerance = 1.0e-8; double scalRelativeTolerance = 0.01 * scalAbsoluteTolerance; FirstOrderIntegrator integ = new DormandPrince853Integrator( minStep, maxStep, scalAbsoluteTolerance, scalRelativeTolerance); TestProblemHandler handler = new TestProblemHandler(pb, integ); integ.addStepHandler(handler); integ.integrate( pb, pb.getInitialTime(), pb.getInitialState(), pb.getFinalTime(), new double[pb.getDimension()]); Assert.assertTrue(handler.getLastError() < 1.1e-7); Assert.assertTrue(handler.getMaximalValueError() < 1.1e-7); Assert.assertEquals(0, handler.getMaximalTimeError(), 1.0e-12); Assert.assertEquals("Dormand-Prince 8 (5, 3)", integ.getName()); }
@Test public void testUnstableDerivative() throws DimensionMismatchException, NumberIsTooSmallException, MaxCountExceededException, NoBracketingException { final StepProblem stepProblem = new StepProblem(0.0, 1.0, 2.0); FirstOrderIntegrator integ = new DormandPrince853Integrator(0.1, 10, 1.0e-12, 0.0); integ.addEventHandler(stepProblem, 1.0, 1.0e-12, 1000); double[] y = {Double.NaN}; integ.integrate(stepProblem, 0.0, new double[] {0.0}, 10.0, y); Assert.assertEquals(8.0, y[0], 1.0e-12); }
@Test(expected = NumberIsTooSmallException.class) public void testMinStep() throws DimensionMismatchException, NumberIsTooSmallException, MaxCountExceededException, NoBracketingException { TestProblem1 pb = new TestProblem1(); double minStep = 0.1 * (pb.getFinalTime() - pb.getInitialTime()); double maxStep = pb.getFinalTime() - pb.getInitialTime(); double[] vecAbsoluteTolerance = {1.0e-15, 1.0e-16}; double[] vecRelativeTolerance = {1.0e-15, 1.0e-16}; FirstOrderIntegrator integ = new DormandPrince853Integrator( minStep, maxStep, vecAbsoluteTolerance, vecRelativeTolerance); TestProblemHandler handler = new TestProblemHandler(pb, integ); integ.addStepHandler(handler); integ.integrate( pb, pb.getInitialTime(), pb.getInitialState(), pb.getFinalTime(), new double[pb.getDimension()]); Assert.fail("an exception should have been thrown"); }
// loop through current job/results, assembling dataset private HashMap<Integer, SpeciesZoneType> genSpeciesDataset( SimJob job, EcosystemTimesteps ecosysTimesteps, Map<Integer, NodeRelationships> ecosysRelationships) { // calc information relevant to entire ecosystem int speciesCnt = ecosysTimesteps.getNodeList().size(); // Number of species int timesteps = ecosysTimesteps.getTimesteps(); // Maximum number of timesteps to run simulation int timestepsToSave = 0; // Number of timesteps of data to save to output file int[] matchingTimesteps = null; // Array of matching timesteps returned by findMatchingTimesteps() // read in link parameters; this was explicitly configured to allow // manipulation of link parameter values, but no manipulation is // performed in this version LinkParams lPs = new LinkParams(propertiesConfig); // loop through node values and assemble summary data int[] speciesID = new int[speciesCnt]; SimJobSZT[] sztArray = new SimJobSZT[speciesCnt]; int spNum = 0; for (NodeTimesteps nodeTimesteps : ecosysTimesteps.getTimestepMapValues()) { SimJobSZT sjSzt = job.getSpeciesZoneByNodeId(nodeTimesteps.getNodeId()); sztArray[spNum] = sjSzt; speciesID[spNum] = sjSzt.getNodeIndex(); spNum++; } // define objects to track species' contributions double[][][] contribs = new double[timesteps][speciesCnt][speciesCnt]; double[][] calcBiomass = new double[timesteps][speciesCnt]; double[][] contribsT; // current timestep // note: WebServices ATN Model uses B0 with default = 0.5. This presumes // that biomasses are small, i.e. < 1.0. Division by biomassScale // here is consistent with usage in WoB_Server.SimulationEngine to // normalize biomasses. // need to store bm as it varies over time through integration; // start with initial bm for each species double[] currBiomass = new double[speciesCnt]; for (int i = 0; i < speciesCnt; i++) { NodeTimesteps nodeTimeSteps = ecosysTimesteps.getTimestepMap().get(speciesID[i]); // manually set biomass vals for excluded initial timesteps; this // includes the first value to be used as input currBiomass[i] = nodeTimeSteps.getBiomass(initTimeIdx) / biomassScale; calcBiomass[0][i] = currBiomass[i]; } if (Constants.useCommonsMathIntegrator) { // Use Apache Commons Math GraggBulirschStoerIntegrator FirstOrderIntegrator integrator = new GraggBulirschStoerIntegrator( 1.0e-8, // minimal step 100.0, // maximal step ATNEquations.EXTINCT, // allowed absolute error 1.0e-10); // allowed relative error // Set up the ATN equations based on the current food web and parameters ATNEquations ode = new ATNEquations(sztArray, ecosysRelationships, lPs); ATNEventHandler eventHandler = new ATNEventHandler(ode); // FIXME: Choose best parameter values integrator.addEventHandler( new EventFilter(eventHandler, FilterType.TRIGGER_ONLY_DECREASING_EVENTS), 1, // maximal time interval between switching function checks (this interval prevents // missing sign changes in case the integration steps becomes very large) 0.0001, // convergence threshold in the event time search 1000, // upper limit of the iteration count in the event time search new BisectionSolver()); // Set up the StepHandler, which is triggered at each time step by the integrator, // and copies the current biomass of each species into calcBiomass[timestep]. // See the "Continuous Output" section of // https://commons.apache.org/proper/commons-math/userguide/ode.html FixedStepHandler fixedStepHandler = new FixedStepHandler() { public void init(double t0, double[] y0, double t) {} private int timestep = 0; public void handleStep(double t, double[] y, double[] yDot, boolean isLast) { // Ensure we don't go past the last time step due to rounding error if (timestep < calcBiomass.length) { System.arraycopy(y, 0, calcBiomass[timestep], 0, speciesCnt); } timestep++; } }; StepHandler stepHandler = new StepNormalizer(timeIntvl, fixedStepHandler); integrator.addStepHandler(stepHandler); // Run the integrator to compute the biomass time series integrator.integrate(ode, 0.0, currBiomass, timeIntvl * timesteps, currBiomass); if (eventHandler.integrationWasStopped()) { timestepsToSave = (int) (eventHandler.getTimeStopped() / timeIntvl); } else { // Check for an oscillating steady state, // and only save the data through the first period of the oscillation matchingTimesteps = findMatchingTimesteps(calcBiomass, timesteps - 1); System.err.println("\nmatchingTimesteps = " + Arrays.toString(matchingTimesteps)); // Save timesteps up through the second matching timestep, // or all timesteps if there was no second matching timestep. if (matchingTimesteps[1] != -1) { timestepsToSave = matchingTimesteps[1] + 1; } else { timestepsToSave = timesteps; } } } else { // Use BulirschStoerIntegration // create integration object boolean isTest = false; BulirschStoerIntegration bsi = new BulirschStoerIntegration( timeIntvl, speciesID, sztArray, ecosysRelationships, lPs, maxBSIErr, equationSet); // calculate delta-biomass and biomass "contributions" from each related // species for (int t = initTimeIdx + 1; t < timesteps; t++) { boolean success = bsi.performIntegration(time(initTime, t), currBiomass); if (!success) { System.out.printf("Integration failed to converge, t = %d\n", t); System.out.print(bsi.extrapArrayToString(biomassScale)); break; } currBiomass = bsi.getYNew(); System.arraycopy(currBiomass, 0, calcBiomass[t], 0, speciesCnt); contribsT = bsi.getContribs(); for (int i = 0; i < speciesCnt; i++) { System.arraycopy(contribsT[i], 0, contribs[t - 1][i], 0, speciesCnt); } } // timestep loop } if (useHDF5) { saveHDF5OutputFile( calcBiomass, speciesID, matchingTimesteps, job.getNode_Config(), timestepsToSave); return null; } double[][] webServicesData = new double[speciesCnt][timesteps]; if (Constants.useSimEngine) { // We need the webServicesData only for marginOfErrorCalculation // extract timestep data from CSV Functions.extractCSVDataRelns(job.getCsv(), ecosysTimesteps, ecosysRelationships); spNum = 0; for (NodeTimesteps nodeTimesteps : ecosysTimesteps.getTimestepMapValues()) { // copy nodetimestep data to local array for easier access System.arraycopy(nodeTimesteps.getBiomassArray(), 0, webServicesData[spNum], 0, timesteps); spNum++; } } // output data // A. print header psATN.printf("timesteps"); for (int i = 0; i < timesteps; i++) { psATN.printf(",%d", i); } psATN.println(); /* Convert to CSV String */ String biomassCSV = ""; biomassCSV = "Manipulation_id: " + job.getATNManipulationId() + "\n\n"; int maxTimestep = job.getTimesteps(); // Create Timestep Labels for (int j = 1; j <= maxTimestep; j++) { biomassCSV += "," + j; } HashMap<Integer, SpeciesZoneType> mSpecies = new HashMap<Integer, SpeciesZoneType>(); // loop through each species for (int i = 0; i < speciesCnt; i++) { if (Constants.useSimEngine) { psATN.printf("i.%d.sim", speciesID[i]); // B. print WebServices simulation data for species for (int t = 0; t < timesteps; t++) { psATN.printf(",%9.0f", webServicesData[i][t]); } psATN.println(); } // B. print combined biomass contributions (i.e. locally calculated biomass) // for current species. psATN.printf("i.%d.calc", speciesID[i]); for (int t = 0; t < timesteps; t++) { psATN.printf(",%9.0f", calcBiomass[t][i] * biomassScale); } psATN.println(); // //C. print individual biomass contributions from other species // for (int j = 0; j < speciesCnt; j++) { // psATN.printf("i.%d.j.%d.", speciesID[i], speciesID[j]); // for (int t = 0; t < timesteps; t++) { // psATN.printf(",%9.0f", contribs[t][i][j] * biomassScale); // } // psATN.println(); // } float extinction = 1.E-15f; SimJobSZT sjSzt = job.getSpeciesZoneByNodeId(speciesID[i]); // add nodes to list in the order that they are received from infos String name = sjSzt.getName().replaceAll(",", " ") + " [" + sjSzt.getNodeIndex() + "]"; String tempStr = name; for (int t = 0; t < maxTimestep; t++) { tempStr += ","; double biomass = calcBiomass[t][i] * biomassScale; if (biomass > 0) { tempStr += biomass > extinction ? Math.ceil(biomass) : 0; } if (t == maxTimestep - 1) { SpeciesZoneType szt = null; if (!mSpecies.containsKey(sjSzt.getNodeIndex())) { szt = new SpeciesZoneType(sjSzt.getName(), sjSzt.getNodeIndex(), 0, 0, biomass, null); mSpecies.put(sjSzt.getNodeIndex(), szt); } else { // update existing species current biomass szt = mSpecies.get(sjSzt.getNodeIndex()); szt.setCurrentBiomass(biomass); } } } biomassCSV += "\n" + tempStr; } // Append node config to the ATN CSV psATN.println(); psATN.println("\"node-config: " + job.getNode_Config() + "\""); biomassCSV += "\n\n"; biomassCSV += job.getConsumeMap().toString() + "\n\n"; biomassCSV += job.getPathTable().toString(); job.setBiomassCsv(biomassCSV); // System.out.println(biomassCSV); return mSpecies; }