/* Copyright (C) 2003 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 #include #ifndef __WIN32 #include #endif #include "gdis.h" #include "coords.h" #include "matrix.h" #include "model.h" #include "shortcuts.h" #include "interface.h" #include "dialog.h" #define DEBUG 0 /****************/ extern struct sysenv_pak sysenv; /****************/ void mdi_model_create(gint); void rot(gdouble *, gdouble , gdouble , gdouble); GtkWidget *spinner[MAX_MODELS]; struct mdi_pak mdi_data; /*******************/ /* MDI setup & run */ /*******************/ void mdi_model_setup(void) { GtkSpinButton *spin; gint i,num_req,last_spin; gdouble biggest; GSList *list; struct model_pak *data; /* box size required */ spin = GTK_SPIN_BUTTON (spinner[0]); mdi_data.box_dim = gtk_spin_button_get_value_as_int(spin); /* NB: if an MDI run has already been done - terminate on this model */ last_spin = 0; for (list=sysenv.mal ; list ; list=g_slist_next(list)) { data = list->data; if (data->id == MDI) break; last_spin++; } /* numer of loaded models = max possible components */ mdi_data.num_comp = last_spin; mdi_data.comp_idx = g_malloc0(mdi_data.num_comp*sizeof(gint)); mdi_data.comp_req = g_malloc0(mdi_data.num_comp*sizeof(gint)); mdi_data.comp_done = g_malloc0(mdi_data.num_comp*sizeof(gint)); /* error trap - don't use an MDI model as a (non-zero) component */ if (!last_spin) { gui_text_show(ERROR, "Have you done something silly?\n"); return; } /* go through non solvent molecules & sum amount required */ num_req=0; for (i=1 ; irmax > biggest) biggest = data->rmax; } /* auto setting = 2*biggest model's radius + safety */ mdi_data.latt_sep=2.0*biggest + 1.0; #if DEBUG printf("Boxdim = %d\n",mdi_data.box_dim); printf("Lattice sep = %f\n",mdi_data.latt_sep); for (i=0 ; istr); gtk_box_pack_start(GTK_BOX(GTK_DIALOG(window)->vbox), frame, TRUE, TRUE, 0); vbox = gtk_vbox_new(FALSE, 0); gtk_container_set_border_width(GTK_CONTAINER(vbox), PANEL_SPACING); gtk_container_add(GTK_CONTAINER(frame), vbox); label = gtk_label_new ("Side length (lattice points)"); /* gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5); */ gtk_box_pack_start(GTK_BOX(vbox), label, FALSE, TRUE, 0); adj = (GtkAdjustment *) gtk_adjustment_new (4, 3, 100, 1, 1, 0); spinner[0] = gtk_spin_button_new (adj, 0, 0); gtk_spin_button_set_wrap(GTK_SPIN_BUTTON (spinner[0]), FALSE); gtk_box_pack_start(GTK_BOX (vbox), spinner[0], FALSE, TRUE, 0); g_string_sprintf(frame_label,"Model: %s",data->basename); frame = gtk_frame_new(frame_label->str); gtk_box_pack_start(GTK_BOX(GTK_DIALOG(window)->vbox), frame, TRUE, TRUE, 0); vbox = gtk_vbox_new(FALSE, 0); gtk_container_set_border_width(GTK_CONTAINER (vbox), PANEL_SPACING); gtk_container_add(GTK_CONTAINER(frame), vbox); label = gtk_label_new ("This will be the solvent"); gtk_box_pack_start(GTK_BOX(vbox), label, FALSE, TRUE, 0); /* omit solvent (model 0) */ i = 1; list = g_slist_next(sysenv.mal); while (list) { data = list->data; /* don't include any previous MDI model */ if (data->id == MDI) continue; g_string_sprintf(frame_label,"Model: %s",data->basename); frame = gtk_frame_new(frame_label->str); gtk_box_pack_start(GTK_BOX(GTK_DIALOG(window)->vbox), frame, TRUE, TRUE, 0); vbox = gtk_vbox_new(FALSE, 0); gtk_container_set_border_width(GTK_CONTAINER(vbox), PANEL_SPACING); gtk_container_add(GTK_CONTAINER(frame), vbox); label = gtk_label_new ("Number required"); /* gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5); */ gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, TRUE, 0); adj = (GtkAdjustment *) gtk_adjustment_new (0, 0, 100, 1, 5, 0); spinner[i] = gtk_spin_button_new (adj, 0, 0); gtk_spin_button_set_wrap (GTK_SPIN_BUTTON (spinner[i]), TRUE); gtk_box_pack_start (GTK_BOX (vbox), spinner[i], FALSE, TRUE, 0); list = g_slist_next(list); i++; } /* buttons */ gui_stock_button(GTK_STOCK_EXECUTE, mdi_model_setup, NULL, GTK_DIALOG(window)->action_area); gui_stock_button(GTK_STOCK_CLOSE, dialog_destroy, dialog, GTK_DIALOG(window)->action_area); /* display the dialog */ gtk_widget_show_all(window); g_string_free(frame_label, TRUE); } /***********/ /* run MDI */ /***********/ #define DEBUG_MDI_MODEL_CREATE 0 void mdi_model_create(gint new) { gint i,j,na,nb,ns,replace,ret; struct model_pak *data; #ifndef __WIN32 struct tms buffer; #endif /* main array */ mdi_data.array = (gint *) g_malloc0(mdi_data.box_dim*mdi_data.box_dim* mdi_data.box_dim*sizeof(gint)); /* calculate the total number of atoms & bonds & sites in the box */ na = nb = 0; ns = -mdi_data.comp_req[0]; for (i=0 ; iid = MDI; strcpy(data->filename,"MDI_model"); g_free(data->basename); data->basename = g_strdup("MDI model"); /* initialize random generator */ #if __WIN32 j=666; #else j=times(&buffer); #endif #if DEBUG_MDI_MODEL_CREATE printf("Random seed = %d\n",j); #endif srand(j); /* do the business */ ret = fill(); #if DEBUG_MDI_MODEL_CREATE printf("fill() return code: %d\n",ret); #endif if (ret == 2) { gui_text_show(ERROR, "Run was unsuccessful!\n"); model_delete(data); g_free(mdi_data.array); return; } /* copy box into the model coord data array */ write_dat(data); model_prep(data); /* update model tree display */ if (replace) { tree_model_add(data); gui_model_select(data); } else { tree_model_add(data); } #if DEBUG_MDI_MODEL_CREATE printf("done model init\n"); #endif g_free(mdi_data.array); #if DEBUG_MDI_MODEL_CREATE printf("MDI done.\n"); #endif } /*********************/ /* Main box fill sub */ /*********************/ gint fill() { gint num_sites, max_sites,num_cand; gint i,j,k,di,dj,dk,r2,s; gint req_tot,ci,ri,pos; gint *r2_min, max_min; gdouble ran2(); struct cand_pak *cand; struct box_pak *site; /* allocate for sites - ie solvent not included XCPT corners */ max_sites = pow(mdi_data.box_dim,3) - mdi_data.comp_req[0] + 8; site = (struct box_pak *) g_malloc(max_sites*sizeof(struct box_pak)); r2_min = (gint *) g_malloc(pow(mdi_data.box_dim,3)*sizeof(gint)); /* max out the number of candidate sites */ cand = (struct cand_pak *) g_malloc(pow(mdi_data.box_dim,3) *sizeof(struct cand_pak)); /* NB: initially every point in box should be 0 => solvent */ #if DEBUG printf("Filling box: %d x %d x %d\n",mdi_data.box_dim, mdi_data.box_dim,mdi_data.box_dim); #endif /* NO cadidate inititalization */ num_sites = 0; /* compute total number of components to dissolve */ req_tot=0; for (i=1 ; i= mdi_data.comp_req[ci]) ci++; if (ci == g_slist_length(sysenv.mal)) { printf("fill() error: mismatch in component requirements!\n"); return(2); } mdi_data.comp_done[ci]++; /* evaluate all sites - sphere of clearance */ pos=0; max_min=0; for(i=0 ; i mdi_data.box_dim/2.0) di -= mdi_data.box_dim/2.0; dj = abs(site[s].y-j); if (dj > mdi_data.box_dim/2.0) dj -= mdi_data.box_dim/2.0; dk = abs(site[s].z-k); if (dk > mdi_data.box_dim/2.0) dk -= mdi_data.box_dim/2.0; r2 = di*di + dj*dj + dk*dk; /* test for new minimum */ if (r2 < r2_min[pos]) r2_min[pos] = r2; } /* get the overall maximum (of the minima) */ if (r2_min[pos] > max_min) max_min = r2_min[pos]; pos++; } } } s=pos=0; for(i=0 ; i= pow(mdi_data.box_dim,3)) { printf("Error at (%f,%f,%f)\n",x,y,z); printf("Program bug: address (pos) out of bounds!\n"); return; } /* get component at this (x,y,z) pos'n */ s = *(mdi_data.array+pos); /* get the model this corresponds to */ m = mdi_data.comp_idx[s]; data = model_ptr(m, RECALL); pos++; /* create some random rotations */ phi = 2.0*PI*ran2(); theta = PI - 2.0*PI*ran2(); psi = 2.0*PI*ran2(); for (list=data->cores ; list ; list=g_slist_next(list)) { core = (struct core_pak *) list->data; if (core->status & DELETED) continue; /* do rotation */ ARR3SET(q, core->rx); rot(&q[0],phi,theta,psi); /* do lattice site translation of coords */ q[0] += x; q[1] += y; q[2] += z; /* write the atom data to the model structure */ copy = dup_core(core); dest->cores = g_slist_prepend(dest->cores, copy); copy->status = NORMAL; copy->orig = TRUE; copy->primary = TRUE; copy->primary_core = NULL; copy->region = REGION1A; ARR3SET(copy->x, q); } } } } /* model info */ dest->id = MDI; dest->fractional = FALSE; dest->periodic = 3; dest->pbc[0] = box_len; dest->pbc[1] = box_len; dest->pbc[2] = box_len; dest->pbc[3] = PI/2.0; dest->pbc[4] = PI/2.0; dest->pbc[5] = PI/2.0; #if DEBUG printf("write_dat() done\n"); #endif } /***********************************************/ /* input a 3 element array = coords to rotate */ /* plus angles to rotate by */ /* output the three coords rotated about 0,0,0 */ /* by input angles */ /***********************************************/ void rot(gdouble *coords, gdouble phi, gdouble theta, gdouble psi) { gdouble sph, cph, sth, cth, sps, cps; gdouble rot[3][3]; /* let's make things easier */ sph=sin(phi); cph=cos(phi); sth=sin(theta); cth=cos(theta); sps=sin(psi); cps=cos(psi); /* make the matrix */ rot[0][0]= cps*cph-cth*sph*sps; rot[0][1]= cps*sph+cth*cph*sps; rot[0][2]= sps*sth; rot[1][0]=-sps*cph-cth*sph*cps; rot[1][1]=-sps*sph+cth*cph*cps; rot[1][2]= cps*sth; rot[2][0]= sth*sph; rot[2][1]=-sth*cph; rot[2][2]= cth; /* multiply the coords with the matrix */ vecmat(&rot[0][0],coords); } /*********************/ /* My random routine */ /*********************/ gdouble ran2() { gint i,j; gdouble f; i=j=0; /* generate 2 random (non 0) integers */ while(!i) i = rand(); while(!j) j = rand(); /* convert to a single float (0.0,1.0] */ if (i > j) f = (gdouble) j / (gdouble) i; else f = (gdouble) i / (gdouble) j; return f; }