diff --git a/src/dump_image.cpp b/src/dump_image.cpp index a9af9d81f3..55fd565d9a 100644 --- a/src/dump_image.cpp +++ b/src/dump_image.cpp @@ -35,6 +35,8 @@ using namespace LAMMPS_NS; using namespace MathConst; +#define BIG 1.0e20 + enum{PPM,JPG}; enum{NUMERIC,ATOM,TYPE,ELEMENT,ATTRIBUTE}; enum{STATIC,DYNAMIC}; @@ -492,9 +494,6 @@ void DumpImage::write() if (viewflag == DYNAMIC) view_params(); // nme = # of atoms this proc will contribute to dump - // pack buf with x,y,z,color,diameter - // set minmax color range if using atom color map - // create my portion of image for my particles nme = count(); @@ -504,8 +503,28 @@ void DumpImage::write() memory->create(buf,maxbuf*size_one,"dump:buf"); } + // pack buf with color & diameter + pack(NULL); - if (acolor == ATTRIBUTE) image->map_minmax(0,nchoose,buf,size_one); + + // set minmax color range if using dynamic atom color map + + if (acolor == ATTRIBUTE && image->map_dynamic(0)) { + double two[2],twoall[2]; + double lo = BIG; + double hi = -BIG; + int m = 0; + for (int i = 0; i < nchoose; i++) { + lo = MIN(lo,buf[m]); + hi = MAX(hi,buf[m]); + m += size_one; + } + two[0] = -lo; + two[1] = hi; + MPI_Allreduce(two,twoall,2,MPI_DOUBLE,MPI_MAX,world); + int flag = image->map_minmax(0,-twoall[0],twoall[1]); + if (flag) error->all(FLERR,"Invalid color map min/max values"); + } // create image on each proc, then merge them diff --git a/src/image.cpp b/src/image.cpp index a76af35906..77df9b5a7f 100644 --- a/src/image.cpp +++ b/src/image.cpp @@ -37,7 +37,6 @@ using namespace MathConst; #define NCOLORS 140 #define NELEMENTS 109 -#define BIG 1.0e20 #define EPSILON 1.0e-6 enum{NUMERIC,MINVALUE,MAXVALUE}; @@ -1032,6 +1031,15 @@ void Image::write_PPM(FILE *fp) writeBuffer[2 + x*3 + y*width*3]); } +/* ---------------------------------------------------------------------- + return static/dynamic status of color map index +------------------------------------------------------------------------- */ + +int Image::map_dynamic(int index) +{ + return maps[index]->dynamic; +} + /* ---------------------------------------------------------------------- redefine properties of the color map index return 1 if any error in args, else return 0 @@ -1046,9 +1054,9 @@ int Image::map_reset(int index, int narg, char **arg) set min/max bounds of color map index ------------------------------------------------------------------------- */ -void Image::map_minmax(int index, int n, double *buf, int stride) +int Image::map_minmax(int index, double mindynamic, double maxdynamic) { - maps[index]->minmax(n,buf,stride); + return maps[index]->minmax(mindynamic,maxdynamic); } /* ---------------------------------------------------------------------- @@ -1597,6 +1605,8 @@ ColorMap::ColorMap(LAMMPS *lmp, Image *caller) : Pointers(lmp) // default color map + dynamic = 1; + mlo = MINVALUE; mhi = MAXVALUE; mstyle = CONTINUOUS; @@ -1604,9 +1614,9 @@ ColorMap::ColorMap(LAMMPS *lmp, Image *caller) : Pointers(lmp) nentry = 2; mentry = new MapEntry[nentry]; - mentry[0].svalue = 0.0; + mentry[0].single = MINVALUE; mentry[0].color = image->color2rgb("blue"); - mentry[1].svalue = 1.0; + mentry[1].single = MAXVALUE; mentry[1].color = image->color2rgb("red"); } @@ -1639,6 +1649,9 @@ int ColorMap::reset(int narg, char **arg) if (mlo == NUMERIC && mhi == NUMERIC && mlovalue >= mhivalue) return 1; + if (mlo == MINVALUE || mhi == MAXVALUE) dynamic = 1; + else dynamic = 0; + if (strlen(arg[2]) != 2) return 1; if (arg[2][0] == 'c') mstyle = CONTINUOUS; else if (arg[2][0] == 'd') mstyle = DISCRETE; @@ -1708,44 +1721,47 @@ int ColorMap::reset(int narg, char **arg) if (nentry < 1) return 1; } + // one-time call to minmax if color map is static + + if (!dynamic) return minmax(mlovalue,mhivalue); + return 0; } /* ---------------------------------------------------------------------- - set explicit values for all min/max settings in color map - lo/hi current and lvalue/hvalue settings for lo/hi = MIN/MAX VALUE in entries - if mlo/mhi = MIN/MAX VALUE, compute bounds based on N strided values in buf + set explicit values for all min/max settings in color map + from min/max dynamic values + set lo/hi current and lvalue/hvalue entries that are MIN/MAX VALUE + called only once if mlo/mhi != MIN/MAX VALUE, else called repeatedly + return 1 = error if any values now overlap incorrectly with dynamic bounds + else return 0 ------------------------------------------------------------------------- */ -void ColorMap::minmax(int n, double *buf, int stride) +int ColorMap::minmax(double mindynamic, double maxdynamic) { - double two[2],twoall[2]; - - if (mlo == MINVALUE || mhi == MAXVALUE) { - double lo = BIG; - double hi = -BIG; - int m = 0; - for (int i = 0; i < n; i++) { - lo = MIN(lo,buf[m]); - hi = MAX(hi,buf[m]); - m += stride; - } - two[0] = -lo; - two[1] = hi; - MPI_Allreduce(two,twoall,2,MPI_DOUBLE,MPI_MAX,world); - } - - if (mlo == MINVALUE) locurrent = -twoall[0]; + if (mlo == MINVALUE) locurrent = mindynamic; else locurrent = mlovalue; - if (mhi == MAXVALUE) hicurrent = twoall[1]; + if (mhi == MAXVALUE) hicurrent = maxdynamic; else hicurrent = mhivalue; - if (locurrent > hicurrent) error->all(FLERR,"Invalid image color range"); + if (locurrent > hicurrent) return 1; if (mstyle == CONTINUOUS) { if (mrange == ABSOLUTE) mentry[0].svalue = locurrent; else mentry[0].svalue = 0.0; if (mrange == ABSOLUTE) mentry[nentry-1].svalue = hicurrent; else mentry[nentry-1].svalue = 1.0; + + // error in ABSOLUTE mode if new lo/hi current cause + // first/last entry to become lo > hi with adjacent entry + + if (mrange == ABSOLUTE) { + if (mentry[0].svalue > mentry[1].svalue) return 1; + if (mentry[nentry-2].svalue > mentry[nentry-1].svalue) return 1; + } + + // OK if new lo/hi current cause an entry to have lo > hi, + // since last entry will always be a match + } else if (mstyle == DISCRETE) { for (int i = 0; i < nentry; i++) { if (mentry[i].lo == MINVALUE) { diff --git a/src/image.h b/src/image.h index 3cf8c6f7af..207f18b84d 100644 --- a/src/image.h +++ b/src/image.h @@ -51,8 +51,9 @@ class Image : protected Pointers { void draw_box(double (*)[3], double); void draw_axes(double (*)[3], double); + int map_dynamic(int); int map_reset(int, int, char **); - void map_minmax(int, int, double *, int); + int map_minmax(int, double, double); double *map_value2color(int, double); int addcolor(char *, double, double, double); @@ -138,10 +139,12 @@ class Image : protected Pointers { class ColorMap : protected Pointers { public: + int dynamic; // 0/1 if lo/hi bounds are static/dynamic + ColorMap(class LAMMPS *, class Image*); ~ColorMap(); int reset(int, char **); - void minmax(int, double *, int); + int minmax(double, double); double *value2color(double); private: