diff --git a/.github/CHANGELOG.md b/.github/CHANGELOG.md index 221c3b3..6d492e8 100644 --- a/.github/CHANGELOG.md +++ b/.github/CHANGELOG.md @@ -15,15 +15,17 @@ * Add CLI option to disable centering of molecules (#14) * Disable default rotation wrt inertia axis for z-matrix input and add a CLI option to force it (#14) * Read molecules from the standard input +* Improve data structures and code readability ### Fixes * Exit correctly when window closed (#10) * Fix chiral z-matrix input (#14) * Fix NaNs when compute dihedrals (#14) +* Fix the "readagain" (`r`) and "readmore" (`tab`) bugs (#31) +* Fix z-matrix input with unit=bohr (8554864) ### Coming in the next version: * extended xyz (#16, #17) -* fix `readmore` bug (#7) * high-symmetry determination bugs (#21) * how to build on mac diff --git a/figures/periodic.gif b/figures/periodic.gif index 480bb1a..600ff30 100644 Binary files a/figures/periodic.gif and b/figures/periodic.gif differ diff --git a/figures/periodic2.png b/figures/periodic2.png index c667654..bb52b0c 100644 Binary files a/figures/periodic2.png and b/figures/periodic2.png differ diff --git a/obj/api.d b/obj/api.d index 87cc184..dc48b93 100644 --- a/obj/api.d +++ b/obj/api.d @@ -1,2 +1,2 @@ obj/api.o obj-pic/api.o: src/api.c src/v/v.h src/mol/mol.h \ - src/mol/common.h + src/mol/common.h src/v/pars.h diff --git a/obj/math/zmat.d b/obj/math/zmat.d new file mode 100644 index 0000000..fd6fbda --- /dev/null +++ b/obj/math/zmat.d @@ -0,0 +1,2 @@ +obj/math/zmat.o obj-pic/math/zmat.o: src/math/zmat.c src/math/3d.h \ + src/math/matrix.h src/math/vecn.h src/math/vec3.h diff --git a/obj/v.d b/obj/v.d index e1d7b69..f0ff6dc 100644 --- a/obj/v.d +++ b/obj/v.d @@ -1,2 +1,3 @@ obj/v.o obj-pic/v.o: src/v.c src/v/v.h src/mol/mol.h src/mol/common.h \ - src/v/x.h src/v/evr.h src/math/3d.h src/math/matrix.h src/math/vecn.h + src/v/pars.h src/v/x.h src/v/evr.h src/math/3d.h src/math/matrix.h \ + src/math/vecn.h diff --git a/obj/v/ac3_draw.d b/obj/v/ac3_draw.d index 83c907e..ac2058d 100644 --- a/obj/v/ac3_draw.d +++ b/obj/v/ac3_draw.d @@ -1,2 +1,2 @@ obj/v/ac3_draw.o obj-pic/v/ac3_draw.o: src/v/ac3_draw.c src/v/v.h \ - src/mol/mol.h src/mol/common.h src/v/x.h + src/mol/mol.h src/mol/common.h src/v/pars.h src/v/x.h diff --git a/obj/v/ac3_print.d b/obj/v/ac3_print.d index e95987c..197fbc5 100644 --- a/obj/v/ac3_print.d +++ b/obj/v/ac3_print.d @@ -1,2 +1,2 @@ obj/v/ac3_print.o obj-pic/v/ac3_print.o: src/v/ac3_print.c src/v/v.h \ - src/mol/mol.h src/mol/common.h + src/mol/mol.h src/mol/common.h src/v/pars.h diff --git a/obj/v/ac3_read.d b/obj/v/ac3_read.d index 1fcc562..08c3d55 100644 --- a/obj/v/ac3_read.d +++ b/obj/v/ac3_read.d @@ -1,2 +1,3 @@ obj/v/ac3_read.o obj-pic/v/ac3_read.o: src/v/ac3_read.c src/v/v.h \ - src/mol/mol.h src/mol/common.h src/math/vec3.h + src/mol/mol.h src/mol/common.h src/v/pars.h src/math/vecn.h \ + src/math/vec3.h diff --git a/obj/v/ac3_read_in.d b/obj/v/ac3_read_in.d index c91c418..6dcdbcc 100644 --- a/obj/v/ac3_read_in.d +++ b/obj/v/ac3_read_in.d @@ -1,3 +1,3 @@ obj/v/ac3_read_in.o obj-pic/v/ac3_read_in.o: src/v/ac3_read_in.c \ - src/v/v.h src/mol/mol.h src/mol/common.h src/math/vec3.h src/math/3d.h \ - src/math/matrix.h src/math/vecn.h + src/v/v.h src/mol/mol.h src/mol/common.h src/v/pars.h src/math/3d.h \ + src/math/matrix.h src/math/vecn.h src/math/vec3.h diff --git a/obj/v/ac3_read_out.d b/obj/v/ac3_read_out.d index 725c44c..d0f0c45 100644 --- a/obj/v/ac3_read_out.d +++ b/obj/v/ac3_read_out.d @@ -1,2 +1,2 @@ obj/v/ac3_read_out.o obj-pic/v/ac3_read_out.o: src/v/ac3_read_out.c \ - src/v/v.h src/mol/mol.h src/mol/common.h + src/v/v.h src/mol/mol.h src/mol/common.h src/v/pars.h src/math/vec3.h diff --git a/obj/v/ac3_read_xyz.d b/obj/v/ac3_read_xyz.d index e4c8c36..9faf7c0 100644 --- a/obj/v/ac3_read_xyz.d +++ b/obj/v/ac3_read_xyz.d @@ -1,2 +1,2 @@ obj/v/ac3_read_xyz.o obj-pic/v/ac3_read_xyz.o: src/v/ac3_read_xyz.c \ - src/v/v.h src/mol/mol.h src/mol/common.h + src/v/v.h src/mol/mol.h src/mol/common.h src/v/pars.h diff --git a/obj/v/bonds.d b/obj/v/bonds.d index d6da7fd..33d0df6 100644 --- a/obj/v/bonds.d +++ b/obj/v/bonds.d @@ -1,2 +1,2 @@ obj/v/bonds.o obj-pic/v/bonds.o: src/v/bonds.c src/v/v.h src/mol/mol.h \ - src/mol/common.h src/math/vec3.h + src/mol/common.h src/v/pars.h src/math/vec3.h diff --git a/obj/v/cli.d b/obj/v/cli.d index 70cb4ee..b83ea3a 100644 --- a/obj/v/cli.d +++ b/obj/v/cli.d @@ -1,3 +1,3 @@ obj/v/cli.o obj-pic/v/cli.o: src/v/cli.c src/v/v.h src/mol/mol.h \ - src/mol/common.h src/math/vecn.h src/math/matrix.h src/math/vecn.h \ - src/math/vec3.h + src/mol/common.h src/v/pars.h src/math/vecn.h src/math/matrix.h \ + src/math/vecn.h src/math/vec3.h diff --git a/obj/v/evr.d b/obj/v/evr.d index 36e63cb..540e7cf 100644 --- a/obj/v/evr.d +++ b/obj/v/evr.d @@ -1,3 +1,3 @@ obj/v/evr.o obj-pic/v/evr.o: src/v/evr.c src/v/v.h src/mol/mol.h \ - src/mol/common.h src/v/x.h src/v/evr.h src/math/3d.h src/math/matrix.h \ - src/math/vecn.h src/math/vec3.h + src/mol/common.h src/v/pars.h src/v/x.h src/v/evr.h src/math/3d.h \ + src/math/matrix.h src/math/vecn.h src/math/vec3.h diff --git a/obj/v/get_atpar.d b/obj/v/get_atpar.d index b57c45a..cbf981f 100644 --- a/obj/v/get_atpar.d +++ b/obj/v/get_atpar.d @@ -1,2 +1,2 @@ obj/v/get_atpar.o obj-pic/v/get_atpar.o: src/v/get_atpar.c src/v/v.h \ - src/mol/mol.h src/mol/common.h src/mol/elements.h + src/mol/mol.h src/mol/common.h src/v/pars.h src/mol/elements.h diff --git a/obj/v/headless.d b/obj/v/headless.d index f635684..3048fee 100644 --- a/obj/v/headless.d +++ b/obj/v/headless.d @@ -1,3 +1,3 @@ obj/v/headless.o obj-pic/v/headless.o: src/v/headless.c src/v/v.h \ - src/mol/mol.h src/mol/common.h src/v/evr.h src/math/3d.h \ + src/mol/mol.h src/mol/common.h src/v/pars.h src/v/evr.h src/math/3d.h \ src/math/matrix.h src/math/vecn.h diff --git a/obj/v/load.d b/obj/v/load.d index e92d472..ea515ec 100644 --- a/obj/v/load.d +++ b/obj/v/load.d @@ -1,2 +1,2 @@ obj/v/load.o obj-pic/v/load.o: src/v/load.c src/v/v.h src/mol/mol.h \ - src/mol/common.h src/math/vec3.h src/math/vecn.h + src/mol/common.h src/v/pars.h src/math/vec3.h src/math/vecn.h diff --git a/obj/v/loop.d b/obj/v/loop.d index 24176d7..4af8815 100644 --- a/obj/v/loop.d +++ b/obj/v/loop.d @@ -1,3 +1,3 @@ obj/v/loop.o obj-pic/v/loop.o: src/v/loop.c src/v/v.h src/mol/mol.h \ - src/mol/common.h src/v/x.h src/v/evr.h src/math/3d.h src/math/matrix.h \ - src/math/vecn.h + src/mol/common.h src/v/pars.h src/v/x.h src/v/evr.h src/math/3d.h \ + src/math/matrix.h src/math/vecn.h diff --git a/obj/v/man.d b/obj/v/man.d index a7667c4..67a241e 100644 --- a/obj/v/man.d +++ b/obj/v/man.d @@ -1,2 +1,2 @@ obj/v/man.o obj-pic/v/man.o: src/v/man.c src/v/v.h src/mol/mol.h \ - src/mol/common.h + src/mol/common.h src/v/pars.h diff --git a/obj/v/mode_read.d b/obj/v/mode_read.d index c51ab23..f3a3c1c 100644 --- a/obj/v/mode_read.d +++ b/obj/v/mode_read.d @@ -1,2 +1,2 @@ obj/v/mode_read.o obj-pic/v/mode_read.o: src/v/mode_read.c src/v/v.h \ - src/mol/mol.h src/mol/common.h + src/mol/mol.h src/mol/common.h src/v/pars.h diff --git a/obj/v/scale.d b/obj/v/scale.d index 5dd9798..c7301cb 100644 --- a/obj/v/scale.d +++ b/obj/v/scale.d @@ -1,2 +1,2 @@ obj/v/scale.o obj-pic/v/scale.o: src/v/scale.c src/v/v.h src/mol/mol.h \ - src/mol/common.h src/math/vec3.h + src/mol/common.h src/v/pars.h src/math/vec3.h diff --git a/obj/v/tools.d b/obj/v/tools.d index 6e83f5a..5a2c5d4 100644 --- a/obj/v/tools.d +++ b/obj/v/tools.d @@ -1,3 +1,3 @@ obj/v/tools.o obj-pic/v/tools.o: src/v/tools.c src/v/v.h src/mol/mol.h \ - src/mol/common.h src/sym/sym.h src/math/vec3.h src/math/3d.h \ - src/math/matrix.h src/math/vecn.h + src/mol/common.h src/v/pars.h src/sym/sym.h src/math/vec3.h \ + src/math/3d.h src/math/matrix.h src/math/vecn.h diff --git a/obj/v/x.d b/obj/v/x.d index ae44fe9..a00fd1b 100644 --- a/obj/v/x.d +++ b/obj/v/x.d @@ -1,2 +1,3 @@ obj/v/x.o obj-pic/v/x.o: src/v/x.c src/v/v.h src/mol/mol.h \ - src/mol/common.h src/v/x.h + src/mol/common.h src/v/pars.h src/v/x.h src/math/vec2.h \ + src/mol/palette_v.h src/mol/palette_cpk.h diff --git a/obj/v/xinput.d b/obj/v/xinput.d index 7f4499a..069e87e 100644 --- a/obj/v/xinput.d +++ b/obj/v/xinput.d @@ -1,2 +1,2 @@ obj/v/xinput.o obj-pic/v/xinput.o: src/v/xinput.c src/v/v.h src/mol/mol.h \ - src/mol/common.h src/v/x.h + src/mol/common.h src/v/pars.h src/v/x.h diff --git a/python/vmol/main.py b/python/vmol/main.py index eb453e5..f8332a2 100644 --- a/python/vmol/main.py +++ b/python/vmol/main.py @@ -14,19 +14,30 @@ c_int_p = ctypes.POINTER(c_int) -class inp_mols_t(ctypes.Structure): # noqa: N801 - """C structure for the input molecule data, containing the number of atoms, charge array, coordinate array, and name.""" +class mol_t(ctypes.Structure): # noqa: N801 + """C structure for the input molecule data, containing the number of atoms, charge array, coordinate array, and name. + + Declared in src/mol/mol.h as + ``` + typedef struct { + double * r; + int * q; + char * name; + int n; + } mol; + ``` + """ _fields_ = ( - ("n", c_int), - ("q", c_int_p), ("r", c_double_p), + ("q", c_int_p), ("name", c_char_p), + ("n", c_int), ) ARGS_T = (c_int, ctypes.POINTER(ctypes.c_char_p)) -INP_MOLS_T = (c_int, ctypes.POINTER(inp_mols_t)) +INP_MOLS_T = (c_int, ctypes.POINTER(mol_t)) def mol2struct(get_element, mol): @@ -49,7 +60,7 @@ def mol2struct(get_element, mol): mol (dict or ase.atoms.Atoms-like): The molecule to convert. Returns: - inp_mols_t: An instance of `inp_mols_t` with the fields set according to the input molecule. + mol_t: An instance of `mol_t` with the fields set according to the input molecule. Raises: TypeError: If mol is not a dictionary. @@ -103,7 +114,7 @@ def mol2struct(get_element, mol): n = c_int(n) q = q.ctypes.data_as(c_int_p) r = r.ctypes.data_as(c_double_p) - in_str = inp_mols_t(n=n, q=q, r=r, name=name) + in_str = mol_t(n=n, q=q, r=r, name=name) in_str._keepalive = (n, q, r, name) # keep strong references return in_str @@ -245,10 +256,10 @@ def wrapped_func(argv: list[str], ...) ``` If `add_molecules` is True, the function is also expected to take an integer - and a pointer to an array of `inp_mols_t` structures as additional arguments after the first two, + and a pointer to an array of `mol_t` structures as additional arguments after the first two, which represent the number of molecules and the molecule data, respectively, i.e., ``` - void func(int argc, char ** argv, int nmol, inp_mols_t * mols, ...) -> def wrapped_func(argv: list[str], mols: object or list[object], ...) + void func(int argc, char ** argv, int nmol, mol_t * mols, ...) -> def wrapped_func(argv: list[str], mols: object or list[object], ...) ``` The decorator will convert a molecule or a list of molecules passed as the last argument to the wrapped function. @@ -303,7 +314,7 @@ def myinner(*args): argc, argv, _argv = make_array(args[0], c_char_p, convert_func=lambda x: x.encode('utf-8')) args.pop(0) if add_molecules: - nmol, mols, _mols = make_array(args[0], inp_mols_t, convert_func=lambda x: mol2struct(self.f.get_element, x)) + nmol, mols, _mols = make_array(args[0], mol_t, convert_func=lambda x: mol2struct(self.f.get_element, x)) args.pop(0) args = [nmol, mols, *args] args = [argc, argv, *args] diff --git a/src/api.c b/src/api.c index 9eb9cbf..563585d 100644 --- a/src/api.c +++ b/src/api.c @@ -2,21 +2,24 @@ #include "v.h" #define PRINTBUFLEN (1024*128) -#define FREE0(PTR) { free(PTR); PTR = NULL; } struct { - int n_inp_mols; - inp_mols_t * inp_mols; + mol * inp_mols; char * out_str; + int n_inp_mols; } globals; char * main_wrap_out(int argc, char * argv[], int * ret) { globals.out_str = calloc(PRINTBUFLEN, 1); + if(!globals.out_str){ + *ret = -1; + return NULL; + } *ret = main(argc, argv); return globals.out_str; } -int main_wrap_in(int argc, char * argv[], int n_inp_mols, inp_mols_t * inp_mols) { +int main_wrap_in(int argc, char * argv[], int n_inp_mols, mol * inp_mols) { globals.inp_mols = inp_mols; globals.n_inp_mols = n_inp_mols; int ret = main(argc, argv); @@ -26,9 +29,13 @@ int main_wrap_in(int argc, char * argv[], int n_inp_mols, inp_mols_t * inp_mols) } char * main_wrap_in_out(int argc, char * argv[], - int n_inp_mols, inp_mols_t * inp_mols, + int n_inp_mols, mol * inp_mols, int * ret){ globals.out_str = calloc(PRINTBUFLEN, 1); + if(!globals.out_str){ + *ret = -1; + return NULL; + } *ret = main_wrap_in(argc, argv, n_inp_mols, inp_mols); return globals.out_str; } @@ -65,7 +72,12 @@ void PRINTOUT(FILE * f, char * format, ...){ if(m >= size){ N = m < N ? N * 2 : N + 2*m; - globals.out_str = realloc(globals.out_str, N); + char * tmp = realloc(globals.out_str, N); + if(!tmp){ + PRINT_ERR("cannot reallocate output buffer\n"); + abort(); + } + globals.out_str = tmp; va_start(args, format); vsnprintf(globals.out_str+n, N-n, format, args); va_end(args); @@ -75,15 +87,15 @@ void PRINTOUT(FILE * f, char * format, ...){ } } -void * READ_FILES(drawpars * dp){ - void * ret; +object * READ_FILES(allpars * ap){ + object * ret; if(!globals.inp_mols){ - ret = read_files(dp); + ret = read_files(ap); } else{ - ret = get_in_str(globals.n_inp_mols, globals.inp_mols, dp); + ret = acs_from_var(globals.n_inp_mols, globals.inp_mols, ap); } - FREE0(dp->input_files); + FREE0(ap->ip.input_files); return ret; } diff --git a/src/math/3d.h b/src/math/3d.h index c905d6b..04f9de9 100644 --- a/src/math/3d.h +++ b/src/math/3d.h @@ -1,6 +1,12 @@ #include "matrix.h" +#define DEG2RAD (M_PI/180.0) + void rotmx0_update(double mx[9], double mx1[9], double phi, int axis); void rot3d (int n, double * r, double m[9]); void rotmx (double * rot, double * u, double phi); void rot_around_perp(double rot[9], double dx, double dy, double factor); + +int zmat2cart(int n, double r[3], + double a[3], double b[3], double c[3], + double R, double phi, double theta); diff --git a/src/math/zmat.c b/src/math/zmat.c new file mode 100644 index 0000000..e90eb5b --- /dev/null +++ b/src/math/zmat.c @@ -0,0 +1,62 @@ +#include "3d.h" +#include "vec3.h" + +#define EPS 1e-15 + +int zmat2cart(int n, double r[3], + double a[3], double b[3], double c[3], + double R, double phi, double theta){ + + if(n == 0){ + r[0] = r[1] = r[2] = 0.0; + } + + else if(n == 1){ + r[0] = a[0]; + r[1] = a[1] + R; + r[2] = a[2]; + } + + else if(n == 2){ + r[0] = a[0] + R * sqrt( 1 - cos(phi)*cos(phi) ); + r[1] = a[1] + ( (b[1]X + (X##_size)/sizeof(*((S)->X)) ) + #define MAX(x,y) ( ((x) > (y)) ? (x) : (y) ) #define MIN(x,y) ( ((x) < (y)) ? (x) : (y) ) diff --git a/src/mol/inertia.c b/src/mol/inertia.c index 5330345..1ef7450 100644 --- a/src/mol/inertia.c +++ b/src/mol/inertia.c @@ -3,6 +3,18 @@ #include "vec3.h" #define EPS 1e-10 +#define EIGEN_EPS 1e-15 +#define EIGEN_NIT 20 + +static inline void swap_ev(double d[3], double I_b[9], int i, int j){ + double td = d[i]; + d[i] = d[j]; + d[j] = td; + double tb[3]; + r3cp(tb, I_b+i*3); + r3cp(I_b+i*3, I_b+j*3); + r3cp(I_b+j*3, tb); +} static const double amass[]={ #include "masses.h" @@ -58,25 +70,20 @@ void position(mol * m, double d[3], int preserve_chirality){ I_t[mpos(1,2)] -= tm * (y*z); //Iyz } double I_b[9]={1,0,0, 0,1,0, 0,0,1}; - jacobi(I_t, I_b, d, 3, 1e-15, 20, NULL); + jacobi(I_t, I_b, d, 3, EIGEN_EPS, EIGEN_NIT, NULL); -#if 1 -#define SWITCH(I,J) { double td, tb[3];\ - td = d[I]; d[I] = d[J]; d[J] = td; \ - r3cp(tb, I_b+I*3); r3cp(I_b+I*3, I_b+J*3); r3cp(I_b+J*3, tb); } //sort ev - if(d[0]n; i++){ double u[3]; diff --git a/src/mol/mol.h b/src/mol/mol.h index ded41fd..eb2ae76 100644 --- a/src/mol/mol.h +++ b/src/mol/mol.h @@ -6,9 +6,21 @@ typedef struct { double * r; int * q; + const char * name; int n; } mol; +static inline mol * alloc_mol(int n){ + size_t r_size = sizeof(double) * n*3; + size_t q_size = sizeof(int ) * n; + mol * m = calloc(sizeof(mol)+r_size+q_size, 1); + m->r = (double *) (m + 1); + m->q = (int *) MEM_END(m, r); + m->name = NULL; + m->n = n; + return m; +} + void position(mol * m, double d[3], int preserve_chirality); void center_mol(int n, double * r, int * q); diff --git a/src/mol/palette_cpk.h b/src/mol/palette_cpk.h new file mode 100644 index 0000000..774284f --- /dev/null +++ b/src/mol/palette_cpk.h @@ -0,0 +1,110 @@ + [ 0] = {0x9999, 0x9999, 0x9999}, + [ 1] = {0xBFFF, 0xBFFF, 0xBFFF}, /* H */ + [ 2] = {0xD9D9, 0xFFFF, 0xFFFF}, /* He */ + [ 3] = {0xCCCC, 0x8080, 0xFFFF}, /* Li */ + [ 4] = {0xC2C2, 0xFFFF, 0x0000}, /* Be */ + [ 5] = {0xFFFF, 0xB5B5, 0xB5B5}, /* B */ + [ 6] = {0x5FFF, 0x5FFF, 0x5FFF}, /* C */ + [ 7] = {0x1FFF, 0x1FFF, 0xBFFF}, /* N */ + [ 8] = {0xBFFF, 0x1FFF, 0x1FFF}, /* O */ + [ 9] = {0xF500, 0xFFFF, 0x8500}, /* F */ + [ 10] = {0xAAAA, 0xFFFF, 0xFFFF}, /* Ne */ + [ 11] = {0xABAB, 0x5C5C, 0xF2F2}, /* Na */ + [ 12] = {0x8A8A, 0xFFFF, 0x0000}, /* Mg */ + [ 13] = {0xBFBF, 0xA6A6, 0xA6A6}, /* Al */ + [ 14] = {0x5FFF, 0x5FFF, 0x5FFF}, /* Si */ + [ 15] = {0xFFFF, 0xCCCC, 0x9999}, /* P */ + [ 16] = {0xFFFF, 0xEEEE, 0x1111}, /* S */ + [ 17] = {0xCCCC, 0xFFFF, 0x9999}, /* Cl */ + [ 18] = {0xAAAA, 0xFFFF, 0xFFFF}, /* Ar */ + [ 19] = {0x8F8F, 0x4040, 0xD4D4}, /* K */ + [ 20] = {0x3D3D, 0xFFFF, 0x0000}, /* Ca */ + [ 21] = {0xE6E6, 0xE6E6, 0xE6E6}, /* Sc */ + [ 22] = {0xBFBF, 0xC2C2, 0xC7C7}, /* Ti */ + [ 23] = {0xA6A6, 0xA6A6, 0xABAB}, /* V */ + [ 24] = {0x8A8A, 0x9999, 0xC7C7}, /* Cr */ + [ 25] = {0x9C9C, 0x7A7A, 0xC7C7}, /* Mn */ + [ 26] = {0xDDDD, 0x6666, 0x3333}, /* Fe */ + [ 27] = {0xEEEE, 0x8888, 0x9999}, /* Co */ + [ 28] = {0x5050, 0xD0D0, 0x5050}, /* Ni */ + [ 29] = {0xBBBB, 0x7777, 0x3333}, /* Cu */ + [ 30] = {0x7D7D, 0x8080, 0xB0B0}, /* Zn */ + [ 31] = {0xC2C2, 0x8F8F, 0x8F8F}, /* Ga */ + [ 32] = {0x6666, 0x8F8F, 0x8F8F}, /* Ge */ + [ 33] = {0xBDBD, 0x8080, 0xE3E3}, /* As */ + [ 34] = {0xFFFF, 0xAAAA, 0x1111}, /* Se */ + [ 35] = {0xAAAA, 0x4444, 0x0000}, /* Br */ + [ 36] = {0xAAAA, 0xFFFF, 0xFFFF}, /* Kr */ + [ 37] = {0x7070, 0x2E2E, 0xB0B0}, /* Rb */ + [ 38] = {0x0000, 0xFFFF, 0x0000}, /* Sr */ + [ 39] = {0x9494, 0xFFFF, 0xFFFF}, /* Y */ + [ 40] = {0x9494, 0xE0E0, 0xE0E0}, /* Zr */ + [ 41] = {0x7373, 0xC2C2, 0xC9C9}, /* Nb */ + [ 42] = {0x5454, 0xB5B5, 0xB5B5}, /* Mo */ + [ 43] = {0x3B3B, 0x9E9E, 0x9E9E}, /* Tc */ + [ 44] = {0x2424, 0x8F8F, 0x8F8F}, /* Ru */ + [ 45] = {0x0A0A, 0x7D7D, 0x8C8C}, /* Rh */ + [ 46] = {0x0000, 0x6969, 0x8585}, /* Pd */ + [ 47] = {0xC0C0, 0xC0C0, 0xC0C0}, /* Ag */ + [ 48] = {0xFFFF, 0xD9D9, 0x8F8F}, /* Cd */ + [ 49] = {0xA6A6, 0x7575, 0x7373}, /* In */ + [ 50] = {0x6666, 0x8080, 0x8080}, /* Sn */ + [ 51] = {0x9E9E, 0x6363, 0xB5B5}, /* Sb */ + [ 52] = {0xD4D4, 0x7A7A, 0x0000}, /* Te */ + [ 53] = {0x9494, 0x0000, 0x9494}, /* I */ + [ 54] = {0x4242, 0x9E9E, 0xB0B0}, /* Xe */ + [ 55] = {0x5757, 0x1717, 0x8F8F}, /* Cs */ + [ 56] = {0x0000, 0xC9C9, 0x0000}, /* Ba */ + [ 57] = {0x7070, 0xD4D4, 0xFFFF}, /* La */ + [ 58] = {0xFFFF, 0xFFFF, 0xC7C7}, /* Ce */ + [ 59] = {0xD9D9, 0xFFFF, 0xC7C7}, /* Pr */ + [ 60] = {0xC7C7, 0xFFFF, 0xC7C7}, /* Nd */ + [ 61] = {0xA3A3, 0xFFFF, 0xC7C7}, /* Pm */ + [ 62] = {0x8F8F, 0xFFFF, 0xC7C7}, /* Sm */ + [ 63] = {0x6161, 0xFFFF, 0xC7C7}, /* Eu */ + [ 64] = {0x4545, 0xFFFF, 0xC7C7}, /* Gd */ + [ 65] = {0x3030, 0xFFFF, 0xC7C7}, /* Tb */ + [ 66] = {0x1F1F, 0xFFFF, 0xC7C7}, /* Dy */ + [ 67] = {0x0000, 0xFFFF, 0x9C9C}, /* Ho */ + [ 68] = {0x0000, 0xE6E6, 0x7575}, /* Er */ + [ 69] = {0x0000, 0xD4D4, 0x5252}, /* Tm */ + [ 70] = {0x0000, 0xBFBF, 0x3838}, /* Yb */ + [ 71] = {0x0000, 0xABAB, 0x2424}, /* Lu */ + [ 72] = {0x4D4D, 0xC2C2, 0xFFFF}, /* Hf */ + [ 73] = {0x4D4D, 0xA6A6, 0xFFFF}, /* Ta */ + [ 74] = {0x2121, 0x9494, 0xD6D6}, /* W */ + [ 75] = {0x2626, 0x7D7D, 0xABAB}, /* Re */ + [ 76] = {0x2626, 0x6666, 0x9696}, /* Os */ + [ 77] = {0x1717, 0x5454, 0x8787}, /* Ir */ + [ 78] = {0xD0D0, 0xD0D0, 0xE0E0}, /* Pt */ + [ 79] = {0xFFFF, 0xD1D1, 0x2323}, /* Au */ + [ 80] = {0xB8B8, 0xB8B8, 0xD0D0}, /* Hg */ + [ 81] = {0xA6A6, 0x5454, 0x4D4D}, /* Tl */ + [ 82] = {0x5757, 0x5959, 0x6161}, /* Pb */ + [ 83] = {0x9E9E, 0x4F4F, 0xB5B5}, /* Bi */ + [ 84] = {0xABAB, 0x5C5C, 0x0000}, /* Po */ + [ 85] = {0x7575, 0x4F4F, 0x4545}, /* At */ + [ 86] = {0x4242, 0x8282, 0x9696}, /* Rn */ + [ 87] = {0x4242, 0x0000, 0x6666}, /* Fr */ + [ 88] = {0x0000, 0x7D7D, 0x0000}, /* Ra */ + [ 89] = {0x7070, 0xABAB, 0xFAFA}, /* Ac */ + [ 90] = {0x0000, 0xBABA, 0xFFFF}, /* Th */ + [ 91] = {0x0000, 0xA1A1, 0xFFFF}, /* Pa */ + [ 92] = {0x0000, 0x8F8F, 0xFFFF}, /* U */ + [ 93] = {0x0000, 0x8080, 0xFFFF}, /* Np */ + [ 94] = {0x0000, 0x6B6B, 0xFFFF}, /* Pu */ + [ 95] = {0x5454, 0x5C5C, 0xF2F2}, /* Am */ + [ 96] = {0x7878, 0x5C5C, 0xE3E3}, /* Cm */ + [ 97] = {0x8A8A, 0x4F4F, 0xE3E3}, /* Bk */ + [ 98] = {0xA1A1, 0x3636, 0xD4D4}, /* Cf */ + [ 99] = {0xB3B3, 0x1F1F, 0xD4D4}, /* Es */ + [100] = {0xB3B3, 0x1F1F, 0xBABA}, /* Fm */ + [101] = {0xB3B3, 0x0D0D, 0xA6A6}, /* Md */ + [102] = {0xBDBD, 0x0D0D, 0x8787}, /* No */ + [103] = {0xC7C7, 0x0000, 0x6666}, /* Lr */ + [104] = {0xCCCC, 0x0000, 0x5959}, /* Rf */ + [105] = {0xD1D1, 0x0000, 0x4F4F}, /* Db */ + [106] = {0xD9D9, 0x0000, 0x4545}, /* Sg */ + [107] = {0xE0E0, 0x0000, 0x3838}, /* Bh */ + [108] = {0xE6E6, 0x0000, 0x2E2E}, /* Hs */ + [109] = {0xEBEB, 0x0000, 0x2626}, /* Mt */ diff --git a/src/mol/palette_v.h b/src/mol/palette_v.h new file mode 100644 index 0000000..d17b954 --- /dev/null +++ b/src/mol/palette_v.h @@ -0,0 +1,25 @@ + [ 0] = {0x9999, 0x9999, 0x9999}, + [ 1] = {0xBFFF, 0xBFFF, 0xBFFF}, /* H */ + [ 2] = {0xAAAA, 0xFFFF, 0xFFFF}, /* He */ + [ 6] = {0x5FFF, 0x5FFF, 0x5FFF}, /* C */ + [ 5] = {0xFFFF, 0xDDDD, 0xFFFF}, /* P */ + [ 7] = {0x1FFF, 0x1FFF, 0xBFFF}, /* N */ + [ 8] = {0xBFFF, 0x1FFF, 0x1FFF}, /* O */ + [ 9] = {0xF500, 0xFFFF, 0x8500}, /* F */ + [ 10] = {0xAAAA, 0xFFFF, 0xFFFF}, /* Ne */ + [ 14] = {0x5FFF, 0x5FFF, 0x5FFF}, /* Si */ + [ 15] = {0xFFFF, 0xCCCC, 0x9999}, /* P */ + [ 16] = {0xFFFF, 0xEEEE, 0x1111}, /* S */ + [ 17] = {0xCCCC, 0xFFFF, 0x9999}, /* Cl */ + [ 18] = {0xAAAA, 0xFFFF, 0xFFFF}, /* Ar */ + [ 28] = {0x9999, 0x5555, 0xFFFF}, /* Ni */ + [ 29] = {0xBBBB, 0x7777, 0x3333}, /* Cu */ + [ 34] = {0xFFFF, 0xAAAA, 0x1111}, /* Se */ + [ 35] = {0xAAAA, 0x4444, 0x0000}, /* Br */ + [ 36] = {0xAAAA, 0xFFFF, 0xFFFF}, /* Kr */ + [ 46] = {0x0000, 0x6666, 0x7777}, /* Pd */ + [ 47] = {0xAAAA, 0xAAAA, 0xAAAA}, /* Ag */ + [ 53] = {0xAAAA, 0x0000, 0xFFFF}, /* I */ + [ 54] = {0xAAAA, 0xFFFF, 0xFFFF}, /* Xe */ + [ 78] = {0x3333, 0x9999, 0xDDDD}, /* Pt */ + [ 79] = {0xFFFF, 0xCCCC, 0x0000}, /* Au */ diff --git a/src/sym/pointgroup.c b/src/sym/pointgroup.c index c6f5ec3..49d61d1 100644 --- a/src/sym/pointgroup.c +++ b/src/sym/pointgroup.c @@ -1,5 +1,17 @@ #include "sym.h" +static inline molsym * alloc_molsym(int a, int mssize){ + size_t r_size = sizeof(double) * mssize*3; + size_t o_size = sizeof(int ) * mssize; + size_t e_size = sizeof(elsym ) * mssize; + molsym * ms = calloc(sizeof(molsym)+ e_size + o_size + r_size, 1); + ms->r = (double *) (ms+1); + ms->o = (int *) MEM_END(ms,r); + ms->e = (elsym *) MEM_END(ms,o); + ms->a = a; + return ms; +} + static inline int isnew(int N, double * R, double r[3], double eps2){ for(int i=0; ie[(I)], MS->o[(I)], MS->r[(I)*3], MS->r[(I)*3+1], MS->r[(I)*3+2]); #define MSSIZE 4 - molsym * ms = malloc(sizeof(molsym)+MSSIZE*(sizeof(elsym)+sizeof(int)+3*sizeof(double))); - ms->a = m->n; - ms->n = 0; - ms->r = (double *)(ms+1); - ms->o = (int *)(ms->r + MSSIZE*3); - ms->e = (elsym *)(ms->o + MSSIZE); + molsym * ms = alloc_molsym(m->n, MSSIZE); double d[3]; position(m, d, 0); diff --git a/src/sym/sym.h b/src/sym/sym.h index b933b91..ab50289 100644 --- a/src/sym/sym.h +++ b/src/sym/sym.h @@ -10,12 +10,12 @@ typedef enum {INV, SIGMA, CN, SN} elsym; typedef struct { - styp s; + double * r; // vectors associated with generators + int * o; // orders of generators + elsym * e; // types of generators + styp s; // point group int a; // number of atoms int n; // number of group generators - elsym * e; // types of generators - int * o; // orders of generators - double * r; // vectors associated with generators } molsym; molsym * pointgroup(mol * m, double eps); diff --git a/src/v.c b/src/v.c index f3eee5f..a56c657 100644 --- a/src/v.c +++ b/src/v.c @@ -78,31 +78,32 @@ int main (int argc, char * argv[]) { /*= Input ==================================================================*/ - drawpars dp = cli_parse(argc, argv); + allpars ap = cli_parse(argc, argv); - void * ent = READ_FILES(&dp); + object * ent = READ_FILES(&ap); if(!ent){ PRINT_ERR("no files to read\n"); return 1; } - if(dp.n >= dp.N){ - dp.n = dp.n%dp.N; + drawpars * dp = &ap.dp; + if(dp->n >= dp->N){ + dp->n = dp->n%dp->N; } - else if(dp.n<0){ - dp.n = dp.N-(-dp.n)%dp.N; + else if(dp->n<0){ + dp->n = dp->N-(-dp->n)%dp->N; } - if(!dp.gui){ - return headless(&dp, ent); + if(!ap.ip.gui){ + return headless(dp, ent); } /*= X11 init ===============================================================*/ ptf kp[NKP]; - init_x(dp.fname, dp.colors); + init_x(dp->read.fname, ap.ip.colors); init_keys(kp); - init_font(dp.fontname); + init_font(ap.ip.fontname); #if 0 myDrawString = &XDrawString; #else @@ -115,7 +116,7 @@ int main (int argc, char * argv[]) { #endif /*= Main loop ==============================================================*/ - main_loop(ent, &dp, kp); + main_loop(ent, dp, kp); return 0; } diff --git a/src/v/ac3_draw.c b/src/v/ac3_draw.c index fe85e91..657dcbe 100644 --- a/src/v/ac3_draw.c +++ b/src/v/ac3_draw.c @@ -1,6 +1,10 @@ #include "v.h" #include "x.h" +#define EPS 1e-15 +#define BOND_OFFSET 0.666 // bond line starts this fraction of the atom radius away from the atom center +#define RESOL_SCALE (128.0/768.0) // reference resolution for atom sizes + extern int W,H; extern int screen; extern Display * dis; @@ -30,27 +34,27 @@ static int cmpz(const void * p1, const void * p2){ return 0; } -void ac3_draw(atcoord * ac, double r0, double scale, double xy0[2], int b, int num){ +void ac3_draw(atcoord * ac, rendpars rend){ -#define SCREEN_X(X) (W/2 + d*(xy0[0] + (X))) -#define SCREEN_Y(Y) (H/2 - d*(xy0[1] + (Y))) +#define SCREEN_X(X) (W/2 + d*(rend.xy0[0] + (X))) +#define SCREEN_Y(Y) (H/2 - d*(rend.xy0[1] + (Y))) CLEARCANV; int n = ac->n; kzstr * kz = malloc(sizeof(kzstr)*n); - int * ks = (b>0) ? malloc(sizeof(int)*n) : NULL; + int * ks = (rend.bonds>0) ? malloc(sizeof(int)*n) : NULL; - double d = MIN(H,W) * scale; - double resol = MIN(H,W) * (128.0/768.0); - double r1 = r0 * resol * scale; + double d = MIN(H,W) * rend.scale; + double resol = MIN(H,W) * RESOL_SCALE; + double r1 = rend.r * resol * rend.scale; for(int k=0; kr[k*3+2]; } qsort(kz, n, sizeof(kzstr), cmpz); - if(b>0){ + if(rend.bonds>0){ for(int i=0; i0?gc_black:gc_dot[1], x-r, y-r, 2*r, 2*r, 0, 360*64); } - if(num == 1){ + if(rend.num == 1){ char text[16]; snprintf(text, sizeof(text), "%d", k+1); myDrawString(dis, canv, gc_black, x, y, text, strlen(text)); } - else if(num == -1){ + else if(rend.num == -1){ char text[16]; const char * s = getname(q); s ? snprintf(text, sizeof(text), "%s", s) : snprintf(text, sizeof(text), "%d", q ); myDrawString(dis, canv, gc_black, x, y, text, strlen(text)); } - if(b>0){ + if(rend.bonds>0){ for(int j=k*BONDS_MAX; j<(k+1)*BONDS_MAX; j++){ - int k1 = ac->bond_a[j]; + int k1 = ac->bonds.a[j]; if(k1 == -1 ){ break; } @@ -96,14 +100,14 @@ void ac3_draw(atcoord * ac, double r0, double scale, double xy0[2], int b, int n int dx = x1-x; int dy = y1-y; double r2d = dx*dx+dy*dy; - if(r2d < 1e-15){ + if(r2d < EPS){ continue; } - double dd = 0.666 * r / sqrt(r2d); + double dd = BOND_OFFSET * r / sqrt(r2d); XDrawLine(dis, canv, gc_black, x+dd*dx, y+dd*dy, x1, y1); - if(b==2){ + if(rend.bonds==2){ char text[16]; - snprintf(text, sizeof(text), "%.3lf", ac->bond_r[j]); + snprintf(text, sizeof(text), "%.3lf", ac->bonds.r[j]); myDrawString(dis, canv, gc_black, x+dx/2, y+dy/2, text, strlen(text)); } } diff --git a/src/v/ac3_print.c b/src/v/ac3_print.c index 16d875e..470783e 100644 --- a/src/v/ac3_print.c +++ b/src/v/ac3_print.c @@ -1,16 +1,16 @@ #include "v.h" -void ac3_print(atcoord * ac, double xy0[2], int b){ +void ac3_print(atcoord * ac, rendpars rend){ PRINTOUT(stdout, "$molecule\ncart\n"); for(int k=0; kn; k++){ PRINTOUT(stdout, "%3d % lf % lf % lf", ac->q[k], - xy0[0] + ac->r[k*3 ], - xy0[1] + ac->r[k*3+1], + rend.xy0[0] + ac->r[k*3 ], + rend.xy0[1] + ac->r[k*3+1], ac->r[k*3+2]); - if(b>0){ + if(rend.bonds>0){ for(int j=0; jbond_a[k*BONDS_MAX+j]; + int k1 = ac->bonds.a[k*BONDS_MAX+j]; if(k1 == -1 ){ break; } @@ -23,7 +23,7 @@ void ac3_print(atcoord * ac, double xy0[2], int b){ return; } -void ac3_print_xyz(atcoord * ac, double xy0[2]){ +void ac3_print_xyz(atcoord * ac, rendpars rend){ PRINTOUT(stdout, "%d\n\n", ac->n); for(int k=0; kn; k++){ const char * s = getname(ac->q[k]); @@ -35,36 +35,36 @@ void ac3_print_xyz(atcoord * ac, double xy0[2]){ PRINTOUT(stdout, " %3d", ac->q[k]); } PRINTOUT(stdout, " % lf % lf % lf\n", - xy0[0] + ac->r[k*3 ], - xy0[1] + ac->r[k*3+1], + rend.xy0[0] + ac->r[k*3 ], + rend.xy0[1] + ac->r[k*3+1], ac->r[k*3+2]); } return; } -void ac3_print2fig(atcoord * ac, double xy0[2], int b, double * v){ +void ac3_print2fig(atcoord * ac, rendpars rend, double * v){ int n = ac->n; for(int i=0; iq[i], - xy0[0] + ac->r[i*3 ], - xy0[1] + ac->r[i*3+1], + rend.xy0[0] + ac->r[i*3 ], + rend.xy0[1] + ac->r[i*3+1], ac->r[i*3+2]); } if(v){ for(int i=0; i<8; i++){ PRINTOUT(stdout, "atom %3d% 13.7lf% 13.7lf% 13.7lf\n", 0, - xy0[0] + v[i*3 ], - xy0[1] + v[i*3+1], + rend.xy0[0] + v[i*3 ], + rend.xy0[1] + v[i*3+1], v[i*3+2]); } } - if(b>0){ + if(rend.bonds>0){ for(int k=0; kbond_a[k*BONDS_MAX+j]; + int k1 = ac->bonds.a[k*BONDS_MAX+j]; if(k1 == -1 ){ break; } @@ -77,18 +77,15 @@ void ac3_print2fig(atcoord * ac, double xy0[2], int b, double * v){ if(v){ #define LINE(I,J) PRINTOUT(stdout, "bond %3d %3d % 3d\n", (J)+n+1, (I)+n+1, -1) - LINE(0,1); - LINE(0,2); - LINE(0,3); - LINE(1,4); - LINE(1,5); - LINE(2,4); - LINE(2,6); - LINE(3,5); - LINE(3,6); - LINE(4,7); - LINE(5,7); - LINE(6,7); + for(int i=0; i<8; i+=2){ + LINE(i,i+1); // || z-axis + } + for(int j=0; j<2; j++){ + for(int i=0; i<2; i++){ + LINE(i*4+j, i*4+2+j); // || y-axis + LINE(i*2+j, i*2+4+j); // || x-axis + } + } #undef LINE } diff --git a/src/v/ac3_read.c b/src/v/ac3_read.c index 57cf11f..daf57e9 100644 --- a/src/v/ac3_read.c +++ b/src/v/ac3_read.c @@ -1,113 +1,96 @@ #include "v.h" +#include "vecn.h" #include "vec3.h" - -#define END(S,X) ( (S)->X + (X##_size)/sizeof(*((S)->X)) ) - - -atcoord * atcoord_fill(int n, txyz * a, const char * fname, int b, int center, int inertia, int bohr){ +atcoord * atcoord_fill(mol * m0, int b, const geompars geom){ + int n = m0->n; size_t q_size = sizeof(int ) * n; size_t r_size = sizeof(double) * n*3; - atcoord * m; - if(b != -1){ - size_t bond_a_size = sizeof(int ) * n*BONDS_MAX; - size_t bond_r_size = sizeof(double) * n*BONDS_MAX; - size_t size = sizeof(atcoord) + q_size + r_size + bond_a_size + bond_r_size; - m = malloc(size); - m->n = n; - m->r = (double *) (m + 1); - m->bond_r = (double *) END(m,r); - m->q = (int *) END(m,bond_r); - m->bond_a = (int *) END(m,q); - m->bond_flag = 0; - m->bond_rl = 0.0; + struct {size_t r_size; size_t a_size;} bonds = {0, 0}; + if(b!=-1){ + bonds.a_size = sizeof(int ) * n*BONDS_MAX; + bonds.r_size = sizeof(double) * n*BONDS_MAX; + } + size_t size = sizeof(atcoord) + q_size + r_size + bonds.a_size + bonds.r_size; + atcoord * m = calloc(size, 1); + + if(b==-1){ + m->r = (double *) (m + 1); + m->q = (int *) MEM_END(m,r); } else{ - size_t size = sizeof(atcoord) + q_size + r_size; - m = malloc(size); - m->n = n; - m->r = (double *) (m + 1); - m->bond_r = NULL; - m->q = (int *) END(m,r); - m->bond_a = NULL; - m->bond_flag = -1; - m->bond_rl = 0.0; + m->r = (double *) (m + 1); + m->bonds.r = (double *) MEM_END(m,r); + m->q = (int *) MEM_END(m,bonds.r); + m->bonds.a = (int *) MEM_END(m,q); } - memset(m->sym, 0, sizeof(m->sym)); - m->fname = fname; - + m->n = n; + m->fname = m0->name; for(int i=0; iq[i] = a[i].t; - if(bohr){ - r3scal(a[i].r, BA); - } - r3cp(m->r+i*3, a[i].r); + m->q[i] = m0->q[i]; + r3cp(m->r+i*3, m0->r+i*3); } - if(inertia){ - mol M = {.n=m->n, .q=m->q, .r=m->r}; - position(&M, NULL, 1); + + if(geom.bohr){ + vecscal(n*3, m->r, BA); } - if(center){ - center_mol(n, m->r, center==2 ? m->q : NULL); + if(geom.inertia){ + // should not change m0 + position(&((mol){.n=n, .q=m->q, .r=m->r}), NULL, 1); + } + if(geom.center){ + center_mol(n, m->r, geom.center==2 ? m->q : NULL); } return m; } +atcoord * ac3_read(readpars read, int b, const geompars geom, format_t * format){ -atcoord * ac3_read(FILE * f, int b, int center, int inertia, int bohr, const char * fname, format_t * format){ - - int n; - int zmat=0; - txyz * a; + mol * m = NULL; + FILE * f = read.f; switch(*format){ case XYZ: - if((a=ac3_read_xyz(&n, f))){ + if((m=ac3_read_xyz(f))){ *format = XYZ; } break; case IN: - if((a=ac3_read_in(&n, &zmat, f))){ + if((m=ac3_read_in(f))){ *format = IN; } break; case OUT: - if((a=ac3_read_out(&n, f))){ + if((m=ac3_read_out(f))){ *format = OUT; } break; default: - if((a=ac3_read_xyz(&n, f))){ + if((m=ac3_read_xyz(f))){ *format = XYZ; } - if(!a){ - if((a=ac3_read_in(&n, &zmat, f))){ + if(!m){ + if((m=ac3_read_in(f))){ *format = IN; } } - if(!a){ - if((a=ac3_read_out(&n, f))){ + if(!m){ + if((m=ac3_read_out(f))){ *format = OUT; } } break; } - if(!a){ + if(!m){ return NULL; } + m->name = read.fname; - atcoord * m = atcoord_fill(n, a, fname, b, center, inertia, bohr); - -#if 0 - printf("%d\n\n", n); - for(int i=0; iq[i], m->r[i*3 ], m->r[i*3+1], m->r[i*3+2]); - } -#endif - free(a); - return m; + atcoord * M = atcoord_fill(m, b, geom); + free(m); + return M; } diff --git a/src/v/ac3_read_in.c b/src/v/ac3_read_in.c index 5515893..ad1a2d7 100644 --- a/src/v/ac3_read_in.c +++ b/src/v/ac3_read_in.c @@ -1,83 +1,93 @@ +#include #include "v.h" -#include "vec3.h" -#define EPS 1e-15 #include "3d.h" +#include "vec3.h" -static int zmat2cart(int n, txyz * mr, double r[3], - int a1, int a2, int a3, - double R, double phi, double theta){ - - if(n == 0){ - r[0] = r[1] = r[2] = 0.0; +int read_cart_atom(FILE * f, int n, mol * m){ + int q; + double r[3]; + int res = (fscanf(f, "%d%lf%lf%lf", &q, r, r+1, r+2)==4); + if(res && m){ + m->q[n] = q; + r3cp(m->r+3*n, r); } + return res; +} + +static int read_z_atom( FILE * f, int n, mol * m){ + + int res, q, a, b, c; + double R, phi, theta; - else if(n == 1){ - r[0] = mr[a1].r[0]; - r[1] = mr[a1].r[1] + R; - r[2] = mr[a1].r[2]; + switch(n){ + case 0: + res = (fscanf(f, "%d", &q) == 1); + break; + case 1: + res = (fscanf(f, "%d%d%lf", &q, &a, &R) == 3); + break; + case 2: + res = (fscanf(f, "%d%d%lf%d%lf", &q, &a, &R, &b, &phi) == 5); + break; + default: + res = (fscanf(f, "%d%d%lf%d%lf%d%lf", &q, &a, &R, &b, &phi, &c, &theta) == 7); + break; } - else if(n == 2){ - r[0] = mr[a1].r[0] + R * sqrt( 1 - cos(phi)*cos(phi) ); - r[1] = mr[a1].r[1] + ( (mr[a2].r[1]q[n] = q; + res = !zmat2cart(n, m->r+3*n, + m->r+3*(a-1), m->r+3*(b-1), m->r+3*(c-1), + R, phi*DEG2RAD, theta*DEG2RAD); } + return res; +} +static inline int read_atom(FILE * f, int zmat, int n, mol * m){ + if(zmat){ + return read_z_atom(f, n, m); + } else{ + return read_cart_atom(f, n, m); + } +} - double ab[3], bc[3]; - double r1[3], r2[3]; - double perp[3]; - double rot[9]; - double t; - - double * a = mr[a1].r; - double * b = mr[a2].r; - double * c = mr[a3].r; - - r3diff(ab, b, a); - t = r3dot(ab,ab); - if(tr, BA); + } + return m; + hell: - fseek(f, pos, SEEK_SET); - free(a); + fseek(f, pos0, SEEK_SET); return NULL; } diff --git a/src/v/ac3_read_out.c b/src/v/ac3_read_out.c index 7d42703..96365d5 100644 --- a/src/v/ac3_read_out.c +++ b/src/v/ac3_read_out.c @@ -1,29 +1,41 @@ #include "v.h" +#include "vec3.h" +#include "mol.h" -txyz * ac3_read_out(int * n_p, FILE * f){ +mol * ac3_read_out(FILE * f){ - txyz * a = NULL; + long pos0 = ftell(f); + // find where the molecule begins char s[STRLEN]; - while (1){ - if (!fgets(s, sizeof(s), f)) { - return NULL; + while(1){ + if(!fgets(s, sizeof(s), f)){ + goto hell; } if(strstr(s, "Atomic Coordinates:")){ break; } } - int n = 0; - while(1) { - a = realloc(a, sizeof(txyz)*(n+1)); - if (fscanf (f, "%d%lf%lf%lf", - &(a[n].t), a[n].r, a[n].r+1, a[n].r+2) != 4) { - break; - } + // count atoms + long pos1 = ftell(f); + int n=0; + while(read_cart_atom(f, n, NULL)){ n++; } + if(!n){ + goto hell; + } + fseek(f, pos1, SEEK_SET); + + // fill in + mol * m = alloc_mol(n); + for(int i=0; ir+3*i, m->r+3*i+1, m->r+3*i+2, tmp_str) < 4) { + free(m); return NULL; } - a[i].t = get_element(type); + m->q[i] = get_element(type); } - *n_p = n; - return a; + return m; } diff --git a/src/v/bonds.c b/src/v/bonds.c index e13a6f5..a092168 100644 --- a/src/v/bonds.c +++ b/src/v/bonds.c @@ -1,6 +1,7 @@ #include "v.h" #include "vec3.h" +#define DMAX_SCALE 2.01 // look for bonds within max. atom diameter + eps #define boxnumber(BOX,NB) (BOX[0]*NB[1]*NB[2] + BOX[1]*NB[2] + BOX[2]) static int cmpint(const void * p1, const void * p2){ @@ -32,9 +33,10 @@ static void makelist(int bsize_max, int * bsize, int * list, return; } -static void bonds_add(double rl, double bmax, atcoord * ac){ - - double dmax = (bmax > 0.0) ? bmax : (2.01 * rl * getmaxradius(ac->n, ac->q)); +static void bonds_add(bondpars bond, atcoord * ac){ + double bmax = bond.bmax; + double rl = bond.rl; + double dmax = (bmax > 0.0) ? bmax : (DMAX_SCALE * rl * getmaxradius(ac->n, ac->q)); double rmin[3], rmax[3]; r3cp(rmin, ac->r); @@ -86,8 +88,8 @@ static void bonds_add(double rl, double bmax, atcoord * ac){ for(int ii=0; iibond_rl > 0.0 && ac->bond_a[k1*BONDS_MAX+BONDS_MAX-1] != -1){ - // at the 1st time ac->bond_rl==0.0 + if(ac->bonds.rl > 0.0 && ac->bonds.a[k1*BONDS_MAX+BONDS_MAX-1] != -1){ + // at the 1st time ac->bond->rl==0.0 if(!warned){ PRINT_WARN("too many bonds (>= %d)\n", BONDS_MAX); warned = 1; @@ -96,7 +98,7 @@ static void bonds_add(double rl, double bmax, atcoord * ac){ } for(int l=0; lbond_a[k1*BONDS_MAX+l] = -1; + ac->bonds.a[k1*BONDS_MAX+l] = -1; } int nb = 0; @@ -122,7 +124,7 @@ static void bonds_add(double rl, double bmax, atcoord * ac){ continue; } if(nbbond_a[k1*BONDS_MAX+nb] = k2; + ac->bonds.a[k1*BONDS_MAX+nb] = k2; nb++; } else{ @@ -137,10 +139,10 @@ static void bonds_add(double rl, double bmax, atcoord * ac){ } } toomany: - qsort(ac->bond_a+k1*BONDS_MAX, nb, sizeof(int), cmpint); + qsort(ac->bonds.a+k1*BONDS_MAX, nb, sizeof(int), cmpint); for(int l=0; lbond_a[k1*BONDS_MAX+l]; - ac->bond_r[k1*BONDS_MAX+l] = sqrt(r3d2(ac->r+k1*3, ac->r+k2*3)); + int k2 = ac->bonds.a[k1*BONDS_MAX+l]; + ac->bonds.r[k1*BONDS_MAX+l] = sqrt(r3d2(ac->r+k1*3, ac->r+k2*3)); } } @@ -153,36 +155,34 @@ static void bonds_add(double rl, double bmax, atcoord * ac){ return; } -static void bonds_reduce(double rl, atcoord * ac){ +static void bonds_reduce(bondpars bond, atcoord * ac){ for(int k1=0; k1n; k1++){ double r1 = getradius(ac->q[k1]); int nb = 0; for(int j=0; jbond_a[k1*BONDS_MAX+j]; + int k2 = ac->bonds.a[k1*BONDS_MAX+j]; if(k2==-1) break; - double r = ac->bond_r[k1*BONDS_MAX+j]; + double r = ac->bonds.r[k1*BONDS_MAX+j]; double r2 = getradius(ac->q[k2]); - if( r < rl*(r1+r2) ){ - ac->bond_a[k1*BONDS_MAX+nb] = k2; - ac->bond_r[k1*BONDS_MAX+nb] = r; + if( r < bond.rl*(r1+r2) ){ + ac->bonds.a[k1*BONDS_MAX+nb] = k2; + ac->bonds.r[k1*BONDS_MAX+nb] = r; nb++; } } for(int j=nb; jbond_a[k1*BONDS_MAX+j] = -1; + ac->bonds.a[k1*BONDS_MAX+j] = -1; } } return; } -void bonds_fill(double rl, double bmax, atcoord * ac){ - if(rl > ac->bond_rl){ - bonds_add (rl, bmax, ac); - } - else{ - bonds_reduce(rl, ac); +void bonds_fill(bondpars bond, atcoord * ac){ + if(ac->bonds.flag){ + return; } - ac->bond_rl = rl; + (bond.rl > ac->bonds.rl) ? bonds_add(bond, ac) : bonds_reduce(bond, ac); + ac->bonds.rl = bond.rl; + ac->bonds.flag = 1; return; } - diff --git a/src/v/cli.c b/src/v/cli.c index 0bb28d3..21c032c 100644 --- a/src/v/cli.c +++ b/src/v/cli.c @@ -3,104 +3,141 @@ #include "matrix.h" #include "vec3.h" -static int sscan_rot(const char * arg, double rot[9]){ - return sscanf(arg, "rot:%lf,%lf,%lf,%lf,%lf,%lf,%lf,%lf,%lf", rot, rot+1, rot+2, rot+3, rot+4, rot+5, rot+6, rot+7, rot+8); -} - -static int sscan_cell(const char * arg, double cell[9]){ - int count = sscanf(arg, "cell:b%lf,%lf,%lf,%lf,%lf,%lf,%lf,%lf,%lf", cell, cell+1, cell+2, cell+3, cell+4, cell+5, cell+6, cell+7, cell+8); - if(count==9 || count==3){ - vecscal(count, cell, BA); - return count; +#define EPS_INV 1e-15 + +static int lazysscanf(char * const s, const char * const template, char ** ret){ + // if the string `s` begins with the template, + // assign *ret to the part of the string after the template, + // otherwise do nothing + int n = strlen(template); + int r = !strncmp(template, s, n); + if(r){ + if(strlen(s)==n){ + PRINT_WARN("option %s needs an argument\n", template) + } + else{ + *ret = s+n; + } } - count = sscanf(arg, "cell:%lf,%lf,%lf,%lf,%lf,%lf,%lf,%lf,%lf", cell, cell+1, cell+2, cell+3, cell+4, cell+5, cell+6, cell+7, cell+8); - return count; + return r; } -static int sscan_shell(const char * arg, double shell[2]){ - int count = sscanf (arg, "shell:b%lf,%lf", shell, shell+1); - if(count==2){ - vecscal(count, shell, BA); - return count; +static int sscan_rot(const char * arg, double ac3rmx[9]){ + double rot[9]; + int count = sscanf(arg, "rot:%lf,%lf,%lf,%lf,%lf,%lf,%lf,%lf,%lf", rot, rot+1, rot+2, rot+3, rot+4, rot+5, rot+6, rot+7, rot+8); + if(count <= 0){ + return 0; } - count = sscanf (arg, "shell:%lf,%lf", shell, shell+1); - return count; + else if(count == 9){ + veccp(9, ac3rmx, rot); // we don't check if it is unitary + } + else{ + PRINT_WARN("option `rot:` takes exactly 9 comma-separated arguments\n") + } + return 1; } -static void getcell(double cell[9], drawpars * dp, int cell_count){ +static int sscan_cell(const char * arg, cellpars * cp){ + double cell[9]; + int count = sscanf(arg, "cell:b%lf,%lf,%lf,%lf,%lf,%lf,%lf,%lf,%lf", cell, cell+1, cell+2, cell+3, cell+4, cell+5, cell+6, cell+7, cell+8); + if(count > 0){ + if(count==9 || count==3){ + vecscal(count, cell, BA); + } + else{ + PRINT_WARN("option `cell:b` takes exactly 3 or 9 comma-separated arguments\n") + return 1; + } + } + else{ + count = sscanf(arg, "cell:%lf,%lf,%lf,%lf,%lf,%lf,%lf,%lf,%lf", cell, cell+1, cell+2, cell+3, cell+4, cell+5, cell+6, cell+7, cell+8); + if(count <= 0){ + return 0; + } + else if(count!=3 && count!=9){ + PRINT_WARN("option `cell:` takes exactly 3 or 9 comma-separated arguments\n") + return 1; + } + } - double a[3]={}; - double b[3]={}; - double c[3]={}; - if(cell_count==3){ + double a[3]={}, b[3]={}, c[3]={}; + if(count==3){ a[0] = cell[0]; b[1] = cell[1]; c[2] = cell[2]; } - else if(cell_count==9){ + else{ r3cp(a, cell+0); r3cp(b, cell+3); r3cp(c, cell+6); } - r3sums3(dp->vertices+ 0, a, -0.5, b, -0.5, c, -0.5); - r3sums3(dp->vertices+ 3, a, +0.5, b, -0.5, c, -0.5); - r3sums3(dp->vertices+ 6, a, -0.5, b, +0.5, c, -0.5); - r3sums3(dp->vertices+ 9, a, -0.5, b, -0.5, c, +0.5); - r3sums3(dp->vertices+12, a, +0.5, b, +0.5, c, -0.5); - r3sums3(dp->vertices+15, a, +0.5, b, -0.5, c, +0.5); - r3sums3(dp->vertices+18, a, -0.5, b, +0.5, c, +0.5); - r3sums3(dp->vertices+21, a, +0.5, b, +0.5, c, +0.5); + for(int i=0; i<2; i++){ + for(int j=0; j<2; j++){ + for(int k=0; k<2; k++){ + r3sums3(cp->vertices + (i*4+j*2+k)*3, a, i-0.5, b, j-0.5, c, k-0.5); + } + } + } double rot_to_lab_basis[9] = {a[0], b[0], c[0], a[1], b[1], c[1], a[2], b[2], c[2]}; - veccp(9, dp->rot_to_lab_basis, rot_to_lab_basis); - mx_id(3, dp->rot_to_cell_basis); - mx_inv(3, 3, dp->rot_to_cell_basis, rot_to_lab_basis, 1e-15); + veccp(9, cp->rot_to_lab_basis, rot_to_lab_basis); + mx_id(3, cp->rot_to_cell_basis); + mx_inv(3, 3, cp->rot_to_cell_basis, rot_to_lab_basis, EPS_INV); - dp->vert = 1; - return; + cp->vert = 1; + return 1; } -static void getshell(double shell[2], drawpars * dp){ - dp->vertices[0] = shell[0]; - dp->vertices[1] = shell[1]; - dp->vert = 2; - return; +static int sscan_shell(const char * arg, cellpars * cp){ + double shell[2]; + int count = sscanf(arg, "shell:b%lf,%lf", shell, shell+1); + if(count > 0){ + if(count==2) + vecscal(count, shell, BA); + } + else{ + count = sscanf(arg, "shell:%lf,%lf", shell, shell+1); + } + if(count <= 0) + return 0; + if(count == 2){ + cp->vertices[0] = shell[0]; + cp->vertices[1] = shell[1]; + cp->vert = 2; + } + return 1; } -static int cli_parse_arg(char * arg, drawpars * dp){ - int vib = -1; - int bonds = 1; - int frame = 1; - double rot [9]={0}; - double cell [9]={0}; - double shell[2]={0}; - double tf = 0.0; - double bmax = 0.0; - char ts[256] = ""; - - int a0 = sscanf (arg, "vib:%d", &vib); - int a1 = sscanf (arg, "dt:%lf", &tf); - int a2 = sscanf (arg, "symtol:%lf", &(dp->symtol)); - int a3 = sscanf (arg, "bonds:%d", &bonds); - int a4 = sscanf (arg, "z:%d,%d,%d,%d,%d", dp->z, dp->z+1, dp->z+2, dp->z+3, dp->z+4); - int a5 = sscanf (arg, "font:%255s", dp->fontname); - int a6 = sscanf (arg, "gui:%d", &(dp->gui)); - int a7 = sscanf (arg, "bohr:%d", &(dp->bohr)); - int a8 = sscanf (arg, "bmax:%lf", &bmax); - int a9 = sscanf (arg, "frame:%d", &frame); - int a10 = sscanf (arg, "center:%d", &(dp->center)); - int a11 = sscanf (arg, "inertia:%d", &(dp->inertia)); - int a12 = sscanf (arg, "com:%255s", dp->com); - int a13 = sscanf (arg, "exitcom:%255s", dp->on_exit); - int a14 = sscanf (arg, "colors:%255s", ts); - int rot_count = sscan_rot (arg, rot); - int cell_count = sscan_cell (arg, cell); - int shell_count = sscan_shell(arg, shell); - - int cli = a0||a1||a2||a3||a4||a5||a6||a7||a8||a9||a10||a11||a12||a13||a14 || rot_count||cell_count||shell_count; +static int cli_parse_arg(char * arg, allpars * ap){ + drawpars * dp = &ap->dp; + initpars * ip = &ap->ip; + int vib = -1, bonds = -2, frame = 0; + double tf = 0, bmax = 0; + char * ts = NULL; + + int cli = + sscanf (arg, "vib:%d", &vib) + || sscanf (arg, "bonds:%d", &bonds) + || sscanf (arg, "dt:%lf", &tf) + || sscanf (arg, "bmax:%lf", &bmax) + || sscanf (arg, "frame:%d", &frame) + || sscanf (arg, "symtol:%lf", &dp->anal.symtol) + || sscanf (arg, "gui:%d", &ip->gui) + || sscanf (arg, "bohr:%d", &dp->geom.bohr) + || sscanf (arg, "center:%d", &dp->geom.center) + || sscanf (arg, "inertia:%d", &dp->geom.inertia) + || sscanf (arg, "z:%d,%d,%d,%d,%d", dp->anal.intcoord, dp->anal.intcoord+1, dp->anal.intcoord+2, dp->anal.intcoord+3, dp->anal.intcoord+4) + || lazysscanf(arg, "font:", &ip->fontname) + || lazysscanf(arg, "com:", &dp->ui.com) + || lazysscanf(arg, "exitcom:", &dp->ui.on_exit) + || lazysscanf(arg, "colors:", &ts) + || sscan_rot (arg, dp->rend.ac3rmx) + || sscan_cell (arg, &dp->cell) + || sscan_shell(arg, &dp->cell) + ; if(vib==0){ dp->task = AT3COORDS; @@ -109,26 +146,30 @@ static int cli_parse_arg(char * arg, drawpars * dp){ dp->task = VIBRO; } - if(!bonds){ - dp->b = -1; + if(bonds==0){ + dp->rend.bonds = -1; } if(tf>0.0){ - dp->dt = ceil(tf*1e6); + dp->anim.dt = ceil(tf*S_TO_MS); } if(bmax>0.0){ - dp->bmax = bmax; + dp->bond.bmax = bmax; } - if(ts[0]){ + if(frame){ + dp->n = frame-1; + } + + if(ts){ const char * const colorscheme_names[] = {[V_COLORS] = "v", [CPK_COLORS] = "cpk"}; int ncs = sizeof(colorscheme_names)/sizeof(colorscheme_names[0]); for(int i=0; icolors = i; + ip->colors = i; break; } if(i==ncs-1){ @@ -137,77 +178,45 @@ static int cli_parse_arg(char * arg, drawpars * dp){ } } - if(rot_count==9){ - veccp(9, dp->ac3rmx, rot); // we don't check if the matrix is unitary - } - if(cell_count==3 || cell_count==9){ - getcell(cell, dp, cell_count); - } - if(shell_count==2){ - getshell(shell, dp); - } - dp->n = frame-1; - if(!cli){ - dp->input_files[dp->input_files_n++] = arg; + ip->input_files[ip->input_files_n++] = arg; } return cli; } -static drawpars dp_init(void){ - drawpars dp = {}; - dp.task = UNKNOWN; - dp.gui = 1; - dp.input = 0; - memset(dp.input_text, 0, STRLEN); - dp.dt = DEFAULT_TIMEOUT; - memset(dp.fontname, 0, STRLEN); - dp.n = 0; - dp.fbw = 0; - dp.num = 0; - dp.t = 0; - dp.rl = 1.0; - dp.r = 1.0; - dp.xy0[0] = dp.xy0[1] = 0.0; - mx_id(3, dp.ac3rmx); - // from command-line - dp.inertia = 0; - dp.center = 1; - dp.b = 1; - dp.bmax = 0.0; - dp.symtol = DEFAULT_SYMTOL; - dp.vert = -1; - dp.z[0] = dp.z[1] = dp.z[2] = dp.z[3] = dp.z[4] = 0; - vecset(3*8, dp.vertices, 0.0); - memset(dp.com, 0, STRLEN); - memset(dp.on_exit, 0, STRLEN); - dp.input_files_n = 0; - dp.input_files = NULL; - dp.colors = V_COLORS; - // from data read - dp.scale = 1.0; - dp.N = 0; - dp.f = NULL; - dp.fname = NULL; - dp.bohr = 0; - // runtime - dp.closed = 0; - return dp; +static allpars allpars_init(void){ + allpars ap = {}; // everything not set below is 0 / 0.0 / NULL / '\0' + + ap.ip.gui = 1; + ap.ip.colors = V_COLORS; + + ap.dp.task = UNKNOWN; + ap.dp.anim.dt = DEFAULT_TIMEOUT; + ap.dp.anal.symtol = DEFAULT_SYMTOL; + ap.dp.bond.rl = 1.0; + ap.dp.cell.vert = -1; + ap.dp.geom.center = 1; + + ap.dp.rend.r = 1.0; + ap.dp.rend.scale = 1.0; + ap.dp.rend.bonds = 1; + mx_id(3, ap.dp.rend.ac3rmx); + + return ap; } -drawpars cli_parse(int argc, char ** argv){ - drawpars dp = dp_init(); - dp.input_files = malloc(argc*sizeof(char*)); +allpars cli_parse(int argc, char ** argv){ + allpars ap = allpars_init(); + ap.ip.input_files = malloc(argc*sizeof(char*)); for(int i=1; im[dp->n]; +static void redraw_ac3(object * ent, drawpars * dp){ + atcoord * ac = ent->m[dp->n]; - if(dp->b>0 && !ac->bond_flag){ - bonds_fill(dp->rl, dp->bmax, ac); - ac->bond_flag = 1; + if(dp->rend.bonds>0){ + bonds_fill(dp->bond, ac); } - ac3_draw(ac, dp->r, dp->scale, dp->xy0, dp->b, dp->num); + ac3_draw(ac, dp->rend); ac3_text(ac, dp); - if(dp->vert == 1){ + if(dp->cell.vert == 1){ double v[24]; for(int i=0; i<8; i++){ - r3mx (v+3*i, dp->vertices+3*i, dp->ac3rmx); + r3mx (v+3*i, dp->cell.vertices+3*i, dp->rend.ac3rmx); } - drawvertices(v, dp->scale, dp->xy0); + drawvertices(v, dp->rend.scale, dp->rend.xy0); } - else if(dp->vert == 2){ - drawshell(dp->vertices[0], dp->vertices[1], dp->scale, dp->xy0); + else if(dp->cell.vert == 2){ + drawshell(dp->cell.vertices[0], dp->cell.vertices[1], dp->rend.scale, dp->rend.xy0); } return; } -static void redraw_vibro(void * ent, drawpars * dp){ +static void redraw_vibro(object * ent, drawpars * dp){ - atcoord * ac = ((vibrstr *)ent)->ac; - double * m0 = ((vibrstr *)ent)->mode0; - modestr * ms = ((vibrstr *)ent)->modes; - double * m = ms->d + dp->n * ac->n*3; + atcoord * m = ent->m[0]; + double * r0 = ent->vib->r0; + double * dr = ent->vib->disp + dp->n * m->n*3; - if(dp->b>0 && !ac->bond_flag){ - bonds_fill(dp->rl, dp->bmax, ac); - ac->bond_flag = 1; + if(dp->rend.bonds>0){ + bonds_fill(dp->bond, m); } - vecsums(ac->n*3, ac->r, m0, m, sin( dp->t * 2.0*M_PI/TMAX ) * 0.1*sqrt(ac->n) ); - for(int j=0; jn; j++){ + vecsums(m->n*3, m->r, r0, dr, sin( dp->anim.t * 2.0*M_PI/TMAX ) * vibration_amplitude*sqrt(m->n) ); + for(int j=0; jn; j++){ double v[3]; - r3mx(v, ac->r+3*j, dp->ac3rmx); - r3cp(ac->r+3*j, v); + r3mx(v, m->r+3*j, dp->rend.ac3rmx); + r3cp(m->r+3*j, v); } - ac3_draw(ac, dp->r, dp->scale, dp->xy0, dp->b, dp->num); - vibro_text(ms, dp); + ac3_draw(m, dp->rend); + vibro_text(ent->vib, dp); return; } -void kp_readmore(void * ent, drawpars * dp){ +void kp_readmore(object * ent, drawpars * dp){ if(dp->task == AT3COORDS){ - atcoords * acs = ent; - if(!dp->f){ - PRINT_ERR("cannot read from the file '%s'\n", dp->fname); + object * acs = ent; + if(!dp->read.f){ + PRINT_ERR("cannot read from the file '%s'\n", dp->read.fname); return; } - fseek(dp->f, 0, SEEK_CUR); - acs_readmore(dp->f, dp->b, dp->center, dp->inertia, dp->bohr, acs, dp->fname); + fseek(dp->read.f, 0, SEEK_CUR); + acs_readmore(dp->read, dp->rend.bonds, dp->geom, acs); newmol_prep(acs, dp); redraw_ac3 (acs, dp); } return; } -void kp_readagain(void * ent, drawpars * dp){ +void kp_readagain(object * ent, drawpars * dp){ if(dp->task == AT3COORDS){ - if(!dp->f || !(fclose(dp->f), dp->f = fopen(dp->fname, "r"))){ - PRINT_WARN("cannot reload the file '%s'\n", dp->fname); + if(!dp->read.f || !(fclose(dp->read.f), dp->read.f = fopen(dp->read.fname, "r"))){ + PRINT_WARN("cannot reload the file '%s'\n", dp->read.fname); return; } - atcoords * acs = ent; + object * acs = ent; for(int i=0; in; i++){ free(acs->m[i]); } acs->n = dp->N = dp->n = 0; - acs_readmore(dp->f, dp->b, dp->center, dp->inertia, dp->bohr, acs, dp->fname); + acs_readmore(dp->read, dp->rend.bonds, dp->geom, acs); newmol_prep(acs, dp); redraw_ac3 (acs, dp); } return; } -void kp_print(void * ent, drawpars * dp){ +void kp_print(object * ent, drawpars * dp){ if (dp->task == AT3COORDS){ - atcoord * ac = ((atcoords *)ent)->m[dp->n]; - ac3_print(ac, dp->xy0, dp->b); + atcoord * ac = ent->m[dp->n]; + ac3_print(ac, dp->rend); } return; } -void kp_print_xyz(void * ent, drawpars * dp){ +void kp_print_xyz(object * ent, drawpars * dp){ if (dp->task == AT3COORDS){ - atcoord * ac = ((atcoords *)ent)->m[dp->n]; - ac3_print_xyz(ac, dp->xy0); + atcoord * ac = ent->m[dp->n]; + ac3_print_xyz(ac, dp->rend); } return; } -void kp_printrot(void * ent __attribute__ ((unused)), drawpars * dp){ - double * U = dp->ac3rmx; +void kp_printrot(object * ent __attribute__ ((unused)), drawpars * dp){ + double * U = dp->rend.ac3rmx; for(int i=0; i<3; i++){ PRINTOUT(stdout, "rotation> % 20.15lf % 20.15lf % 20.15lf\n", U[i*3], U[i*3+1], U[i*3+2]); } @@ -121,106 +122,100 @@ void kp_printrot(void * ent __attribute__ ((unused)), drawpars * dp){ return; } -void kp_print2fig(void * ent, drawpars * dp){ +void kp_print2fig(object * ent, drawpars * dp){ if (dp->task == AT3COORDS){ double v[3*8]; - if(dp->vert == 1){ + if(dp->cell.vert == 1){ for(int i=0; i<8; i++){ - r3mx (v+3*i, dp->vertices+3*i, dp->ac3rmx); + r3mx (v+3*i, dp->cell.vertices+3*i, dp->rend.ac3rmx); } } - atcoord * ac = ((atcoords *)ent)->m[dp->n]; - ac3_print2fig(ac, dp->xy0, dp->b, dp->vert==1?v:NULL); + atcoord * ac = ent->m[dp->n]; + ac3_print2fig(ac, dp->rend, dp->cell.vert==1?v:NULL); } return; } -static void rl_changed(void * ent, drawpars * dp){ - if(dp->task==AT3COORDS){ - for(int i=0; iN; i++){ - ((atcoords *)ent)->m[i]->bond_flag = 0; - } - redraw_ac3(ent, dp); - } - else{ - ((vibrstr *)ent)->ac->bond_flag = 0; - redraw_vibro(ent, dp); +static void rl_changed(object * ent, drawpars * dp){ + for(int i=0; in; i++){ + ent->m[i]->bonds.flag = 0; } + exp_redraw(ent, dp); return; } -void kp_rl_dec(void * ent, drawpars * dp){ - if(dp->b>0){ - dp->rl /= step_r; +void kp_rl_dec(object * ent, drawpars * dp){ + if(dp->rend.bonds>0){ + dp->bond.rl /= step_r; rl_changed(ent, dp); } return; } -void kp_rl_inc(void * ent, drawpars * dp){ - if(dp->b>0){ - dp->rl *= step_r; +void kp_rl_inc(object * ent, drawpars * dp){ + if(dp->rend.bonds>0){ + dp->bond.rl *= step_r; rl_changed(ent, dp); } return; } -void kp_r_dec(void * ent, drawpars * dp){ - dp->r /= step_r; +void kp_r_dec(object * ent, drawpars * dp){ + dp->rend.r /= step_r; exp_redraw(ent, dp); return; } -void kp_r_inc(void * ent, drawpars * dp){ - dp->r *= step_r; +void kp_r_inc(object * ent, drawpars * dp){ + dp->rend.r *= step_r; exp_redraw(ent, dp); return; } -void kp_zoom_out(void * ent, drawpars * dp){ - dp->scale /= step_zoom; +void kp_zoom_out(object * ent, drawpars * dp){ + dp->rend.scale /= step_zoom; exp_redraw(ent, dp); return; } -void kp_zoom_in(void * ent, drawpars * dp){ - dp->scale *= step_zoom; +void kp_zoom_in(object * ent, drawpars * dp){ + dp->rend.scale *= step_zoom; exp_redraw(ent, dp); return; } -void kp_frame_inc(void * ent, drawpars * dp){ +void kp_frame_inc(object * ent, drawpars * dp){ if (dp->n < dp->N-1){ dp->n++; exp_redraw(ent, dp); } if (dp->n == dp->N-1 && dp->task == AT3COORDS){ - dp->fbw = 0; + dp->anim.dir = 0; } return; } -void kp_frame_dec(void * ent, drawpars * dp){ +void kp_frame_dec(object * ent, drawpars * dp){ if (dp->n > 0){ dp->n--; exp_redraw(ent, dp); } if (dp->n == 0 && dp->task == AT3COORDS){ - dp->fbw = 0; + dp->anim.dir = 0; } return; } -void rot_ent_pointer(void * ent, drawpars * dp, int dx, int dy, double speed){ +void rot_ent_pointer(object * ent, drawpars * dp, int dx, int dy, double speed){ double rotation_matrix[9]; rot_around_perp(rotation_matrix, (double)dx, (double)dy, speed); double mx0[9]; - veccp(9, mx0, dp->ac3rmx); - mx_multmx(3,3,3, dp->ac3rmx, rotation_matrix, mx0); + veccp(9, mx0, dp->rend.ac3rmx); + mx_multmx(3,3,3, dp->rend.ac3rmx, rotation_matrix, mx0); if(dp->task == AT3COORDS){ - atcoords * acs = ent; + object * acs = ent; for(int i=0; iN; i++){ rot3d(acs->m[i]->n, acs->m[i]->r, rotation_matrix); } @@ -228,16 +223,16 @@ void rot_ent_pointer(void * ent, drawpars * dp, int dx, int dy, double speed){ return; } -static void rot_ent(void * ent, drawpars * dp, int axis, double angle){ - if(dp->modkey){ +static void rot_ent(object * ent, drawpars * dp, int axis, double angle){ + if(dp->ui.modkey){ angle *= step_mod; } double m[9]; - rotmx0_update(dp->ac3rmx, m, angle, axis); + rotmx0_update(dp->rend.ac3rmx, m, angle, axis); if(dp->task == AT3COORDS){ - atcoords * acs = ent; + object * acs = ent; for(int i=0; iN; i++){ rot3d(acs->m[i]->n, acs->m[i]->r, m); } @@ -245,37 +240,37 @@ static void rot_ent(void * ent, drawpars * dp, int axis, double angle){ return; } -void kp_rotx_l(void * ent, drawpars * dp){ +void kp_rotx_l(object * ent, drawpars * dp){ rot_ent(ent, dp, 0, +step_rot); exp_redraw(ent, dp); return; } -void kp_rotx_r(void * ent, drawpars * dp){ +void kp_rotx_r(object * ent, drawpars * dp){ rot_ent(ent, dp, 0, -step_rot); exp_redraw(ent, dp); return; } -void kp_roty_l(void * ent, drawpars * dp){ +void kp_roty_l(object * ent, drawpars * dp){ rot_ent(ent, dp, 1, +step_rot); exp_redraw(ent, dp); return; } -void kp_roty_r(void * ent, drawpars * dp){ +void kp_roty_r(object * ent, drawpars * dp){ rot_ent(ent, dp, 1, -step_rot); exp_redraw(ent, dp); return; } -void kp_rotz_l(void * ent, drawpars * dp){ +void kp_rotz_l(object * ent, drawpars * dp){ rot_ent(ent, dp, 2, +step_rot); exp_redraw(ent, dp); return; } -void kp_rotz_r(void * ent, drawpars * dp){ +void kp_rotz_r(object * ent, drawpars * dp){ rot_ent(ent, dp, 2, -step_rot); exp_redraw(ent, dp); return; @@ -283,11 +278,11 @@ void kp_rotz_r(void * ent, drawpars * dp){ static void mol2cell(double r0[3], drawpars * dp){ double mat[9], r[3]; - veccp(9, mat, dp->ac3rmx); + veccp(9, mat, dp->rend.ac3rmx); r3cp(r, r0); - mx_inv (3, 1, r, mat, 1e-15); + mx_inv (3, 1, r, mat, EPS_INV); double rcell[3]; - r3mx(rcell, r, dp->rot_to_cell_basis); + r3mx(rcell, r, dp->cell.rot_to_cell_basis); for(int i=0; i<3; i++){ if(rcell[i]<-0.5){ rcell[i] += 1.0; @@ -296,111 +291,112 @@ static void mol2cell(double r0[3], drawpars * dp){ rcell[i] -= 1.0; } } - r3mx(r, rcell, dp->rot_to_lab_basis); - r3mx(r0, r, dp->ac3rmx); + r3mx(r, rcell, dp->cell.rot_to_lab_basis); + r3mx(r0, r, dp->rend.ac3rmx); return; } -static void move_pbc(atcoords * acs, drawpars * dp, int dir, double d){ +static void move_pbc(object * acs, drawpars * dp, int dir, double d){ for(int i=0; iN; i++){ for(int j=0; jm[i]->n; j++){ double * r = acs->m[i]->r+j*3; r[dir] += d; mol2cell(r, dp); } - if(dp->b>0){ - acs->m[i]->bond_flag = 0; - acs->m[i]->bond_rl *= 0.9; + if(dp->rend.bonds>0){ + acs->m[i]->bonds.flag = 0; + acs->m[i]->bonds.rl *= rl_move_pbc_scale; } } return; } -static void move_ent(void * ent, drawpars * dp, int dir, double step){ - if(dp->modkey){ +static void move_ent(object * ent, drawpars * dp, int dir, double step){ + if(dp->ui.modkey){ step *= step_mod; } - if(dp->vert == 1){ + if(dp->cell.vert == 1){ move_pbc(ent, dp, dir, step); } else { - dp->xy0[dir] += step; + dp->rend.xy0[dir] += step; } return; } -void kp_move_l(void * ent, drawpars * dp){ +void kp_move_l(object * ent, drawpars * dp){ move_ent(ent, dp, 0, -step_move); exp_redraw(ent, dp); return; } -void kp_move_r(void * ent, drawpars * dp){ +void kp_move_r(object * ent, drawpars * dp){ move_ent(ent, dp, 0, +step_move); exp_redraw(ent, dp); return; } -void kp_move_u(void * ent, drawpars * dp){ +void kp_move_u(object * ent, drawpars * dp){ move_ent(ent, dp, 1, +step_move); exp_redraw(ent, dp); return; } -void kp_move_d(void * ent, drawpars * dp){ +void kp_move_d(object * ent, drawpars * dp){ move_ent(ent, dp, 1, -step_move); exp_redraw(ent, dp); return; } -void kp_exit(void * ent, drawpars * dp){ - run_commands(NULL, dp->on_exit, dp, ent); - ent_free(ent, dp); +void kp_exit(object * ent, drawpars * dp){ + run_commands(NULL, dp->ui.on_exit, dp, ent); + obj_free(ent); close_x(); - dp->closed = 1; + CLOSE0(dp->read.f); + dp->ui.closed = 1; } -void kp_fw_toggle(void * ent __attribute__ ((unused)), drawpars * dp){ - dp->fbw = (dp->fbw == 1) ? 0 : 1; +void kp_fw_toggle(object * ent __attribute__ ((unused)), drawpars * dp){ + dp->anim.dir = (dp->anim.dir == 1) ? 0 : 1; return; } -void kp_bw_toggle(void * ent __attribute__ ((unused)), drawpars * dp){ +void kp_bw_toggle(object * ent __attribute__ ((unused)), drawpars * dp){ if (dp->task == AT3COORDS){ - dp->fbw = (dp->fbw == -1) ? 0 : -1; + dp->anim.dir = (dp->anim.dir == -1) ? 0 : -1; } return; } -void kp_l_toggle(void * ent, drawpars * dp){ - if(dp->b>0){ - dp->b = 1+!(dp->b-1); +void kp_l_toggle(object * ent, drawpars * dp){ + if(dp->rend.bonds>0){ + dp->rend.bonds = 1+!(dp->rend.bonds-1); exp_redraw(ent, dp); } return; } -void kp_b_toggle(void * ent, drawpars * dp){ - if(dp->b>-1){ - dp->b = !dp->b; +void kp_b_toggle(object * ent, drawpars * dp){ + if(dp->rend.bonds>-1){ + dp->rend.bonds = !dp->rend.bonds; } exp_redraw(ent, dp); return; } -void kp_n_toggle(void * ent, drawpars * dp){ - dp->num = (dp->num == 1) ? 0 : 1; +void kp_n_toggle(object * ent, drawpars * dp){ + dp->rend.num = (dp->rend.num == 1) ? 0 : 1; exp_redraw(ent, dp); return; } -void kp_t_toggle(void * ent, drawpars * dp){ - dp->num = (dp->num == -1) ? 0 : -1; +void kp_t_toggle(object * ent, drawpars * dp){ + dp->rend.num = (dp->rend.num == -1) ? 0 : -1; exp_redraw(ent, dp); return; } -void kp_goto_last(void * ent, drawpars * dp){ +void kp_goto_last(object * ent, drawpars * dp){ if (dp->n < dp->N-1){ dp->n=dp->N-1; exp_redraw(ent, dp); @@ -408,7 +404,7 @@ void kp_goto_last(void * ent, drawpars * dp){ return; } -void kp_goto_1st(void * ent, drawpars * dp){ +void kp_goto_1st(object * ent, drawpars * dp){ if (dp->n > 0){ dp->n = 0; exp_redraw(ent, dp); @@ -416,7 +412,7 @@ void kp_goto_1st(void * ent, drawpars * dp){ return; } -void exp_redraw(void * ent, drawpars * dp){ +void exp_redraw(object * ent, drawpars * dp){ switch (dp->task){ case AT3COORDS: redraw_ac3(ent, dp); @@ -430,10 +426,10 @@ void exp_redraw(void * ent, drawpars * dp){ return; } -void time_gone(void * ent, drawpars * dp){ +void time_gone(object * ent, drawpars * dp){ if(dp->task == VIBRO){ - if(dp->t >= TMAX){ - dp->t = dp->t-TMAX; + if(dp->anim.t >= TMAX){ + dp->anim.t = dp->anim.t-TMAX; } redraw_vibro(ent, dp); } @@ -443,7 +439,7 @@ void time_gone(void * ent, drawpars * dp){ static void savevib(drawpars * dp, int c){ char s[STRLEN]; int l = (int)(log10( dp->N + 0.5 )) + 1; - snprintf(s, sizeof(s), "%s_%0*d_%02d.xpm", dp->fname, l, dp->n+1, c); + snprintf(s, sizeof(s), "%s_%0*d_%02d.xpm", dp->read.fname, l, dp->n+1, c); if (savepic(s) != XpmSuccess){ PRINT_ERR("cannot save '%s'\n", s); } @@ -453,10 +449,10 @@ static void savevib(drawpars * dp, int c){ return; } -void kp_savepic(void * ent __attribute__ ((unused)), drawpars * dp){ +void kp_savepic(object * ent __attribute__ ((unused)), drawpars * dp){ char s[STRLEN]; int l = (int)(log10(dp->N+0.5))+1; - atcoord * ac = ((atcoords *)ent)->m[dp->n]; + atcoord * ac = ent->m[dp->n]; snprintf(s, sizeof(s), "%s_%0*d.xpm", ac->fname, l, dp->n+1); if (savepic(s) != XpmSuccess){ PRINT_ERR("cannot save '%s'\n", s); @@ -467,7 +463,7 @@ void kp_savepic(void * ent __attribute__ ((unused)), drawpars * dp){ return; } -void kp_film(void * ent, drawpars * dp){ +void kp_film(object * ent, drawpars * dp){ if(dp->task != VIBRO){ kp_savepic (ent, dp); while(dp->nN-1){ @@ -477,30 +473,30 @@ void kp_film(void * ent, drawpars * dp){ } else{ int c = 0; - dp->t = 0; + dp->anim.t = 0; do{ savevib(dp, c); - dp->t++; + dp->anim.t++; time_gone(ent, dp); } while(++ctask == AT3COORDS){ - atcoord * ac = ((atcoords *)ent)->m[dp->n]; + atcoord * ac = ent->m[dp->n]; if(!ac->sym[0]){ - pg(ac, ac->sym, dp->symtol); + pg(ac, dp->anal.symtol); redraw_ac3(ent, dp); } } return; } -void kp_jump(void * ent, drawpars * dp){ - if(!dp->input){ - dp->input = 1; +void kp_jump(object * ent, drawpars * dp){ + if(!dp->ui.input){ + dp->ui.input = 1; exp_redraw(ent, dp); } return; diff --git a/src/v/evr.h b/src/v/evr.h index 54cb720..949e32d 100644 --- a/src/v/evr.h +++ b/src/v/evr.h @@ -1,45 +1,45 @@ #include "3d.h" #define TMAX 20 -void kp_readmore (void * ent, drawpars * dp); -void kp_readagain(void * ent, drawpars * dp); -void kp_print (void * ent, drawpars * dp); -void kp_print_xyz(void * ent, drawpars * dp); -void kp_print2fig(void * ent, drawpars * dp); -void kp_printrot (void * ent, drawpars * dp); -void kp_rl_inc (void * ent, drawpars * dp); -void kp_rl_dec (void * ent, drawpars * dp); -void kp_r_inc (void * ent, drawpars * dp); -void kp_r_dec (void * ent, drawpars * dp); -void kp_zoom_out (void * ent, drawpars * dp); -void kp_zoom_in (void * ent, drawpars * dp); -void kp_lat_dec (void * ent, drawpars * dp); -void kp_lat_inc (void * ent, drawpars * dp); -void kp_frame_inc(void * ent, drawpars * dp); -void kp_frame_dec(void * ent, drawpars * dp); -void kp_rotz_l (void * ent, drawpars * dp); -void kp_rotz_r (void * ent, drawpars * dp); -void kp_roty_l (void * ent, drawpars * dp); -void kp_roty_r (void * ent, drawpars * dp); -void kp_rotx_l (void * ent, drawpars * dp); -void kp_rotx_r (void * ent, drawpars * dp); -void kp_move_l (void * ent, drawpars * dp); -void kp_move_r (void * ent, drawpars * dp); -void kp_move_u (void * ent, drawpars * dp); -void kp_move_d (void * ent, drawpars * dp); -void kp_exit (void * ent, drawpars * dp); -void kp_l_toggle (void * ent, drawpars * dp); -void kp_b_toggle (void * ent, drawpars * dp); -void kp_t_toggle (void * ent, drawpars * dp); -void kp_n_toggle (void * ent, drawpars * dp); -void kp_fw_toggle(void * ent, drawpars * dp); -void kp_bw_toggle(void * ent, drawpars * dp); -void kp_goto_last(void * ent, drawpars * dp); -void kp_goto_1st (void * ent, drawpars * dp); -void exp_redraw (void * ent, drawpars * dp); -void time_gone (void * ent, drawpars * dp); -void kp_savepic (void * ent, drawpars * dp); -void kp_film (void * ent, drawpars * dp); -void kp_pg (void * ent, drawpars * dp); -void kp_jump (void * ent, drawpars * dp); -void rot_ent_pointer(void * ent, drawpars * dp, int dx, int dy, double speed); +void kp_readmore (object * ent, drawpars * dp); +void kp_readagain(object * ent, drawpars * dp); +void kp_print (object * ent, drawpars * dp); +void kp_print_xyz(object * ent, drawpars * dp); +void kp_print2fig(object * ent, drawpars * dp); +void kp_printrot (object * ent, drawpars * dp); +void kp_rl_inc (object * ent, drawpars * dp); +void kp_rl_dec (object * ent, drawpars * dp); +void kp_r_inc (object * ent, drawpars * dp); +void kp_r_dec (object * ent, drawpars * dp); +void kp_zoom_out (object * ent, drawpars * dp); +void kp_zoom_in (object * ent, drawpars * dp); +void kp_lat_dec (object * ent, drawpars * dp); +void kp_lat_inc (object * ent, drawpars * dp); +void kp_frame_inc(object * ent, drawpars * dp); +void kp_frame_dec(object * ent, drawpars * dp); +void kp_rotz_l (object * ent, drawpars * dp); +void kp_rotz_r (object * ent, drawpars * dp); +void kp_roty_l (object * ent, drawpars * dp); +void kp_roty_r (object * ent, drawpars * dp); +void kp_rotx_l (object * ent, drawpars * dp); +void kp_rotx_r (object * ent, drawpars * dp); +void kp_move_l (object * ent, drawpars * dp); +void kp_move_r (object * ent, drawpars * dp); +void kp_move_u (object * ent, drawpars * dp); +void kp_move_d (object * ent, drawpars * dp); +void kp_exit (object * ent, drawpars * dp); +void kp_l_toggle (object * ent, drawpars * dp); +void kp_b_toggle (object * ent, drawpars * dp); +void kp_t_toggle (object * ent, drawpars * dp); +void kp_n_toggle (object * ent, drawpars * dp); +void kp_fw_toggle(object * ent, drawpars * dp); +void kp_bw_toggle(object * ent, drawpars * dp); +void kp_goto_last(object * ent, drawpars * dp); +void kp_goto_1st (object * ent, drawpars * dp); +void exp_redraw (object * ent, drawpars * dp); +void time_gone (object * ent, drawpars * dp); +void kp_savepic (object * ent, drawpars * dp); +void kp_film (object * ent, drawpars * dp); +void kp_pg (object * ent, drawpars * dp); +void kp_jump (object * ent, drawpars * dp); +void rot_ent_pointer(object * ent, drawpars * dp, int dx, int dy, double speed); diff --git a/src/v/get_atpar.c b/src/v/get_atpar.c index 325c929..7114a12 100644 --- a/src/v/get_atpar.c +++ b/src/v/get_atpar.c @@ -57,13 +57,14 @@ int get_element(styp s){ return (int)q; } - s[0] = toupper(s[0]); + styp ts = ""; + ts[0] = toupper(s[0]); for(int i=1; s[i]; i++){ - s[i] = tolower(s[i]); + ts[i] = tolower(s[i]); } for(int q=1; q<=NATOMS; q++){ - if(!strncmp(s, aname[q], NAMELEN)){ + if(!strncmp(ts, aname[q], NAMELEN)){ return q; } } diff --git a/src/v/headless.c b/src/v/headless.c index 0673d4d..485ad84 100644 --- a/src/v/headless.c +++ b/src/v/headless.c @@ -1,13 +1,13 @@ #include "v.h" #include "evr.h" -void run_commands(FILE * f, char * command, drawpars * dp, void * ent){ +void run_commands(FILE * f, char * command, drawpars * dp, object * ent){ char * com = command; char c; while(1){ - if(command[0]){ + if(command && command[0]){ c = *(com++); } else if(f){ @@ -29,9 +29,9 @@ void run_commands(FILE * f, char * command, drawpars * dp, void * ent){ kp_print(ent, dp); break; case('.'): { - styp sym; - pg(((atcoords *)ent)->m[dp->n], sym, dp->symtol); - PRINTOUT(stdout, "%s\n", sym); + atcoord * ac = ent->m[dp->n]; + pg(ac, dp->anal.symtol); + PRINTOUT(stdout, "%s\n", ac->sym); }; break; case(' '): @@ -47,12 +47,13 @@ void run_commands(FILE * f, char * command, drawpars * dp, void * ent){ return; } -int headless(drawpars * dp, void * ent){ - atcoord * ac = ((atcoords *)ent)->m[dp->n]; - if(dp->b>0 && !ac->bond_flag){ - bonds_fill(dp->rl, dp->bmax, ac); +int headless(drawpars * dp, object * ent){ + atcoord * ac = ent->m[dp->n]; + if(dp->rend.bonds>0){ + bonds_fill(dp->bond, ac); } - run_commands(stdin, dp->com, dp, ent); - ent_free(ent, dp); + run_commands(stdin, dp->ui.com, dp, ent); + obj_free(ent); + CLOSE0(dp->read.f); return 0; } diff --git a/src/v/load.c b/src/v/load.c index 6826a92..3fb4096 100644 --- a/src/v/load.c +++ b/src/v/load.c @@ -5,7 +5,7 @@ #define N_MIN 256 -static inline void fill_nf(atcoords * acs, int n0){ +static inline void fill_nf(object * acs, int n0){ for(int j=n0; jn; j++){ acs->m[j]->nf[0] = j-n0; acs->m[j]->nf[1] = acs->n-n0; @@ -13,12 +13,12 @@ static inline void fill_nf(atcoords * acs, int n0){ return; } -void acs_readmore(FILE * f, int b, int center, int inertia, int bohr, atcoords * acs, const char * fname){ +void acs_readmore(readpars read, int b, geompars geom, object * acs){ // needed to reset nf int n0 = acs->n; // if continue reading from a previously opened file, find the first molecule from it - if(ftell(f) && acs->n){ + if(ftell(read.f) && acs->n){ for(int i=1; i<=acs->n; i++){ int n1 = acs->n-i; if(acs->m[n1]->nf[0]==0){ @@ -30,12 +30,12 @@ void acs_readmore(FILE * f, int b, int center, int inertia, int bohr, atcoords * atcoord * m; format_t format = UNKNOWN_FORMAT; - while((m = ac3_read(f, b, center, inertia, bohr, fname, &format))!=NULL){ + while((m = ac3_read(read, b, geom, &format))!=NULL){ if(acs->n==acs->Nmem){ int N = acs->Nmem ? acs->Nmem*2 : N_MIN; atcoord ** ms = realloc(acs->m, N*sizeof(atcoord *)); if(!ms){ - acs_free(acs); + obj_free(acs); free(m); PRINT_ERR("cannot reallocate memory\n"); abort(); @@ -49,21 +49,22 @@ void acs_readmore(FILE * f, int b, int center, int inertia, int bohr, atcoords * return; } -static vibrstr * mode_read_try(FILE * f, atcoord * ac){ +static object * mode_read_try(FILE * f, atcoord * ac){ long pos = ftell(f); rewind(f); int n = ac->n; - modestr * modes = mode_read(f, n); + vibr_t * modes = mode_read(f, n); if(modes){ - vibrstr * vib = malloc(sizeof(vibrstr) + sizeof(double)*n*3); - vib->ac = ac; - vib->modes = modes; - vib->mode0 = (double *)(vib + 1); - veccp(n*3, vib->mode0, ac->r); - return vib; + object * ent = malloc(sizeof(object)); + ent->Nmem = ent->n = 1; + ent->m = malloc(ent->Nmem*sizeof(atcoord *)); + ent->m[0] = ac; + ent->vib = modes; + veccp(n*3, ent->vib->r0, ac->r); + return ent; } else{ fseek(f, pos, SEEK_SET); @@ -71,7 +72,7 @@ static vibrstr * mode_read_try(FILE * f, atcoord * ac){ } } -static FILE * acs_read_newfile(atcoords * acs, char * fname, drawpars * dp){ +static FILE * acs_read_newfile(object * acs, char * fname, drawpars * dp){ FILE * f; if(!strcmp(fname, "-")){ f = stdin; @@ -82,32 +83,33 @@ static FILE * acs_read_newfile(atcoords * acs, char * fname, drawpars * dp){ return NULL; } } - acs_readmore(f, dp->b, dp->center, dp->inertia, dp->bohr, acs, fname); + acs_readmore((readpars){f, fname}, dp->rend.bonds, dp->geom, acs); return f; } -static void * ent_read(char * fname, drawpars * dp){ +static object * ent_read(char * fname, drawpars * dp){ - atcoords * acs = malloc(sizeof(atcoords)); + object * acs = malloc(sizeof(object)); acs->Nmem = 0; acs->n = 0; acs->m = NULL; + acs->vib = NULL; FILE * f = acs_read_newfile(acs, fname, dp); if(!f || !acs->n){ free(acs); return NULL; } - dp->fname = fname; + dp->read.fname = fname; if(dp->task==UNKNOWN || dp->task==VIBRO){ - vibrstr * vib = mode_read_try(f, acs->m[acs->n-1]); + object * vib = mode_read_try(f, acs->m[acs->n-1]); if(vib){ acs->n--; - acs_free(acs); + obj_free(acs); fclose(f); - dp->scale = ac3_scale(vib->ac); - dp->N = vib->modes->n; + dp->rend.scale = ac3_scale(vib->m[0]); + dp->N = vib->vib->n; dp->task = VIBRO; return vib; } @@ -119,15 +121,17 @@ static void * ent_read(char * fname, drawpars * dp){ } dp->task = AT3COORDS; - dp->f = f; + dp->read.f = f; return acs; } -void * read_files(drawpars * dp){ +object * read_files(allpars * ap){ + drawpars * dp = &ap->dp; + initpars * ip = &ap->ip; - int fn = dp->input_files_n; - char ** flist = dp->input_files; - void * ent = NULL; + int fn = ip->input_files_n; + char ** flist = ip->input_files; + object * ent = NULL; int i=0; // read the first available file @@ -138,7 +142,7 @@ void * read_files(drawpars * dp){ // if the first file does not contain normal modes, try to read other files if(ent && (dp->task == AT3COORDS)){ - atcoords * acs = ent; + object * acs = ent; int n0 = acs->n; for(i++; if); - dp->f = f; - dp->fname = flist[i]; + fclose(dp->read.f); + dp->read.f = f; + dp->read.fname = flist[i]; n0 = acs->n; } } - dp->scale = acs_scale(acs); + dp->rend.scale = acs_scale(acs); newmol_prep(acs, dp); - intcoord_check(INT_MAX, dp->z); + intcoord_check(INT_MAX, dp->anal.intcoord); } else{ - dp->z[0] = 0; + dp->anal.intcoord[0] = 0; } return ent; } -atcoords * get_in_str(int N, inp_mols_t * inp_mols, drawpars * dp){ +object * acs_from_var(int n, mol * m, allpars * ap){ + drawpars * dp = &ap->dp; + initpars * ip = &ap->ip; - for(int i=0; iinput_files_n; i++){ - PRINT_WARN("ignoring file '%s'\n", dp->input_files[i]); + for(int i=0; iinput_files_n; i++){ + PRINT_WARN("ignoring file '%s'\n", ip->input_files[i]); } if(dp->task==VIBRO){ PRINT_WARN("cannot read vibrations from input variable\n"); } dp->task = AT3COORDS; - atcoords * acs = malloc(sizeof(atcoords)); - acs->Nmem = N; + object * acs = malloc(sizeof(object)); + acs->Nmem = acs->n = n; acs->m = malloc(acs->Nmem*sizeof(atcoord *)); - acs->n = N; + acs->vib = NULL; - int nmax = 0; - for(int i=0; im[i] = atcoord_fill(m+i, dp->rend.bonds, dp->geom); } - txyz * xyz = malloc(sizeof(txyz)*nmax); - for(int i=0; in; i++){ - xyz[i].t = inmol->q[i]; - r3cp(xyz[i].r, inmol->r+i*3); - } - acs->m[i] = atcoord_fill(inmol->n, xyz, inmol->name, dp->b, dp->center, dp->inertia, dp->bohr); - } - - free(xyz); fill_nf(acs, 0); - dp->scale = acs_scale(acs); + dp->rend.scale = acs_scale(acs); newmol_prep(acs, dp); - intcoord_check(nmax, dp->z); + + int natmax = 0; + for(int i=0; ianal.intcoord); return acs; } diff --git a/src/v/loop.c b/src/v/loop.c index b8409f0..1dd4971 100644 --- a/src/v/loop.c +++ b/src/v/loop.c @@ -2,19 +2,79 @@ #include "x.h" #include "evr.h" +#define VIBRO_SUBSTEPS 4 + extern int W,H; extern Display * dis; extern Window win; -void main_loop(void * ent, drawpars * dp, ptf kp[NKP]){ +typedef struct { + int click; + int x0; + int y0; +} mouse_state_t; + +static void process_mouse(XMotionEvent * event, object * ent, drawpars * dp, mouse_state_t * mouse){ + if(mouse->click){ + int x = event->x; + int y = event->y; + rot_ent_pointer(ent, dp, x-mouse->x0, y-mouse->y0, POINTER_SPEED/MIN(W,H)); + exp_redraw(ent, dp); + mouse->x0 = x; + mouse->y0 = y; + } + return; +} + +static void process_input(XKeyEvent * event, drawpars * dp){ + int stop_input = process_x_input(dp->ui.input_text, event->keycode); + if(stop_input){ + if(stop_input==1){ + switch(dp->ui.input){ + case(1): + { + int frame = atoi(dp->ui.input_text); + frame = MAX(1, MIN(frame, dp->N)); + dp->n = frame-1; + }; break; + } + } + memset(dp->ui.input_text, 0, STRLEN); + dp->ui.input=0; + } + return; +} + +static void run_animation(object * ent, drawpars * dp, int * tr){ + if(dp->task == AT3COORDS){ + dp->anim.dir > 0 ? kp_frame_inc(ent, dp) : kp_frame_dec(ent, dp); + usleep(dp->anim.dt); + } + else{ + /* We draw 5 times for each dp->anim.t, + * because dt is too small to look good + * and 5*dt is too big to behave well (keyboard control). + * Also we cannot draw only when *tr==4, + * because we need an XEvent to reiterate the main loop. + * Alternatively, we can send an event manually. + */ + if(++*tr == VIBRO_SUBSTEPS){ + *tr = 0; + dp->anim.t++; + } + usleep(dp->anim.dt); + time_gone(ent, dp); + } + return; +} + +void main_loop(object * ent, drawpars * dp, ptf kp[NKP]){ // To handle window closing. Thanks to https://stackoverflow.com/a/1186544 Atom wm_delete_window = XInternAtom(dis, "WM_DELETE_WINDOW", False); XSetWMProtocols(dis, win, &wm_delete_window, 1); - int mouse_click = 0; - int mouse_x0 = 0; - int mouse_y0 = 0; + mouse_state_t mouse = {.click=0, .x0=0, .y0=0}; int tr = 0; while(1) { XEvent event_rec; @@ -33,42 +93,30 @@ void main_loop(void * ent, drawpars * dp, ptf kp[NKP]){ } while(XEventsQueued(dis, QueuedAlready)); if (event->type == ClientMessage) { - if ((Atom)event->xclient.data.l[0] == wm_delete_window) { - kp_exit(ent, dp); - } + if ((Atom)event->xclient.data.l[0] == wm_delete_window) { + kp_exit(ent, dp); + } } else if(event->type == Expose && event->xexpose.count == 0) { exp_redraw(ent, dp); } + else if(event->type == ConfigureNotify){ W = event->xconfigure.width; H = event->xconfigure.height; - dp->xy0[0] = dp->xy0[1] = 0.0; + dp->rend.xy0[0] = dp->rend.xy0[1] = 0.0; exp_redraw(ent, dp); } + else if(event->type == KeyPress) { - if(dp->input){ - int stop_input = process_x_input(dp, event); - if(stop_input==1){ - switch(dp->input){ - case(1): - { - int frame = atoi(dp->input_text); - frame = MAX(1, MIN(frame, dp->N)); - dp->n = frame-1; - }; break; - } - } - if(stop_input){ - memset(dp->input_text, 0, STRLEN); - dp->input=0; - } + if(dp->ui.input){ + process_input(&(event->xkey), dp); exp_redraw(ent, dp); } else{ if(kp[event->xkey.keycode]){ - dp->modkey = event->xkey.state & (ShiftMask | ControlMask); + dp->ui.modkey = event->xkey.state & (ShiftMask | ControlMask); kp[event->xkey.keycode](ent, dp); } } @@ -78,64 +126,36 @@ void main_loop(void * ent, drawpars * dp, ptf kp[NKP]){ (event->xbutton.button==Button1 || event->xbutton.button==Button2 || event->xbutton.button==Button3)){ - mouse_click = 1; - mouse_x0 = event->xbutton.x; - mouse_y0 = event->xbutton.y; + mouse.click = 1; + mouse.x0 = event->xbutton.x; + mouse.y0 = event->xbutton.y; } + else if(event->type == ButtonRelease && (event->xbutton.button==Button1 || event->xbutton.button==Button2 || event->xbutton.button==Button3)){ - mouse_click = 0; + mouse.click = 0; } + else if(event->type == ButtonPress && event->xbutton.button==Button4){ kp_zoom_in(ent, dp); } + else if(event->type == ButtonPress && event->xbutton.button==Button5){ kp_zoom_out(ent, dp); } else if(event->type == MotionNotify){ - if(mouse_click){ - int x = event->xmotion.x; - int y = event->xmotion.y; - rot_ent_pointer(ent, dp, x-mouse_x0, y-mouse_y0, POINTER_SPEED/MIN(W,H)); - exp_redraw(ent, dp); - mouse_x0 = x; - mouse_y0 = y; - } + process_mouse(&(event->xmotion), ent, dp, &mouse); } - if(dp->closed){ + if(dp->ui.closed){ return; } - if(dp->fbw){ - if(dp->task == AT3COORDS){ - if(dp->fbw > 0){ - kp_frame_inc(ent, dp); - } - else{ - kp_frame_dec(ent, dp); - } - usleep(dp->dt); - } - - else if(dp->task == VIBRO){ - /* We draw 5 times for each dp->t, - * because dt is too small to look good - * and 5*dt is too big to behave well (keyboard control). - * Also we cannot draw only when tr==4, - * because we need an XEvent to reiterate the main loop. - * Alternatively, we can send an event manually. - */ - if(++tr == 4){ - tr = 0; - dp->t++; - } - usleep(dp->dt); - time_gone(ent, dp); - } + if(dp->anim.dir){ + run_animation(ent, dp, &tr); } } } diff --git a/src/v/man.c b/src/v/man.c index dd2ead7..fec45eb 100644 --- a/src/v/man.c +++ b/src/v/man.c @@ -71,7 +71,7 @@ void printman(FILE * f, char * exename){ \n\ q / esc quit \n\ \n\ -", exename, DEFAULT_TIMEOUT*1e-6, DEFAULT_SYMTOL); +", exename, DEFAULT_TIMEOUT*MS_TO_S, DEFAULT_SYMTOL); return; } diff --git a/src/v/mode_read.c b/src/v/mode_read.c index f2845c9..4cf2f11 100644 --- a/src/v/mode_read.c +++ b/src/v/mode_read.c @@ -1,6 +1,19 @@ #include "v.h" -static int readb(FILE * f, int i, int Nmax, int N, int na, modestr * m){ +static inline vibr_t * make_vibr_t(int n_modes, int n_atoms){ + size_t freq_size = sizeof(double) * n_modes; + size_t r0_size = sizeof(double) * n_atoms*3; + size_t disp_size = sizeof(double) * n_modes*n_atoms*3; + size_t size = sizeof(vibr_t) + freq_size + r0_size + disp_size; + vibr_t * v = malloc(size); + v->n = n_modes; + v->freq = (double *) (v + 1); + v->disp = (double *) MEM_END(v,freq); + v->r0 = (double *) MEM_END(v,disp); + return v; +} + +static int readb(FILE * f, int i, int Nmax, int N, int na, vibr_t * m){ double d; char s[STRLEN]; int t,k,j; @@ -21,7 +34,7 @@ static int readb(FILE * f, int i, int Nmax, int N, int na, modestr * m){ if(s[1]=='i'){ d = -d; } - m->f[i*Nmax+j] = d; + m->freq[i*Nmax+j] = d; } if (!fgets(s, sizeof(s), f)) { @@ -41,7 +54,7 @@ static int readb(FILE * f, int i, int Nmax, int N, int na, modestr * m){ if (fscanf (f, "%lf", &d) != 1) { return -1; } - m->d[3*na*(i*Nmax+j)+k] = d; + m->disp[3*na*(i*Nmax+j)+k] = d; } } #if 0 @@ -55,7 +68,7 @@ static int readb(FILE * f, int i, int Nmax, int N, int na, modestr * m){ return 0; } -modestr * mode_read (FILE * f, int na){ +vibr_t * mode_read (FILE * f, int na){ const int N = 6; int n = 0; @@ -69,7 +82,9 @@ modestr * mode_read (FILE * f, int na){ break; } } - fgets(s, sizeof(s), f); + if (!fgets(s, sizeof(s), f)){ + return NULL; + } while(1){ if (!fgets(s, sizeof(s), f)) { return NULL; @@ -82,11 +97,7 @@ modestr * mode_read (FILE * f, int na){ } } - size_t size = sizeof(modestr) + n*sizeof(double) + n*na*3*sizeof(double); - modestr * m = malloc(size); - m->n = n; - m->f = (double *)(m+1); - m->d = m->f+n; + vibr_t * m = make_vibr_t(n, na); for (int i=0; i<3; i++){ if (!fgets(s, sizeof(s), f)) { diff --git a/src/v/pars.h b/src/v/pars.h new file mode 100644 index 0000000..a347ec1 --- /dev/null +++ b/src/v/pars.h @@ -0,0 +1,95 @@ +typedef enum { + UNKNOWN, + AT3COORDS, + VIBRO, +} task_t; + +typedef enum { + V_COLORS, + CPK_COLORS, +} colorscheme_t; + +typedef struct { + int gui; // if gui is enabled + char * fontname; // font + int input_files_n; // number of input files + char ** input_files; // input files + colorscheme_t colors; // colorscheme (v or cpk) +} initpars; + +typedef struct { + FILE * f; // open file for kp_readmore() + const char * fname; // file name +} readpars; + +typedef struct { + int center; // 0: nothing; 1: center each molecule upon reading; 2: center wrt center of mass + int inertia; // 0: nothing; 1: rotate each molecule upon reading wrt axis of inertia + int bohr; // 0: Å 1: Bohr +} geompars; + + +typedef struct { + int closed; // 1: time to go + char * com; // command string for gui:0 + char * on_exit; // command string to run on exit + int input; // 0=no input regime, 1=jump, ... + char input_text[STRLEN]; + int modkey; // whether ctrl or shift are pressed +} uipars; + +typedef struct { + double xy0[2]; // translation vector + double ac3rmx[9]; // rotational matrix + double scale; // zoom + double r; // atom size scale factor + int num; // 0: do not show; 1: show numbers; -1: show atom types + int bonds; // 0: do not show; 1: show bonds; 2: show bond+lengths; -1: never show +} rendpars; + +typedef struct { + double rl; // bond length scale factor + double bmax; // max. bond length to show +} bondpars; + +typedef struct { + double vertices[3*8]; // parameters of cell/shell + double rot_to_lab_basis[3*3]; // "rotation" matrix for PBC + double rot_to_cell_basis[3*3]; // "rotation" matrix for PBC + int vert; // 0: nothing; 1: show cell; 2: show shell +} cellpars; + +typedef struct { + int t; // counter for mode animation + int dir; // 0: nothing; 1: play forwards; -1: play backwards + unsigned int dt; // animation timeout +} animpars; + +typedef struct { + double symtol; // tolerance for symmetry determination + int intcoord[5]; // internal coordinate to show +} analpars; + +typedef struct { + + task_t task; // data type + + int N; // number of structures / modes + int n; // current structure / mode + + readpars read; + geompars geom; + uipars ui; + rendpars rend; + bondpars bond; + cellpars cell; + animpars anim; + analpars anal; + +} drawpars; + +typedef struct { + initpars ip; + drawpars dp; +} allpars; + diff --git a/src/v/scale.c b/src/v/scale.c index 189b988..4721933 100644 --- a/src/v/scale.c +++ b/src/v/scale.c @@ -1,6 +1,8 @@ #include "v.h" #include "vec3.h" +#define VIEWPORT_FILL 0.5 // molecule fills this fraction of the viewport + double ac3_scale(atcoord * ac){ double center[3] = {}; for(int k=0; kn; k++){ @@ -13,10 +15,10 @@ double ac3_scale(atcoord * ac){ double d2 = r3d2(center, ac->r+3*k); d2max = MAX(d2max, d2+rad*rad); } - return 0.5 / sqrt(d2max); + return VIEWPORT_FILL / sqrt(d2max); } -double acs_scale(atcoords * acs){ +double acs_scale(object * acs){ double d2max = ac3_scale(acs->m[0]); for(int i=1; in; i++){ d2max = MIN(ac3_scale(acs->m[i]), d2max); diff --git a/src/v/tools.c b/src/v/tools.c index e1fbca7..ae5897e 100644 --- a/src/v/tools.c +++ b/src/v/tools.c @@ -1,36 +1,24 @@ #include "v.h" #include "sym.h" -void ent_free(void * ent, drawpars * dp){ - if (dp->task == VIBRO){ - free(((vibrstr *)ent)->ac); - free(((vibrstr *)ent)->modes); - free(ent); +void obj_free(object * ent){ + if(ent->vib){ + free(ent->vib); } - else if (dp->task == AT3COORDS){ - if(dp->f){ - fclose(dp->f); - } - acs_free(ent); - } - return; -} - -void acs_free(atcoords * acs){ - for(int i=0; in; i++){ - free(acs->m[i]); + for(int i=0; in; i++){ + free(ent->m[i]); } - free(acs->m); - free(acs); + free(ent->m); + free(ent); return; } -void newmol_prep(atcoords * acs, drawpars * dp){ +void newmol_prep(object * acs, drawpars * dp){ for(int j=dp->N; jn; j++){ atcoord * ac = acs->m[j]; for(int i=0; in; i++){ double v[3]; - r3mx(v, ac->r+3*i, dp->ac3rmx); + r3mx(v, ac->r+3*i, dp->rend.ac3rmx); r3cp(ac->r+3*i, v); } } @@ -42,9 +30,9 @@ void ac3_text(atcoord * ac, drawpars * dp){ char text[STRLEN]; int tp = snprintf(text, sizeof(text), "%*d / %d r = %.1lf rl = %.1lf", - 1+(int)(log10(dp->N)), dp->n+1, dp->N, dp->r, dp->rl); - if( tpz[0] ){ - tp += snprintf(text+tp, sizeof(text)-tp, " | %d,%d,%d,%d,%d: %lf", dp->z[0], dp->z[1], dp->z[2], dp->z[3], dp->z[4], intcoord_calc(1, ac->n, dp->z, ac->r)); + 1+(int)(log10(dp->N)), dp->n+1, dp->N, dp->rend.r, dp->bond.rl); + if( tpanal.intcoord[0] ){ + tp += snprintf(text+tp, sizeof(text)-tp, " | %d,%d,%d,%d,%d: %lf", dp->anal.intcoord[0], dp->anal.intcoord[1], dp->anal.intcoord[2], dp->anal.intcoord[3], dp->anal.intcoord[4], intcoord_calc(1, ac->n, dp->anal.intcoord, ac->r)); } if( tpsym[0] ){ tp += snprintf(text+tp, sizeof(text)-tp, " | PG: %s", ac->sym); @@ -58,9 +46,9 @@ void ac3_text(atcoord * ac, drawpars * dp){ textincorner(text, text2); } - if(dp->input==1){ + if(dp->ui.input==1){ char text3[STRLEN]; - snprintf(text3, sizeof(text3), "JUMP TO >>> %s", dp->input_text); + snprintf(text3, sizeof(text3), "JUMP TO >>> %s", dp->ui.input_text); textincorner2(text3); } @@ -68,34 +56,31 @@ void ac3_text(atcoord * ac, drawpars * dp){ return; } -void vibro_text(modestr * ms, drawpars * dp){ +void vibro_text(vibr_t * ms, drawpars * dp){ char text[STRLEN]; - double fq = ms->f[dp->n]; + double fq = ms->freq[dp->n]; char i = fq > 0.0 ? ' ' : 'i'; snprintf(text, sizeof(text), "%*d / %d %.1lf%c r = %.1lf rl = %.1lf", - 1+(int)(log10(ms->n)), dp->n+1, ms->n, fabs(fq), i, dp->r, dp->rl); - textincorner(text, dp->fname); - if(dp->input==1){ + 1+(int)(log10(ms->n)), dp->n+1, ms->n, fabs(fq), i, dp->rend.r, dp->bond.rl); + textincorner(text, dp->read.fname); + if(dp->ui.input==1){ char text3[STRLEN]; - snprintf(text3, sizeof(text3), "JUMP TO >>> %s", dp->input_text); + snprintf(text3, sizeof(text3), "JUMP TO >>> %s", dp->ui.input_text); textincorner2(text3); } return; } -void pg(atcoord * a, styp s, double symtol){ +void pg(atcoord * a, double symtol){ int n = a->n; - mol m; - m.n = n; - m.q = a->q; - m.r = malloc(sizeof(double )*n*3); + mol m = {.n = n, .q = a->q, .r=malloc(sizeof(double)*n*3), .name=NULL}; veccp (n*3, m.r, a->r); vecscal(n*3, m.r, AB); molsym * ms = pointgroup(&m, symtol*AB); - strcpy(s, ms->s); + snprintf(a->sym, sizeof(styp), "%s", ms->s); free(m.r); free(ms); diff --git a/src/v/v.h b/src/v/v.h index c64159f..6c33107 100644 --- a/src/v/v.h +++ b/src/v/v.h @@ -8,13 +8,9 @@ #define STRLEN 256 #define BIGSTRLEN 4096 -typedef void (* ptf )(); +#include "pars.h" -typedef enum { - UNKNOWN, - AT3COORDS, - VIBRO, -} task_t; +typedef void (* ptf )(); typedef enum { UNKNOWN_FORMAT, @@ -23,137 +19,71 @@ typedef enum { OUT, } format_t; -typedef enum { - V_COLORS, - CPK_COLORS, -} colorscheme_t; +typedef struct { + int flag; // whether bonds are up-to-date. 0: no, 1: yes + double rl; // the last used bond length scale factor + int * a; // lists of bonded atoms + double * r; // distances to the bonded atoms +} bondstr; typedef struct { int n; // number of atoms - int bond_flag; // whether bonds are up-to-date. 0: no, 1: yes, -1: disabled - double bond_rl; // the last used bond length scale factor int * q; // charges of atoms double * r; // coordinates of atoms - styp sym; // point group - int * bond_a; // lists of bounded atoms - double * bond_r; // distances to the bonded atoms const char * fname; // file name + int nf[2]; // number of molecule in file, file size + styp sym; // point group + bondstr bonds; } atcoord; typedef struct { - int n, Nmem; - atcoord ** m; -} atcoords; + int n; // number of modes + double * freq; // frequencies + double * disp; // displacements + double * r0; // atom configuration at the central point +} vibr_t; typedef struct { - int n; - double * f; - double * d; -} modestr; - -typedef struct { - modestr * modes; - double * mode0; - atcoord * ac; -} vibrstr; - -typedef struct { - - task_t task; // data type - unsigned int dt; // animation timeout - char fontname[STRLEN];// font - int gui; // - - int input; // 0=no input regime, 1=jump, ... - char input_text[STRLEN]; - - double xy0[2]; // translation vector - double ac3rmx[9]; // rotational matrix - - double scale; // zoom - double r; // atom size scale factor - double rl; // bond length scale factor - - FILE * f; // opened file for kp_readmore() - const char * fname; // file name - double vertices[3*8]; // parameters of cell/shell - double rot_to_lab_basis[3*3]; // "rotation" matrix for PBC - double rot_to_cell_basis[3*3]; // "rotation" matrix for PBC - double symtol; // tolerance for symmetry determination - double bmax; // max. bond length to show - int z[5]; // internal coordinate to show - int modkey; // whether ctrl of shift are pressed - - int N; // number of structures / modes - int n; // current structure / mode - int t; // counter for mode animation - - int b; // 0: do not show; 1: show bonds; 2: show bond+lengths; -1: never show - int fbw; // 0: nothing; 1: play forwards; -1: play backwards - int num; // 0: do not show; 1: show numbers; -1: show atom types - int vert; // 0: nothing; 1: show cell; 2: show shell - - int center; // 0: nothing; 1: center each molecule upon reading ; 2: center wrt center of mass - int inertia; // 0: nothing; 1: rotate each molecule upon reading wrt axis of inertia - int bohr; // 0: Å 1: Bohr - // - int closed; // 1: time to go - char com[STRLEN]; // command string for gui:0 - char on_exit[STRLEN]; // command string to run on exit - - int input_files_n; // number of input files - char ** input_files; // input files - // - colorscheme_t colors; // colorscheme (v or cpk) - -} drawpars; - -typedef struct { - int t; - double r[3]; -} txyz; - -typedef struct { - int n; - int * q; - double * r; - char * name; -} inp_mols_t; + int n, Nmem; + atcoord ** m; + vibr_t * vib; +} object; // load.c -atcoords * get_in_str(int N, inp_mols_t * inp_mols, drawpars * dp); -void acs_readmore (FILE * f, int b, int center, int inertia, int bohr, atcoords * acs, const char * fname); -void * read_files(drawpars * dp); +object * acs_from_var(int n, mol * m, allpars * ap); +void acs_readmore (readpars read, int b, geompars geom, object * acs); +object * read_files(allpars * ap); // scale.c double ac3_scale(atcoord * ac); -double acs_scale(atcoords * acs); +double acs_scale(object * acs); // mode_read.c -modestr * mode_read(FILE * f, int na); +vibr_t * mode_read(FILE * f, int na); // ac3_read*.c -atcoord * atcoord_fill(int n, txyz * a, const char * fname, int b, int center, int inertia, int bohr); -atcoord * ac3_read(FILE * f, int b, int center, int inertia, int bohr, const char * fname, format_t * format); -txyz * ac3_read_in (int * n_p, int * zmat, FILE * f); -txyz * ac3_read_out(int * n_p, FILE * f); -txyz * ac3_read_xyz(int * n_p, FILE * f); +int read_cart_atom(FILE * f, int n, mol * m); +atcoord * atcoord_fill(mol * m, int b, geompars geom); +atcoord * ac3_read(readpars read, int b, geompars geom, format_t * format); +mol * ac3_read_in (FILE * f); +mol * ac3_read_out(FILE * f); +mol * ac3_read_xyz(FILE * f); // man.c void printman(FILE * f, char * exename); // cli.c -drawpars cli_parse(int argc, char ** argv); +allpars cli_parse(int argc, char ** argv); // loop.c -void main_loop(void * ent, drawpars * dp, ptf kp[NKP]); +void main_loop(object * ent, drawpars * dp, ptf kp[NKP]); // ac3_draw.c -void ac3_draw (atcoord * ac, double r0, double scale, double xy0[2], int b, int num); +void ac3_draw (atcoord * ac, rendpars rend); // ac3_print.c -void ac3_print (atcoord * ac, double xy0[2], int b); -void ac3_print_xyz(atcoord * ac, double xy0[2]); -void ac3_print2fig(atcoord * ac, double xy0[2], int b, double * v); +void ac3_print (atcoord * ac, rendpars rend); +void ac3_print_xyz(atcoord * ac, rendpars rend); +void ac3_print2fig(atcoord * ac, rendpars rend, double * v); // bonds.c -void bonds_fill(double rl, double bmax, atcoord * ac); +void bonds_fill(bondpars bond, atcoord * ac); // get_atpar.c double getradius(int q); @@ -163,7 +93,7 @@ int get_element(char * s); // x.c void close_x (void); -void init_x(const char * const capt, const colorscheme_t colorscheme); +void init_x (const char * const capt, const colorscheme_t colorscheme); void init_font (char * fontname); void textincorner (const char * const text1, const char * const text2); void textincorner2(const char * const text1); @@ -172,24 +102,23 @@ void drawvertices (double * v, double scale, double xy0[2]); void drawshell (double rmin, double rmax, double scale, double * xy0); int savepic (char * s); // xinput.c -int process_x_input(drawpars * dp, void * event); +int process_x_input(char input_text[STRLEN], unsigned int keycode); // tools.c -void ent_free(void * ent, drawpars * dp); -void acs_free(atcoords * acs); -void newmol_prep(atcoords * acs, drawpars * dp); +void obj_free(object * ent); +void newmol_prep(object * acs, drawpars * dp); void ac3_text(atcoord * ac, drawpars * dp); -void vibro_text(modestr * ms, drawpars * dp); -void pg(atcoord * a, styp s, double symtol); +void vibro_text(vibr_t * ms, drawpars * dp); +void pg(atcoord * a, double symtol); // headless.c -void run_commands(FILE * f, char * command, drawpars * dp, void * ent); -int headless(drawpars * dp, void * ent); +void run_commands(FILE * f, char * command, drawpars * dp, object * ent); +int headless(drawpars * dp, object * ent); // main.c int main (int argc, char * argv[]); // api.c void PRINTOUT(FILE * f, char * format, ...); -void * READ_FILES(drawpars * dp); +object * READ_FILES(allpars * ap); int SHOULD_PRINT_MAN(int argc); diff --git a/src/v/x.c b/src/v/x.c index 6448a2f..74b436d 100644 --- a/src/v/x.c +++ b/src/v/x.c @@ -1,5 +1,6 @@ #include "v.h" #include "x.h" +#include "vec2.h" extern Display * dis; extern int screen; @@ -30,154 +31,32 @@ void close_x(void) { static void setcolors(colorscheme_t colorscheme){ - XColor c[NCOLORS] = {}; + static const unsigned int palette_v[NCOLORS][3]={ + #include "palette_v.h" + }; - if(colorscheme==V_COLORS){ - for(int i=0; i0.0 || vj[2]>0.0) ? 0 : 1; + double pi[2], pj[2]; + r2sum(pi, xy0, vi); + r2sum(pj, xy0, vj); + XDrawLine(dis, win, gc_dot[iw], + W/2+scale*pi[0], H/2-scale*pi[1], + W/2+scale*pj[0], H/2-scale*pj[1]); + return; } void drawvertices(double * v, double scale, double xy0[2]){ double d = MIN(H, W)*scale; - int iw; -#define LINE(I,J) \ - iw=( v[(I)*3+2]>0.0 || v[(J)*3+2]>0.0) ? 0 : 1; \ - XDrawLine(dis, win, gc_dot[iw],\ - W/2+d*(xy0[0]+v[(I)*3]), H/2-d*(xy0[1]+v[(I)*3+1]),\ - W/2+d*(xy0[0]+v[(J)*3]), H/2-d*(xy0[1]+v[(J)*3+1])); - LINE(0,1); - LINE(0,2); - LINE(0,3); - LINE(1,4); - LINE(1,5); - LINE(2,4); - LINE(2,6); - LINE(3,5); - LINE(3,6); - LINE(4,7); - LINE(5,7); - LINE(6,7); +#define LINE(i,j) draw_edge(v+(i)*3, v+(j)*3, d, xy0) + for(int i=0; i<8; i+=2){ + LINE(i,i+1); // || z-axis + } + for(int j=0; j<2; j++){ + for(int i=0; i<2; i++){ + LINE(i*4+j, i*4+2+j); // || y-axis + LINE(i*2+j, i*2+4+j); // || x-axis + } + } #undef LINE return; } void drawshell(double rmin, double rmax, double scale, double xy0[2]){ double d = MIN(H,W)*scale; - rmax *= d; - rmin *= d; + double r[] = {rmax*d, rmin*d}; int x = W/2+d*xy0[0]; int y = H/2-d*xy0[1]; - XDrawArc(dis, win, gc_dot[0], x-rmax, y-rmax, 2*rmax, 2*rmax, 0, 360*64); - XDrawArc(dis, win, gc_dot[1], x-rmin, y-rmin, 2*rmin, 2*rmin, 0, 360*64); + for(int i=0; i<2; i++){ + XDrawArc(dis, win, gc_dot[i], x-r[i], y-r[i], 2*r[i], 2*r[i], 0, 360*64); + } return; } diff --git a/src/v/xinput.c b/src/v/xinput.c index d21c496..0e0aab6 100644 --- a/src/v/xinput.c +++ b/src/v/xinput.c @@ -3,27 +3,28 @@ extern Display * dis; -int process_x_input(drawpars * dp, void * event_){ - XEvent * event = event_; +int process_x_input(char input_text[STRLEN], unsigned int keycode){ int keysyms_per_keycode_return; - KeySym * keysym = XGetKeyboardMapping(dis, event->xkey.keycode, 1, &keysyms_per_keycode_return); - int input_length = strlen(dp->input_text); + KeySym * keysym = XGetKeyboardMapping(dis, keycode, 1, &keysyms_per_keycode_return); + int input_length = strlen(input_text); if(!((keysym[0]>='0' && keysym[0]<='9')||(keysym[0]>='a' && keysym[0]<='z'))){ if(keysym[0]==XK_Escape){ - return 2; // only stop input & clean + XFree(keysym); + return -1; // only stop input & clean } else if(keysym[0]==XK_Return){ + XFree(keysym); return 1; // use the input } else if(keysym[0]==XK_BackSpace){ if(input_length>0){ - dp->input_text[input_length-1] = 0; + input_text[input_length-1] = 0; } } } else{ if(input_lengthinput_text[input_length] = keysym[0]; + input_text[input_length] = keysym[0]; } } XFree(keysym);