From 87d8c7d962967dae1e2158e51ec68753a6b882fc Mon Sep 17 00:00:00 2001 From: Craig Fisher <66772456+cajfisher@users.noreply.github.com> Date: Fri, 8 Oct 2021 13:17:11 +0900 Subject: [PATCH 1/8] Update bonds when atoms moved individually Refreshes bonds in model window when atom coordinates changed in Model:Editing box (same as already done for groups of selected atoms). --- src/gui_edit.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/gui_edit.c b/src/gui_edit.c index 81511ed..4389638 100644 --- a/src/gui_edit.c +++ b/src/gui_edit.c @@ -438,6 +438,7 @@ printf("new dipole: %f\n", data->gulp.sdipole); sprintf(txt, "New surface dipole: %f\n", data->gulp.sdipole); gui_text_show(STANDARD, txt); +gui_refresh(GUI_MODEL_PROPERTIES); redraw_canvas(SINGLE); } @@ -3050,18 +3051,21 @@ if (CEDIT.apd_core->shell) text = gtk_entry_get_text(GTK_ENTRY(CEDIT.apd_x)); CEDIT.apd_core->x[0] = str_to_float(text); coords_compute(model); + connect_refresh(model); break; case COORD_Y: text = gtk_entry_get_text(GTK_ENTRY(CEDIT.apd_y)); CEDIT.apd_core->x[1] = str_to_float(text); coords_compute(model); + connect_refresh(model); break; case COORD_Z: text = gtk_entry_get_text(GTK_ENTRY(CEDIT.apd_z)); CEDIT.apd_core->x[2] = str_to_float(text); coords_compute(model); + connect_refresh(model); break; case SOF: From f33967d6cdf6a1a2c7ff317f16caa792de901a53 Mon Sep 17 00:00:00 2001 From: Craig Fisher <66772456+cajfisher@users.noreply.github.com> Date: Fri, 29 Oct 2021 13:30:52 +0900 Subject: [PATCH 2/8] Add reader and writer for XCrysDen format (.xsf) Enables reading and writing of structures in xsf format (including animation files) --- src/file.c | 13 ++ src/file.h | 3 + src/file_xsf.c | 459 +++++++++++++++++++++++++++++++++++++++++++++++ src/interface.h | 2 +- src/makefile.src | 2 +- 5 files changed, 477 insertions(+), 2 deletions(-) create mode 100644 src/file_xsf.c diff --git a/src/file.c b/src/file.c index 243d00a..d2dca61 100644 --- a/src/file.c +++ b/src/file.c @@ -677,6 +677,19 @@ file_data->read_file = read_xml; file_data->read_frame = NULL; /* frame reading */ sysenv.file_list = g_slist_prepend(sysenv.file_list, file_data); +/* supported file type */ +file_data = g_malloc(sizeof(struct file_pak)); +file_data->id = XSF; +file_data->group = XSF; +file_data->menu = TRUE; +file_data->label = g_strdup("XSF"); +file_data->ext = NULL; +file_data->ext = g_slist_prepend(file_data->ext, "xsf"); +file_data->write_file = write_xsf; +file_data->read_file = read_xsf; +file_data->read_frame = read_xsf_frame; /* frame reading */ +sysenv.file_list = g_slist_prepend(sysenv.file_list, file_data); + /* supported file type */ file_data = g_malloc(sizeof(struct file_pak)); file_data->id = XTL; diff --git a/src/file.h b/src/file.h index 497e436..02aa147 100644 --- a/src/file.h +++ b/src/file.h @@ -101,6 +101,7 @@ gint write_gmf(gchar *, struct model_pak *); gint write_planes(gchar *, struct model_pak *); gint write_marvin(gchar *, struct model_pak *); gint write_xml(gchar *, struct model_pak *); +gint write_xsf(gchar *, struct model_pak *); gint write_xtl(gchar *, struct model_pak *); gint write_xyz(gchar *, struct model_pak *); gint write_gms(gchar *, struct model_pak *); @@ -142,6 +143,7 @@ gint read_marvin(gchar *, struct model_pak *); gint read_mvnout(gchar *, struct model_pak *); gint read_sout(gchar *, struct model_pak *); gint read_xml(gchar *, struct model_pak *); +gint read_xsf(gchar *, struct model_pak *); gint read_xtl(gchar *, struct model_pak *); gint read_xyz(gchar *, struct model_pak *); gint read_using_babel(gchar *, struct model_pak *); @@ -189,6 +191,7 @@ gint read_qe_out_frame(FILE *, struct model_pak *); gint read_xyz_frame(FILE *, struct model_pak *); gint read_dlpoly_frame(FILE *, struct model_pak *); gint read_dmol_frame(FILE *, struct model_pak *); +gint read_xsf_frame(FILE *, struct model_pak *); /*NEW: track/update frames (TODO)*/ gint update_frame_uspex(gint idx,struct model_pak *model); diff --git a/src/file_xsf.c b/src/file_xsf.c new file mode 100644 index 0000000..de9fcc8 --- /dev/null +++ b/src/file_xsf.c @@ -0,0 +1,459 @@ +/* +Copyright (C) 2000 by Sean David Fleming + +sean@ivec.org + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +The GNU GPL can also be found at http://www.gnu.org +*/ + +#include +#include + +#include "gdis.h" +#include "coords.h" +#include "model.h" +#include "file.h" +#include "matrix.h" +#include "interface.h" +#include "parse.h" + +/* main structures */ +extern struct sysenv_pak sysenv; + +/****************************/ +/* write a coordinate block */ +/****************************/ +gint write_xsf_frame(FILE *fp, struct model_pak *model) +{ +gint i=0; +gdouble vec[3]; +GSList *list; +struct core_pak *core; + +/* header */ +if (model->periodic == 3) + { + for (list=model->cores ; list ; list=g_slist_next(list)) + { + core = (struct core_pak *) list->data; + + if (core->status & (DELETED | HIDDEN)) + continue; + i++; + } + fprintf(fp,"%4d 1\n", i); + } + +/* coords */ +for (list=model->cores ; list ; list=g_slist_next(list)) + { + core = (struct core_pak *) list->data; + + if (core->status & (DELETED | HIDDEN)) + continue; + if (core->primary) + { + ARR3SET(vec, core->x); + vecmat(model->latmat, vec); + + fprintf(fp,"%4d %9.5f %9.5f %9.5f\n", + core->atom_code, vec[0], vec[1], vec[2]); + } + } +return(0); +} + +/**********************/ +/* save in XSF format */ +/**********************/ +#define DEBUG_WRITE_XSF 1 +gint write_xsf(gchar *filename, struct model_pak *data) +{ +gint n, current, status; +FILE *fp; +GString *err_text; + +/* checks */ +g_return_val_if_fail(data != NULL, 1); +g_return_val_if_fail(filename != NULL, 2); + +if( g_slist_length(data->cores) > 9999) + { + gui_text_show(ERROR, "Too many atoms for XSF format!\n"); + return(1); + } + +if( data->periodic == 1) + { + gui_text_show(ERROR, "Model must be 0, 2 or 3 dimensional.n"); + return(1); + } + +/* open the file */ +fp = fopen(filename,"w"); +if (!fp) + { + gui_text_show(ERROR, "Bad filename!\n"); + return(1); + } + +if (data->frame_list) + { + data->afp = fopen(data->filename, "r"); + + if (!data->afp) + { + gui_text_show(ERROR, "Failed to open animation stream.\n"); + return(0); + } + + current = data->cur_frame; /* Remember current position */ + + fprintf(fp,"ANIMSTEPS %d\n", data->num_frames); + + for (n=data->cur_frame ; nnum_frames ; n++) + { + status = read_raw_frame(data->afp, n, data); +#if DEBUG_WRITE_XSF +printf("Frame no: %d\n",n); +#endif + if (status) + { + err_text = g_string_new(""); + g_string_printf(err_text, "Error reading frame: %d\n", n); + gui_text_show(ERROR, err_text->str); + g_string_free(err_text, TRUE); + return(2); + } + + if (data->periodic == 0) + { + fprintf(fp, "ATOMS %d\n", n+1); + } + else + { + if (data->periodic == 2) + fputs("SLAB\n", fp); + else + fputs("CRYSTAL\n", fp); + + fprintf(fp, "PRIMVEC %d\n", n+1); + fprintf(fp,"%11.6f %11.6f %11.6f\n", data->latmat[0], data->latmat[1], data->latmat[2]); + fprintf(fp,"%11.6f %11.6f %11.6f\n", data->latmat[3], data->latmat[4], data->latmat[5]); + fprintf(fp,"%11.6f %11.6f %11.6f\n", data->latmat[6], data->latmat[7], data->latmat[8]); + + if (data->periodic == 3) + { + fprintf(fp, "CONVVEC %d\n", n+1); + fprintf(fp,"%11.6f %11.6f %11.6f\n", data->latmat[0], data->latmat[1], data->latmat[2]); + fprintf(fp,"%11.6f %11.6f %11.6f\n", data->latmat[3], data->latmat[4], data->latmat[5]); + fprintf(fp,"%11.6f %11.6f %11.6f\n", data->latmat[6], data->latmat[7], data->latmat[8]); + } + + fprintf(fp, "PRIMCOORD %d\n", n+1); + } + + write_xsf_frame(fp, data); + } + + /* Restore data for current frame */ + read_raw_frame(data->afp, current, data); + connect_molecules(data); + fclose(data->afp); + } +else + { + if (data->periodic == 0) + fputs("ATOMS\n", fp); + else + { + if (data->periodic == 2) + fputs("SLAB\n", fp); + else + fputs("CRYSTAL\n", fp); + + fputs("PRIMVEC\n", fp); + fprintf(fp,"%11.6f %11.6f %11.6f\n", data->latmat[0], data->latmat[1], data->latmat[2]); + fprintf(fp,"%11.6f %11.6f %11.6f\n", data->latmat[3], data->latmat[4], data->latmat[5]); + fprintf(fp,"%11.6f %11.6f %11.6f\n", data->latmat[6], data->latmat[7], data->latmat[8]); + + if (data->periodic == 3) + { + fputs("CONVVEC\n", fp); + fprintf(fp,"%11.6f %11.6f %11.6f\n", data->latmat[0], data->latmat[1], data->latmat[2]); + fprintf(fp,"%11.6f %11.6f %11.6f\n", data->latmat[3], data->latmat[4], data->latmat[5]); + fprintf(fp,"%11.6f %11.6f %11.6f\n", data->latmat[6], data->latmat[7], data->latmat[8]); + } + fputs("PRIMCOORD\n", fp); + } + write_xsf_frame(fp, data); + } + +/* done */ +gui_text_show(STANDARD, "File saved in XSF format\n"); +fclose(fp); +return(0); +} + +/*********************************************/ +/* read a xsf block into the model structure */ +/*********************************************/ +#define DEBUG_READ_XSF_BLOCK 0 +/* NB: assumes fp is one line before frame data */ +void read_xsf_block(FILE *fp, struct model_pak *data) +{ +gint i, code, num_tokens; +gint n = 0, num_atoms = 0; +gchar **buff; +struct core_pak *core; +struct elem_pak elem_data; +GSList *clist; + +g_assert(fp != NULL); +g_assert(data != NULL); + +clist = data->cores; + +/* loop while there's data */ +for (;;) + { + buff = get_tokenized_line(fp, &num_tokens); + if (!buff) + break; + + if (num_tokens) + { + if (num_tokens == 1) + { + if (!g_ascii_strcasecmp(*buff, "crystal")) + break; + else if (!g_ascii_strcasecmp(*buff, "slab")) + break; + } + if (!g_ascii_strcasecmp(*buff, "atoms")) + break; + + if (!g_ascii_strcasecmp(*buff, "primvec")) + { + data->construct_pbc = TRUE; + for (i=0; i<3; i++) + { + g_strfreev(buff); + buff = get_tokenized_line(fp, &num_tokens); + if (num_tokens == 3) + { + data->latmat[3*i] = str_to_float(*(buff)); + data->latmat[3*i+1] = str_to_float(*(buff+1)); + data->latmat[3*i+2] = str_to_float(*(buff+2)); + } +#if DEBUG_READ_XSF_BLOCK +P3MAT("Lattice:", data->latmat); +#endif + } + } + if (!g_ascii_strcasecmp(*buff, "primcoord")) + { + g_strfreev(buff); + buff = get_tokenized_line(fp, &num_tokens); + + if (num_tokens == 2) + num_atoms = (gint)str_to_float(*buff); + else + return; + } + + if (num_tokens > 3) + { + code = (gint)str_to_float(*buff); + if (code > 0) + { + n++; +/* overwrite existing core (if any) */ + if (clist) + { + core = (struct core_pak *) clist->data; + clist = g_slist_next(clist); + } + else + { +/* otherwise, add a new core */ + get_elem_data(code, &elem_data, data); + core = core_new(elem_data.symbol, NULL, data); + data->cores = g_slist_append(data->cores, core); + } + + core->x[0] = str_to_float(*(buff+1)); + core->x[1] = str_to_float(*(buff+2)); + core->x[2] = str_to_float(*(buff+3)); + core->lookup_charge = TRUE; +#if DEBUG_READ_XSF_BLOCK +printf("Atom %d %s %f %f %f\n",n, core->atom_label, core->x[0], + core->x[1], core->x[2]); +#endif + } + } + } + g_strfreev(buff); + } + +#if DEBUG_READ_XSF_BLOCK +printf("Periodicity: %d\n", data->periodic); +#endif + +if (n != g_slist_length(data->cores) || + (data->periodic > 0 && num_atoms != n) || + n == 0) + gui_text_show(ERROR, "Wrong number of atoms in xsf file.\n"); + +/* convert input cartesian coords to fractional */ +if( data->periodic) + { + matrix_lattice_init(data); + coords_make_fractional(data); + data->fractional = TRUE; + } + +g_strfreev(buff); +} +/******************/ +/* xsf frame read */ +/******************/ +gint read_xsf_frame(FILE *fp, struct model_pak *data) +{ +/* frame overwrite */ +read_xsf_block(fp, data); +return(0); +} +/****************/ +/* read routine */ +/****************/ +#define DEBUG_READ_XSF 0 +gint read_xsf(gchar *filename, struct model_pak *data) +{ +gint frame = 0, end_flag = 0; +gint num_tokens; +gchar **buff; +fpos_t *offset; +FILE *fp; + +/* checks */ +g_return_val_if_fail(data != NULL, 1); +g_return_val_if_fail(filename != NULL, 1); + +if (strlen(filename) < FILELEN) + strcpy(data->filename, filename); +else + { + gui_text_show(ERROR, "File name is too long.\n"); + return(-1); + } + +fp = fopen(filename, "rt"); +if (fp == NULL) + return(2); + +/* inits */ +data->fractional = FALSE; + +for (;;) + { + buff = get_tokenized_line(fp, &num_tokens); + if (buff == NULL) + break; + + /* first line should be type */ + if (!g_ascii_strcasecmp(*buff, "animsteps")) + { + g_strfreev(buff); + buff = get_tokenized_line(fp, &num_tokens); + if (!buff) + break; + } + + if (!g_ascii_strcasecmp(*buff, "atoms")) + { + data->periodic = 0; + end_flag++; + } + else if (!g_ascii_strcasecmp(*buff, "slab")) + { + data->periodic = 2; + end_flag++; + } + else if (!g_ascii_strcasecmp(*buff, "crystal")) + { + data->periodic = 3; + end_flag++; + } + else + end_flag = 0; + +/* coords search */ + if ( end_flag == 1) + { + add_frame_offset(fp, data); + +/* increment counter */ + frame++; + } + + g_strfreev(buff); + } + +offset = g_list_nth_data(data->frame_list, 0); + +#if DEBUG_READ_XSF +printf("Total frames: %d\n", g_list_length(data->frame_list)); +#endif + +if (!offset) + return(1); + +if (fsetpos(fp, offset)) + { + printf("Error positioning file pointer.\n"); + return(2); + } +else + { +/* use supplied routine (if available) */ + read_xsf_frame(fp, data); + } + +/* got everything */ +data->num_asym = g_slist_length(data->cores); +data->num_frames = frame; + +/* get rid of frame list if only one frame */ +if (data->num_frames == 1) + { + free_list(data->frame_list); + data->frame_list = NULL; + } + +#if DEBUG_READ_XSF +printf("Found %d atoms.\n", n); +#endif + +/* model setup */ +g_free(data->basename); +data->basename = parse_strip(filename); + +model_prep(data); + +return(0); +} diff --git a/src/interface.h b/src/interface.h index 251a1e5..5833655 100644 --- a/src/interface.h +++ b/src/interface.h @@ -60,7 +60,7 @@ GDIS, SGINFO, SYMMETRY, GPERIODIC, ELEM_EDIT, POVRAY, GENSURF, ABOUT, ANIM, PLOTS, SURF, DISPLAY, GEOMETRY, SPATIAL, TASKMAN, MANUAL, SETUP, FILE_SELECT, FILE_LOAD, FILE_SAVE, FILE_SAVE_AS, NODATA, DATA, BIOSYM, CIF, FDF, GULP, MONTY, MARVIN, MORPH, -META_DATA, XML, XTL, XYZ, MOL2, +META_DATA, XML, XSF, XTL, XYZ, MOL2, AUTO, CSSR, GAMOUT, PDB, GEOMVIEW_OFF, PROJECT, DOCKING, MDI, CREATOR, MVNOUT, GULPOUT, GULP_TRJ, SIESTA_OUT, VASP, CVASP, USPEX, CUSPEX, REPLACE_ATOMS, DYNAMICS, ZMATRIX, diff --git a/src/makefile.src b/src/makefile.src index 9394deb..209116c 100644 --- a/src/makefile.src +++ b/src/makefile.src @@ -10,7 +10,7 @@ SRC = main.c model.c coords.c connect.c matrix.c module.c task.c \ ff.c ff_gulp.c test.c \ file.c file_cif.c file_gulp.c file_gmf.c file_marvin.c file_xtl.c \ file_arc.c file_xyz.c file_fdf.c file_vasp.c file_gms.c file_diff.c file_xml.c \ - file_abinit.c file_pdb.c file_povray.c file_nwchem.c file_castep.c \ + file_abinit.c file_pdb.c file_povray.c file_nwchem.c file_castep.c file_xsf.c \ file_gauss.c file_qe.c file_rietica.c file_geomview.c file_cssr.c file_cel.c \ file_dmol.c file_dlpoly.c file_bgf.c file_cgf.c file_dlp.c \ file_gromacs.c file_meta.c file_mol2.c file_uspex.c From eaddb50e70a7cdb71fe27c57837fd3946ab60d81 Mon Sep 17 00:00:00 2001 From: Craig Fisher <66772456+cajfisher@users.noreply.github.com> Date: Wed, 31 Aug 2022 14:06:07 +0900 Subject: [PATCH 3/8] Fix bug in meta file reader Fixes bug in file_meta.c when parsing units Replaces deprecated g_pattern_match_string with g_pattern_spec_match_string in file.c Replace QE with Quantum Espresso in file type lists for clarity Correct various spelling/punctuation errors --- src/analysis.c | 2 +- src/file.c | 127 +++++++++++++++++++++++++++++++++++++++++------- src/file_meta.c | 12 ++--- src/gui_task.c | 2 +- src/spatial.c | 4 +- 5 files changed, 119 insertions(+), 28 deletions(-) diff --git a/src/analysis.c b/src/analysis.c index 7824514..2842469 100644 --- a/src/analysis.c +++ b/src/analysis.c @@ -482,7 +482,7 @@ for (n=0 ; nnum_frames ; n++) */ /* CURRENT - loop over all atoms - even duplicates so that we can record */ -/* distance between an atom and it's periodic images (NB: correct for double counting) */ +/* distance between an atom and its periodic images (NB: correct for double counting) */ for (i=0 ; inum_atoms ; i++) { corei = g_slist_nth_data(model->cores, i); diff --git a/src/file.c b/src/file.c index d2dca61..f6fbdcc 100644 --- a/src/file.c +++ b/src/file.c @@ -56,9 +56,74 @@ The GNU GPL can also be found at http://www.gnu.org extern struct sysenv_pak sysenv; extern struct elem_pak elements[]; -/***************************************/ -/* setup the recognized file type list */ -/***************************************/ +/**********************************************************/ +/* Check if file is binary or ascii */ +/**********************************************************/ +gint ascii_check(const gchar *filename) +{ +FILE *fp; +gchar c; +gint flag = 0; + +fp = fopen(filename, "r"); + +/* checks */ +g_assert(fp != NULL); + +c = fgetc(fp); + +while (c != EOF) + { + if (!isascii(c) || + (iscntrl(c) && !isspace(c) && + c != '\b' && c != '\032' && c != '\033')) + flag++; /* not all ASCII */ + c = fgetc(fp); + } + +fclose(fp); + +if (flag) + return 1; /* Binary */ +else + return 0; /* Ascii */ +} +/**********************************************************/ +/* change model basename and update filenames & tree */ +/**********************************************************/ +void change_basename(GtkWidget *w, struct model_pak *data) +{ +g_assert(w != NULL); +g_assert(data != NULL); + +/* de-alloc */ +g_free(data->basename); + +/* set the new basename & related info */ +data->basename = g_strdup(gtk_entry_get_text(GTK_ENTRY(w))); + +/* update the model tree */ +tree_model_add(data); +} + +/********************************************/ +/* construct file name if path not included */ +/********************************************/ +gchar* construct_filename(gchar *filename) +{ +gchar *fullname; + +/* construct complete filename */ +if( !g_ascii_strcasecmp(filename, g_path_get_basename(filename)) ) + fullname = g_build_filename(sysenv.cwd, filename, NULL); +else + fullname = g_strdup(filename); + +return fullname; +} +/****************************************/ +/* set up the recognized file type list */ +/****************************************/ #define DEBUG_FILE_INIT 0 void file_init(void) { @@ -346,7 +411,7 @@ file_data = g_malloc(sizeof(struct file_pak)); file_data->id = QE; file_data->group = QE; file_data->menu = TRUE; -file_data->label = g_strdup("QE"); +file_data->label = g_strdup("Quantum Espresso"); file_data->ext = NULL; file_data->ext = g_slist_append(file_data->ext, "qein"); file_data->write_file = write_qe; @@ -491,6 +556,45 @@ file_data->read_file = read_mol2; file_data->read_frame = NULL; sysenv.file_list = g_slist_prepend(sysenv.file_list, file_data); +/* supported file type */ +file_data = (struct file_pak *) g_malloc(sizeof(struct file_pak)); +file_data->id = MOLDY; +file_data->group = MOLDY; +file_data->menu = TRUE; +file_data->label = g_strdup("Moldy"); +file_data->ext = NULL; +file_data->ext = g_slist_prepend(file_data->ext, "in"); +file_data->ext = g_slist_prepend(file_data->ext, "min"); +file_data->ext = g_slist_prepend(file_data->ext, "mdy"); +file_data->read_file = read_moldy; +file_data->write_file = write_moldy_sys; +sysenv.file_list = g_slist_prepend(sysenv.file_list, file_data); + +/* supported file type */ +file_data = (struct file_pak *) g_malloc(sizeof(struct file_pak)); +file_data->id = MOLDY_POT; +file_data->group = MOLDY; +file_data->menu = FALSE; +file_data->label = g_strdup("Moldy potentials"); +file_data->ext = NULL; +file_data->ext = g_slist_prepend(file_data->ext, "pot"); +file_data->read_file = NULL; +file_data->write_file = NULL; +sysenv.file_list = g_slist_prepend(sysenv.file_list, file_data); + +/* supported file type */ +file_data = (struct file_pak *) g_malloc(sizeof(struct file_pak)); +file_data->id = MOLDY_RES; +file_data->group = MOLDY; +file_data->menu = TRUE; +file_data->label = g_strdup("Moldy restart"); +file_data->ext = NULL; +file_data->ext = g_slist_prepend(file_data->ext, "sav"); +file_data->ext = g_slist_prepend(file_data->ext, "mds"); +file_data->read_file = read_moldy_restart; +file_data->write_file = NULL; +sysenv.file_list = g_slist_prepend(sysenv.file_list, file_data); + /* supported file type */ file_data = g_malloc(sizeof(struct file_pak)); file_data->id = NWCHEM; @@ -677,19 +781,6 @@ file_data->read_file = read_xml; file_data->read_frame = NULL; /* frame reading */ sysenv.file_list = g_slist_prepend(sysenv.file_list, file_data); -/* supported file type */ -file_data = g_malloc(sizeof(struct file_pak)); -file_data->id = XSF; -file_data->group = XSF; -file_data->menu = TRUE; -file_data->label = g_strdup("XSF"); -file_data->ext = NULL; -file_data->ext = g_slist_prepend(file_data->ext, "xsf"); -file_data->write_file = write_xsf; -file_data->read_file = read_xsf; -file_data->read_frame = read_xsf_frame; /* frame reading */ -sysenv.file_list = g_slist_prepend(sysenv.file_list, file_data); - /* supported file type */ file_data = g_malloc(sizeof(struct file_pak)); file_data->id = XTL; @@ -814,7 +905,7 @@ while (list) name = list->data; list = g_slist_next(list); - if (!g_pattern_match_string(ps, name)) + if (!g_pattern_spec_match_string(ps, name)) { files = g_slist_remove(files, name); g_free(name); diff --git a/src/file_meta.c b/src/file_meta.c index 4ca3c60..25a9064 100644 --- a/src/file_meta.c +++ b/src/file_meta.c @@ -35,21 +35,21 @@ extern struct elem_pak elements[]; /* meta data for computational chemistry archiving */ -/*****************************************************************/ -/* split a string containing units into it's raw value and units */ -/*****************************************************************/ +/****************************************************************/ +/* split a string containing units into its raw value and units */ +/****************************************************************/ void meta_parse_units(gchar **value, gchar **units, gchar *source) { gchar **buff; buff = g_strsplit(source, " ", 2); -if (*buff+0) - *value = g_strdup(*(buff+0)); +if (*buff) + *value = g_strdup(*(buff)); else *value = NULL; -if (*buff+1) +if (g_strv_length(buff) == 2) *units = g_strdup(*(buff+1)); else *units = NULL; diff --git a/src/gui_task.c b/src/gui_task.c index 9b288ac..8fceeac 100644 --- a/src/gui_task.c +++ b/src/gui_task.c @@ -246,7 +246,7 @@ printf("%s", line); pclose(fp); /* Build the process hierarchy. Every process marks itself as first child */ -/* of it's parent or as sister of first child of its parent */ +/* of its parent or as sister of first child of its parent */ /* algorithm taken from pstree.c by Fred Hucht */ for (me = 0; me < psarray->len; me++) diff --git a/src/spatial.c b/src/spatial.c index 60c3e68..73d0cfd 100644 --- a/src/spatial.c +++ b/src/spatial.c @@ -399,8 +399,8 @@ struct core_pak *core1, *core2, *core3; /* FIXME - this only uses the 1st 3 points, in future - an average for n pts */ /* http://www.geocities.com/CollegePark/Campus/1278/JBook/LSQ_Plane.html */ /* shouldn't matter when this routine is properly implemented, as we'll go */ -/* through the atom_list in the usual fashoin & terminate when it is NULL, */ -/* not when it's data ptr is NULL */ +/* through the atom_list in the usual fashoin and terminate when it's NULL, */ +/* not when its data ptr is NULL */ g_assert(cores != NULL); g_assert(g_list_length(cores) > 2); From da5aa574a414edfe6e136191af58abc529eae635 Mon Sep 17 00:00:00 2001 From: Craig Fisher <66772456+cajfisher@users.noreply.github.com> Date: Wed, 31 Aug 2022 14:10:19 +0900 Subject: [PATCH 4/8] Remove moldy files specs --- src/file.c | 104 ----------------------------------------------------- 1 file changed, 104 deletions(-) diff --git a/src/file.c b/src/file.c index f6fbdcc..6bc884c 100644 --- a/src/file.c +++ b/src/file.c @@ -56,71 +56,6 @@ The GNU GPL can also be found at http://www.gnu.org extern struct sysenv_pak sysenv; extern struct elem_pak elements[]; -/**********************************************************/ -/* Check if file is binary or ascii */ -/**********************************************************/ -gint ascii_check(const gchar *filename) -{ -FILE *fp; -gchar c; -gint flag = 0; - -fp = fopen(filename, "r"); - -/* checks */ -g_assert(fp != NULL); - -c = fgetc(fp); - -while (c != EOF) - { - if (!isascii(c) || - (iscntrl(c) && !isspace(c) && - c != '\b' && c != '\032' && c != '\033')) - flag++; /* not all ASCII */ - c = fgetc(fp); - } - -fclose(fp); - -if (flag) - return 1; /* Binary */ -else - return 0; /* Ascii */ -} -/**********************************************************/ -/* change model basename and update filenames & tree */ -/**********************************************************/ -void change_basename(GtkWidget *w, struct model_pak *data) -{ -g_assert(w != NULL); -g_assert(data != NULL); - -/* de-alloc */ -g_free(data->basename); - -/* set the new basename & related info */ -data->basename = g_strdup(gtk_entry_get_text(GTK_ENTRY(w))); - -/* update the model tree */ -tree_model_add(data); -} - -/********************************************/ -/* construct file name if path not included */ -/********************************************/ -gchar* construct_filename(gchar *filename) -{ -gchar *fullname; - -/* construct complete filename */ -if( !g_ascii_strcasecmp(filename, g_path_get_basename(filename)) ) - fullname = g_build_filename(sysenv.cwd, filename, NULL); -else - fullname = g_strdup(filename); - -return fullname; -} /****************************************/ /* set up the recognized file type list */ /****************************************/ @@ -556,45 +491,6 @@ file_data->read_file = read_mol2; file_data->read_frame = NULL; sysenv.file_list = g_slist_prepend(sysenv.file_list, file_data); -/* supported file type */ -file_data = (struct file_pak *) g_malloc(sizeof(struct file_pak)); -file_data->id = MOLDY; -file_data->group = MOLDY; -file_data->menu = TRUE; -file_data->label = g_strdup("Moldy"); -file_data->ext = NULL; -file_data->ext = g_slist_prepend(file_data->ext, "in"); -file_data->ext = g_slist_prepend(file_data->ext, "min"); -file_data->ext = g_slist_prepend(file_data->ext, "mdy"); -file_data->read_file = read_moldy; -file_data->write_file = write_moldy_sys; -sysenv.file_list = g_slist_prepend(sysenv.file_list, file_data); - -/* supported file type */ -file_data = (struct file_pak *) g_malloc(sizeof(struct file_pak)); -file_data->id = MOLDY_POT; -file_data->group = MOLDY; -file_data->menu = FALSE; -file_data->label = g_strdup("Moldy potentials"); -file_data->ext = NULL; -file_data->ext = g_slist_prepend(file_data->ext, "pot"); -file_data->read_file = NULL; -file_data->write_file = NULL; -sysenv.file_list = g_slist_prepend(sysenv.file_list, file_data); - -/* supported file type */ -file_data = (struct file_pak *) g_malloc(sizeof(struct file_pak)); -file_data->id = MOLDY_RES; -file_data->group = MOLDY; -file_data->menu = TRUE; -file_data->label = g_strdup("Moldy restart"); -file_data->ext = NULL; -file_data->ext = g_slist_prepend(file_data->ext, "sav"); -file_data->ext = g_slist_prepend(file_data->ext, "mds"); -file_data->read_file = read_moldy_restart; -file_data->write_file = NULL; -sysenv.file_list = g_slist_prepend(sysenv.file_list, file_data); - /* supported file type */ file_data = g_malloc(sizeof(struct file_pak)); file_data->id = NWCHEM; From 7a969760690555ee0911303ec7c02ea165800c9a Mon Sep 17 00:00:00 2001 From: Craig Fisher <66772456+cajfisher@users.noreply.github.com> Date: Mon, 5 Sep 2022 11:43:17 +0900 Subject: [PATCH 5/8] Update copyright statement --- src/file_xsf.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/file_xsf.c b/src/file_xsf.c index de9fcc8..3437b92 100644 --- a/src/file_xsf.c +++ b/src/file_xsf.c @@ -1,7 +1,7 @@ /* -Copyright (C) 2000 by Sean David Fleming +Copyright (C) 2022 by Craig Andrew James Fisher -sean@ivec.org +c_fisher@jfcc.or.jp This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License From 43eb9325000b7e712d65d1490346313ed83106bc Mon Sep 17 00:00:00 2001 From: Craig Fisher <66772456+cajfisher@users.noreply.github.com> Date: Mon, 5 Sep 2022 16:15:08 +0900 Subject: [PATCH 6/8] Fix bug in cif reader --- src/file_cif.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/file_cif.c b/src/file_cif.c index 5eb03c5..bca09c1 100644 --- a/src/file_cif.c +++ b/src/file_cif.c @@ -182,7 +182,7 @@ return(0); /***************/ /* CIF loading */ /***************/ -#define DEBUG_LOAD_CIF 0 +#define DEBUG_LOAD_CIF 1 gint read_cif(gchar *filename, struct model_pak *data) { gint i, j, n, natom, new, order, pos, keyword, loop_count=0; @@ -776,7 +776,7 @@ else return(-1); } #if DEBUG_LOAD_CIF -printf("Found %d atom%c.\n", natom, (natom != 1?'s':'')); +printf("Found %d atom%s\n", natom, (natom != 1 ? "s.":".")); printf("Found %d symmetry matrices.\n", data->sginfo.order); printf("Found %d model(s)\n", new); printf("Periodicity is %d\n", data->periodic); From b36620ac7a48ce0f4d15aac44eebdc9fff46061a Mon Sep 17 00:00:00 2001 From: Craig Fisher <66772456+cajfisher@users.noreply.github.com> Date: Mon, 26 Jun 2023 13:59:35 +0900 Subject: [PATCH 7/8] Add surface dipole option Adds a button to "Region" window of "Model editing" dialog to calculate surface dipole of a 2D model and report it in message box --- src/coords.c | 26 +++++++++++++++++ src/coords.h | 1 + src/file_cif.c | 2 +- src/gui_edit.c | 78 ++++++++++++++++++++++++++++++++++++++++++++++++++ src/main.c | 67 ++++++++++++++++++++++++++++++------------- src/pak.h | 9 ++++++ 6 files changed, 162 insertions(+), 21 deletions(-) diff --git a/src/coords.c b/src/coords.c index 9d61406..7b0b3c0 100644 --- a/src/coords.c +++ b/src/coords.c @@ -47,6 +47,32 @@ The GNU GPL can also be found at http://www.gnu.org extern struct sysenv_pak sysenv; extern struct elem_pak elements[]; +#define DEBUG_CALC_CENTROID 0 +/*************************************/ +/* return centroid of selected atoms */ +/*************************************/ +void calc_centroid(gdouble *centroid, GSList *input) +{ +GSList *list=NULL; +struct core_pak *core; + +if (!input) + return; + +VEC3SET(centroid, 0.0, 0.0, 0.0); +for (list=input ; list ; list=g_slist_next(list)) + { + core = list->data; + ARR3ADD(centroid, core->x); + } + +VEC3MUL(centroid, 1.0 / (gdouble) g_slist_length(input)); + +#if DEBUG_CALC_CENTROID + P3VEC("Centroid = ", centroid); +#endif +} + /**********************/ /* debugging routines */ /**********************/ diff --git a/src/coords.h b/src/coords.h index 29ca9e9..12f4ebc 100644 --- a/src/coords.h +++ b/src/coords.h @@ -291,3 +291,4 @@ GSList *connect_fragment_get(struct core_pak *, struct model_pak *); GSList *connect_neighbours(struct core_pak *) ; +void calc_centroid(gdouble *, GSList *); diff --git a/src/file_cif.c b/src/file_cif.c index bca09c1..424dee6 100644 --- a/src/file_cif.c +++ b/src/file_cif.c @@ -182,7 +182,7 @@ return(0); /***************/ /* CIF loading */ /***************/ -#define DEBUG_LOAD_CIF 1 +#define DEBUG_LOAD_CIF 0 gint read_cif(gchar *filename, struct model_pak *data) { gint i, j, n, natom, new, order, pos, keyword, loop_count=0; diff --git a/src/gui_edit.c b/src/gui_edit.c index 4389638..c07e18d 100644 --- a/src/gui_edit.c +++ b/src/gui_edit.c @@ -63,6 +63,81 @@ extern struct elem_pak elements[]; enum{AT_ANY, AT_SELECTED, AT_LATTICE}; +void show_surface_dipole(struct model_pak *data) +{ +gchar txt[60]; + +calc_emp(data); + +/* inform the user */ +sprintf(txt, "Surface dipole: %f e.Angs\n", data->gulp.sdipole); +gui_text_show(STANDARD, txt); + +} + +/***************************************/ +/* hook for dipole moment button */ +/***************************************/ +void surface_dipole(GtkWidget *w) +{ +struct model_pak *data; + +data = sysenv.active_model; + +/* checks */ +if (!data) + return; + +if (data->periodic != 2) { + gui_text_show(WARNING, "Model must be 2D.\n"); + return; + } + +show_surface_dipole(data); +} + +/*********************************************/ +/* update widget values with internal values */ +/*********************************************/ +void update_centre(void) +{ +/* set transformation matrix widget entries */ +gui_relation_update_widget(&CEDIT.edit_x[0]); +gui_relation_update_widget(&CEDIT.edit_x[1]); +gui_relation_update_widget(&CEDIT.edit_x[2]); +} + +/*****************************************/ +/* set centre to centre of selected ions */ +/*****************************************/ +void set_centre(GtkWidget *w) +{ +/* gint n; */ +struct model_pak *model; +gdouble centroid[3]; + +model = sysenv.active_model; +if (!model) + return; + +/* list = model->selection; +n = g_slist_length(list); +if (!n) + return; */ + +if (!model->selection) + return; + +calc_centroid(centroid, model->selection); + +if( model->periodic > 0 ) + vecmat(model->latmat, centroid); + +ARR3SET(CEDIT.edit_x, centroid); + +update_centre(); +} + /*********************************************/ /* update widget values with internal values */ /*********************************************/ @@ -2418,6 +2493,9 @@ gui_button_x("Add selected atoms to region 4", region_change, GINT_TO_POINTER(RE gui_button_x("Add selected atoms to growth slice", region_growth_slice, (gpointer) GROWTH_ADD, vbox); gui_button_x("Remove selected atoms from growth slice", region_growth_slice, (gpointer) GROWTH_DEL, vbox); +vbox = gui_frame_vbox("Properties", FALSE, FALSE, box); +gui_button_x("Calculate surface dipole", surface_dipole, NULL, vbox); + /* if (model->periodic == 0 || model->periodic == 2) gtk_widget_set_sensitive(GTK_WIDGET(model->edit_regions_frame), TRUE); else diff --git a/src/main.c b/src/main.c index 1d6a6ea..83a7a49 100644 --- a/src/main.c +++ b/src/main.c @@ -423,27 +423,54 @@ sysenv.apb_on = TRUE; sysenv.lmb_on = FALSE; sysenv.pib_on = FALSE; -/*edit_dialog*/ -sysenv.cedit.edit_anim_n=0; -sysenv.cedit.edit_chirality[0]=6.; -sysenv.cedit.edit_chirality[1]=6.; -sysenv.cedit.edit_length=1.44; -sysenv.cedit.edit_basis[0]=NULL; -sysenv.cedit.edit_basis[1]=NULL; -sysenv.cedit.edit_spatial_colour[0]=1.0; -sysenv.cedit.edit_spatial_colour[1]=0.0; -sysenv.cedit.edit_spatial_colour[2]=0.0; -sysenv.cedit.edit_label_colour[0]=1.0; -sysenv.cedit.edit_label_colour[1]=1.0; -sysenv.cedit.edit_label_colour[2]=1.0; -sysenv.cedit.spatial_list=NULL; -sysenv.cedit.spatial_tree=NULL; -sysenv.cedit.spatial_selected=NULL; -sysenv.cedit.diffract_model=NULL; +/* edit_dialog */ +sysenv.cedit.edit_anim_n = 0; +sysenv.cedit.edit_chirality[0] = 6.; +sysenv.cedit.edit_chirality[1] = 6.; +sysenv.cedit.edit_length = 1.44; +sysenv.cedit.edit_basis[0] = NULL; +sysenv.cedit.edit_basis[1] = NULL; +sysenv.cedit.edit_spatial_colour[0] = 1.0; +sysenv.cedit.edit_spatial_colour[1] = 0.0; +sysenv.cedit.edit_spatial_colour[2] = 0.0; +sysenv.cedit.edit_label_colour[0] = 1.0; +sysenv.cedit.edit_label_colour[1] = 1.0; +sysenv.cedit.edit_label_colour[2] = 1.0; +sysenv.cedit.spatial_list = NULL; +sysenv.cedit.spatial_tree = NULL; +sysenv.cedit.spatial_selected = NULL; +sysenv.cedit.diffract_model = NULL; /*edit_widget*/ -sysenv.cedit.apd_data=NULL; -sysenv.cedit.apd_core=NULL; - +sysenv.cedit.apd_data = NULL; +sysenv.cedit.apd_core = NULL; + +/* edit miscellaneous functions dialog */ +sysenv.cedit.edit_x[0] = 0.0; +sysenv.cedit.edit_x[1] = 0.0; +sysenv.cedit.edit_x[2] = 0.0; +/* sysenv.misc.edit_anim_n = 0; +sysenv.misc.edit_length = 1.44; +sysenv.misc.edit_percent = 0.0; +sysenv.misc.edit_number = 1.0; +sysenv.misc.edit_subdist = 0.0; +sysenv.misc.edit_dist = 1.0; +sysenv.misc.edit_shift_min = 0.0; +sysenv.misc.edit_shift_max = 1.0; +sysenv.misc.edit_length = 1.44; +sysenv.misc.edit_construct; +sysenv.misc.edit_basis[2] = {NULL, NULL}; +sysenv.misc.edit_type = NULL; +sysenv.misc.edit_insert = NULL; +sysenv.misc.elem_entry; +sysenv.misc.grid_diml +sysenv.misc.grid_sep; +sysenv.misc.periodicity_spin; +sysenv.misc.obj_reference; +sysenv.misc.transmat[12]; +sysenv.misc.angle = 0.0; +sysenv.misc.edit_radius = 10.0; +sysenv.misc.edit_avcut = 0.8; +*/ /* default to single model display */ sysenv.mal = NULL; sysenv.displayed[0] = -1; diff --git a/src/pak.h b/src/pak.h index 07c5d3b..1c90ef6 100644 --- a/src/pak.h +++ b/src/pak.h @@ -153,6 +153,15 @@ GtkWidget *apd_element, *apd_label, *apd_type, *apd_charge, *apd_mass, *apd_sof, *apd_x, *apd_y, *apd_z, *apd_growth, *apd_region, *apd_translate; struct model_pak *apd_data; struct core_pak *apd_core; + +gdouble edit_percent, edit_number, edit_subdist; +gdouble edit_dist, edit_shift_min, edit_shift_max; +gchar *edit_type; +gchar *edit_insert; +GtkWidget *elem_entry, *grid_dim, *grid_sep; +GtkWidget *obj_reference; +gdouble angle, edit_radius, edit_avcut; +gdouble edit_x[3]; }; /***********************/ From 514da97c325248ca7e39d8fdc4d1cedca08d17c2 Mon Sep 17 00:00:00 2001 From: Craig Fisher <66772456+cajfisher@users.noreply.github.com> Date: Thu, 22 Feb 2024 10:26:41 +0900 Subject: [PATCH 8/8] Check GLIB version Some OSs use older versions of glib, before g_pattern_spec_match_string replaced g_pattern_match_string (deprecated since v2.70) --- src/file.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/file.c b/src/file.c index 6bc884c..e5bd3ae 100644 --- a/src/file.c +++ b/src/file.c @@ -33,6 +33,12 @@ The GNU GPL can also be found at http://www.gnu.org #include #include +#define GLIB_VERSION(major, minor, micro) \ + (GLIB_MAJOR_VERSION > (major) || \ + (GLIB_MAJOR_VERSION == (major) && GLIB_MINOR_VERSION > (minor)) || \ + (GLIB_MAJOR_VERSION == (major) && GLIB_MINOR_VERSION == (minor) && \ + GLIB_MICRO_VERSION >= (micro))) + #include "gdis.h" #include "coords.h" #include "error.h" @@ -801,7 +807,11 @@ while (list) name = list->data; list = g_slist_next(list); +#if GLIB_VERSION(2, 7, 0) if (!g_pattern_spec_match_string(ps, name)) +#else + if (!g_pattern_match_string(ps, name)) +#endif { files = g_slist_remove(files, name); g_free(name);