/**
   * Initializes the controller and returns the number of ticks for the first simulation run
   *
   * @return
   */
  public synchronized long initialize() {
    error = 1e+10;
    repetition = 0;
    counter = 0;

    Coordinator c = Coordinator.getInstance();

    if (parameterSweep != null) {
      parameterSweep.setInitialValuesAndAdvance();
    }

    currentParameters = VariableSetFactory.createVariableSet("batch@run@current@set");
    currentParameters.synchronizeWithParameters(c.getParameters());
    goodParameters = null;

    if (log != null) {
      log.print("Run,Repetition,Error,");
      log.println(currentParameters.getVariableNames());
    }

    for (Render render : Coordinator.getInstance().getRenders()) {
      render.setSnapshotNamePrefix("" + counter + "-" + repetition + "-");
    }

    // Register the data layer saver
    dataLayerSaver.setFileNamePrefix("" + counter + "-" + repetition + "-");
    c.getDataReceiver().addDataConsumer(dataLayerSaver.getFilter());

    return numberOfTicks;
  }
  /**
   * Saves collected data, begins a new simulation step, and return the number of ticks for the new
   * step. If ticks number == 0, then end the batch process.
   *
   * @return
   */
  public synchronized long nextStep(DataSet dataSet) {
    // Save data
    if (saveDataFlag) {
      saveData();
    }

    // Save snapshots
    if (saveFinalSnapshots) {
      for (Render render : Coordinator.getInstance().getRenders()) {
        render.takeSnapshot("" + counter + "-" + repetition + "-");
      }
    }

    // Analyze data
    if (dataAnalyzer != null && dataSet != null) {
      double err = dataAnalyzer.analyze(dataSet, variableName);

      if (log != null) {
        log.print(counter);
        log.print(',');
        log.print(repetition);
        log.print(',');
        log.print(err);
        log.print(',');
        log.println(currentParameters.getVariableValues());
        log.flush();
      }

      if (err < error) {
        error = err;
        goodCounter = counter;
        goodRepetition = repetition;
        goodParameters = currentParameters;
      }
    }

    if (dataSet != null) {
      dataSet.clear();
    }

    dataLayerSaver.clear();

    repetition++;
    if (repetition >= numberOfRepetition) {
      if (parameterSweep != null) {
        if (!parameterSweep.setCurrentValuesAndAdvance()) {
          stop();
          return 0;
        }

        repetition = 0;
        counter++;
      } else {
        stop();
        return 0;
      }
    }

    currentParameters = VariableSetFactory.createVariableSet("batch@run@current@set");
    currentParameters.synchronizeWithParameters(Coordinator.getInstance().getParameters());

    for (Render render : Coordinator.getInstance().getRenders()) {
      render.setSnapshotNamePrefix("" + counter + "-" + repetition + "-");
    }

    dataLayerSaver.setFileNamePrefix("" + counter + "-" + repetition + "-");

    return numberOfTicks;
  }