Unverified Commit d750cc02 authored by Anne Gunn's avatar Anne Gunn Committed by Axel Kohlmeyer
Browse files

Changed the code in the read_F_table function to conform to the "expected...

Changed the code in the read_F_table function to conform to the "expected behavior" description in #1572. Adopted a best-of-both-worlds approach, though, and processed the whole input file all the way through, emitting a message for each problem found, before issuing a final error message to stop processing. Updated doc to clarify requirement for uniform spacing of pressure correction points.
parent de366c27
Loading
Loading
Loading
Loading
+2 −2
Original line number Original line Diff line number Diff line
@@ -47,13 +47,13 @@ or {cubic_spline}.


With either spline method, the only argument that needs to follow it
With either spline method, the only argument that needs to follow it
is the name of a file that contains the desired pressure correction
is the name of a file that contains the desired pressure correction
as a function of volume. The file should be formatted so each line has:
as a function of volume. The file must be formatted so each line has:


Volume_i, PressureCorrection_i :pre
Volume_i, PressureCorrection_i :pre


Note both the COMMA and the SPACE separating the volume's
Note both the COMMA and the SPACE separating the volume's
value and its corresponding pressure correction. The volumes in the file
value and its corresponding pressure correction. The volumes in the file
should be uniformly spaced. Both the volumes and the pressure corrections
must be uniformly spaced. Both the volumes and the pressure corrections
should be provided in the proper units, e.g. if you are using {units real},
should be provided in the proper units, e.g. if you are using {units real},
the volumes should all be in cubic angstroms, and the pressure corrections
the volumes should all be in cubic angstroms, and the pressure corrections
should all be in atmospheres. Furthermore, the table should start/end at a
should all be in atmospheres. Furthermore, the table should start/end at a
+58 −18
Original line number Original line Diff line number Diff line
@@ -59,6 +59,9 @@ enum{NOBIAS,BIAS};
enum{NONE,XYZ,XY,YZ,XZ};
enum{NONE,XYZ,XY,YZ,XZ};
enum{ISO,ANISO,TRICLINIC};
enum{ISO,ANISO,TRICLINIC};


// NB: Keep error and warning messages less than 255 chars long.
const int MAX_MESSAGE_LENGTH = 256;

/* ----------------------------------------------------------------------
/* ----------------------------------------------------------------------
   NVT,NPH,NPT integrators for improved Nose-Hoover equations of motion
   NVT,NPH,NPT integrators for improved Nose-Hoover equations of motion
 ---------------------------------------------------------------------- */
 ---------------------------------------------------------------------- */
@@ -630,24 +633,32 @@ int FixBocs::read_F_table( char *filename, int p_basis_type )
  double **data = (double **) calloc(N_columns,sizeof(double *));
  double **data = (double **) calloc(N_columns,sizeof(double *));
  char * line = (char *) calloc(200,sizeof(char));
  char * line = (char *) calloc(200,sizeof(char));


  bool badInput = false;
  char badDataMsg[MAX_MESSAGE_LENGTH];
  fpi = fopen(filename,"r");
  fpi = fopen(filename,"r");
  if (fpi)
  if (fpi)
  {
  {
    while (fgets(line,199,fpi)) { ++n_entries; }
    while (fgets(line,199,fpi)) { ++n_entries; }
    fclose(fpi);

    for (i = 0; i < N_columns; ++i)
    for (i = 0; i < N_columns; ++i)
    {
    {
      data[i] = (double *) calloc(n_entries,sizeof(double));
      data[i] = (double *) calloc(n_entries,sizeof(double));
    }
    }
  } else {
    char errmsg[128];
    snprintf(errmsg,128,"Unable to open file: %s\n",filename);
    error->all(FLERR,errmsg);
  }


    // Don't need to re-open the file to make a second pass through it
    // simply rewind to beginning
    rewind(fpi);

    double stdVolumeInterval = 0.0;
    double currVolumeInterval = 0.0;
    // When comparing doubles/floats, we need an Epsilon.
    // The literature indicates getting this value right in the
    // general case can be pretty complicated. I don't think it
    // needs to be complicated here, though. At least based on the
    // sample data I've seen where the volume values are fairly
    // large.
    const double volumeIntervalTolerance = 0.001;
    n_entries = 0;
    n_entries = 0;
  fpi = fopen(filename,"r");
  if (fpi) {
    while( fgets(line,199,fpi)) {
    while( fgets(line,199,fpi)) {
      ++n_entries;
      ++n_entries;
      test_sscanf = sscanf(line," %f , %f ",&f1, &f2);
      test_sscanf = sscanf(line," %f , %f ",&f1, &f2);
@@ -655,19 +666,47 @@ int FixBocs::read_F_table( char *filename, int p_basis_type )
      {
      {
        data[0][n_entries-1] = (double) f1;
        data[0][n_entries-1] = (double) f1;
        data[1][n_entries-1] = (double) f2;
        data[1][n_entries-1] = (double) f2;
        if (n_entries == 2) {
          stdVolumeInterval = data[0][n_entries-1] - data[0][n_entries-2];
        }
        else if (n_entries > 2) {
          currVolumeInterval = data[0][n_entries-1] - data[0][n_entries-2];
          if (fabs(currVolumeInterval - stdVolumeInterval) > volumeIntervalTolerance) {
            snprintf(badDataMsg,MAX_MESSAGE_LENGTH,
                     "BAD VOLUME INTERVAL: spline analysis requires uniform"
                     " volume distribution, found inconsistent volume"
                     " differential, line %d of file %s\n\tline: %s",
                     n_entries,filename,line);
            error->message(FLERR,badDataMsg);
            badInput = true;
          }
        }
        // no else -- first entry is simply ignored
      }
      }
      else
      else
      {
      {
        fprintf(stderr,"WARNING: did not find 2 comma separated values in "
        snprintf(badDataMsg,MAX_MESSAGE_LENGTH,
                 "line %d of file %s\n\tline: %s",n_entries,filename,line);
                 "BAD INPUT FORMAT: did not find 2 comma separated numeric"
                 " values in line %d of file %s\n\tline: %s",
                 n_entries,filename,line);
        error->message(FLERR,badDataMsg);
        badInput = true;
      }
      }
    }
    }
  } else {
    fclose(fpi);
    char errmsg[128];
  }
    snprintf(errmsg,128,"Unable to open file: %s\n",filename);
  else {
    char errmsg[MAX_MESSAGE_LENGTH];
    snprintf(errmsg,MAX_MESSAGE_LENGTH,"Unable to open file: %s\n",filename);
    error->all(FLERR,errmsg);
  }

  if (badInput) {
    char errmsg[MAX_MESSAGE_LENGTH];
    snprintf(errmsg,MAX_MESSAGE_LENGTH,
             "Bad volume / pressure-correction data: %s\nSee details above",filename);
    error->all(FLERR,errmsg);
    error->all(FLERR,errmsg);
  }
  }
  fclose(fpi);


  if (p_basis_type == 1)
  if (p_basis_type == 1)
  {
  {
@@ -691,9 +730,10 @@ int FixBocs::read_F_table( char *filename, int p_basis_type )
  }
  }
  else
  else
  {
  {
    char * errmsg = (char *) calloc(70,sizeof(char));
    char errmsg[MAX_MESSAGE_LENGTH];
    sprintf(errmsg,"ERROR: invalid p_basis_type value "
    snprintf(errmsg, MAX_MESSAGE_LENGTH,
                                    "of %d in read_F_table",p_basis_type);
             "ERROR: invalid p_basis_type value of %d in read_F_table",
             p_basis_type);
    error->all(FLERR,errmsg);
    error->all(FLERR,errmsg);
  }
  }
  // cleanup
  // cleanup