void saveConfiguration() {
    // create strings list from arrays
    try {
      BufferedWriter writer = Files.newBufferedWriter(myConfigPath, Charset.forName("UTF-8"));
      final double avgEnergy1 = myEnsemble.getAvgEnergy(0);
      final double avgEnergy2 = myEnsemble.getAvgEnergy(1);
      //          first line format:
      //
      // current step, boxBorder, avg. energy 1 (per prtcl), avg density 1, avg. energy 2, avg.
      // density 2, total Gamma
      writer.write(
          ""
              + myEnsemble.getCurrStep()
              + "\t"
              + myEnsemble.getBoxBorder()
              + "\t"
              + long_format.format(avgEnergy1)
              + "\t"
              + long_format.format(myEnsemble.getDensitiesAvg()[0])
              + "\t"
              + long_format.format(avgEnergy2)
              + "\t"
              + long_format.format(myEnsemble.getDensitiesAvg()[1])
              + "\t"
              + short_format.format(myEnsemble.opt.getGamma())
              + "\t");

      writer.newLine();
      writeCoordinates(writer);
      writer.close();
    } catch (IOException e) {
      e.printStackTrace();
      System.out.println("ERROR: failed to save state for " + myFolder);
    }
  }
  /**
   * Loads state from given strings array, treating first line as a general parameters and all other
   * as an array of particles' coordinates inside correspondent boxes.
   *
   * <p>throws Exception if no valid config could be read (either
   */
  private void readCoordinates(List<String> strings) throws Exception {
    //          first line format:
    // current step, boxBorder, avg. energy 1 (per prtcl), avg density 1, avg. energy 2, avg.
    // density 2, total Gamma
    String firstline = strings.remove(0);

    myEnsemble.setCurrStep(Integer.parseInt(firstline.split("\\s+")[0]));
    final int boxBorder = Integer.parseInt(firstline.split("\\s+")[1]);
    myEnsemble.setBoxBorder(boxBorder);

    final double avgE1 = Double.parseDouble(firstline.split("\\s+")[2]);
    final double density1 = Double.parseDouble(firstline.split("\\s+")[3]);
    final double avgE2 = Double.parseDouble(firstline.split("\\s+")[4]);
    final double density2 = Double.parseDouble(firstline.split("\\s+")[5]);

    myEnsemble.setCurrReducedEnergies(avgE1, avgE2);
    myEnsemble.setDensitiesAvg(density1, density2);

    if (strings.size() != Nei * 2) {
      throw new IndexOutOfBoundsException("file size doesn't fit particles number");
    }

    for (int type = 0; type < 2; type++) {
      for (int i = 0 + type * Nei; i < Nei + type * Nei; i++) {
        String[] strs = strings.get(i).split("\\s");

        prtcls[type][0][i - type * Nei] = Double.parseDouble(strs[0]);
        prtcls[type][1][i - type * Nei] = Double.parseDouble(strs[1]);
        prtcls[type][2][i - type * Nei] = Double.parseDouble(strs[2]);
      }
    }
  }
  public GibbsConfigurationManager(GibbsEnsemble ensemble) {
    myEnsemble = ensemble;

    myFolder = ensemble.myFolder;
    configFile = IEnsemble.STATE_FILE;

    Nei = ensemble.Nei;

    myConfigPath = GibbsConfigurationManager.getPath(myFolder + "/" + configFile);

    short_format = myEnsemble.SHORT_FORMAT;
    long_format = myEnsemble.FORMAT;

    prtcls = myEnsemble.getParticles();

    // OPTIONS first bit == save longtail
    saveLongTail = ((myEnsemble.opt.getStrategy() & 1) == 1);

    //        corrNormirovka = 4. * (boxSize * boxSize * boxSize) / (Nei * Nei);
    //        corrDr = Math.sqrt(3.0 * boxSize * boxSize) / 1.99999999999 / (CORR_LENGTH);
    //        corrArray[0] = new double[CORR_LENGTH];
    //        corrArray[1] = new double[CORR_LENGTH];
    //        corrArray[2] = new double[CORR_LENGTH];

  }
  /** fill random arrays of particles, resetting all counters */
  void initParticlesPosition() {
    final double[] boxSizes = myEnsemble.getBoxSizes();
    final int boxBorder = myEnsemble.getBoxBorder();

    // uniformly distribute particles in the box NaCL structure (fcc)
    if (CLOptions.START_FROM_FCC) {
      fillBoxFCC(0, boxBorder, boxSizes[0]);
      fillBoxFCC(boxBorder, Nei, boxSizes[1]);
    } else {
      // random configuration.
      for (int type = 0; type < 2; type++) {
        for (int j = 0; j < Nei; j++) {
          int box = (j < boxBorder) ? 0 : 1;
          /* spreading the particles */
          prtcls[type][0][j] = myEnsemble.myRandom(boxSizes[box]);
          prtcls[type][1][j] = myEnsemble.myRandom(boxSizes[box]);
          prtcls[type][2][j] = myEnsemble.myRandom(boxSizes[box]);
        }
      }
    }
  }
  public void workOnFrequentCalc(int curr_step) {
    // write reduced densities and particles numbers in the following format
    // curr_step, N1, v*1, N2, v*2

    try {
      additionalStateWriter.write(
          curr_step
              + "\t"
              + myEnsemble.getBoxBorder() * 2
              + "\t"
              + long_format.format(myEnsemble.getSizeParam(0))
              + "\t"
              + (Nei - myEnsemble.getBoxBorder()) * 2
              + "\t"
              + long_format.format(myEnsemble.getSizeParam(1))
              + "\t");
      additionalStateWriter.newLine();
      //            System.out.println("written");
    } catch (IOException e) {
      System.out.println(
          "ERROR: can't write " + myFolder + " gibbs state to " + GibbsEnsemble.GIBBS_STATE_FILE);
      e.printStackTrace();
    }
  }