diff -urN A/A.c A3/A.c --- A/A.c 2009-07-28 06:48:53.000000000 +0900 +++ A3/A.c 2011-02-22 15:15:37.000000000 +0900 @@ -6,6 +6,12 @@ #include "A.h" #include "Icon/icon.c" +#ifdef USE_CUI +# include "cui.h" +#endif +#ifdef USE_P3D +# include "p3dp.h" +#endif /* from libAtoms: */ Aapp_Define_Config; @@ -109,6 +115,9 @@ } AX_3D_Lines_Zprint(iw, L); } +#ifdef USE_P3D + p3dp_zmap_reduce(iw); +#endif return; } /* end paint_scene() */ @@ -766,6 +775,9 @@ default: return (FALSE); } } /* end treatevent() */ +#ifdef USE_CUI +# define treatevent(iw) ((cui_enabled) ? gui_treatevent(iw) : treatevent(iw)) +#endif void thread_start (void *icopy) @@ -853,6 +865,10 @@ ((H[2][2] < 0)?1:0) * H[2][2]; look_at_the_anchor(iw); if (np < 256) perspective_to_parallel(iw); +#ifdef USE_CUI + if (cui_xterm_win) xterm_win = cui_xterm_win; + else +#endif xterm_win = AXIdentifyWIN(iw,xterm_identifier); /* fprintf (stderr, "xterm_win = 0x%lx\n", (long)xterm_win); */ XStoreName(AX_display[iw],xterm_win,AX_title[iw]); @@ -869,6 +885,10 @@ { /* blocking is more CPU efficient */ while (!nontrivial_event) { +#ifdef USE_CUI + if (cui_enabled >= 0 && (!cui_enabled || AXPending(iw))) + { +#endif AXNextEvent(iw); nontrivial_event = treatevent (iw); for (j=3; ;j*=2) @@ -887,6 +907,11 @@ } else break; } +#ifdef USE_CUI + } + if (cui_enabled && !nontrivial_event) + nontrivial_event = cui_treatevent(iw) && cui_diligence; +#endif } paint_scene(iw); AX_dump(iw); AX_show(iw); @@ -918,10 +943,23 @@ register int i; int k,god; double tmp[3]; +#ifdef USE_CUI + double timing[4]; +#else char command[512], *TTYname; +#endif memcpy(CoordColor, ATOM_COORDINATION_COLOR, (ATOM_COORDINATION_MAX+1)*sizeof(Atom_coordination_color)); memcpy(Dmitri, MENDELEYEV, (MENDELEYEV_MAX+1)*sizeof(struct Mendeleyev)); +#ifdef USE_CUI + if (cui_init(&argc, &argv)) + { + fprintf(stderr, "Threaded atomistic configuration viewer V%s " + "(C) Ju Li %s\nUsage: %s \n", + AX_VERSION, JLCPL_YRS, argv[0]); + return (1); + } +#else if (argc == 2) { if (!command_exists("xterm")) @@ -953,6 +991,10 @@ strcpy (config_fname, argv[1]); strcpy (xterm_identifier, argv[2]); redirect_stderr_to (wOpen(argv[3])); +#endif +#ifdef USE_P3D + if (!p3dp_enabled) { +#endif if (!Fexists(config_fname)) { pr ("\n** %s: **\n", config_fname); @@ -965,7 +1007,16 @@ pr ("** This file is unreadable! **\n"); return(1); } +#ifdef USE_P3D + } +#endif +#ifdef USE_CUI + if (cui_enabled && IS_MANAGER) timing[0] = cui_wtime(); +#endif i = CONFIG_LOAD (config_fname, Config_Aapp_to_Alib); +#ifdef USE_CUI + if (cui_enabled && IS_MANAGER) timing[1] = cui_wtime() - timing[0]; +#endif for (k=0; kt; k++) */ /* NEIGHBOR_TABLE(N->rcut,ct,i,k) = 0; */ +#ifdef USE_CUI + if (cui_enabled && IS_MANAGER) timing[0] = cui_wtime(); + if (cui_enabled && !IS_MANAGER) + Neighborlist_Recreate (Config_Aapp_to_Alib, NULL, ct, &tp, N); + else +#endif Neighborlist_Recreate (Config_Aapp_to_Alib, stdout, ct, &tp, N); +#ifdef USE_CUI + if (cui_enabled && IS_MANAGER) timing[2] = cui_wtime() - timing[0]; +#endif /* H[][] may have been modified in Neighborlist_Recreate() */ M3InV (H, HI, volume); lengthscale = cbrt(volume); geo_clear_has_evaluated_flags(); evaluate_geo_measures(); Free(s1); Free(mass); +#ifdef USE_CUI + if (!cui_enabled || IS_MANAGER) { +#endif print_coordination_histogram(); cr(); if (guess_to_be_PBC) { S3PR("avg. M = %M\n ", avg_M); printf ("avg. microscopic shear strain = %g\n", avg_shear_strain); } +#ifdef USE_CUI + } +#endif V3ASSIGN (0.5,0.5,0.5,tmp); V3mM3 (tmp,H,cm); rcut_patching = rcut_patch_top = 0; select_fbasename (config_fname); +#ifdef USE_CUI + if (cui_enabled && IS_MANAGER) timing[0] = cui_wtime(); +#endif /* pmemusage(); */ Config_to_3D_Balls (DEFAULT_ATOM_R_RATIO); /* pmemusage(); */ Config_to_3D_Bonds (DEFAULT_BOND_RADIUS); +#ifdef USE_CUI + if (cui_enabled && IS_MANAGER) { + timing[3] = cui_wtime() - timing[0]; + fprintf(stderr, "config_load: %.3f\n" + "neighborlist: %.3f\n" + "config_to_3D: %.3f\n", timing[1],timing[2],timing[3]); + } +#endif pmemusage(); god = -1; +#ifdef USE_P3D + if (p3dp_enabled && setjmp(quit_env)) p3dp_finalize(); + else +#endif thread_start(&god); return(0); } /* end main() */ diff -urN A/Makefile A3/Makefile --- A/Makefile 2009-05-01 02:36:46.000000000 +0900 +++ A3/Makefile 2011-02-22 15:15:37.000000000 +0900 @@ -7,10 +7,12 @@ PROG = A HEADER = $(PROG).h OBJS = $(PROG).o primitives.o viewport.o utils.o xtal_shift.o info.o \ - rcut_patch.o scratch.o geo.o LeastSquareStrain.o + rcut_patch.o scratch.o geo.o LeastSquareStrain.o \ + cui.o cui_AX.o p3dp.o p3dp_info.o p3dp_AX.o P3DCore.o SRCS = $(addsuffix .c, $(basename ${OBJS})) INPUT = 1D66.pdb.bz2 -USE_SYSTEM_LIB = -lm -L/usr/X11R6/lib/ -lXext -lX11 -lpthread +USE_SYSTEM_LIB = -lm -L/usr/X11R6/lib/ -lXext -lX11 -lpthread \ + -lmpi -llam -laio -laio -lutil USE_MY_LIB = -lAX -lpng -lz -ljpeg -lAtoms -lVecMat3 -lVecMat -lIO -lScalar \ -lTimer -llapack -lblas -lXpm -lreadline -lhistory -ltermcap SHELL = sh @@ -106,14 +108,13 @@ # LD = /usr/local/pgcc/bin/g77 -static # # CCFLAGS = -Wall -O6 -mpentiumpro -march=pentiumpro -mmx -ffast-math \ # # -funroll-loops -inline-functions -s # - CC = icc -w + CC = mpicc # LD = icc -static # - LD = icc + LD = mpicc # CCFLAGS = -g # - CCFLAGS = -O2 -axKWNBP + CCFLAGS = -O2 USE_MY_LIB = -lAX -lpng -lz -ljpeg -lAtoms -lVecMat3 -lVecMat -lIO -lScalar \ - -lTimer -L/opt/intel/mkl70/lib/32/ -lmkl_lapack -lmkl_ia32 \ - -lguide -lXpm -lreadline -lhistory -ltermcap -lsvml -ldl + -lTimer -llapack -lXpm -lreadline -lhistory -ltermcap -ldl # USE_MY_LIB = -lAX -lpng -lz -ljpeg -lAtoms -lVecMat3 -lVecMat -lIO -lScalar\ # # -lTimer \ # # /opt/intel/mkl/8.0.2/lib/32/libmkl_lapack.a \ # @@ -164,7 +165,8 @@ # one may use 'otool -L' instead of 'ldd' to check dynamic lib # endif -CFLAGS = -D_$(SYS) ${CCFLAGS} -I${MY_INC_DIR} +CFLAGS = -D_$(SYS) ${CCFLAGS} -I${MY_INC_DIR} \ + -I.. -DUSE_CUI -DUSE_P3D LDFLAGS = -L${MY_LIB_DIR} ${USE_MY_LIB} ${SYSTEM_LIB_FLAG} ${USE_SYSTEM_LIB} .PHONY: all i install c clean b backup t test g r relink a access diff -urN A/P3D.h A3/P3D.h --- A/P3D.h 1970-01-01 09:00:00.000000000 +0900 +++ A3/P3D.h 2011-02-22 15:15:37.000000000 +0900 @@ -0,0 +1,253 @@ +/* $Id: P3D.h,v 1.10 2005/07/23 17:36:36 shimizu Exp $ + * 2004-2005 Futoshi SHIMIZU + */ +#ifndef P3D_H +#define P3D_H + +#include "mpi.h" +#include "VecMat3.h" +#include "P3DExt.h" + +#define P3D_INFINITY 1.e+308 +#define P3D_LINEMAX 1024 + +#ifndef CONFIG_MAX_AUXILIARY +#define CONFIG_MAX_AUXILIARY 32 +#endif + + +typedef struct { +#ifdef P3DAtomPRE + P3DAtomPRE +#endif + V3 r, v; /* position, velocity */ + double m; /* mass */ + char sym[sizeof(int)]; /* symbol */ + int iw; /* work (for P3D) */ + double aux[CONFIG_MAX_AUXILIARY]; +#ifdef P3DAtomMD + V3 a, f; /* acceleration, force */ + double p; /* potential */ + M3 vir; /* virial */ +#endif +#ifdef P3DAtomPOST + P3DAtomPOST +#endif +} P3DAtom; + +typedef struct Auxiliary_tag { + int n_aux; + char name[CONFIG_MAX_AUXILIARY][P3D_LINEMAX]; + char unit[CONFIG_MAX_AUXILIARY][P3D_LINEMAX]; +} *Auxiliary; + + +typedef struct Cell_tag { + M3 h, virial; + int idx_trans; + int pbc[3]; + int reduced_coordinates; + Auxiliary auxiliary; + struct Cell_private_tag *private; +} *Cell; + +typedef struct Pair_tag { + P3DAtom **begin, **end; +} *Pair; + +typedef struct List_tag *List; + + + +enum p3d_index_flags { + I_ENT, I_ONT, I_WNT, + I_EOT, I_OOT, I_WOT, + I_EST, I_OST, I_WST, + + I_ENO, I_ONO, I_WNO, + I_EOO, I_OOO, I_WOO, + I_ESO, I_OSO, I_WSO, + + I_ENB, I_ONB, I_WNB, + I_EOB, I_OOB, I_WOB, + I_ESB, I_OSB, I_WSB, + I_XYZ +}; + +enum p3d_flags_index { + F_OOO = 0x00, + F_EOO = 0x20, + F_WOO = 0x10, + F_ONO = 0x08, + F_ENO = F_EOO | F_ONO, + F_WNO = F_WOO | F_ONO, + F_OSO = 0x04, + F_ESO = F_EOO | F_OSO, + F_WSO = F_WOO | F_OSO, + F_OOT = 0x02, + F_EOT = F_EOO | F_OOT, + F_WOT = F_WOO | F_OOT, + F_ONT = F_ONO | F_OOT, + F_ENT = F_EOO | F_ONO | F_OOT, + F_WNT = F_WOO | F_ONO | F_OOT, + F_OST = F_OSO | F_OOT, + F_EST = F_EOO | F_OSO | F_OOT, + F_WST = F_WOO | F_OSO | F_OOT, + F_OOB = 0x01, + F_EOB = F_EOO | F_OOB, + F_WOB = F_WOO | F_OOB, + F_ONB = F_ONO | F_OOB, + F_ENB = F_EOO | F_ONO | F_OOB, + F_WNB = F_WOO | F_ONO | F_OOB, + F_OSB = F_OSO | F_OOB, + F_ESB = F_EOO | F_OSO | F_OOB, + F_WSB = F_WOO | F_OSO | F_OOB +}; + + + +#ifndef P3D_GLOBAL +# define P3D_GLOBAL extern +#endif +P3D_GLOBAL MPI_Comm p3d_global_comm; +P3D_GLOBAL int p3d_global_nprocs, p3d_global_rank; +P3D_GLOBAL int p3d_global_io_any, p3d_global_rank_fprintf; +P3D_GLOBAL char *p3d_global_decomp_string; + + +/*#undef P3D_QUIET*/ + +/** +#define p3d_abort(errorcode) (fprintf(stderr, "[%d] Abort, %s %u(%s): %d\n",\ + p3d_global_rank, __FILE__, __LINE__, __func__, errorcode),\ + fflush(stderr), MPI_Abort(MPI_COMM_WORLD, errorcode)) +**/ +/**/ +#define p3d_abort(errorcode) (fprintf(stderr, "[%d] Abort, %s %u: %d\n",\ + p3d_global_rank, __FILE__, __LINE__, errorcode),\ + fflush(stderr), MPI_Abort(MPI_COMM_WORLD, errorcode)) +/**/ + + +#define P3D_LOOP(cell,pnt) \ + for (pnt = p3d_atom_begin(cell); pnt < p3d_atom_end(cell); pnt++) + +#define P3D_LOOP_PAIR_HEAD(pair,pnt)\ + {P3DAtom **pp; for (pnt = *(pp=pair->begin); pp < pair->end; pnt=*++pp){ + +#define P3D_LOOP_PAIR_TAIL(pair) }} pair++ + +#define p3d_zero(cell,member) \ + do {P3DAtom *pnt; P3D_LOOP(cell,pnt) pnt->member=0; } while(0) + +#define p3d_V3zero(cell,member) \ + do {P3DAtom *pnt; P3D_LOOP(cell,pnt) V3ZERO(pnt->member); } while(0) + +#define p3d_M3zero(cell,member) \ + do {P3DAtom *pnt; P3D_LOOP(cell,pnt) M3ZERO(pnt->member); } while(0) + +#define DWIDTH "24" +#define DDIGIT "16" +#define DFORMAT "%" DWIDTH "." DDIGIT "e" +#define VFORMAT DFORMAT DFORMAT DFORMAT +#define MFORMAT VFORMAT VFORMAT VFORMAT +#define FFORMAT " %." DWIDTH "f" +#define FFORMAT3 FFORMAT FFORMAT FFORMAT + + +/* Core.c */ + +int p3d_init(int *argc,char ***argv, MPI_Comm comm); +int p3d_finalize(void); + +int p3d_fflush(FILE *fp); +int p3d_fprintf(FILE *fp, const char *format, ...); +int p3d_message(const char *format, ...); + +MPI_Comm p3d_comm(Cell cell); +int p3d_nprocs(Cell cell); +int p3d_rank(Cell cell); +int p3d_n_atoms(Cell cell); +int p3d_n_images(Cell cell); +P3DAtom *p3d_atom_begin(Cell cell); +P3DAtom *p3d_atom_end(Cell cell); +P3DAtom *p3d_image_begin(Cell cell); +P3DAtom *p3d_image_end(Cell cell); + +Cell p3d_new_cell(char *decomp, MPI_Datatype m_image, MPI_Comm comm); +int p3d_set_atoms(Cell cell, P3DAtom *atoms, int n); +int p3d_cat_atoms(Cell cell, P3DAtom *atoms, int n); +int p3d_remove_atom(Cell cell, P3DAtom *atom); +int p3d_reset_cell_c(Cell cell, double crust); +#define p3d_reset_cell(cell) p3d_reset_cell_c(cell, 0.0) +int p3d_update_cell(Cell cell); + +int p3d_bcast(Cell cell, void *buff, int count, + MPI_Datatype datatype, int root); +int p3d_reduce(Cell cell, void *sbuf, void *rbuf, int count, + MPI_Datatype datatype, MPI_Op op); + +int p3d_read_config(Cell cell, char *path); +int p3d_write_config(Cell cell, char *path, + char *s_formats, char*velocity_formats, int n_aux, ...); + +void p3d_coord_reduced2real(Cell cell); + + +/* P3DNeighborList.c */ + +List p3d_new_list(Cell cell); +void p3d_realloc_list(List list, int n_max, int p_max, int i_max); +int p3d_reset_list(List list, Cell cell, double cutoff); +Pair p3d_pair_atom_begin(List list); +Pair p3d_pair_image_begin(List list); + +#define p3d_reset_both(cell, list, rc_list) \ + do {\ + p3d_reset_cell_c(cell, rc_list); p3d_reset_list(list, cell, rc_list);\ + } while (0) + + +/* P3DUtils.c */ + +#define p3d_set_a_from_f(cell) \ + do { P3DAtom *pnt; P3D_LOOP(cell,pnt)\ + V3MUL(1.0/pnt->m, pnt->f, pnt->a);\ + } while (0) + + +enum { + F_FORCE = 0x01, + F_POTENTIAL = 0x02, + F_VIRIAL = 0x04, + F_ALL = F_FORCE | F_POTENTIAL | F_VIRIAL +}; + +void calc_interaction(Cell cell, List list, int flags); + +void p3d_update_r_v_verlet(Cell cell, double dt); +void p3d_update_va_v_verlet(Cell cell, double dt); +void p3d_update_gear3_pred(Cell cell, double dt); +void p3d_update_gear3_corr(Cell cell, double dt); + +double p3d_step_sd(Cell cell, double alpha, double drmax); + +double p3d_sum_kinetic_energy(Cell cell); +double p3d_sum_potential_energy(Cell cell); +double p3d_sum_momentum(Cell cell, V3 momentum); +void p3d_sum_stress(Cell cell, M3 stress); +double p3d_calc_temperature(Cell cell, double k_blt); +double p3d_calc_temperature2(Cell cell, double k_blt); +void p3d_velocity_scaling(Cell cell, double temperature, double k_blt); +void p3d_velocity_scaling2(Cell cell, double temperature, double k_blt); +void p3d_set_temperature(Cell cell, double temp, double k_blt); +void p3d_cm_vzero(Cell cell); +double p3d_sum_msd(Cell cell, int offset_0, int offset_s, int reset); + +void p3d_set_number(Cell cell, int offset); +void p3d_scale_cell(Cell cell, double target_pressure, double pk, int ip[3]); + +/* +*/ + +#endif diff -urN A/P3DCore.c A3/P3DCore.c --- A/P3DCore.c 1970-01-01 09:00:00.000000000 +0900 +++ A3/P3DCore.c 2011-02-22 15:17:23.000000000 +0900 @@ -0,0 +1,1921 @@ +/* $Id: P3DCore.c,v 1.10 2005/08/19 02:42:36 shimizu Exp $ + * 2004-2005 Futoshi SHIMIZU + */ + +#define P3D_GLOBAL +#include "P3D_p.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include + +enum p3d_index_flags + direction_flags[] = {F_EOO, F_WOO, F_ONO, F_OSO, F_OOT, F_OOB}; + +#define P3D_DECOMP_KEY "-decomp=" + +static int initialized; + +int p3d_init(int *argc, char ***argv, MPI_Comm comm) +{ + int flag, *attr_val; + + p3d_global_rank_fprintf = 0; + + MPI_Initialized(&initialized); + if (!initialized) MPI_Init(argc, argv); + + if (comm == MPI_COMM_NULL) comm = MPI_COMM_WORLD; + MPI_Comm_dup(comm, &p3d_global_comm); + MPI_Comm_size(p3d_global_comm, &p3d_global_nprocs); + MPI_Comm_rank(p3d_global_comm, &p3d_global_rank); + + MPI_Attr_get(MPI_COMM_WORLD, MPI_IO, &attr_val, &flag); + p3d_global_io_any = (flag && *attr_val == MPI_ANY_SOURCE); + + if (!(p3d_global_decomp_string = (char*) malloc(1))) p3d_abort(-1); + *p3d_global_decomp_string = '\0'; + + if (argv && *argv) { + int i, len, keylen = strlen(P3D_DECOMP_KEY); + for (i = 1; i < *argc; i++) { + if (strncmp((*argv)[i], P3D_DECOMP_KEY, keylen) == 0) { + if ((len = strlen((*argv)[i])) > keylen) { + p3d_global_decomp_string = + (char*)realloc(p3d_global_decomp_string, len-keylen+1); + if (p3d_global_decomp_string) + strcpy(p3d_global_decomp_string, (*argv)[i] + keylen); + } + (*argv)[i] = 0; + } + } + { /* mpich: MPID_ArgSqueeze */ + int j = i = 0; + while (j < *argc) { + while ((*argv)[j] == 0 && j < *argc) j++; + if (j < *argc) (*argv)[i++] = (*argv)[j++]; + } + if (!(*argv)[i-1]) i--; + *argc = i; + (*argv)[*argc] = 0; + } + } + + return 0; +} + + +int p3d_finalize(void) +{ + MPI_Comm_free(&p3d_global_comm); + if (!initialized) MPI_Finalize(); + return 0; +} + + +MPI_Comm p3d_comm(Cell cell) { return cell->private->comm; } +int p3d_nprocs(Cell cell) { return cell->private->nprocs; } +int p3d_rank(Cell cell) { return cell->private->rank; } +int p3d_n_atoms(Cell cell) { return cell->private->point_end + - cell->private->point_begin; } +int p3d_n_images(Cell cell) { return cell->private->image_end + - cell->private->point_end; } +P3DAtom *p3d_atom_begin(Cell cell) { return cell->private->point_begin; } +P3DAtom *p3d_atom_end(Cell cell) { return cell->private->point_end; } +P3DAtom *p3d_image_begin(Cell cell) { return cell->private->point_end; } +P3DAtom *p3d_image_end(Cell cell) { return cell->private->image_end; } + + +static void p3d_realloc_cell(Cell cell, int n_max, int p_max) +{ + Cell_private p = cell->private; + /*int i;*/ + + if (n_max > p->n_max) { + P3DAtom *point_begin_org = p->point_begin; + + /*p3d_fprintf(stderr, "n_max: %d -> %d\n", p->n_max, n_max);*/ + p->point_begin=(P3DAtom*)realloc(p->point_begin, n_max*sizeof(P3DAtom)); + if (p->point_begin == NULL) p3d_abort(1); + p->n_max = n_max; + + if ((char*)p->point_begin != (char*)point_begin_org) { + P3DAtom **pp; + p->point_end = p->point_begin + (p->point_end - point_begin_org); + p->image_end = p->point_begin + (p->image_end - point_begin_org); + for (pp = p->p_point_begin; pp < p->p_point_end; pp++) + *pp = p->point_begin + (*pp - point_begin_org); + } + + p->f_realloc = 1; + } + if (p_max > p->p_max) { + P3DAtom **p_point_begin_org = p->p_point_begin; + + /*p3d_fprintf(stderr, "p_max: %d -> %d\n", p->p_max, p_max);*/ + p->p_point_begin = + (P3DAtom**) realloc(p->p_point_begin, p_max*sizeof(P3DAtom*)); + if (p->point_begin == NULL) p3d_abort(1); + p->p_max = p_max; + + if ((char*)p->p_point_begin != (char*)p_point_begin_org) { + p->p_point_end=p->p_point_begin+(p->p_point_end-p_point_begin_org); + /* + for (i = 0; i <= 6; i++) + p->update[i]=p->p_point_begin+(p->update[i]-p_point_begin_org); + */ + } + + p->f_realloc = 1; + } +} + +static V3 v_eps = {1.e-7, 1.e-7, 1.e-7}; + +static int p3d_decompose(Cell cell, char *decomp, MPI_Comm comm) +{ + Cell_private p = cell->private; + char spec[3][512] = {"0", "0", "0"}; + int i; + + + for (i = 0; i < 6; i++) { + if (p->req_send[i]!=MPI_REQUEST_NULL) MPI_Request_free(&p->req_send[i]); + if (p->req_recv[i]!=MPI_REQUEST_NULL) MPI_Request_free(&p->req_recv[i]); + } + + if (!decomp || !strlen(decomp)) decomp = p3d_global_decomp_string; + { + char *s = strstr(decomp, "io_any"); + if (s) { + s += strlen("io_any"); + if (*s == '=') + sscanf(s+1, "%d", &p3d_global_io_any); + else + p3d_global_io_any = 1; + } + } + + { + int j, k; + sscanf(decomp, "%[^,],%[^,],%[^,]", spec[0], spec[1], spec[2]); + for (i = 0; i < 3; i++) { + k = 0; + for (j = 0; j < strlen(spec[i]); j++) { + switch (spec[i][j]) { + case '(': + case '/': + case ')': + k++; + break; + default: + break; + } + } + if (k != 0) p->dims[i] = k; + else p->dims[i] = atoi(spec[i]); + } + } + { + int nprocs, free, c[3], periods[3] = {1, 1, 1}; + int *rank_send = p->rank_send, *rank_recv = p->rank_recv; + + if (comm == MPI_COMM_NULL) { + if (p->comm != MPI_COMM_NULL) { + comm = p->comm; + free = 1; + } + else + comm = p3d_global_comm; + } + free = (p->comm != MPI_COMM_NULL); + + MPI_Comm_size(comm, &nprocs); + MPI_Dims_create(nprocs, 3, p->dims); + MPI_Cart_create(comm, 3, p->dims, periods, 1, &p->comm); + if (free) MPI_Comm_free(&comm); + + MPI_Comm_size(p->comm, &p->nprocs); + MPI_Comm_rank(p->comm, &p->rank); + MPI_Cart_coords(p->comm, p->rank, 3, p->coords); + + p->trans_mask = F_OOO; + if (p->coords[0] == p->dims[0] - 1) p->trans_mask |= F_EOO; + if (p->coords[0] == 0) p->trans_mask |= F_WOO; + if (p->coords[1] == p->dims[1] - 1) p->trans_mask |= F_ONO; + if (p->coords[1] == 0) p->trans_mask |= F_OSO; + if (p->coords[2] == p->dims[2] - 1) p->trans_mask |= F_OOT; + if (p->coords[2] == 0) p->trans_mask |= F_OOB; + + c[1] = p->coords[1]; c[2] = p->coords[2]; + c[0] = p->coords[0] + 1; MPI_Cart_rank(p->comm, c, &rank_send[0]); + c[0] = p->coords[0] - 1; MPI_Cart_rank(p->comm, c, &rank_send[1]); + c[0] = p->coords[0]; c[2] = p->coords[2]; + c[1] = p->coords[1] + 1; MPI_Cart_rank(p->comm, c, &rank_send[2]); + c[1] = p->coords[1] - 1; MPI_Cart_rank(p->comm, c, &rank_send[3]); + c[0] = p->coords[0]; c[1] = p->coords[1]; + c[2] = p->coords[2] + 1; MPI_Cart_rank(p->comm, c, &rank_send[4]); + c[2] = p->coords[2] - 1; MPI_Cart_rank(p->comm, c, &rank_send[5]); + rank_recv[0] = rank_send[1]; rank_recv[1] = rank_send[0]; + rank_recv[2] = rank_send[3]; rank_recv[3] = rank_send[2]; + rank_recv[4] = rank_send[5]; rank_recv[5] = rank_send[4]; + } + { + double *lb = (double*) &p->lb, *ub = (double*) &p->ub; + char *s; + int j; + for (i = 0; i < 3; i++) { + s = strchr(spec[i], '('); + if (s != NULL) { + if (p->coords[i] == 0) { + lb[i] = 0.0; + sscanf(++s, "%lf", &ub[i]); + } + else { + for (j = 1; j < p->coords[i]; j++) s = strchr(++s, '/'); + sscanf(++s, "%lf", &lb[i]); + if (p->coords[i] == p->dims[i] - 1) + ub[i] = 1.0; + else { + s = strchr(++s, '/'); + sscanf(++s, "%lf", &ub[i]); + } + } + } + else { + double d = 1.0 / p->dims[i]; + lb[i] = d * p->coords[i]; + ub[i] = d * (p->coords[i] + 1); + } + } +#ifndef P3D_QUIET + { + char line[P3D_LINEMAX]; + snprintf(line, sizeof(line), + "# %d: %d[%g,%g] %d[%g,%g] %d[%g,%g]\n", + p->rank, + p->coords[0], p->lb[0], p->ub[0], + p->coords[1], p->lb[1], p->ub[1], + p->coords[2], p->lb[2], p->ub[2]); + if (p->rank) + MPI_Send(line, sizeof(line), MPI_CHAR, 0, 0, p->comm); + else { + MPI_Status stat; + int rank; + fprintf(stderr, "# \"%s\" -> %d procs (%dx%dx%d)\n%s", + decomp, p->nprocs, p->dims[0], p->dims[1], p->dims[2],line); + for (rank = 1; rank < p->nprocs; rank++) { + MPI_Recv(line, sizeof(line), MPI_CHAR,rank,0,p->comm,&stat); + fprintf(stderr, line); + } + } + } +#endif + V3SuB(lb, v_eps); + V3AdD(v_eps, ub); + } + + return 0; +} + + +Cell p3d_new_cell(char *decomp, MPI_Datatype m_image, MPI_Comm comm) +{ + Cell cell = (Cell) malloc(sizeof(struct Cell_tag)); + Cell_private p = (Cell_private) malloc(sizeof(struct Cell_private_tag)); + + if (cell == NULL) p3d_abort(1); + if (p == NULL) p3d_abort(1); + cell->private = p; + + M3ASSIGN(1., 0., 0., 0., 1., 0., 0., 0., 1., cell->h); + + p->crust = 0.0; + p->n_max = 0; + p->point_begin = p->point_end = p->image_end = NULL; + + p->p_max = 0; + p->p_point_begin = p->p_point_end = NULL; + + p->f_realloc = 1; + + { + int i; + for (i = 0; i <= 6; i++) p->update[i] = NULL; + } + + MPI_Type_contiguous(sizeof(P3DAtom), MPI_CHAR, &p->M_POINT); + MPI_Type_commit(&p->M_POINT); + + if (m_image != MPI_DATATYPE_NULL) { + p->M_IMAGE = m_image; + } + else { + int blocklengths[2] = {offsetof(P3DAtom, r) + sizeof(V3), 1}; + MPI_Datatype types[2] = {MPI_CHAR, MPI_UB}; + MPI_Aint displacements[2] = {0, sizeof(P3DAtom)}; + MPI_Type_struct(2, blocklengths, displacements, types, &p->M_IMAGE); + MPI_Type_commit(&p->M_IMAGE); + } + + { + int i; + for (i = 0; i < 6; i++) p->req_send[i]=p->req_recv[i]=MPI_REQUEST_NULL; + } + + p->comm = MPI_COMM_NULL; + p3d_decompose(cell, decomp, comm); + + cell->reduced_coordinates = 0; + + cell->auxiliary = (Auxiliary) malloc(sizeof(struct Auxiliary_tag)); + cell->auxiliary->n_aux = 0; + + return cell; +} + + +int p3d_set_atoms(Cell cell, P3DAtom *point, int n) +{ + Cell_private p = cell->private; + + if (p->point_begin != point) { + p3d_realloc_cell(cell, n, 0); + memcpy(p->point_begin, point, sizeof(P3DAtom) * n); + } + p->image_end = p->point_end = p->point_begin + n; + + return (p->point_begin == point); +} + + +int p3d_cat_atoms(Cell cell, P3DAtom *point, int n) +{ + Cell_private p = cell->private; + int n_max = p->point_end - p->point_begin + n; + + p3d_realloc_cell(cell, n_max, 0); + + memcpy(p->point_end, point, sizeof(P3DAtom) * n); + p->point_end += n; + p->image_end = p->point_end; + + return n_max; +} + + +int p3d_remove_atom(Cell cell, P3DAtom *atom) +{ + Cell_private p = cell->private; + + if (atom - p->point_begin < 0 || atom - p->point_end >= 0) + return -1; + *atom = *(--p->point_end); + p->image_end = p->point_end; + + return p->point_end - p->point_begin; +} + + +int p3d_flags_boundary(V3 s, V3 lb, V3 ub) +{ + int flags = F_OOO; + if (s[0] < lb[0]) flags |= F_WOO; + if (s[0] >= ub[0]) flags |= F_EOO; + if (s[1] < lb[1]) flags |= F_OSO; + if (s[1] >= ub[1]) flags |= F_ONO; + if (s[2] < lb[2]) flags |= F_OOB; + if (s[2] >= ub[2]) flags |= F_OOT; + return flags; +} + + +int p3d_flags_boundary2(V3 s, V3 lb, V3 ub) +{ + int flags = F_OOO; + + if (s[0] < 0.0) s[0] += 1.0; + else if (s[0] >= 1.0) s[0] -= 1.0; + if (s[1] < 0.0) s[1] += 1.0; + else if (s[1] >= 1.0) s[1] -= 1.0; + if (s[2] < 0.0) s[2] += 1.0; + else if (s[2] >= 1.0) s[2] -= 1.0; + + if (s[0] < lb[0]) flags |= F_WOO; + if (s[0] >= ub[0]) flags |= F_EOO; + if (s[1] < lb[1]) flags |= F_OSO; + if (s[1] >= ub[1]) flags |= F_ONO; + if (s[2] < lb[2]) flags |= F_OOB; + if (s[2] >= ub[2]) flags |= F_OOT; + return flags; +} + + +int p3d_reset_cell_c(Cell cell, double crust) +{ + Cell_private p = cell->private; + P3DAtom *pnt; + M3 h_inv; + int dir0, n_max, p_max, n_send_total = 0; + + p->p_point_end = p->p_point_begin; + for (dir0 = 0; dir0 < 6; dir0++) { + if (p->req_recv[dir0] != MPI_REQUEST_NULL) + MPI_Request_free(&p->req_recv[dir0]); + if (p->req_send[dir0] != MPI_REQUEST_NULL) + MPI_Request_free(&p->req_send[dir0]); + } + + M3inv(cell->h, h_inv); + + if (cell->reduced_coordinates) { + for (pnt = p->point_begin; pnt < p->point_end; pnt++) { + pnt->iw = p3d_flags_boundary(pnt->r, p->lb, p->ub); + } + } + else { + for (pnt = p->point_begin; pnt < p->point_end; pnt++) { + V3 s; + V3mM3(pnt->r, h_inv, s); + pnt->iw = p3d_flags_boundary(s, p->lb, p->ub); + } + } + + for (dir0 = 0; dir0 < 6; dir0++) { + int n_send, n_recv, dir_flags; + P3DAtom *point_send; + MPI_Status status; + P3DAtom temp; + + dir_flags = direction_flags[dir0]; + + n_send = 0; + for (pnt = p->point_begin; pnt < p->point_end; pnt++) + if (pnt->iw & dir_flags) n_send++; + n_send_total += n_send; + MPI_Sendrecv( &n_send, 1, MPI_INT, p->rank_send[dir0], dir0, + &n_recv, 1, MPI_INT, p->rank_recv[dir0], dir0, + p->comm, &status); + + n_max = (p->point_end - p->point_begin) + n_recv; + p3d_realloc_cell(cell, n_max, 0); + + point_send = p->point_begin + p->n_max; + for (pnt = p->point_begin; pnt < p->point_end; pnt++) { + if (pnt->iw & dir_flags) { + temp = *pnt; + *pnt-- = *--p->point_end; + *--point_send = temp; + } + } + if (dir_flags & p->trans_mask) { /* PBC */ + int idx = dir0 / 2; + V3 trans; + V3ZERO(trans); + trans[idx] = 1.0; + if (!cell->reduced_coordinates) { + V3 tmp; + V3EQV(trans, tmp); + V3mM3(tmp, cell->h, trans); + } + if (dir0 % 2 == 0) { + for (pnt = point_send; pnt < p->point_begin + p->n_max; pnt++) + V3SuB(pnt->r, trans); + } + else { + for (pnt = point_send; pnt < p->point_begin + p->n_max; pnt++) + V3AdD(trans, pnt->r); + } + } + MPI_Sendrecv(point_send, n_send, p->M_POINT, p->rank_send[dir0], dir0, + p->point_end, n_recv, p->M_POINT, p->rank_recv[dir0], dir0, + p->comm, &status); + + pnt = p->point_end; + p->point_end += n_recv; + if (cell->reduced_coordinates) { + while (pnt < p->point_end) { + pnt->iw = p3d_flags_boundary(pnt->r, p->lb, p->ub); + pnt++; + } + } + else { + while (pnt < p->point_end) { + V3 s; + V3mM3(pnt->r, h_inv, s); + pnt->iw = p3d_flags_boundary(s, p->lb, p->ub); + pnt++; + } + } + } + + p->image_end = p->point_end; + if ((p->crust = crust)) { + V3 lb_c, ub_c, c; + P3DAtom *image_end, **p_point; + int n_send[6], n_recv[6], max_nn_send = 0; + + V3ASSIGN(h_inv[0][0], h_inv[1][1], h_inv[2][2], c); + V3MuL(crust, c); + V3ADD(p->lb, c, lb_c); V3AdD(v_eps, lb_c); V3AdD(v_eps, lb_c); + V3SUB(p->ub, c, ub_c); V3SuB(ub_c, v_eps); V3SuB(ub_c, v_eps); + + if (cell->reduced_coordinates) { + for (pnt = p->point_begin; pnt < p->point_end; pnt++) { + pnt->iw = p3d_flags_boundary(pnt->r, lb_c, ub_c); + } + } + else { + for (pnt = p->point_begin; pnt < p->point_end; pnt++) { + V3 s; + V3mM3(pnt->r, h_inv, s); + pnt->iw = p3d_flags_boundary(s, lb_c, ub_c); + } + } + + for (dir0 = 0; dir0 < 6; dir0 += 2) { + P3DAtom *point_send0, *point_send1; + V3 trans; + MPI_Request req_send[2], req_recv[2]; + MPI_Status status[2]; + int nn_send, nn_recv; + int dir_flags0, dir_flags1, dir1 = dir0 + 1, idx = dir0 / 2; + + /* count */ + dir_flags0 = direction_flags[dir0]; + dir_flags1 = direction_flags[dir1]; + n_send[dir0] = n_send[dir1] = 0; + for (pnt = p->point_begin; pnt < p->image_end; pnt++) { + if (pnt->iw & dir_flags0) n_send[dir0]++; + if (pnt->iw & dir_flags1) n_send[dir1]++; + } + nn_send = n_send[dir0] + n_send[dir1]; + if (nn_send > max_nn_send) max_nn_send = nn_send; + MPI_Sendrecv( &n_send[dir0], 1, MPI_INT, p->rank_send[dir0], dir0, + &n_recv[dir0], 1, MPI_INT, p->rank_recv[dir0], dir0, + p->comm, status); + MPI_Sendrecv( &n_send[dir1], 1, MPI_INT, p->rank_send[dir1], dir1, + &n_recv[dir1], 1, MPI_INT, p->rank_recv[dir1], dir1, + p->comm, status); + nn_recv = n_recv[dir0] + n_recv[dir1]; + n_max = p->image_end - p->point_begin + max_nn_send + nn_recv; + p_max = p->p_point_end - p->p_point_begin + nn_send; + p3d_realloc_cell(cell, n_max, p_max); + + /* sendrecv */ + image_end = p->image_end; + if (n_recv[dir0] > 0) { + MPI_Irecv(image_end, n_recv[dir0], p->M_POINT, + p->rank_recv[dir0], dir0, p->comm, &req_recv[0]); + image_end += n_recv[dir0]; + } + else + req_recv[0] = MPI_REQUEST_NULL; + if (n_recv[dir1] > 0) { + MPI_Irecv(image_end, n_recv[dir1], p->M_POINT, + p->rank_recv[dir1], dir1, p->comm, &req_recv[1]); + image_end += n_recv[dir1]; + } + else + req_recv[1] = MPI_REQUEST_NULL; + + V3ZERO(trans); + trans[idx] = 1.0; + if (!cell->reduced_coordinates) { + V3 tmp; + V3EQV(trans, tmp); + V3mM3(tmp, cell->h, trans); + } + + p_point = p->p_point_end; + p->p_point_end += nn_send; + + point_send0 = p->point_begin + p->n_max; + if (n_send[dir0] > 0) { + for (pnt = p->point_begin; pnt < p->image_end; pnt++) { + if (pnt->iw & dir_flags0) { + *p_point++ = pnt; + *--point_send0 = *pnt; + } + } + if (dir_flags0 & p->trans_mask) { + for (pnt=point_send0; pntpoint_begin+p->n_max; pnt++) + V3SuB(pnt->r, trans); + } + MPI_Isend(point_send0, n_send[dir0], p->M_POINT, + p->rank_send[dir0], dir0, p->comm, &req_send[0]); + } + else + req_send[0] = MPI_REQUEST_NULL; + + point_send1 = point_send0; + if (n_send[dir1] > 0) { + for (pnt = p->point_begin; pnt < p->image_end; pnt++) { + if (pnt->iw & dir_flags1) { + *p_point++ = pnt; + *--point_send1 = *pnt; + } + } + if (dir_flags1 & p->trans_mask) { + for (pnt = point_send1; pnt < point_send0; pnt++) + V3AdD(trans, pnt->r); + } + MPI_Isend(point_send1, n_send[dir1], p->M_POINT, + p->rank_send[dir1], dir1, p->comm, &req_send[1]); + } + else + req_send[1] = MPI_REQUEST_NULL; + + MPI_Waitall(2, req_recv, status); + if (cell->reduced_coordinates) { + for (pnt = p->image_end; pnt < image_end; pnt++) { + pnt->iw = p3d_flags_boundary(pnt->r, lb_c, ub_c); + } + } + else { + for (pnt = p->image_end; pnt < image_end; pnt++) { + V3 s; + V3mM3(pnt->r, h_inv, s); + pnt->iw = p3d_flags_boundary(s, lb_c, ub_c); + } + } + p->image_end = image_end; + MPI_Waitall(2, req_send, status); + } + + /* init */ + image_end = p->point_end; + p_point = p->p_point_begin; + for (dir0 = 0; dir0 < 6; dir0 += 2) { + P3DAtom *point_send = p->point_begin + p->n_max; + int dir1 = dir0 + 1; + + if (n_recv[dir0] > 0) { + MPI_Recv_init(image_end, n_recv[dir0], p->M_IMAGE, + p->rank_recv[dir0], dir0, p->comm, &p->req_recv[dir0]); + image_end += n_recv[dir0]; + } + if (n_recv[dir1] > 0) { + MPI_Recv_init(image_end, n_recv[dir1], p->M_IMAGE, + p->rank_recv[dir1], dir1, p->comm, &p->req_recv[dir1]); + image_end += n_recv[dir1]; + } + + p->update[dir0] = p_point; + if (n_send[dir0] > 0) { + p_point += n_send[dir0]; + point_send -= n_send[dir0]; + MPI_Send_init(point_send, n_send[dir0], p->M_IMAGE, + p->rank_send[dir0], dir0, p->comm, &p->req_send[dir0]); + } + + p->update[dir1] = p_point; + if (n_send[dir1] > 0) { + p_point += n_send[dir1]; + point_send -= n_send[dir1]; + MPI_Send_init(point_send, n_send[dir1], p->M_IMAGE, + p->rank_send[dir1], dir1, p->comm, &p->req_send[dir1]); + } + + } + p->update[6] = p_point; + } + + p->f_realloc = 0; + + return n_send_total; +} + + +int p3d_update_cell(Cell cell) +{ + Cell_private p = cell->private; + P3DAtom *pnt, *point_send0, *point_send1, **p_point; + V3 trans; + MPI_Status status[2]; + int dir0, dir1, dir2; + + if (p->f_realloc) p3d_abort(-1); + + for (dir0 = 0; dir0 < 6; dir0 += 2) { + int idx = dir0 / 2; + dir1 = dir0 + 1; + + if (p->req_recv[dir0]!=MPI_REQUEST_NULL) MPI_Start(&p->req_recv[dir0]); + if (p->req_recv[dir1]!=MPI_REQUEST_NULL) MPI_Start(&p->req_recv[dir1]); + + V3ZERO(trans); + trans[idx] = 1.0; + if (!cell->reduced_coordinates) { + V3 tmp; + V3EQV(trans, tmp); + V3mM3(tmp, cell->h, trans); + } + + point_send0 = p->point_begin + p->n_max; + if (p->req_send[dir0] != MPI_REQUEST_NULL) { + for (p_point=p->update[dir0]; p_pointupdate[dir1]; p_point++) + *--point_send0 = **p_point; + if (direction_flags[dir0] & p->trans_mask) { + for (pnt = point_send0; pnt < p->point_begin+p->n_max; pnt++) + V3SuB(pnt->r, trans); + } + MPI_Start(&p->req_send[dir0]); + } + + point_send1 = point_send0; + if (p->req_send[dir1] != MPI_REQUEST_NULL) { + dir2 = dir1 + 1; + for (p_point=p->update[dir1]; p_pointupdate[dir2]; p_point++) + *--point_send1 = **p_point; + if (direction_flags[dir1] & p->trans_mask) { + for (pnt = point_send1; pnt < point_send0; pnt++) + V3AdD(trans, pnt->r); + } + MPI_Start(&p->req_send[dir1]); + } + + MPI_Waitall(2, &p->req_recv[dir0], status); + MPI_Waitall(2, &p->req_send[dir0], status); + } + + return 0; +} + + +/* Comm */ +int p3d_bcast(Cell cell, void *buff, int count, MPI_Datatype datatype, int root) +{ + return MPI_Bcast(buff, count, datatype, root, cell->private->comm); +} + +int p3d_reduce(Cell cell, void *sbuf, void *rbuf, int count, + MPI_Datatype datatype, MPI_Op op) +{ + return MPI_Allreduce(sbuf, rbuf, count, datatype, op, cell->private->comm); +} + + +/* I/O */ + +int p3d_fflush(FILE *fp) +{ + int ret = 0; + + if ((p3d_global_rank_fprintf==2) || + (p3d_global_rank_fprintf==0 && p3d_global_rank==0) || + (p3d_global_rank_fprintf==1 && p3d_global_rank==p3d_global_nprocs-1)) { + ret = fflush(fp); + } + + return ret; +} + + +int p3d_fprintf(FILE *fp, const char *format, ...) +{ + int ret; + + ret=(p3d_global_rank_fprintf==2)? fprintf(fp, "[%d] ", p3d_global_rank) : 0; + if ((p3d_global_rank_fprintf==2) || + (p3d_global_rank_fprintf==0 && p3d_global_rank==0) || + (p3d_global_rank_fprintf==1 && p3d_global_rank==p3d_global_nprocs-1)) { + char *s; + for (s = (char*)format; s; s++) { + if (*s == '%' && *(s+1) != '%') + break; + } + if (*s) { + va_list va; + va_start(va, format); + ret += vfprintf(fp, format, va); + va_end(va); + } + else + ret += fprintf(fp, format); + } + + return ret; +} + + +static char *fgets2(char *s, int size, FILE *stream) +{ + do { + if (NULL == fgets(s, size, stream)) return NULL; + } while ('#' == *s || '\n' == *s); + return s; +} + + +static int GZIP_MAGIC[] = {0x1f, 0x8b}; +static int BZIP2_MAGIC[] = {'B','Z','h'}; +static int PMDS_MAGIC[] = {'<','M','D','S','t','e','n','c','i','l','A'}; + +struct filter_t { + int num; + int *magic; + char *command; + char *option; +}; + +static struct filter_t filters[] = { + { sizeof(GZIP_MAGIC) /sizeof(int), GZIP_MAGIC, "gzip", "-cd" }, + { sizeof(BZIP2_MAGIC)/sizeof(int), BZIP2_MAGIC, "bzip2", "-cd" }, + { sizeof(PMDS_MAGIC) /sizeof(int), PMDS_MAGIC, "pmds_cat", "-v" }, + { 0, NULL, NULL, NULL } +}; + + +static FILE *fopen2(const char *path, const char *mode) +{ + FILE *fp = fopen(path, mode); + + if (fp && *mode == 'r') { + struct filter_t *f; + + for (f = filters; f->num; f++) { + int i; + + for (i = 0; i < f->num; i++) { + if (f->magic[i] != fgetc(fp)) + break; + } + if (i == f->num) { + int pipefds[2]; + pid_t pid; + + fclose(fp); + if (pipe(pipefds) == -1 || (pid = fork()) == -1) + return NULL; + + if (pid == 0) { + if (fork() == 0) { + char *argv[4]; + close(1); + dup(pipefds[1]); + close(pipefds[1]); + close(pipefds[0]); + argv[0] = f->command; + argv[1] = f->option; + argv[2] = (char*)path; + argv[3] = NULL; + execvp(f->command, argv); + } + _exit(0); + } + else { + wait(NULL); + close(pipefds[1]); + fp = fdopen(pipefds[0], mode); + return fp; + } + } + else + rewind(fp); + } + } + + return fp; +} + +#ifndef USE_ZLIB + + typedef FILE *P3DFileP; +# define P3DFopen(path, mode) ((P3DFileP)fopen2(path, mode)) +# define P3DFclose(fp) fclose(fp) +# define P3DFputs(s, fp) fputs(s, fp) +# define P3DFgets(s, n, fp) fgets(s, n, fp) +# define P3DFgets2(s, n, fp) fgets2(s, n, fp) + +#else + +# include "zlib.h" + typedef struct File_tag { + void *fp; + int compress; + } *P3DFileP; +# define P3DFputs(s, fp) (((fp)->compress) ? gzputs((gzFile)(fp)->fp, s)\ + : fputs(s, (FILE*)(fp)->fp)) +# define P3DFgets(s, n, fp) (((fp)->compress) ? gzgets((gzFile)(fp)->fp,s,n)\ + : fgets(s, n, (FILE*)(fp)->fp)) + + static int chknamegz(const char *path) + { + int len = strlen(path); + return (len > 2 && path[len-3] == '.' + && path[len-2] == 'g' && path[len-1] == 'z'); + } + + static P3DFileP P3DFopen(const char *path, const char *mode) + { + P3DFileP fp = (P3DFileP) malloc(sizeof(struct File_tag)); + + if (fp) { + if (*mode == 'r') { + fp->compress = 0; + fp->fp = (P3DFileP) fopen2(path, mode); + } + else if (chknamegz(path)) { + fp->compress = 1; + fp->fp = (P3DFileP) gzopen(path, mode); + } + else { + fp->compress = 0; + fp->fp = (P3DFileP) fopen(path, mode); + } + } + return fp; + } + + int P3DFclose(P3DFileP fp) + { + int value = EOF; + + if (fp) { + value = (fp->compress) ? + gzclose((gzFile)(fp->fp)) : fclose((FILE*)(fp->fp)); + free(fp); + } + + return value; + } + + static char *P3DFgets2(char *s, int n, P3DFileP fp) + { + if (fp->compress) { + do { + if (NULL == gzgets((gzFile)fp->fp, s, n)) return NULL; + } while ('#' == *s || '\n' == *s); + return s; + } + else + return fgets2(s, n, (FILE*)fp->fp); + + } +#endif + +static int chkpathname(char *path) +{ + int i, divided = 0; + + for (i=0; iprivate->rank); + break; + } + } + + return (newpath[0] != '\0') ? newpath : path; +} + + + + +enum p3d_cfg_tags { + CHG_TAG_NOMATCH, + CHG_TAG_NUM, CHG_TAG_A, CHG_TAG_R, + CHG_TAG_H0_11, CHG_TAG_H0_12, CHG_TAG_H0_13, + CHG_TAG_H0_21, CHG_TAG_H0_22, CHG_TAG_H0_23, + CHG_TAG_H0_31, CHG_TAG_H0_32, CHG_TAG_H0_33, + CHG_TAG_Tr_11, CHG_TAG_Tr_12, CHG_TAG_Tr_13, + CHG_TAG_Tr_21, CHG_TAG_Tr_22, CHG_TAG_Tr_23, + CHG_TAG_Tr_31, CHG_TAG_Tr_32, CHG_TAG_Tr_33, + CHG_TAG_Et_11, CHG_TAG_Et_12, CHG_TAG_Et_13, + CHG_TAG_Et_21, CHG_TAG_Et_22, CHG_TAG_Et_23, + CHG_TAG_Et_31, CHG_TAG_Et_32, CHG_TAG_Et_33, + CHG_TAG_NO_V, CHG_TAG_ENTRY, CHG_TAG_AUX +}; + +typedef struct { + enum p3d_cfg_tags id; + char *name; + char *comment; +} ChgTag; + +static ChgTag CHG_TAGS[] = { + {CHG_TAG_NUM, "Number of particles =", + "(required) this must be the first line"}, + {CHG_TAG_A, "A =", + "(optional) basic length-scale: default A = 1.0"}, + {CHG_TAG_R, "R =", + "(optional) basic rate-scale: default R = 1.0 [ns^-1]"}, + {CHG_TAG_H0_11, "H0(1,1) =", NULL}, + {CHG_TAG_H0_12, "H0(1,2) =", NULL}, + {CHG_TAG_H0_13, "H0(1,3) =", + "(required) this is the supercell's 1st edge, in A"}, + {CHG_TAG_H0_21, "H0(2,1) =", NULL}, + {CHG_TAG_H0_22, "H0(2,2) =", NULL}, + {CHG_TAG_H0_23, "H0(2,3) =", + "(required) this is the supercell's 2nd edge, in A"}, + {CHG_TAG_H0_31, "H0(3,1) =", NULL}, + {CHG_TAG_H0_32, "H0(3,2) =", NULL}, + {CHG_TAG_H0_33, "H0(3,3) =", + "(required) this is the supercell's 3rd edge, in A"}, + {CHG_TAG_Tr_11, "Transform(1,1) =", NULL}, + {CHG_TAG_Tr_12, "Transform(1,2) =", NULL}, + {CHG_TAG_Tr_13, "Transform(1,3) =", NULL}, + {CHG_TAG_Tr_21, "Transform(2,1) =", NULL}, + {CHG_TAG_Tr_22, "Transform(2,2) =", NULL}, + {CHG_TAG_Tr_23, "Transform(2,3) =", NULL}, + {CHG_TAG_Tr_31, "Transform(3,1) =", NULL}, + {CHG_TAG_Tr_32, "Transform(3,2) =", NULL}, + {CHG_TAG_Tr_33, "Transform(3,3) =", + "(optional) apply additional transformation on H0:" + " H = H0 * Transform;\n# default = Identity matrix."}, + {CHG_TAG_Et_11, "eta(1,1) =", NULL}, + {CHG_TAG_Et_12, "eta(1,2) =", NULL}, + {CHG_TAG_Et_13, "eta(1,3) =", NULL}, + {CHG_TAG_Et_21, "eta(2,1) =", NULL}, + {CHG_TAG_Et_22, "eta(2,2) =", NULL}, + {CHG_TAG_Et_23, "eta(2,3) =", NULL}, + {CHG_TAG_Et_31, "eta(3,1) =", NULL}, + {CHG_TAG_Et_32, "eta(3,2) =", NULL}, + {CHG_TAG_Et_33, "eta(3,3) =", + "(optional) apply additional Lagrangian strain on H0:" + "\n# H = H0 * sqrt(Identity_matrix + 2 * eta);" + "\n# default = zero matrix."}, + {CHG_TAG_NO_V, ".NO_VELOCITY.", NULL}, + {CHG_TAG_ENTRY, "entry_count =", NULL}, + {CHG_TAG_AUX, "auxiliary[", NULL}, +}; +#define N_CHG_TAGS sizeof(CHG_TAGS)/sizeof(ChgTag) + + +static int chk_tag(char *line, char **s) +{ + ChgTag *ct; + for (ct = CHG_TAGS; ct < CHG_TAGS + N_CHG_TAGS; ct++) { + if ((*s = strstr(line, ct->name))) { + *s += strlen(ct->name); + return ct->id; + } + } + return CHG_TAG_NOMATCH; +} + +#define SCANFMT3 "%lf%lf%lf" +#define AUXSCANFMT "%lf%lf%lf%lf%lf%lf%lf%lf%lf%lf%lf%lf%lf%lf%lf%lf" +#define AUX16(pnt) (pnt)->aux, (pnt)->aux+1, (pnt)->aux+2, (pnt)->aux+3,\ + (pnt)->aux+4, (pnt)->aux+5, (pnt)->aux+6, (pnt)->aux+7,\ + (pnt)->aux+8, (pnt)->aux+9, (pnt)->aux+10,(pnt)->aux+11,\ + (pnt)->aux+12,(pnt)->aux+13,(pnt)->aux+14,(pnt)->aux+15\ + +#define ulength_IN_A 1.0 +#define utime_IN_NS 1.0 +#define umass_IN_AMU 1.0 + + +static int read_config_header(Cell cell, P3DFileP fp, char *line, int size, + double *r, int *entry_count, int *no_velocity) +{ + int n; + double a = 1.0; + + *r = 1.0; + *entry_count = *no_velocity = 0; + + while (P3DFgets2(line, size, fp)) { + char *s; + int k; + chk_tag(line, &s); + switch (chk_tag(line, &s)) { + case CHG_TAG_NOMATCH: + if (a != 1.0) { + a /= ulength_IN_A; + M3MultiplY(a, cell->h); + } + if (*r != 1.0) { + *r *= utime_IN_NS; + } + return n; + break; + case CHG_TAG_NUM: + sscanf(s, "%d", &n); + break; + case CHG_TAG_A: + sscanf(s, "%lf", &a); + break; + case CHG_TAG_R: + sscanf(s, "%lf", r); + break; + case CHG_TAG_H0_11: sscanf(s, "%lf", &cell->h[0][0]); break; + case CHG_TAG_H0_12: sscanf(s, "%lf", &cell->h[0][1]); break; + case CHG_TAG_H0_13: sscanf(s, "%lf", &cell->h[0][2]); break; + case CHG_TAG_H0_21: sscanf(s, "%lf", &cell->h[1][0]); break; + case CHG_TAG_H0_22: sscanf(s, "%lf", &cell->h[1][1]); break; + case CHG_TAG_H0_23: sscanf(s, "%lf", &cell->h[1][2]); break; + case CHG_TAG_H0_31: sscanf(s, "%lf", &cell->h[2][0]); break; + case CHG_TAG_H0_32: sscanf(s, "%lf", &cell->h[2][1]); break; + case CHG_TAG_H0_33: sscanf(s, "%lf", &cell->h[2][2]); break; + case CHG_TAG_NO_V: + *no_velocity = 1; + break; + case CHG_TAG_ENTRY: + sscanf(s, "%d" , entry_count); + cell->auxiliary->n_aux = *entry_count; + if (*no_velocity) cell->auxiliary->n_aux -= 3; + break; + case CHG_TAG_AUX: + if (sscanf(s, "%d", &k) == 1 && k < CONFIG_MAX_AUXILIARY) { + char *name, *unit; + if (k >= cell->auxiliary->n_aux) + cell->auxiliary->n_aux = k + 1; + (name = cell->auxiliary->name[k])[0] = 0; + (unit = cell->auxiliary->unit[k])[0] = 0; + if ((s = strchr(s, '='))) { + s++; + while (*s && isspace(*s)) s++; + if (*s) { + int i; + sscanf(s, "%[^[]", name); + for (i = strlen(name) - 1; i >= 0; i--) { + if (!isspace(name[i])) + break; + else + name[i] = 0; + } + if ((s = strchr(s, '['))) { + strncpy(unit, s, P3D_LINEMAX); + for (i = strlen(unit) - 1; i >= 0; i--) { + if (!isspace(unit[i])) + break; + else + unit[i] = 0; + } + } + } + } + } + break; + default: + break; + } + } + + return -1; +} + + +static int read_config_body(Cell cell, P3DFileP fp, char *line, int size, + P3DAtom *point, int max, int *remain, double r, + int entry_count, int no_velocity) +{ + static char symbol[sizeof(int)] = " "; + P3DAtom *point_end; + int i, n = (*remain < max) ? *remain : max; + *remain -= n; + + if (!entry_count) { /* Standard cfg */ + P3DAtom *pnt = point; + sscanf(line, "%lf%s%lf%lf%lf%lf%lf%lf", + &pnt->m, &symbol[1], V3e(pnt->r), V3e(pnt->v)); + strncpy(pnt->sym, &symbol[strlen(symbol)-2], sizeof(int)); + pnt++; + + for (i = 1; i < n; i++) { + P3DFgets2(line, size, fp); + sscanf(line, "%lf%s%lf%lf%lf%lf%lf%lf", + &pnt->m, &symbol[1], V3e(pnt->r), V3e(pnt->v)); + strncpy(pnt->sym, &symbol[strlen(symbol)-2],sizeof(int)); + pnt++; + } + point_end = pnt; + } + else { /* Extended cfg */ + static char *sym; + static double mass; + P3DAtom *pnt = point; + if (no_velocity) { + if (sscanf(line,SCANFMT3 AUXSCANFMT,V3e(pnt->r),AUX16(pnt))==1) { + mass = pnt->r[0]; + P3DFgets2(line, size, fp); + sscanf(line, "%s", &symbol[1]); + sym = &symbol[strlen(symbol) - 2]; + P3DFgets2(line, size, fp); + sscanf(line,SCANFMT3 AUXSCANFMT, V3e(pnt->r), AUX16(pnt)); + } + pnt->m = mass; + strncpy(pnt->sym, sym, sizeof(int)); + V3ZERO(pnt->v); + pnt++; + + for (i = 1; i < n; i++) { + P3DFgets2(line, size, fp); + if (sscanf(line,SCANFMT3 AUXSCANFMT,V3e(pnt->r),AUX16(pnt))==1){ + mass = pnt->r[0]; + P3DFgets2(line, size, fp); + sscanf(line, "%s", &symbol[1]); + sym = &symbol[strlen(symbol) - 2]; + P3DFgets2(line, size, fp); + sscanf(line, SCANFMT3 AUXSCANFMT, V3e(pnt->r), AUX16(pnt)); + } + pnt->m = mass; + strncpy(pnt->sym, sym, sizeof(int)); + V3ZERO(pnt->v); + pnt++; + } + + } + else { /* with velocity */ + if (sscanf(line, "%lf%lf%lf%lf%lf%lf"AUXSCANFMT, + V3e(pnt->r), V3e(pnt->v), AUX16(pnt)) == 1) { + mass = pnt->r[0]; + P3DFgets2(line, size, fp); + sscanf(line, "%s", &symbol[1]); + sym = &symbol[strlen(symbol) - 2]; + P3DFgets2(line, size, fp); + sscanf(line, "%lf%lf%lf%lf%lf%lf"AUXSCANFMT, + V3e(pnt->r), V3e(pnt->v), AUX16(pnt)); + } + pnt->m = mass; + strncpy(pnt->sym, sym, sizeof(int)); + pnt++; + + for (i = 1; i < n; i++) { + P3DFgets2(line, size, fp); + if (sscanf(line, "%lf%lf%lf%lf%lf%lf"AUXSCANFMT, + V3e(pnt->r), V3e(pnt->v), AUX16(pnt))==1) { + mass = pnt->r[0]; + P3DFgets2(line, size, fp); + sscanf(line, "%s", &symbol[1]); + sym = &symbol[strlen(symbol) - 2]; + P3DFgets2(line, size, fp); + sscanf(line, "%lf%lf%lf%lf%lf%lf"AUXSCANFMT, + V3e(pnt->r), V3e(pnt->v), AUX16(pnt)); + } + pnt->m = mass; + strncpy(pnt->sym, sym, sizeof(int)); + pnt++; + } + } + point_end = pnt; + } + + + if (!entry_count || !no_velocity) { + P3DAtom *pnt; + if (r != 1.0) { + for (pnt = point; pnt < point_end; pnt++) { + V3MuL(r, pnt->v); + } + } + if (!cell->reduced_coordinates) { + V3 sv; + for (pnt = point; pnt < point_end; pnt++) { + V3EQV(pnt->v, sv); + V3mM3(sv, cell->h, pnt->v); + } + } + } + + if (!cell->reduced_coordinates) { + P3DAtom *pnt; + V3 sr; + for (pnt = point; pnt < point_end; pnt++) { + V3EQV(pnt->r, sr); + V3mM3(sr, cell->h, pnt->r); + } + } + + if (umass_IN_AMU != 1.0) { + P3DAtom *pnt; + for (pnt = point; pnt < point_end; pnt++) { + pnt->m /= umass_IN_AMU; + } + } + + if (*remain) P3DFgets2(line, size, fp); + + return point_end - point; +} + + +static int read_config_body_filter(Cell cell, P3DFileP fp, char *line, int size, + P3DAtom *point, int max, int *remain, double r, + int entry_count, int no_velocity) +{ + static char symbol[sizeof(int)] = " "; + P3DAtom *start = point, *end = start + max, *pnt = start; + P3DAtom dummy, *dp = &dummy; + V3 lb, ub; + int i; + + for (i = 0; i < 3; i++) { + lb[i] = ((double)cell->private->coords[i] )/ cell->private->dims[i]; + ub[i] = ((double)cell->private->coords[i] + 1)/ cell->private->dims[i]; + } + + if (!entry_count) { /* Standard cfg */ + sscanf(line, "%lf%s%lf%lf%lf%lf%lf%lf", + &dp->m, &symbol[1], V3e(dp->r), V3e(dp->v)); + if (!p3d_flags_boundary2(dp->r, lb, ub)) { + if (pnt == end) + goto scale; + strncpy(dp->sym, &symbol[strlen(symbol)-2], sizeof(int)); + *pnt++ = *dp; + } + + for (i = 1; i < *remain; i++) { + P3DFgets2(line, size, fp); + sscanf(line, "%lf%s%lf%lf%lf%lf%lf%lf", + &dp->m, &symbol[1], V3e(dp->r), V3e(dp->v)); + if (!p3d_flags_boundary2(dp->r, lb, ub)) { + if (pnt == end) { + *remain -= i; + goto scale; + } + strncpy(dp->sym, &symbol[strlen(symbol)-2], sizeof(int)); + *pnt++ = *dp; + } + } + } + else { /* Extended cfg */ + static char *sym; + static double mass; + if (no_velocity) { + V3ZERO(dp->v); + if (sscanf(line,"%lf%lf%lf"AUXSCANFMT,V3e(dp->r),AUX16(dp)) == 1) { + mass = dp->r[0]; + P3DFgets2(line, size, fp); + sscanf(line, "%s", &symbol[1]); + sym = &symbol[strlen(symbol) - 2]; + P3DFgets2(line, size, fp); + sscanf(line,"%lf%lf%lf"AUXSCANFMT,V3e(dp->r),AUX16(dp)); + } + if (!p3d_flags_boundary2(dp->r, lb, ub)) { + if (pnt == end) + goto scale; + dp->m = mass; + strncpy(dp->sym, sym, sizeof(int)); + *pnt++ = *dp; + } + + for (i = 1; i < *remain; i++) { + P3DFgets2(line, size, fp); + if (sscanf(line,"%lf%lf%lf"AUXSCANFMT,V3e(dp->r),AUX16(dp))==1){ + mass = dp->r[0]; + P3DFgets2(line, size, fp); + sscanf(line, "%s", &symbol[1]); + sym = &symbol[strlen(symbol) - 2]; + P3DFgets2(line, size, fp); + sscanf(line, "%lf%lf%lf"AUXSCANFMT,V3e(dp->r),AUX16(dp)); + } + if (!p3d_flags_boundary2(dp->r, lb, ub)) { + if (pnt == end) { + *remain -= i; + goto scale; + } + dp->m = mass; + strncpy(dp->sym, sym, sizeof(int)); + *pnt++ = *dp; + } + } + } + else { /* with velocity */ + if (sscanf(line, "%lf%lf%lf%lf%lf%lf"AUXSCANFMT, + V3e(dp->r), V3e(dp->v), AUX16(dp)) == 1) { + mass = dp->r[0]; + P3DFgets2(line, size, fp); + sscanf(line, "%s", &symbol[1]); + sym = &symbol[strlen(symbol) - 2]; + P3DFgets2(line, size, fp); + sscanf(line, "%lf%lf%lf%lf%lf%lf"AUXSCANFMT, + V3e(dp->r), V3e(dp->v), AUX16(dp)); + } + if (!p3d_flags_boundary2(dp->r, lb, ub)) { + if (pnt == end) + goto scale; + dp->m = mass; + strncpy(dp->sym, sym, sizeof(int)); + *pnt++ = *dp; + } + + for (i = 1; i < *remain; i++) { + P3DFgets2(line, size, fp); + if (sscanf(line, "%lf%lf%lf%lf%lf%lf"AUXSCANFMT, + V3e(dp->r), V3e(dp->v), AUX16(dp))==1) { + mass = dp->r[0]; + P3DFgets2(line, size, fp); + sscanf(line, "%s", &symbol[1]); + sym = &symbol[strlen(symbol) - 2]; + P3DFgets2(line, size, fp); + sscanf(line, "%lf%lf%lf%lf%lf%lf"AUXSCANFMT, + V3e(dp->r), V3e(dp->v), AUX16(dp)); + } + if (!p3d_flags_boundary2(dp->r, lb, ub)) { + if (pnt == end) { + *remain -= i; + goto scale; + } + dp->m = mass; + strncpy(dp->sym, sym, sizeof(int)); + *pnt++ = *dp; + } + } + } + } + *remain = 0; + end = pnt; + +scale: + if (!entry_count || !no_velocity) { + if (r != 1.0) { + for (pnt = start; pnt < end; pnt++) { + V3MuL(r, pnt->v); + } + } + if (!cell->reduced_coordinates) { + V3 sv; + for (pnt = start; pnt < end; pnt++) { + V3EQV(pnt->v, sv); + V3mM3(sv, cell->h, pnt->v); + } + } + } + + if (!cell->reduced_coordinates) { + V3 sr; + for (pnt = start; pnt < end; pnt++) { + V3EQV(pnt->r, sr); + V3mM3(sr, cell->h, pnt->r); + } + } + + if (umass_IN_AMU != 1.0) { + for (pnt = start; pnt < end; pnt++) { + pnt->m /= umass_IN_AMU; + } + } + + return end - start; +} + + +int p3d_read_config(Cell cell, char *path) +{ + Cell_private p = cell->private; + int n, ml, mg, nl, ndiv; + int entry_count, no_velocity, remain = 0, ntmp = 0; + int multi, k = 0; + P3DAtom *ptmp = NULL; + P3DFileP fp = NULL; + double r; + char line[P3D_LINEMAX]; + + /*p3d_global_io_any = 0;*/ + multi = chkpathname(path); + + p3d_set_atoms(cell, p3d_atom_begin(cell), 0); + cell->auxiliary->n_aux = 0; + ndiv = (multi) ? 1 : p->nprocs; + + if (multi && !p3d_global_io_any && p->nprocs > 1) { + fprintf(stderr, "open error\n"); + p3d_abort(-1); + } + + if (p3d_global_io_any || p->rank == 0) { + if ((fp = P3DFopen(p3d_filename(path, cell), "r")) == NULL) + p3d_abort(-1); + } + + if (p3d_global_io_any) { + int (*read_body)(Cell,P3DFileP,char*,int,P3DAtom*,int,int*, + double,int,int) + = (multi) ? read_config_body : read_config_body_filter; + for (k = 0; ; k++) { + if (remain == 0) + remain = read_config_header(cell, fp, line, sizeof(line), + &r, &entry_count, &no_velocity); + if (remain < 0) + break; + else if (remain > 0) { + if (k == 0) { + n = remain / ndiv + 1; + if (p->n_max < n) + p3d_realloc_cell(cell, n, 0); + nl = read_body(cell, fp, line, sizeof(line), p->point_begin, + p->n_max, &remain, r, entry_count, no_velocity); + p3d_set_atoms(cell, p->point_begin, nl); + } + else { + n = remain; + if(ntmprank == 0) + remain = read_config_header(cell, fp, line, sizeof(line), + &r, &entry_count, &no_velocity); + p3d_bcast(cell, &remain, 1, MPI_INT, 0); + if (remain < 0) + break; + else if (remain > 0) { + p3d_bcast(cell, &cell->h[0][0], 9, MPI_DOUBLE, 0); + p3d_bcast(cell, &cell->auxiliary->n_aux, 1, MPI_INT, 0); + if (cell->auxiliary->n_aux) { + p3d_bcast(cell, cell->auxiliary, + sizeof(struct Auxiliary_tag), MPI_CHAR,0); + } + + if (p->rank == 0) { + if (k == 0) { + n = remain / ndiv; + if (p->n_max < n) + p3d_realloc_cell(cell, n, 0); + nl = read_config_body(cell,fp,line,sizeof(line), + p->point_begin, p->n_max, &remain, + r, entry_count, no_velocity); + p3d_set_atoms(cell, p->point_begin, nl); + } + else { + n = remain; + if (ntmp < nl && !(ptmp = + (P3DAtom*)malloc(sizeof(P3DAtom)*(ntmp=n)))) + p3d_abort(-2); + nl = read_config_body(cell, fp, line, sizeof(line),ptmp, + ntmp, &remain, r, entry_count, no_velocity); + p3d_cat_atoms(cell, ptmp, nl); + } + } + do { + ml = p3d_reset_cell(cell); + p3d_reduce(cell, &ml, &mg, 1, MPI_INT, MPI_SUM); + } while (mg); + } + } + } + + if (ptmp) free(ptmp); + + return p3d_n_atoms(cell); +} + + +#define TAG_WRITE(fp, buf, fmt, num, val) \ + do {\ + ChgTag *ct;\ + for (ct = CHG_TAGS; ct < CHG_TAGS + N_CHG_TAGS; ct++) {\ + if (ct->id == num) {\ + sprintf(buf, "%s" fmt "\n", ct->name, val);\ + P3DFputs(line, fp);\ + if (ct->comment) {\ + sprintf(buf, "# %s\n\n", ct->comment);\ + P3DFputs(line, fp);\ + }\ + break;\ + }\ + }\ + } while (0) + +int p3d_write_config(Cell cell, char *path, + char *s_formats, char*velocity_formats, int n_aux, ...) +{ + Cell_private p = cell->private; + V3 sr, sv; + M3 h_inv; + P3DAtom *pnt; + P3DFileP fp = NULL; + char line[P3D_LINEMAX], line2[P3D_LINEMAX], oldsymbol[sizeof(int)]; + double cv_inv = 1.0 / utime_IN_NS, oldmass; + int n = p3d_n_atoms(cell), write_each = chkpathname(path); + int entry_count = 3; + struct auxiliary { + char *description; + char *format; + void *pointer; + int bytes_separation; + } aux[CONFIG_MAX_AUXILIARY]; + + if (!s_formats) /* Standerd */ + n_aux = 0; + else { /* Extended */ + va_list ap; + int i; + if (n_aux > CONFIG_MAX_AUXILIARY || n_aux < 0) p3d_abort(-1); + va_start(ap, n_aux); + for (i = 0; i < n_aux; i++) { + aux[i].description = va_arg(ap, char *); + aux[i].format = va_arg(ap, char *); + aux[i].pointer = va_arg(ap, char *); + aux[i].bytes_separation = va_arg(ap, int); + } + va_end(ap); + } + + if (!write_each) { + int m = n; + MPI_Reduce(&m, &n, 1, MPI_INT, MPI_SUM, 0, p->comm); + } + + if (write_each || p->rank == 0) { + if ((fp = P3DFopen(p3d_filename(path,cell),"w")) == NULL) p3d_abort(-1); + + if (p->nprocs > 1 && write_each ) { + sprintf(line2, "%d \t\t# %%%d (/%d)", n, p->rank, p->nprocs); + TAG_WRITE(fp, line, " %s", CHG_TAG_NUM, line2); + } + else + TAG_WRITE(fp, line, " %d", CHG_TAG_NUM, n); + + TAG_WRITE(fp, line,"%s",CHG_TAG_A," 1.0 Angstrom (basic length-scale)"); + + TAG_WRITE(fp, line, DFORMAT" A", CHG_TAG_H0_11, cell->h[0][0]); + TAG_WRITE(fp, line, DFORMAT" A", CHG_TAG_H0_12, cell->h[0][1]); + TAG_WRITE(fp, line, DFORMAT" A", CHG_TAG_H0_13, cell->h[0][2]); + TAG_WRITE(fp, line, DFORMAT" A", CHG_TAG_H0_21, cell->h[1][0]); + TAG_WRITE(fp, line, DFORMAT" A", CHG_TAG_H0_22, cell->h[1][1]); + TAG_WRITE(fp, line, DFORMAT" A", CHG_TAG_H0_23, cell->h[1][2]); + TAG_WRITE(fp, line, DFORMAT" A", CHG_TAG_H0_31, cell->h[2][0]); + TAG_WRITE(fp, line, DFORMAT" A", CHG_TAG_H0_32, cell->h[2][1]); + TAG_WRITE(fp, line, DFORMAT" A", CHG_TAG_H0_33, cell->h[2][2]); + P3DFputs("# H = H0\n\n", fp); + + if (!s_formats) { /* Standard cfg */ + P3DFputs( + "# ENSUING ARE THE ATOMS, EACH ATOM DESCRIBED BY A ROW\n" + "# 1st entry is atomic mass in a.m.u.\n" + "# 2nd entry is the chemical symbol (max 2 chars)\n" + "\n" + "# 3rd entry is reduced coordinate s1 (dimensionless)\n" + "# 4th entry is reduced coordinate s2 (dimensionless)\n" + "# 5th entry is reduced coordinate s3 (dimensionless)\n" + "# real coordinates x = s * H, x, s are 1x3 row vectors\n" + "\n" + "# 6th entry is d(s1)/dt in basic rate-scale R\n" + "# 7th entry is d(s2)/dt in basic rate-scale R\n" + "# 8th entry is d(s3)/dt in basic rate-scale R\n" + , fp); + TAG_WRITE(fp, line, "%s", CHG_TAG_R, " 1.0 [ns^-1]"); + } + else { /* Extended cfg */ + int i; + P3DFputs( + "# Each atom is described by a row:\n" + "\n" + "# 1st entry is reduced coordinate s1 (dimensionless)\n" + "# 2nd entry is reduced coordinate s1 (dimensionless)\n" + "# 3rd entry is reduced coordinate s1 (dimensionless)\n" + "# real coordinates x = s * H, x, s are 1x3 row vectors\n" + "\n" + , fp); + if (velocity_formats) { + P3DFputs( + "# 4th entry is d(s1)/dt in basic rate-scale R\n" + "# 5th entry is d(s2)/dt in basic rate-scale R\n" + "# 6th entry is d(s3)/dt in basic rate-scale R\n" + , fp); + TAG_WRITE(fp, line, "%s", CHG_TAG_R, " 1.0 [ns^-1]"); + entry_count += 3; + } + else { + TAG_WRITE(fp, line, "%s", CHG_TAG_NO_V, ""); + P3DFputs( + "# Atom velocities are deemed irrelevant for\n" + "# this configuration so they are not stored.\n" + "\n" + , fp); + } + + entry_count += n_aux; + TAG_WRITE(fp, line, " %d\n", CHG_TAG_ENTRY, entry_count); + + for (i = 0; i < n_aux; i++) { + sprintf(line2, "%d] = %s", i, aux[i].description); + TAG_WRITE(fp, line, "%s", CHG_TAG_AUX, line2); + } + + pnt = p3d_atom_begin(cell); + oldmass = pnt->m; + strncpy(oldsymbol, pnt->sym, sizeof(oldsymbol)); + sprintf(line, + "#\n" + "# These properties are piece-wise uniform:\n" + "%.15g\n" + "# (required) atomic mass in a.m.u.\n" + "%2s\n" + "# (required) chemical symbol (max 2 chars)\n\n", + oldmass * umass_IN_AMU, oldsymbol); + P3DFputs(line, fp); + } + + M3inv(cell->h, h_inv); + + if (!s_formats) { + if (cell->reduced_coordinates) { + for (pnt=p3d_atom_begin(cell);pntv, sv); + sprintf(line, "%f %s"FFORMAT3 FFORMAT3"\n", + pnt->m*umass_IN_AMU, pnt->sym, V3E(pnt->r),V3E(sv)); + P3DFputs(line, fp); + } + } + else { + for (pnt=p3d_atom_begin(cell);pntr, h_inv, sr); + V3mM3(pnt->v, h_inv, sv); + V3MuL(cv_inv, sv); + sprintf(line, "%f %s"FFORMAT3 FFORMAT3"\n", + pnt->m*umass_IN_AMU, pnt->sym, V3E(sr), V3E(sv)); + P3DFputs(line, fp); + } + } + } + else { + char *pointer[CONFIG_MAX_AUXILIARY]; + int i; + for (i = 0; i < n_aux; i++) pointer[i] = aux[i].pointer; + for (pnt=p3d_atom_begin(cell); pntm || strncmp(oldsymbol, pnt->sym, 2)) { + oldmass = pnt->m; + strncpy(oldsymbol, pnt->sym, sizeof(oldsymbol)); + sprintf(line,"%.15g\n%2s\n",oldmass*umass_IN_AMU,oldsymbol); + P3DFputs(line, fp); + } + if (cell->reduced_coordinates) + sprintf(line, s_formats, V3E(pnt->r)); + else { + V3mM3(pnt->r, h_inv, sr); + sprintf(line, s_formats, V3E(sr)); + } + P3DFputs(line, fp); + if (velocity_formats) { + if (cell->reduced_coordinates) + V3MUL(cv_inv, pnt->v, sv); + else { + V3mM3(pnt->v, h_inv, sv); + V3MuL(cv_inv, sv); + } + sprintf(line, velocity_formats, V3E(sv)); + P3DFputs(line, fp); + } + for (i = 0; i < n_aux; i++) { + sprintf(line, aux[i].format, *((double*)pointer[i])); + P3DFputs(line, fp); + pointer[i] += aux[i].bytes_separation; + } + P3DFputs("\n", fp); + } + } + } + + if (!write_each) { + static int ntmp = 0; + static double *atmp = NULL; + double *pp; + MPI_Datatype m_point = cell->private->M_POINT; + int tag = 0; + if (p->rank) { + MPI_Send(&n, 1, MPI_INT, 0, tag, p->comm); + MPI_Send(p3d_atom_begin(cell), n, m_point, 0, tag, p->comm); + if (n_aux) { + char *pointer[CONFIG_MAX_AUXILIARY]; + int i, j; + if (n > ntmp) { + ntmp = n; + atmp = (double*) realloc(atmp, sizeof(double)*ntmp*n_aux); + if (atmp == NULL) p3d_abort(-2); + } + for (i = 0; i < n_aux; i++) pointer[i] = aux[i].pointer; + pp = atmp; + for (j = 0; j < n; j++) { + for (i = 0; i < n_aux; i++) { + *pp++ = *((double*)pointer[i]); + pointer[i] += aux[i].bytes_separation; + } + } + MPI_Send(atmp, n*n_aux, MPI_DOUBLE, 0, tag, p->comm); + } + } + else { + MPI_Status stat; + int rank, nn = n; + static P3DAtom *ptmp = NULL; + for (rank = 1; rank < p->nprocs; rank++) { + MPI_Recv(&n, 1, MPI_INT, rank, tag, p->comm, &stat); + if (n > ntmp) { + ntmp = n; + ptmp = (P3DAtom*) realloc(ptmp, sizeof(P3DAtom) * ntmp); + if (ptmp == NULL) p3d_abort(-2); + if (n_aux) { + atmp = (double*)realloc(atmp,sizeof(double)*ntmp*n_aux); + if (atmp == NULL) p3d_abort(-2); + } + } + MPI_Recv(ptmp, n, m_point, rank, tag, p->comm, &stat); + if (n_aux) { + MPI_Recv(atmp, n*n_aux, MPI_DOUBLE, rank,tag,p->comm,&stat); + pp = atmp; + } + if (!s_formats) { + if (cell->reduced_coordinates) { + for (pnt = ptmp; pnt < ptmp + n; pnt++) { + V3MUL(cv_inv, pnt->v, sv); + sprintf(line, "%f %s"FFORMAT3 FFORMAT3"\n", + pnt->m, pnt->sym, V3E(pnt->r),V3E(sv)); + P3DFputs(line, fp); + } + } + else { + for (pnt = ptmp; pnt < ptmp + n; pnt++) { + V3mM3(pnt->r, h_inv, sr); + V3mM3(pnt->v, h_inv, sv); + V3MuL(cv_inv, sv); + sprintf(line, "%f %s"FFORMAT3 FFORMAT3"\n", + pnt->m, pnt->sym, V3E(sr), V3E(sv)); + P3DFputs(line, fp); + } + } + } else { + for (pnt = ptmp; pnt < ptmp + n; pnt++) { + int i; + if (oldmass != pnt->m||strncmp(oldsymbol,pnt->sym,2)) { + oldmass = pnt->m; + strncpy(oldsymbol, pnt->sym, sizeof(oldsymbol)); + sprintf(line, "%.15g\n%2s\n", + oldmass*umass_IN_AMU, oldsymbol); + P3DFputs(line, fp); + } + if (cell->reduced_coordinates) + sprintf(line, s_formats, V3E(pnt->r)); + else { + V3mM3(pnt->r, h_inv, sr); + sprintf(line, s_formats, V3E(sr)); + } + P3DFputs(line, fp); + if (velocity_formats) { + if (cell->reduced_coordinates) + V3MUL(cv_inv, pnt->v, sv); + else { + V3mM3(pnt->v, h_inv, sv); + V3MuL(cv_inv, sv); + } + sprintf(line, velocity_formats, V3E(sv)); + P3DFputs(line, fp); + } + for (i = 0; i < n_aux; i++) { + sprintf(line, aux[i].format, *pp++); + P3DFputs(line, fp); + } + P3DFputs("\n", fp); + } + } + } + n = nn; + } + } + + if (fp) P3DFclose(fp); + + return p3d_n_atoms(cell); +} + + +void p3d_coord_reduced2real(Cell cell) +{ + P3DAtom *pnt; + V3 s; + P3D_LOOP(cell, pnt) { + V3EQV(pnt->r, s); + V3mM3(s, cell->h, pnt->r); + V3EQV(pnt->v, s); + V3mM3(s, cell->h, pnt->v); + } + cell->reduced_coordinates = 0; +} diff -urN A/P3DExt.h A3/P3DExt.h --- A/P3DExt.h 1970-01-01 09:00:00.000000000 +0900 +++ A3/P3DExt.h 2011-02-22 15:15:37.000000000 +0900 @@ -0,0 +1,7 @@ +/* $Id: $ + * 2004-2005 Futoshi SHIMIZU + */ +#ifndef P3DExt_H +#define P3DExt_H + +#endif diff -urN A/P3D_p.h A3/P3D_p.h --- A/P3D_p.h 1970-01-01 09:00:00.000000000 +0900 +++ A3/P3D_p.h 2011-02-22 15:15:37.000000000 +0900 @@ -0,0 +1,36 @@ +/* $Id: P3D_p.h,v 1.1.1.1 2005/03/20 20:14:24 shimizu Exp $ + * 2004-2005 Futoshi SHIMIZU + */ +#ifndef P3D_P_H +#define P3D_P_H + +#include "P3D.h" + +struct Cell_private_tag { + P3DAtom *point_begin, *point_end, *image_end; + P3DAtom **p_point_begin, **p_point_end, **update[7]; + int n_max, p_max, f_realloc; + V3 lb, ub; + double crust; + int nprocs, rank; + int dims[3], coords[3], trans_mask; + int rank_send[6], rank_recv[6]; + MPI_Comm comm; + MPI_Request req_send[6], req_recv[6]; + MPI_Datatype M_POINT, M_IMAGE; +}; + +typedef struct Cell_private_tag *Cell_private; + +struct List_tag { + int *num; + Pair pair_point, pair_image; + P3DAtom ***p3d_point, ***p3d_image, **p_point_begin; + int n_max, p_max, i_max; +}; + +/* P3DCore.c */ + +int p3d_flags_boundary(V3 s, V3 lb, V3 ub); + +#endif diff -urN A/cui.c A3/cui.c --- A/cui.c 1970-01-01 09:00:00.000000000 +0900 +++ A3/cui.c 2012-11-15 15:20:00.000000000 +0900 @@ -0,0 +1,4887 @@ +/* 2004-2005 Futoshi Shimizu */ +#define CUI_GLOBAL +#include "cui.h" +#ifdef USE_P3D +# include "p3dp.h" +#endif +#include "A.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static char buf[CUI_LINEMAX], cmdline[CUI_LINEMAX]; +static char fname[FILENAME_MAX] = ""; +static int quit = 0; +static int frontend = -1; +#define nonvacant(iw) (AX_cid[iw]!=0) + +#define STRCATN(d, s) strncat((d), (s), sizeof(d)-strlen(d)-strlen(s)-1) + +double cui_wtime(void) +{ + struct timeval now; + gettimeofday(&now, NULL); + return now.tv_sec + now.tv_usec * 1.e-6; +} + + +static char *cui_stripspace(char *line) +{ + char *s, *t; + + s = line; + while (*s && isspace(*s)) s++; + if (!*s) return s; + + t = s + strlen(s) - 1; + while (t > s && isspace(*t)) t--; + *++t = 0; + + return s; +} + +static char cui_show_syntax[] = "syntax: "; + +static void cui_send(char *line, FILE *fp) +{ + char *s, sendbuf[CUI_LINEMAX]; + if (fp) { + if (fileno(fp) == STDIN_FILENO) fp = stdout; + strncpy(sendbuf, line, sizeof(sendbuf)-1); + s = cui_stripspace(sendbuf); + fputs(strcat(s, "\n"), fp); + fflush(fp); + } +} + + +static int cui_send_result(char *line, FILE *fp) +{ + int fd = fileno(fp); + if (!line || !*line) { + if (fd != frontend) + cui_send(CUI_PROTOCOL_OK, fp); + return 0; + } + else { + int len, len0; + char *s, sendbuf[CUI_LINEMAX]; + strncpy(sendbuf, line, sizeof(sendbuf)-1); + s = cui_stripspace(sendbuf); + len = strlen(s); + len0 = len - 1; + if (len0 > strlen(CUI_PROTOCOL_OK)&& + strcmp(s+len0-strlen(CUI_PROTOCOL_OK),"\n"CUI_PROTOCOL_OK)==0) { + if (fd == frontend) + *(s+len-strlen(CUI_PROTOCOL_OK)) = 0; + cui_send(s, fp); + return 0; + } + if (len0 > strlen(CUI_PROTOCOL_NG)&& + strcmp(s+len0-strlen(CUI_PROTOCOL_NG),"\n"CUI_PROTOCOL_NG)==0) { + if (fd == frontend) + *(s+len-strlen(CUI_PROTOCOL_NG)) = 0; + cui_send(s, fp); + return 1; + } + cui_send(s, fp); + if (fd != frontend) + cui_send(CUI_PROTOCOL_NG, fp); + return 1; + } +} + + +static int cui_recv_print(FILE *fp, FILE *out) +{ + char recvbuf[CUI_LINEMAX]; + if (fp) { + while (fgets(recvbuf, sizeof(recvbuf), fp)) { + if (!*recvbuf || strcmp(recvbuf, CUI_PROTOCOL_QUIT"\n") == 0) + return -1; + else if (strcmp(recvbuf, CUI_PROTOCOL_OK"\n") == 0) + return 0; + else if (strcmp(recvbuf, CUI_PROTOCOL_NG"\n") == 0) + return 1; + if (out) { + fputs(recvbuf, out); + fflush(out); + } + } + } + return -1; +} + + +static void stdin_gets(char *line) +{ + if (line) { + strncpy(cmdline, line, sizeof(cmdline)); + free(line); + } +} + +static char *gui_readline_gets(int iw, char *prompt, char *danswer) +{ + static char answer[CUI_LINEMAX] = ""; + if (AX_display[iw]) { + if (IS_MANAGER) { + xterm_get_focus(iw); + if (frontend >= 0) + rl_callback_handler_remove(); + clear_stdin_buffer(); + strncpy(answer, readline_gets(prompt, danswer), sizeof(answer)); + if (frontend >= 0) + rl_callback_handler_install(CUI_PROMPT, stdin_gets); + } +#ifdef USE_P3D + } + if (p3dp_enabled) { + int len = strlen(answer); + p3d_bcast(p3dp_cell, &len, 1, MPI_INT, 0); + if (len > 0) + p3d_bcast(p3dp_cell, answer, len+1, MPI_CHAR, 0); + } + if (AX_display[iw]) { +#endif + if (IS_MANAGER) + xterm_release_focus(iw); + } + return answer; +} + +/*******************************************************************/ + +struct aec { + char *name; + bool (*proc)(int iw, char *instr, char **outstr); + char *instr; + char *syntax; +}; + +struct gkt { + KeySym keysym; + struct aec *normal, *shift, *ctrl, *ctrl_shift, *meta, *meta_shift; + char *n, *s, *c, *cs, *m, *ms; +}; +#define RPT2(name) name, name +#define RPT3(name) name, name, name +#define RPT4(name) name, name, name, name +#define RPT6(name) name, name, name, name, name, name +#define GKT(keysym) keysym, RPT6(NULL) +static struct gkt gui_key_table[] = { + +/* TTY Functions */ + {GKT(XK_BackSpace),}, + {GKT(XK_Tab), RPT6("toggle_parallel_projection")}, + {GKT(XK_Linefeed),}, + {GKT(XK_Clear),}, + {GKT(XK_Return), RPT6("finish_rcut_patch")}, + {GKT(XK_Pause),}, + {GKT(XK_Scroll_Lock),}, + {GKT(XK_Sys_Req),}, + {GKT(XK_Escape), RPT6("isoatomic_reference_imprint")}, + {GKT(XK_Delete), "load_config_forward", NULL, "load_config_last"}, + +/* Cursor control & motion */ + {GKT(XK_Home), "change_bond_radius_inc", + "change_view_angle_amplification_inc", + "rcut_patch_inc"}, + {GKT(XK_End), "change_bond_radius_dec", + "change_view_angle_amplification_dec", + "rcut_patch_dec"}, + {GKT(XK_Right), "rotate_1_dec", "shift_cutting_plane_inc", + RPT2( "translate_0_inc"), RPT2( "shift_xtal_0_dec" )}, + {GKT(XK_Left), "rotate_1_inc", "shift_cutting_plane_dec", + RPT2( "translate_0_dec"), RPT2( "shift_xtal_0_inc" )}, + {GKT(XK_Up), "rotate_0_dec", "rotate_2_inc", + "translate_1_dec", "translate_2_inc", + "shift_xtal_1_inc", "shift_xtal_2_dec" }, + {GKT(XK_Down), "rotate_0_inc", "rotate_2_dec", + "translate_1_inc", "translate_2_dec", + "shift_xtal_1_dec", "shift_xtal_2_inc" }, + {GKT(XK_Page_Up), "change_atom_r_ratio_inc", + "change_aux_property_threshold_upper_inc", + "change_aux_property_threshold_lower_inc", + NULL, "advance_dec"}, + {GKT(XK_Page_Down), "change_atom_r_ratio_dec", + "change_aux_property_threshold_upper_dec", + "change_aux_property_threshold_lower_dec", + NULL, "advance_inc"}, + +/* Misc Functions */ + {GKT(XK_Select),}, + {GKT(XK_Print),}, + {GKT(XK_Execute),}, + {GKT(XK_Insert), "load_config_backward", NULL, "load_config_first"}, + {GKT(XK_Undo),}, + {GKT(XK_Redo),}, + {GKT(XK_Menu),}, + {GKT(XK_Find),}, + {GKT(XK_Cancel),}, + {GKT(XK_Help),}, + {GKT(XK_Break),}, + {GKT(XK_Mode_switch),}, + +/* Keypad Functions, keypad numbers */ + {GKT(XK_KP_Home), "change_bond_radius_inc"}, + {GKT(XK_KP_End), "change_bond_radius_dec"}, + {GKT(XK_KP_Right), "rotate_1_dec", "shift_cutting_plane_inc", + RPT2( "translate_0_inc"), RPT2( "shift_xtal_0_dec" )}, + {GKT(XK_KP_Left), "rotate_1_inc", "shift_cutting_plane_dec", + RPT2( "translate_0_dec"), RPT2( "shift_xtal_0_inc" )}, + {GKT(XK_KP_Up), "rotate_0_dec", "rotate_2_inc", + "translate_1_dec", "translate_2_inc", + "shift_xtal_1_inc", "shift_xtal_2_dec" }, + {GKT(XK_KP_Down), "rotate_0_inc", "rotate_2_dec", + "translate_1_inc", "translate_2_dec", + "shift_xtal_1_dec", "shift_xtal_2_inc" }, + {GKT(XK_KP_Page_Up), "change_atom_r_ratio_inc", + "change_aux_property_threshold_upper_inc", + "change_aux_property_threshold_lower_inc"}, + {GKT(XK_KP_Page_Down), "change_atom_r_ratio_dec", + "change_aux_property_threshold_upper_dec", + "change_aux_property_threshold_lower_dec"}, + {GKT(XK_KP_Insert),}, + {GKT(XK_KP_Delete),}, + {GKT(XK_KP_Enter),}, + {GKT(XK_KP_Multiply),}, + {GKT(XK_KP_Add),}, + {GKT(XK_KP_Subtract),}, + {GKT(XK_KP_Decimal),}, + {GKT(XK_KP_Divide),}, + {GKT(XK_KP_0),}, + {GKT(XK_KP_1),}, + {GKT(XK_KP_2),}, + {GKT(XK_KP_3),}, + {GKT(XK_KP_4),}, + {GKT(XK_KP_5),}, + {GKT(XK_KP_6),}, + {GKT(XK_KP_7),}, + {GKT(XK_KP_8),}, + {GKT(XK_KP_9),}, + +/* Auxilliary Functions */ + {GKT(XK_F1),}, + {GKT(XK_F2), RPT2("reset_scratch"), RPT4("free_scratch")}, + {GKT(XK_F3), RPT6("scratch_coloring")}, + {GKT(XK_F4),}, + {GKT(XK_F5),}, + {GKT(XK_F6),}, + {GKT(XK_F7), RPT6("capture_eps")}, + {GKT(XK_F8), RPT6("find_atom")}, + {GKT(XK_F9), RPT6("load_config")}, + {GKT(XK_F10), RPT6("reload_config")}, + {GKT(XK_F11), RPT6("load_aux")}, + {GKT(XK_F12), RPT6("load_atom_color")}, + +/* Latin 1 */ + {GKT(XK_space),}, + {GKT(XK_exclam),}, + {GKT(XK_numbersign),}, + {GKT(XK_dollar),}, + {GKT(XK_percent),}, + {GKT(XK_parenright),}, + {GKT(XK_asterisk),}, + {GKT(XK_plus),}, + {GKT(XK_comma), "print_atom_info_pair"}, + {GKT(XK_period),"print_atom_info_triplet"}, + {GKT(XK_slash), "print_atom_info_quartet"}, + {GKT(XK_0), "select_gear_0", "cutting_plane_0", + "aux_property_coloring_20", "shift_cutting_plane_to_anchor_0", + "aux_property_coloring_0", "delete_cutting_plane_0"}, + {GKT(XK_1), "select_gear_1", "cutting_plane_1", + "aux_property_coloring_21", "shift_cutting_plane_to_anchor_1", + "aux_property_coloring_1", "delete_cutting_plane_1"}, + {GKT(XK_2), "select_gear_2", "cutting_plane_2", + "aux_property_coloring_22", "shift_cutting_plane_to_anchor_2", + "aux_property_coloring_2", "delete_cutting_plane_2"}, + {GKT(XK_3), "select_gear_3", "cutting_plane_3", + "aux_property_coloring_23", "shift_cutting_plane_to_anchor_3", + "aux_property_coloring_3", "delete_cutting_plane_3"}, + {GKT(XK_4), "select_gear_4", "cutting_plane_4", + "aux_property_coloring_24", "shift_cutting_plane_to_anchor_4", + "aux_property_coloring_4", "delete_cutting_plane_4"}, + {GKT(XK_5), "select_gear_5", "cutting_plane_5", + "aux_property_coloring_25", "shift_cutting_plane_to_anchor_5", + "aux_property_coloring_5", "delete_cutting_plane_5"}, + {GKT(XK_6), "select_gear_6", "cutting_plane_6", + "aux_property_coloring_26", "shift_cutting_plane_to_anchor_6", + "aux_property_coloring_6", "delete_cutting_plane_6"}, + {GKT(XK_7), "select_gear_7", "cutting_plane_7", + "aux_property_coloring_27", "shift_cutting_plane_to_anchor_7", + "aux_property_coloring_7", "delete_cutting_plane_7"}, + {GKT(XK_8), "select_gear_8", "cutting_plane_8", + "aux_property_coloring_28", "shift_cutting_plane_to_anchor_8", + "aux_property_coloring_8", "delete_cutting_plane_8"}, + {GKT(XK_9), "select_gear_9", "cutting_plane_9", + "aux_property_coloring_29", "shift_cutting_plane_to_anchor_9", + "aux_property_coloring_9", "delete_cutting_plane_9"}, + {GKT(XK_agrave), "select_gear_0", "cutting_plane_0", + NULL, "shift_cutting_plane_to_anchor_0", + "aux_property_coloring_0", "delete_cutting_plane_0"}, + {GKT(XK_ampersand), "select_gear_1", "cutting_plane_1", + NULL, "shift_cutting_plane_to_anchor_1", + "aux_property_coloring_1", "delete_cutting_plane_1"}, + {GKT(XK_eacute), "select_gear_2", "cutting_plane_2", + NULL, "shift_cutting_plane_to_anchor_2", + "aux_property_coloring_2", "delete_cutting_plane_2"}, + {GKT(XK_quotedbl), "select_gear_3", "cutting_plane_3", + NULL, "shift_cutting_plane_to_anchor_3", + "aux_property_coloring_3", "delete_cutting_plane_3"}, + {GKT(XK_apostrophe), "select_gear_4","cutting_plane_4", + NULL, "shift_cutting_plane_to_anchor_4", + "aux_property_coloring_4", "delete_cutting_plane_4"}, + {GKT(XK_parenleft), "select_gear_5", "cutting_plane_5", + NULL, "shift_cutting_plane_to_anchor_5", + "aux_property_coloring_5", "delete_cutting_plane_5"}, + {GKT(XK_minus), "select_gear_6", "cutting_plane_6", + NULL, "shift_cutting_plane_to_anchor_6", + RPT2("change_aux_colormap_prev")}, + {GKT(XK_egrave), "select_gear_7", "cutting_plane_7", + NULL, "shift_cutting_plane_to_anchor_7", + "aux_property_coloring_7", "delete_cutting_plane_7"}, + {GKT(XK_underscore), "select_gear_8","cutting_plane_8", + NULL, "shift_cutting_plane_to_anchor_8", + "aux_property_coloring_8", "delete_cutting_plane_8"}, + {GKT(XK_ccedilla), "select_gear_9", "cutting_plane_9", + NULL, "shift_cutting_plane_to_anchor_9", + "aux_property_coloring_9", "delete_cutting_plane_9"}, + + {GKT(XK_colon), "save_atom_indices"}, + {GKT(XK_semicolon), "save_atom_indices"}, + {GKT(XK_less),}, + {GKT(XK_equal), RPT4(NULL), RPT2("change_aux_colormap_next")}, + {GKT(XK_greater),}, + {GKT(XK_question),}, + {GKT(XK_at),}, + {GKT(XK_bracketleft),}, + {GKT(XK_backslash),}, + {GKT(XK_bracketright),}, + {GKT(XK_asciicircum),}, + {GKT(XK_grave),}, + {GKT(XK_a), "look_at_the_anchor", "cutting_plane_a", + "toggle_aux_property_thresholds_saturation", + "shift_cutting_plane_to_anchor_a", + "aux_property_coloring_10", "delete_cutting_plane_a"}, + {GKT(XK_b), "toggle_bond_mode", "cutting_plane_b", + "toggle_bond_mode", "shift_cutting_plane_to_anchor_b", + "aux_property_coloring_11", "delete_cutting_plane_b"}, + {GKT(XK_c), "clone", "cutting_plane_c", + "close", "shift_cutting_plane_to_anchor_c", + "aux_property_coloring_12", "delete_cutting_plane_c"}, + {GKT(XK_d), "change_bgcolor", "cutting_plane_d", + "change_bgcolor", "shift_cutting_plane_to_anchor_d", + "aux_property_coloring_13", "delete_cutting_plane_d"}, + {GKT(XK_e), "capture_eps", "cutting_plane_e", + NULL, "shift_cutting_plane_to_anchor_e", + "aux_property_coloring_14", "delete_cutting_plane_e"}, + {GKT(XK_f), "find_atom", "cutting_plane_f", + NULL, "shift_cutting_plane_to_anchor_f", + "aux_property_coloring_15", "delete_cutting_plane_f"}, + {GKT(XK_g), "observer_goto", "change_shear_strain_subtract_mean", + "aux_property_coloring_16", NULL, + "shear_strain_coloring", NULL}, + {GKT(XK_h), NULL, "change_central_symm_neighbormax", + "aux_property_coloring_17", NULL, + "central_symmetry_coloring", NULL}, + {GKT(XK_i), "change_wireframe_mode", "change_cutting_plane_wireframe_mode", + "aux_property_coloring_18", NULL}, + {GKT(XK_j), "capture_jpg", NULL, + "aux_property_coloring_19", NULL}, + {GKT(XK_k), "toggle_coordination_coloring", NULL, + "aux_property_coloring_30"}, + {GKT(XK_l), "normal_coloring", NULL, + "aux_property_coloring_31", NULL, "load_script"}, + {GKT(XK_m), RPT4(NULL), "change_aux_colormap", NULL}, + {GKT(XK_n), "new"}, + {GKT(XK_o), "original_normal_coloring"}, + {GKT(XK_p), "capture_png", "flip_cutting_plane"}, + {GKT(XK_q), "close"}, + {GKT(XK_r), "toggle_rcut_patch_mode", NULL,"reset_aux_property_thresholds"}, + {GKT(XK_s), NULL, NULL, "resize", "resize", "save"}, + {GKT(XK_t), "xtal_origin_goto", NULL, + "toggle_aux_property_thresholds_rigid"}, + {GKT(XK_u), "viewframe_upright"}, + {GKT(XK_v), "toggle_shell_viewer_mode"}, + {GKT(XK_w), "reset_anchor"}, + {GKT(XK_x), "toggle_xtal_mode"}, + {GKT(XK_y), "script_animate"}, + {GKT(XK_z), "xtal_origin_zero"}, + {GKT(XK_braceleft),}, + {GKT(XK_bar),}, + {GKT(XK_braceright),}, + {GKT(XK_asciitilde),}, + + {GKT(XK_nobreakspace),}, + {GKT(XK_exclamdown),}, + {GKT(XK_cent),}, + {GKT(XK_sterling),}, + {GKT(XK_currency),}, + {GKT(XK_yen),}, + {GKT(XK_brokenbar),}, + {GKT(XK_section),}, + {GKT(XK_diaeresis),}, + {GKT(XK_copyright),}, + {GKT(XK_ordfeminine),}, + {GKT(XK_guillemotleft),}, + {GKT(XK_notsign),}, + {GKT(XK_hyphen),}, + {GKT(XK_registered),}, + {GKT(XK_macron),}, + {GKT(XK_degree),}, + {GKT(XK_plusminus),}, + {GKT(XK_twosuperior),}, + {GKT(XK_threesuperior),}, + {GKT(XK_acute),}, + {GKT(XK_mu),}, + {GKT(XK_paragraph),}, + {GKT(XK_periodcentered),}, + {GKT(XK_cedilla),}, + {GKT(XK_onesuperior),}, + {GKT(XK_masculine),}, + {GKT(XK_guillemotright),}, + {GKT(XK_onequarter),}, + {GKT(XK_onehalf),}, + {GKT(XK_threequarters),}, + {GKT(XK_questiondown),}, + {GKT(XK_Agrave),}, + {GKT(XK_Aacute),}, + {GKT(XK_Acircumflex),}, + {GKT(XK_Atilde),}, + {GKT(XK_Adiaeresis),}, + {GKT(XK_Aring),}, + {GKT(XK_AE),}, + {GKT(XK_Ccedilla),}, + {GKT(XK_Egrave),}, + {GKT(XK_Eacute),}, + {GKT(XK_Ecircumflex),}, + {GKT(XK_Ediaeresis),}, + {GKT(XK_Igrave),}, + {GKT(XK_Iacute),}, + {GKT(XK_Icircumflex),}, + {GKT(XK_Idiaeresis),}, + {GKT(XK_ETH),}, + {GKT(XK_Ntilde),}, + {GKT(XK_Ograve),}, + {GKT(XK_Oacute),}, + {GKT(XK_Ocircumflex),}, + {GKT(XK_Otilde),}, + {GKT(XK_Odiaeresis),}, + {GKT(XK_multiply),}, + {GKT(XK_Ooblique),}, + {GKT(XK_Ugrave),}, + {GKT(XK_Uacute),}, + {GKT(XK_Ucircumflex),}, + {GKT(XK_Udiaeresis),}, + {GKT(XK_Yacute),}, + {GKT(XK_THORN),}, + {GKT(XK_ssharp),}, + {GKT(XK_aacute),}, + {GKT(XK_acircumflex),}, + {GKT(XK_atilde),}, + {GKT(XK_adiaeresis),}, + {GKT(XK_aring),}, + {GKT(XK_ae),}, + {GKT(XK_ecircumflex),}, + {GKT(XK_ediaeresis),}, + {GKT(XK_igrave),}, + {GKT(XK_iacute),}, + {GKT(XK_icircumflex),}, + {GKT(XK_idiaeresis),}, + {GKT(XK_eth),}, + {GKT(XK_ntilde),}, + {GKT(XK_ograve),}, + {GKT(XK_oacute),}, + {GKT(XK_ocircumflex),}, + {GKT(XK_otilde),}, + {GKT(XK_odiaeresis),}, + {GKT(XK_division),}, + {GKT(XK_oslash),}, + {GKT(XK_ugrave),}, + {GKT(XK_uacute),}, + {GKT(XK_ucircumflex),}, + {GKT(XK_udiaeresis),}, + {GKT(XK_yacute),}, + {GKT(XK_thorn),}, + {GKT(XK_ydiaeresis),}, + +/* Japanese keyboard */ + {GKT(XK_Muhenkan),}, + {GKT(XK_Henkan),}, + {GKT(XK_Hiragana_Katakana),}, + {GKT(XK_Zenkaku_Hankaku),}, + + {GKT(NoSymbol)} +}; + +static struct gkt *gktp_bykeysym(KeySym keysym) +{ + struct gkt *gktp; + for (gktp = gui_key_table; gktp->keysym != NoSymbol; gktp++) + if (gktp->keysym == keysym) + return gktp; + return NULL; +} + +static struct aec **aecpp_bykeyname(char *keyname) +{ + char *s, buf2[CUI_LINEMAX]; + KeySym keysym; + struct gkt *gktp; + int shift = 0, ctrl = 0, meta = 0; + + if (!keyname || !*keyname) return NULL; + strncpy(buf2, keyname, sizeof(buf2)); + + if ((s = strchr(buf2, '+'))) { + *s++ = 0; + if (*s) { + switch (toupper(*s++)) { + case 'S': shift = 1; break; + case 'C': ctrl = 1; break; + case 'M': meta = 1; break; + } + } + if (*s) { + switch (toupper(*s++)) { + case 'S': shift = 1; break; + case 'C': ctrl = 1; break; + case 'M': meta = 1; break; + } + } + } + + if ((keysym = XStringToKeysym(buf2)) != NoSymbol && + (gktp = gktp_bykeysym(keysym))) { + if (ctrl) + if (shift) return &gktp->ctrl_shift; + else return &gktp->ctrl; + else if (meta) + if (shift) return &gktp->meta_shift; + else return &gktp->meta; + else + if (shift) return &gktp->shift; + else return &gktp->normal; + } + + return NULL; +} + +static int rgb_url_printed = 0; +static int maxfd_plus_1 = 0, listen_fd = -1; +static fd_set allset; + +static struct { + FILE *fp; + int fd; + double pause; + int opener; + int writable; +} cmdf[CUI_N_FILE] = {{NULL, -1, 0.0, 0, 0}}; + +static int cmdfdopen(int fd, char *mode, int opener) +{ + int i; + + for (i = 0; i < CUI_N_FILE; i++) + if (!cmdf[i].fp) break; + if (i == CUI_N_FILE) + return -1; + + if (fd == -1 || !(cmdf[i].fp = fdopen(fd, mode))) + return -1; + + cmdf[i].fd = fd; + cmdf[i].pause = 0.0; + cmdf[i].opener = opener; + cmdf[i].writable = (strcmp(mode, "r+") == 0 || fd == STDIN_FILENO) ? 1 : 0; + setbuf(cmdf[i].fp, NULL); + + FD_SET(cmdf[i].fd, &allset); + if (cmdf[i].fd >= maxfd_plus_1) + maxfd_plus_1 = cmdf[i].fd + 1; + if (opener >= 0) + cmdf[opener].pause = -1.0; + + return i; +} + + +static void cmdfclose(int k) +{ + int i, k0 = k, k1 = k + 1; + + if (k < 0) { + k0 = 0; + k1 = CUI_N_FILE; + } + + for (i = k0; i < k1; i++) { + if (!cmdf[i].fp) continue; + + if (cmdf[i].fd == STDIN_FILENO) + quit = 1; + + if (cmdf[i].fd == frontend) + rl_callback_handler_remove(); + else if (cmdf[i].writable) { + cui_send(CUI_PROTOCOL_QUIT, cmdf[i].fp); + } + + FD_CLR(cmdf[i].fd, &allset); + if (maxfd_plus_1 == cmdf[i].fd + 1) { + int j; + maxfd_plus_1 = 0; + if (listen_fd >= maxfd_plus_1) maxfd_plus_1 = listen_fd + 1; + for (j = 0; j < CUI_N_FILE; j++) { + if (cmdf[j].fp && cmdf[j].fd >= maxfd_plus_1) + maxfd_plus_1 = cmdf[j].fd + 1; + } + } + cmdf[i].fd = -1; + if (cmdf[i].opener >= 0) + cmdf[cmdf[i].opener].pause = 0.0; + + fclose(cmdf[i].fp); + cmdf[i].fp = NULL; + cmdf[i].writable = 0; + } +} + +enum isv_type { ISV_int, ISV_double, ISV_v2, ISV_v3, ISV_v4}; + +#define NAVI(type,mem)\ + {ISV_##type, "n->"#mem, offsetof(Navigator,mem)} + /*{ISV_##type, "n->"#mem, (size_t) &((Navigator *)0)->mem}*/ +#define NAVI_POINTER(iw,isvtp) (((char*)&n[(iw)])+(isvtp)->offset) + +#define AX3D(type,mem)\ + {ISV_##type, "AX_3D->"#mem, offsetof(AX_3D_Viewport,mem)} + /*{ISV_##type, "AX_3D->"#mem, (size_t)&((AX_3D_Viewport *)0)->mem}*/ +#define AX3D_POINTER(iw,isvtp) (((char*)&AX_3D[(iw)])+(isvtp)->offset) + +#define ACC(num) \ + {ISV_v3,"CC["#num"]", (size_t) (\ + num*sizeof(Atom_coordination_color)+\ + offsetof(Atom_coordination_color,r))} + /*(size_t)&((Atom_coordination_color *)0)->r)}*/ +#define ACC_POINTER(isvtp) (((char*)CoordColor)+(isvtp)->offset) + +static struct isvt { + enum isv_type type; + char *name; + size_t offset; +} internal_state_variable_table[] = { + + NAVI(v3, bgcolor), /* background color r,g,b */ + /*NAVI(int, lx),*//* last pointer position */ + /*NAVI(int, ly),*/ + /*NAVI(long, last_button_press_time), for capturing double click */ + NAVI(int, anchor), /* -1: hook[] as anchor, >=0: certain atom */ +/* +#if (ATOM_STACK_SIZE == 4) + NAVI(int, atom_stack[0]),*//* keep track of selected atoms *//* + NAVI(int, atom_stack[1]), NAVI(int, atom_stack[2]),NAVI(int, atom_stack[3]), +#else +# error +#endif*/ + NAVI(v3, hook), /* real space coordinates */ + NAVI(int, suppress_printout), /* term printout */ + NAVI(double, delta), /* rate of change (gear-box) */ + NAVI(double, mgs_radius), /* magic sphere for pointer rotation */ + NAVI(double, atom_r_ratio), /* compared to ATOM_RADIUS */ + NAVI(int, color_mode), /* NORMAL, COORD, AUXILIARY or SCRATCH */ + NAVI(int, last_color_mode), + NAVI(int, wireframe_mode), /* draw H-box */ + NAVI(int, bond_mode), /* draw bonds */ + NAVI(double, bond_radius), /* in Angstrom */ + /*NAVI(int, bond_atom_color_need_update), delayed update due to atom color */ + NAVI(int, shell_viewer_mode), /* xv and ghostview */ + NAVI(int, xtal_mode), + /* to allow for crystal translation and shear-encoding */ + NAVI(v3, xtal_origin), /* shifted xtal origin */ + /*NAVI(int, bond_xtal_origin_need_update), delayed bond update due to shift */ + NAVI(int, last_surface_id), /* for if the pointer is not pointing at H box*/ + /*NAVI(int, mitosis),*//* for spawning children thread */ + NAVI(int, auxiliary_idx), + /* which auxiliary property should we render */ + NAVI(int, auxiliary_cmap), /* which colormap should we use */ +#if (CONFIG_MAX_AUXILIARY+MAX_GEO_MEASURES == 34) /* 18 */ +# define NAVI_AUX_THR(i) NAVI(v2, auxiliary_threshold[i]) + NAVI_AUX_THR(0), NAVI_AUX_THR(1), NAVI_AUX_THR(2), NAVI_AUX_THR(3), + NAVI_AUX_THR(4), NAVI_AUX_THR(5), NAVI_AUX_THR(6), NAVI_AUX_THR(7), + NAVI_AUX_THR(8), NAVI_AUX_THR(9), NAVI_AUX_THR(10),NAVI_AUX_THR(11), + NAVI_AUX_THR(12),NAVI_AUX_THR(13),NAVI_AUX_THR(14),NAVI_AUX_THR(15), + NAVI_AUX_THR(16),NAVI_AUX_THR(17),NAVI_AUX_THR(18),NAVI_AUX_THR(19), + NAVI_AUX_THR(20),NAVI_AUX_THR(21),NAVI_AUX_THR(22),NAVI_AUX_THR(23), + NAVI_AUX_THR(24),NAVI_AUX_THR(25),NAVI_AUX_THR(26),NAVI_AUX_THR(27), + NAVI_AUX_THR(28),NAVI_AUX_THR(29),NAVI_AUX_THR(30),NAVI_AUX_THR(31), + NAVI_AUX_THR(32),NAVI_AUX_THR(33), +#else +# error +#endif + NAVI(int, auxiliary_thresholds_saturation), + /* 0:invisible if outside thresholds */ + NAVI(int, auxiliary_thresholds_rigid), /* 0: floating thresholds */ + NAVI(int, parallel_projection), + /* parallel / perspective projections */ + NAVI(int, glob_advance), /* how fast the file list advances */ +#if (AX_3D_MAX_FILTER_PLANE == 16) +# define NAVI_FP(i) \ + NAVI(int, fp[i].wireframe_mode), NAVI(v3, fp[i].s0),\ + NAVI(v4, fp[i].dx_input), NAVI(v4, fp[i].dx_cache) + NAVI_FP(0), NAVI_FP(1), NAVI_FP(2), NAVI_FP(3), NAVI_FP(4), NAVI_FP(5), + NAVI_FP(6), NAVI_FP(7), NAVI_FP(8), NAVI_FP(9), NAVI_FP(10),NAVI_FP(11), + NAVI_FP(12),NAVI_FP(13),NAVI_FP(14),NAVI_FP(15), +#else +# error +#endif + NAVI(int, just_activated_fp), /* index of the fp under focus */ + + AX3D(v3, x), /* coordinates of the viewpoint */ + AX3D(double, k), /* conversion factor from radian to window pixels*/ + AX3D(v3, V[0]), /* V[i][0-2] is the normalized ith axis of viewport*/ + AX3D(v3, V[1]), + AX3D(v3, V[2]), + AX3D(double, zcut), /* (0,zcut] of the view frustum */ + AX3D(double, wx),/* viewpoint coordinates in window frame (pixels)*/ + AX3D(double, wy), +#if (AX_3D_MAX_FILTER_PLANE == 16) +# define AX3D_FP(i) AX3D(double, fp[i].d0), AX3D(v3, fp[i].dx) + AX3D_FP(0), AX3D_FP(1), AX3D_FP(2), AX3D_FP(3), AX3D_FP(4), AX3D_FP(5), + AX3D_FP(6), AX3D_FP(7), AX3D_FP(8), AX3D_FP(9), AX3D_FP(10),AX3D_FP(11), + AX3D_FP(12),AX3D_FP(13),AX3D_FP(14),AX3D_FP(15), /* filter planes */ +#else +# error +#endif +#if (ATOM_COORDINATION_MAX+1 == 25) + ACC(0), ACC(1), ACC(2), ACC(3), ACC(4), + ACC(5), ACC(6), ACC(7), ACC(8), ACC(9), + ACC(10), ACC(11), ACC(12), ACC(13), ACC(14), + ACC(15), ACC(16), ACC(17), ACC(18), ACC(19), + ACC(20), ACC(21), ACC(22), ACC(23), ACC(24), +#else +# error +#endif + + {0, NULL, 0} +}; + +static struct aec *aecp_byname(char *name); +static bool proc_set(int iw, char *instr, char **outstr) +{ + char name[CUI_LINEMAX] = ""; + + *outstr = NULL; + buf[0] = 0; + if (sscanf(instr, " %[^ ] %[^\n]", name, buf) < 2) + goto error; + + if (strncmp(name, "key->", strlen("key->")) == 0) { + struct aec **aecpp, *aecp; + if (!(aecpp = aecpp_bykeyname(name + strlen("key->")))) { + goto error; + } + else if (!(aecp = aecp_byname(buf))) { + goto error; + } + *aecpp = aecp; + return FALSE; + } + else { + struct isvt *isvtp; + for (isvtp = internal_state_variable_table; isvtp->name; isvtp++) { + if (strcmp(isvtp->name, name) == 0) { + void *pointer; + switch (*isvtp->name) { + case 'n': pointer = NAVI_POINTER(iw, isvtp); break; + case 'A': pointer = AX3D_POINTER(iw, isvtp); break; + case 'C': pointer = ACC_POINTER( isvtp); break; + default: goto error; + } + switch (isvtp->type) { + case ISV_int: + if (sscanf(buf, "%d", (int*) pointer) == 1) + return FALSE; + else + goto error; + case ISV_double: + if (sscanf(buf, "%lf", (double*)pointer) == 1) + return FALSE; + else + goto error; + case ISV_v2: + if (sscanf(buf, "%lf %lf", + (double*)pointer, (double*)pointer+1) > 0) + return FALSE; + else + goto error; + case ISV_v3: + if (sscanf(buf, "%lf %lf %lf", V3e((double*)pointer)) > 0) + return FALSE; + else + goto error; + case ISV_v4: + if (sscanf(buf, "%lf %lf %lf %lf", + (double*)pointer, (double*)pointer+1, + (double*)pointer+2, (double*)pointer+3) > 0) + return FALSE; + else + goto error; + } + } + } + } +error: + *outstr = cui_show_syntax; + return FALSE; +} + + +#define SETKEYPRINT(fp, keystr, modstr, entry)\ + if (gktp->entry && gktp->entry->name && *gktp->entry->name)\ + fprintf(fp, "set key->%s%s %s\n", keystr, modstr, gktp->entry->name) + +static bool proc_save(int iw, char *instr, char **outstr) +{ + char fname[FILENAME_MAX] = CUI_SCRIPT_DEFAULT; + int isv = 1, key = 0; + + if (!instr) + goto error; + else if (strcmp(instr, CUI_ARG_REQUIRED) == 0) + instr = cui_stripspace( + gui_readline_gets(iw, "\nSave script_file", CUI_SCRIPT_DEFAULT)); + + *outstr = NULL; + buf[0] = 0; + + if (!IS_MANAGER) return FALSE; + + if (sscanf(instr, " %[^ ] %[^ ]", fname, buf) == 2) { + if (strcmp(buf, "both") == 0) + key = 1; + else if (strcmp(buf, "key") == 0) { + key = 1; + isv = 0; + } + } + + if (fname[0]) { + FILE *fp = fopen(fname, "w"); + if (!fp) + goto error; + if (isv) { + struct isvt *isvtp; + void *pointer; + + for (isvtp = internal_state_variable_table; isvtp->name; isvtp++) { + switch (*isvtp->name) { + case 'n': pointer = NAVI_POINTER(iw, isvtp); break; + case 'A': pointer = AX3D_POINTER(iw, isvtp); break; + case 'C': pointer = ACC_POINTER( isvtp); break; + default: goto error; + } + switch (isvtp->type) { + case ISV_int: + fprintf(fp, "set %s %d\n", + isvtp->name, *(int*) pointer); + break; + case ISV_double: + fprintf(fp, "set %s %.15g\n", + isvtp->name, *(double*)pointer); + break; + case ISV_v2: + fprintf(fp, "set %s %.15g %.15g\n", + isvtp->name, *(double*)pointer, *((double*)pointer+1)); + break; + case ISV_v3: + fprintf(fp, "set %s %.15g %.15g %.15g\n", + isvtp->name, V3E((double*)pointer)); + break; + case ISV_v4: + fprintf(fp, "set %s %.15g %.15g %.15g %.15g\n", + isvtp->name,*(double*)pointer , *((double*)pointer+1), + *(double*)pointer+2, *((double*)pointer+3)); + break; + } + } + fprintf(fp, "resize %d %d\n", AX_size[iw].width,AX_size[iw].height); + fprintf(fp, "redraw\n"); + } + + if (key) { + struct gkt *gktp; + char *keystr; + for (gktp = gui_key_table; gktp->keysym != NoSymbol; gktp++) { + keystr = XKeysymToString(gktp->keysym); + if (!keystr) continue; + SETKEYPRINT(fp, keystr, "" , normal ); + SETKEYPRINT(fp, keystr, "+S" , shift ); + SETKEYPRINT(fp, keystr, "+C" , ctrl ); + SETKEYPRINT(fp, keystr, "+CS", ctrl_shift); + SETKEYPRINT(fp, keystr, "+M" , meta ); + SETKEYPRINT(fp, keystr, "+MS", meta_shift); + } + } + + fclose(fp); + return FALSE; + } +error: + *outstr = cui_show_syntax; + return FALSE; +} + + +static bool proc_nop(int iw, char *instr, char **outstr) +{ + *outstr = NULL; + return FALSE; +} + +static bool proc_internal_error(int iw, char *instr, char **outstr) +{ + *outstr = "internal error"; + return FALSE; +} + +static bool proc_load_script(int iw, char *instr, char **outstr) +{ + int i = -1; + *outstr = cui_show_syntax; + if (!instr) + return FALSE; + else if (strcmp(instr, CUI_ARG_REQUIRED) == 0) + instr = cui_stripspace( + gui_readline_gets(iw, "\nLoad script_file", CUI_SCRIPT_DEFAULT)); + + *outstr = NULL; + + if (!IS_MANAGER) return FALSE; + strncpy(fname, CUI_SCRIPT_DEFAULT, sizeof(fname)); + sscanf(instr, " %[^ ]%d", fname, &i); + + if (cmdfdopen(open(fname, O_RDONLY), "r", i) == -1) + *outstr = "open failed"; + + return FALSE; +} + +static bool proc_next(int iw, char *instr, char **outstr) +{ + int jw; +#ifdef USE_P3D + if (p3dp_enabled) + return FALSE; +#endif + *outstr = NULL; + for (jw = iw + 1; jw < AX_MAXWIN; jw++) { + if (nonvacant(jw)) { + cui_iw = jw; + AXSetName(iw); + AXSetName(jw); + return FALSE; + } + } + for (jw = 0; jw < iw; jw++) { + if (nonvacant(jw)) { + cui_iw = jw; + AXSetName(iw); + AXSetName(jw); + return FALSE; + } + } + cui_iw = -1; + return FALSE; +} + +static bool proc_close(int iw, char *instr, char **outstr) +{ + if (iw == cui_iw) + proc_next(iw, NULL, outstr); + if (cui_iw < 0) + cmdfclose(-1); + AX_closewindow(iw); +#ifdef USE_P3D + if (p3dp_enabled) longjmp(quit_env, 1); + else +#endif + pthread_exit ((void *)NULL); + exit(-1); +} + +static bool proc_quit(int iw, char *instr, char **outstr) +{ + quit = 1; + proc_close(iw, NULL, outstr); + exit (-1); +} + + +static bool proc_new(int iw, char *instr, char **outstr) +{ + pthread_t tid; + +#ifdef USE_P3D + if (p3dp_enabled) { + *outstr = "Not implemented in Parallel"; + return FALSE; + } +#endif + if (instr && strcmp(instr, "clone") == 0) + n[iw].mitosis = iw; /* clone */ + else + n[iw].mitosis = -1; + + *outstr = NULL; + pthread_create(&tid, NULL, (void *(*)(void *)) thread_start, + (void *)(&(n[iw].mitosis))); + return FALSE; +} + + +static bool proc_key(int iw, char *instr, char **outstr) +{ + struct aec **aecpp; + + *outstr = NULL; + if (instr && (aecpp = aecpp_bykeyname(instr)) && *aecpp) { + if (strcmp((*aecpp)->name, "load_script") == 0) + goto error; + else if ((*aecpp)->instr && strcmp((*aecpp)->instr,CUI_ARG_REQUIRED)!=0) + return (*(*aecpp)->proc)(iw, (*aecpp)->instr, outstr); + else + return (*(*aecpp)->proc)(iw, NULL, outstr); + } +error: + *outstr = cui_show_syntax; + return FALSE; +} + + +static bool proc_free_scratch(int iw, char *instr, char **outstr) +{ + extern AX_Float *scratch_r, *scratch_g, *scratch_b; + extern int scratch_np; + int i = ((scratch_r!=NULL)+(scratch_g!=NULL)+(scratch_b!=NULL)); + + *outstr = NULL; + Free(scratch_r); + Free(scratch_g); + Free(scratch_b); + sprintf(buf, "Previous scratch colors freed (%s bytes).", + strmem((long)i*scratch_np*sizeof(AX_Float))); + *outstr = buf; + scratch_np = 0; + return FALSE; +} + + +static bool proc_scratch_coloring(int iw, char *instr, char **outstr) +{ + extern AX_Float *scratch_r, *scratch_g, *scratch_b; + extern int scratch_np; + int i; + +#ifdef USE_P3D + if (p3dp_enabled) { + *outstr = "Not implemented in Parallel"; + return FALSE; + } +#endif + *outstr = NULL; + if (np != scratch_np) { + sprintf(buf,"scratch_color: current np=%d not equals to that of\n" + "old scratch=%d, Please rescratch.", np, scratch_np); + *outstr = buf; + return FALSE; + } + strcpy(AX_title[iw], str4(fbasename, " (", "scratch", ")")); + AXSetName(iw); + XStoreName(AX_display[iw],xterm_win,AX_title[iw]); + XSetIconName(AX_display[iw],xterm_win,AX_title[iw]); + for (i=0; iBALL[i],scratch_r[i],scratch_g[i],scratch_b[i]); + n[iw].color_mode = COLOR_MODE_SCRATCH; + if (n[iw].bond_mode) { + bond_xtal_origin_update(iw); + bond_atom_color_update(iw); + } + else { + n[iw].bond_xtal_origin_need_update = TRUE; + n[iw].bond_atom_color_need_update = TRUE; + } + return TRUE; +} + + +static bool proc_reset_scratch(int iw, char *instr, char **outstr) +{ + extern AX_Float *scratch_r, *scratch_g, *scratch_b; + extern int scratch_np, scratch_n[3]; + char *c; + int i, j; + double ds[3], new_s[3]; + +#ifdef USE_P3D + if (p3dp_enabled) { + *outstr = "Not implemented in Parallel"; + return FALSE; + } +#endif + *outstr = NULL; + if (instr) { + c = cui_stripspace(strncpy(buf, instr,sizeof(buf))); + if (strcmp(instr, CUI_ARG_REQUIRED) == 0) + instr = gui_readline_gets(iw, + "\nScratch into n1xn2xn3 color blocks", "2 2 2"); + sscanf(instr, " %d %d %d\n", scratch_n, scratch_n+1, scratch_n+2); + } + else + scratch_n[0] = scratch_n[1] = scratch_n[2] = 2; + + REALLOC(rescratch, scratch_r, np, AX_Float); + REALLOC(rescratch, scratch_g, np, AX_Float); + REALLOC(rescratch, scratch_b, np, AX_Float); + scratch_np = np; + if (scratch_n[0] < 1) scratch_n[0] = 2; + if (scratch_n[1] < 1) scratch_n[1] = 2; + if (scratch_n[2] < 1) scratch_n[2] = 2; + V3mM3 (n[iw].xtal_origin, HI, ds); + V3TRIM (ds, ds); + for (i=0; i 2) + goto error; + else + return translate(iw, axis, d); + default: + /* error */ + break; + } +error: + *outstr = cui_show_syntax; + return FALSE; +} + + +static bool proc_shift_xtal(int iw, char *instr, char **outstr) +{ + int axis = 0; + double d = 0.0; + + if (!n[iw].xtal_mode) + return FALSE; + + if (!instr) + goto error; + else if (strcmp(instr, CUI_ARG_REQUIRED) == 0) + instr = cui_stripspace(gui_readline_gets(iw, "\nXtal shift", "0 0.0")); + + *outstr = NULL; + buf[0] = 0; + switch (sscanf(instr, " %d%lf %[^ ]", &axis, &d, buf)) + { + case 3: + if (strcmp(buf, "delta") == 0) + d *= n[iw].delta; + else + goto error; + case 2: + if (axis < 0 || axis > 2) + goto error; + else + return xtal_shift(iw, axis, d); + default: + /* error */ + break; + } +error: + *outstr = cui_show_syntax; + return FALSE; +} + + +static bool proc_rotate(int iw, char *instr, char **outstr) +{ + int axis = 0; + double theta = 0.0; + + if (!instr) + goto error; + else if (strcmp(instr, CUI_ARG_REQUIRED) == 0) + instr = cui_stripspace(gui_readline_gets(iw, "\nRotate axis", "0 0.0")); + + *outstr = NULL; + buf[0] = 0; + switch (sscanf(instr, " %d%lf %[^ ]", &axis, &theta, buf)) + { + case 3: + if (strcmp(buf, "delta") == 0) + theta *= n[iw].delta; + else + goto error; + case 2: + if (axis < 0 || axis > 2) + goto error; + else + return axis_rotate(iw, axis, theta*PI); + default: + /* error */ + break; + } +error: + *outstr = cui_show_syntax; + return FALSE; +} + + +static bool proc_advance(int iw, char *instr, char **outstr) +{ + double delta = 0.0; + double tmp[3]; + + *outstr = cui_show_syntax; + if (!instr) + return FALSE; + else if (strcmp(instr, CUI_ARG_REQUIRED) == 0) { + if (AX_display[iw]) + printf("\nChange the distance between viewpoint and anchor:\n" + "if delta >=0, d -> d/(1+delta), else d -> d * (1-delta)."); + instr = cui_stripspace(gui_readline_gets(iw, "\ndelta", "0.0")); + } + + buf[0] = 0; + if (sscanf(instr, " %lf %s", &delta, buf) < 1) + return FALSE; + + *outstr = NULL; + if (strcmp(buf, "delta") == 0) + delta *= n[iw].delta; + + if (delta >= 0) delta = 1/(1+delta); + else delta = (1-delta); + if (n[iw].anchor >= 0) { +#ifdef USE_P3D + if (p3dp_enabled) return FALSE; +#endif + V3SUB (AX_3D[iw].x, B->BALL[n[iw].anchor].x, tmp); + V3ADDMUL (B->BALL[n[iw].anchor].x, delta, tmp, AX_3D[iw].x); + } + else { + V3SUB (AX_3D[iw].x, n[iw].hook, tmp); + V3ADDMUL (n[iw].hook, delta, tmp, AX_3D[iw].x); + } + return TRUE; +} + + +static bool proc_shift_cutting_plane(int iw, char *instr, char **outstr) +{ + double d; + + if (!instr) + goto error; + else if (strcmp(instr, CUI_ARG_REQUIRED) == 0) + instr = cui_stripspace( + gui_readline_gets(iw, "\nShift filter plane", "0.0")); + + *outstr = NULL; + buf[0] = 0; + if (sscanf(instr, " %lf %[^ ]", &d, buf) == 2) + { + if (strcmp(buf, "delta") == 0) + d *= n[iw].delta; + else + goto error; + } + return shift_filter_plane(iw, d); +error: + *outstr = "parameter error"; + return FALSE; +} + + +static bool proc_change_bgcolor(int iw, char *instr, char **outstr) +{ + double c[3]; + + *outstr = cui_show_syntax; + if (!instr) + return FALSE; + else if (strcmp(instr, CUI_ARG_REQUIRED) == 0) { + if (AX_display[iw] && !rgb_url_printed) { + printf("\nColor choices at:\n%s\n", RGB_URL); + rgb_url_printed = 1; + } + sprintf(buf, "%.3f %.3f %.3f", + n[iw].bgcolor[0], n[iw].bgcolor[1], n[iw].bgcolor[2]); + instr = cui_stripspace( + gui_readline_gets(iw,"\nChange background color",buf)); + } + + V3EQV(n[iw].bgcolor, c); + if (sscanf(instr, "%lf %lf %lf", c, c+1, c+2) < 1) + return FALSE; + *outstr = NULL; + if (c[0]>1) c[0]/=255; + if (c[1]>1) c[1]/=255; + if (c[2]>1) c[2]/=255; + if ( V3NE(c, n[iw].bgcolor) ) { + V3EQV(c, n[iw].bgcolor); + return TRUE; + } + else return FALSE; +} + +static bool proc_change_atom_r_ratio(int iw, char *instr, char **outstr) +{ + double c = 0.0; + if (!instr) + goto error; + else if (strcmp(instr, CUI_ARG_REQUIRED) == 0) + instr = cui_stripspace( + gui_readline_gets(iw, "\nChange atom r ratio", "0.0")); + + *outstr = NULL; + buf[0] = 0; + if (sscanf(instr, " %lf %[^ ]", &c, buf) == 2) + { + if (strcmp(buf, "delta") == 0) + c *= n[iw].delta; + else + goto error; + } + + if (c >= 0) { + /* change_atom_r_ratio(n[iw].atom_r_ratio*=(1+c)); */ + n[iw].atom_r_ratio*=(1+c); + change_atom_r_ratio( 1+c); + } + else { + /* change_atom_r_ratio(n[iw].atom_r_ratio/=(1-c)); */ + n[iw].atom_r_ratio/=(1-c); + change_atom_r_ratio(1./(1-c)); + } + return TRUE; + +error: + *outstr = "parameter error"; + return FALSE; +} + + +static bool proc_change_bond_radius(int iw, char *instr, char **outstr) +{ + double c = 0.0; + if (!n[iw].bond_mode) { + *outstr = NULL; + return FALSE; + } + + if (!instr) + goto error; + else if (strcmp(instr, CUI_ARG_REQUIRED) == 0) + instr = cui_stripspace( + gui_readline_gets(iw, "\nChange bond radius", "0.0")); + + *outstr = NULL; + buf[0] = 0; + if (sscanf(instr, " %lf %[^ ]", &c, buf) == 2) + { + if (strcmp(buf, "delta") == 0) + c *= n[iw].delta; + else + goto error; + } + + if (c >= 0) { + /* change_bond_radius(n[iw].bond_radius*=(1+c)); */ + n[iw].bond_radius*=(1+c); + change_bond_radius( 1+c); + } + else { + /* change_bond_radius(n[iw].bond_radius/=(1-c)); */ + n[iw].bond_radius/=(1-c); + change_bond_radius( 1-c); + } + return TRUE; + +error: + *outstr = "parameter error"; + return FALSE; +} + + +static bool proc_change_view_angle_amplification(int iw,char*instr,char**outstr) +{ + double c = 0.0; + if (!instr || !*instr) + goto error; + else if (strcmp(instr, CUI_ARG_REQUIRED) == 0) + instr = cui_stripspace(gui_readline_gets(iw, + "\nChange view angle amplification", "0.0")); + + *outstr = NULL; + buf[0] = 0; + if (sscanf(instr, " %lf %[^ ]", &c, buf) == 2) + { + if (strcmp(buf, "delta") == 0) + c *= n[iw].delta; + else + goto error; + } + + if (c >= 0) + AX_3D[iw].k *= (1+c); + else + AX_3D[iw].k /= (1-c); + return TRUE; + +error: + *outstr = "parameter error"; + return FALSE; +} + + +static bool proc_toggle_parallel_projection(int iw, char *instr, char **outstr) +{ + if (n[iw].parallel_projection) + return(parallel_to_perspective(iw)); + else + return(perspective_to_parallel(iw)); +} + + +static bool proc_toggle_bond_mode(int iw, char *instr, char **outstr) +{ + n[iw].bond_mode = !n[iw].bond_mode; + if (n[iw].bond_mode) + { + if (n[iw].bond_xtal_origin_need_update) + bond_xtal_origin_update (iw); + if (n[iw].bond_atom_color_need_update) + bond_atom_color_update (iw); + } + return (TRUE); +} + + + +static bool proc_normal_coloring(int iw, char *instr, char **outstr) +{ + *outstr = NULL; + if (instr && strcmp(instr, "original") == 0) + return assign_original_normal_color(iw); + else + return assign_normal_color(iw); +} + + +bool proc_change_atom_color(int iw, char *instr, char **outstr) +{ + int items, i; + double c[4]; + char question[MAX_FILENAME_SIZE]; + + if (!instr || sscanf(instr, " %d %[^\n]", &i, buf) != 2) { + *outstr = cui_show_syntax; + return FALSE; + } + instr = buf; + + *outstr = NULL; +#ifdef USE_P3D + if (!p3dp_enabled || p3dp_rank_grab == p3d_rank(p3dp_cell)) { +#endif + c[0] = B->BALL[i].r; + c[1] = B->BALL[i].g; + c[2] = B->BALL[i].b; + c[3] = B->BALL[i].radius / n[iw].atom_r_ratio; +#ifdef USE_P3D + } + if (p3dp_enabled) + p3d_bcast(p3dp_cell, c, 4, MPI_DOUBLE, p3dp_rank_grab); +#endif + if (strcmp(instr, CUI_ARG_REQUIRED) == 0) { + if (!rgb_url_printed) { + if (AX_display[iw]) + printf("\nColor choices at:\n%s\n", RGB_URL); + rgb_url_printed = 1; + } +#ifdef USE_P3D + if (p3dp_enabled) { + if (p3dp_rank_grab == p3d_rank(p3dp_cell)) + sprintf(question, "\nChange color [radius] of atom (\"%s\")", + COMPACT_SYMBOL(Symbol(symbol,i))); + p3d_bcast(p3dp_cell, question, + sizeof(question), MPI_CHAR, p3dp_rank_grab); + } + else +#endif + sprintf(question, "\nChange color [radius] of atom-%d (\"%s\")", + i, COMPACT_SYMBOL(Symbol(symbol,i))); + sprintf(buf, "%.3f %.3f %.3f [%.3f]", c[0], c[1], c[2], c[3]); + instr = cui_stripspace(gui_readline_gets(iw, question, buf)); + } +#ifdef USE_P3D + if (!p3dp_enabled || p3dp_rank_grab == p3d_rank(p3dp_cell)) { +#endif + items = sscanf(instr, "%lf %lf %lf %lf", c, c+1, c+2, c+3); + if (c[0] < 0 || c[1] < 0 || c[2] < 0) { + c[0] = c[1] = c[2] = -1; + c[3] = B->BALL[i].radius / n[iw].atom_r_ratio; + } + else if (items == 1) { + c[3] = c[0]; + c[0] = B->BALL[i].r; + } + else { + if (c[0]>1) c[0]/=255; + if (c[1]>1) c[1]/=255; + if (c[2]>1) c[2]/=255; + } + AX_3D_AssignRGB(B->BALL[i], c[0],c[1],c[2]); + B->BALL[i].radius = c[3] * n[iw].atom_r_ratio; +#ifdef USE_P3D + } +#endif + bond_atom_color_update(iw); + return TRUE; +} + + +bool proc_change_bond_color(int iw, char *instr, char **outstr) +{ + int items, i; + double c[4]; + char question[MAX_FILENAME_SIZE]; + + if (!instr || sscanf(instr, " %d %[^\n]", &i, buf) != 2) { + *outstr = cui_show_syntax; + return FALSE; + } + instr = buf; + + *outstr = NULL; +#ifdef USE_P3D + if (!p3dp_enabled || p3dp_rank_grab == p3d_rank(p3dp_cell)) { +#endif + c[0] = C->CYLINDER[i].r; + c[1] = C->CYLINDER[i].g; + c[2] = C->CYLINDER[i].b; + c[3] = C->CYLINDER[i].radius; +#ifdef USE_P3D + } + if (p3dp_enabled) + p3d_bcast(p3dp_cell, c, 4, MPI_DOUBLE, p3dp_rank_grab); +#endif + if (strcmp(instr, CUI_ARG_REQUIRED) == 0) { + if (!rgb_url_printed) { + if (AX_display[iw]) + printf("\nColor choices at:\n%s\n", RGB_URL); + rgb_url_printed = 1; + } +#ifdef USE_P3D + if (p3dp_enabled) + strncpy(question, + "\nChange color [radius] of bond", sizeof(question)); + else +#endif + sprintf(question, "\nChange color [radius] of bond-%d", i); + sprintf(buf, "%.3f %.3f %.3f [%.3f]", c[0], c[1], c[2], c[3]); + instr = cui_stripspace(gui_readline_gets(iw, question, buf)); + } +#ifdef USE_P3D + if (!p3dp_enabled || p3dp_rank_grab == p3d_rank(p3dp_cell)) { +#endif + items = sscanf(instr, "%lf %lf %lf %lf", c, c+1, c+2, c+3); + if (c[0] < 0 || c[1] < 0 || c[2] < 0) { + c[0] = c[3] = -1; + } + else if (items == 1) { + c[3] = c[0]; + c[0] = C->CYLINDER[i].r; + } + else { + if (c[0]>1) c[0]/=255; + if (c[1]>1) c[1]/=255; + if (c[2]>1) c[2]/=255; + } + C->CYLINDER[i].r = c[0]; + C->CYLINDER[i].g = c[1]; + C->CYLINDER[i].b = c[2]; + C->CYLINDER[i].radius = c[3]; +#ifdef USE_P3D + } +#endif + return TRUE; +} + + +bool proc_change_normal_color(int iw, char *instr, char **outstr) +{ + int t, items, z; + double c[4]; + char question[MAX_FILENAME_SIZE] = ""; + /* selection means there must be something there already */ + if (n[iw].color_mode != COLOR_MODE_NORMAL) { + *outstr = "You need to be in NORMAL color mode first."; + return FALSE; + } + else if (!instr || (sscanf(instr, " %d %[^\n]", &z, buf) != 2 && + sscanf(instr, " %s %[^\n]", question, buf) != 2)) { + *outstr = cui_show_syntax; + return FALSE; + } + if (question[0]) z = search_atom_by_symbol(question); + instr = buf; + + *outstr = NULL; + for (t = 0; t < ct->t; t++) + if (ct->Z[t] == z) break; + if (t == ct->t) { + t = -1; + c[0] = c[1] = c[2] = c[3] = 0; + } + else { + c[0] = ATOM_Color_R(ct->Z[t]); + c[1] = ATOM_Color_G(ct->Z[t]); + c[2] = ATOM_Color_B(ct->Z[t]); + c[3] = ATOM_Radius(ct->Z[t]); + } + if (strcmp(instr, CUI_ARG_REQUIRED) == 0) { + if (!rgb_url_printed) { + if (AX_display[iw]) + printf("\nColor choices at:\n%s\n", RGB_URL); + rgb_url_printed = 1; + } + sprintf(question, "\nChange color [radius] of type-%d (\"%s\") atoms", + t, atom_symbol(z)); + /*t, COMPACT_SYMBOL(Symbol(symbol,ct->first[t])));*/ + sprintf(buf, "%.3f %.3f %.3f [%.3f]", c[0], c[1], c[2], c[3]); + instr = cui_stripspace(gui_readline_gets(iw, question, buf)); + } + items = sscanf(instr, "%lf %lf %lf %lf", c, c+1, c+2, c+3); + + if (t >= 0) { + if (c[0] < 0 || c[1] < 0 || c[2] < 0) { + c[0] = c[1] = c[2] = -1; + c[3] = ATOM_Radius(ct->Z[t]); + } + else if (items == 1) { + c[3] = c[0]; + c[0] = ATOM_Color_R(ct->Z[t]); + } + else { + if (c[0]>1) c[0]/=255; + if (c[1]>1) c[1]/=255; + if (c[2]>1) c[2]/=255; + } + ATOM_Color_R(ct->Z[t]) = c[0]; + ATOM_Color_G(ct->Z[t]) = c[1]; + ATOM_Color_B(ct->Z[t]) = c[2]; + ATOM_Radius(ct->Z[t]) = c[3]; + } + return assign_normal_color(iw); +} + + +bool proc_change_coordination_color(int iw, char *instr, char **outstr) +{ + int coord; + char question[MAX_FILENAME_SIZE]; + double c[3]; + + if (!n[iw].xtal_mode) { + *outstr = "Coordination color change works only in Xtal mode."; + goto error; + } + else if (n[iw].color_mode != COLOR_MODE_COORD) { + *outstr = "You need to be in COORDINATION color mode first."; + goto error; + } + else if (!instr || sscanf(instr, " %d %[^\n]", &coord, buf) != 2) { + *outstr = cui_show_syntax; + return FALSE; + } + instr = buf; + + c[0] = CoordColor[coord].r; + c[1] = CoordColor[coord].g; + c[2] = CoordColor[coord].b; + + if (strcmp(instr, CUI_ARG_REQUIRED) == 0) { + if (!rgb_url_printed) { + if (AX_display[iw]) + printf("\nColor choices at:\n%s\n", RGB_URL); + rgb_url_printed = 1; + } + sprintf(question, "\nChange color of %d-coordinated atoms", coord); + sprintf(buf, "%.3f %.3f %.3f", c[0], c[1], c[2]); + instr = cui_stripspace(gui_readline_gets(iw, question, buf)); + } + sscanf(instr, " %lf %lf %lf", c, c+1, c+2); + + if (c[0] < 0 || c[1] < 0 || c[2] < 0) + c[0] = c[1] = c[2] = -1; + else { + if (c[0] > 1) c[0]/=255; + if (c[1] > 1) c[1]/=255; + if (c[2] > 1) c[2]/=255; + } + + CoordColor[coord].r = c[0]; + CoordColor[coord].g = c[1]; + CoordColor[coord].b = c[2]; + return assign_coordination_color(iw); + +error: + if (AX_display[iw] && !cui_xterm_win) + printf("%s\n", *outstr); + return FALSE; +} + +static int get_number(int iw, char *instr) +{ + int number = -1; + char c; + + if (!instr || !*instr) + return -1; + + if (strcmp(instr, CUI_ARG_REQUIRED) == 0) + instr = cui_stripspace(gui_readline_gets(iw, "\nNumber", "0")); + + if (sscanf(instr, "%d", &number) != 1 && + sscanf(instr, "%c", &c) == 1 && isalpha(c)) + number = c - 'a' + 10; + + return number; +} + +static bool proc_aux_property_coloring(int iw, char *instr, char **outstr) +{ + int number = get_number(iw, instr); + + if (XIN(number, 0, 33)) { + n[iw].auxiliary_idx = number; + if ( OUW(n[iw].auxiliary_idx,CONFIG_num_auxiliary) && + OUW(n[iw].auxiliary_idx-CONFIG_MAX_AUXILIARY,MAX_GEO_MEASURES) ) { + sprintf(buf,"Auxiliary %d is not available.\n",n[iw].auxiliary_idx); + *outstr = buf; + return (FALSE); + } + *outstr = NULL; + n[iw].color_mode = COLOR_MODE_AUXILIARY; + return color_encode_auxiliary(iw); + } + + *outstr = cui_show_syntax; + return FALSE; +} + +static bool proc_central_symmetry_coloring(int iw, char *instr, char **outstr) +{ + *outstr = NULL; + n[iw].auxiliary_idx = 33; + n[iw].color_mode = COLOR_MODE_AUXILIARY; + n[iw].auxiliary_threshold[n[iw].auxiliary_idx][0] = 0.00376; + n[iw].auxiliary_thresholds_rigid = 1; + color_encode_auxiliary(iw); + return TRUE ; +} + + +static bool proc_typein_auxiliary_threshold(int iw, char *instr, char **outstr) +{ + double threshold[2]; + char danswer[MAX_FILENAME_SIZE]; + + *outstr = NULL; + if (n[iw].color_mode != COLOR_MODE_AUXILIARY) + { + *outstr = "Must be in AUXILIARY color mode to change " + "auxiliary thresholds manually."; + return(FALSE); + } + else if (!instr) { + *outstr = "parameter error"; + return(FALSE); + } + + threshold[0] = n[iw].auxiliary_threshold[n[iw].auxiliary_idx][0]; + threshold[1] = n[iw].auxiliary_threshold[n[iw].auxiliary_idx][1]; + + if ((strcmp(instr, CUI_ARG_REQUIRED) == 0) || + (strlen(cui_stripspace(instr)) == 0)) { + sprintf (danswer, "%g %g", threshold[0], threshold[1]); + instr = cui_stripspace(gui_readline_gets(iw, str2( + OUW(n[iw].auxiliary_idx,CONFIG_num_auxiliary) ? + geolist[n[iw].auxiliary_idx-CONFIG_MAX_AUXILIARY].token : + CONFIG_auxiliary_name[n[iw].auxiliary_idx], " thresholds"), + danswer)); + } + sscanf (instr, "%lf %lf", threshold+0, threshold+1); + if ( (threshold[0] == n[iw].auxiliary_threshold[n[iw].auxiliary_idx][0]) && + (threshold[1] == n[iw].auxiliary_threshold[n[iw].auxiliary_idx][1]) ) + return(FALSE); + n[iw].auxiliary_threshold[n[iw].auxiliary_idx][0] = threshold[0]; + n[iw].auxiliary_threshold[n[iw].auxiliary_idx][1] = threshold[1]; + n[iw].auxiliary_thresholds_rigid = 1; + return (color_encode_auxiliary(iw)); +} + + +static bool proc_change_aux_property_threshold(int iw,char *instr,char **outstr) +{ + int idx = n[iw].auxiliary_idx, ul = 0; + double value; + + *outstr = NULL; + if (n[iw].color_mode != COLOR_MODE_AUXILIARY) + return FALSE; + + if (!instr) + goto error; + else if (strcmp(instr, CUI_ARG_REQUIRED) == 0) { + value = n[iw].auxiliary_threshold[idx][ul]; + sprintf(buf, "%d %.3f", ul, value); + instr = cui_stripspace(gui_readline_gets(iw, + "\nChange auxiliary property threshold", buf)); + } + + buf[0] = 0; + if (sscanf(instr, " %d%lf", &ul, &value) == 2 || + sscanf(instr, " %s%lf", buf, &value) == 2) { + + if (buf[0]) { + if (strcmp(buf, "lower") == 0) + ul = 0; + else if (strcmp(buf, "upper") == 0) + ul = 1; + else + goto error; + } + + if (strstr(instr, "delta")) + n[iw].auxiliary_threshold[idx][ul] + += ( n[iw].auxiliary_threshold[idx][1] - + n[iw].auxiliary_threshold[idx][0] ) + * value * n[iw].delta; + else if ((ul == 0 && value <= n[iw].auxiliary_threshold[idx][1]) || + (ul == 1 && value >= n[iw].auxiliary_threshold[idx][0])) + n[iw].auxiliary_threshold[idx][ul] = value; + else + goto error; + + if (AX_display[iw]) { + if (idx < CONFIG_num_auxiliary) + printf("Thresholds of %s = [%g, %g]%s%s.\n", + CONFIG_auxiliary_name[idx], + n[iw].auxiliary_threshold[idx][0], + n[iw].auxiliary_threshold[idx][1], + (*CONFIG_auxiliary_unit[idx]==EOS)?"":" ", + CONFIG_auxiliary_unit[idx]); + else + printf("Thresholds of %s = [%g, %g].\n", + geolist[idx-CONFIG_MAX_AUXILIARY].token, + n[iw].auxiliary_threshold[idx][0], + n[iw].auxiliary_threshold[idx][1]); + } + + return color_encode_auxiliary(iw); + } + +error: + *outstr = "parameter error"; + return FALSE; +} + + +static bool proc_reset_aux_property_thresholds(int iw,char *instr,char **outstr) +{ + *outstr = NULL; + if (n[iw].color_mode == COLOR_MODE_AUXILIARY) { + int idx = n[iw].auxiliary_idx; + reset_auxiliary_threshold(iw, idx); + if (AX_display[iw]) + printf("\nAuxiliary[%d] = %s [%s]'s thresholds have been reset:\n" + "Thresholds now = [%g, %g].\n\n", + idx, CONFIG_auxiliary_name[idx], CONFIG_auxiliary_unit[idx], + n[iw].auxiliary_threshold[idx][0], + n[iw].auxiliary_threshold[idx][1]); + return color_encode_auxiliary(iw); + } + return FALSE; +} + +static bool proc_toggle_aux_property_thresholds_saturation( + int iw, char *instr, char **outstr) +{ + *outstr = NULL; + if (n[iw].color_mode == COLOR_MODE_AUXILIARY) { + n[iw].auxiliary_thresholds_saturation = + !n[iw].auxiliary_thresholds_saturation; + return color_encode_auxiliary(iw); + } + else + return FALSE; +} + +static bool proc_toggle_aux_property_thresholds_rigid( + int iw,char *instr,char **outstr) +{ + *outstr = NULL; + if (n[iw].color_mode == COLOR_MODE_AUXILIARY) { + n[iw].auxiliary_thresholds_rigid = + !n[iw].auxiliary_thresholds_rigid; + if (AX_display[iw]) + printf("floating auxiliary thresholds flag = %s.\n", + (n[iw].auxiliary_thresholds_rigid) ? "OFF" : "ON"); + } + return FALSE; +} + + +static bool proc_rcut_patch(int iw, char *instr, char **outstr) +{ + if (!instr || !*instr) { + *outstr = cui_show_syntax; + return FALSE; + } + + *outstr = NULL; + buf[0] = 0; + sscanf(instr, " %s", buf); + if (strcmp(buf, "start") == 0 || strcmp(buf, "toggle") == 0) { + char ini[3], inj[3], *q; + int i, j, patch_Zi, patch_Zj, k, *count; + + if (rcut_patching) { + if (strcmp(buf, "toggle") == 0) + goto finish; + else { + if (AX_display[iw]) + printf( + "You haven't yet finished patching the last rcut.\n" + "Press R to submit the last item.\n"); + return FALSE; + } + } + if (rcut_patch_pairname[0] == EOS) { /* popularity contest */ + CALLOC (start_rcut_patch, count, SQUARE(ct->t), int); + for (i=0; iidx[i]; jidx[i+1]; j++) + count[ct->t*((int)tp[i])+((int)tp[N->list[j]])]++; +#ifdef USE_P3D + if (p3dp_enabled) { + int *c_l; + CALLOC(start_rcut_patch, c_l, SQUARE(ct->t), int); + for (i = 0; i < SQUARE(ct->t); i++) + c_l[i] = count[i]; + p3d_reduce(p3dp_cell, c_l, count,SQUARE(ct->t),MPI_INT,MPI_SUM); + free(c_l); + } +#endif + for (i=0; it; i++) + for (j=i+1; jt; j++) + count[ct->t*i+j] = count[ct->t*j+i] = + count[ct->t*i+j] + count[ct->t*j+i]; + for (i=j=k=0; it); i++) + if (count[i] > j) + { + j = count[i]; + k = i; + } + free (count); + i = k / ct->t; + j = k % ct->t; + sprintf (rcut_patch_pairname, "%s %s", + COMPACT_SYMBOL(ATOM_SYMBOL(ct->Z[i])), + COMPACT_SYMBOL(ATOM_SYMBOL(ct->Z[j]))); + } + if (ct->t > 1) { + if (strcmp(buf, "start") == 0) + strncpy(buf,strstr(instr,"start") +strlen("start"),sizeof(buf)); + else + strncpy(buf,strstr(instr,"toggle")+strlen("toggle"), + sizeof(buf)); + instr = cui_stripspace(buf); + if (strcmp(instr, CUI_ARG_REQUIRED) == 0) { + strncpy(buf, rcut_patch_pairname, sizeof(buf)); + instr = cui_stripspace(gui_readline_gets(iw, + "\nStart patching neighbor distance cutoff between", buf)); + } + q = (strlen(instr)) ? instr : rcut_patch_pairname; + sscanf (q, "%2s %2s", ini, inj); + SAFE_SYMBOL(ini); + SAFE_SYMBOL(inj); + patch_Zi = search_atom_by_symbol(ini); + patch_Zj = search_atom_by_symbol(inj); + } + else { + patch_Zi = patch_Zj = ct->Z[0]; + if (AX_display[iw]) + printf("\n" + "Start patching neighbor distance cutoff between %s %s:\n", + COMPACT_SYMBOL(ATOM_SYMBOL(patch_Zi)), + COMPACT_SYMBOL(ATOM_SYMBOL(patch_Zj))); + } + if (AX_display[iw]) + sprintf(rcut_patch_pairname, "%s %s", + COMPACT_SYMBOL(ATOM_SYMBOL(patch_Zi)), + COMPACT_SYMBOL(ATOM_SYMBOL(patch_Zj))); + for (k=0; k= RCUT_PATCH_MAX) { + if (AX_display[iw]) { + printf ("RCUT_PATCH_MAX = %d reached.\n", RCUT_PATCH_MAX); + printf ("Cannot add rcut patch no more.\n\n"); + } + rcut_patch_top--; + return FALSE; + } + else rcut_patching = 1; + if (AX_display[iw]) + printf ("RCUT(%s) = %g.\n", rcut_patch_pairname, + rcut_patch[rcut_patch_item].rcut); + return FALSE; + } + else if (strcmp(buf, "finish") == 0) { +finish: + if (rcut_patching) { + if (AX_display[iw]) { + printf ("RCUT(%s) = %g.\n\n", + rcut_patch_pairname, rcut_patch[rcut_patch_item].rcut); + Sfpr(stdout, "rlist = %M (reduced)\n ", N->rcut, ct->t,ct->t); + print_coordination_histogram(); cr(); + } + rcut_patching = 0; + } + return FALSE; + } + else if (rcut_patching) { + double rcut, c = 0.0; + if (strcmp(instr, CUI_ARG_REQUIRED) == 0) + instr = cui_stripspace( + gui_readline_gets(iw, "\nChange cutoff", "0.0")); + buf[0] = 0; + if (sscanf(instr, " %lf %[^ ]", &c, buf) == 2) { + if (strcmp(buf, "delta") == 0) + c *= n[iw].delta; + else { + *outstr = cui_show_syntax; + return FALSE; + } + } + rcut = rcut_patch[rcut_patch_item].rcut + c; + if (rcut < 0) + rcut = 0; + else if (c > 0) { + int i; + double thickness[DIMENSION]; + M3rowthicknesses(H, thickness); + for (i = 0; i < DIMENSION; i++) { + if (thickness[i] < 2 * rcut) { + sprintf(buf, "losing r=0&&n[iw].atom_stack[1]>=0&&n[iw].atom_stack[2]>=0){ +#if USE_P3D + if (p3dp_enabled) { + double sk[3], sj[3], si[3]; + if ( n[iw].atom_stack[2] != n[iw].atom_stack[0] || + p3dp_n[iw].rank_stack[2] != p3dp_n[iw].rank_stack[0]) { + if ( n[iw].atom_stack[0] == n[iw].atom_stack[1] && + p3dp_n[iw].rank_stack[0] == p3dp_n[iw].rank_stack[1]) { + p3dp_s(sk, n[iw].atom_stack[0], p3dp_n[iw].rank_stack[0]); + p3dp_s(si, n[iw].atom_stack[2], p3dp_n[iw].rank_stack[2]); + p3dp_atom_pair_s(sk, si, n[iw].fp[number].dx_input); + V3ADDMULMUL(0.5, sk, 0.5, si, n[iw].fp[number].s0); + } + else if ( n[iw].atom_stack[1] != n[iw].atom_stack[2] || + p3dp_n[iw].rank_stack[1] != p3dp_n[iw].rank_stack[2]) { + p3dp_s(sk, n[iw].atom_stack[0], p3dp_n[iw].rank_stack[0]); + p3dp_s(sj, n[iw].atom_stack[1], p3dp_n[iw].rank_stack[1]); + p3dp_s(si, n[iw].atom_stack[2], p3dp_n[iw].rank_stack[2]); + p3dp_atom_triplet_s(sk, sj, si, dxkj, dxij); + V3CROSS(dxkj, dxij, n[iw].fp[number].dx_input); + V3EQV(sk, n[iw].fp[number].s0); + } + } + } + else { +#endif + if ( n[iw].atom_stack[2] != n[iw].atom_stack[0]) { + if (n[iw].atom_stack[0] == n[iw].atom_stack[1]) { + atom_pair (n[iw].atom_stack[0], n[iw].atom_stack[2], + n[iw].fp[number].dx_input); + V3ADDMULMUL (0.5, &s[DIMENSION*n[iw].atom_stack[0]], + 0.5, &s[DIMENSION*n[iw].atom_stack[2]], + n[iw].fp[number].s0); + } + else if (n[iw].atom_stack[1] != n[iw].atom_stack[2]){ + atom_triplet (n[iw].atom_stack[0], n[iw].atom_stack[1], + n[iw].atom_stack[2], dxkj, dxij); + V3CROSS (dxkj, dxij, n[iw].fp[number].dx_input); + V3EQV (&s[DIMENSION*n[iw].atom_stack[0]], n[iw].fp[number].s0); + } + } +#if USE_P3D + } +#endif + } + + if (!instr || !*instr || strstr(instr, CUI_ARG_REQUIRED)) { + sprintf (danswer, "%g %g %g %g %g %g", + V3E(n[iw].fp[number].dx_input), V3E(n[iw].fp[number].s0)); + sprintf(buf, "\nCutting plane %d's dx dy dz s0 s1 s2", number); + instr = gui_readline_gets(iw, buf, danswer); + } + + if (sscanf(instr, "%lf %lf %lf %lf %lf %lf", + V3e(AX_3D[iw].fp[number].dx), V3e(n[iw].fp[number].s0)) < 3) { + *outstr = "parameter error"; + return FALSE; + } + else if (V3NEZERO(AX_3D[iw].fp[number].dx)) { + V3EQV( AX_3D[iw].fp[number].dx, n[iw].fp[number].dx_input ); + V3normalize (AX_3D[iw].fp[number].dx); + AX_3D[iw].fp[number].d0 = + V3ADOT(n[iw].fp[number].s0, H, AX_3D[iw].fp[number].dx, tmp); + *outstr = NULL; + return TRUE; + + } + else { + if (AX_display[iw]) + printf("(%g %g %g) is unacceptable as a plane normal!\n", + V3E(AX_3D[iw].fp[number].dx)); + *outstr = danswer; + return FALSE; + } +} + + +static bool proc_cutting_plane(int iw, char *instr, char **outstr) +{ + int number = get_number(iw, instr), j; + + if (!XIN(number, 0, 15)) { + *outstr = "parameter error"; + return FALSE; + } + else + *outstr = NULL; + + if (n[iw].anchor >= 0) + V3EQV(B->BALL[n[iw].anchor].x, n[iw].hook); + + if (V3EQZERO(AX_3D[iw].fp[number].dx)) { + /* not active but will be activated and focused */ + n[iw].just_activated_fp = number; + if (V3EQZERO(n[iw].fp[number].dx_cache)) { /* no cached plane normal */ + char *s = NULL; + if (instr && strcmp(instr, CUI_ARG_REQUIRED) != 0) { + s = instr; + while (*s && isspace(*s)) s++; + if (*s) { + s++; + while (*s && !isspace(*s)) s++; + } + } + return new_plane(iw, s, outstr, number); + } + else { /* there is cached plane normal */ + double tmp[3]; + V3EQV( n[iw].fp[number].dx_cache, AX_3D[iw].fp[number].dx ); + AX_3D[iw].fp[number].d0 = + V3ADOT(n[iw].fp[number].s0, H, AX_3D[iw].fp[number].dx, + tmp); + return TRUE; + } + } + else if (n[iw].just_activated_fp != number) { + /* activated but not the focus */ + n[iw].just_activated_fp = number; + /* just gain focus */ + V3EQV( AX_3D[iw].fp[number].dx, n[iw].fp[number].dx_cache ); + V3ZERO( AX_3D[iw].fp[number].dx ); + for (j=0; j= 0) + V3EQV(B->BALL[n[iw].anchor].x, n[iw].hook); + + if (V3EQZERO(AX_3D[iw].fp[number].dx)) { + /* not active but will be activated and focused */ + n[iw].just_activated_fp = number; + if (V3EQZERO(n[iw].fp[number].dx_cache)) { /* no cached plane normal */ + return FALSE; + } + else { /* there is cached plane normal */ + V3mM3 (n[iw].hook, HI, n[iw].fp[number].s0); + V3EQV( n[iw].fp[number].dx_cache, AX_3D[iw].fp[number].dx ); + AX_3D[iw].fp[number].d0 = + V3ADOT(n[iw].fp[number].s0, H, AX_3D[iw].fp[number].dx, tmp); + return TRUE; + } + } + else if (n[iw].just_activated_fp != number) { + /* activated but not the focus */ + n[iw].just_activated_fp = number; + V3mM3 (n[iw].hook, HI, n[iw].fp[number].s0); + AX_3D[iw].fp[number].d0 = + V3ADOT(n[iw].fp[number].s0, H, AX_3D[iw].fp[number].dx, tmp); + return TRUE; + } + else { + /* activated and is the focus */ + V3mM3 (n[iw].hook, HI, n[iw].fp[number].s0); + AX_3D[iw].fp[number].d0 = + V3ADOT(n[iw].fp[number].s0, H, AX_3D[iw].fp[number].dx, tmp); + return TRUE; + } + return FALSE; +} + + +static bool proc_delete_cutting_plane(int iw, char *instr, char **outstr) +{ + int number = get_number(iw, instr), j; + + if (!XIN(number, 0, 15)) { + *outstr = "parameter error"; + return FALSE; + } + else + *outstr = NULL; + + if (n[iw].anchor >= 0) + V3EQV(B->BALL[n[iw].anchor].x, n[iw].hook); + + if (V3EQZERO(AX_3D[iw].fp[number].dx)) { + /* not active but will be activated and focused */ + n[iw].just_activated_fp = number; + if (V3EQZERO(n[iw].fp[number].dx_cache)) { /* no cached plane normal */ + return FALSE; + } + else { /* there is cached plane normal */ + V3ZERO( n[iw].fp[number].dx_cache ); + for (j=0; j AX_MAXWIDTH) ? + AX_MAXWIDTH : CUI_EPS_RESOLUTION_DEFAULT; + else + new_resolution = MAX(AX_size[iw].width, AX_size[iw].height); + new_res = new_resolution; + fname = buffer+4; + if ((strcmp(danswer, CUI_ARG_REQUIRED) == 0) || + (strlen(cui_stripspace(danswer)) == 0)) { + sprintf (danswer, "%s%s %d", fbasename, buf, new_res); + answer = gui_readline_gets(iw, "\nSave screen on", danswer); + sscanf(answer, "%s %d", fname, &new_res); + } + else + sscanf(danswer, "%s %d", fname, &new_res); + if (new_res > 1) + new_resolution = new_res; + else if (new_res < -1) + new_resolution = -new_res; + if (new_resolution <= 1 || !*fname) + return FALSE; + + *outstr = NULL; + if (new_res > 0) { + if (strcasecmp(eos(fname)-4, buf)) strcat(fname, buf); + if (n[iw].color_mode == COLOR_MODE_AUXILIARY) + save_auxiliary_colormap(iw,str2(fname, ".cmap.eps")); + } + if (IS_MANAGER) + writable = (tested_to_be_writable(fname)); +#ifdef USE_P3D + if (p3dp_enabled) + p3d_bcast(p3dp_cell, &writable, 1, MPI_INT, 0); +#endif + if (writable) + { + cui_CaptureResize(iw, new_resolution, &cs); +#ifdef USE_P3D + if (p3dp_enabled) + MPI_Barrier(p3d_comm(p3dp_cell)); +#endif + if (IS_MANAGER) { + switch (buf[1]) { + case 'p': + sprintf(danswer, "image saved on \"%s\" (%d bytes)\n", fname, + AX_save_pixmap_as_PNG (iw,fname)); + break; + case 'j': + sprintf(danswer, "image saved on \"%s\" (%d bytes)\n", fname, + AX_save_pixmap_as_JPG (iw,fname)); + break; + case 'e': + sprintf(danswer, "image saved on \"%s\" (%d bytes)\n", fname, + AX_save_pixmap_as_EPS (iw,fname)); + sprintf (fname, "-geometry %dx%d+%d+%d %s", + 2*cs.old_size.width, 2*cs.old_size.height, + ZERO_RAMP(AX_root_x[iw]-cs.old_size.width), + ZERO_RAMP(AX_root_y[iw]-cs.old_size.height/2), + absolute_pathname(fname)); + break; + } + if (AX_display[iw] && !cui_xterm_win) + printf(danswer); + STRCATN(danswer, CUI_PROTOCOL_OK); + *outstr = danswer; + } + AXQueryPointer (iw); + cui_CaptureRecover(iw, &cs); + if (n[iw].shell_viewer_mode && IS_MANAGER) { + switch (buf[1]) { + case 'p': + case 'j': + sprintf (fname, "-geometry +%d+%d %s", + ZERO_RAMP(AX_root_x[iw]-AX_size[iw].width/2), + ZERO_RAMP(AX_root_y[iw]-AX_size[iw].height/4), + absolute_pathname(fname)); + try_to_runbg (NUMBER_RASTER_VIEWERS, raster_viewers, fname); + break; + case 'e': + try_to_runbg(NUMBER_POSTSCRIPT_VIEWERS, + postscript_viewers, fname); + break; + } + } + } + else + { + if (AX_display[iw]) + printf ("\n** %s: **\n""** This file is unwritable! **\n", fname); + *outstr = "file is unwritable"; + } + + cui_diligence = TRUE; + return FALSE; +} + +static bool proc_change_wireframe_mode(int iw, char *instr, char **outstr) +{ + int number = get_number(iw, instr); + + if (XIN(number, 0, 4)) { + n[iw].wireframe_mode = number; + } + else + n[iw].wireframe_mode = (n[iw].wireframe_mode+1) % 5; + + *outstr = NULL; + return TRUE; +} + + +static bool proc_change_cutting_plane_wireframe_mode +(int iw, char *instr, char **outstr) +{ + int i = n[iw].just_activated_fp; + int number = get_number(iw, instr); + + *outstr = NULL; + if (!V3NEZERO(AX_3D[iw].fp[i].dx)) + return FALSE; + + + if (XIN(number, 0, FILTER_PLANE_WIREFRAME_GRADES)) + n[iw].fp[i].wireframe_mode = number; + else + n[iw].fp[i].wireframe_mode = ( n[iw].fp[i].wireframe_mode + 1 ) % + (FILTER_PLANE_WIREFRAME_GRADES + 1 ); + + return TRUE; +} + + +static bool proc_load_config(int iw, char *instr, char **outstr) +{ + int i, j, k, old_np; + char fname[MAX_FILENAME_SIZE], oldfname[MAX_FILENAME_SIZE]; + V3 hook_s, tmp, dx; + char *old_symbol=NULL; + bool incompatible_config; + + *outstr = NULL; + if (!instr) + goto error; + else if (!*instr) + instr = config_fname; + else if (strcmp(instr, CUI_ARG_REQUIRED) == 0) + instr = cui_stripspace( + gui_readline_gets(iw, "\nLoad configuration", config_fname)); + + strcpy(oldfname, config_fname); + if (n[iw].anchor >= 0) { + /* the new configuration may not even have the atom */ + V3EQV (B->BALL[n[iw].anchor].x, n[iw].hook); + n[iw].anchor = -1; + } + /* hook_s[] is what is kept invariant */ + V3mM3 (n[iw].hook, HI, hook_s); + + strncpy(fname, instr, sizeof(fname)); + strcpy(config_fname,fname); + +#ifdef USE_P3D + if (!p3dp_enabled) { +#endif + if (!Fexists(config_fname)) { + if (AX_display[iw]) + printf("\n** %s: **\n** There is no such file! **\n", config_fname); + strcpy(config_fname, oldfname); + return FALSE; + } + if (!Freadable(config_fname)) { + if (AX_display[iw]) + printf("\n** %s: **\n** This file is unreadable! **\n", + config_fname); + strcpy(config_fname, oldfname); + return FALSE; + } +#ifdef USE_P3D + } +#endif + if (AX_display[iw]) printf("\n"); + + old_np = np; + CLONE(symbol, SYMBOL_SIZE*np, char, old_symbol); + i = CONFIG_LOAD(config_fname, Config_Aapp_to_Alib); + + for (k=0; ks_overflow_err_handler = + NEIGHBORLIST_S_OVERFLOW_ERR_HANDLER_FOLD_INTO_PBC; + else + N->s_overflow_err_handler = + NEIGHBORLIST_S_OVERFLOW_ERR_HANDLER_BOUNDING_BOX; + N->small_cell_err_handler = NEIGHBORLIST_SMALL_CELL_ERR_HANDLER_MULTIPLY; + for (i=0; it; i++) + for (j=i; jt; j++) + for (k=0; kZ[i]) && + (rcut_patch[k].Zj == ct->Z[j]) ) || + ( (rcut_patch[k].Zi == ct->Z[j]) && + (rcut_patch[k].Zj == ct->Z[i]) ) ) ) + NEIGHBOR_TABLE(N->rcut,ct,i,j) = + NEIGHBOR_TABLE(N->rcut,ct,j,i) = rcut_patch[k].rcut; + Neighborlist_Recreate (Config_Aapp_to_Alib, stdout, ct, &tp, N); + V3mM3 (hook_s, H, tmp); + V3SUB (tmp, n[iw].hook, dx); + V3EQV (tmp, n[iw].hook); + V3AdD (dx, AX_3D[iw].x); + M3InV (H, HI, volume); + lengthscale = cbrt(volume); + V3ASSIGN (0.5,0.5,0.5,tmp); + V3mM3 (tmp, H, cm); + geo_clear_has_evaluated_flags(); + evaluate_geo_measures(); Free(s1); Free(mass); + + if ( ComputeLeastSquareStrain ) + { + if (ConfigChecksum(Config_Aapp_to_Alib) != ref->checksum) { + static char buf2[CUI_LINEMAX]; + snprintf(buf2, sizeof(buf2), + "This configuration is not isoatomic with the imprinted " + "reference\n%s. Least-square strain NOT calculated.\n", + ref_fbasename); + *outstr = buf2; + fprintf(stderr, "%s", buf2); + } + else LeastSquareStrain_Append(); + } + + incompatible_config = (np != old_np) || + memcmp(symbol, old_symbol, SYMBOL_SIZE*MIN(np,old_np)); + Free(old_symbol); + + if (incompatible_config) + Config_to_3D_Balls (n[iw].atom_r_ratio); + else for (i=0; iBALL[i].x ); + + atom_xtal_origin (n[iw].xtal_origin); + if (!n[iw].auxiliary_thresholds_rigid) { + for (i=0; i100)) + { + *outstr = "quality is out of valid range ([0,100])."; + fclose(fp); + fp = NULL; + } + else if (AX_display[iw]) printf ("\nquality = %d\n", quality); + ptr = fgets(buf,SCRIPT_LINE_SIZE,fp); + } + else + quality = AX_JPG_DEF_QUALITY; + } + if (!fp) + quality = -1; + } +#ifdef USE_P3D + if (p3dp_enabled) p3d_bcast(p3dp_cell, &quality, 1, MPI_INT, 0); +#endif + if (quality < 0) + return FALSE; + + *outstr = NULL; + frames = 0; + /* If bonds are not on now, there is no need to refresh */ + temporary_disable_bond = !n[iw].bond_mode; + /* cylinder data structure during the rendering. */ + while (1) { + int count; + if (IS_MANAGER) + count = (ptr) ? strlen(buf) + 1 : -1; +#ifdef USE_P3D + if (p3dp_enabled) p3d_bcast(p3dp_cell, &count, 1, MPI_INT, 0); +#endif + if (count < 0) break; +#ifdef USE_P3D + if (p3dp_enabled) p3d_bcast(p3dp_cell, buf, count, MPI_CHAR, 0); +#endif + buf[SCRIPT_LINE_CHAR] = EOS; + sscanf (buf, "%s %s", config_fname, output); + + proc_load_config(iw, config_fname, outstr); + + paint_scene(iw); + AX_dump(iw); AX_show(iw); + if (str_caseend_with(output,".png")) + AX_save_pixmap_as_png + (iw,AX_JPG_QUALITY_TO_PNG_LEVEL(quality),output); + else if (str_caseend_with(output,".eps")) + AX_save_pixmap_as_eps(iw,quality,output); + else AX_save_pixmap_as_jpg(iw,quality,output); + frames++; + if (IS_MANAGER) + ptr = fgets(buf,SCRIPT_LINE_SIZE,fp); + } + if (IS_MANAGER) { + fclose(fp); + if (AX_display[i]) + printf("%d frames saved.\n\n", frames); + } + if (temporary_disable_bond) { + Config_to_3D_Bonds (n[iw].bond_radius); + if (n[iw].bond_mode) { + bond_xtal_origin_update (iw); + bond_atom_color_update(iw); + } + else { + n[iw].bond_xtal_origin_need_update = TRUE; + n[iw].bond_atom_color_need_update = TRUE; + } + temporary_disable_bond = 0; + } + return FALSE; +} +#undef SCRIPT_LINE_CHAR +#undef SCRIPT_LINE_SIZE + + +/* Load color/radii file for atoms */ +static bool proc_load_atom_color(int iw, char *instr, char **outstr) +{ + char fname[MAX_FILENAME_SIZE]; + FILE *fp; + int m, j, k, items; + double c[4]; + +#ifdef USE_P3D + if (p3dp_enabled) { + *outstr = "Not implemented in Parallel"; + return FALSE; + } +#endif + *outstr = NULL; + if (!instr) { + *outstr = "parameter error"; + return FALSE; + } + + if ((strcmp(instr, CUI_ARG_REQUIRED) == 0) || + (strlen(cui_stripspace(instr)) == 0)) { + sprintf (buf, "%s.usr", fbasename); + instr = gui_readline_gets(iw, "\nLoad color properties from", buf); + } + + strncpy(fname, instr, sizeof(fname)); + if (!Freadable(fname)) { + sprintf(buf, "** %s: **\n** This file is unreadable! **", fname); + *outstr = buf; + return FALSE; + } + + return( load_atom_color_from_file (iw, fname) ); +} + + +static bool proc_load_aux(int iw, char *instr, char **outstr) +{ + char fname[MAX_FILENAME_SIZE]; + FILE *fp; + int i,j,k,m; + SimpleStatistics ss; + +#ifdef USE_P3D + if (p3dp_enabled) { + *outstr = "Not implemented in Parallel"; + return FALSE; + } +#endif + *outstr = NULL; + if (!instr) { + *outstr = "parameter error"; + return FALSE; + } + else if (strcmp(instr, CUI_ARG_REQUIRED) == 0) { + sprintf (buf, "%s.aux", fbasename); + instr = gui_readline_gets(iw, "\nLoad auxiliary properties from", buf); + } + strncpy(fname, instr, sizeof(fname)); + + if (Freadable(fname)) { + fp = ropen(fname); + CONFIG_num_auxiliary = CONFIG_MAX_AUXILIARY; + for (k=0; k= np) { + sprintf(buf, "** %s has more rows than atoms **", fname); + *outstr = buf; + goto safe_exit; + } + for (i=j=0; ;) { + while ( ISNOTDIGIT(buf[i]) && (buf[i]!='.') && (buf[i]!='-') && + (buf[i]!=EOS) ) i++; + if (buf[i] == EOS) { + if (m==0) { + CONFIG_num_auxiliary = j; + if (AX_display[iw]) + printf("number of auxiliaries found = %d.\n",j); + if (j==0) goto safe_exit; + for (k=j; k= sizeof(buf)-1) { + sprintf(buf, "load_auxiliary_from_file: %s" + " line too long", fname); + *outstr = buf; + goto safe_exit; + } + if (j >= CONFIG_MAX_AUXILIARY) { + sprintf(buf, "load_auxiliary_from_file: number of " + "entries > CONFIG_MAX_AUXILIARY=%d", + CONFIG_MAX_AUXILIARY); + *outstr = buf; + goto safe_exit; + } + if (buf[k]==EOS) { + CONFIG_auxiliary[j++][m] = atof(&buf[i]); + i = k; + } + else { + buf[k] = EOS; + CONFIG_auxiliary[j++][m] = atof(&buf[i]); + i = k+1; + } + } + } + else if (m < np) { + sprintf(buf, "** premature ending of %s **", fname); + *outstr = buf; + goto safe_exit; + } + else break; + } + else { + sprintf(buf, "** %s: **\n** This file is unreadable! **", fname); + *outstr = buf; + return FALSE; + } + for (i=0; i= np)) + *outstr = "find_atom: illegal index"; + else { + n[iw].anchor = i; + print_atom(iw,i); + last_atom = i; + *outstr = NULL; + } + return FALSE; +} + + +static bool proc_resize(int iw, char *instr, char **outstr) +{ + int new_width = AX_size[iw].width, new_height = AX_size[iw].height; + + *outstr = cui_show_syntax; + if (!instr) + return FALSE; + else if (strcmp(instr, CUI_ARG_REQUIRED) == 0) { + sprintf(buf, "%d %d", new_width, new_height); + instr = cui_stripspace( + gui_readline_gets(iw, "\nInput new window width height", buf)); + } + + if (sscanf(instr, " %d %d", &new_width, &new_height) < 1) + return FALSE; + + *outstr = NULL; + if ( (new_width == 0) || (new_width > AX_MAXWIDTH) ) { + if (AX_display[iw]) + printf("width = %d, set to AX_MAXWIDTH = %d\n", + new_width, AX_MAXWIDTH); + new_width = AX_MAXWIDTH; + } + if ( (new_height==0) || (new_height > AX_MAXHEIGHT) ) { + if (AX_display[iw]) + printf("height = %d, set to AX_MAXHEIGHT = %d\n", + new_height, AX_MAXHEIGHT); + new_height = AX_MAXHEIGHT; + } + if ( (new_width < 0) || (new_height < 0) || + ( (new_width == AX_size[iw].width) && + (new_height == AX_size[iw].height) ) ) return FALSE; + AX_size[iw].width = new_width; + AX_size[iw].height = new_height; + AX_resizewindow(iw, TRUE); + cui_diligence = TRUE; + return TRUE; +} + + +static bool proc_change_aux_colormap(int iw, char *instr, char **outstr) +{ + int i; + + *outstr = NULL; + if (!instr || !*instr) + goto error; + else if (strcmp(instr, CUI_ARG_REQUIRED) == 0) { + if (AX_display[iw]) { + printf("\nPlease choose a colormap index from:\n"); + for (i=0; i= 0) && + (n[iw].atom_stack[1] >= 0) && + (n[iw].atom_stack[2] >= 0) ) { + *outstr = NULL; + printf ("\n"); + save_atoms_in_monoclinic_filter (iw); + } + else + *outstr = cui_show_syntax; + return FALSE; +} + +static bool proc_change_central_symm_neighbormax +(int iw, char *instr, char **outstr) +{ + int new_central_symm_neighbormax; + extern int central_symm_neighbormax; + + *outstr = cui_show_syntax; + if (!instr) + return FALSE; + else if (strcmp(instr, CUI_ARG_REQUIRED) == 0) { + sprintf(buf, "%d", central_symm_neighbormax); + instr = cui_stripspace( + gui_readline_gets(iw, "\ncentral_symm_neighbormax", buf)); + } + + sscanf(instr, "%d", &new_central_symm_neighbormax); + if (new_central_symm_neighbormax <= 0) + new_central_symm_neighbormax = coordination_crystal; + /* it must be an even number */ + new_central_symm_neighbormax = new_central_symm_neighbormax / 2 * 2; + if ( new_central_symm_neighbormax == central_symm_neighbormax ) + return (FALSE); + central_symm_neighbormax = new_central_symm_neighbormax; + evaluate_central_symm (geo+GEO_CENTRAL_SYMM); + n[iw].color_mode = COLOR_MODE_AUXILIARY; + n[iw].auxiliary_idx = CONFIG_MAX_AUXILIARY + GEO_CENTRAL_SYMM; + return color_encode_auxiliary(iw); +} + + +static bool proc_timer(int iw, char *instr, char **outstr) +{ + double time; + char title[CUI_LINEMAX] = "", *t = title; + int reset = 0; + + buf[0] = 0; + if (instr) { + strncpy(title, instr, sizeof title); + if (title[0] && sscanf(title, "%s", buf) && strcmp(buf, "reset") == 0) { + reset = 1; + t = cui_stripspace(strstr(title, "reset")+strlen("reset")); + } + } + + time = cui_wtime(); + if (*t) + sprintf(buf, "%s: %.3f\n"CUI_PROTOCOL_OK, t, time - cui_time); + else + sprintf(buf, "%.3f\n"CUI_PROTOCOL_OK, time - cui_time); + *outstr = buf; + if (reset) + cui_time = time; + + return FALSE; +} + + +static bool proc_isoatomic_reference_imprint(int iw, char *instr, char **outstr) +{ +#ifdef USE_P3D + if (p3dp_enabled) { + *outstr = "Not implemented in Parallel"; + return FALSE; + } +#endif + if ( (!ComputeLeastSquareStrain) || + (strcmp(ref_fbasename, fbasename)!=0) ) { + ComputeLeastSquareStrain = 1; + strcpy (ref_fbasename, fbasename); + IsoAtomicReferenceReImprint (Config_Aapp_to_Alib, ref); + snprintf(buf, sizeof(buf), "\"%s\" is now reference for least-square " + "strain calculation.\n", ref_fbasename); + } + else { + ComputeLeastSquareStrain = 0; + IsoAtomicReferenceFree (ref); + LeastSquareStrain_Free(); + strncpy(buf, "Least-square strain calculation " + "turned OFF.\n", sizeof(buf)); + } + *outstr = STRCATN(buf, CUI_PROTOCOL_OK); + return FALSE; +} + + +static bool proc_toggle_shell_viewer_mode(int iw, char *instr, char **outstr) +{ + n[iw].shell_viewer_mode = !n[iw].shell_viewer_mode; + *outstr = (n[iw].shell_viewer_mode) ? + "Shell viewer auto-invoke is turned ON.\n" CUI_PROTOCOL_OK : + "Shell viewer auto-invoke is turned OFF.\n" CUI_PROTOCOL_OK ; + return FALSE; +} + + +static bool proc_toggle_xtal_mode(int iw, char *instr, char **outstr) +{ + *outstr = NULL; + n[iw].xtal_mode = !n[iw].xtal_mode; + return FALSE; +} + + +static bool proc_lazydraw(int iw, char *instr, char **outstr) +{ + *outstr = NULL; + cui_diligence = FALSE; + return FALSE; +} + + +static bool proc_change_shear_strain_subtract_mean +(int iw, char *instr, char **outstr) +{ + *outstr = NULL; + return change_shear_strain_subtract_mean(iw); +} + + +static bool proc_open_port(int iw, char *instr, char **outstr) +{ + *outstr = NULL; + if (listen_fd < 0 && (listen_fd=socket(PF_INET, SOCK_STREAM, 0)) != -1) { + int i, port_from = CUI_PORT_FROM, port_to = CUI_PORT_TO; + struct sockaddr_in inet_address; + if (*instr == ':') + instr++; + if (sscanf(instr, " %d-%d", &port_from, &port_to) == 1) + port_to = port_from; + + memset(&inet_address, 0, sizeof(inet_address)); + inet_address.sin_family = PF_INET; + inet_address.sin_addr.s_addr = htonl(INADDR_ANY); + + for (i = port_from; i <= port_to; i++) { + inet_address.sin_port = htons(i); + if (bind(listen_fd, (struct sockaddr*)&inet_address, + sizeof(inet_address)) >= 0) { + if (listen(listen_fd, 5) < 0) { + close(listen_fd); + listen_fd = -1; + } + else { + FD_SET(listen_fd, &allset); + if (listen_fd >= maxfd_plus_1) + maxfd_plus_1 = listen_fd + 1; + } + sprintf(buf, "port: %d\n"CUI_PROTOCOL_OK, i); + *outstr = buf; + break; + } + } + } + return FALSE; +} + + +static bool proc_close_port(int iw, char *instr, char **outstr) +{ + if (listen_fd >= 0) { + int j; + close(listen_fd); + listen_fd = -1; + maxfd_plus_1 = 0; + for (j = 0; j < CUI_N_FILE; j++) { + if (cmdf[j].fp && cmdf[j].fd >= maxfd_plus_1) + maxfd_plus_1 = cmdf[j].fd + 1; + } + } + return FALSE; +} + + +static bool proc_syntax(int iw, char *instr, char **outstr) +{ + if (!instr || !*instr) + *outstr = cui_show_syntax; + else { + struct aec *aecp; + char name[CUI_LINEMAX] = "", *s; + strncpy(buf, instr, sizeof(buf)); + s = cui_stripspace(buf); + sscanf(s, " %[^ ]", name); + if ((aecp = aecp_byname(name))) { + if (aecp->syntax) + sprintf(buf, "%s%s %s", cui_show_syntax, name, aecp->syntax); + else + sprintf(buf, "%s%s", cui_show_syntax, name); + } + else { + sprintf(buf, "%sunkown command \"%s\"", cui_show_syntax, name); + } + *outstr = buf; + } + return FALSE; +} + +/* +static bool proc_subcommand(int iw, char *instr, char **outstr); +*/ + +#define AEC_NP(name) #name, proc_##name +#define AEC_EP(name, ext) #name"_"#ext, proc_##name +static struct aec atomeye_commands[] = { + {AEC_NP(nop), NULL, NULL}, + {AEC_NP(next), NULL, NULL}, + {AEC_NP(close), NULL, NULL}, {"close_window", proc_close, NULL, NULL}, + {CUI_PROTOCOL_QUIT, proc_quit, NULL, NULL}, + {AEC_NP(new), NULL, "[clone]"}, + {"clone", proc_new, "clone", NULL}, + {AEC_NP(resize), CUI_ARG_REQUIRED, "width [height]"}, + {AEC_NP(set), CUI_ARG_REQUIRED, "variable_name value"}, + {AEC_NP(save), CUI_ARG_REQUIRED, "file_name [key|both]"}, + {AEC_NP(redraw), NULL, NULL}, + {AEC_NP(lazydraw), NULL, NULL}, + {AEC_NP(key), CUI_ARG_REQUIRED, "key_string"}, + {AEC_NP(change_bgcolor), CUI_ARG_REQUIRED, "R G B"}, + {AEC_NP(toggle_parallel_projection), NULL, NULL}, + {AEC_NP(toggle_bond_mode), NULL, NULL}, + {AEC_NP(toggle_coordination_coloring), NULL, NULL}, + {AEC_NP(normal_coloring), CUI_ARG_REQUIRED, "[original]"}, + {"original_normal_coloring", proc_normal_coloring, "original", NULL}, + {AEC_NP(change_atom_color), CUI_ARG_REQUIRED, "i [r g b] [R]"}, + {AEC_NP(change_normal_color), CUI_ARG_REQUIRED, "Z|Symbol [r g b] [R]"}, + {AEC_NP(change_coordination_color), CUI_ARG_REQUIRED,"c r g b"}, + {AEC_NP(change_bond_color), CUI_ARG_REQUIRED, "i [r g b] [R]"}, + {AEC_NP(translate), CUI_ARG_REQUIRED, "axis delta"}, + {AEC_EP(translate, 0_inc), "0 1 delta", NULL}, + {AEC_EP(translate, 0_dec), "0 -1 delta", NULL}, + {AEC_EP(translate, 1_inc), "1 1 delta", NULL}, + {AEC_EP(translate, 1_dec), "1 -1 delta", NULL}, + {AEC_EP(translate, 2_inc), "2 1 delta", NULL}, + {AEC_EP(translate, 2_dec), "2 -1 delta", NULL}, + {AEC_NP(shift_xtal), CUI_ARG_REQUIRED, "axis delta"}, + {AEC_EP(shift_xtal, 0_inc), "0 1 delta", NULL}, + {AEC_EP(shift_xtal, 0_dec), "0 -1 delta", NULL}, + {AEC_EP(shift_xtal, 1_inc), "1 1 delta", NULL}, + {AEC_EP(shift_xtal, 1_dec), "1 -1 delta", NULL}, + {AEC_EP(shift_xtal, 2_inc), "2 1 delta", NULL}, + {AEC_EP(shift_xtal, 2_dec), "2 -1 delta", NULL}, + {AEC_NP(rotate), CUI_ARG_REQUIRED, "axis theta"}, + {AEC_EP(rotate, 0_inc), "0 1 delta", NULL}, + {AEC_EP(rotate, 0_dec), "0 -1 delta", NULL}, + {AEC_EP(rotate, 1_inc), "1 1 delta", NULL}, + {AEC_EP(rotate, 1_dec), "1 -1 delta", NULL}, + {AEC_EP(rotate, 2_inc), "2 1 delta", NULL}, + {AEC_EP(rotate, 2_dec), "2 -1 delta", NULL}, + {AEC_NP(advance), CUI_ARG_REQUIRED, "delta"}, + {AEC_EP(advance, inc), " 1 delta", NULL}, + {AEC_EP(advance, dec), "-1 delta", NULL}, + {AEC_NP(shift_cutting_plane), CUI_ARG_REQUIRED, NULL}, + {AEC_EP(shift_cutting_plane, inc), " .33333333 delta", NULL}, + {AEC_EP(shift_cutting_plane, dec), "-.33333333 delta", NULL}, + {AEC_NP(change_view_angle_amplification), CUI_ARG_REQUIRED, NULL}, + {AEC_EP(change_view_angle_amplification, inc), " 1 delta", NULL}, + {AEC_EP(change_view_angle_amplification, dec), "-1 delta", NULL}, + {AEC_NP(change_atom_r_ratio), CUI_ARG_REQUIRED, NULL}, + {AEC_EP(change_atom_r_ratio, inc), " 1 delta", NULL}, + {AEC_EP(change_atom_r_ratio, dec), "-1 delta", NULL}, + {AEC_NP(change_bond_radius), CUI_ARG_REQUIRED, NULL}, + {AEC_EP(change_bond_radius, inc), " 1 delta", NULL}, + {AEC_EP(change_bond_radius, dec), "-1 delta", NULL}, + {AEC_NP(change_aux_colormap), CUI_ARG_REQUIRED, "number|prev|next"}, + {AEC_EP(change_aux_colormap, prev), "prev", NULL}, + {AEC_EP(change_aux_colormap, next), "next", NULL}, + {AEC_NP(aux_property_coloring), CUI_ARG_REQUIRED, "number"}, + {AEC_EP(aux_property_coloring, 0), " 0", NULL}, + {AEC_EP(aux_property_coloring, 1), " 1", NULL}, + {AEC_EP(aux_property_coloring, 2), " 2", NULL}, + {AEC_EP(aux_property_coloring, 3), " 3", NULL}, + {AEC_EP(aux_property_coloring, 4), " 4", NULL}, + {AEC_EP(aux_property_coloring, 5), " 5", NULL}, + {AEC_EP(aux_property_coloring, 6), " 6", NULL}, + {AEC_EP(aux_property_coloring, 7), " 7", NULL}, + {AEC_EP(aux_property_coloring, 8), " 8", NULL}, + {AEC_EP(aux_property_coloring, 9), " 9", NULL}, + {AEC_EP(aux_property_coloring, 10), "10", NULL}, + {AEC_EP(aux_property_coloring, 11), "11", NULL}, + {AEC_EP(aux_property_coloring, 12), "12", NULL}, + {AEC_EP(aux_property_coloring, 13), "13", NULL}, + {AEC_EP(aux_property_coloring, 14), "14", NULL}, + {AEC_EP(aux_property_coloring, 15), "15", NULL}, + {AEC_EP(aux_property_coloring, 16), "16", NULL}, + {AEC_EP(aux_property_coloring, 17), "17", NULL}, + {AEC_EP(aux_property_coloring, 18), "18", NULL}, + {AEC_EP(aux_property_coloring, 19), "19", NULL}, + {AEC_EP(aux_property_coloring, 20), "20", NULL}, + {AEC_EP(aux_property_coloring, 21), "21", NULL}, + {AEC_EP(aux_property_coloring, 22), "22", NULL}, + {AEC_EP(aux_property_coloring, 23), "23", NULL}, + {AEC_EP(aux_property_coloring, 24), "24", NULL}, + {AEC_EP(aux_property_coloring, 25), "25", NULL}, + {AEC_EP(aux_property_coloring, 26), "26", NULL}, + {AEC_EP(aux_property_coloring, 27), "27", NULL}, + {AEC_EP(aux_property_coloring, 28), "28", NULL}, + {AEC_EP(aux_property_coloring, 29), "29", NULL}, + {AEC_EP(aux_property_coloring, 30), "30", NULL}, + {AEC_EP(aux_property_coloring, 31), "31", NULL}, + {"shear_strain_coloring", proc_aux_property_coloring, "32", NULL}, + {AEC_NP(central_symmetry_coloring), NULL, NULL}, + {AEC_EP(aux_property_coloring, a), "10", NULL}, /* obsolete */ + {AEC_EP(aux_property_coloring, b), "11", NULL}, /* obsolete */ + {AEC_EP(aux_property_coloring, c), "12", NULL}, /* obsolete */ + {AEC_EP(aux_property_coloring, d), "13", NULL}, /* obsolete */ + {AEC_EP(aux_property_coloring, e), "14", NULL}, /* obsolete */ + {AEC_EP(aux_property_coloring, f), "15", NULL}, /* obsolete */ + {AEC_EP(aux_property_coloring, g), "32", NULL}, /* obsolete */ + {AEC_EP(aux_property_coloring, h), "33", NULL}, /* obsolete */ + {AEC_NP(typein_auxiliary_threshold), CUI_ARG_REQUIRED, "[lb ub]"}, + {AEC_NP(change_aux_property_threshold), CUI_ARG_REQUIRED, NULL}, + {AEC_EP(change_aux_property_threshold, lower_inc), "0 1 delta", NULL}, + {AEC_EP(change_aux_property_threshold, lower_dec), "0 -1 delta", NULL}, + {AEC_EP(change_aux_property_threshold, upper_inc), "1 1 delta", NULL}, + {AEC_EP(change_aux_property_threshold, upper_dec), "1 -1 delta", NULL}, + {AEC_NP(reset_aux_property_thresholds), NULL, NULL}, + {AEC_NP(toggle_aux_property_thresholds_saturation), NULL, NULL}, + {AEC_NP(toggle_aux_property_thresholds_rigid), NULL, NULL}, + /*{AEC_NP(select_gear), CUI_ARG_REQUIRED, "number"},*/ + {AEC_EP(select_gear, 0), "0", NULL}, + {AEC_EP(select_gear, 1), "1", NULL}, + {AEC_EP(select_gear, 2), "2", NULL}, + {AEC_EP(select_gear, 3), "3", NULL}, + {AEC_EP(select_gear, 4), "4", NULL}, + {AEC_EP(select_gear, 5), "5", NULL}, + {AEC_EP(select_gear, 6), "6", NULL}, + {AEC_EP(select_gear, 7), "7", NULL}, + {AEC_EP(select_gear, 8), "8", NULL}, + {AEC_EP(select_gear, 9), "9", NULL}, + {AEC_NP(cutting_plane), CUI_ARG_REQUIRED, NULL}, + {AEC_EP(cutting_plane, 0), " 0 " CUI_ARG_REQUIRED, NULL}, + {AEC_EP(cutting_plane, 1), " 1 " CUI_ARG_REQUIRED, NULL}, + {AEC_EP(cutting_plane, 2), " 2 " CUI_ARG_REQUIRED, NULL}, + {AEC_EP(cutting_plane, 3), " 3 " CUI_ARG_REQUIRED, NULL}, + {AEC_EP(cutting_plane, 4), " 4 " CUI_ARG_REQUIRED, NULL}, + {AEC_EP(cutting_plane, 5), " 5 " CUI_ARG_REQUIRED, NULL}, + {AEC_EP(cutting_plane, 6), " 6 " CUI_ARG_REQUIRED, NULL}, + {AEC_EP(cutting_plane, 7), " 7 " CUI_ARG_REQUIRED, NULL}, + {AEC_EP(cutting_plane, 8), " 8 " CUI_ARG_REQUIRED, NULL}, + {AEC_EP(cutting_plane, 9), " 9 " CUI_ARG_REQUIRED, NULL}, + {AEC_EP(cutting_plane, a), "10 " CUI_ARG_REQUIRED, NULL}, + {AEC_EP(cutting_plane, b), "11 " CUI_ARG_REQUIRED, NULL}, + {AEC_EP(cutting_plane, c), "12 " CUI_ARG_REQUIRED, NULL}, + {AEC_EP(cutting_plane, d), "13 " CUI_ARG_REQUIRED, NULL}, + {AEC_EP(cutting_plane, e), "14 " CUI_ARG_REQUIRED, NULL}, + {AEC_EP(cutting_plane, f), "15 " CUI_ARG_REQUIRED, NULL}, + /*{AEC_NP(shift_cutting_plane_to_anchor), CUI_ARG_REQUIRED},*/ + {AEC_EP(shift_cutting_plane_to_anchor, 0), " 0", NULL}, + {AEC_EP(shift_cutting_plane_to_anchor, 1), " 1", NULL}, + {AEC_EP(shift_cutting_plane_to_anchor, 2), " 2", NULL}, + {AEC_EP(shift_cutting_plane_to_anchor, 3), " 3", NULL}, + {AEC_EP(shift_cutting_plane_to_anchor, 4), " 4", NULL}, + {AEC_EP(shift_cutting_plane_to_anchor, 5), " 5", NULL}, + {AEC_EP(shift_cutting_plane_to_anchor, 6), " 6", NULL}, + {AEC_EP(shift_cutting_plane_to_anchor, 7), " 7", NULL}, + {AEC_EP(shift_cutting_plane_to_anchor, 8), " 8", NULL}, + {AEC_EP(shift_cutting_plane_to_anchor, 9), " 9", NULL}, + {AEC_EP(shift_cutting_plane_to_anchor, a), "10", NULL}, + {AEC_EP(shift_cutting_plane_to_anchor, b), "11", NULL}, + {AEC_EP(shift_cutting_plane_to_anchor, c), "12", NULL}, + {AEC_EP(shift_cutting_plane_to_anchor, d), "13", NULL}, + {AEC_EP(shift_cutting_plane_to_anchor, e), "14", NULL}, + {AEC_EP(shift_cutting_plane_to_anchor, f), "15", NULL}, + /*{AEC_NP(delete_cutting_plane), CUI_ARG_REQUIRED, NULL},*/ + {AEC_EP(delete_cutting_plane, 0), " 0 " CUI_ARG_REQUIRED, NULL}, + {AEC_EP(delete_cutting_plane, 1), " 1 " CUI_ARG_REQUIRED, NULL}, + {AEC_EP(delete_cutting_plane, 2), " 2 " CUI_ARG_REQUIRED, NULL}, + {AEC_EP(delete_cutting_plane, 3), " 3 " CUI_ARG_REQUIRED, NULL}, + {AEC_EP(delete_cutting_plane, 4), " 4 " CUI_ARG_REQUIRED, NULL}, + {AEC_EP(delete_cutting_plane, 5), " 5 " CUI_ARG_REQUIRED, NULL}, + {AEC_EP(delete_cutting_plane, 6), " 6 " CUI_ARG_REQUIRED, NULL}, + {AEC_EP(delete_cutting_plane, 7), " 7 " CUI_ARG_REQUIRED, NULL}, + {AEC_EP(delete_cutting_plane, 8), " 8 " CUI_ARG_REQUIRED, NULL}, + {AEC_EP(delete_cutting_plane, 9), " 9 " CUI_ARG_REQUIRED, NULL}, + {AEC_EP(delete_cutting_plane, a), "10 " CUI_ARG_REQUIRED, NULL}, + {AEC_EP(delete_cutting_plane, b), "11 " CUI_ARG_REQUIRED, NULL}, + {AEC_EP(delete_cutting_plane, c), "12 " CUI_ARG_REQUIRED, NULL}, + {AEC_EP(delete_cutting_plane, d), "13 " CUI_ARG_REQUIRED, NULL}, + {AEC_EP(delete_cutting_plane, e), "14 " CUI_ARG_REQUIRED, NULL}, + {AEC_EP(delete_cutting_plane, f), "15 " CUI_ARG_REQUIRED, NULL}, + {AEC_NP(flip_cutting_plane), NULL, NULL}, + {AEC_NP(change_cutting_plane_wireframe_mode), NULL, NULL}, + {AEC_NP(change_wireframe_mode), NULL, NULL}, + {AEC_NP(capture), CUI_ARG_REQUIRED, "png|jpg|eps [file_name [res]]"}, + {"capture_png", proc_capture, "png " CUI_ARG_REQUIRED, "[file_name [res]]"}, + {"capture_jpg", proc_capture, "jpg " CUI_ARG_REQUIRED, "[file_name [res]]"}, + {"capture_eps", proc_capture, "eps " CUI_ARG_REQUIRED, "[file_name [res]]"}, + + {AEC_NP(load_config), CUI_ARG_REQUIRED, NULL}, + {"reload_config", proc_load_config, "", NULL}, + /*{AEC_NP(load_config_advance), CUI_ARG_REQUIRED, NULL},*/ + {"load_config_forward", proc_load_config_advance, "forward", NULL}, + {"load_config_backward",proc_load_config_advance, "backward", NULL}, + {"load_config_first", proc_load_config_advance, "first", NULL}, + {"load_config_last", proc_load_config_advance, "last", NULL}, + {AEC_NP(script_animate), CUI_ARG_REQUIRED, NULL}, + {AEC_NP(load_atom_color),CUI_ARG_REQUIRED, "[file_name]"}, + {AEC_NP(load_aux), CUI_ARG_REQUIRED, NULL}, + + {AEC_NP(look_at_the_anchor), NULL, NULL}, + {"reset_anchor", proc_look_at_the_anchor, "reset", NULL}, + {"viewframe_upright", proc_look_at_the_anchor, "upright", NULL}, + {AEC_NP(observer_goto), CUI_ARG_REQUIRED, "s0 s1 s2"}, + {AEC_NP(xtal_origin_goto), CUI_ARG_REQUIRED, "s0 s1 s2"}, + {"xtal_origin_zero", proc_xtal_origin_goto, "0 0 0", NULL}, + {AEC_NP(find_atom), CUI_ARG_REQUIRED, "i"}, + + {AEC_NP(rcut_patch), CUI_ARG_REQUIRED, "start symbol symbol" + "|finish|value [delta]"}, + {AEC_EP(rcut_patch, inc), " 1 delta", NULL}, + {AEC_EP(rcut_patch, dec), "-1 delta", NULL}, + {AEC_NP(start_rcut_patch), CUI_ARG_REQUIRED, "symbol symbol"}, + {AEC_NP(toggle_rcut_patch_mode),CUI_ARG_REQUIRED, NULL}, + {AEC_NP(finish_rcut_patch), NULL, NULL}, + + /*{AEC_NP(print_atom_info), CUI_ARG_REQUIRED, "pair|triplet|quartet"},*/ + {AEC_EP(print_atom_info, pair), "pair", NULL}, + {AEC_EP(print_atom_info, triplet), "triplet", NULL}, + {AEC_EP(print_atom_info, quartet), "quartet", NULL}, + + {AEC_NP(save_atom_indices), NULL, NULL}, + + {AEC_NP(timer), CUI_ARG_REQUIRED, "[reset] title"}, + {"reset_timer", proc_timer, "reset " CUI_ARG_REQUIRED, "title"}, + + {AEC_NP(toggle_shell_viewer_mode), NULL, NULL}, + {AEC_NP(toggle_xtal_mode), NULL, NULL}, + + {AEC_NP(syntax), CUI_ARG_REQUIRED, "commandname"}, + + {AEC_NP(change_shear_strain_subtract_mean), NULL, NULL}, + {AEC_NP(change_central_symm_neighbormax), CUI_ARG_REQUIRED, "num"}, + + {AEC_NP(isoatomic_reference_imprint), NULL, NULL}, + + {AEC_NP(scratch_coloring), NULL, NULL}, + {AEC_NP(reset_scratch), CUI_ARG_REQUIRED, "n1 n2 n3"}, + {AEC_NP(free_scratch), NULL, NULL}, + + {AEC_NP(load_script), CUI_ARG_REQUIRED, "scriptfile"}, + {"disconnect", proc_internal_error, NULL, NULL}, + {"end", proc_internal_error, NULL, NULL}, + {"pause", proc_internal_error, NULL, NULL}, + + {AEC_NP(open_port), CUI_ARG_REQUIRED, "[port]"}, + {AEC_NP(close_port), NULL, NULL}, + + {NULL, NULL, NULL, NULL}, +}; + + + +static struct aec *aecp_byname(char *name) +{ + struct aec *aecp; + if (name && *name) + for (aecp = atomeye_commands; aecp->name; aecp++) + if (strcmp(name, aecp->name) == 0) + return aecp; + return NULL; +} + +#define DEFAULTKEY(gktp, str, entry) \ + do { struct aec *aecp;\ + if (gktp->str && *gktp->str) \ + if ((aecp = aecp_byname(gktp->str)))\ + gktp->entry = aecp;\ + else {\ + fprintf(stderr, "unknown name \"%s\"\n", gktp->str);\ + exit(1);\ + }\ + else\ + if ((aecp = aecp_byname("nop")))\ + gktp->entry = aecp;\ + else {\ + fprintf(stderr, "unknown name \"nop\"\n");\ + exit(1);\ + }\ + } while (0) + +static void gui_defaultkey(void) +{ + struct gkt *gktp; + for (gktp = gui_key_table; gktp->keysym != NoSymbol; gktp++) { + DEFAULTKEY(gktp, n, normal); + DEFAULTKEY(gktp, s, shift); + DEFAULTKEY(gktp, c, ctrl); + DEFAULTKEY(gktp, cs, ctrl_shift); + DEFAULTKEY(gktp, m, meta); + DEFAULTKEY(gktp, ms, meta_shift); + } +} + + + +bool cui_treatevent(int iw) +{ + bool result = FALSE; + static int firsttime = 1; + + if (firsttime && IS_MANAGER) { + firsttime = 0; + if (frontend >= 0) { + rl_initialize(); + rl_redisplay(); + } + else if (cui_stdin) + cui_send(CUI_PROTOCOL_OK, stdout); + } + + if (quit) { + char *outstr; + proc_close(iw, NULL, &outstr); + } + else if (iw == cui_iw) { + char *line = cmdline; + int len, i = 0; + struct timeval timeout = CUI_TIMEOUT; + fd_set rfds = allset; + if (IS_MANAGER) { + for (i = 0; i < CUI_N_FILE; i++) { + if (cmdf[i].fp && cmdf[i].pause) { + if (cmdf[i].pause > 0.0) { + if (cmdf[i].pause < cui_wtime()) { + cmdf[i].pause = 0.0; + continue; + } + } + FD_CLR(cmdf[i].fd, &rfds); + } + } + + select(maxfd_plus_1, &rfds, NULL, NULL, &timeout); + + len = 0; + for (i = 0; i < CUI_N_FILE; i++) { + if (cmdf[i].fp && FD_ISSET(cmdf[i].fd, &rfds)) { + cmdline[0] = 0; + if (cmdf[i].fd == frontend) + rl_callback_read_char(); + else if (!fgets(cmdline, sizeof(cmdline), cmdf[i].fp)) { + cmdfclose(i); + cmdline[0] = 0; + } + if ((len = strlen(line = cui_stripspace(cmdline)))) + break; + } + } + if (len > 0 && cmdf[i].fd == frontend) + fputc('\r', stdout); + } +#ifdef USE_P3D + if (p3dp_enabled) { + if (quit) + len = -1; + p3d_bcast(p3dp_cell, &len, 1, MPI_INT, 0); + if (len > 0) + p3d_bcast(p3dp_cell, line, len+1, MPI_CHAR, 0); + else if (len < 0) + quit = 1; + else + usleep(80000); + } +#endif + if (len > 0) { + struct aec *aecp; + char *outstr = "parameter error"; + + if (!line || !*line) return FALSE; + + outstr = NULL; + buf[0] = 0; + sscanf(line, "%s", buf); + + if (buf[0] == '#') { + } + else if (strcmp(buf,"end") == 0 || strcmp(buf,"disconnect") == 0) { + if (IS_MANAGER) + cmdfclose(i); +#ifdef USE_P3D + if (p3dp_enabled) + p3d_bcast(p3dp_cell, &quit, 1, MPI_INT, 0); +#endif + } + else if (strncmp(buf, "pause", strlen("pause")) == 0) { + if (IS_MANAGER) { + double seconds = 0; + if (sscanf(line,"pause %lf",&seconds) == 1 && seconds >= 0) + cmdf[i].pause = cui_wtime() + seconds; + else + outstr = "parameter error"; + } + } + else if ((aecp = aecp_byname(buf))) { + char args[CUI_LINEMAX] = "", *instr = aecp->instr; + if (strcmp(aecp->name, "load_script") == 0) { + strncpy(fname, CUI_SCRIPT_DEFAULT, sizeof(fname)); + sscanf(line + strlen(aecp->name), " %s", fname); + sprintf(args, "%s %d", fname, i); + instr = args; + } + else if (instr) { + char *s = cui_stripspace(line + strlen(aecp->name)); + if (strcmp(instr, CUI_ARG_REQUIRED) == 0) + instr = s; + else if (strstr(instr, CUI_ARG_REQUIRED)) { + strncpy(args, instr, sizeof(args)); + *strstr(args, CUI_ARG_REQUIRED) = 0; + instr = STRCATN(args, s); + } + } + result = (*aecp->proc)(cui_iw, instr, &outstr); + if (outstr) { + if (!*outstr) + outstr = NULL; + else if (outstr == cui_show_syntax && aecp->syntax) { + sprintf(buf, "%s%s %s", + cui_show_syntax, aecp->name, aecp->syntax); + outstr = buf; + } + } + } + else + outstr = "unknown command"; + + if (IS_MANAGER && cmdf[i].writable) { + int j = cui_send_result(outstr, cmdf[i].fp); + char *s; + if (cmdf[i].fd == frontend) { + if (j == 0 && *(s = cui_stripspace(cmdline))) + add_history(cmdline); + rl_initialize(); + rl_redisplay(); + } + } + } + if (IS_MANAGER && listen_fd >= 0 && FD_ISSET(listen_fd, &rfds)) { + struct sockaddr_in inet_address; + int j, fd; + socklen_t l; + if ((fd=accept(listen_fd,(struct sockaddr*)&inet_address,&l)) == -1) + fprintf(stderr, "inet: accept\n"); + else if ((j = cmdfdopen(fd, "r+", -1)) == -1) { + strncpy(buf, "open failed\n", sizeof(buf)); + write(fd, buf, strlen(buf)); + close(fd); + } + else { + cui_send(CUI_GREETINGS, cmdf[j].fp); + cui_send(CUI_PROTOCOL_OK, cmdf[j].fp); + } + } + } + else { + struct timeval timeout = CUI_TIMEOUT; + select(0, NULL, NULL, NULL, &timeout); + } + return result; +} + + +bool gui_treatevent(int iw) +{ + int i=0; + bool pointer_in_window; + AXSize newsize; + static int WindowUnMapped[AX_MAXWIN] = {0}; + pointer_in_window = AXQueryPointer(iw); + switch (AX_event[iw].type) + { + case UnmapNotify: + for (i=0; ictrl_shift; + else aecp = gktp->ctrl; + else if (AXLOCK(iw) || AXMETA(iw)) + if (AXShft(iw)) aecp = gktp->meta_shift; + else aecp = gktp->meta; + else + if (AXShft(iw)) aecp = gktp->shift; + else aecp = gktp->normal; + if (aecp->proc && *aecp->proc) { + bool result = (*aecp->proc)(iw, aecp->instr, &outstr); + if (IS_MANAGER && outstr && *outstr && frontend >= 0) + cui_send_result(outstr, stdin); + return result; + } + } + return FALSE; + } + case ButtonPress: +#ifdef USE_P3D + p3dp_bcast_int2(&AX_win_x[iw], &AX_win_y[iw]); +#endif + if (AXPRESSBTN(iw) == 4) { + if (AXSHFT(iw) && n[iw].xtal_mode) + if (AXCTRL(iw)) return(xtal_shift(iw, 2, -3*n[iw].delta)); + else return(xtal_shift(iw, 2, -n[iw].delta)); + else + if (AXCTRL(iw)) return(advance(iw, 5*n[iw].delta)); + else return(advance(iw, n[iw].delta)); + } + else if (AXPRESSBTN(iw) == 5) { + if (AXSHFT(iw) && n[iw].xtal_mode) + if (AXCTRL(iw)) return(xtal_shift(iw, 2, 3*n[iw].delta)); + else return(xtal_shift(iw, 2, n[iw].delta)); + else + if (AXCTRL(iw)) return(advance(iw, -5*n[iw].delta)); + else return(advance(iw, -n[iw].delta)); + } + else if ( (AXPRESSBTN(iw) == 2) || (AXPRESSBTN(iw) == 3) || + (AXBTNTIME(iw) - n[iw].last_button_press_time < + DEFAULT_DBLECLICK_IN_MS) || AXCTRL(iw) || + AXLOCK(iw) || AXMETA(iw) ) { + char instr[CUI_LINEMAX], *outstr; +#ifdef USE_P3D + if (p3dp_enabled) + i = p3dp_AX_3D_Balls_Zgrab( + iw, B, AX_win_x[iw], AX_win_y[iw], &p3dp_rank_grab); + else +#endif + i = AX_3D_Balls_Zgrab(iw, B, AX_win_x[iw], AX_win_y[iw]); + if (i >= 0) { +#ifdef USE_P3D + if (p3dp_enabled) + p3dp_atom_stack_insert(iw, i, p3dp_rank_grab); + else +#endif + atom_stack_insert (iw, i); + if (AXCTRL(iw) && AXSHFT(iw)) { + if (n[iw].color_mode == COLOR_MODE_NORMAL) { + int z; +#ifdef USE_P3D + if (!p3dp_enabled || + p3dp_rank_grab == p3d_rank(p3dp_cell)) +#endif + z = ct->Z[(int)tp[i]]; +#ifdef USE_P3D + if (p3dp_enabled) + p3d_bcast(p3dp_cell, &z, 1, MPI_INT, + p3dp_rank_grab); +#endif + + sprintf(instr, "%d %s", z, + (AXPRESSBTN(iw)!=1)?"-1":CUI_ARG_REQUIRED); + return proc_change_normal_color(iw, instr, &outstr); + } + else if (n[iw].color_mode == COLOR_MODE_COORD) { + int coord; +#ifdef USE_P3D + if (!p3dp_enabled || + p3dp_rank_grab == p3d_rank(p3dp_cell)) +#endif + coord = coordination[i]; +#ifdef USE_P3D + if (p3dp_enabled) + p3d_bcast(p3dp_cell, &coord, 1, MPI_INT, + p3dp_rank_grab); +#endif + sprintf(instr, "%d %s", coord, + (AXPRESSBTN(iw)!=1)?"-1":CUI_ARG_REQUIRED); + return proc_change_coordination_color(iw, instr, + &outstr); + } + } + else if ( AXLOCK(iw) || AXMETA(iw) ) { + sprintf(instr, "%d %s", i, + (AXPRESSBTN(iw)!=1)?"-1":CUI_ARG_REQUIRED); + return proc_change_atom_color(iw, instr, &outstr); + } + else if ( (AXPRESSBTN(iw) != 1) || AXCTRL(iw) ) { +#ifdef USE_P3D + if (p3dp_enabled) { + if (p3d_rank(p3dp_cell) == p3dp_rank_grab) + V3EQV(B->BALL[i].x, n[iw].hook); + p3d_bcast(p3dp_cell, + n[iw].hook, 3, MPI_DOUBLE, p3dp_rank_grab); + } + else +#endif + n[iw].anchor = i; +/* +#ifdef USE_P3D + if (p3dp_enabled) + p3dp_atom_stack_insert(iw, i, p3dp_rank_grab); + else +#endif + atom_stack_insert (iw, i); +*/ + } +#ifdef USE_P3D + if (!p3dp_enabled || p3d_rank(p3dp_cell) == p3dp_rank_grab) +#endif + print_atom (iw,i); + } + else if (n[iw].bond_mode) + { +#ifdef USE_P3D + if (p3dp_enabled) + i = p3dp_AX_3D_Cylinders_Zgrab( + iw, C, AX_win_x[iw],AX_win_y[iw], &p3dp_rank_grab); + else +#endif + i = AX_3D_Cylinders_Zgrab(iw, C, AX_win_x[iw],AX_win_y[iw]); + if (i >= 0) + { + if ( AXLOCK(iw) || AXMETA(iw) ) { + sprintf(instr, "%d %s", i, + (AXPRESSBTN(iw)!=1)?"-1":CUI_ARG_REQUIRED); + return proc_change_bond_color(iw, instr, &outstr); + } +#ifdef USE_P3D + if (!p3dp_enabled||p3d_rank(p3dp_cell)==p3dp_rank_grab) +#endif + print_bond(iw,i); + if ( (AXPRESSBTN(iw) != 1) || AXCTRL(iw) ) + { + n[iw].anchor = -1; +#ifdef USE_P3D + if (!p3dp_enabled || + p3d_rank(p3dp_cell) == p3dp_rank_grab) +#endif + hook_to_cylinder(i, n[iw].hook); +#ifdef USE_P3D + if (p3dp_enabled) + p3d_bcast(p3dp_cell, + n[iw].hook, 3, MPI_DOUBLE, p3dp_rank_grab); +#endif + } + } + } + n[iw].lx = AX_win_x[iw]; + n[iw].ly = AX_win_y[iw]; + return (FALSE); + } + else + { + n[iw].lx = AX_win_x[iw]; + n[iw].ly = AX_win_y[iw]; + n[iw].last_button_press_time = AXBTNTIME(iw); + return (FALSE); + } + case MotionNotify: +#ifdef USE_P3D + p3dp_bcast_int2(&AX_win_x[iw], &AX_win_y[iw]); +#endif + if (AXMOTIONBTN2(iw) || AXMOTIONBTN3(iw)) + return( pointer_advance(iw, AX_win_x[iw], AX_win_y[iw]) ); + else if (AXMOTIONBTN1(iw)) + { + if (AXSHFT(iw) && n[iw].xtal_mode) + return( pointer_xtal_shift + (iw, AX_win_x[iw], AX_win_y[iw]) ); + else if (AXCTRL(iw) || AXSHFT(iw)) + return( pointer_translate + (iw, AX_win_x[iw], AX_win_y[iw]) ); + else return( pointer_rotate(iw, AX_win_x[iw], AX_win_y[iw]) ); + } + case Expose: + AXGetGeometry (iw, newsize); + if ( (newsize.width != AX_size[iw].width) || + (newsize.height != AX_size[iw].height) ) + { + /* there is a 4-byte alignment requirement for shm pixmap */ + /* in 16-bit graphics, therefore width must be even. */ + AX_size[iw] = newsize; + if (AX_size[iw].width & 1) AX_size[iw].width++; + AX_resizewindow(iw,False); + n[iw].mgs_radius = DEFAULT_MGS_RATIO * + sqrt((double)AX_size[iw].width*AX_size[iw].height/PI); + return (TRUE); + } + return (TRUE); + default: return (FALSE); + } +} /* end treatevent() */ + + +int cui_config_load_A3(Alib_Declare_Config) +{ + int i; + double mul = 1.15; + M3 h = {{28.83722875,0.,0.}, {0.,23.069783,0.}, {0.,0.,9.0782}}; + struct cfg { + char sym[3]; + V3 s; + } sample[] = { + {"Au",{0.1000,0.3250,0.3631}}, {"Au",{0.1000,0.4500,0.3631}}, + {"Au",{0.1000,0.5750,0.3631}}, {"Au",{0.1000,0.7000,0.3631}}, + {"Au",{0.1000,0.8250,0.3631}}, {"Au",{0.2000,0.2000,0.3631}}, + {"Au",{0.2000,0.5750,0.3631}}, {"Au",{0.3000,0.2000,0.3631}}, + {"Au",{0.3000,0.5750,0.3631}}, {"Au",{0.4000,0.3250,0.3631}}, + {"Au",{0.4000,0.4500,0.3631}}, {"Au",{0.4000,0.5750,0.3631}}, + {"Au",{0.4000,0.7000,0.3631}}, {"Au",{0.4000,0.8250,0.3631}}, + {"Au",{0.6000,0.2000,0.3631}}, {"Au",{0.6000,0.7000,0.3631}}, + {"Au",{0.7000,0.2000,0.3631}}, {"Au",{0.7000,0.4500,0.3631}}, + {"Au",{0.7000,0.8250,0.3631}}, {"Au",{0.8000,0.2000,0.3631}}, + {"Au",{0.8000,0.4500,0.3631}}, {"Au",{0.8000,0.8250,0.3631}}, + {"Au",{0.9000,0.2000,0.3631}}, {"Au",{0.9000,0.3250,0.3631}}, + {"Au",{0.9000,0.5750,0.3631}}, {"Au",{0.9000,0.7000,0.3631}}, + + {"Ag",{0.0500,0.1375,0.5877}}, {"Ag",{0.0500,0.2625,0.5877}}, + {"Ag",{0.0500,0.3875,0.5877}}, {"Ag",{0.0500,0.5125,0.5877}}, + {"Ag",{0.0500,0.6375,0.5877}}, {"Ag",{0.0500,0.7625,0.5877}}, + {"Ag",{0.0500,0.8875,0.5877}}, {"Ag",{0.1500,0.1375,0.5877}}, + {"Ag",{0.1500,0.2625,0.5877}}, {"Ag",{0.1500,0.3875,0.5877}}, + {"Ag",{0.1500,0.5125,0.5877}}, {"Ag",{0.1500,0.6375,0.5877}}, + {"Ag",{0.1500,0.7625,0.5877}}, {"Ag",{0.1500,0.8875,0.5877}}, + {"Ag",{0.2500,0.1375,0.5877}}, {"Ag",{0.2500,0.2625,0.5877}}, + {"Ag",{0.2500,0.3875,0.5877}}, {"Ag",{0.2500,0.5125,0.5877}}, + {"Ag",{0.2500,0.6375,0.5877}}, {"Ag",{0.2500,0.7625,0.5877}}, + {"Ag",{0.2500,0.8875,0.5877}}, {"Ag",{0.3500,0.1375,0.5877}}, + {"Ag",{0.3500,0.2625,0.5877}}, {"Ag",{0.3500,0.3875,0.5877}}, + {"Ag",{0.3500,0.5125,0.5877}}, {"Ag",{0.3500,0.6375,0.5877}}, + {"Ag",{0.3500,0.7625,0.5877}}, {"Ag",{0.3500,0.8875,0.5877}}, + {"Ag",{0.4500,0.1375,0.5877}}, {"Ag",{0.4500,0.2625,0.5877}}, + {"Ag",{0.4500,0.3875,0.5877}}, {"Ag",{0.4500,0.5125,0.5877}}, + {"Ag",{0.4500,0.6375,0.5877}}, {"Ag",{0.4500,0.7625,0.5877}}, + {"Ag",{0.4500,0.8875,0.5877}}, {"Ag",{0.5500,0.1375,0.5877}}, + {"Ag",{0.5500,0.2625,0.5877}}, {"Ag",{0.5500,0.3875,0.5877}}, + {"Ag",{0.5500,0.5125,0.5877}}, {"Ag",{0.5500,0.6375,0.5877}}, + {"Ag",{0.5500,0.7625,0.5877}}, {"Ag",{0.5500,0.8875,0.5877}}, + {"Ag",{0.6500,0.1375,0.5877}}, {"Ag",{0.6500,0.2625,0.5877}}, + {"Ag",{0.6500,0.3875,0.5877}}, {"Ag",{0.6500,0.5125,0.5877}}, + {"Ag",{0.6500,0.6375,0.5877}}, {"Ag",{0.6500,0.7625,0.5877}}, + {"Ag",{0.6500,0.8875,0.5877}}, {"Ag",{0.7500,0.1375,0.5877}}, + {"Ag",{0.7500,0.2625,0.5877}}, {"Ag",{0.7500,0.3875,0.5877}}, + {"Ag",{0.7500,0.5125,0.5877}}, {"Ag",{0.7500,0.6375,0.5877}}, + {"Ag",{0.7500,0.7625,0.5877}}, {"Ag",{0.7500,0.8875,0.5877}}, + {"Ag",{0.8500,0.1375,0.5877}}, {"Ag",{0.8500,0.2625,0.5877}}, + {"Ag",{0.8500,0.3875,0.5877}}, {"Ag",{0.8500,0.5125,0.5877}}, + {"Ag",{0.8500,0.6375,0.5877}}, {"Ag",{0.8500,0.7625,0.5877}}, + {"Ag",{0.8500,0.8875,0.5877}}, {"Ag",{0.9500,0.1375,0.5877}}, + {"Ag",{0.9500,0.2625,0.5877}}, {"Ag",{0.9500,0.3875,0.5877}}, + {"Ag",{0.9500,0.5125,0.5877}}, {"Ag",{0.9500,0.6375,0.5877}}, + {"Ag",{0.9500,0.7625,0.5877}}, {"Ag",{0.9500,0.8875,0.5877}}, + + {"",{.0,.0,.0}}, + }; + + M3MULTIPLY(mul, h, H); + + i = 0; + while (*sample[i].sym) + i++; + + *np = i; + Config_realloc (Config_Alib_to_Alib); + + if (CONFIG_num_auxiliary) { + for (i = 1; i < CONFIG_num_auxiliary; i++) { + Free (CONFIG_auxiliary[i]); + CONFIG_auxiliary_name[i][0] = EOS; + CONFIG_auxiliary_unit[i][0] = EOS; + } + } + CONFIG_num_auxiliary = 1; + REALLOC (Config_load, CONFIG_auxiliary[0], *np, double); + strncpy(CONFIG_auxiliary_name[0],"linear",sizeof(CONFIG_auxiliary_name[0])); + CONFIG_auxiliary_unit[0][0] = EOS; + + i = 0; + while (*sample[i].sym) { + (*mass)[i] = 1.0; + strncpy(SYMBOL(i), sample[i].sym, 3); + (*s )[i * DIMENSION ] = sample[i].s[0]; + (*s )[i * DIMENSION + 1] = sample[i].s[1]; + (*s )[i * DIMENSION + 2] = sample[i].s[2]; + CONFIG_auxiliary[0][i] = sample[i].s[0]-sample[i].s[1]; + i++; + } + return CONFIG_CFG_LOADED; +} + + + +static char *command_generator(const char *text, int state) +{ + static int list_index, len; + char *name; + + if (!state) { + list_index = 0; + len = strlen(text); + } + + while ((name = atomeye_commands[list_index].name)) { + list_index++; + if (strncmp(name, text, len) == 0) { + char *r = malloc(strlen(name)+1); + if (r) + strcpy(r, name); + return (r); + } + } + + return ((char *)NULL); +} + +static char **atomeye_completion(const char *text, int start, int end) +{ + char **matches; + extern char **rl_completion_matches(); + + matches = (char **)NULL; + + if (start == 0) + matches = rl_completion_matches (text, command_generator); + + return (matches); +} + + +static void cui_initialize_readline(void) +{ + rl_readline_name = "AtomEye"; + rl_attempted_completion_function = atomeye_completion; +} + + +static FILE *terminal_fp, *terminal_out = NULL; +static char *terminal_prompt = ""; + +static void terminal_exit(int i) +{ + if (terminal_out) + fprintf(terminal_out, "\n"); + if (*terminal_prompt) + rl_callback_handler_remove(); + exit(i); +} + + +static void terminal_treatline(char *line) +{ + if (line) { + if (*line) { + char *s = cui_stripspace(line); + int status = -1; + + if (*s) { + cui_send(s, terminal_fp); + status = cui_recv_print(terminal_fp, terminal_out); + } + + if (*terminal_prompt) { + if (status < 0) + terminal_exit(0); + else if (status == 0 && *line) + add_history(line); + free(line); + } + } + } + else { + cui_send("disconnect", terminal_fp); + terminal_exit(0); + } +} + + +static int cui_terminal(void) +{ + int fd, port = CUI_PORT_FROM; + char host[CUI_LINEMAX] = "localhost"; + char buf[CUI_LINEMAX]; + struct sockaddr_in addr; + struct hostent *hp; + + if (sscanf(cui_hostport, " %[^:]:%d", host, &port) == 1) { + int tmp = 0; + if (sscanf(host, " %d", &tmp) == 1 && strchr(host, '.') == NULL) { + strncpy(host, "localhost", sizeof(host)); + port = tmp; + } + } + if (port < CUI_PORT_FROM || port > CUI_PORT_TO) { + fprintf(stderr, "error: (port < %d || prot > %d)\n", + CUI_PORT_FROM, CUI_PORT_TO); + return 1; + } + + if ((fd = socket(PF_INET, SOCK_STREAM, 0)) < 0) + return 1; + + memset(&addr, 0, sizeof(addr)); + addr.sin_family = PF_INET; + if ((hp = gethostbyname(host))) + memcpy(&addr.sin_addr, hp->h_addr, hp->h_length); + else if ((addr.sin_addr.s_addr = inet_addr(host)) == -1) + return 1; + addr.sin_port = htons(port); + if (connect(fd, (struct sockaddr*)&addr, sizeof(addr)) != 0) + return 1; + + if ((terminal_fp = fdopen(fd, "r+"))) { + int maxfd_plus_1; + fd_set allset; + + if (isatty(STDIN_FILENO)) { + terminal_prompt = CUI_PROMPT; + terminal_out = stderr; + setbuf(terminal_fp, NULL); + } + + cui_recv_print(terminal_fp, terminal_out); + + FD_ZERO(&allset); + FD_SET(STDIN_FILENO, &allset); + FD_SET(fd, &allset); + maxfd_plus_1 = (fd > STDIN_FILENO) ? fd + 1 : STDIN_FILENO + 1; + + if (*terminal_prompt) { + cui_initialize_readline(); + rl_callback_handler_install(terminal_prompt, terminal_treatline); + } + + while (1) { + fd_set rfds = allset; + if (select(maxfd_plus_1, &rfds, NULL, NULL, NULL) == -1) + terminal_exit(0); + if (FD_ISSET(fd, &rfds) && fgets(buf, sizeof(buf), terminal_fp)) { + char *s = cui_stripspace(buf); + if (strcmp(s, CUI_PROTOCOL_QUIT) == 0) { + terminal_exit(0); + } + else { + cui_send(CUI_PROTOCOL_OK, terminal_fp); /* NG? */ + } + } + if (FD_ISSET(STDIN_FILENO, &rfds)) { + if (*terminal_prompt) + rl_callback_read_char(); + else { + if (fgets(buf, sizeof(buf), stdin)) + terminal_treatline(buf); + else + terminal_exit(0); + } + } + } + } + + return 0; +} + +struct co { + char *name; + int *pointer, value; + char **strp; +}; + +static char *cui_xterm; + +static struct co cui_options[] = { + {"v2", &cui_enabled, 0, NULL}, + {"nowindow", &cui_enabled, -1, NULL}, + {"nostdin", &cui_stdin, 0, NULL}, + {"listen", &cui_listen, 1, NULL}, + {"listen=", &cui_listen, 1, &cui_hostport}, + {"c", &cui_connect, 1, NULL}, + {"connect", &cui_connect, 1, NULL}, + {"connect=", &cui_connect, 1, &cui_hostport}, + {"f=", NULL, 0, &cui_scrfname}, + {NULL, NULL, 0} +}; + +int cui_init(int *argc, char ***argv) +{ + int i, retval = 0; + char *str, *display_str = NULL, *TTYname = "/dev/null"; + extern char config_fname[MAX_FILENAME_SIZE]; + extern char xterm_identifier[XTERM_IDENTIFIER_SIZE]; + + cui_time = cui_wtime(); + cui_xterm = CUI_XTERM_DEFAULT; + cui_xterm_win = ((str = getenv("WINDOWID"))) ? atol(str) : 0; + cui_enabled = 1; + cui_listen = 0; + cui_connect = 0; + cui_stdin = 1; + cui_hostport = ""; + cui_scrfname = ""; + cui_geometry = ""; + config_fname[0] = 0; + xterm_identifier[0] = 0; + cui_diligence = TRUE; + +#ifdef USE_P3D + if ((i = p3dp_init(argc, argv)) < 0) + return i; +#endif + + if (argv && *argv) { + for (i = 1; i < *argc; i++) { + if (*(str = (*argv)[i]) != '-') { + if (!config_fname[0]) + strcpy(config_fname, str); + else { + retval = 1; + if (!xterm_identifier[0]) + strcpy(xterm_identifier, str); + else + TTYname = str; + } + } + else if (strcmp(str, "-nofep") == 0 && cui_stdin) { + cui_stdin = -1; + } + else if (strcmp(str, "-display") == 0 && ++i < *argc) { + display_str = (*argv)[i]; + } + else if (strcmp(str, "-geometry") == 0 && ++i < *argc) { + cui_geometry = (*argv)[i]; + } + else if (strcmp(str, "-xterm") == 0) { + cui_xterm_win = 0; + } + else if (strncmp(str, "-xterm=", strlen("-xterm=")) == 0) { + cui_xterm_win = 0; + cui_xterm = str + strlen("-xterm="); + } + else if (strncmp(str, "-xterm_win=", strlen("-xterm_win=")) == 0) { + cui_xterm_win = atol(str + strlen("-xterm_win=")); + } + else { + struct co *cop; + for (cop = cui_options; cop->name; cop++) { + if (strcmp(str+1, cop->name) == 0) { + if (cop->pointer) + *cop->pointer = cop->value; + break; + } + else if (cop->strp) { + int len = strlen(cop->name); + if (strncmp(str+1, cop->name, len) == 0) { + if (cop->pointer) + *cop->pointer = cop->value; + *cop->strp = str + len + 1; + break; + } + } + } + if (!cop->name) { + fprintf(stderr, "unknown option \"%s\"\n", str); + return -1; + } + } + } + } + + if (cui_connect) { + if (cui_listen) + return -1; /* error */ +#ifdef USE_P3D + if (p3dp_enabled) + return -2; /* error */ +#endif + cui_enabled = 1; + if (cui_terminal()) { + fprintf(stderr, "%s: failed to connect.\n", (*argv)[0]); + exit(1); + } + exit(0); + } + + if ((cui_listen || *cui_scrfname) && !cui_enabled) + cui_enabled = 1; + + if (!config_fname[0]) { + if (cui_enabled) + strcpy(config_fname, "/dev/null"); + else + return -1; /* error */ + } + + if (!cui_enabled || display_str) + cui_xterm_win = 0; + + if (display_str) { + char *display_env = + (char*)malloc(strlen("DISPLAY=")+strlen(display_str)+1); + if (display_env) { + strcpy(display_env, "DISPLAY="); + strcat(display_env, display_str); + putenv(display_env); + } + } + + if (!retval) { + char **p; + + cui_argc = 0; + +#ifdef USE_P3D + if (p3dp_enabled) { + if (!p3dp_mpiexec_argc) goto renderer; + } + else +#endif + if (cui_enabled < 0 || (cui_enabled && cui_xterm_win)) + goto renderer; + +#ifdef USE_P3D + if (cui_enabled >= 0) +#endif + if (!cui_xterm_win) { + int len; + strncpy(buf, cui_xterm, sizeof(buf)); + len = strlen(buf); + for (i = 0; i < len; i++) + if (isspace(buf[i])) + buf[i] = 0; + i = 0; + while (i < len) { + while ((!buf[i] || isspace(buf[i])) && i < len) + i++; + if (i < len) { + cui_argv[cui_argc++] = buf + i; + while (buf[i] && !isspace(buf[i]) && i < len) + i++; + } + } + cui_argv[cui_argc++] = "-xrm"; + cui_argv[cui_argc++] = xterm_identifier; + cui_argv[cui_argc++] = "-e"; + } + +#ifdef USE_P3D + if (p3dp_enabled) { + for (p = p3dp_mpiexec_argv; *p; p++) + cui_argv[cui_argc++] = *p; + } +#endif + TimeRandomize(); + RandomBase64String(XTERM_IDENTIFIER_SIZE, xterm_identifier); + cui_argv[cui_argc++] = (*argv)[0]; + cui_argv[cui_argc++] = config_fname; + cui_argv[cui_argc++] = xterm_identifier; + cui_argv[cui_argc++] = ttyname(STDERR_FILENO); + + if (!cui_enabled) + cui_argv[cui_argc++] = "-v2"; + else { + if (*cui_geometry) { + cui_argv[cui_argc++] = "-geometry"; + cui_argv[cui_argc++] = cui_geometry; + } + + if (cui_enabled < 0) + cui_argv[cui_argc++] = "-nowindow"; + + if (*cui_scrfname) { + strncpy(fname, "-f=", sizeof(fname)); + STRCATN(fname, cui_scrfname); + cui_argv[cui_argc++] = fname; + } + + if (*cui_hostport) { + char *chp = + (char*)malloc(strlen("-listen=")+strlen(cui_hostport)+1); + if (chp) { + strcpy(chp, "-listen="); + strcat(chp, cui_hostport); + cui_argv[cui_argc++] = chp; + } + } + else if (cui_listen) + cui_argv[cui_argc++] = "-listen"; + } + +#ifdef USE_P3D + if (p3dp_enabled) { + cui_argv[cui_argc++] = p3dp_decomp; + if (!cui_xterm_win) + cui_argv[cui_argc++] = "-xterm"; + } +#endif + + cui_argv[cui_argc] = NULL; + execvp(cui_argv[0], cui_argv); + exit(-2); + } + +renderer: + if (!cui_enabled) + redirect_stderr_to(wOpen(TTYname)); + else + { + gui_defaultkey(); + if (*cui_geometry) { + if (sscanf(cui_geometry, "%dx%d", &cui_startup_width, + &cui_startup_height) < 1) + sscanf(cui_geometry, "x%d", &cui_startup_height); + } + + if (IS_MANAGER) { + char *home; + int i; + + for (i = 0; i < CUI_N_FILE; i++) cmdf[i].fp = NULL; + FD_ZERO(&allset); + + /* startup file */ + fname[0] = 0; + if (*cui_scrfname) + strncpy(fname, cui_scrfname, sizeof(fname)); + else if ((home = getenv("HOME"))) { + strncpy(fname, home, sizeof(fname)); + STRCATN(fname, "/"); + STRCATN(fname, CUI_SCRIPT_STARTUP); + } + if (fname[0]) + cmdfdopen(open(fname, O_RDONLY), "r", -1); + + /* greetings */ + cui_send(CUI_GREETINGS, stderr); + +#ifdef USE_P3D + if (p3dp_enabled) { + sprintf(buf, "[parallel: %d]", p3d_nprocs(p3dp_cell)); + cui_send(buf, stderr); + } +#endif + /* inet */ + if (cui_listen) { + char *outstr; + proc_open_port(0, cui_hostport, &outstr); + cui_send(outstr, stderr); + } + + /* frontend */ + if (cui_stdin) { + if ((i = cmdfdopen(STDIN_FILENO, + isatty(STDIN_FILENO) ? "r+" : "r", -1)) >= 0) { + if (i != 0) { + cmdf[i].pause = -1.0; + cmdf[0].opener = i; + } + if (cui_stdin > 0 && isatty(STDIN_FILENO)) { + frontend = cmdf[i].fd; + cui_initialize_readline(); + rl_callback_handler_install(CUI_PROMPT, stdin_gets); + } + } + } + } + + cui_iw = 0; + cui_title[0] = '*'; + } + + return 0; +} diff -urN A/cui.h A3/cui.h --- A/cui.h 1970-01-01 09:00:00.000000000 +0900 +++ A3/cui.h 2011-02-22 15:15:37.000000000 +0900 @@ -0,0 +1,135 @@ +/* 2004-2005 Futoshi Shimizu */ +#ifndef CUI_H +#define CUI_H + +#include "A.h" + +#define CUI_GREETINGS "Threaded atomistic configuration viewer V3.0" +#define CUI_N_FILE 5 +#define CUI_TIMEOUT {0, 10000} +#define CUI_LINEMAX 2048 +#define CUI_SCRIPT_DEFAULT "scr_cmds" +#define CUI_SCRIPT_STARTUP ".A" +#define CUI_PORT_FROM 21040 +#define CUI_PORT_TO 21049 +#define CUI_PROMPT "> " +#define CUI_PROTOCOL_OK "ok" +#define CUI_PROTOCOL_NG "error" +#define CUI_PROTOCOL_QUIT "quit" +#define CUI_ARG_REQUIRED "arg_required" +#define CUI_EPS_RESOLUTION_DEFAULT 2560 +#define CUI_XTERM_DEFAULT \ + "xterm -bg gray40 -fg white -sb -sl 3000 -cr yellow -fn 7x13" + + + +#define IS_MANAGER 1 + +#ifdef CUI_GLOBAL + int cui_startup_width = DEFAULT_WIDTH, cui_startup_height = DEFAULT_HEIGHT; + void cui_AX_dump(int iw) { if (AX_display[iw]) AX_dump(iw); } +#else +# define CUI_GLOBAL extern + CUI_GLOBAL int cui_startup_width, cui_startup_height; + void cui_AX_dump(int iw); +#endif + +CUI_GLOBAL int cui_enabled; +CUI_GLOBAL int cui_listen; +CUI_GLOBAL int cui_connect; +CUI_GLOBAL int cui_stdin; +CUI_GLOBAL int cui_startup_width; +CUI_GLOBAL int cui_startup_height; +CUI_GLOBAL int cui_argc; +CUI_GLOBAL int cui_iw; +CUI_GLOBAL char *cui_argv[128]; +CUI_GLOBAL char *cui_hostport; +CUI_GLOBAL char *cui_scrfname; +CUI_GLOBAL char *cui_geometry; +CUI_GLOBAL char cui_title[CUI_LINEMAX]; +CUI_GLOBAL bool cui_diligence; +CUI_GLOBAL double cui_time; +CUI_GLOBAL Window cui_xterm_win; + +/* cui.c */ +double cui_wtime(void); +int cui_init(int *argc, char ***argv); +bool cui_treatevent(int iw); +bool gui_treatevent(int iw); +int cui_config_load_A3(Alib_Declare_Config); + +/* cui_AX.c */ +int cui_AX_openwindow +(int cid, char *title, unsigned int width, unsigned int height); +void cui_AX_resizewindow(int iw, Bool do_window_too); +void cui_AX_closewindow(int iw); + +/* A */ + +#undef DEFAULT_WIDTH +#define DEFAULT_WIDTH cui_startup_width +#undef DEFAULT_HEIGHT +#define DEFAULT_HEIGHT cui_startup_height + +/* Atoms */ + +#undef CONFIG_LOAD +#define CONFIG_LOAD(fname,Config_Alib_to_Alib)\ + ((strcmp(fname,"/dev/null") == 0)\ + ? cui_config_load_A3(Config_Aapp_to_Alib)\ + : Config_Load(fname,stdout,Config_Alib_to_Alib)) + +/* X & AX */ +#define XStoreName(display, w, window_name)\ + ((display&&w!=xterm_win) ? XStoreName( display,w,window_name) : 0) +#define XSetIconName(display, w, window_name)\ + ((display&&w!=xterm_win) ? XSetIconName(display,w,window_name) : 0) +#define XMapWindow(display, w)\ + ((display&&w) ? XMapWindow(display, w) : 0) +#define XIconifyWindow(display, w, screen_number)\ + (display ? XIconifyWindow(display, w,screen_number) : (Status)0) + +#define CUI_AX(IW, type, value) (AX_display[IW] ? (value) : (type)0) +#define CUI_TITLE(iw) ((!cui_enabled||iw!=cui_iw) ? AX_title[iw] :\ + strncpy(cui_title+1, AX_title[iw], sizeof(cui_title))-1) + +#undef AXQueryPointer +#define AXQueryPointer(iw) CUI_AX(iw, Bool,\ + XQueryPointer(AX_display[iw],AX_win[iw],&AX_root[iw],&AX_child[iw],\ + &AX_root_x[iw],&AX_root_y[iw],&AX_win_x[iw],&AX_win_y[iw],\ + &AX_pointermask[iw])) +#undef AXSetName +#define AXSetName(iw) CUI_AX(iw, int, (\ + XStoreName(AX_display[iw],AX_win[iw],CUI_TITLE(iw)),\ + XSetIconName(AX_display[iw],AX_win[iw],CUI_TITLE(iw)))) +#undef AXIdentifyWIN +#define AXIdentifyWIN(iw,identifier) CUI_AX(iw, Window,\ + AXIdentifyWin(iw, AX_root[iw], identifier)) +#undef AXSETICON +#define AXSETICON(iw) CUI_AX(iw, int, AXSetICON(iw,icon)) +#undef AXRaiseWindow +#define AXRaiseWindow(iw) CUI_AX(iw,int,XRaiseWindow(AX_display[iw],AX_win[iw])) + +#undef AX_show +#define AX_show(iw) if (AX_display[iw])\ + { if (AX_videomode == AX_VIDEOMODE_SHM_PIXMAP) \ + XCopyArea(AX_display[iw], AX_pixmap[iw], AX_win[iw], AX_gc[iw], 0,0, \ + AX_size[iw].width, AX_size[iw].height, 0,0); AXSYNC(iw); } + +#undef AX_dump +#define AX_dump(iw) cui_AX_dump(iw) +#define AX_openwindow(cid, title, width, height) \ + ((cui_enabled >= 0)\ + ? AX_openwindow( cid, title, width, height)\ + : cui_AX_openwindow(-1*(cid), title, width, height)) +#define AX_resizewindow(iw, dwt)\ + switch ((AX_cid[iw] >= 0)) {\ + case 0: cui_AX_resizewindow(iw, dwt); break;\ + default: AX_resizewindow(iw, dwt); break;\ + } +#define AX_closewindow(iw)\ + switch ((AX_cid[iw] >= 0)) {\ + case 0: cui_AX_closewindow(iw); break;\ + default: AX_closewindow(iw); break;\ + } +#endif diff -urN A/cui_AX.c A3/cui_AX.c --- A/cui_AX.c 1970-01-01 09:00:00.000000000 +0900 +++ A3/cui_AX.c 2011-02-22 15:15:37.000000000 +0900 @@ -0,0 +1,151 @@ +/* 2004-2005 Futoshi Shimizu */ +#include "cui.h" +#undef AX_openwindow +#undef AX_resizewindow +#undef AX_closewindow +#define nonvacant(iw) (AX_cid[iw]!=0) + +static int cui_AX_plugin_ShmGC_module (int iw) +{ + AX_AssertWinID ("cui_AX_plugin_ShmGC_module", iw); + AX_Check_Module_Dependence ("cui_AX_plugin_ShmGC_module", iw,MODULE_ShmGC); + if ( AX_Module_Is_PluggedIn [iw] [MODULE_ShmGC] ) + pe ("cui_AX_plugin_ShmGC_module:\n" + "you are crazy, this module is already plugged in\n"); + + /*switch (AX_depth[iw]) { + case 8: AX_bytes = 1; break; + case 16: AX_bytes = 2; break; + case 24: case 32: AX_bytes = 4; break; + default: AX_bytes = 4; + }*/ + AX_bytes = 4; + + /* non-shared client data-memory */ + MALLOC ( AX_plugin_ShmGC_module, AX_mem[iw].uc, + AX_size[iw].width * AX_size[iw].height * AX_bytes, + unsigned char ); + +/* AX_bytes = AX_img[iw] -> bytes_per_line / AX_size[iw].width; */ + if (AX_bytes > sizeof(AX_Carrier)) + pe ("AX_plugin_ShmGC_module: AX_Carrier unable to carry\n" + "one pixmap unit of %d bytes\n", AX_bytes); + AX_8b = AX_bytes & 1; + AX_16b = AX_bytes & 2; + /* calling it 24-bit is inconsistent because no one calls above 15-bit */ + AX_32b = AX_bytes & 4; + if ( ! (AX_8b || AX_16b || AX_32b) ) + pe ("AX_plugin_ShmGC_module: AX_bytes = %d, neither 8,\n16, or 32-bit " + "graphics. Small revisions required.\n", AX_bytes); + + AX_namedbg(iw,AX_DEF_BACKGROUND); + AX_Module_Is_PluggedIn [iw] [MODULE_ShmGC] = 1; + return (1); +} /* end cui_AX_plugin_ShmGC_module() */ + + +static int cui_AX_plugout_ShmGC_module (int iw) +{ + AX_AssertWinID ("cui_AX_plugout_ShmGC_module", iw); + if ( ! AX_Module_Is_PluggedIn [iw] [MODULE_ShmGC] ) + pe ("cui_AX_plugout_ShmGC_module:\n" + "you are crazy, this module is not plugged in\n"); + + Free(AX_mem[iw].uc); + AX_Module_Is_PluggedIn [iw] [MODULE_ShmGC] = 0; + return (1); +} /* end cui_AX_plugout_ShmGC_module() */ + + +static int cui_AX_resize_ShmGC_module (int iw) +{ + REALLOC( AX_plugin_ShmGC_module, AX_mem[iw].uc, + AX_size[iw].width * AX_size[iw].height * AX_bytes, + unsigned char ); + return (1); +} /* end cui_AX_resize_ShmGC_module() */ + + +static struct { + int (*plugin) (int iw); + int (*plugout) (int iw); + int (*resize) (int iw); +} cui_AX_modules [MODULE_MAX] = { + {&cui_AX_plugin_ShmGC_module, + &cui_AX_plugout_ShmGC_module, + &cui_AX_resize_ShmGC_module}, + {&AX_plugin_Scan_module, &AX_plugout_Scan_module, &AX_resize_Scan_module}, + {&AX_plugin_3D_module, &AX_plugout_3D_module, &AX_resize_3D_module}, + {&AX_plugin_BC_module, &AX_plugout_BC_module, &AX_resize_BC_module} +}; + + +int cui_AX_openwindow +(int cid, char *title, unsigned int width, unsigned int height) +{ + int iw, minor; + + for (iw = 0; (iw < AX_MAXWIN) && nonvacant(iw); iw++); + if (iw == AX_MAXWIN) { + fprintf(stderr,"cui_AX_openwindow: AX_MAXWIN = %d reached\n",AX_MAXWIN); + return -1; + } + + AX_display[iw] = NULL; + AX_cid[iw] = cid; + AX_size[iw].width = width; + AX_size[iw].height = height; + AX_borderwidth[iw] = 0; + AX_depth[iw] = 32; + AX_rmask = 0xff0000; + AX_gmask = 0x00ff00; + AX_bmask = 0x0000ff; + AX_namedpixel[AX_RED] = AX_Colorpixel(1,0,0); + AX_namedpixel[AX_GREEN] = AX_Colorpixel(0,1,0); + AX_namedpixel[AX_BLUE] = AX_Colorpixel(0,0,1); + AX_noneedcolormap = 1; + AX_videomode = AX_VIDEOMODE_NO_SHM; + + for (minor=0; minor<=AX_DEF_Module_Support_Level; minor++) + cui_AX_modules[minor].plugin(iw); + + return iw; +} + +/* Resize all modules that are already plugged in, to AX_size[iw] */ +void cui_AX_resizewindow (int iw, Bool do_window_too) +{ + int module; + AX_AssertWinID ("AX_resizewindow", iw); + for (module=0; module= p3d_n_atoms(p3dp_cell)) continue; +#endif if (coordination[i] > ATOM_COORDINATION_MAX) pe ("evaluate_shear_strain:\n" "ATOM_COORDINATION_MAX = %d exceeded\n",ATOM_COORDINATION_MAX); else coordination_hist[coordination[i]]++; +#ifdef USE_P3D + } + if (p3dp_enabled) + { + int buf[ATOM_COORDINATION_MAX+1]; + for (i=0; i<=ATOM_COORDINATION_MAX; i++) buf[i] = coordination_hist[i]; + p3d_reduce(p3dp_cell, buf, coordination_hist, ATOM_COORDINATION_MAX+1, + MPI_INT, MPI_SUM); + } +#endif j = -1; for (i=0; i<=ATOM_COORDINATION_MAX; i++) if (coordination_hist[i] > j) @@ -89,6 +106,9 @@ dx[0] = dx[1] = 0; for (i=0; i= p3d_n_atoms(p3dp_cell)) continue; +#endif if (participant[i] == coordination_crystal) { for (j=0; jidx[i]; jidx[i+1]; j++) @@ -135,6 +163,9 @@ for (j=0; j<6; j++) metric[j] = 0; for (avg_coordination=i=0; i= p3d_n_atoms(p3dp_cell)) continue; +#endif avg_coordination += coordination[i]; for (j=0; j<6; j++) { @@ -143,10 +174,30 @@ } } free(participant); +#ifdef USE_P3D + if (p3dp_enabled) + { + double sbuf[8], rbuf[8]; + for (j=0; j<6; j++) sbuf[j] = metric[j]; + sbuf[6] = avg_coordination; + sbuf[7] = p3d_n_atoms(p3dp_cell); + p3d_reduce(p3dp_cell, sbuf, rbuf, 8, MPI_DOUBLE, MPI_SUM); + avg_coordination = rbuf[6] / rbuf[7]; + for (j=0; j<6; j++) metric[j] = rbuf[j] / rbuf[7]; + } + else + { +#endif avg_coordination /= np; for (j=0; j<6; j++) metric[j] /= np; +#ifdef USE_P3D + } +#endif for (i=0; i= p3d_n_atoms(p3dp_cell)) continue; +#endif if (shear_strain_subtract_mean) { avg_M[0][0] = (*shear_strain)[6*i] - metric[0]; @@ -253,6 +304,9 @@ REALLOC (evaluate_central_symm, dx, (DIMENSION+1)*n, double); for (i=0; i= p3d_n_atoms(p3dp_cell)) continue; +#endif n = 0; for (j=M->idx[i]; jidx[i+1]; j++) { @@ -320,5 +374,45 @@ geolist[i].fun(geo + i); geolist[i].has_evaluated = 1; } +#ifdef USE_P3D + if (p3dp_enabled) { + int i; + P3DAtom *p = p3d_atom_begin(p3dp_cell); + + /* (geo[j]) -> v[j] */ + if (geolist[0].has_evaluated) { + for (i = 0; i < p3d_n_atoms(p3dp_cell); i++) { + p[i].v[0] = geo[0][i]; + p[i].v[2] = coordination[i]; + } + } + if (geolist[1].has_evaluated) { + for (i = 0; i < p3d_n_atoms(p3dp_cell); i++) { + p[i].v[1] = geo[1][i]; + } + } + + p3d_update_cell(p3dp_cell); + + /* v[j] -> (geo[j]) */ + if (geolist[0].has_evaluated) { + i = p3d_n_atoms(p3dp_cell); + for (p=p3d_image_begin(p3dp_cell);piw) continue; + geo[0][i] = p->v[0]; + coordination[i] = p->v[2] + 0.1; + i++; + } + } + if (geolist[1].has_evaluated) { + i = p3d_n_atoms(p3dp_cell); + for (p=p3d_image_begin(p3dp_cell);piw) continue; + geo[1][i] = p->v[1]; + i++; + } + } + } +#endif return; } /* end evaluate_geo_measures() */ diff -urN A/info.c A3/info.c --- A/info.c 2009-07-29 00:19:54.000000000 +0900 +++ A3/info.c 2011-02-22 15:15:37.000000000 +0900 @@ -5,6 +5,9 @@ /*******************************************/ #include "A.h" +#ifdef USE_P3D +# include "p3dp.h" +#endif static char *auxiliary_keycode[16] = { "Alt+0", diff -urN A/p3dp.c A3/p3dp.c --- A/p3dp.c 1970-01-01 09:00:00.000000000 +0900 +++ A3/p3dp.c 2011-02-22 15:15:37.000000000 +0900 @@ -0,0 +1,962 @@ +/* 2004-2005 Futoshi Shimizu */ +#include "P3DExt.h" +#include "P3D_p.h" +#define P3DP_GLOBAL +#include "p3dp.h" +#include "Atoms.h" +#include + + +#ifdef AX_MEMORY_EFFICIENT +# define MPI_AX_FLOAT MPI_FLOAT +# define MPI_AX_FLOAT_INT MPI_FLOAT_INT +#else +# define MPI_AX_FLOAT MPI_DOUBLE +# define MPI_AX_FLOAT_INT MPI_DOUBLE_INT +#endif + +#define STRCATN(d, s) strncat((d), (s), sizeof(d)-strlen(d)-strlen(s)-1) + +static MPI_Datatype m_sym; +static MPI_Op m_minsym; +static void minsym_func(void *in, void *inout, int *len, MPI_Datatype *datatype) +{ + int i, j; + char *c_in = in, *c_inout = inout; + + for (j = 0; j < *len; j++) { + if (strncmp(c_in, c_inout, SYMBOL_CHAR) < 0) + for (i = 0; i < SYMBOL_CHAR; i++) + c_inout[i] = c_in[i]; + c_in += SYMBOL_CHAR; + c_inout += SYMBOL_CHAR; + } +} + +int p3dp_init(int *argc, char ***argv) +{ + int i; + static char buf[CUI_LINEMAX] = ""; + + p3dp_mpiexec_argc = 0; + p3dp_enabled = 0; + p3dp_decomp = ""; + + if (argv && *argv) { + if ((i = strlen((*argv)[0])) > 0 && (*argv)[0][i-1] == 'p') { + p3dp_enabled = cui_enabled = 1; + MPI_Init(argc, argv); + } + + for (i = 1; i < *argc; i++) { + if (strncmp((*argv)[i], "-mpi=", strlen("-mpi=")) == 0) { + STRCATN(buf, " "); + STRCATN(buf, (*argv)[i]+strlen("-mpi=")); + (*argv)[i] = 0; + } + else if (strncmp((*argv)[i], "-decomp=", strlen("-decomp=")) == 0 || + strncmp((*argv)[i], "-DECOMP=", strlen("-DECOMP=")) == 0) { + p3dp_decomp = (*argv)[i]; + (*argv)[i] = 0; + } + } + } + { + int j = i = 0; + while (j < *argc) { + while ((*argv)[j] == 0 && j < *argc) j++; + if (j < *argc) (*argv)[i++] = (*argv)[j++]; + } + if (!(*argv)[i-1]) i--; + *argc = i; + } + + if (!p3dp_enabled && buf[0]) { /* mpiexec */ + int len = strlen(buf); + char **p; + + p3dp_enabled = cui_enabled = 1; + if (!*p3dp_decomp) + p3dp_decomp = "-decomp=0"; + + i = 0; + while (i < len) { + while (isspace(buf[i]) && i < len) i++; + if (i < len) { + p3dp_mpiexec_argc++; + while (!isspace(buf[i]) && i < len) i++; + } + } + if (p3dp_mpiexec_argc == 0) { + strcpy(buf, " mpiexec -n 1"); + p3dp_mpiexec_argc = 3; + } + else if (p3dp_mpiexec_argc == 1 && (i = atoi(buf)) > 0) { + sprintf(buf, " mpiexec -n %d", i); + p3dp_mpiexec_argc = 3; + } + + fprintf(stderr, "[MPI process startup command: \"%s\"]\n", buf+1); + len = strlen(buf); + for (i = 0; i < len; i++) + if (isspace(buf[i])) + buf[i] = 0; + + MALLOC(p3dp_init, p3dp_mpiexec_argv, p3dp_mpiexec_argc+1, char*); + p = p3dp_mpiexec_argv; + i = 0; + while (i < len) { + while ((!buf[i] || isspace(buf[i])) && i < len) i++; + if (i < len) { + *p++ = buf+i; + while (buf[i] && !isspace(buf[i]) && i < len) i++; + } + } + *p = NULL; + return 0; + } + + if (*p3dp_decomp) + p3dp_enabled = (p3dp_decomp[1] == 'D') ? -1: 1; + + if (p3dp_enabled) { /*p3dp_init0(argc, argv);*/ + MPI_Datatype m_image, types[2] = {MPI_CHAR, MPI_UB}; + MPI_Aint displacements[2] = {0, sizeof(P3DAtom)}; + int blocklengths[2] = {(size_t)&((P3DAtom*)0)->iw, 1}; + + MPI_Initialized(&i); + if (!i) + MPI_Init(argc, argv); + p3d_init(argc, argv, MPI_COMM_NULL); + + MPI_Type_contiguous(SYMBOL_CHAR, MPI_CHAR, &m_sym); + MPI_Type_commit(&m_sym); + MPI_Op_create(minsym_func, True, &m_minsym); + + MPI_Type_struct(2, blocklengths, displacements, types,&m_image); + MPI_Type_commit(&m_image); + + if (!*p3dp_decomp) + p3dp_decomp = "-decomp=0"; + p3dp_cell = p3d_new_cell(p3dp_decomp+strlen("-decomp="), + m_image, MPI_COMM_WORLD); + p3dp_cell->reduced_coordinates = 1; + } + + return 0; +} + + +int p3dp_finalize(void) +{ + if (p3dp_enabled) { + p3d_finalize(); + MPI_Finalize(); + } + return 0; +} + + +static int compsym(const void *s1, const void *s2) +{ + return strncmp((char*) s1, (char*) s2, SYMBOL_CHAR); +} + + +static void p3dp_config_add_image(Alib_Declare_Config) +{ + Cell_private cp = p3dp_cell->private; + P3DAtom *p; + V3 lb, ub; + enum p3d_flags_index f_xyz[3] = {F_EOO|F_WOO, F_ONO|F_OSO, F_OOT|F_OOB}; + int i, j, k, n, nspec_l, nspec_g, mask = 0; + double rcut, rcut_max = 0.0; + char spec[(MENDELEYEV_MAX+1)*SYMBOL_CHAR+1] = ""; + char sym_i[SYMBOL_SIZE], sym_j[SYMBOL_SIZE], sym_end[SYMBOL_SIZE]; + + for (i = 0; i < SYMBOL_CHAR; i++) + sym_end[i] = 0x7f; + sym_end[SYMBOL_CHAR] = 0; + + nspec_l = 0; + for (p = p3d_atom_begin(p3dp_cell); p < p3d_atom_end(p3dp_cell); p++) { + for (i = 0; i < nspec_l; i++) + if (strncmp(p->sym, &spec[i*SYMBOL_CHAR], SYMBOL_CHAR) == 0) + break; + if (i == nspec_l) { + for (j = 0; j < SYMBOL_CHAR; j++) + spec[nspec_l*SYMBOL_CHAR+j] = p->sym[j]; + nspec_l++; + } + } + qsort(spec, nspec_l, SYMBOL_CHAR, compsym); + spec[(nspec_l+1)*SYMBOL_CHAR] = 0; + strncat(spec, sym_end, SYMBOL_CHAR); + i = 0; + for (nspec_g = 0; nspec_g < MENDELEYEV_MAX; nspec_g++) { + p3d_reduce(p3dp_cell, &spec[i*SYMBOL_CHAR], + &p3dp_spec[nspec_g*SYMBOL_CHAR], 1, m_sym, m_minsym); + if (strncmp(&p3dp_spec[nspec_g*SYMBOL_CHAR], sym_end, SYMBOL_CHAR) == 0) + break; + if (i < nspec_l && strncmp(&p3dp_spec[nspec_g*SYMBOL_CHAR], + &spec[i*SYMBOL_CHAR], SYMBOL_CHAR) == 0) + i++; + }; + p3dp_spec[(nspec_g)*SYMBOL_CHAR] = 0; + + sym_i[SYMBOL_CHAR] = sym_j[SYMBOL_CHAR] = 0; + for (i = 0; i < nspec_g*SYMBOL_CHAR; i += SYMBOL_CHAR) { + for (k = 0; k < SYMBOL_CHAR; k++) + sym_i[k] = p3dp_spec[i + k]; + for (j = i; j < nspec_g*SYMBOL_CHAR; j += SYMBOL_CHAR) { + for (k = 0; k < SYMBOL_CHAR; k++) + sym_j[k] = p3dp_spec[j + k]; + rcut = NEIGHBORLIST_RCUT_RATIO * + (ATOM_RADIUS_IN_A(search_atom_by_symbol(sym_i))+ + ATOM_RADIUS_IN_A(search_atom_by_symbol(sym_j))); + if (rcut > rcut_max) rcut_max = rcut; + } + } + rcut_max += 0.1; + + p3d_reset_cell_c(p3dp_cell, rcut_max); + + V3EQV(cp->lb, lb); + V3EQV(cp->ub, ub); + for (i = 0; i < 3; i++) { + if (cp->dims[i] == 1) + mask |= f_xyz[i]; + if (lb[i] < 0) + lb[i] = 0; + if (ub[i] >= 1.0) + ub[i] = 1.0; + } + + n = 0; + for (p = p3d_image_begin(p3dp_cell); p < p3d_image_end(p3dp_cell); p++) + if (!(p->iw = mask & p3d_flags_boundary(p->r, lb, ub))) n++; + + *np = p3d_n_atoms(p3dp_cell) + n; + Config_realloc (Config_Alib_to_Alib); + for (k = 0; k < CONFIG_num_auxiliary; k++) + REALLOC(p3dp_config_add_image, CONFIG_auxiliary[k], *np, double); + + n = 0; + for (p = p3d_atom_begin(p3dp_cell); p < p3d_atom_end(p3dp_cell); p++) { + (*mass)[n] = p->m; + strncpy(SYMBOL(n), p->sym, 3); + (*s )[n * DIMENSION ] = p->r[0]; + (*s )[n * DIMENSION + 1] = p->r[1]; + (*s )[n * DIMENSION + 2] = p->r[2]; + for (k = 0; k < CONFIG_num_auxiliary; k++) + CONFIG_auxiliary[k][n]= p->aux[k]; + n++; + } + + for (p = p3d_image_begin(p3dp_cell); p < p3d_image_end(p3dp_cell); p++) { + if (p->iw) continue; + (*mass)[n] = p->m; + strncpy(SYMBOL(n), p->sym, 3); + (*s )[n * DIMENSION ] = p->r[0]; + (*s )[n * DIMENSION + 1] = p->r[1]; + (*s )[n * DIMENSION + 2] = p->r[2]; + for (k = 0; k < CONFIG_num_auxiliary; k++) + CONFIG_auxiliary[k][n]= p->aux[k]; + n++; + } +} + +static int p3dp_Config_load(char *fname, FILE *info, Alib_Declare_Config) +{ + Auxiliary auxiliary = p3dp_cell->auxiliary; + int k; + extern void Config_analyze_H (Alib_Declare_Config, FILE *out); + + if (info) Fprintf(info, "Loading configuration from \"%s\":\n", fname); + + p3d_read_config(p3dp_cell, fname); + M3EQV(p3dp_cell->h, H); + + *np = p3d_n_atoms(p3dp_cell); + if (info) Fprintf(info, "%d atoms found.. reallocating memory\n\n", *np); + if ((CONFIG_num_auxiliary = auxiliary->n_aux)) { + for (k = 0; k < CONFIG_num_auxiliary; k++) { + strncpy(CONFIG_auxiliary_name[k], auxiliary->name[k], TERMSIZE); + strncpy(CONFIG_auxiliary_unit[k], auxiliary->unit[k], TERMSIZE); + } + } + + p3dp_config_add_image(Config_Alib_to_Alib); + + if (info) { + Config_analyze_H (Config_Alib_to_Alib, info); fcr(info); + Config_analyze_density (Config_Alib_to_Alib, info); fcr(info); + Config_analyze_species (Config_Alib_to_Alib, info); fcr(info); + } + + return(CONFIG_CFG_LOADED); +} + +void p3dp_config_scatter(Alib_Declare_Config) +{ + int mg, ml, k; + Auxiliary auxiliary; + + if (!p3dp_enabled) + return; + + p3d_set_atoms(p3dp_cell, p3d_atom_begin(p3dp_cell), 0); + auxiliary = p3dp_cell->auxiliary; + if (!p3d_rank(p3dp_cell)) { + int n; + P3DAtom *atoms = (P3DAtom*) malloc(*np * sizeof(P3DAtom)), *p = atoms; + + if (!atoms) p3d_abort(-1); + M3EQV(H, p3dp_cell->h); + for (n = 0; n < *np; n++,p++) { + p->m = (*mass)[n]; + strncpy(p->sym, SYMBOL(n), 3); + p->r[0] = (*s )[n * DIMENSION ]; + p->r[1] = (*s )[n * DIMENSION + 1]; + p->r[2] = (*s )[n * DIMENSION + 2]; + for (k = 0; k < CONFIG_num_auxiliary; k++) + p->aux[k] = CONFIG_auxiliary[k][n]; + } + p3d_set_atoms(p3dp_cell, atoms, *np); + free(atoms); + + if ((auxiliary->n_aux = CONFIG_num_auxiliary)) { + for (k = 0; k < CONFIG_num_auxiliary; k++) { + strncpy(auxiliary->name[k],CONFIG_auxiliary_name[k],P3D_LINEMAX); + strncpy(auxiliary->unit[k],CONFIG_auxiliary_unit[k],P3D_LINEMAX); + } + } + } + + p3d_bcast(p3dp_cell, p3dp_cell->h, 9, MPI_DOUBLE, 0); + do { + ml = p3d_reset_cell(p3dp_cell); + p3d_reduce(p3dp_cell, &ml, &mg, 1, MPI_INT, MPI_SUM); + } while (mg); + M3EQV(p3dp_cell->h, H); + + p3d_bcast(p3dp_cell, &CONFIG_num_auxiliary, 1, MPI_INT, 0); + if (CONFIG_num_auxiliary) { + p3d_bcast(p3dp_cell, auxiliary,sizeof(struct Auxiliary_tag),MPI_CHAR,0); + if (p3d_rank(p3dp_cell)) { + for (k = 0; k < CONFIG_num_auxiliary; k++) { + strncpy(CONFIG_auxiliary_name[k], auxiliary->name[k], TERMSIZE); + strncpy(CONFIG_auxiliary_unit[k], auxiliary->unit[k], TERMSIZE); + } + } + } + + p3dp_config_add_image(Config_Alib_to_Alib); +} + + +int p3dp_Config_Load(char *fname, FILE *info, Alib_Declare_Config) +{ + char *p, *q; + + if (strcmp(config_fname, "/dev/null") == 0) { + if (IS_MANAGER) + cui_config_load_A3(Config_Alib_to_Alib); + if (p3dp_enabled) + p3dp_config_scatter(Config_Alib_to_Alib); + return CONFIG_CFG_LOADED; + } + else if (!p3dp_enabled) + return Config_Load(fname, info, Config_Alib_to_Alib); + + if (!IS_MANAGER) + info = NULL; + + Fprintf(info, "Guessing file format of \"%s\":\n", fname); + p = strrchr(fname, '/'); + if (p == NULL) p = fname; + q = strchr(p, '.'); + if (q != NULL) { + p = strrstr(q, "cfg"); + if (p != NULL) { + if (strstr(p, "pdb") || strstr(p, "PDB")) + goto PDB; + } + else if (strstr(q, "pdb") || strstr(q, "PDB")) + goto PDB; + } + Fprintf(info, "should be Ju Li's CFG format.\n\n"); + p3dp_Config_load(fname, info, Config_Alib_to_Alib); + return CONFIG_CFG_LOADED; + PDB: + Fprintf(info, "should be Protein Data Bank format.\n\n"); + + if (IS_MANAGER) { + Config_load_from_pdb(fname, info, Config_Alib_to_Alib); + Config_to_bounding_box_config(Config_Alib_to_Alib,info); + } + p3dp_config_scatter(Config_Alib_to_Alib); + + return CONFIG_CFG_LOADED; /*return CONFIG_PDB_LOADED;*/ +} /* end Config_Load() */ + + + +void p3dp_CalculateSimpleStatistics +(int N, char *series, int bytes_separation, int valtype, SimpleStatistics *s) +{ + int i, nn; + char *p; + double val; + + if (!p3dp_enabled) { + CalculateSimpleStatistics(N, series, bytes_separation, valtype, s); + return; + } + + nn = p3d_n_atoms(p3dp_cell); + p3d_reduce(p3dp_cell, &nn, &N, 1, MPI_INT, MPI_SUM); + + if (N < 1) + { + s->N = 0; + s->idx_min = -1; + s->min = 0; + s->idx_max = -1; + s->max = 0; + s->average = 0; + s->variance = 0; + s->standard_deviation = 0; + return; + } + + s->N = N; + s->idx_min = 0; + s->min = IOVAL(series,valtype); + s->idx_max = 0; + s->max = IOVAL(series,valtype); + s->average = 0; + s->variance = 0; + + for (i=0,p=series; imin) + { + s->idx_min = i; + s->min = val; + } + if (val > s->max) + { + s->idx_max = i; + s->max = val; + } + s->average += val; + s->variance += val*val; + } + + { + double og[2], ol[2], min_l, max_l; + ol[0] = s->average; + ol[1] = s->variance; + p3d_reduce(p3dp_cell, ol, og, 2, MPI_DOUBLE, MPI_SUM); + s->average = og[0]; + s->variance = og[1]; + min_l = s->min; + p3d_reduce(p3dp_cell, &min_l, &s->min, 1, MPI_DOUBLE, MPI_MIN); + if (s->min != min_l) + s->idx_min = -1; + max_l = s->max; + p3d_reduce(p3dp_cell, &max_l, &s->max, 1, MPI_DOUBLE, MPI_MAX); + if (s->max != max_l) + s->idx_max = -1; + } + + s->average /= N; + s->variance -= N*s->average*s->average; + if (N>1) s->variance /= (N-1); + else s->variance = 0; + s->standard_deviation = sqrt(s->variance); +} + + +void p3dp_bcast_int2(int *val0, int *val1) +{ + if (p3dp_enabled) { + int val[2]; + val[0] = *val0; + val[1] = *val1; + p3d_bcast(p3dp_cell, val, 2, MPI_INT, 0); + *val0 = val[0]; + *val1 = val[1]; + } +} + + +void p3dp_zmap_reduce(int iw) +{ + if (p3dp_enabled) { + static int size_zmap_mem_uc[AX_MAXWIN] = {0}; + static struct ax_float_int { + AX_Float zmap; + int mem_uc; + } *zmap_mem_uc_l[AX_MAXWIN] = {0}, *zmap_mem_uc_g[AX_MAXWIN] = {0}; + int i, n = AX_size[iw].width*AX_size[iw].height; + /*if (AX_bytes > sizeof(int)) p3d_abort(-1);*/ + + if (n > size_zmap_mem_uc[iw]) { + int size = n * sizeof(struct ax_float_int); + if (!(zmap_mem_uc_l[iw] = + (struct ax_float_int*) realloc(zmap_mem_uc_l[iw], size)) || + !(zmap_mem_uc_g[iw] = + (struct ax_float_int*) realloc(zmap_mem_uc_g[iw], size))) + p3d_abort(-2); + size_zmap_mem_uc[iw] = n; + } + + for(i = 0; i < n; i++ ) { + zmap_mem_uc_l[iw][i].zmap = AX_zmap[iw][i]; + zmap_mem_uc_l[iw][i].mem_uc = *(int *)&AX_mem[iw].uc[AX_bytes*i]; + } + p3d_reduce(p3dp_cell, zmap_mem_uc_l[iw], zmap_mem_uc_g[iw], + n, MPI_AX_FLOAT_INT, MPI_MINLOC); + if (!p3d_rank(p3dp_cell)) { + for (i = 0; i < n; i++) + *(int *)&AX_mem[iw].uc[AX_bytes*i]= zmap_mem_uc_g[iw][i].mem_uc; + } + for(i = 0; i < n; i++) + AX_zmap[iw][i] = zmap_mem_uc_g[iw][i].zmap; + } +} + + + +void p3dp_atom_stack_insert(int iw, int atom, int rank) +{ + int i; + for (i=ATOM_STACK_SIZE-1; i>0; i--) + n[iw].atom_stack[i] = n[iw].atom_stack[i-1]; + n[iw].atom_stack[0] = atom; + if (p3dp_enabled) { + for (i=ATOM_STACK_SIZE-1; i>0; i--) { + p3dp_n[iw].rank_stack[i] = p3dp_n[iw].rank_stack[i-1]; + } + p3dp_n[iw].rank_stack[0] = rank; + } + return; +} + + +/* AX */ + +int p3dp_AXNextEvent(int iw) +{ + if (p3dp_enabled) { + int value[AX_MAXWIN]; + if (!p3d_rank(p3dp_cell)) + value[iw] = AXNextEvent(iw); + p3d_bcast(p3dp_cell, &AX_event[iw], sizeof(XEvent), MPI_BYTE, 0); + p3d_bcast(p3dp_cell, &value[iw], 1, MPI_INT, 0); + return value[iw]; + } + else + return AXNextEvent(iw); +} + + +int p3dp_AXQLength(int iw) +{ + if (p3dp_enabled) { + int value[AX_MAXWIN]; + if (!p3d_rank(p3dp_cell)) + value[iw] = AXQLength(iw); + p3d_bcast(p3dp_cell, &value[iw], 1, MPI_INT, 0); + return value[iw]; + } + else + return AXQLength(iw); +} + +int p3dp_AXPending(int iw) +{ + if (p3dp_enabled) { + int value[AX_MAXWIN]; + if (!p3d_rank(p3dp_cell)) + value[iw] = AXPending(iw); + p3d_bcast(p3dp_cell, &value[iw], 1, MPI_INT, 0); + return value[iw]; + } + else + return AXPending(iw); +} + + +Status p3dp_AXGetGeometry(int iw, AXSize *newsize) +{ + if (p3dp_enabled) { + Status value[AX_MAXWIN]; + if (!p3d_rank(p3dp_cell)) + value[iw] = AXGetGeometry(iw, (*newsize)); + p3d_bcast(p3dp_cell, newsize, sizeof(AXSize), MPI_BYTE, 0); + p3d_bcast(p3dp_cell, &value[iw], sizeof(Status), MPI_BYTE, 0); + return value[iw]; + } + else + return AXGetGeometry(iw, (*newsize)); +} + + +Bool p3dp_AXQueryPointer(int iw) +{ + if (p3dp_enabled) { + Bool value[AX_MAXWIN]; + if (!p3d_rank(p3dp_cell)) + value[iw] = AXQueryPointer(iw); + p3d_bcast(p3dp_cell, &value[iw], sizeof(Bool), MPI_CHAR, 0); + return value[iw]; + } + else + return AXQueryPointer(iw); +} + + +KeySym p3dp_AXKeysym0(int iw) +{ + if (p3dp_enabled) { + KeySym value[AX_MAXWIN]; + if (!p3d_rank(p3dp_cell)) + value[iw] = AXKeysym0(iw); + p3d_bcast(p3dp_cell, &value[iw], sizeof(KeySym), MPI_CHAR, 0); + return value[iw]; + } + else + return AXKeysym0(iw); +} + + +/* Atoms/Neighborlist.c */ + +#undef NEIGHBORLIST_BINATOM_RATIO +#define NEIGHBORLIST_BINATOM_RATIO P3DP_NEIGHBORLIST_BINATOM_RATIO +#undef NEIGHBORLIST_BINDEXS +#define NEIGHBORLIST_BINDEXS(N,s,i) p3dp_neighborlist_bindexs(N,s,i) +#define LIST_DISPOSABLE(N) \ + (((N)->min_shrinkage == 1) && ((N)->max_atom_displacement == 0)) +static int nbin_g[3], nbin_o[3]; +static int p3dp_neighborlist_bindexs(Neighborlist *N, double *s, int i) +{ + int j, ii[3]; + for (j = 0; j < DIMENSION; j++) { + ii[j] = INT(s[DIMENSION*i+j]*nbin_g[j]) - nbin_o[j]; + if (ii[j] < 0) ii[j] = N->nbin[j] - 1; + else if (ii[j] > N->nbin[j] - 1) ii[j] = 0; + } + return NEIGHBORLIST_BINDEX(N, ii[0], ii[1], ii[2]); +} + +/* Recreate neighborlist according to submitted form */ +void p3dp_Neighborlist_Recreate +(Alib_Declare_Config, FILE *info, Chemtab *ct, Tp **tp, Neighborlist *N) +{ + register int i, m; + int j, k, di, dj, dk, ii, jj, kk, l, n; + double rmax, thickness[DIMENSION], ds[DIMENSION], dx[DIMENSION]; + + /* Verify the only assumption of this program */ + for (i=0; i<*np; i++) + { + /* if (IN( (*s)[DIMENSION*i], -EPS, 0 )) (*s)[DIMENSION*i] = 0; */ + /* if (IN( (*s)[DIMENSION*i+1], -EPS, 0 )) (*s)[DIMENSION*i+1] = 0; */ + /* if (IN( (*s)[DIMENSION*i+2], -EPS, 0 )) (*s)[DIMENSION*i+2] = 0; */ + if ( V3NEED_TRIM(&((*s)[DIMENSION*i])) ) + { + Fprintf(info, "** %s atom (1-%d) has\n""** s = (%g %g %g)\n", + word_for_order(i+1), *np, (*s)[DIMENSION*i], + (*s)[DIMENSION*i+1], (*s)[DIMENSION*i+2]); + V3mM3( &((*s)[DIMENSION*i]), H, dx ); + V3MuL( ulength_IN_A, dx ); + Fprintf(info, "** or x = (%g %g %g) A.\n\n", dx[0], dx[1], dx[2]); + Fprintf(info, "This is impermissible for constructing " + "neighborlist,\n"); + if (N->s_overflow_err_handler == + NEIGHBORLIST_S_OVERFLOW_ERR_HANDLER_QUIT) + pe ("Neighborlist_Recreate() exiting...\n"); + else if (N->s_overflow_err_handler == + NEIGHBORLIST_S_OVERFLOW_ERR_HANDLER_FOLD_INTO_PBC) + { /* even though the user may not mean PBC */ + Fprintf(info, "so we have to fold all atoms into [0,1).\n\n"); + Config_fold_into_PBC (Config_Alib_to_Alib); + break; + } + else /* NEIGHBORLIST_S_OVERFLOW_ERR_HANDLER_BOUNDING_BOX */ + { /* even though the user may mean PBC */ + Fprintf(info, "so we use BOUNDING BOX as H[][] instead:\n\n"); + Config_to_bounding_box_config(Config_Alib_to_Alib,info); + Fcr(info); + break; + } + } + } + + /* Also check RCUT symmetry in the case of pairwise interaction */ + if (N->pairwise) + for (i=0; it; i++) + for (j=i+1; jt; j++) + if (NEIGHBOR_TABLE(N->rcut,ct,i,j) != + NEIGHBOR_TABLE(N->rcut,ct,j,i)) + { + Fprintf(info, "Warning: rcut[%d][%d] != " + "rcut[%d][%d]\n", i,j, j,i); + Fprintf(info, "-> %f will be used for both.\n\n", + NEIGHBOR_TABLE(N->rcut,ct,i,j)= + NEIGHBOR_TABLE(N->rcut,ct,j,i)= + MAX(NEIGHBOR_TABLE(N->rcut,ct,i,j), + NEIGHBOR_TABLE(N->rcut,ct,j,i))); + } + + /* Print out the form */ + Fprintf(info, "Create neighborlist with the following parameters:\n"); + Fprintf(info, "pairwise saving = %s, track_dx = %s\n", + BWORD(N->pairwise), BWORD(N->track_dx)); + for (i=0; ipbc[i])); + Fcr(info); + Fprintf(info, "Strain Session min_shrinkage = %g,\n" + "All Atom Tether max_atom_displacement = %g (reduced),\n", + N->min_shrinkage, N->max_atom_displacement); + if ( (N->min_shrinkage > 1) || (N->min_shrinkage <= 0) ) + pe ("Neighborlist_Recreate: min_shrinkage must be (0,1].\n\n"); + if ( N->max_atom_displacement < 0 ) + pe ("Neighborlist_Recreate: max_atom_displacement must be >= 0.\n\n"); + + REALLOC( Neighborlist_Recreate_Form, N->rlist, SQUARE(ct->t), double ); + if (LIST_DISPOSABLE(N)) + { + Fprintf(info, "-> COMPRESSED disposable atom-atom list\n" + "with Rlist_ij = Rcut_ij;\n\n"); + VEQV( SQUARE(ct->t), N->rcut, N->rlist ); + } + else + { + Fprintf(info, "-> UNCOMPRESSED reusable atom-atom list\n" + "with %g x Rlist_ij = Rcut_ij + 2 x %g;\n\n", + N->min_shrinkage, N->max_atom_displacement); + if (info) Sfpr(info, "Rcut = %M (reduced)\n ", N->rcut, ct->t,ct->t); + for (i=0; it; i++) + for (j=0; jt; j++) + NEIGHBOR_TABLE(N->rlist,ct,i,j) = + (NEIGHBOR_TABLE(N->rcut,ct,i,j) + + 2 * N->max_atom_displacement) / N->min_shrinkage; + } + + for (i=0; it; i++) + for (j=0; jt; j++) + if (NEIGHBOR_TABLE(N->rcut,ct,i,j) <= 0) + NEIGHBOR_TABLE(N->rlist,ct,i,j) = 0; + + REALLOC( Neighborlist_Recreate_Form, N->rlist2, SQUARE(ct->t), double ); + for (i=0; it; i++) + for (j=0; jt; j++) + NEIGHBOR_TABLE(N->rlist2,ct,i,j) = + SQUARE(NEIGHBOR_TABLE(N->rlist,ct,i,j)); + + if (info) Sfpr(info, "rlist = %M (reduced)\n ", N->rlist, ct->t,ct->t); + rmax = VMAX (SQUARE(ct->t), N->rlist); + Fprintf(info, "MAX(rlist) = %g -> bin thicknesses should >= %g\n", + rmax, rmax); + + restart: + M3rowthicknesses (H, thickness); + if (info) Vfpr(info, "since H thicknesses = %M", thickness, DIMENSION); + + if ( N->small_cell_err_handler == + NEIGHBORLIST_SMALL_CELL_ERR_HANDLER_MULTIPLY ) + { + ii = ceil(2*rmax / thickness[0]); + jj = ceil(2*rmax / thickness[1]); + kk = ceil(2*rmax / thickness[2]); + if ( (ii > 1) || (jj > 1) || (kk > 1) ) + { + Config_multiply ( ii, jj, kk, Config_Alib_to_Alib ); + rebind_CT (Config_Alib_to_Alib, "", ct, tp); + goto restart; + } + } + + N->nbin[DIMENSION] = 1; + for (i=0; ipbc[i] && (thickness[i] < 2*rmax) && + (N->small_cell_err_handler != + NEIGHBORLIST_SMALL_CELL_ERR_HANDLER_NOCHECK) ) + pe ("Neighborlist_Recreate: losing rnbin[i] = thickness[i] / rmax / p3dp_cell->private->dims[i]; + if (N->nbin[i] < 1) N->nbin[i] = 1; + if (N->nbin[i] > NEIGHBORLIST_MAXBIN) N->nbin[i]=NEIGHBORLIST_MAXBIN; + nbin_g[i] = N->nbin[i] * p3dp_cell->private->dims[i]; + nbin_o[i] = N->nbin[i] * p3dp_cell->private->coords[i]; + N->nbin[DIMENSION] *= N->nbin[i]; + } + Fprintf(info, "-> %d x ", N->nbin[0]); + for (i=1; inbin[i]); + Fprintf(info, "%d = %d bins.\n", N->nbin[DIMENSION-1], + N->nbin[DIMENSION]); + + /* bin-bin: prepare for maximal bin connectivity */ + N->binbinlist = Irecreatelist + (&N->binbindx, N->nbin[DIMENSION], DIMENSION3); + for (i=0; inbin[0]; i++) + for (j=0; jnbin[1]; j++) + for (k=0; knbin[2]; k++) + { + l = NEIGHBORLIST_BINDEX(N,i,j,k); + for (di=-1; di<=1; di++) + for (dj=-1; dj<=1; dj++) + for (dk=-1; dk<=1; dk++) + { + ii = i + di; + jj = j + dj; + kk = k + dk; + if (ii >= N->nbin[0]) + { + if (N->pbc[0]) ii-=N->nbin[0]; else continue; + } + if (ii < 0) + { + if (N->pbc[0]) ii+=N->nbin[0]; else continue; + } + if (jj >= N->nbin[1]) + { + if (N->pbc[1]) jj-=N->nbin[1]; else continue; + } + if (jj < 0) + { + if (N->pbc[1]) jj+=N->nbin[1]; else continue; + } + if (kk >= N->nbin[2]) + { + if (N->pbc[2]) kk-=N->nbin[2]; else continue; + } + if (kk < 0) + { + if (N->pbc[2]) kk+=N->nbin[2]; else continue; + } + m = NEIGHBORLIST_BINDEX(N,ii,jj,kk); + /* make sure it is a new record */ + for (n=N->binbindx[2*l]; nbinbindx[2*l+1]; n++) + if (m == N->binbinlist[n]) break; + if (n == N->binbindx[2*l+1]) + N->binbinlist[N->binbindx[2*l+1]++] = m; + } + } + Fprintf(info, "bin-bin list created.\n\n"); + + /* it is reasonable to assume that bin-connectivity never changes */ + N->binbinlist = Icompresslist (&N->binbindx, N->nbin[DIMENSION]); + Ilist_statistics ("bin-bin", N->binbindx, N->nbin[DIMENSION], TRUE, info); + Fcr(info); + + Fprintf(info, "On average, there are %.2f atoms per bin,\n" + "but we will offer space of %d for each.\n", + DOUBLE(*np) / N->nbin[DIMENSION], n = ceil + (DOUBLE(*np) / N->nbin[DIMENSION] * NEIGHBORLIST_BINATOM_RATIO)); + N->binlist = Irecreatelist (&N->bindx, N->nbin[DIMENSION], n); + REALLOC( Neighborlist_Recreate, N->mybin, *np, int ); + + /* bin-atom: fill atoms into bins */ + for (i=0; i<*np; i++) + Iappend(N->bindx, N->binlist, i, N->mybin[i]= + NEIGHBORLIST_BINDEXS(N,*s,i), 0, N->nbin[DIMENSION]); + Fprintf(info, "bin-atom list created.\n\n"); + + Ilist_statistics("bin-atom", N->bindx, N->nbin[DIMENSION], FALSE, info); + Fcr(info); + + /* atom-atom */ + for (n=i=0; it; i++) + { + if ( N->pairwise && (!N->keepcounter) ) + N->neighbormax[i] = N->neighbormax[i] / 2; + if (rmax == 0) N->neighbormax[i] = 0; + n += N->neighbormax[i] * ct->count[i]; + } + if (N->pairwise) Fprintf(info, "After pairwise/own_pair saving,\n"); + if (info) + ifpr(info, "likely MAX(neighbor) = %M atoms,", N->neighbormax, ct->t); + REALLOC( Neighborlist_Recreate, N->idx, 2*(*np)+1+n, int ); + N->idx[0] = N->idx[1] = 0; + for (i=1; i<*np; i++) + N->idx[2*i] = N->idx[2*i+1] = + N->idx[2*i-1]+N->neighbormax[(int)(*tp)[i-1]]; + if ( (N->idx[2*(*np)]=n) != N->idx[2*i-1]+N->neighbormax[(int)(*tp)[i-1]] ) + pe ("Neighborlist_Recreate: checksum failed.\n"); + N->list = &N->idx[2*(*np)] + 1; + if (rmax == 0) goto DoNotCompute; + for (i=0; i<*np; i++) + { /* already compressed bin-bin list */ + ii = N->binbindx[N->mybin[i]]; + jj = N->binbindx[N->mybin[i]+1]; + for (j=ii; jbinbinlist[j]; + for (k=N->bindx[2*l]; kbindx[2*l+1]; k++) + { /* particles in neighboring bins */ + m = N->binlist[k]; + if (N->pairwise && (!own_pair(i,m))) continue; + if (i == m) continue; + V3SUB ( &((*s)[DIMENSION*m]), &((*s)[DIMENSION*i]), ds); + if (N->pbc[0]) Image(ds[0]); + if (N->pbc[1]) Image(ds[1]); + if (N->pbc[2]) Image(ds[2]); + V3mM3 (ds, H, dx); + if (V3LENGTH2(dx) < + NEIGHBOR_TABLE(N->rlist2,ct,(*tp)[i],(*tp)[m])) + Iappend (N->idx, N->list, m, i, 0, *np); + } + } + } + DoNotCompute: + Fprintf(info, "atom-atom list created.\n\n"); + Ilist_statistics ("atom-atom", N->idx, *np, FALSE, info); + Fcr(info); + + M3EQV (H, N->H0); + if (LIST_DISPOSABLE(N)) + { + N->list = Icompresslist (&N->idx, *np); + Ilist_statistics ("atom-atom", N->idx, *np, TRUE, info); + Fcr(info); + Ifreelist (&N->binbindx, &N->binbinlist); + Ifreelist (&N->bindx, &N->binlist); + Free (N->mybin); + Fprintf(info, "All bin-related allocations freed.\n"); + } + else /* LIST_REUSABLE(N)) */ + { + if (!N->keepcounter) N->remesh_counter = 0; + REALLOC (Neighborlist_Recreate, N->sa, DIMENSION*(*np), double); + VEQV (DIMENSION*(*np), (*s), N->sa); + Fprintf (info, "Particle anchors established.\n"); + REALLOC (Neighborlist_Recreate, N->maxtether2, ct->t, double); + VMaX (ct->t, N->neighbormax, i, N->stack_max); + N->stack_max *= NEIGHBORLIST_STACK_MAX_RATIO; + REALLOC (Neighborlist_Recreate, N->stack, N->stack_max, int); + if (!N->keepcounter) N->reanchor_counter = 0; + if (N->track_dx) + { + REALLOC (Neighborlist_Recreate, N->dx, 2*DIMENSION*(*np), double); + N->dxa = N->dx + DIMENSION*(*np); + if (!N->keepcounter) + { + VZERO (2*DIMENSION*(*np), N->dx); + Fprintf (info, "dx tracking initiated, counters cleared.\n"); + } + } + if (!N->keepcounter) N->maintenance_counter = 0; + } + N->keepcounter = TRUE; + return; +} diff -urN A/p3dp.h A3/p3dp.h --- A/p3dp.h 1970-01-01 09:00:00.000000000 +0900 +++ A3/p3dp.h 2011-02-22 15:15:37.000000000 +0900 @@ -0,0 +1,141 @@ +/* 2004-2005 Futoshi Shimizu */ +#ifndef P3DPATCH_H +#define P3DPATCH_H + +#ifndef USE_CUI +# error +#else +# include "cui.h" +#endif + +#include "P3DExt.h" +#include "P3D.h" + +#include "A.h" +#include + +#define P3DP_NEIGHBORLIST_BINATOM_RATIO 4.0 /* 3.0 */ + +#define Neighborlist_Recreate(Config_Alib_to_Alib,info,ct,tp,N) do {\ + if (p3dp_enabled)\ + p3dp_Neighborlist_Recreate(Config_Alib_to_Alib,info,ct,tp,N);\ + else Neighborlist_Recreate(Config_Alib_to_Alib,info,ct,tp,N);\ + } while (0) + +#ifndef P3DP_GLOBAL + +# define CalculateSimpleStatistics(N, series, bytes_separation, valtype, s)\ + p3dp_CalculateSimpleStatistics(N, series, bytes_separation, valtype, s) + +# undef AXNextEvent +# define AXNextEvent(iw) p3dp_AXNextEvent(iw) +# undef AXQLength +# define AXQLength(iw) p3dp_AXQLength(iw) +# undef AXPending +# define AXPending(iw) p3dp_AXPending(iw) +# undef AXGetGeometry +# define AXGetGeometry(iw,newsize) p3dp_AXGetGeometry(iw,&(newsize)) +# undef AXQueryPointer +# define AXQueryPointer(iw) p3dp_AXQueryPointer(iw) +# undef AXKeysym0 +# define AXKeysym0(iw) p3dp_AXKeysym0(iw) + +# undef AX_openwindow +# define AX_openwindow p3dp_AX_openwindow +/* +# define AX_openwindow(cid, title, width, height) \ + ((cui_enabled >= 0 && (p3dp_enabled < 1 || !p3d_rank(p3dp_cell)))\ + ? AX_openwindow( cid, title, width, height)\ + : cui_AX_openwindow(-1*(cid), title, width, height)) +*/ +# undef AX_resizewindow +# define AX_resizewindow p3dp_AX_resizewindow +# undef AX_closewindow +# define AX_closewindow p3dp_AX_closewindow +int p3dp_AX_openwindow +(int cid, char *title, unsigned int width, unsigned int height); +void p3dp_AX_resizewindow (int iw, Bool do_window_too); +void p3dp_AX_closewindow (int iw); + +# define AX_3D_Balls_Zdet(iw, B)\ + switch (p3dp_enabled) {\ + case 0: AX_3D_Balls_Zdet(iw, B); break;\ + default: p3dp_AX_3D_Balls_Zdet(iw, B); break;} + +# define AX_3D_Cylinders_Zdet(iw, C)\ + switch (p3dp_enabled) {\ + case 0: AX_3D_Cylinders_Zdet(iw, C); break;\ + default: p3dp_AX_3D_Cylinders_Zdet(iw, C); break;} + +# define P3DP_GLOBAL extern +#endif + +P3DP_GLOBAL Cell p3dp_cell; +P3DP_GLOBAL jmp_buf quit_env; +P3DP_GLOBAL int p3dp_enabled; +P3DP_GLOBAL char *p3dp_decomp; +P3DP_GLOBAL char **p3dp_mpiexec_argv; +P3DP_GLOBAL int p3dp_mpiexec_argc; +P3DP_GLOBAL int p3dp_rank_grab; +P3DP_GLOBAL char p3dp_spec[(MENDELEYEV_MAX+1)*SYMBOL_CHAR+1]; + +typedef struct { + int rank_stack[ATOM_STACK_SIZE]; +} P3DP_Navigator; +P3DP_GLOBAL P3DP_Navigator p3dp_n[AX_MAXWIN]; + +#undef IS_MANAGER +#define IS_MANAGER (!p3dp_enabled || !p3d_rank(p3dp_cell)) + +#undef CONFIG_LOAD +#define CONFIG_LOAD(fname,Config_Alib_to_Alib) \ + p3dp_Config_Load(fname,stdout,Config_Alib_to_Alib) + +#undef rebind_CT +#define rebind_CT(Config_Alib_to_Alib, specification, ct, tp) (!p3dp_enabled) ?\ + rebind_ct(Config_Alib_to_Alib, specification, ct, tp, stdout) :\ + rebind_ct(Config_Alib_to_Alib, p3dp_spec, ct, tp,\ + (IS_MANAGER) ? stdout : NULL) + +#define p3dp_Bcast(buf, count, type) do { if (p3dp_enabled) \ + p3d_bcast(p3dp_cell, buf, count, type, 0); } while (0) + + +int p3dp_init(int *argc, char ***argv); +int p3dp_finalize(void); +int p3dp_Config_Load(char *fname, FILE *info, Alib_Declare_Config); +void p3dp_config_scatter(Alib_Declare_Config); +void p3dp_zmap_reduce(int iw); +void p3dp_atom_stack_insert(int iw, int atom, int rank); +void p3dp_CalculateSimpleStatistics +(int N, char *series, int bytes_separation, int valtype, SimpleStatistics *s); +void p3dp_bcast_int2(int *val0, int *val1); + +int p3dp_AXNextEvent(int iw); +int p3dp_AXQLength(int iw); +int p3dp_AXPending(int iw); +int p3dp_AX_plugin_3D_module(int iw); +Status p3dp_AXGetGeometry(int iw, AXSize *newsize); +Bool p3dp_AXQueryPointer(int iw); +KeySym p3dp_AXKeysym0(int iw); + +void p3dp_Neighborlist_Recreate +(Alib_Declare_Config, FILE *info, Chemtab *ct, Tp **tp, Neighborlist *N); + +/* p3dp_info.c */ +void p3dp_s(double *si, int i, int irank); +void p3dp_atom_pair_s(double *sj, double *si, double dxji[4]); +double p3dp_atom_triplet_s +(double *sk, double *sj, double *si, double dxkj[4], double dxij[4]); +void p3dp_print_atom_pair_info(int iw, int j, int i, int jrank, int irank); +void p3dp_print_atom_triplet_info +(int iw, int k, int j, int i, int krank, int jrank, int irank); +void p3dp_print_atom_quartet_info +(int iw, int l, int k, int j, int i, int lrank, int krank, int jrank,int irank); + +/* p3dp_AX.c */ +void p3dp_AX_3D_Balls_Zdet(int iw, AX_3D_Balls *B); +int p3dp_AX_3D_Balls_Zgrab(int iw, AX_3D_Balls *B, int gi, int gj, int *rank); +void p3dp_AX_3D_Cylinders_Zdet(int iw, AX_3D_Cylinders *C); +int p3dp_AX_3D_Cylinders_Zgrab(int iw,AX_3D_Cylinders*C,int gi,int gj,int*rank); +#endif diff -urN A/p3dp_AX.c A3/p3dp_AX.c --- A/p3dp_AX.c 1970-01-01 09:00:00.000000000 +0900 +++ A3/p3dp_AX.c 2011-02-22 15:15:37.000000000 +0900 @@ -0,0 +1,717 @@ +#include "AX/3D.c" +#include "p3dp.h" + +typedef struct { + double d; + int i; +} double_int; + +/* Calculate coordinates in viewport frame and determine visibility */ +void p3dp_AX_3D_Balls_Zdet (int iw, AX_3D_Balls *B) +{ + register AX_3D_Ball *ball=NULL; + register int i, m; + register AX_Float tmp=0; + int j, fp_activated, activated[AX_3D_MAX_FILTER_PLANE], i_g, i_l; + AX_Float dx[3]; + for (fp_activated=0,j=0; jn_shown = 0; + for (i=B->n_balls; i--;) + { + ball = B->BALL + i; + if (ball->r < 0) continue; /* invisibility flag */ + if (fp_activated) + { + for (j=0; jx) < + AX_3D[iw].fp[j].d0-AX_TINY ) + break; + if (jx, AX_3D[iw].x, dx); + /* if viewpoint inside the ball, initiate ejection */ + tmp = AX_V3LENGTH2(dx); + if (tmp <= SQUARE(ball->radius)) break; + /* convert to viewframe coordinates */ + ball->vx[2] = AX_V3DOT(AX_3D[iw].V[2], dx); + /* must be in (0,zcut) view frustum */ + if ((ball->vx[2] <= 0) || + (ball->vx[2] > AX_3D[iw].zcut)) continue; + /* now ball is at front and not enclosing the viewpoint */ + tmp = AX_3D[iw].k / ball->vx[2]; + ball->vx[0] = AX_V3DOT(AX_3D[iw].V[0], dx) * tmp + AX_3D[iw].wx; + ball->vx[1] = AX_V3DOT(AX_3D[iw].V[1], dx) * tmp + AX_3D[iw].wy; + tmp *= ball->radius; + if ( OU(ball->vx[0],-tmp,AX_size[iw].width+tmp) || + OU(ball->vx[1],-tmp,AX_size[iw].height+tmp) ) continue; + B->status[i] = 0; + if (tmp < AX_BC_rmax[iw]) + { + B->status[i] |= AX_3D_BALL_CACHED; + ball->vs.bc = &AX_bc[iw][INT(tmp*AX_BC_RMESH)]; + /* circle center quantization (periodic) */ + FLOOR(ball->vx[0], ball->i0); + FLOOR(ball->vx[1], ball->j0); + ball->vx[0] = ball->i0 + 0.5; + ball->vx[1] = ball->j0 + 0.5; + tmp = ball->vs.bc->radius; + } + if ( AX_CircleIntersectWindowBorder + ( ball->vx[0], ball->vx[1], tmp, + AX_size[iw].width, AX_size[iw].height ) ) + B->idx[B->n_shown++] = i; + else if ( AX_XYINWIN(iw, ball->vx[0], ball->vx[1]) ) + { + B->idx[B->n_shown++] = i; + B->status[i] |= AX_3D_BALL_COMPLETE; + } + } + + i_l = i; + p3d_reduce(p3dp_cell, &i_l, &i_g, 1, MPI_INT, MPI_MAX); + + if (i_g >= 0) /* viewpoint ejection */ + { + double_int di_g, di_l; + di_l.d = tmp; + di_l.i = p3d_rank(p3dp_cell); + p3d_reduce(p3dp_cell, &di_l, &di_g,1,MPI_DOUBLE_INT,MPI_MINLOC); + if (di_g.i == p3d_rank(p3dp_cell)) { + if (tmp == 0) + AX_V3ADDMUL( AX_3D[iw].x, ball->radius * (1+AX_TINY), + AX_3D[iw].V[2] ); + else + { + tmp = ball->radius * (1+AX_TINY) / sqrt(tmp) - 1; + AX_V3SUBMUL( AX_3D[iw].x, tmp, dx ); + } + if (m >= 3) + { + AX_V3sub (AX_3D[iw].x, ball->x, dx); + AX_3D[iw].x[0] += Frandom() * dx[0]; + AX_3D[iw].x[1] += Frandom() * dx[1]; + AX_3D[iw].x[2] += Frandom() * dx[2]; + } + } + if (m >= 1000) pe ("AX_3D_Balls_Zdet: viewpoint ejection failed\n"); + p3d_bcast(p3dp_cell, AX_3D[iw].x, 3, MPI_DOUBLE, di_g.i); + } + else break; + } + AX_sort_3D_Balls(B); + return; +} /* end AX_3D_Balls_Zdet() */ + +/* Find out the index of the topmost ball at a given pixel */ +/* after Zpaper/ZBprint(); return -1 if there is no match. */ +int p3dp_AX_3D_Balls_Zgrab (int iw, AX_3D_Balls *B, int gi, int gj, int *rank) +{ + register AX_3D_Ball *ball; + register int m,goffset,k; + register AX_Float *base, vradius, x2, y2, r2; + register AX_BC_Unit *b; + int i; + double_int di_g, di_l = {AX_INFINITY, 0}; + if (AX_IJOUWIN(iw,gi,gj)) goto not_found; + goffset = AX_OFF(iw,gi,gj); + for (i=0; in_shown; i++) + { + ball = B->BALL + B->idx[i]; + vradius = AX_3D[iw].k / ball->vx[2] * ball->radius; + x2 = SQUARE(gi+0.5-ball->vx[0]); + y2 = SQUARE(gj+0.5-ball->vx[1]); + r2 = SQUARE(vradius); + if (x2 + y2 < r2) + { + if (B->status[B->idx[i]] & AX_3D_BALL_CACHED) + { + k = AX_OFF(iw, ball->i0, ball->j0); + base = AX_zmap[iw] + k; + k = goffset - k; + b = ball->vs.bc->b; + for (m=ball->vs.bc->nb; m--;) + if ((b[m].offset == k) && + (ball->vx[2] - b[m].c1 * ball->radius < + base[b[m].offset] * (1+AX_TINY))) + goto found; + b = ball->vs.bc->a; + for (m=ball->vs.bc->na; m--;) + if ((b[m].offset == k) && + (ball->vx[2] < base[b[m].offset])) + goto found; + } + else /* scan it on the fly */ + { + AX_CircleWindowScan + ( ball->vx[0], ball->vx[1], vradius, + AX_size[iw].width, AX_size[iw].height, + AX_AOP_top(iw), AX_BOP_top(iw) ); + for (m=1; mvx[2] - sqrt(1.-(x2+y2)/r2) * + ball->radius <= AX_zmap[iw][goffset] * (1+AX_TINY) ) + goto found; + } + for (m=1; mvx[2] <= AX_zmap[iw][goffset] ) + goto found; + } + } + } + } + goto not_found; + +found: + di_l.d = ball->vx[2]; +not_found: + di_l.i = p3d_rank(p3dp_cell); + p3d_reduce(p3dp_cell, &di_l, &di_g, 1, MPI_DOUBLE_INT, MPI_MINLOC); + if (di_g.d == AX_INFINITY) + return -1; + else { + int idx; + *rank = di_g.i; + if (p3d_rank(p3dp_cell) == *rank) + idx = B->idx[i]; + p3d_bcast(p3dp_cell, &idx, 1, MPI_INT, *rank); + return idx; + } +} /* end AX_3D_Balls_Zgrab() */ + + + +void p3dp_AX_3D_Cylinders_Zdet (int iw, AX_3D_Cylinders *C) +{ + register AX_3D_Cylinder *cylinder; + register AX_3D_Cylinder_Power *power; + register double tmp=0; + int i, m, i_g, i_l; + double x1[4], radius2, UU[3],VV[3], xx[3], X0[4],X1[4], A,B,c; + int j, fp_activated, activated[AX_3D_MAX_FILTER_PLANE]; + MALLOC (AX_3D_Cylinders_Zdet, C->power, C->n_cylinders, + AX_3D_Cylinder_Power ); + MALLOC (AX_3D_Cylinders_Zdet, C->vz, C->n_cylinders, AX_Float); + MALLOC (AX_3D_Cylinders_Zdet, C->idx, C->n_cylinders, int); + REALLOC (AX_3D_Cylinders_Zdet, C->cylinder, C->n_cylinders, + AX_3D_Cylinder *); + for (fp_activated=0,j=0; jpower,m=0; ; power=C->power,m++) + { + for (i=0; in_cylinders; i++) + { + cylinder = C->CYLINDER + i; + /* invisibility flag */ + if (cylinder->radius <= 0) continue; + if (fp_activated) + { + AX_V3addmul (cylinder->x0, cylinder->axis[3], + cylinder->axis, x1); + for (j=0; jx0) < + AX_3D[iw].fp[j].d0-AX_TINY ) || + ( AX_V3DOT(AX_3D[iw].fp[j].dx, x1) < + AX_3D[iw].fp[j].d0-AX_TINY ) ) + break; + if (jx0, AX_3D[iw].x, power->dx); + A = AX_V3DOT (power->dx, cylinder->axis); + AX_V3submul (power->dx, A, cylinder->axis, power->y0); + tmp = AX_V3LENGTH2 (power->y0); + radius2 = SQUARE (cylinder->radius); + if (tmp <= radius2 * (1+AX_3D_CYLINDER_REIL)) + { + if ((A<=0) && (A>=-cylinder->axis[3])) break; + else continue; /* invisible */ + } + /* Convert to viewport frame */ + AX_M3mulV3 (AX_3D[iw].V, power->dx, power->y0); + AX_M3mulV3 (AX_3D[iw].V, cylinder->axis, power->U); + AX_V3addmul (power->y0, cylinder->axis[3], power->U, x1); + if ( (power->y0[2] <= 0) || (power->y0[2] > AX_3D[iw].zcut) || + (x1[2] <= 0) || (x1[2] > AX_3D[iw].zcut) ) + { /* intercepted by the z=0 plane */ + if ((power->y0[2] <= 0) && (x1[2] <= 0)) continue; + else if ( (power->y0[2] <= 0) && (x1[2] > 0) ) + { + tmp = AX_3D_CYLINDER_VEIL * x1[2] - power->y0[2]; + power->y0[0] += tmp * (x1[0] - power->y0[0]) / + (x1[2] - power->y0[2]); + power->y0[1] += tmp * (x1[1] - power->y0[1]) / + (x1[2] - power->y0[2]); + power->y0[2] = AX_3D_CYLINDER_VEIL * x1[2]; + } + else if ( (power->y0[2] > 0) && (x1[2] <= 0) ) + { + tmp = AX_3D_CYLINDER_VEIL * power->y0[2] - x1[2]; + x1[0] += tmp * (power->y0[0] - x1[0]) / + (power->y0[2] - x1[2]); + x1[1] += tmp * (power->y0[1] - x1[1]) / + (power->y0[2] - x1[2]); + x1[2] = AX_3D_CYLINDER_VEIL * power->y0[2]; + } + /* intercepted by the z=AX_3D[iw].zcut plane */ + if ( (power->y0[2] > AX_3D[iw].zcut) && + (x1[2] > AX_3D[iw].zcut) ) continue; + else if ( (power->y0[2] > AX_3D[iw].zcut) && + (x1[2] <= AX_3D[iw].zcut) ) + { + tmp = AX_3D[iw].zcut - power->y0[2]; + power->y0[0] += tmp * (x1[0] - power->y0[0]) / + (x1[2] - power->y0[2]); + power->y0[1] += tmp * (x1[1] - power->y0[1]) / + (x1[2] - power->y0[2]); + power->y0[2] = AX_3D[iw].zcut; + } + else if ( (power->y0[2] <= AX_3D[iw].zcut) && + (x1[2] > AX_3D[iw].zcut) ) + { + tmp = AX_3D[iw].zcut - x1[2]; + x1[0] += tmp * (power->y0[0] - x1[0]) / + (power->y0[2] - x1[2]); + x1[1] += tmp * (power->y0[1] - x1[1]) / + (power->y0[2] - x1[2]); + x1[2] = AX_3D[iw].zcut; + } + power->U[3] = DISTANCE( x1[0] - power->y0[0], + x1[1] - power->y0[1], + x1[2] - power->y0[2] ); + } + else power->U[3] = cylinder->axis[3]; + /* both centers are at front and we are not in the cylinder */ + X0[0] = AX_3D[iw].k * power->y0[0] / power->y0[2]; + X0[1] = AX_3D[iw].k * power->y0[1] / power->y0[2]; + X1[0] = AX_3D[iw].k * x1[0] / x1[2]; + X1[1] = AX_3D[iw].k * x1[1] / x1[2]; + if ( radius2 * AX_3D[iw].k/power->y0[2] * AX_3D[iw].k/x1[2] * + (SQUARE(X1[0]-X0[0])+SQUARE(X1[1]-X0[1])) < + AX_3D_CYLINDERS_MINAREA2 ) continue; + tmp = AX_V3LENGTH2(power->y0); + power->dx[0] = -AX_V3DOT(power->U, power->y0); + power->dx[1] = tmp - power->dx[0]*power->dx[0] - radius2; + power->dx[2] = AX_3D[iw].k * AX_3D[iw].k; + /* generate perpendicular wheels */ + AX_V3CROSS (power->U, x1, UU); + tmp = cylinder->radius / AX_V3LENGTH(UU); + AX_V3MUL (tmp, UU); + AX_V3CROSS (power->U, UU, VV); + /* scan sequence */ + ENSURE (X0[0], X1[0], tmp); + ENSURE (X0[1], X1[1], tmp); + if ( X1[0]-X0[0] >= X1[1]-X0[1] ) + { + for (m=0; my0[0] + (table[2*m]*UU[0] + + table[2*m+1]*VV[0]); + xx[1] = power->y0[1] + (table[2*m]*UU[1] + + table[2*m+1]*VV[1]); + xx[2] = power->y0[2] + (table[2*m]*UU[2] + + table[2*m+1]*VV[2]); + if (xx[2] > 0) + { + tmp = AX_3D[iw].k * xx[0] / xx[2]; + if (tmp > X1[0]) X1[0] = tmp; + else if (tmp < X0[0]) X0[0] = tmp; + } + xx[0] = x1[0] + (table[2*m]*UU[0] + table[2*m+1]*VV[0]); + xx[1] = x1[1] + (table[2*m]*UU[1] + table[2*m+1]*VV[1]); + xx[2] = x1[2] + (table[2*m]*UU[2] + table[2*m+1]*VV[2]); + if (xx[2] > 0) + { + tmp = AX_3D[iw].k * xx[0] / xx[2]; + if (tmp > X1[0]) X1[0] = tmp; + else if (tmp < X0[0]) X0[0] = tmp; + } + } + if (X0[0] < -AX_3D[iw].wx) X0[0] = -AX_3D[iw].wx; + if (X1[0] > AX_size[iw].width-AX_3D[iw].wx) + X1[0] = AX_size[iw].width-AX_3D[iw].wx; + /* to get the y-limits */ + X0[2] = power->U[0]*X0[0]/AX_3D[iw].k+power->U[2]; + X0[3] = -power->y0[0]*X0[0]/AX_3D[iw].k- + power->y0[2]-power->dx[0]*X0[2]; + A = (SQUARE(power->y0[1]+power->dx[0]*power->U[1])- + (1-power->U[1]*power->U[1])*power->dx[1]) + / power->dx[2]; + B = (X0[3]*(-power->y0[1]-power->dx[0]*power->U[1])+ + X0[2]*power->U[1]*power->dx[1]) / AX_3D[iw].k; + c = X0[3]*X0[3] - (X0[0]*X0[0]/power->dx[2]+1-X0[2]*X0[2]) + *(power->dx[1]); + AX_SOLVE_QUADRATIC(A,B,c,tmp,X0[2],X0[3]); + X1[2] = power->U[0]*X1[0]/AX_3D[iw].k+power->U[2]; + X1[3] = -power->y0[0]*X1[0]/AX_3D[iw].k-power->y0[2]- + power->dx[0]*X1[2]; + A = (SQUARE(power->y0[1]+power->dx[0]*power->U[1])- + (1-power->U[1]*power->U[1])*power->dx[1]) + / power->dx[2]; + B = (X1[3]*(-power->y0[1]-power->dx[0]*power->U[1])+ + X1[2]*power->U[1]*power->dx[1]) / AX_3D[iw].k; + c = X1[3]*X1[3] - (X1[0]*X1[0]/power->dx[2]+1-X1[2]*X1[2]) + *(power->dx[1]); + AX_SOLVE_QUADRATIC(A,B,c,tmp,X1[2],X1[3]); + power->p->nVertex = 4; + power->p->Vertex[0].x = power->p->Vertex[1].x = + AX_3D[iw].wx + X0[0]; + power->p->Vertex[0].y = AX_3D[iw].wy + X0[2]; + power->p->Vertex[1].y = AX_3D[iw].wy + X0[3]; + power->p->Vertex[2].x = power->p->Vertex[3].x = + AX_3D[iw].wx + X1[0]; + power->p->Vertex[2].y = AX_3D[iw].wy + X1[3]; + power->p->Vertex[3].y = AX_3D[iw].wy + X1[2]; + } + else /* X1[0]-X0[0] < X1[1]-X0[1] */ + { + for (m=0; my0[0] + (table[2*m]*UU[0] + + table[2*m+1]*VV[0]); + xx[1] = power->y0[1] + (table[2*m]*UU[1] + + table[2*m+1]*VV[1]); + xx[2] = power->y0[2] + (table[2*m]*UU[2] + + table[2*m+1]*VV[2]); + if (xx[2] > 0) + { + tmp = AX_3D[iw].k * xx[1] / xx[2]; + if (tmp > X1[1]) X1[1] = tmp; + else if (tmp < X0[1]) X0[1] = tmp; + } + xx[0] = x1[0] + (table[2*m]*UU[0] + table[2*m+1]*VV[0]); + xx[1] = x1[1] + (table[2*m]*UU[1] + table[2*m+1]*VV[1]); + xx[2] = x1[2] + (table[2*m]*UU[2] + table[2*m+1]*VV[2]); + if (xx[2] > 0) + { + tmp = AX_3D[iw].k * xx[1] / xx[2]; + if (tmp > X1[1]) X1[1] = tmp; + else if (tmp < X0[1]) X0[1] = tmp; + } + } + if (X0[1] < -AX_3D[iw].wy) X0[1] = -AX_3D[iw].wy; + if (X1[1] > AX_size[iw].height-AX_3D[iw].wy) + X1[1] = AX_size[iw].height-AX_3D[iw].wy; + /* to get the y-limits */ + X0[2] = power->U[1]*X0[1]/AX_3D[iw].k+power->U[2]; + X0[3] = -power->y0[1]*X0[1]/AX_3D[iw].k- + power->y0[2]-power->dx[0]*X0[2]; + A = (SQUARE(power->y0[0]+power->dx[0]*power->U[0])- + (1-power->U[0]*power->U[0])*power->dx[1]) + / power->dx[2]; + B = (X0[3]*(-power->y0[0]-power->dx[0]*power->U[0])+ + X0[2]*power->U[0]*power->dx[1]) / AX_3D[iw].k; + c = X0[3]*X0[3] - (X0[1]*X0[1]/power->dx[2]+1-X0[2]*X0[2]) + *(power->dx[1]); + AX_SOLVE_QUADRATIC(A,B,c,tmp,X0[2],X0[3]); + X1[2] = power->U[1]*X1[1]/AX_3D[iw].k+power->U[2]; + X1[3] = -power->y0[1]*X1[1]/AX_3D[iw].k- + power->y0[2]-power->dx[0]*X1[2]; + A = (SQUARE(power->y0[0]+power->dx[0]*power->U[0])- + (1-power->U[0]*power->U[0])*power->dx[1]) / + power->dx[2]; + B = (X1[3]*(-power->y0[0]-power->dx[0]*power->U[0])+ + X1[2]*power->U[0]*power->dx[1]) / AX_3D[iw].k; + c = X1[3]*X1[3] - (X1[1]*X1[1]/power->dx[2]+1-X1[2]*X1[2]) + *(power->dx[1]); + AX_SOLVE_QUADRATIC(A,B,c,tmp,X1[2],X1[3]); + power->p->nVertex = 4; + power->p->Vertex[1].y = power->p->Vertex[0].y = + AX_3D[iw].wy + X0[1]; + power->p->Vertex[0].x = AX_3D[iw].wx + X0[2]; + power->p->Vertex[1].x = AX_3D[iw].wx + X0[3]; + power->p->Vertex[2].y = power->p->Vertex[3].y = + AX_3D[iw].wy + X1[1]; + power->p->Vertex[2].x = AX_3D[iw].wx + X1[3]; + power->p->Vertex[3].x = AX_3D[iw].wx + X1[2]; + } + AX_SH_PolygonWindowClip (power->p, AX_size[iw].width, + AX_size[iw].height, power->p); + if (power->p->nVertex >= 3) + { + C->cylinder[power-C->power] = cylinder; + C->vz[power-C->power] = power->y0[2] + x1[2]; + power++; + } + } + /*if (i < C->n_cylinders)*/ + i_l = (i < C->n_cylinders); + p3d_reduce(p3dp_cell, &i_l, &i_g, 1, MPI_INT, MPI_MAX); + if (i_g) + { /* viewpoint ejection */ + double_int di_g, di_l; + di_l.d = 0.0; + di_l.i = p3d_rank(p3dp_cell); + if (i_l) di_l.d = V3LENGTH2(power->y0); + p3d_reduce(p3dp_cell, &di_l, &di_g, 1, MPI_DOUBLE_INT, MPI_MAXLOC); + if (di_g.i == p3d_rank(p3dp_cell)) { + AX_V3ADD(AX_3D[iw].x, power->y0); + while (tmp == 0) + { /* get a random orientation */ + AX_V3FRANDOM(power->dx); + tmp = AX_V3DOT(power->dx, cylinder->axis); + AX_V3submul(power->dx, tmp, cylinder->axis, power->y0); + tmp = AX_V3LENGTH2(power->y0); + } + tmp = (1+AX_3D_CYLINDER_REIL)*cylinder->radius / sqrt(tmp); + AX_V3SUBMUL(AX_3D[iw].x, tmp, power->y0); + } + if (m>=1000) + pe ("AX_3D_Cylinders_Zdet: viewpoint ejection failed\n"); + p3d_bcast(p3dp_cell, AX_3D[iw].x, 3, MPI_DOUBLE, di_g.i); + } + else break; + } + C->n_power = power - C->power; + REALLOC(AX_3D_Cylinders_Zdet, C->power, C->n_power, AX_3D_Cylinder_Power); + REALLOC(AX_3D_Cylinders_Zdet, C->cylinder, C->n_power, AX_3D_Cylinder *); + REALLOC(AX_3D_Cylinders_Zdet, C->idx, C->n_power, int); + AX_qsort_numerical_recipes(C->n_power, C->vz, C->idx, AX_USE_NEW_IDX); + Free (C->vz); + return; +} /* end AX_3D_Cylinders_Zdet() */ + + +int p3dp_AX_3D_Cylinders_Zgrab(int iw,AX_3D_Cylinders*C,int gi,int gj,int*rank) +{ + register AX_3D_Pixel *img; + register int m,goffset; + int i; + double_int di_g, di_l = {AX_INFINITY, 0}; + if (AX_IJOUWIN(iw,gi,gj)) goto not_found; + goffset = AX_OFF(iw,gi,gj); + for (i=0; in_power; i++) + { + img = C->cylinder[i]->img; + for (m=1; mcylinder[i]-C->CYLINDER; + p3d_bcast(p3dp_cell, &idx, 1, MPI_INT, *rank); + return idx; + } +} /* end AX_3D_Cylinders_Zgrab() */ + + +#undef AX_openwindow +#undef AX_resizewindow +#undef AX_closewindow +#define nonvacant(iw) (AX_cid[iw]!=0) + +static int p3dp_AX_plugin_ShmGC_module (int iw) +{ + AX_AssertWinID ("p3dp_AX_plugin_ShmGC_module", iw); + AX_Check_Module_Dependence ("p3dp_AX_plugin_ShmGC_module", iw,MODULE_ShmGC); + if ( AX_Module_Is_PluggedIn [iw] [MODULE_ShmGC] ) + pe ("p3dp_AX_plugin_ShmGC_module:\n" + "you are crazy, this module is already plugged in\n"); + + switch (AX_depth[iw]) { + case 8: AX_bytes = 1; break; + case 16: AX_bytes = 2; break; + case 24: case 32: AX_bytes = 4; break; + default: AX_bytes = 4; + } + + /* non-shared client data-memory */ + MALLOC ( AX_plugin_ShmGC_module, AX_mem[iw].uc, + AX_size[iw].width * AX_size[iw].height * AX_bytes, + unsigned char ); + +/* AX_bytes = AX_img[iw] -> bytes_per_line / AX_size[iw].width; */ + if (AX_bytes > sizeof(AX_Carrier)) + pe ("AX_plugin_ShmGC_module: AX_Carrier unable to carry\n" + "one pixmap unit of %d bytes\n", AX_bytes); + AX_8b = AX_bytes & 1; + AX_16b = AX_bytes & 2; + /* calling it 24-bit is inconsistent because no one calls above 15-bit */ + AX_32b = AX_bytes & 4; + if ( ! (AX_8b || AX_16b || AX_32b) ) + pe ("AX_plugin_ShmGC_module: AX_bytes = %d, neither 8,\n16, or 32-bit " + "graphics. Small revisions required.\n", AX_bytes); + + AX_namedbg(iw,AX_DEF_BACKGROUND); + AX_Module_Is_PluggedIn [iw] [MODULE_ShmGC] = 1; + return (1); +} /* end p3dp_AX_plugin_ShmGC_module() */ + + +static int p3dp_AX_plugout_ShmGC_module (int iw) +{ + AX_AssertWinID ("p3dp_AX_plugout_ShmGC_module", iw); + if ( ! AX_Module_Is_PluggedIn [iw] [MODULE_ShmGC] ) + pe ("p3dp_AX_plugout_ShmGC_module:\n" + "you are crazy, this module is not plugged in\n"); + + Free(AX_mem[iw].uc); + AX_Module_Is_PluggedIn [iw] [MODULE_ShmGC] = 0; + return (1); +} /* end p3dp_AX_plugout_ShmGC_module() */ + + +static int p3dp_AX_resize_ShmGC_module (int iw) +{ + REALLOC( AX_plugin_ShmGC_module, AX_mem[iw].uc, + AX_size[iw].width * AX_size[iw].height * AX_bytes, + unsigned char ); + return (1); +} /* end p3dp_AX_resize_ShmGC_module() */ + + +static struct { + int (*plugin) (int iw); + int (*plugout) (int iw); + int (*resize) (int iw); +} p3dp_AX_modules [MODULE_MAX] = { + {&p3dp_AX_plugin_ShmGC_module, + &p3dp_AX_plugout_ShmGC_module, + &p3dp_AX_resize_ShmGC_module}, + {&AX_plugin_Scan_module, &AX_plugout_Scan_module, &AX_resize_Scan_module}, + {&AX_plugin_3D_module, &AX_plugout_3D_module, &AX_resize_3D_module}, + {&AX_plugin_BC_module, &AX_plugout_BC_module, &AX_resize_BC_module} +}; + + +int p3dp_AX_openwindow +(int cid, char *title, unsigned int width, unsigned int height) +{ + int iw, minor; + AX_Carrier mask[3]; + AX_Pixel pixel[3]; + + if (cui_enabled < 0) + return cui_AX_openwindow(-1*cid, title, width, height); + else if (p3dp_enabled <= 0) + return AX_openwindow(cid, title, width, height); + + if (p3d_rank(p3dp_cell) == 0) { + iw = AX_openwindow(cid, title, width, height); + mask[0] = AX_rmask; + mask[1] = AX_gmask; + mask[2] = AX_bmask; + pixel[0] = AX_namedpixel[AX_RED]; + pixel[1] = AX_namedpixel[AX_GREEN]; + pixel[2] = AX_namedpixel[AX_BLUE]; + p3d_bcast(p3dp_cell, &AX_depth[iw], 1, MPI_INT, 0); + p3d_bcast(p3dp_cell, mask, 3*sizeof(AX_Carrier), MPI_CHAR, 0); + p3d_bcast(p3dp_cell, pixel, 3*sizeof(AX_Pixel), MPI_CHAR, 0); + } + else { + for (iw = 0; (iw < AX_MAXWIN) && nonvacant(iw); iw++); + if (iw == AX_MAXWIN) { + fprintf(stderr,"cui_AX_openwindow: AX_MAXWIN = %d reached\n", + AX_MAXWIN); + return -1; + } + + AX_display[iw] = NULL; + AX_cid[iw] = cid; + AX_size[iw].width = width; + AX_size[iw].height = height; + AX_borderwidth[iw] = 0; + AX_noneedcolormap = 1; + AX_videomode = AX_VIDEOMODE_NO_SHM; + + p3d_bcast(p3dp_cell, &AX_depth[iw], 1, MPI_INT, 0); + p3d_bcast(p3dp_cell, mask, 3*sizeof(AX_Carrier), MPI_CHAR, 0); + p3d_bcast(p3dp_cell, pixel, 3*sizeof(AX_Pixel), MPI_CHAR, 0); + + AX_rmask = mask[0]; + AX_gmask = mask[1]; + AX_bmask = mask[2]; + AX_namedpixel[AX_RED] = pixel[0]; + AX_namedpixel[AX_GREEN] = pixel[1]; + AX_namedpixel[AX_BLUE] = pixel[2]; + + for (minor=0; minor<=AX_DEF_Module_Support_Level; minor++) + p3dp_AX_modules[minor].plugin(iw); + } + + return iw; +} + +/* Resize all modules that are already plugged in, to AX_size[iw] */ +void p3dp_AX_resizewindow (int iw, Bool do_window_too) +{ + if (cui_enabled < 0) + cui_AX_resizewindow(iw, do_window_too); + else if (p3dp_enabled <= 0 || p3d_rank(p3dp_cell) == 0) + AX_resizewindow(iw, do_window_too); + else { + int module; + AX_AssertWinID ("AX_resizewindow", iw); + for (module=0; module0) && (dxij[3]>0) ) + return( acos( V3DOT(dxkj, dxij) / sqrt(dxkj[3]) / sqrt(dxij[3]) ) ); + else return (0); +} + + +void p3dp_print_atom_triplet_info +(int iw, int k, int j, int i, int krank, int jrank, int irank) +{ + double dxkj[4], dxij[4], angle; + double sk[3], sj[3], si[3]; + p3dp_s(sk, k, krank); + p3dp_s(sj, j, jrank); + p3dp_s(si, i, irank); + angle = p3dp_atom_triplet_s(sk, sj, si, dxkj, dxij); + print_atom_pair_info_s(iw, i, j, irank, jrank, si, sj); + if (IS_MANAGER) + printf ("bond angle = %g degrees.\n", RADIAN_TO_DEGREE(angle)); + print_atom_pair_info_s(iw, k, j, krank, jrank, sk, sj); + return; +} + + +void p3dp_print_atom_quartet_info +(int iw, int l, int k, int j, int i, int lrank, int krank, int jrank, int irank) +{ + double dxkj[4], dxij[4], angle, normal[4], dxlk[4], dxjk[4], dihedral; + double sl[3], sk[3], sj[3], si[3]; + p3dp_s(sl, l, lrank); + p3dp_s(sk, k, krank); + p3dp_s(sj, j, jrank); + p3dp_s(si, i, irank); + angle = p3dp_atom_triplet_s(sk, sj, si, dxkj, dxij); + print_atom_pair_info_s(iw, i, j, irank, jrank, si, sj); + if (IS_MANAGER) + printf ("bond angle = %g degrees.\n", RADIAN_TO_DEGREE(angle)); + print_atom_pair_info_s(iw, k, j, krank, jrank, sk, sj); + V3CROSS (dxkj, dxij, normal); + normal[3] = V3LENGTH2 (normal); + angle = p3dp_atom_triplet_s(sl, sk, sj, dxlk, dxjk); + if (IS_MANAGER) + printf ("bond angle = %g degrees.\n", RADIAN_TO_DEGREE(angle)); + print_atom_pair_info_s(iw, l, k, lrank, krank, sl, sk); + /* right-handed helix gives positive dihedral angle */ + if ( (normal[3]>0) && (dxlk[3]>0) ) + dihedral = acos( V3DOT(normal,dxlk)/sqrt(normal[3])/sqrt(dxlk[3]) ) - + PI / 2; + else dihedral = 0; + if (IS_MANAGER) + printf ("dihedral angle = %g degrees.\n", RADIAN_TO_DEGREE(dihedral)); + return; +} diff -urN A/primitives.c A3/primitives.c --- A/primitives.c 2009-07-29 00:18:41.000000000 +0900 +++ A3/primitives.c 2011-02-22 15:15:37.000000000 +0900 @@ -5,6 +5,9 @@ /*******************************************/ #include "A.h" +#ifdef USE_P3D +# include "p3dp.h" +#endif int temporary_disable_bond = 0; diff -urN A/utils.c A3/utils.c --- A/utils.c 2009-07-28 21:46:00.000000000 +0900 +++ A3/utils.c 2011-02-22 15:15:37.000000000 +0900 @@ -5,6 +5,12 @@ /*******************************************/ #include "A.h" +#ifdef USE_CUI +# include "cui.h" +#endif +#ifdef USE_P3D +# include "p3dp.h" +#endif static int rgb_url_printed = 0; @@ -301,6 +307,10 @@ return; } /* end CaptureRecover() */ +#ifdef USE_CUI +void (*cui_CaptureResize)(int, int, CaptureSwitch *) = &CaptureResize; +void (*cui_CaptureRecover)(int, CaptureSwitch*) = &CaptureRecover; +#endif /* Portable Network Graphics screenshot */ bool capture_png (int iw) @@ -823,15 +833,35 @@ double x,r,g,b,grade,width,height; FILE *fp; SimpleStatistics ss; +#ifdef USE_CUI + int writable; + if (cui_enabled) + strncpy(fname, default_cmap_fname, sizeof(fname)); + else { +#endif clear_stdin_buffer(); if (default_cmap_fname == NULL) default_cmap_fname = DEFAULT_CMAP_FNAME; strcpy (fname, readline_gets("Save colormap on",default_cmap_fname)); +#ifdef USE_CUI + } + if (IS_MANAGER) + writable = tested_to_be_writable(fname); +#ifdef USE_P3D + if (p3dp_enabled) + p3d_bcast(p3dp_cell, &writable, 1, MPI_INT, 0); +#endif + if (writable) +#else if (tested_to_be_writable(fname)) +#endif { /* pr("here %s %g %g\n", fname, */ /* n[iw].auxiliary_threshold[n[iw].auxiliary_idx][0], */ /* n[iw].auxiliary_threshold[n[iw].auxiliary_idx][1]); */ +#ifdef USE_CUI + if (IS_MANAGER) { +#endif fp = wopen(fname); fprintf (fp, "%%!PS-Adobe-2.0 EPSF-1.2\n"); fprintf (fp, "%%%%BoundingBox: %d %d %d %d\n", 0, 0, @@ -842,11 +872,17 @@ n[iw].auxiliary_threshold[n[iw].auxiliary_idx][0]); sprintf (buf[1], AUX_COLORMAP_FONTFMT, n[iw].auxiliary_threshold[n[iw].auxiliary_idx][1]); +#ifdef USE_CUI + } +#endif CalculateSimpleStatistics (np, CHARP(INW(n[iw].auxiliary_idx,CONFIG_num_auxiliary) ? CONFIG_auxiliary[n[iw].auxiliary_idx] : geo[n[iw].auxiliary_idx-CONFIG_MAX_AUXILIARY]), sizeof(double), IOVAL_DOUBLE, &ss); +#ifdef USE_CUI + if (IS_MANAGER) { +#endif if (ss.min > 0.9 * n[iw].auxiliary_threshold[n[iw].auxiliary_idx][0] + 0.1 * n[iw].auxiliary_threshold[n[iw].auxiliary_idx][1]) sprintf (buf[2], AUX_COLORMAP_FONTFMT, ss.min); @@ -894,10 +930,17 @@ AUX_COLORMAP_HEIGHT, buf[3]); fprintf (fp, "showpage\n"); fclose(fp); +#ifdef USE_CUI + } + if (AX_display[iw]) +#endif printf ("auxiliary colormap saved on \"%s\" (%d bytes)\n", fname, (int)Fsize(fname)); } else +#ifdef USE_CUI + if (AX_display[iw]) +#endif { printf ("\n** %s: **\n", fname); printf ("** This file is unwritable! **\n"); @@ -1193,6 +1236,9 @@ void xterm_get_focus (int iw) { XWindowAttributes WindowAttributes; +#ifdef USE_CUI + if (!xterm_win) return; +#endif XMapRaised (AX_display[iw], xterm_win); AXSYNC(iw); do XGetWindowAttributes(AX_display[iw],xterm_win,&WindowAttributes);