示例#1
0
void *lammps_extract_compute(void *ptr, char *id, int style, int type)
{
  LAMMPS *lmp = (LAMMPS *) ptr;

  int icompute = lmp->modify->find_compute(id);
  if (icompute < 0) return NULL;
  Compute *compute = lmp->modify->compute[icompute];

  if (style == 0) {
    if (type == 0) {
      if (!compute->scalar_flag) return NULL;
      if (compute->invoked_scalar != lmp->update->ntimestep)
	compute->compute_scalar();
      return (void *) &compute->scalar;
    }
    if (type == 1) {
      if (!compute->vector_flag) return NULL;
      if (compute->invoked_vector != lmp->update->ntimestep)
	compute->compute_vector();
      return (void *) compute->vector;
    }
    if (type == 2) {
      if (!compute->array_flag) return NULL;
      if (compute->invoked_array != lmp->update->ntimestep)
	compute->compute_array();
      return (void *) compute->array;
    }
  }

  if (style == 1) {
    if (!compute->peratom_flag) return NULL;
    if (type == 1) {
      if (compute->invoked_peratom != lmp->update->ntimestep)
	compute->compute_peratom();
      return (void *) compute->vector_atom;
    }
    if (type == 2) {
      if (compute->invoked_peratom != lmp->update->ntimestep)
	compute->compute_peratom();
      return (void *) compute->array_atom;
    }
  }

  if (style == 2) {
    if (!compute->local_flag) return NULL;
    if (type == 1) {
      if (compute->invoked_local != lmp->update->ntimestep)
	compute->compute_local();
      return (void *) compute->vector_local;
    }
    if (type == 2) {
      if (compute->invoked_local != lmp->update->ntimestep)
	compute->compute_local();
      return (void *) compute->array_local;
    }
  }

  return NULL;
}
void ComputeAtomMolecule::compute_one(int m)
{
  int vidx = value2index[m];
  int aidx = argindex[m];

  // invoke compute if not previously invoked

  if (which[m] == COMPUTE) {
    Compute *compute = modify->compute[vidx];

    if (!(compute->invoked_flag & INVOKED_PERATOM)) {
      compute->compute_peratom();
      compute->invoked_flag |= INVOKED_PERATOM;
    }

    if (aidx == 0) {
      peratom = compute->vector_atom;
      nstride = 1;
    } else {
      if (compute->array_atom) peratom = &compute->array_atom[0][aidx-1];
      else peratom = NULL;
      nstride = compute->size_array_cols;
    }

  // access fix fields, check if fix frequency is a match

  } else if (which[m] == FIX) {
    if (update->ntimestep % modify->fix[vidx]->peratom_freq)
      error->all(FLERR,"Fix used in compute atom/molecule not computed "
                 "at compatible time");
    Fix *fix = modify->fix[vidx];

    if (aidx == 0) {
      peratom = fix->vector_atom;
      nstride = 1;
    } else {
      peratom = &fix->array_atom[0][aidx-1];
      nstride = fix->size_array_cols;
    }

  // evaluate atom-style variable

  } else if (which[m] == VARIABLE) {
    if (atom->nlocal > maxatom) {
      maxatom = atom->nmax;
      memory->destroy(scratch);
      memory->create(scratch,maxatom,"atom/molecule:scratch");
      peratom = scratch;
    }

    input->variable->compute_atom(vidx,igroup,peratom,1,0);
    nstride = 1;
  }
}
double ComputeReduceRegion::compute_one(int m, int flag)
{
  int i;

  Region *region = domain->regions[iregion];
  region->prematch();

  // invoke the appropriate attribute,compute,fix,variable
  // compute scalar quantity by summing over atom scalars
  // only include atoms in group

  index = -1;
  double **x = atom->x;
  int *mask = atom->mask;
  int nlocal = atom->nlocal;

  int n = value2index[m];
  int j = argindex[m];

  double one;
  if (mode == SUM) one = 0.0;
  else if (mode == MINN) one = BIG;
  else if (mode == MAXX) one = -BIG;
  else if (mode == AVE) one = 0.0;

  if (which[m] == X) {
    if (flag < 0) {
      for (i = 0; i < nlocal; i++)
        if (mask[i] & groupbit && region->match(x[i][0],x[i][1],x[i][2]))
          combine(one,x[i][j],i);
    } else one = x[flag][j];
  } else if (which[m] == V) {
    double **v = atom->v;
    if (flag < 0) {
      for (i = 0; i < nlocal; i++)
        if (mask[i] & groupbit && region->match(x[i][0],x[i][1],x[i][2]))
          combine(one,v[i][j],i);
    } else one = v[flag][j];
  } else if (which[m] == F) {
    double **f = atom->f;
    if (flag < 0) {
      for (i = 0; i < nlocal; i++)
        if (mask[i] & groupbit && region->match(x[i][0],x[i][1],x[i][2]))
          combine(one,f[i][j],i);
    } else one = f[flag][j];

  // invoke compute if not previously invoked

  } else if (which[m] == COMPUTE) {
    Compute *compute = modify->compute[n];

    if (flavor[m] == PERATOM) {
      if (!(compute->invoked_flag & INVOKED_PERATOM)) {
        compute->compute_peratom();
        compute->invoked_flag |= INVOKED_PERATOM;
      }

      if (j == 0) {
        double *compute_vector = compute->vector_atom;
        int n = nlocal;
        if (flag < 0) {
          for (i = 0; i < n; i++)
            if (mask[i] & groupbit && region->match(x[i][0],x[i][1],x[i][2]))
              combine(one,compute_vector[i],i);
        } else one = compute_vector[flag];
      } else {
        double **compute_array = compute->array_atom;
        int n = nlocal;
        int jm1 = j - 1;
        if (flag < 0) {
          for (i = 0; i < n; i++)
            if (mask[i] & groupbit && region->match(x[i][0],x[i][1],x[i][2]))
              combine(one,compute_array[i][jm1],i);
        } else one = compute_array[flag][jm1];
      }

    } else if (flavor[m] == LOCAL) {
      if (!(compute->invoked_flag & INVOKED_LOCAL)) {
        compute->compute_local();
        compute->invoked_flag |= INVOKED_LOCAL;
      }

      if (j == 0) {
        double *compute_vector = compute->vector_local;
        int n = compute->size_local_rows;
        if (flag < 0)
          for (i = 0; i < n; i++)
            combine(one,compute_vector[i],i);
        else one = compute_vector[flag];
      } else {
        double **compute_array = compute->array_local;
        int n = compute->size_local_rows;
        int jm1 = j - 1;
        if (flag < 0)
          for (i = 0; i < n; i++)
            combine(one,compute_array[i][jm1],i);
        else one = compute_array[flag][jm1];
      }
    }

  // check if fix frequency is a match

  } else if (which[m] == FIX) {
    if (update->ntimestep % modify->fix[n]->peratom_freq)
      error->all(FLERR,"Fix used in compute reduce not computed at "
                 "compatible time");
    Fix *fix = modify->fix[n];

    if (flavor[m] == PERATOM) {
      if (j == 0) {
        double *fix_vector = fix->vector_atom;
        int n = nlocal;
        if (flag < 0) {
          for (i = 0; i < n; i++)
            if (mask[i] & groupbit && region->match(x[i][0],x[i][1],x[i][2]))
              combine(one,fix_vector[i],i);
        } else one = fix_vector[flag];
      } else {
        double **fix_array = fix->array_atom;
        int jm1 = j - 1;
        if (flag < 0) {
          for (i = 0; i < nlocal; i++)
            if (mask[i] & groupbit && region->match(x[i][0],x[i][1],x[i][2]))
              combine(one,fix_array[i][jm1],i);
        } else one = fix_array[flag][jm1];
      }

    } else if (flavor[m] == LOCAL) {
      if (j == 0) {
        double *fix_vector = fix->vector_local;
        int n = fix->size_local_rows;
        if (flag < 0)
          for (i = 0; i < n; i++)
            combine(one,fix_vector[i],i);
        else one = fix_vector[flag];
      } else {
        double **fix_array = fix->array_local;
        int n = fix->size_local_rows;
        int jm1 = j - 1;
        if (flag < 0)
          for (i = 0; i < n; i++)
            combine(one,fix_array[i][jm1],i);
        else one = fix_array[flag][jm1];
      }
    }

  // evaluate atom-style variable

  } else if (which[m] == VARIABLE) {
    if (nlocal > maxatom) {
      maxatom = atom->nmax;
      memory->destroy(varatom);
      memory->create(varatom,maxatom,"reduce/region:varatom");
    }

    input->variable->compute_atom(n,igroup,varatom,1,0);
    if (flag < 0) {
      for (i = 0; i < nlocal; i++)
        if (mask[i] & groupbit && region->match(x[i][0],x[i][1],x[i][2]))
          combine(one,varatom[i],i);
    } else one = varatom[flag];
  }

  return one;
}
示例#4
0
double ComputeReduce::compute_one(int m, int flag)
{
  int i;

  // invoke the appropriate attribute,compute,fix,variable
  // for flag = -1, compute scalar quantity by scanning over atom properties
  // only include atoms in group for atom properties and per-atom quantities

  index = -1;
  int vidx = value2index[m];
  int aidx = argindex[m];

  int *mask = atom->mask;
  int nlocal = atom->nlocal;

  double one;
  if (mode == SUM) one = 0.0;
  else if (mode == MINN) one = BIG;
  else if (mode == MAXX) one = -BIG;
  else if (mode == AVE) one = 0.0;

  if (which[m] == X) {
    double **x = atom->x;
    if (flag < 0) {
      for (i = 0; i < nlocal; i++)
	if (mask[i] & groupbit) combine(one,x[i][aidx],i);
    } else one = x[flag][aidx];
  } else if (which[m] == V) {
    double **v = atom->v;
    if (flag < 0) {
      for (i = 0; i < nlocal; i++)
	if (mask[i] & groupbit) combine(one,v[i][aidx],i);
    } else one = v[flag][aidx];
  } else if (which[m] == F) {
    double **f = atom->f;
    if (flag < 0) {
      for (i = 0; i < nlocal; i++)
	if (mask[i] & groupbit) combine(one,f[i][aidx],i);
    } else one = f[flag][aidx];
    
  // invoke compute if not previously invoked

  } else if (which[m] == COMPUTE) {
    Compute *compute = modify->compute[vidx];
    
    if (flavor[m] == PERATOM) {
      if (!(compute->invoked_flag & INVOKED_PERATOM)) {
	compute->compute_peratom();
	compute->invoked_flag |= INVOKED_PERATOM;
      }

      if (aidx == 0) {
	double *comp_vec = compute->vector_atom;
	int n = nlocal;
	if (flag < 0) {
	  for (i = 0; i < n; i++)
	    if (mask[i] & groupbit) combine(one,comp_vec[i],i);
	} else one = comp_vec[flag];
      } else {
	double **carray_atom = compute->array_atom;
	int n = nlocal;
	int aidxm1 = aidx - 1;
	if (flag < 0) {
	  for (i = 0; i < n; i++)
	    if (mask[i] & groupbit) combine(one,carray_atom[i][aidxm1],i);
	} else one = carray_atom[flag][aidxm1];
      }

    } else if (flavor[m] == LOCAL) {
      if (!(compute->invoked_flag & INVOKED_LOCAL)) {
	compute->compute_local();
	compute->invoked_flag |= INVOKED_LOCAL;
      }

      if (aidx == 0) {
	double *comp_vec = compute->vector_local;
	int n = compute->size_local_rows;
	if (flag < 0)
	  for (i = 0; i < n; i++)
	    combine(one,comp_vec[i],i);
	else one = comp_vec[flag];
      } else {
	double **carray_local = compute->array_local;
	int n = compute->size_local_rows;
	int aidxm1 = aidx - 1;
	if (flag < 0)
	  for (i = 0; i < n; i++)
	    combine(one,carray_local[i][aidxm1],i);
	else one = carray_local[flag][aidxm1];
      }
    }

  // access fix fields, check if fix frequency is a match

  } else if (which[m] == FIX) {
    if (update->ntimestep % modify->fix[vidx]->peratom_freq)
      error->all("Fix used in compute reduce not computed at compatible time");
    Fix *fix = modify->fix[vidx];

    if (flavor[m] == PERATOM) {
      if (aidx == 0) {
	double *fix_vector = fix->vector_atom;
	int n = nlocal;
	if (flag < 0) {
	  for (i = 0; i < n; i++)
	    if (mask[i] & groupbit) combine(one,fix_vector[i],i);
	} else one = fix_vector[flag];
      } else {
	double **fix_array = fix->array_atom;
	int aidxm1 = aidx - 1;
	if (flag < 0) {
	  for (i = 0; i < nlocal; i++)
	    if (mask[i] & groupbit) combine(one,fix_array[i][aidxm1],i);
	} else one = fix_array[flag][aidxm1];
      }

    } else if (flavor[m] == LOCAL) {
      if (aidx == 0) {
	double *fix_vector = fix->vector_local;
	int n = fix->size_local_rows;
	if (flag < 0)
	  for (i = 0; i < n; i++)
	    combine(one,fix_vector[i],i);
	else one = fix_vector[flag];
      } else {
	double **fix_array = fix->array_local;
	int n = fix->size_local_rows;
	int aidxm1 = aidx - 1;
	if (flag < 0)
	  for (i = 0; i < n; i++)
	    combine(one,fix_array[i][aidxm1],i);
	else one = fix_array[flag][aidxm1];
      }
    }
    
  // evaluate atom-style variable

  } else if (which[m] == VARIABLE) {
    if (nlocal > maxatom) {
      maxatom = atom->nmax;
      memory->destroy(varatom);
      memory->create(varatom,maxatom,"reduce:varatom");
    }

    input->variable->compute_atom(vidx,igroup,varatom,1,0);
    if (flag < 0) {
      for (i = 0; i < nlocal; i++)
	if (mask[i] & groupbit) combine(one,varatom[i],i);
    } else one = varatom[flag];
  }

  return one;
}
void FixAveAtom::end_of_step()
{
  int i,j,m,n;

  // skip if not step which requires doing something

  bigint ntimestep = update->ntimestep;
  if (ntimestep != nvalid) return;

  // zero if first step

  int nlocal = atom->nlocal;

  if (irepeat == 0)
    for (i = 0; i < nlocal; i++)
      for (m = 0; m < nvalues; m++)
        array[i][m] = 0.0;

  // accumulate results of attributes,computes,fixes,variables to local copy
  // compute/fix/variable may invoke computes so wrap with clear/add

  modify->clearstep_compute();

  int *mask = atom->mask;

  for (m = 0; m < nvalues; m++) {
    n = value2index[m];
    j = argindex[m];

    if (which[m] == X) {
      double **x = atom->x;
      for (i = 0; i < nlocal; i++)
        if (mask[i] & groupbit) array[i][m] += x[i][j];

    } else if (which[m] == V) {
      double **v = atom->v;
      for (i = 0; i < nlocal; i++)
        if (mask[i] & groupbit) array[i][m] += v[i][j];

    } else if (which[m] == F) {
      double **f = atom->f;
      for (i = 0; i < nlocal; i++)
        if (mask[i] & groupbit) array[i][m] += f[i][j];

    // invoke compute if not previously invoked

    } else if (which[m] == COMPUTE) {
      Compute *compute = modify->compute[n];
      if (!(compute->invoked_flag & INVOKED_PERATOM)) {
        compute->compute_peratom();
        compute->invoked_flag |= INVOKED_PERATOM;
      }

      if (j == 0) {
        double *compute_vector = compute->vector_atom;
        for (i = 0; i < nlocal; i++)
          if (mask[i] & groupbit) array[i][m] += compute_vector[i];
      } else {
        int jm1 = j - 1;
        double **compute_array = compute->array_atom;
        for (i = 0; i < nlocal; i++)
          if (mask[i] & groupbit) array[i][m] += compute_array[i][jm1];
      }

    // access fix fields, guaranteed to be ready

    } else if (which[m] == FIX) {
      if (j == 0) {
        double *fix_vector = modify->fix[n]->vector_atom;
        for (i = 0; i < nlocal; i++)
          if (mask[i] & groupbit) array[i][m] += fix_vector[i];
      } else {
        int jm1 = j - 1;
        double **fix_array = modify->fix[n]->array_atom;
        for (i = 0; i < nlocal; i++)
          if (mask[i] & groupbit) array[i][m] += fix_array[i][jm1];
      }

    // evaluate atom-style variable
    // final argument = 1 sums result to array

    } else if (which[m] == VARIABLE && array)
      input->variable->compute_atom(n,igroup,&array[0][m],nvalues,1);
  }

  // done if irepeat < nrepeat
  // else reset irepeat and nvalid

  irepeat++;
  if (irepeat < nrepeat) {
    nvalid += nevery;
    modify->addstep_compute(nvalid);
    return;
  }

  irepeat = 0;
  nvalid = ntimestep+peratom_freq - (nrepeat-1)*nevery;
  modify->addstep_compute(nvalid);

  // average the final result for the Nfreq timestep

  double repeat = nrepeat;
  for (i = 0; i < nlocal; i++)
    for (m = 0; m < nvalues; m++)
      array[i][m] /= repeat;
}
示例#6
0
void FixAveHisto::end_of_step()
{
  int i,j,m;

  // skip if not step which requires doing something
  // error check if timestep was reset in an invalid manner

  bigint ntimestep = update->ntimestep;
  if (ntimestep < nvalid_last || ntimestep > nvalid) 
    error->all(FLERR,"Invalid timestep reset for fix ave/histo");
  if (ntimestep != nvalid) return;
  nvalid_last = nvalid;

  // zero if first step

  if (irepeat == 0) {
    stats[0] = stats[1] = 0.0;
    stats[2] = BIG;
    stats[3] = -BIG;
    for (i = 0; i < nbins; i++) bin[i] = 0.0;
  }

  // accumulate results of computes,fixes,variables to local copy
  // compute/fix/variable may invoke computes so wrap with clear/add

  modify->clearstep_compute();

  for (i = 0; i < nvalues; i++) {
    m = value2index[i];
    j = argindex[i];

    // atom attributes

    if (which[i] == X)
      bin_atoms(&atom->x[0][j],3);
    else if (which[i] == V)
      bin_atoms(&atom->v[0][j],3);
    else if (which[i] == F)
      bin_atoms(&atom->f[0][j],3);

    // invoke compute if not previously invoked

    if (which[i] == COMPUTE) {
      Compute *compute = modify->compute[m];

      if (kind == GLOBAL && mode == SCALAR) {
        if (j == 0) {
          if (!(compute->invoked_flag & INVOKED_SCALAR)) {
            compute->compute_scalar();
            compute->invoked_flag |= INVOKED_SCALAR;
          }
          bin_one(compute->scalar);
        } else {
          if (!(compute->invoked_flag & INVOKED_VECTOR)) {
            compute->compute_vector();
            compute->invoked_flag |= INVOKED_VECTOR;
          }
          bin_one(compute->vector[j-1]);
        }
      } else if (kind == GLOBAL && mode == VECTOR) {
        if (j == 0) {
          if (!(compute->invoked_flag & INVOKED_VECTOR)) {
            compute->compute_vector();
            compute->invoked_flag |= INVOKED_VECTOR;
          }
          bin_vector(compute->size_vector,compute->vector,1);
        } else {
          if (!(compute->invoked_flag & INVOKED_ARRAY)) {
            compute->compute_array();
            compute->invoked_flag |= INVOKED_ARRAY;
          }
          if (compute->array)
            bin_vector(compute->size_array_rows,&compute->array[0][j-1],
                       compute->size_array_cols);
        }

      } else if (kind == PERATOM) {
        if (!(compute->invoked_flag & INVOKED_PERATOM)) {
          compute->compute_peratom();
          compute->invoked_flag |= INVOKED_PERATOM;
        }
        if (j == 0)
          bin_atoms(compute->vector_atom,1);
        else if (compute->array_atom)
          bin_atoms(&compute->array_atom[0][j-1],compute->size_peratom_cols);

      } else if (kind == LOCAL) {
        if (!(compute->invoked_flag & INVOKED_LOCAL)) {
          compute->compute_local();
          compute->invoked_flag |= INVOKED_LOCAL;
        }
        if (j == 0)
          bin_vector(compute->size_local_rows,compute->vector_local,1);
        else if (compute->array_local)
          bin_vector(compute->size_local_rows,&compute->array_local[0][j-1],
                     compute->size_local_cols);
      }

      // access fix fields, guaranteed to be ready

    } else if (which[i] == FIX) {

      Fix *fix = modify->fix[m];

      if (kind == GLOBAL && mode == SCALAR) {
        if (j == 0) bin_one(fix->compute_scalar());
        else bin_one(fix->compute_vector(j-1));

      } else if (kind == GLOBAL && mode == VECTOR) {
        if (j == 0) {
          int n = fix->size_vector;
          for (i = 0; i < n; i++) bin_one(fix->compute_vector(i));
        } else {
          int n = fix->size_vector;
          for (i = 0; i < n; i++) bin_one(fix->compute_array(i,j-1));
        }

      } else if (kind == PERATOM) {
        if (j == 0) bin_atoms(fix->vector_atom,1);
        else if (fix->array_atom)
          bin_atoms(fix->array_atom[j-1],fix->size_peratom_cols);

      } else if (kind == LOCAL) {
        if (j == 0) bin_vector(fix->size_local_rows,fix->vector_local,1);
        else if (fix->array_local)
          bin_vector(fix->size_local_rows,&fix->array_local[0][j-1],
                     fix->size_local_cols);
      }

      // evaluate equal-style variable

    } else if (which[i] == VARIABLE && kind == GLOBAL) {
      bin_one(input->variable->compute_equal(m));

    } else if (which[i] == VARIABLE && kind == PERATOM) {
      if (atom->nlocal > maxatom) {
        memory->destroy(vector);
        maxatom = atom->nmax;
        memory->create(vector,maxatom,"ave/histo:vector");
      }
      input->variable->compute_atom(m,igroup,vector,1,0);
      bin_atoms(vector,1);
    }
  }

  // done if irepeat < nrepeat
  // else reset irepeat and nvalid

  irepeat++;
  if (irepeat < nrepeat) {
    nvalid += nevery;
    modify->addstep_compute(nvalid);
    return;
  }

  irepeat = 0;
  nvalid = ntimestep + nfreq - (nrepeat-1)*nevery;
  modify->addstep_compute(nvalid);

  // merge histogram stats across procs if necessary

  if (kind == PERATOM || kind == LOCAL) {
    MPI_Allreduce(stats,stats_all,2,MPI_DOUBLE,MPI_SUM,world);
    MPI_Allreduce(&stats[2],&stats_all[2],1,MPI_DOUBLE,MPI_MIN,world);
    MPI_Allreduce(&stats[3],&stats_all[3],1,MPI_DOUBLE,MPI_MAX,world);
    MPI_Allreduce(bin,bin_all,nbins,MPI_DOUBLE,MPI_SUM,world);

    stats[0] = stats_all[0];
    stats[1] = stats_all[1];
    stats[2] = stats_all[2];
    stats[3] = stats_all[3];
    for (i = 0; i < nbins; i++) bin[i] = bin_all[i];
  }

  // if ave = ONE, only single Nfreq timestep value is needed
  // if ave = RUNNING, combine with all previous Nfreq timestep values
  // if ave = WINDOW, combine with nwindow most recent Nfreq timestep values

  if (ave == ONE) {
    stats_total[0] = stats[0];
    stats_total[1] = stats[1];
    stats_total[2] = stats[2];
    stats_total[3] = stats[3];
    for (i = 0; i < nbins; i++) bin_total[i] = bin[i];

  } else if (ave == RUNNING) {
    stats_total[0] += stats[0];
    stats_total[1] += stats[1];
    stats_total[2] = MIN(stats_total[2],stats[2]);
    stats_total[3] = MAX(stats_total[3],stats[3]);
    for (i = 0; i < nbins; i++) bin_total[i] += bin[i];

  } else if (ave == WINDOW) {
    stats_total[0] += stats[0];
    if (window_limit) stats_total[0] -= stats_list[iwindow][0];
    stats_list[iwindow][0] = stats[0];
    stats_total[1] += stats[1];
    if (window_limit) stats_total[1] -= stats_list[iwindow][1];
    stats_list[iwindow][1] = stats[1];

    if (window_limit) m = nwindow;
    else m = iwindow+1;

    stats_list[iwindow][2] = stats[2];
    stats_total[2] = stats_list[0][2];
    for (i = 1; i < m; i++)
      stats_total[2] = MIN(stats_total[2],stats_list[i][2]);
    stats_list[iwindow][3] = stats[3];
    stats_total[3] = stats_list[0][3];
    for (i = 1; i < m; i++)
      stats_total[3] = MAX(stats_total[3],stats_list[i][3]);

    for (i = 0; i < nbins; i++) {
      bin_total[i] += bin[i];
      if (window_limit) bin_total[i] -= bin_list[iwindow][i];
      bin_list[iwindow][i] = bin[i];
    }

    iwindow++;
    if (iwindow == nwindow) {
      iwindow = 0;
      window_limit = 1;
    }
  }

  // output result to file

  if (fp && me == 0) {
    if (overwrite) fseek(fp,filepos,SEEK_SET);
    fprintf(fp,BIGINT_FORMAT " %d %g %g %g %g\n",ntimestep,nbins,
            stats_total[0],stats_total[1],stats_total[2],stats_total[3]);
    if (stats_total[0] != 0.0)
      for (i = 0; i < nbins; i++)
        fprintf(fp,"%d %g %g %g\n",
                i+1,coord[i],bin_total[i],bin_total[i]/stats_total[0]);
    else
      for (i = 0; i < nbins; i++)
        fprintf(fp,"%d %g %g %g\n",i+1,coord[i],0.0,0.0);
    fflush(fp);
    if (overwrite) {
      long fileend = ftell(fp);
      ftruncate(fileno(fp),fileend);
    }
  }
}
示例#7
0
void FixAveChunk::end_of_step()
{
  int i,j,m,n,index;

  // skip if not step which requires doing something
  // error check if timestep was reset in an invalid manner

  bigint ntimestep = update->ntimestep;
  if (ntimestep < nvalid_last || ntimestep > nvalid) 
    error->all(FLERR,"Invalid timestep reset for fix ave/chunk");
  if (ntimestep != nvalid) return;
  nvalid_last = nvalid;

  // first sample within single Nfreq epoch
  // zero out arrays that accumulate over many samples, but not across epochs
  // invoke setup_chunks() to determine current nchunk
  //   re-allocate per-chunk arrays if needed
  // invoke lock() in two cases:
  //   if nrepeat > 1: so nchunk cannot change until Nfreq epoch is over,
  //     will be unlocked on last repeat of this Nfreq
  //   if ave = RUNNING/WINDOW and not yet locked:
  //     set forever, will be unlocked in fix destructor
  // wrap setup_chunks in clearstep/addstep b/c it may invoke computes
  //   both nevery and nfreq are future steps, 
  //   since call below to cchunk->ichunk() 
  //     does not re-invoke internal cchunk compute on this same step

  if (irepeat == 0) {
    if (cchunk->computeflag) modify->clearstep_compute();
    nchunk = cchunk->setup_chunks();
    if (cchunk->computeflag) {
      modify->addstep_compute(ntimestep+nevery);
      modify->addstep_compute(ntimestep+nfreq);
    }
    allocate();
    if (nrepeat > 1 && ave == ONE)
      cchunk->lock(this,ntimestep,ntimestep+(nrepeat-1)*nevery);
    else if ((ave == RUNNING || ave == WINDOW) && !lockforever) {
      cchunk->lock(this,update->ntimestep,-1);
      lockforever = 1;
    }
    for (m = 0; m < nchunk; m++) {
      count_many[m] = count_sum[m] = 0.0;
      for (i = 0; i < nvalues; i++) values_many[m][i] = 0.0;
    }
  }

  // zero out arrays for one sample

  for (m = 0; m < nchunk; m++) {
    count_one[m] = 0.0;
    for (i = 0; i < nvalues; i++) values_one[m][i] = 0.0;
  }

  // compute chunk/atom assigns atoms to chunk IDs
  // extract ichunk index vector from compute
  // ichunk = 1 to Nchunk for included atoms, 0 for excluded atoms
  // wrap compute_ichunk in clearstep/addstep b/c it may invoke computes

  if (cchunk->computeflag) modify->clearstep_compute();

  cchunk->compute_ichunk();
  int *ichunk = cchunk->ichunk;

  if (cchunk->computeflag) modify->addstep_compute(ntimestep+nevery);

  // perform the computation for one sample
  // count # of atoms in each bin
  // accumulate results of attributes,computes,fixes,variables to local copy
  // sum within each chunk, only include atoms in fix group
  // compute/fix/variable may invoke computes so wrap with clear/add

  int *mask = atom->mask;
  int nlocal = atom->nlocal;

  for (i = 0; i < nlocal; i++)
    if (mask[i] & groupbit && ichunk[i] > 0)
      count_one[ichunk[i]-1]++;

  modify->clearstep_compute();

  for (m = 0; m < nvalues; m++) {
    n = value2index[m];
    j = argindex[m];

    // V,F adds velocities,forces to values

    if (which[m] == V || which[m] == F) {
      double **attribute;
      if (which[m] == V) attribute = atom->v;
      else attribute = atom->f;

      for (i = 0; i < nlocal; i++)
        if (mask[i] & groupbit && ichunk[i] > 0) {
          index = ichunk[i]-1;
          values_one[index][m] += attribute[i][j];
        }

    // DENSITY_NUMBER adds 1 to values

    } else if (which[m] == DENSITY_NUMBER) {

      for (i = 0; i < nlocal; i++)
        if (mask[i] & groupbit && ichunk[i] > 0) {
          index = ichunk[i]-1;
          values_one[index][m] += 1.0;
        }

    // DENSITY_MASS or MASS adds mass to values

    } else if (which[m] == DENSITY_MASS || which[m] == MASS) {
      int *type = atom->type;
      double *mass = atom->mass;
      double *rmass = atom->rmass;

      if (rmass) {
	for (i = 0; i < nlocal; i++)
	  if (mask[i] & groupbit && ichunk[i] > 0) {
	    index = ichunk[i]-1;
	    values_one[index][m] += rmass[i];
          }
      } else {
        for (i = 0; i < nlocal; i++)
	  if (mask[i] & groupbit && ichunk[i] > 0) {
	    index = ichunk[i]-1;
	    values_one[index][m] += mass[type[i]];
          }
      }

    // TEMPERATURE adds KE to values
    // subtract and restore velocity bias if requested

    } else if (which[m] == TEMPERATURE) {

      if (biasflag) {
        if (tbias->invoked_scalar != ntimestep) tbias->compute_scalar();
        tbias->remove_bias_all();
      }

      double **v = atom->v;
      int *type = atom->type;
      double *mass = atom->mass;
      double *rmass = atom->rmass;

      if (rmass) {
        for (i = 0; i < nlocal; i++)
          if (mask[i] & groupbit && ichunk[i] > 0) {
            index = ichunk[i]-1;
            values_one[index][m] += 
              (v[i][0]*v[i][0] + v[i][1]*v[i][1] + v[i][2]*v[i][2]) * rmass[i];
          }
      } else {
        for (i = 0; i < nlocal; i++)
          if (mask[i] & groupbit && ichunk[i] > 0) {
            index = ichunk[i]-1;
            values_one[index][m] += 
              (v[i][0]*v[i][0] + v[i][1]*v[i][1] + v[i][2]*v[i][2]) * 
              mass[type[i]];
          }
      }

      if (biasflag) tbias->restore_bias_all();

    // COMPUTE adds its scalar or vector component to values
    // invoke compute if not previously invoked

    } else if (which[m] == COMPUTE) {
      Compute *compute = modify->compute[n];
      if (!(compute->invoked_flag & INVOKED_PERATOM)) {
        compute->compute_peratom();
        compute->invoked_flag |= INVOKED_PERATOM;
      }
      double *vector = compute->vector_atom;
      double **array = compute->array_atom;
      int jm1 = j - 1;

      for (i = 0; i < nlocal; i++)
        if (mask[i] & groupbit && ichunk[i] > 0) {
          index = ichunk[i]-1;
          if (j == 0) values_one[index][m] += vector[i];
          else values_one[index][m] += array[i][jm1];
        }

    // FIX adds its scalar or vector component to values
    // access fix fields, guaranteed to be ready

    } else if (which[m] == FIX) {
      double *vector = modify->fix[n]->vector_atom;
      double **array = modify->fix[n]->array_atom;
      int jm1 = j - 1;

      for (i = 0; i < nlocal; i++)
        if (mask[i] & groupbit && ichunk[i] > 0) {
          index = ichunk[i]-1;
          if (j == 0) values_one[index][m] += vector[i];
          else values_one[index][m] += array[i][jm1];
        }

    // VARIABLE adds its per-atom quantities to values
    // evaluate atom-style variable

    } else if (which[m] == VARIABLE) {
      if (nlocal > maxvar) {
        maxvar = atom->nmax;
        memory->destroy(varatom);
        memory->create(varatom,maxvar,"ave/chunk:varatom");
      }

      input->variable->compute_atom(n,igroup,varatom,1,0);

      for (i = 0; i < nlocal; i++)
        if (mask[i] & groupbit && ichunk[i] > 0) {
          index = ichunk[i]-1;
          values_one[index][m] += varatom[i];
        }
    }
  }

  // process the current sample
  // if normflag = ALL, accumulate values,count separately to many
  // if normflag = SAMPLE, one = value/count, accumulate one to many
  //   count is MPI summed here, value is MPI summed below across samples
  //   exception is TEMPERATURE: normalize by DOF
  //   exception is DENSITYs: no normalize by atom count
  //   exception is scaleflag = NOSCALE : no normalize by atom count
  //     check last so other options can take precedence

  double mvv2e = force->mvv2e;
  double boltz = force->boltz;

  if (normflag == ALL) {
    for (m = 0; m < nchunk; m++) {
      count_many[m] += count_one[m];
      for (j = 0; j < nvalues; j++)
        values_many[m][j] += values_one[m][j];
    }
  } else if (normflag == SAMPLE) {
    MPI_Allreduce(count_one,count_many,nchunk,MPI_DOUBLE,MPI_SUM,world);
    for (m = 0; m < nchunk; m++) {
      if (count_many[m] > 0.0)
        for (j = 0; j < nvalues; j++) {
          if (which[j] == TEMPERATURE)
            values_many[m][j] += mvv2e*values_one[m][j] / 
              ((cdof + adof*count_many[m]) * boltz);
          else if (which[j] == DENSITY_NUMBER || which[j] == DENSITY_MASS ||
                   scaleflag == NOSCALE)
            values_many[m][j] += values_one[m][j];
          else
            values_many[m][j] += values_one[m][j]/count_many[m];
        }
      count_sum[m] += count_many[m];
    }
  }

  // done if irepeat < nrepeat
  // else reset irepeat and nvalid

  irepeat++;
  if (irepeat < nrepeat) {
    nvalid += nevery;
    modify->addstep_compute(nvalid);
    return;
  }

  irepeat = 0;
  nvalid = ntimestep+nfreq - (nrepeat-1)*nevery;
  modify->addstep_compute(nvalid);

  // unlock compute chunk/atom at end of Nfreq epoch
  // do not unlock if ave = RUNNING or WINDOW

  if (nrepeat > 1 && ave == ONE) cchunk->unlock(this);

  // time average across samples
  // if normflag = ALL, final is total value / total count
  //   exception is TEMPERATURE: normalize by DOF for total count
  //   exception is DENSITYs: normalize by repeat, not total count
  //   exception is scaleflag == NOSCALE: normalize by repeat, not total count
  //     check last so other options can take precedence
  // if normflag = SAMPLE, final is sum of ave / repeat

  double repeat = nrepeat;
  double mv2d = force->mv2d;

  if (normflag == ALL) {
    MPI_Allreduce(count_many,count_sum,nchunk,MPI_DOUBLE,MPI_SUM,world);
    MPI_Allreduce(&values_many[0][0],&values_sum[0][0],nchunk*nvalues,
                  MPI_DOUBLE,MPI_SUM,world);
    for (m = 0; m < nchunk; m++) {
      if (count_sum[m] > 0.0)
        for (j = 0; j < nvalues; j++) {
          if (which[j] == TEMPERATURE)
            values_sum[m][j] *= mvv2e / ((cdof + adof*count_sum[m]) * boltz);
          else if (which[j] == DENSITY_MASS)
            values_sum[m][j] *= mv2d/repeat;
          else if (which[j] == DENSITY_NUMBER || scaleflag == NOSCALE)
            values_sum[m][j] /= repeat;
          else values_sum[m][j] /= count_sum[m];
        }
      count_sum[m] /= repeat;
    }
  } else if (normflag == SAMPLE) {
    MPI_Allreduce(&values_many[0][0],&values_sum[0][0],nchunk*nvalues,
                  MPI_DOUBLE,MPI_SUM,world);
    for (m = 0; m < nchunk; m++) {
      for (j = 0; j < nvalues; j++) values_sum[m][j] /= repeat;
      count_sum[m] /= repeat;
    }
  }

  // DENSITYs are additionally normalized by chunk volume
  // only relevant if chunks are spatial bins

  for (j = 0; j < nvalues; j++)
    if (which[j] == DENSITY_NUMBER || which[j] == DENSITY_MASS) {
      double chunk_volume = cchunk->chunk_volume_scalar;
      for (m = 0; m < nchunk; m++)
        values_sum[m][j] /= chunk_volume;
    }

  // if ave = ONE, only single Nfreq timestep value is needed
  // if ave = RUNNING, combine with all previous Nfreq timestep values
  // if ave = WINDOW, comine with nwindow most recent Nfreq timestep values

  if (ave == ONE) {
    for (m = 0; m < nchunk; m++) {
      for (i = 0; i < nvalues; i++)
        values_total[m][i] = values_sum[m][i];
      count_total[m] = count_sum[m];
    }
    normcount = 1;

  } else if (ave == RUNNING) {
    for (m = 0; m < nchunk; m++) {
      for (i = 0; i < nvalues; i++)
        values_total[m][i] += values_sum[m][i];
      count_total[m] += count_sum[m];
    }
    normcount++;

  } else if (ave == WINDOW) {
    for (m = 0; m < nchunk; m++) {
      for (i = 0; i < nvalues; i++) {
        values_total[m][i] += values_sum[m][i];
        if (window_limit) values_total[m][i] -= values_list[iwindow][m][i];
        values_list[iwindow][m][i] = values_sum[m][i];
      }
      count_total[m] += count_sum[m];
      if (window_limit) count_total[m] -= count_list[iwindow][m];
      count_list[iwindow][m] = count_sum[m];
    }

    iwindow++;
    if (iwindow == nwindow) {
      iwindow = 0;
      window_limit = 1;
    }
    if (window_limit) normcount = nwindow;
    else normcount = iwindow;
  }

  // output result to file

  if (fp && me == 0) {
    if (overwrite) fseek(fp,filepos,SEEK_SET);
    double count = 0.0;
    for (m = 0; m < nchunk; m++) count += count_total[m];
    fprintf(fp,BIGINT_FORMAT " %d %g\n",ntimestep,nchunk,count);

    int compress = cchunk->compress;
    int *chunkID = cchunk->chunkID;
    int ncoord = cchunk->ncoord;
    double **coord = cchunk->coord;

    if (!compress) {
      if (ncoord == 0) {
        for (m = 0; m < nchunk; m++) {
          fprintf(fp,"  %d %g",m+1,count_total[m]/normcount);
          for (i = 0; i < nvalues; i++)
            fprintf(fp," %g",values_total[m][i]/normcount);
          fprintf(fp,"\n");
        }
      } else if (ncoord == 1) {
        for (m = 0; m < nchunk; m++) {
          fprintf(fp,"  %d %g %g",m+1,coord[m][0],
                  count_total[m]/normcount);
          for (i = 0; i < nvalues; i++)
            fprintf(fp," %g",values_total[m][i]/normcount);
          fprintf(fp,"\n");
        }
      } else if (ncoord == 2) {
        for (m = 0; m < nchunk; m++) {
          fprintf(fp,"  %d %g %g %g",m+1,coord[m][0],coord[m][1],
                  count_total[m]/normcount);
          for (i = 0; i < nvalues; i++)
            fprintf(fp," %g",values_total[m][i]/normcount);
          fprintf(fp,"\n");
        }
      } else if (ncoord == 3) {
        for (m = 0; m < nchunk; m++) {
          fprintf(fp,"  %d %g %g %g %g",m+1,
                  coord[m][0],coord[m][1],coord[m][2],count_total[m]/normcount);
          for (i = 0; i < nvalues; i++)
            fprintf(fp," %g",values_total[m][i]/normcount);
          fprintf(fp,"\n");
        }
      }
    } else {
      int j;
      if (ncoord == 0) {
        for (m = 0; m < nchunk; m++) {
          fprintf(fp,"  %d %d %g",m+1,chunkID[m],count_total[m]/normcount);
          for (i = 0; i < nvalues; i++)
            fprintf(fp," %g",values_total[m][i]/normcount);
          fprintf(fp,"\n");
        }
      } else if (ncoord == 1) {
        for (m = 0; m < nchunk; m++) {
          j = chunkID[m];
          fprintf(fp,"  %d %d %g %g",m+1,j,coord[j-1][0],
                  count_total[m]/normcount);
          for (i = 0; i < nvalues; i++)
            fprintf(fp," %g",values_total[m][i]/normcount);
          fprintf(fp,"\n");
        }
      } else if (ncoord == 2) {
        for (m = 0; m < nchunk; m++) {
          j = chunkID[m];
          fprintf(fp,"  %d %d %g %g %g",m+1,j,coord[j-1][0],coord[j-1][1],
                  count_total[m]/normcount);
          for (i = 0; i < nvalues; i++)
            fprintf(fp," %g",values_total[m][i]/normcount);
          fprintf(fp,"\n");
        }
      } else if (ncoord == 3) {
        for (m = 0; m < nchunk; m++) {
          j = chunkID[m];
          fprintf(fp,"  %d %d %g %g %g %g",m+1,j,coord[j-1][0],
                  coord[j-1][1],coord[j-1][2],count_total[m]/normcount);
          for (i = 0; i < nvalues; i++)
            fprintf(fp," %g",values_total[m][i]/normcount);
          fprintf(fp,"\n");
        }
      }
    }

    fflush(fp);
    if (overwrite) {
      long fileend = ftell(fp);
      ftruncate(fileno(fp),fileend);
    }
  }
}
示例#8
0
void FixAveSpatial::end_of_step()
{
  int i,j,m,n;

  // skip if not step which requires doing something

  bigint ntimestep = update->ntimestep;
  if (ntimestep != nvalid) return;

  // zero out arrays that accumulate over many samples
  // if box changes, first re-setup bins

  if (irepeat == 0) {
    if (domain->box_change) setup_bins();
    for (m = 0; m < nbins; m++) {
      count_many[m] = count_sum[m] = 0.0;
      for (i = 0; i < nvalues; i++) values_many[m][i] = 0.0;
    }
  }

  // zero out arrays for one sample

  for (m = 0; m < nbins; m++) {
    count_one[m] = 0.0;
    for (i = 0; i < nvalues; i++) values_one[m][i] = 0.0;
  }

  // assign each atom to a bin

  double **x = atom->x;
  int *mask = atom->mask;
  int nlocal = atom->nlocal;

  if (nlocal > maxatom) {
    maxatom = atom->nmax;
    memory->destroy(bin);
    memory->create(bin,maxatom,"ave/spatial:bin");
  }

  if (ndim == 1) atom2bin1d();
  else if (ndim == 2) atom2bin2d();
  else atom2bin3d();

  // perform the computation for one sample
  // accumulate results of attributes,computes,fixes,variables to local copy
  // sum within each bin, only include atoms in fix group
  // compute/fix/variable may invoke computes so wrap with clear/add

  modify->clearstep_compute();

  for (m = 0; m < nvalues; m++) {
    n = value2index[m];
    j = argindex[m];

    // V,F adds velocities,forces to values

    if (which[m] == V || which[m] == F) {
      double **attribute;
      if (which[m] == V) attribute = atom->v;
      else attribute = atom->f;

      if (regionflag == 0) {
        for (i = 0; i < nlocal; i++)
          if (mask[i] & groupbit)
            values_one[bin[i]][m] += attribute[i][j];
      } else {
        for (i = 0; i < nlocal; i++)
          if (mask[i] & groupbit && region->match(x[i][0],x[i][1],x[i][2]))
            values_one[bin[i]][m] += attribute[i][j];
      }

    // DENSITY_NUMBER adds 1 to values

    } else if (which[m] == DENSITY_NUMBER) {

      if (regionflag == 0) {
        for (i = 0; i < nlocal; i++)
          if (mask[i] & groupbit)
            values_one[bin[i]][m] += 1.0;
      } else {
        for (i = 0; i < nlocal; i++)
          if (mask[i] & groupbit && region->match(x[i][0],x[i][1],x[i][2]))
            values_one[bin[i]][m] += 1.0;
      }

    // DENSITY_MASS adds mass to values

    } else if (which[m] == DENSITY_MASS) {
      int *type = atom->type;
      double *mass = atom->mass;
      double *rmass = atom->rmass;

      if (regionflag == 0) {
        for (i = 0; i < nlocal; i++)
          if (mask[i] & groupbit) {
            if (rmass) values_one[bin[i]][m] += rmass[i];
            else values_one[bin[i]][m] += mass[type[i]];
          }
      } else {
        for (i = 0; i < nlocal; i++)
          if (mask[i] & groupbit && region->match(x[i][0],x[i][1],x[i][2])) {
            if (rmass) values_one[bin[i]][m] += rmass[i];
            else values_one[bin[i]][m] += mass[type[i]];
          }
      }

    // COMPUTE adds its scalar or vector component to values
    // invoke compute if not previously invoked

    } else if (which[m] == COMPUTE) {
      Compute *compute = modify->compute[n];
      if (!(compute->invoked_flag & INVOKED_PERATOM)) {
        compute->compute_peratom();
        compute->invoked_flag |= INVOKED_PERATOM;
      }
      double *vector = compute->vector_atom;
      double **array = compute->array_atom;
      int jm1 = j - 1;

      if (regionflag == 0) {
        for (i = 0; i < nlocal; i++)
          if (mask[i] & groupbit) {
            if (j == 0) values_one[bin[i]][m] += vector[i];
            else values_one[bin[i]][m] += array[i][jm1];
          }
      } else {
        for (i = 0; i < nlocal; i++)
          if (mask[i] & groupbit && region->match(x[i][0],x[i][1],x[i][2])) {
            if (j == 0) values_one[bin[i]][m] += vector[i];
            else values_one[bin[i]][m] += array[i][jm1];
          }
      }

    // FIX adds its scalar or vector component to values
    // access fix fields, guaranteed to be ready

    } else if (which[m] == FIX) {
      double *vector = modify->fix[n]->vector_atom;
      double **array = modify->fix[n]->array_atom;
      int jm1 = j - 1;

      if (regionflag == 0) {
        for (i = 0; i < nlocal; i++)
          if (mask[i] & groupbit) {
            if (j == 0) values_one[bin[i]][m] += vector[i];
            else values_one[bin[i]][m] += array[i][jm1];
          }
      } else {
        for (i = 0; i < nlocal; i++)
          if (mask[i] & groupbit && region->match(x[i][0],x[i][1],x[i][2])) {
            if (j == 0) values_one[bin[i]][m] += vector[i];
            else values_one[bin[i]][m] += array[i][jm1];
          }
      }

    // VARIABLE adds its per-atom quantities to values
    // evaluate atom-style variable

    } else if (which[m] == VARIABLE) {
      if (nlocal > maxvar) {
        maxvar = atom->nmax;
        memory->destroy(varatom);
        memory->create(varatom,maxvar,"ave/spatial:varatom");
      }

      input->variable->compute_atom(n,igroup,varatom,1,0);

      if (regionflag == 0) {
        for (i = 0; i < nlocal; i++)
          if (mask[i] & groupbit)
            values_one[bin[i]][m] += varatom[i];
      } else {
        for (i = 0; i < nlocal; i++)
          if (mask[i] & groupbit && region->match(x[i][0],x[i][1],x[i][2]))
            values_one[bin[i]][m] += varatom[i];
      }
    }
  }

  // process a single sample
  // if normflag = ALL, accumulate values,count separately to many
  // if normflag = SAMPLE, one = value/count, accumulate one to many
  // exception is SAMPLE density: no normalization by atom count

  if (normflag == ALL) {
    for (m = 0; m < nbins; m++) {
      count_many[m] += count_one[m];
      for (j = 0; j < nvalues; j++)
        values_many[m][j] += values_one[m][j];
    }
  } else {
    MPI_Allreduce(count_one,count_many,nbins,MPI_DOUBLE,MPI_SUM,world);
    for (m = 0; m < nbins; m++) {
      if (count_many[m] > 0.0)
        for (j = 0; j < nvalues; j++) {
          if (which[j] == DENSITY_NUMBER || which[j] == DENSITY_MASS)
            values_many[m][j] += values_one[m][j];
          else values_many[m][j] += values_one[m][j]/count_many[m];
        }
      count_sum[m] += count_many[m];
    }
  }

  // done if irepeat < nrepeat
  // else reset irepeat and nvalid

  irepeat++;
  if (irepeat < nrepeat) {
    nvalid += nevery;
    modify->addstep_compute(nvalid);
    return;
  }

  irepeat = 0;
  nvalid = ntimestep+nfreq - (nrepeat-1)*nevery;
  modify->addstep_compute(nvalid);

  // time average across samples
  // if normflag = ALL, final is total value / total count
  // if normflag = SAMPLE, final is sum of ave / repeat
  // exception is densities: normalized by repeat, not total count

  double repeat = nrepeat;
  double mv2d = force->mv2d;

  if (normflag == ALL) {
    MPI_Allreduce(count_many,count_sum,nbins,MPI_DOUBLE,MPI_SUM,world);
    MPI_Allreduce(&values_many[0][0],&values_sum[0][0],nbins*nvalues,
                  MPI_DOUBLE,MPI_SUM,world);
    for (m = 0; m < nbins; m++) {
      if (count_sum[m] > 0.0)
        for (j = 0; j < nvalues; j++)
          if (which[j] == DENSITY_NUMBER) values_sum[m][j] /= repeat;
          else if (which[j] == DENSITY_MASS) values_sum[m][j] *= mv2d/repeat;
          else values_sum[m][j] /= count_sum[m];
      count_sum[m] /= repeat;
    }
  } else {
    MPI_Allreduce(&values_many[0][0],&values_sum[0][0],nbins*nvalues,
                  MPI_DOUBLE,MPI_SUM,world);
    for (m = 0; m < nbins; m++) {
      for (j = 0; j < nvalues; j++)
        values_sum[m][j] /= repeat;
      count_sum[m] /= repeat;
    }
  }

  // density is additionally normalized by bin volume

  for (j = 0; j < nvalues; j++)
    if (which[j] == DENSITY_NUMBER || which[j] == DENSITY_MASS)
      for (m = 0; m < nbins; m++)
        values_sum[m][j] /= bin_volume;

  // if ave = ONE, only single Nfreq timestep value is needed
  // if ave = RUNNING, combine with all previous Nfreq timestep values
  // if ave = WINDOW, comine with nwindow most recent Nfreq timestep values

  if (ave == ONE) {
    for (m = 0; m < nbins; m++) {
      for (i = 0; i < nvalues; i++)
        values_total[m][i] = values_sum[m][i];
      count_total[m] = count_sum[m];
    }
    norm = 1;

  } else if (ave == RUNNING) {
    for (m = 0; m < nbins; m++) {
      for (i = 0; i < nvalues; i++)
        values_total[m][i] += values_sum[m][i];
      count_total[m] += count_sum[m];
    }
    norm++;

  } else if (ave == WINDOW) {
    for (m = 0; m < nbins; m++) {
      for (i = 0; i < nvalues; i++) {
        values_total[m][i] += values_sum[m][i];
        if (window_limit) values_total[m][i] -= values_list[iwindow][m][i];
        values_list[iwindow][m][i] = values_sum[m][i];
      }
      count_total[m] += count_sum[m];
      if (window_limit) count_total[m] -= count_list[iwindow][m];
      count_list[iwindow][m] = count_sum[m];
    }

    iwindow++;
    if (iwindow == nwindow) {
      iwindow = 0;
      window_limit = 1;
    }
    if (window_limit) norm = nwindow;
    else norm = iwindow;
  }

  // output result to file

  if (fp && me == 0) {
    if (overwrite) fseek(fp,filepos,SEEK_SET);
    if(write_ts_) fprintf(fp,BIGINT_FORMAT " %d\n",ntimestep,nbins);
    if (ndim == 1)
      for (m = 0; m < nbins; m++) {
        fprintf(fp,"  %d %g %g",m+1,coord[m][0],
                count_total[m]/norm);
        for (i = 0; i < nvalues; i++)
          fprintf(fp," %g",values_total[m][i]/norm);
        fprintf(fp,"\n");
      }
    else if (ndim == 2)
      for (m = 0; m < nbins; m++) {
        fprintf(fp,"  %d %g %g %g",m+1,coord[m][0],coord[m][1],
                count_total[m]/norm);
        for (i = 0; i < nvalues; i++)
          fprintf(fp," %g",values_total[m][i]/norm);
        fprintf(fp,"\n");
      }
    else
      for (m = 0; m < nbins; m++) {
        fprintf(fp,"  %d %g %g %g %g",m+1,coord[m][0],coord[m][1],coord[m][2],
                count_total[m]/norm);
        for (i = 0; i < nvalues; i++)
          fprintf(fp," %g",values_total[m][i]/norm);
        fprintf(fp,"\n");
      }

    fflush(fp);
    if (overwrite) {
      long fileend = ftell(fp);
      ftruncate(fileno(fp),fileend);
    }
  }

  // calculate mean and standard deviation
  
  if (calcStd != 0) {
    int n_samples = 0;
    int n_empty = 0;
    int n_lower = 0;
    int n_higher = 0;
    double *true_mean, *samples_mean, *std;
    double diff, count_sum, count_samples, samples_average, count_max;

    memory->create(true_mean,nvalues,"ave/spatial:true_mean");
    memory->create(samples_mean,nvalues,"ave/spatial:samples_mean");
    memory->create(std,nvalues,"ave/spatial:std");

    count_sum = 0;
    count_samples = 0;
    samples_average = 0;
    count_max = 0;

    for (i = 0; i < nvalues; i++) {
      true_mean[i] = 0;

      for (m = 0; m < nbins; m++) {
        true_mean[i] += values_total[m][i] * count_total[m];
        if (i == 0) count_sum += count_total[m];
      }

      if (count_sum != 0) true_mean[i] /= count_sum;

      samples_mean[i] = 0;
      std[i] = 0;
    }

    for (m = 0; m < nbins; m++) {
      if (count_total[m] > count_max) count_max = count_total[m];
      if (count_total[m] == 0) n_empty += 1;
      else if (count_total[m] < lowerLimit) n_lower += 1;
      else if (count_total[m] > upperLimit) n_higher += 1;
      else {
        n_samples += 1;
        count_samples += count_total[m];
        for (i = 0; i < nvalues; i++) {
          samples_mean[i] += values_total[m][i];
          diff = values_total[m][i] - true_mean[i];
          std[i] += diff * diff;
        }
      }
    }

    if (n_samples != 0) {
      for (i = 0; i < nvalues; i++) {
        samples_average = count_samples / n_samples; // average # particles per sample
        samples_mean[i] /= n_samples;
        std[i] /= n_samples; // not(n_sample-1) since true_mean is the true Average
        std[i] = sqrt(std[i]);
        samples_mean[i] /= norm;
        std[i] /= norm;
      }
    }

    // output to file
    if (fp2 && me == 0) {
      fprintf(fp2,BIGINT_FORMAT " %g %d %g %d %d %d %d %g",
        ntimestep,count_sum,nbins,count_max,n_empty,n_lower,n_higher,n_samples,samples_average);
      for (i = 0; i < nvalues; i++) {
        fprintf(fp2," %g %g %g",true_mean[i],samples_mean[i],std[i]); //;
      }
      fprintf(fp2,"\n");
      fflush(fp2);
    }

    memory->destroy(true_mean);
    memory->destroy(samples_mean);
    memory->destroy(std);
  }
}
示例#9
0
void FixAveSpatial::end_of_step()
{
  int i,j,m,n,ilayer;
  double lo,hi;

  // skip if not step which requires doing something

  int ntimestep = update->ntimestep;
  if (ntimestep != nvalid) return;

  // if computing the first sample, setup layers
  // compute current origin = boundary for some layer
  // lo = layer boundary immediately below boxlo
  // hi = layer boundary immediately above boxhi
  // allocate and initialize arrays based on new layer count

  if (irepeat == 0) {
    double *boxlo,*boxhi,*prd;
    if (scaleflag == REDUCED) {
      boxlo = domain->boxlo_lamda;
      boxhi = domain->boxhi_lamda;
      prd = domain->prd_lamda;
    } else {
      boxlo = domain->boxlo;
      boxhi = domain->boxhi;
      prd = domain->prd;
    }

    if (originflag == LOWER) origin = boxlo[dim];
    else if (originflag == UPPER) origin = boxhi[dim];
    else if (originflag == CENTER) origin = 0.5 * (boxlo[dim] + boxhi[dim]);

    if (origin < boxlo[dim]) {
      m = static_cast<int> ((boxlo[dim] - origin) * invdelta);
      lo = origin + m*delta;
    } else {
      m = static_cast<int> ((origin - boxlo[dim]) * invdelta);
      lo = origin - m*delta;
      if (lo > boxlo[dim]) lo -= delta;
    }
    if (origin < boxhi[dim]) {
      m = static_cast<int> ((boxhi[dim] - origin) * invdelta);
      hi = origin + m*delta;
      if (hi < boxhi[dim]) hi += delta;
    } else {
      m = static_cast<int> ((origin - boxhi[dim]) * invdelta);
      hi = origin - m*delta;
    }

    offset = lo;
    nlayers = static_cast<int> ((hi-lo) * invdelta + 0.5);
    double volume = domain->xprd * domain->yprd * domain->zprd;
    layer_volume = delta * volume/prd[dim];

    if (nlayers > maxlayer) {
      maxlayer = nlayers;
      coord = (double *) memory->srealloc(coord,nlayers*sizeof(double),
					  "ave/spatial:coord");
      count_one = (double *) 
	memory->srealloc(count_one,nlayers*sizeof(double),
			 "ave/spatial:count_one");
      count_many = (double *) 
	memory->srealloc(count_many,nlayers*sizeof(double),
			 "ave/spatial:count_many");
      count_sum = (double *) 
	memory->srealloc(count_sum,nlayers*sizeof(double),
			 "ave/spatial:count_sum");
      count_total = (double *) 
	memory->srealloc(count_total,nlayers*sizeof(double),
			 "ave/spatial:count_total");

      values_one = memory->grow_2d_double_array(values_one,nlayers,nvalues,
						"ave/spatial:values_one");
      values_many = memory->grow_2d_double_array(values_many,nlayers,nvalues,
						 "ave/spatial:values_many");
      values_sum = memory->grow_2d_double_array(values_sum,nlayers,nvalues,
						"ave/spatial:values_sum");
      values_total = memory->grow_2d_double_array(values_total,nlayers,nvalues,
						  "ave/spatial:values_total");

      // initialize count and values total to zero since they accumulate

      for (m = 0; m < nlayers; m++) {
	for (i = 0; i < nvalues; i++) values_total[m][i] = 0.0;
	count_total[m] = 0.0;
      }

      // only allocate count and values list for ave = WINDOW
      // only happens once since nlayers never changes for these ave settings
      
      if (ave == WINDOW) {
	count_list =
	  memory->create_2d_double_array(nwindow,nlayers,
					 "ave/spatial:count_list");
	values_list =
	  memory->create_3d_double_array(nwindow,nlayers,nvalues,
					 "ave/spatial:values_list");
      }
    }

    for (m = 0; m < nlayers; m++) {
      coord[m] = offset + (m+0.5)*delta;
      count_many[m] = count_sum[m] = 0.0;
      for (i = 0; i < nvalues; i++) values_many[m][i] = 0.0;
    }
  }
  
  // zero out arrays for one sample

  for (m = 0; m < nlayers; m++) {
    count_one[m] = 0.0;
    for (i = 0; i < nvalues; i++) values_one[m][i] = 0.0;
  }

  // assign each atom to a layer
  // remap each atom's relevant coord back into box via PBC if necessary
  // if scaleflag = REDUCED, box coords -> lamda coords

  double **x = atom->x;
  int *mask = atom->mask;
  int nlocal = atom->nlocal;

  if (nlocal > maxatomlayer) {
    maxatomlayer = atom->nmax;
    memory->sfree(layer);
    layer = (int *) 
      memory->smalloc(maxatomlayer*sizeof(int),"ave/spatial:layer");
  }

  double *boxlo,*boxhi,*prd;
  double xremap;
  int periodicity = domain->periodicity[dim];

  if (periodicity) {
    if (scaleflag == REDUCED) {
      boxlo = domain->boxlo_lamda;
      boxhi = domain->boxhi_lamda;
      prd = domain->prd_lamda;
    } else {
      boxlo = domain->boxlo;
      boxhi = domain->boxhi;
      prd = domain->prd;
    }
  }

  if (scaleflag == REDUCED) domain->x2lamda(nlocal);
  
  for (i = 0; i < nlocal; i++)
    if (mask[i] & groupbit) {
      xremap = x[i][dim];
      if (periodicity) {
	if (xremap < boxlo[dim]) xremap += prd[dim];
	if (xremap >= boxhi[dim]) xremap -= prd[dim];
      }
      ilayer = static_cast<int> ((xremap - offset) * invdelta);
      if (ilayer < 0) ilayer = 0;
      if (ilayer >= nlayers) ilayer = nlayers-1;
      layer[i] = ilayer;
      count_one[ilayer] += 1.0;
    }

  if (scaleflag == REDUCED) domain->lamda2x(nlocal);

  // perform the computation for one sample
  // accumulate results of attributes,computes,fixes,variables to local copy
  // sum within each layer, only include atoms in fix group
  // compute/fix/variable may invoke computes so wrap with clear/add

  modify->clearstep_compute();

  for (m = 0; m < nvalues; m++) {
    n = value2index[m];
    j = argindex[m];

    // X,V,F adds coords,velocities,forces to values

    if (which[m] == X || which[m] == V || which[m] == F) {
      double **attribute;
      if (which[m] == X) attribute = x;
      else if (which[m] == V) attribute = atom->v;
      else attribute = atom->f;

      for (i = 0; i < nlocal; i++)
	if (mask[i] & groupbit)
	  values_one[layer[i]][m] += attribute[i][j];

    // DENSITY_NUMBER adds 1 to values

    } else if (which[m] == DENSITY_NUMBER) {

      for (i = 0; i < nlocal; i++)
	if (mask[i] & groupbit)
	  values_one[layer[i]][m] += 1.0;

    // DENSITY_MASS adds mass to values

    } else if (which[m] == DENSITY_MASS) {
      int *type = atom->type;
      double *mass = atom->mass;
      double *rmass = atom->rmass;

      for (i = 0; i < nlocal; i++)
	if (mask[i] & groupbit)
	  if (rmass) values_one[layer[i]][m] += rmass[i];
	  else values_one[layer[i]][m] += mass[type[i]];

    // COMPUTE adds its scalar or vector component to values
    // invoke compute if not previously invoked

    } else if (which[m] == COMPUTE) {
      Compute *compute = modify->compute[n];
      if (!(compute->invoked_flag & INVOKED_PERATOM)) {
	compute->compute_peratom();
	compute->invoked_flag |= INVOKED_PERATOM;
      }
      double *vector = compute->vector_atom;
      double **array = compute->array_atom;
      int jm1 = j - 1;

      for (i = 0; i < nlocal; i++)
	if (mask[i] & groupbit)
	  if (j == 0) values_one[layer[i]][m] += vector[i];
	  else values_one[layer[i]][m] += array[i][jm1];
      
    // FIX adds its scalar or vector component to values
    // access fix fields, guaranteed to be ready

    } else if (which[m] == FIX) {
      double *vector = modify->fix[n]->vector_atom;
      double **array = modify->fix[n]->array_atom;
      int jm1 = j - 1;

      for (i = 0; i < nlocal; i++)
	if (mask[i] & groupbit) {
	  if (j == 0) values_one[layer[i]][m] += vector[i];
	  else values_one[layer[i]][m] += array[i][jm1];
	}

    // VARIABLE adds its per-atom quantities to values
    // evaluate atom-style variable

    } else if (which[m] == VARIABLE) {
      if (nlocal > maxatomvar) {
	maxatomvar = atom->nmax;
	memory->sfree(varatom);
	varatom = (double *) 
	  memory->smalloc(maxatomvar*sizeof(double),"ave/spatial:varatom");
      }

      input->variable->compute_atom(n,igroup,varatom,1,0);

      for (i = 0; i < nlocal; i++)
	if (mask[i] & groupbit)
	  values_one[layer[i]][m] += varatom[i];
    }
  }

  // process a single sample
  // if normflag = ALL, accumulate values,count separately to many
  // if normflag = SAMPLE, one = value/count, accumulate one to many
  // exception is SAMPLE density: no normalization by atom count

  if (normflag == ALL) {
    for (m = 0; m < nlayers; m++) {
      count_many[m] += count_one[m];
      for (j = 0; j < nvalues; j++)
	values_many[m][j] += values_one[m][j];
    }
  } else {
    MPI_Allreduce(count_one,count_many,nlayers,MPI_DOUBLE,MPI_SUM,world);
    for (m = 0; m < nlayers; m++) {
      if (count_many[m] > 0.0)
	for (j = 0; j < nvalues; j++) {
	  if (which[j] == DENSITY_NUMBER || which[j] == DENSITY_MASS)
	    values_many[m][j] += values_one[m][j];
	  else values_many[m][j] += values_one[m][j]/count_many[m];
	}
      count_sum[m] += count_many[m];
    }
  }

  // done if irepeat < nrepeat
  // else reset irepeat and nvalid

  irepeat++;
  if (irepeat < nrepeat) {
    nvalid += nevery;
    modify->addstep_compute(nvalid);
    return;
  }

  irepeat = 0;
  nvalid = ntimestep+nfreq - (nrepeat-1)*nevery;
  modify->addstep_compute(nvalid);

  // time average across samples
  // if normflag = ALL, final is total value / total count
  // if normflag = SAMPLE, final is sum of ave / repeat
  // exception is ALL density: normalized by repeat, not total count

  double repeat = nrepeat;

  if (normflag == ALL) {
    MPI_Allreduce(count_many,count_sum,nlayers,MPI_DOUBLE,MPI_SUM,world);
    MPI_Allreduce(&values_many[0][0],&values_sum[0][0],nlayers*nvalues,
		  MPI_DOUBLE,MPI_SUM,world);
    for (m = 0; m < nlayers; m++) {
      if (count_sum[m] > 0.0)
	for (j = 0; j < nvalues; j++)
	  if (which[j] == DENSITY_NUMBER || which[j] == DENSITY_MASS)
	    values_sum[m][j] /= repeat;
	  else values_sum[m][j] /= count_sum[m];
      count_sum[m] /= repeat;
    }
  } else {
    MPI_Allreduce(&values_many[0][0],&values_sum[0][0],nlayers*nvalues,
		  MPI_DOUBLE,MPI_SUM,world);
    for (m = 0; m < nlayers; m++) {
      for (j = 0; j < nvalues; j++)
	values_sum[m][j] /= repeat;
      count_sum[m] /= repeat;
    }
  }

  // density is additionally normalized by layer volume

  for (j = 0; j < nvalues; j++)
    if (which[j] == DENSITY_NUMBER || which[j] == DENSITY_MASS)
      for (m = 0; m < nlayers; m++)
	values_sum[m][j] /= layer_volume;

  // if ave = ONE, only single Nfreq timestep value is needed
  // if ave = RUNNING, combine with all previous Nfreq timestep values
  // if ave = WINDOW, comine with nwindow most recent Nfreq timestep values

  if (ave == ONE) {
    for (m = 0; m < nlayers; m++) {
      for (i = 0; i < nvalues; i++) 
	values_total[m][i] = values_sum[m][i];
      count_total[m] = count_sum[m];
    }
    norm = 1;

  } else if (ave == RUNNING) {
    for (m = 0; m < nlayers; m++) {
      for (i = 0; i < nvalues; i++)
	values_total[m][i] += values_sum[m][i];
      count_total[m] += count_sum[m];
    }
    norm++;

  } else if (ave == WINDOW) {
    for (m = 0; m < nlayers; m++) {
      for (i = 0; i < nvalues; i++) {
	values_total[m][i] += values_sum[m][i];
	if (window_limit) values_total[m][i] -= values_list[iwindow][m][i];
	values_list[iwindow][m][i] = values_sum[m][i];
      }
      count_total[m] += count_sum[m];
      if (window_limit) count_total[m] -= count_list[iwindow][m];
      count_list[iwindow][m] = count_sum[m];
    }

    iwindow++;
    if (iwindow == nwindow) {
      iwindow = 0;
      window_limit = 1;
    }
    if (window_limit) norm = nwindow;
    else norm = iwindow;
  }

  // output result to file
  
  if (fp && me == 0) {
    fprintf(fp,"%d %d\n",ntimestep,nlayers);
    for (m = 0; m < nlayers; m++) {
      fprintf(fp,"  %d %g %g",m+1,coord[m],count_total[m]/norm);
      for (i = 0; i < nvalues; i++) fprintf(fp," %g",values_total[m][i]/norm);
      fprintf(fp,"\n");
    }
    fflush(fp);
  }
}
示例#10
0
/*
 Added for mdhandle.
 
 Alternative to lammps_extract_compute() which returns a copy of data
 rather than a pointer to integrate with mdhandle.  Approach is akin to
 lammps_get_coords()
 
 Added additional types to specifically handle vectors, tensors and symmetric
 tensors.
 
 Deleted style 0 (globals) and style 2 (locals) from lammps_extract_compute()
 
 See lammps_extract_compute()  for more information
*/
void *lammps_lazy_extract_compute(void *ptr, double *comp, char *id, 
                                                            int style, int type)
{
  LAMMPS *lmp = (LAMMPS *) ptr;

  int icompute = lmp->modify->find_compute(id);
  if (icompute < 0) return NULL;
  Compute *compute = lmp->modify->compute[icompute];

//  if (lmp->atom->tag_enable == 0 || lmp->atom->tag_consecutive() == 0) return;

  int natoms = static_cast<int> (lmp->atom->natoms);

  // Deleted style == 0 for global data 

  if (style == 1) {
    if (!compute->peratom_flag) return NULL;
    if (type == 0) {
      if (compute->invoked_peratom != lmp->update->ntimestep)
	      compute->compute_peratom();
	      
          double *copy = new double[natoms];
          for (int i = 0; i < natoms; i++) copy[i] = 0.0;
        
          double *x = compute->vector_atom;
          int *tag = lmp->atom->tag;
          int nlocal = lmp->atom->nlocal;

          int id,offset;
          for (int i = 0; i < nlocal; i++) {
              id = tag[i];
              offset = id-1;
              copy[offset] = x[i];
          }

          MPI_Allreduce(copy,comp,natoms,MPI_DOUBLE,MPI_SUM,lmp->world);
          delete [] copy;
      } // end type 0
      
      
      // Vectors
      if (type == 1) {
        if (compute->invoked_peratom != lmp->update->ntimestep)
  	      compute->compute_peratom();

            double *copy = new double[3*natoms];
            for (int i = 0; i < 3*natoms; i++) copy[i] = 0.0;

            double **x =  compute->array_atom;
            int *tag = lmp->atom->tag;
            int nlocal = lmp->atom->nlocal;

            int id,offset;
            for (int i = 0; i < nlocal; i++) {
                id = tag[i];
                offset = 3*(id-1);
                copy[offset+0] = x[i][0];
                copy[offset+1] = x[i][1];
                copy[offset+2] = x[i][2];
            }

            MPI_Allreduce(copy,comp,3*natoms,MPI_DOUBLE,MPI_SUM,lmp->world);
            delete [] copy;

      } // end type 1
      
      // Tensors
      if (type == 2) {
        if (compute->invoked_peratom != lmp->update->ntimestep)
  	      compute->compute_peratom();

            double *copy = new double[9*natoms];
            for (int i = 0; i < 9*natoms; i++) copy[i] = 0.0;

            double **x =  compute->array_atom;
            int *tag = lmp->atom->tag;
            int nlocal = lmp->atom->nlocal;

            int id,offset;
            for (int i = 0; i < nlocal; i++) {
                id = tag[i];
                offset = 9*(id-1);
                copy[offset+0] = x[i][0];
                copy[offset+1] = x[i][1];
                copy[offset+2] = x[i][2];
                copy[offset+3] = x[i][3];
                copy[offset+4] = x[i][4];
                copy[offset+5] = x[i][5];
                copy[offset+6] = x[i][6];
                copy[offset+7] = x[i][7];
                copy[offset+8] = x[i][8];
            }

            MPI_Allreduce(copy,comp,8*natoms,MPI_DOUBLE,MPI_SUM,lmp->world);
            delete [] copy;
      } // end type 2

    // Symmetric tensors
    if (type == 3) {
      if (compute->invoked_peratom != lmp->update->ntimestep)
	      compute->compute_peratom();

          double *copy = new double[6*natoms];
          for (int i = 0; i < 6*natoms; i++) copy[i] = 0.0;
        
          double **x =  compute->array_atom;
          int *tag = lmp->atom->tag;
          int nlocal = lmp->atom->nlocal;

          int id,offset;
          for (int i = 0; i < nlocal; i++) {
              id = tag[i];
              offset = 6*(id-1);
              copy[offset+0] = x[i][0];
              copy[offset+1] = x[i][1];
              copy[offset+2] = x[i][2];
              copy[offset+3] = x[i][3];
              copy[offset+4] = x[i][4];
              copy[offset+5] = x[i][5];
          }

          MPI_Allreduce(copy,comp,6*natoms,MPI_DOUBLE,MPI_SUM,lmp->world);
          delete [] copy;

      } // end type 3
  } // end style 1

  // Deleted style == 2 for local data

  return NULL;
}