/*
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 <fcntl.h>
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/stat.h>
#include "gdis.h"
#include "coords.h"
#include "edit.h"
#include "file.h"
#include "graph.h"
#include "model.h"
#include "parse.h"
#include "scan.h"
#include "task.h"
#include "matrix.h"
#include "surface.h"
#include "spatial.h"
#include "shortcuts.h"
#include "interface.h"
#include "dialog.h"
#include "opengl.h"
#include "render.h"
#include "gui_image.h"
extern struct sysenv_pak sysenv;
extern struct elem_pak elements[];
/* TODO - avoid using these globals */
GtkWidget *phonon_freq, *phonon_ir, *phonon_raman;
/*****************************/
/* phonon selection handlers */
/*****************************/
void update_phonon_range(struct model_pak *model)
{
/* checks */
g_assert(model != NULL);
if (!model->phonon_slider)
return;
/* update the slider */
if (model->num_phonons > 0)
gtk_range_set_range(GTK_RANGE(model->phonon_slider), 1, model->num_phonons);
}
/*******************/
/* run a gulp file */
/*******************/
#define DEBUG_EXEC_GULP 0
gint exec_gulp(const gchar *input, const gchar *output)
{
gint status=0;
gchar *cmd;
/* checks */
if (!sysenv.gulp_path)
return(-1);
/* delete the old file to be sure output is only data from current run */
#if _WIN32
unlink("gulp.got");
/* NB: must enclose paths with single quotes */
cmd = g_strdup_printf("'%s'", sysenv.gulp_path);
#else
unlink(output);
cmd = g_strdup_printf("%s < %s > %s", sysenv.gulp_path, input, output);
#endif
#if DEBUG_EXEC_GULP
printf("executing: [%s]\n",cmd);
#endif
task_sync(cmd);
/* done */
g_free(cmd);
return(status);
}
/*****************************/
/* execute a gulp run (task) */
/*****************************/
#define DEBUG_EXEC_GULP_TASK 0
void exec_gulp_task(gpointer ptr, gpointer data)
{
gchar *inpfile;
struct model_pak *model = ptr;
struct task_pak *task = data;
/* checks */
g_assert(model != NULL);
g_assert(task != NULL);
/* construct fullpath input filename - required for writing */
#if _WIN32
inpfile = g_build_filename(sysenv.cwd, "gulp.gin", NULL);
task->status_file = g_build_filename(sysenv.cwd, "gulp.got", NULL);
#else
inpfile = g_build_filename(sysenv.cwd, model->gulp.temp_file, NULL);
task->status_file = g_build_filename(sysenv.cwd, model->gulp.out_file, NULL);
#endif
#if DEBUG_EXEC_GULP_TASK
printf(" input file: %s\n", inpfile);
printf("output file: %s\n", model->gulp.out_file);
#endif
write_gulp(inpfile, model);
g_free(inpfile);
/* are we supposed to execute GULP? */
if (model->gulp.no_exec)
{
#if DEBUG_EXEC_GULP_TASK
printf("Skipping GULP execution on user request.\n");
#endif
return;
}
exec_gulp(model->gulp.temp_file, model->gulp.out_file);
}
/*****************************/
/* process a gulp run (task) */
/*****************************/
#define DEBUG_PROC_GULP 0
void proc_gulp_task(gpointer ptr)
{
gchar *inp, *res, *out;
GString *line;
struct model_pak *dest, *data;
/* TODO - model locking (moldel_ptr RO/RW etc) to prevent screw ups */
g_return_if_fail(ptr != NULL);
data = ptr;
/* don't attempt to process if gulp execution was turned off */
if (data->gulp.no_exec)
return;
/* FIXME - if the user has moved directories since submitting */
/* the gulp job then cwd will have changed and this will fail */
inp = g_build_filename(sysenv.cwd, data->gulp.temp_file, NULL);
res = g_build_filename(sysenv.cwd, data->gulp.dump_file, NULL);
#if __WIN32
out = g_build_filename(sysenv.cwd, "gulp.got", NULL);
#else
out = g_build_filename(sysenv.cwd, data->gulp.out_file, NULL);
#endif
switch (data->gulp.run)
{
case E_SINGLE:
/* same model (ie with current energetics dialog) so update */
read_gulp_output(out, data);
/* update energy (TODO - only if successful) */
line = g_string_new(NULL);
if (data->gulp.free)
g_string_sprintf(line, "%f (free energy)", data->gulp.energy);
else
g_string_sprintf(line, "%f", data->gulp.energy);
property_add_ranked(2, "Energy", line->str, data);
/* is there a dialog entry to be updated? */
if (GTK_IS_ENTRY(data->gulp.energy_entry))
gtk_entry_set_text(GTK_ENTRY(data->gulp.energy_entry), line->str);
if (data->periodic == 2)
{
/* update surface dipole dialog entry */
g_string_sprintf(line,"%f e.Angs",data->gulp.sdipole);
if (GTK_IS_ENTRY(data->gulp.sdipole_entry))
gtk_entry_set_text(GTK_ENTRY(data->gulp.sdipole_entry), line->str);
/* update surface energy dialog entry */
g_string_sprintf(line,"%f %s",data->gulp.esurf[0], data->gulp.esurf_units);
if (GTK_IS_ENTRY(data->gulp.esurf_entry))
gtk_entry_set_text(GTK_ENTRY(data->gulp.esurf_entry), line->str);
/* update attachment energy dialog entry */
g_string_sprintf(line,"%f %s",data->gulp.eatt[0], data->gulp.eatt_units);
if (GTK_IS_ENTRY(data->gulp.eatt_entry))
gtk_entry_set_text(GTK_ENTRY(data->gulp.eatt_entry), line->str);
}
update_phonon_range(data);
gui_active_refresh();
g_string_free(line, TRUE);
break;
case E_OPTIMIZE:
/* TODO - make it possile to get dialog data by request */
/* so that we can check if a dialog exsits to be updated */
/* get new coords */
/* create new model for the minimized result */
dest = model_new();
g_return_if_fail(dest != NULL);
/* read main data from the res file (correct charges etc.) */
read_gulp(res, dest);
/* graft to the model tree, so subsequent GULP read doesn't replace coords */
tree_model_add(dest);
/* get the output energy/phonons etc. */
read_gulp_output(out, dest);
/* FIXME - if the GULP job fails - model_prep() isnt called, and the */
/* model camera isnt initialized => error trap when gdis tries to visualize */
if (!dest->camera)
{
printf("WARNING: GULP calculation has possibly failed.\n");
model_prep(dest);
}
break;
/* MD */
default:
break;
}
g_free(inp);
g_free(res);
g_free(out);
redraw_canvas(ALL);
return;
}
/***********************************************/
/* controls the use of GULP to optimise coords */
/***********************************************/
#define DEBUG_RUN_GULP 0
void gui_gulp_task(GtkWidget *w, struct model_pak *data)
{
/* checks */
g_return_if_fail(data != NULL);
if (!sysenv.gulp_path)
{
gui_text_show(ERROR, "GULP executable was not found.\n");
return;
}
#if DEBUG_RUN_GULP
printf("output file: %s\n", data->gulp.out_file);
#endif
task_new("Gulp", &exec_gulp_task, data, &proc_gulp_task, data, data);
}
/*************************/
/* GULP run type toggles */
/*************************/
void gulp_run_single(struct model_pak *data)
{
data->gulp.run = E_SINGLE;
}
void gulp_run_optimize(struct model_pak *data)
{
data->gulp.run = E_OPTIMIZE;
}
void gulp_run_dynamics(struct model_pak *data)
{
data->gulp.run = MD;
}
/************************/
/* GULP keyword toggles */
/************************/
gint cb_gulp_keyword(GtkWidget *w, gpointer *obj)
{
gint keyword;
struct model_pak *data;
keyword = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(obj), "key"));
data = (struct model_pak *) g_object_get_data(G_OBJECT(obj), "ptr");
g_return_val_if_fail(data != NULL, FALSE);
switch(keyword)
{
case NVE:
case NVT:
case NPT:
if (data->gulp.run != MD)
{
gui_text_show(WARNING, "Ignoring ensemble as it's not a dynamics run.\n");
return(TRUE);
}
data->gulp.ensemble = keyword;
break;
case CONP:
case CONV:
data->gulp.method = keyword;
break;
case BFGS_OPT:
case CONJ_OPT:
case RFO_OPT:
data->gulp.optimiser = keyword;
break;
case MOLE:
case MOLMEC:
case MOLQ:
case NOBUILD:
data->gulp.coulomb = keyword;
break;
case TEMP_FILE:
g_free(data->gulp.temp_file);
data->gulp.temp_file = g_strdup(gtk_entry_get_text(GTK_ENTRY(obj)));
parse_space_replace(data->gulp.temp_file,'_');
break;
case DUMP_FILE:
g_free(data->gulp.dump_file);
data->gulp.dump_file = g_strdup(gtk_entry_get_text(GTK_ENTRY(obj)));
parse_space_replace(data->gulp.dump_file,'_');
break;
case SBULK_ENERGY:
data->gulp.sbulkenergy = str_to_float(gtk_entry_get_text(GTK_ENTRY(obj)));
break;
}
return(FALSE);
}
/*******************************************************/
/* alternate event parser (overlap in optimiser stuff) */
/*******************************************************/
gint switch_keyword(GtkWidget *w, gpointer *obj)
{
gint keyword;
struct model_pak *data;
keyword = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(obj), "key"));
data = (struct model_pak *) g_object_get_data(G_OBJECT(obj), "ptr");
g_return_val_if_fail(data != NULL, FALSE);
switch(keyword)
{
case SWITCH_OFF:
case BFGS_OPT:
case CONJ_OPT:
case RFO_OPT:
data->gulp.optimiser2 = keyword;
break;
case CYCLE:
case GNORM:
data->gulp.switch_type = keyword;
break;
}
return(FALSE);
}
/*********************************/
/* change optimiser switch value */
/*********************************/
gint switch_value_changed(gpointer *entry)
{
struct model_pak *data;
/* retrieve the appropriate model */
g_return_val_if_fail(entry != NULL, FALSE);
data = (struct model_pak *) g_object_get_data(G_OBJECT(entry), "ptr");
g_return_val_if_fail(data != NULL, FALSE);
data->gulp.switch_value = str_to_float(gtk_entry_get_text(GTK_ENTRY(entry)));
return(FALSE);
}
/***********************************/
/* register structure name changes */
/***********************************/
void gulp_jobname_changed(GtkWidget *w, struct model_pak *model)
{
const gchar *text;
g_assert(w != NULL);
g_assert(model != NULL);
g_free(model->gulp.dump_file);
g_free(model->gulp.temp_file);
g_free(model->gulp.trj_file);
g_free(model->gulp.out_file);
text = gtk_entry_get_text(GTK_ENTRY(w));
model->gulp.temp_file = g_strdup_printf("%s.gin", text);
model->gulp.dump_file = g_strdup_printf("%s.res", text);
model->gulp.trj_file = g_strdup_printf("%s.trg", text);
model->gulp.out_file = g_strdup_printf("%s.got", text);
gui_relation_update_widget(&model->gulp.dump_file);
gui_relation_update_widget(&model->gulp.temp_file);
gui_relation_update_widget(&model->gulp.trj_file);
}
/**************************/
/* phonon scaling handler */
/**************************/
void phonon_scaling_changed(GtkWidget *w, gpointer *ptr)
{
sysenv.render.phonon_scaling = GTK_ADJUSTMENT(w)->value;
}
#define DEBUG_PHONON_DISPLAY 0
/************************************/
/* vibrational mode display handler */
/************************************/
void phonon_mode_hide(GtkWidget *w, struct model_pak *model)
{
spatial_destroy_by_label("phonons", model);
redraw_canvas(SINGLE);
}
/************************************/
/* vibrational mode display handler */
/************************************/
void phonon_mode_show(GtkWidget *w, struct model_pak *data)
{
gdouble x1[3], x2[3], colour[3];
GSList *list, *xlist, *ylist, *zlist;
gpointer *freq;
struct spatial_pak *spatial;
struct core_pak *core, *prim;
/* get rid of previous phonon objects */
spatial_destroy_by_label("phonons", data);
VEC3SET(colour, 0.0, 1.0, 0.0);
/* find and display current */
freq = g_slist_nth_data(data->phonons, data->current_phonon-1);
if (freq)
{
/* create & init the spatial object */
spatial = spatial_new("phonons", SPATIAL_VECTOR, 2, TRUE, data);
/* get eigenvectors from all atoms */
for (list=data->cores ; list; list=g_slist_next(list))
{
core = list->data;
ARR3SET(x1, core->x);
/* get eigenvector list */
if (core->primary)
{
xlist = core->vibx_list;
ylist = core->viby_list;
zlist = core->vibz_list;
}
else
{
prim = core->primary_core;
xlist = prim->vibx_list;
ylist = prim->viby_list;
zlist = prim->vibz_list;
}
g_assert(xlist != NULL);
g_assert(ylist != NULL);
g_assert(zlist != NULL);
/* get current eigenvector */
x2[0] = *((gdouble *) g_slist_nth_data(xlist, data->current_phonon-1));
x2[1] = *((gdouble *) g_slist_nth_data(ylist, data->current_phonon-1));
x2[2] = *((gdouble *) g_slist_nth_data(zlist, data->current_phonon-1));
#if DEBUG_PHONON_DISPLAY
P3VEC("vec: ", x2);
#endif
/* compute coords */
VEC3MUL(x2, sysenv.render.phonon_scaling);
vecmat(data->ilatmat, x2);
ARR3ADD(x2, x1);
/* add to spatial */
spatial_vertex_add(x2, colour, spatial);
spatial_vertex_add(x1, colour, spatial);
}
/* drawing update */
coords_compute(data);
redraw_canvas(SINGLE);
}
}
/********************************/
/* eigenvector show/hide toggle */
/********************************/
void phonon_mode_toggle(GtkWidget *w, struct model_pak *model)
{
if (model->show_eigenvectors)
phonon_mode_show(w, model);
else
phonon_mode_hide(w, model);
}
/***********************************/
/* cleanup a vibrational animation */
/***********************************/
void phonon_timeout_cleanup(struct model_pak *model)
{
GSList *list;
struct core_pak *core;
g_assert(model != NULL);
for (list=model->cores ; list; list=g_slist_next(list))
{
core = list->data;
VEC3SET(core->offset, 0.0, 0.0, 0.0);
}
}
/************************************/
/* timeout to control the animation */
/************************************/
/* NB: lots of sanity checks that return with FALSE (ie stop timeout) */
/* so if the model is deleted during an animation we don't segfault */
#define MAX_PULSE_COUNT 10.0
gint phonon_mode_timeout(struct model_pak *model)
{
static gint count=0;
gdouble f;
gchar *name, *text;
gpointer ptr;
GSList *list, *xlist, *ylist, *zlist;
struct core_pak *core, *prim;
/* checks */
g_assert(model != NULL);
ptr = g_slist_nth_data(model->phonons, model->current_phonon-1);
if (!ptr)
{
phonon_timeout_cleanup(model);
return(FALSE);
}
if (!model->pulse_direction)
return(FALSE);
/* setup scaling for this step */
model->pulse_count += model->pulse_direction;
if (model->pulse_count <= -model->pulse_max)
{
model->pulse_count = -model->pulse_max;
model->pulse_direction = 1;
}
if (model->pulse_count >= model->pulse_max)
{
model->pulse_count = model->pulse_max;
model->pulse_direction = -1;
}
f = sysenv.render.phonon_scaling;
f *= (gdouble) model->pulse_count;
f /= model->pulse_max;
/* get eigenvectors from all atoms */
for (list=model->cores ; list; list=g_slist_next(list))
{
core = list->data;
/* get eigenvector list */
if (core->primary)
{
xlist = core->vibx_list;
ylist = core->viby_list;
zlist = core->vibz_list;
}
else
{
prim = core->primary_core;
xlist = prim->vibx_list;
ylist = prim->viby_list;
zlist = prim->vibz_list;
}
g_assert(xlist != NULL);
g_assert(ylist != NULL);
g_assert(zlist != NULL);
/* vibrational eigenvector */
ptr = g_slist_nth_data(xlist, model->current_phonon-1);
if (!ptr)
{
phonon_timeout_cleanup(model);
return(FALSE);
}
core->offset[0] = *((gdouble *) ptr);
ptr = g_slist_nth_data(ylist, model->current_phonon-1);
if (!ptr)
{
phonon_timeout_cleanup(model);
return(FALSE);
}
core->offset[1] = *((gdouble *) ptr);
ptr = g_slist_nth_data(zlist, model->current_phonon-1);
if (!ptr)
{
phonon_timeout_cleanup(model);
return(FALSE);
}
core->offset[2] = *((gdouble *) ptr);
/* pulse offset scaling */
VEC3MUL(core->offset, f);
vecmat(model->ilatmat, core->offset);
/* TODO - shell also? */
}
/* recalc coords */
coords_compute(model);
/* CURRENT - output to povray for movie rendering */
if (model->phonon_movie)
{
if (!model->pulse_count && model->pulse_direction==1)
{
model->phonon_movie = FALSE;
count=0;
text = g_strdup_printf("%s -delay 20 %s_*.tga %s.gif", sysenv.convert_path,
model->phonon_movie_name, model->phonon_movie_name);
system(text);
g_free(text);
return(FALSE);
}
else
{
text = g_strdup_printf("%s_%06d.pov", model->phonon_movie_name, count++);
name = g_build_filename(sysenv.cwd, text, NULL);
write_povray(name, model);
povray_exec(name);
g_free(text);
g_free(name);
}
}
else
redraw_canvas(SINGLE);
return(TRUE);
}
/****************************/
/* animate the current mode */
/****************************/
void phonon_mode_animate(GtkWidget *w, struct model_pak *model)
{
g_assert(model != NULL);
model->pulse_count = 0;
model->pulse_direction = 1;
g_timeout_add(100, (GSourceFunc) phonon_mode_timeout, model);
}
/****************************/
/* create a movie of the current mode */
/****************************/
void phonon_mode_movie(GtkWidget *w, struct model_pak *model)
{
g_assert(model != NULL);
model->phonon_movie = TRUE;
phonon_mode_animate(NULL, model);
}
/******************************/
/* stop phonon mode animation */
/*****************************/
void phonon_mode_stop(GtkWidget *w, struct model_pak *model)
{
/* reset */
model->pulse_direction = 0;
model->pulse_count = 0;
phonon_timeout_cleanup(model);
/* redraw */
coords_compute(model);
redraw_canvas(SINGLE);
}
/*********************************/
/* phonon slider changed updates */
/*********************************/
void update_phonon_frequency(GtkWidget *w, struct model_pak *model)
{
gpointer freq, ir, raman;
g_assert(model != NULL);
freq = g_slist_nth_data(model->phonons, model->current_phonon-1);
if (freq)
{
ir = g_slist_nth_data(model->ir_list, model->current_phonon-1);
raman = g_slist_nth_data(model->raman_list, model->current_phonon-1);
/* update displayed frequency */
gtk_entry_set_text(GTK_ENTRY(phonon_freq), (gchar *) freq);
gtk_entry_set_text(GTK_ENTRY(phonon_ir), (gchar *) ir);
gtk_entry_set_text(GTK_ENTRY(phonon_raman), (gchar *) raman);
/* update displayed vectors */
if (model->show_eigenvectors)
{
phonon_mode_hide(NULL, model);
phonon_mode_show(NULL, model);
}
}
}
/*****************************/
/* phonon intensity plotting */
/*****************************/
void phonon_graph(GSList *mode, struct model_pak *model)
{
gint n;
gdouble *spectrum;
gpointer graph;
GSList *list;
g_assert(model != NULL);
spectrum = g_malloc(model->num_phonons * sizeof(gdouble));
/* extract data into array */
n=0;
for (list=mode ; list ; list=g_slist_next(list))
{
g_assert(n < model->num_phonons);
spectrum[n] = str_to_float(list->data);
n++;
}
/* create a new graph */
if (mode == model->ir_list)
graph = graph_new("IR spectrum", model);
else
graph = graph_new("Raman spectrum", model);
graph_add_data(model->num_phonons, spectrum, 1, model->num_phonons, graph);
graph_set_yticks(FALSE, 2, graph);
tree_model_add(model);
g_free(spectrum);
}
/***************************************/
/* phonon intensity plotting callbacks */
/***************************************/
void cb_graph_ir(GtkWidget *w, struct model_pak *model)
{
g_assert(model != NULL);
phonon_graph(model->ir_list, model);
}
void cb_graph_raman(GtkWidget *w, struct model_pak *model)
{
g_assert(model != NULL);
phonon_graph(model->raman_list, model);
}
/* CURRENT - invoke test module */
/*
void phonon_module_invoke(void)
{
struct model_pak *model;
model = sysenv.active_model;
module_function_invoke("test", model);
}
*/
/*******************************/
/* decrement current frequency */
/*******************************/
void phonon_mode_prev(GtkWidget *w, struct model_pak *model)
{
if (model->current_phonon > 1)
model->current_phonon--;
gtk_range_set_value(GTK_RANGE(model->phonon_slider),
(gdouble) model->current_phonon);
}
/*******************************/
/* increment current frequency */
/*******************************/
void phonon_mode_next(GtkWidget *w, struct model_pak *model)
{
if (model->current_phonon < model->num_phonons)
model->current_phonon++;
gtk_range_set_value(GTK_RANGE(model->phonon_slider),
(gdouble) model->current_phonon);
}
/****************/
/* phonon page */
/****************/
void gulp_phonon_box(GtkWidget *box, struct model_pak *data)
{
GtkWidget *swin, *table, *frame, *hbox, *hbox2, *vbox, *label;
hbox = gtk_hbox_new(FALSE, 0);
gtk_box_pack_start(GTK_BOX(box), hbox, TRUE, TRUE, 0);
gtk_container_set_border_width(GTK_CONTAINER(hbox), PANEL_SPACING);
frame = gtk_frame_new(NULL);
gtk_box_pack_start(GTK_BOX(hbox), frame, FALSE, FALSE, 0);
vbox = gtk_vbox_new(FALSE, 0);
gtk_container_add(GTK_CONTAINER(frame), vbox);
hbox2 = gtk_hbox_new(FALSE, 0);
gtk_box_pack_start(GTK_BOX(vbox), hbox2, FALSE, FALSE, 0);
gui_direct_check("Compute vibrational modes", &data->gulp.phonon, NULL, NULL, hbox2);
hbox2 = gtk_hbox_new(FALSE, 0);
gtk_box_pack_start(GTK_BOX(vbox), hbox2, FALSE, FALSE, 0);
gui_direct_check("Compute eigenvectors", &data->gulp.eigen, NULL, NULL, hbox2);
if (data->periodic)
{
frame = gtk_frame_new("kpoints");
gtk_box_pack_end(GTK_BOX(hbox), frame, TRUE, TRUE, PANEL_SPACING);
swin = gui_text_window(&data->gulp.kpoints, TRUE);
gtk_container_add(GTK_CONTAINER(frame), swin);
}
/* phonon slide selector */
frame = gtk_frame_new("Eigenvectors");
gtk_box_pack_start(GTK_BOX(box), frame, FALSE, FALSE, 0);
gtk_container_set_border_width(GTK_CONTAINER(frame), PANEL_SPACING);
vbox = gtk_vbox_new(FALSE, PANEL_SPACING);
gtk_container_add(GTK_CONTAINER(frame), vbox);
hbox = gtk_hbox_new(FALSE, 0);
gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0);
label = gtk_label_new("Number ");
gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0);
data->phonon_slider = gui_direct_hscale(0, 1, 1, &data->current_phonon,
update_phonon_frequency, data, hbox);
/* CURRENT */
gui_button(" < ", phonon_mode_prev, data, hbox, FF);
gui_button(" > ", phonon_mode_next, data, hbox, FF);
/* phonon info */
table = gtk_table_new(2, 3, TRUE);
gtk_box_pack_start(GTK_BOX(vbox), table, TRUE, TRUE, 0);
label = gtk_label_new("Frequency");
gtk_table_attach_defaults(GTK_TABLE(table), label, 0, 1, 0, 1);
label = gui_button("IR intensity", cb_graph_ir, data, NULL, 0);
gtk_table_attach_defaults(GTK_TABLE(table), label, 1, 2, 0, 1);
label = gui_button("Raman intensity", cb_graph_raman, data, NULL, 0);
gtk_table_attach_defaults(GTK_TABLE(table), label, 2, 3, 0, 1);
phonon_freq = gtk_entry_new_with_max_length(LINELEN);
gtk_entry_set_text(GTK_ENTRY(phonon_freq), " ");
gtk_entry_set_editable(GTK_ENTRY(phonon_freq), FALSE);
gtk_table_attach_defaults(GTK_TABLE(table), phonon_freq, 0, 1, 1, 2);
phonon_ir = gtk_entry_new_with_max_length(LINELEN);
gtk_entry_set_text(GTK_ENTRY(phonon_ir), " ");
gtk_entry_set_editable(GTK_ENTRY(phonon_ir), FALSE);
gtk_table_attach_defaults(GTK_TABLE(table), phonon_ir, 1, 2, 1, 2);
phonon_raman = gtk_entry_new_with_max_length(LINELEN);
gtk_entry_set_text(GTK_ENTRY(phonon_raman), " ");
gtk_entry_set_editable(GTK_ENTRY(phonon_raman), FALSE);
gtk_table_attach_defaults(GTK_TABLE(table), phonon_raman, 2, 3, 1, 2);
gui_direct_check("Display Eigenvectors", &data->show_eigenvectors,
phonon_mode_toggle, data, vbox);
gui_direct_spin("Eigenvector scaling", &sysenv.render.phonon_scaling,
0.1, 9.9, 0.1, update_phonon_frequency, data, vbox);
gui_direct_spin("Animation resolution", &data->pulse_max,
10.0, 100.0, 1.0, NULL, NULL, vbox);
/* animation */
hbox2 = gtk_hbox_new(FALSE, 0);
gtk_box_pack_start(GTK_BOX(vbox), hbox2, TRUE, FALSE, 0);
gui_text_entry(NULL, &data->phonon_movie_name, TRUE, FALSE, hbox2);
hbox = gtk_hbox_new(TRUE, PANEL_SPACING);
gtk_box_pack_end(GTK_BOX(hbox2), hbox, FALSE, FALSE, 0);
gui_icon_button("image_camera", NULL, phonon_mode_movie, (gpointer) data, hbox);
gui_icon_button("GDIS_PLAY", NULL,
phonon_mode_animate, (gpointer) data, hbox);
gui_icon_button("GDIS_STOP", NULL, phonon_mode_stop, (gpointer) data, hbox);
gtk_widget_show_all(box);
update_phonon_range(data);
}
/*********************************************/
/* read in solvent accessible surface points */
/*********************************************/
/* TODO - put elsewhere? */
void gulp_cosmic_read(gchar *filename, struct model_pak *model)
{
gint i, n=0, dim, expect=-1, num_tokens;
gchar **buff;
gdouble x[3], colour[3];
gpointer scan, spatial;
g_assert(filename != NULL);
g_assert(model != NULL);
VEC3SET(colour, 0.0, 1.0, 0.0);
n=0;
scan = scan_new(filename);
if (!scan)
return;
/* header */
buff = scan_get_tokens(scan, &num_tokens);
if (num_tokens == 1)
expect = str_to_float(*buff);
/* new GULP version - dimension + cell vectors */
buff = scan_get_tokens(scan, &num_tokens);
if (num_tokens == 1)
{
dim = str_to_float(*buff);
g_strfreev(buff);
/* TODO - process cell vectors */
for (i=dim ; i-- ; )
{
buff = scan_get_tokens(scan, &num_tokens);
g_strfreev(buff);
}
}
else
scan_put_line(scan);
/* body */
while (!scan_complete(scan))
{
buff = scan_get_tokens(scan, &num_tokens);
if (num_tokens == 6)
{
/* coordinates */
x[0] = str_to_float(*(buff+2));
x[1] = str_to_float(*(buff+3));
x[2] = str_to_float(*(buff+4));
vecmat(model->ilatmat, x);
/* add a new point */
spatial = spatial_new("SAS", SPATIAL_GENERIC, 1, TRUE, model);
spatial_vertex_add(x, colour, spatial);
n++;
}
else
break;
g_strfreev(buff);
}
/*
printf("points: %d / %d\n", n, expect);
*/
scan_free(scan);
}
void gulp_cosmic_display(GtkWidget *w, struct model_pak *model)
{
gchar *name;
name = parse_extension_set(model->filename, "sas");
/*
printf("cosmic: %s\n", name);
*/
gulp_cosmic_read(name, model);
/* updates */
coords_init(CENT_COORDS, model);
redraw_canvas(SINGLE);
g_free(name);
}
/*************************************/
/* set COSMO widget sensitive status */
/*************************************/
void gulp_cosmo_panel_refresh(GtkWidget *w, gpointer dialog)
{
gchar *text;
GtkWidget *box;
GtkEntry *solvation;
struct model_pak *model;
box = dialog_child_get(dialog, "cosmo_box");
g_assert(box != NULL);
model = dialog_model(dialog);
g_assert(model != NULL);
solvation = dialog_child_get(dialog, "solvation_model");
text = gui_pd_text(solvation);
if (g_ascii_strncasecmp(text, "none", 4) == 0)
{
gtk_widget_set_sensitive(box, FALSE);
model->gulp.solvation_model = GULP_SOLVATION_NONE;
}
if (g_ascii_strncasecmp(text, "cosmo", 5) == 0)
{
gtk_widget_set_sensitive(box, TRUE);
model->gulp.solvation_model = GULP_SOLVATION_COSMO;
}
if (g_ascii_strncasecmp(text, "cosmic", 6) == 0)
{
gtk_widget_set_sensitive(box, TRUE);
model->gulp.solvation_model = GULP_SOLVATION_COSMIC;
}
g_free(text);
}
/********************************************/
/* calculate points for a COSMO calculation */
/********************************************/
gint gulp_cosmo_points(gint shape, gint k, gint l)
{
gint points;
if (shape)
points = 2 + 10 * pow(3, k) * pow(4, l);
else
points = 2 + 4 * pow(3, k) * pow(4, l);
return(points);
}
/********************************************/
/* update points for a COSMO calculation */
/********************************************/
void gulp_cosmo_points_refresh(GtkWidget *w, gpointer dialog)
{
gint k, l;
gchar *text;
GtkLabel *label;
GtkSpinButton *spin;
GtkEntry *shape;
struct model_pak *model;
model = dialog_model(dialog);
g_assert(model != NULL);
shape = dialog_child_get(dialog, "cosmo_shape");
if (g_ascii_strncasecmp(gtk_entry_get_text(shape), "dodec", 5) == 0)
model->gulp.cosmo_shape = 1;
else
model->gulp.cosmo_shape = 0;
spin = dialog_child_get(dialog, "cosmo_index_k");
k = SPIN_IVAL(spin);
spin = dialog_child_get(dialog, "cosmo_index_l");
l = SPIN_IVAL(spin);
model->gulp.cosmo_points = gulp_cosmo_points(model->gulp.cosmo_shape, k, l);
label = dialog_child_get(dialog, "cosmo_points");
g_assert(label != NULL);
text = g_strdup_printf("%6d", model->gulp.cosmo_points);
gtk_label_set_text(label, text);
g_free(text);
/* CURRENT - enforce segments <= points */
spin = dialog_child_get(dialog, "cosmo_segments");
g_assert(spin != NULL);
gtk_spin_button_set_range(spin, 1.0, (gdouble) model->gulp.cosmo_points);
}
/*******************************************/
/* update segments for a COSMO calculation */
/*******************************************/
void gulp_cosmo_segments_refresh(GtkSpinButton *w, gpointer dialog)
{
struct model_pak *model;
model = dialog_model(dialog);
g_assert(model != NULL);
model->gulp.cosmo_segments = SPIN_IVAL(w);
}
/**************************************************/
/* toggle solvent accessible surface (SAS) output */
/**************************************************/
void gulp_cosmo_sas_toggle(GtkWidget *w, gpointer data)
{
struct model_pak *model = data;
g_assert(model != NULL);
if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(w)))
model->gulp.cosmo_sas = TRUE;
else
model->gulp.cosmo_sas = FALSE;
}
/*********************************************************/
/* options for displaying the solvent accessible surface */
/*********************************************************/
void gulp_solvation_box(GtkWidget *box, gpointer dialog)
{
gint active;
GSList *slist;
GList *list=NULL;
gpointer cosmo, ptr;
GtkWidget *hbox, *vbox, *vbox2, *label, *shape_k, *shape_l, *segments;
struct model_pak *model;
model = dialog_model(dialog);
g_assert(model != NULL);
hbox = gtk_hbox_new(FALSE, 0);
gtk_box_pack_start(GTK_BOX(box), hbox, FALSE, FALSE, 0);
gtk_container_set_border_width(GTK_CONTAINER(hbox), PANEL_SPACING);
vbox = gtk_vbox_new(FALSE, PANEL_SPACING);
gtk_box_pack_start(GTK_BOX(hbox), vbox, FALSE, FALSE, 0);
gtk_container_set_border_width(GTK_CONTAINER(vbox), PANEL_SPACING);
vbox2 = gtk_vbox_new(FALSE, PANEL_SPACING);
gtk_box_pack_end(GTK_BOX(vbox), vbox2, TRUE, TRUE, 0);
dialog_child_set(dialog, "cosmo_box", vbox2);
/*
cosmo = new_check_button("COSMO calculation ", gulp_cosmo_panel_refresh, dialog,
model->gulp.cosmo, vbox);
*/
switch(model->gulp.solvation_model)
{
case GULP_SOLVATION_COSMIC:
active = 1;
break;
case GULP_SOLVATION_COSMO:
active = 2;
break;
default:
active = 0;
}
/* FIXME - pulldown needs a way to initialize */
slist = NULL;
slist = g_slist_append(slist, "None");
slist = g_slist_append(slist, "COSMIC");
slist = g_slist_append(slist, "COSMO");
cosmo = gui_pd_new(slist, active, gulp_cosmo_panel_refresh, dialog);
gui_hbox_pack(vbox, "Solvation model ", cosmo, 0);
dialog_child_set(dialog, "solvation_model", cosmo);
g_slist_free(slist);
/* solvent parameters */
gui_direct_spin("Solvent epsilon ", &model->gulp.cosmo_solvent_epsilon,
1.0, 1000.0, 0.1, NULL, NULL, vbox2);
gui_direct_spin("Solvent radius ", &model->gulp.cosmo_solvent_radius,
0.1, 9.9, 0.1, NULL, NULL, vbox2);
gui_direct_spin("Solvent delta ", &model->gulp.cosmo_solvent_delta,
0.1, 9.9, 0.1, NULL, NULL, vbox2);
gui_direct_spin("Solvent rmax ", &model->gulp.cosmo_solvent_rmax,
1.0, 99.0, 1.0, NULL, NULL, vbox2);
gui_direct_spin("Smoothing ", &model->gulp.cosmo_smoothing,
0.0, 2.0, 0.1, NULL, NULL, vbox2);
/* solvent surface construction geometry */
list = NULL;
if (model->gulp.cosmo_shape)
{
list = g_list_append(list, "Dodecahedron");
list = g_list_append(list, "Octahedron");
}
else
{
list = g_list_append(list, "Octahedron");
list = g_list_append(list, "Dodecahedron");
}
ptr = gui_pulldown_new("Shape approximation ", list, FALSE, vbox2);
g_signal_connect(GTK_OBJECT(ptr), "changed",
GTK_SIGNAL_FUNC(gulp_cosmo_points_refresh), dialog);
dialog_child_set(dialog, "cosmo_shape", ptr);
g_list_free(list);
hbox = gtk_hbox_new(FALSE, 0);
gtk_box_pack_start(GTK_BOX(vbox2), hbox, FALSE, FALSE, 0);
shape_k = new_spinner("Shape indices ", 0, 99, 1, gulp_cosmo_points_refresh, dialog, hbox);
shape_l = new_spinner(NULL, 0, 99, 1, gulp_cosmo_points_refresh, dialog, hbox);
dialog_child_set(dialog, "cosmo_index_k", shape_k);
dialog_child_set(dialog, "cosmo_index_l", shape_l);
hbox = gtk_hbox_new(FALSE, 0);
gtk_box_pack_start(GTK_BOX(vbox2), hbox, FALSE, FALSE, 0);
label = gtk_label_new("Points per atom ");
gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0);
label = gtk_label_new("?");
gtk_box_pack_end(GTK_BOX(hbox), label, FALSE, FALSE, 0);
dialog_child_set(dialog, "cosmo_points", label);
/* CURRENT */
hbox = gtk_hbox_new(FALSE, 0);
gtk_box_pack_start(GTK_BOX(vbox2), hbox, FALSE, FALSE, 0);
segments = new_spinner("Segments per atom ", 1, model->gulp.cosmo_points, 1,
gulp_cosmo_segments_refresh, dialog, hbox);
dialog_child_set(dialog, "cosmo_segments", segments);
/* solvent surface */
new_check_button("Output SAS points ", gulp_cosmo_sas_toggle, model,
model->gulp.cosmo_sas, vbox2);
gui_button_x("Visualize SAS points ", gulp_cosmic_display, model, vbox2);
/* initialize values */
gtk_spin_button_set_value(GTK_SPIN_BUTTON(shape_k), model->gulp.cosmo_shape_index[0]);
gtk_spin_button_set_value(GTK_SPIN_BUTTON(shape_l), model->gulp.cosmo_shape_index[1]);
gtk_spin_button_set_value(GTK_SPIN_BUTTON(segments), model->gulp.cosmo_segments);
gulp_cosmo_points_refresh(NULL, dialog);
gulp_cosmo_panel_refresh(cosmo, dialog);
gtk_widget_show_all(box);
}
/*******************************/
/* GULP job setup/results page */
/*******************************/
void gui_gulp_widget(GtkWidget *box, gpointer dialog)
{
gchar *text;
GSList *keyword[5];
GString *line;
GtkWidget *hbox, *vbox, *vbox1, *vbox2, *page, *swin;
GtkWidget *frame, *button, *label, *entry, *notebook;
struct model_pak *model;
model = dialog_model(dialog);
g_assert(model != NULL);
/* string manipulation scratchpad */
line = g_string_new(NULL);
/* create notebook */
notebook = gtk_notebook_new();
gtk_notebook_set_tab_pos(GTK_NOTEBOOK(notebook), GTK_POS_TOP);
gtk_container_add(GTK_CONTAINER(box), notebook);
gtk_notebook_set_show_border(GTK_NOTEBOOK(notebook), FALSE);
/* run type page */
page = gtk_vbox_new(FALSE, 0);
label = gtk_label_new (" Control ");
gtk_notebook_append_page(GTK_NOTEBOOK(notebook), page, label);
hbox = gtk_hbox_new(FALSE, 0);
gtk_container_add(GTK_CONTAINER(page), hbox);
/* split panel */
vbox1 = gtk_vbox_new(FALSE, 0);
gtk_box_pack_start(GTK_BOX(hbox), vbox1, TRUE, TRUE, 0);
vbox2 = gtk_vbox_new(FALSE, 0);
gtk_box_pack_start(GTK_BOX(hbox), vbox2, TRUE, TRUE, 0);
/* frame */
frame = gtk_frame_new("Run type");
gtk_box_pack_start(GTK_BOX(vbox1), frame, FALSE, FALSE, 0);
gtk_container_set_border_width(GTK_CONTAINER(frame), PANEL_SPACING/2);
vbox = gtk_vbox_new(TRUE, 0);
gtk_container_add(GTK_CONTAINER(frame), vbox);
/* do the radio buttons */
new_radio_group(0, vbox, TT);
button = add_radio_button("Single point", (gpointer) gulp_run_single, model);
if (model->gulp.run == E_SINGLE)
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(button), TRUE);
button = add_radio_button("Optimise", (gpointer) gulp_run_optimize, model);
if (model->gulp.run == E_OPTIMIZE)
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(button), TRUE);
button = add_radio_button("Dynamics", (gpointer) gulp_run_dynamics, model);
if (model->gulp.run == MD)
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(button), TRUE);
/* method constraint */
frame = gtk_frame_new(" Constraint ");
gtk_box_pack_start(GTK_BOX(vbox1), frame, FALSE, FALSE, 0);
gtk_container_set_border_width(GTK_CONTAINER(frame), PANEL_SPACING/2);
vbox = gtk_vbox_new(TRUE, 0);
gtk_container_add(GTK_CONTAINER(frame),vbox);
/* do the first (DEFAULT MODE) radio button */
button = gtk_radio_button_new_with_label(NULL, "Constant pressure");
gtk_box_pack_start (GTK_BOX (vbox), button, TRUE, TRUE, 0);
g_signal_connect(GTK_OBJECT(button), "clicked",
GTK_SIGNAL_FUNC (cb_gulp_keyword), (gpointer) button);
g_object_set_data(G_OBJECT(button), "key", (gpointer) CONP);
g_object_set_data(G_OBJECT(button), "ptr", (gpointer) model);
if (model->gulp.method == CONP)
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(button), TRUE);
/* make a radio group */
keyword[1] = gtk_radio_button_group(GTK_RADIO_BUTTON (button));
/* do the next button */
button = gtk_radio_button_new_with_label (keyword[1], "Constant volume");
gtk_box_pack_start(GTK_BOX (vbox), button, TRUE, TRUE, 0);
g_signal_connect(GTK_OBJECT(button), "clicked",
GTK_SIGNAL_FUNC (cb_gulp_keyword), (gpointer) button);
g_object_set_data(G_OBJECT(button), "key", (gpointer) CONV);
g_object_set_data(G_OBJECT(button), "ptr", (gpointer) model);
if (model->gulp.method == CONV)
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(button), TRUE);
/* frame */
frame = gtk_frame_new(" Molecule options ");
gtk_box_pack_start(GTK_BOX(vbox1), frame, FALSE, FALSE, 0);
gtk_container_set_border_width(GTK_CONTAINER(frame), PANEL_SPACING/2);
vbox = gtk_vbox_new(TRUE, 0);
gtk_container_add(GTK_CONTAINER(frame),vbox);
/* do the first radio button */
button = gtk_radio_button_new_with_label(NULL,
"Coulomb subtract all intramolecular");
gtk_box_pack_start (GTK_BOX (vbox), button, TRUE, TRUE, 0);
g_signal_connect(GTK_OBJECT (button), "clicked",
GTK_SIGNAL_FUNC (cb_gulp_keyword), (gpointer) button);
g_object_set_data(G_OBJECT(button), "key", (gpointer) MOLE);
g_object_set_data(G_OBJECT(button), "ptr", (gpointer) model);
if (model->gulp.coulomb == MOLE)
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(button), TRUE);
/* make a radio group */
keyword[2] = gtk_radio_button_group(GTK_RADIO_BUTTON (button));
/* do the next button */
button = gtk_radio_button_new_with_label(keyword[2],
"Coulomb subtract 1-2 and 1-3 intramolecular");
gtk_box_pack_start (GTK_BOX (vbox), button, TRUE, TRUE, 0);
g_signal_connect(GTK_OBJECT(button), "clicked",
GTK_SIGNAL_FUNC(cb_gulp_keyword), (gpointer) button);
g_object_set_data(G_OBJECT(button), "key", (gpointer) MOLMEC);
g_object_set_data(G_OBJECT(button), "ptr", (gpointer) model);
if (model->gulp.coulomb == MOLMEC)
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(button), TRUE);
/* subsequent button... */
button = gtk_radio_button_new_with_label(gtk_radio_button_group
(GTK_RADIO_BUTTON (button)), "Build, but retain coulomb interactions");
gtk_box_pack_start(GTK_BOX (vbox), button, TRUE, TRUE, 0);
g_signal_connect(GTK_OBJECT (button), "clicked",
GTK_SIGNAL_FUNC (cb_gulp_keyword), (gpointer) button);
g_object_set_data(G_OBJECT(button), "key", (gpointer) MOLQ);
g_object_set_data(G_OBJECT(button), "ptr", (gpointer) model);
if (model->gulp.coulomb == MOLQ)
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(button), TRUE);
/* subsequent button... */
button = gtk_radio_button_new_with_label(gtk_radio_button_group
(GTK_RADIO_BUTTON (button)), "Molecule building off");
gtk_box_pack_start(GTK_BOX (vbox), button, TRUE, TRUE, 0);
g_signal_connect(GTK_OBJECT (button), "clicked",
GTK_SIGNAL_FUNC (cb_gulp_keyword), (gpointer) button);
g_object_set_data(G_OBJECT(button), "key", (gpointer) NOBUILD);
g_object_set_data(G_OBJECT(button), "ptr", (gpointer) model);
if (model->gulp.coulomb == NOBUILD)
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(button), TRUE);
gui_direct_check("Fix the initial connectivity", &model->gulp.fix, NULL, NULL, vbox);
/* temperature & pressure */
frame = gtk_frame_new(NULL);
gtk_box_pack_start(GTK_BOX(vbox1), frame, FALSE, FALSE, 0);
gtk_container_set_border_width(GTK_CONTAINER(frame), PANEL_SPACING/2);
vbox = gtk_vbox_new(TRUE, 0);
gtk_container_add(GTK_CONTAINER(frame),vbox);
gui_text_entry("Temperature", &model->gulp.temperature, TRUE, FALSE, vbox);
gui_text_entry("Pressure", &model->gulp.pressure, TRUE, FALSE, vbox);
/* dynamics ensemble */
frame = gtk_frame_new("Dynamics");
gtk_box_pack_start(GTK_BOX(vbox2), frame, FALSE, FALSE, 0);
gtk_container_set_border_width(GTK_CONTAINER(frame), PANEL_SPACING/2);
vbox = gtk_vbox_new(TRUE, 0);
gtk_container_add(GTK_CONTAINER(frame),vbox);
/* do the first (DEFAULT MODE) radio button */
button = gtk_radio_button_new_with_label(NULL, "NVE");
gtk_box_pack_start(GTK_BOX(vbox), button, TRUE, TRUE, 0);
g_signal_connect(GTK_OBJECT(button), "clicked",
GTK_SIGNAL_FUNC (cb_gulp_keyword), (gpointer) button);
g_object_set_data(G_OBJECT(button), "key", (gpointer) NVE);
g_object_set_data(G_OBJECT(button), "ptr", (gpointer) model);
if (model->gulp.ensemble == NVE)
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(button), TRUE);
/* make a radio group */
keyword[1] = gtk_radio_button_group(GTK_RADIO_BUTTON (button));
/* do the next button */
button = gtk_radio_button_new_with_label (keyword[1], "NVT");
gtk_box_pack_start(GTK_BOX(vbox), button, TRUE, TRUE, 0);
g_signal_connect(GTK_OBJECT(button), "clicked",
GTK_SIGNAL_FUNC(cb_gulp_keyword), (gpointer) button);
g_object_set_data(G_OBJECT(button), "key", (gpointer) NVT);
g_object_set_data(G_OBJECT(button), "ptr", (gpointer) model);
/* NEW */
if (model->gulp.ensemble == NVT)
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(button), TRUE);
/* subsequent button... */
button = gtk_radio_button_new_with_label(gtk_radio_button_group
(GTK_RADIO_BUTTON (button)), "NPT");
gtk_box_pack_start(GTK_BOX(vbox), button, TRUE, TRUE, 0);
g_signal_connect(GTK_OBJECT(button), "clicked",
GTK_SIGNAL_FUNC (cb_gulp_keyword), (gpointer) button);
g_object_set_data(G_OBJECT(button), "key", (gpointer) NPT);
g_object_set_data(G_OBJECT(button), "ptr", (gpointer) model);
if (model->gulp.ensemble == NPT)
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(button), TRUE);
/* dynamics sampling */
gtk_box_pack_start(GTK_BOX(vbox), gtk_hseparator_new(), FALSE, FALSE, 0);
gui_text_entry("Timestep", &model->gulp.timestep, TRUE, FALSE, vbox);
gui_text_entry("Equilibration ", &model->gulp.equilibration, TRUE, FALSE, vbox);
gui_text_entry("Production", &model->gulp.production, TRUE, FALSE, vbox);
gui_text_entry("Sample", &model->gulp.sample, TRUE, FALSE, vbox);
gui_text_entry("Write", &model->gulp.write, TRUE, FALSE, vbox);
/* frame for keyword toggles */
frame = gtk_frame_new(NULL);
gtk_box_pack_start(GTK_BOX(vbox2), frame, FALSE, FALSE, 0);
gtk_container_set_border_width(GTK_CONTAINER(frame), PANEL_SPACING/2);
vbox = gtk_vbox_new(TRUE, 0);
gtk_container_add(GTK_CONTAINER(frame), vbox);
gui_direct_check("Create input file then stop", &model->gulp.no_exec, NULL, NULL, vbox);
gui_direct_check("Build cell, then discard symmetry", &model->gulp.nosym, NULL, NULL, vbox);
gui_direct_check("No attachment energy calculation", &model->gulp.no_eatt, NULL, NULL, vbox);
gui_direct_check("QEq Electronegativity equalisation", &model->gulp.qeq, NULL, NULL, vbox);
/* NEW - text box for GULP control files */
hbox = gtk_hbox_new(FALSE,0);
label = gtk_label_new(" Files ");
gtk_notebook_append_page(GTK_NOTEBOOK(notebook), hbox, label);
vbox = gtk_vbox_new(FALSE,0);
gtk_box_pack_start(GTK_BOX(hbox), vbox, FALSE, FALSE, 0);
frame = gtk_frame_new(NULL);
gtk_box_pack_start(GTK_BOX(vbox), frame, FALSE, FALSE, 0);
gtk_container_set_border_width(GTK_CONTAINER(frame), PANEL_SPACING);
vbox = gtk_vbox_new(FALSE, PANEL_SPACING/2);
gtk_container_add(GTK_CONTAINER(frame), vbox);
/* GULP file labels */
/*
hbox = gtk_hbox_new(FALSE, 0);
gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0);
label = gtk_label_new("Input file");
gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0);
label = gui_auto_text_label(&model->gulp.temp_file);
gtk_box_pack_end(GTK_BOX(hbox), label, FALSE, FALSE, 0);
hbox = gtk_hbox_new(FALSE, 0);
gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0);
label = gtk_label_new("Dump file");
gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0);
label = gui_auto_text_label(&model->gulp.dump_file);
gtk_box_pack_end(GTK_BOX(hbox), label, FALSE, FALSE, 0);
hbox = gtk_hbox_new(FALSE, 0);
gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0);
label = gtk_label_new("Trajectory file");
gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0);
label = gui_auto_text_label(&model->gulp.trj_file);
gtk_box_pack_end(GTK_BOX(hbox), label, FALSE, FALSE, 0);
*/
gui_text_entry("Input file", &model->gulp.temp_file, FALSE, FALSE, vbox);
gui_text_entry("Dump file", &model->gulp.dump_file, FALSE, FALSE, vbox);
gui_text_entry("Trajectory file ", &model->gulp.trj_file, FALSE, FALSE, vbox);
gtk_box_pack_start(GTK_BOX(vbox), gtk_hseparator_new(), FALSE, FALSE, 0);
hbox = gtk_hbox_new(FALSE, 0);
gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0);
label = gtk_label_new("Job name ");
gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0);
entry = gtk_entry_new();
gtk_box_pack_end(GTK_BOX(hbox), entry, FALSE, FALSE, 0);
gtk_entry_set_text(GTK_ENTRY(entry), model->basename);
g_signal_connect(GTK_OBJECT(entry), "changed",
GTK_SIGNAL_FUNC(gulp_jobname_changed), (gpointer) model);
/* CURRENT - advanced options */
frame = gtk_frame_new("Options");
gtk_box_pack_start(GTK_BOX(vbox), frame, FALSE, FALSE, 0);
gtk_container_set_border_width(GTK_CONTAINER(frame), PANEL_SPACING);
vbox = gtk_vbox_new(FALSE, PANEL_SPACING/2);
gtk_container_add(GTK_CONTAINER(frame), vbox);
gui_direct_check("Print charge with coordinates ", &model->gulp.print_charge, NULL, NULL, vbox);
/* minimize page */
page = gtk_vbox_new(FALSE,0);
label = gtk_label_new(" Optimisation ");
gtk_notebook_append_page(GTK_NOTEBOOK(notebook), page, label);
hbox = gtk_hbox_new(FALSE, 0);
gtk_box_pack_start(GTK_BOX(page), hbox, FALSE, FALSE, 0);
/* optimiser to use */
frame = gtk_frame_new("Primary optimiser");
gtk_box_pack_start(GTK_BOX(hbox), frame, TRUE, TRUE, 0);
gtk_container_set_border_width(GTK_CONTAINER(frame), PANEL_SPACING);
vbox = gtk_vbox_new(TRUE, 0);
gtk_container_add(GTK_CONTAINER(frame), vbox);
/* do the first (DEFAULT MODE) radio button */
button = gtk_radio_button_new_with_label(NULL, "bfgs");
gtk_box_pack_start(GTK_BOX(vbox), button, TRUE, TRUE, 0);
g_signal_connect(GTK_OBJECT(button), "clicked",
GTK_SIGNAL_FUNC(cb_gulp_keyword), (gpointer) button);
g_object_set_data(G_OBJECT(button), "key", (gpointer) BFGS_OPT);
g_object_set_data(G_OBJECT(button), "ptr", (gpointer) model);
if (model->gulp.optimiser == BFGS_OPT || model->gulp.optimiser == -1)
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(button), TRUE);
/* make a radio group */
keyword[1] = gtk_radio_button_group(GTK_RADIO_BUTTON (button));
/* do the next button */
button = gtk_radio_button_new_with_label (keyword[1], "conj");
gtk_box_pack_start(GTK_BOX(vbox), button, TRUE, TRUE, 0);
g_signal_connect(GTK_OBJECT(button), "clicked",
GTK_SIGNAL_FUNC(cb_gulp_keyword), (gpointer) button);
g_object_set_data(G_OBJECT(button), "key", (gpointer) CONJ_OPT);
g_object_set_data(G_OBJECT(button), "ptr", (gpointer) model);
if (model->gulp.optimiser == CONJ_OPT)
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(button), TRUE);
/* subsequent button... */
button = gtk_radio_button_new_with_label(gtk_radio_button_group
(GTK_RADIO_BUTTON(button)), "rfo");
gtk_box_pack_start(GTK_BOX(vbox), button, TRUE, TRUE, 0);
g_signal_connect(GTK_OBJECT(button), "clicked",
GTK_SIGNAL_FUNC (cb_gulp_keyword), (gpointer) button);
g_object_set_data(G_OBJECT(button), "key", (gpointer) RFO_OPT);
g_object_set_data(G_OBJECT(button), "ptr", (gpointer) model);
if (model->gulp.optimiser == RFO_OPT)
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(button), TRUE);
/* optimiser to use */
frame = gtk_frame_new("Secondary optimiser");
gtk_box_pack_start(GTK_BOX(hbox), frame, TRUE, TRUE, 0);
gtk_container_set_border_width(GTK_CONTAINER(frame), PANEL_SPACING);
vbox = gtk_vbox_new(TRUE, 0);
gtk_container_add(GTK_CONTAINER(frame), vbox);
/* do the first (DEFAULT MODE) radio button */
button = gtk_radio_button_new_with_label(NULL, "none");
gtk_box_pack_start(GTK_BOX(vbox), button, FALSE, FALSE, 0);
g_signal_connect(GTK_OBJECT(button), "clicked",
GTK_SIGNAL_FUNC (switch_keyword), (gpointer) button);
g_object_set_data(G_OBJECT(button), "key", (gpointer) SWITCH_OFF);
g_object_set_data(G_OBJECT(button), "ptr", (gpointer) model);
if (model->gulp.optimiser2 == SWITCH_OFF || model->gulp.optimiser2 == -1)
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(button), TRUE);
/* make a radio group */
keyword[1] = gtk_radio_button_group(GTK_RADIO_BUTTON(button));
/* do the next button */
button = gtk_radio_button_new_with_label(keyword[1], "bfgs");
gtk_box_pack_start(GTK_BOX(vbox), button, FALSE, FALSE, 0);
g_signal_connect(GTK_OBJECT(button), "clicked",
GTK_SIGNAL_FUNC(switch_keyword), (gpointer) button);
g_object_set_data(G_OBJECT(button), "key", (gpointer) BFGS_OPT);
g_object_set_data(G_OBJECT(button), "ptr", (gpointer) model);
if (model->gulp.optimiser2 == BFGS_OPT)
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(button), TRUE);
/* subsequent button... */
button = gtk_radio_button_new_with_label(gtk_radio_button_group
(GTK_RADIO_BUTTON(button)), "conj");
gtk_box_pack_start(GTK_BOX(vbox), button, FALSE, FALSE, 0);
g_signal_connect(GTK_OBJECT(button), "clicked",
GTK_SIGNAL_FUNC(switch_keyword), (gpointer) button);
g_object_set_data(G_OBJECT(button), "key", (gpointer) CONJ_OPT);
g_object_set_data(G_OBJECT(button), "ptr", (gpointer) model);
if (model->gulp.optimiser2 == CONJ_OPT)
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(button), TRUE);
/* subsequent button... */
button = gtk_radio_button_new_with_label(gtk_radio_button_group
(GTK_RADIO_BUTTON(button)), "rfo");
gtk_box_pack_start(GTK_BOX(vbox), button, FALSE, FALSE, 0);
g_signal_connect(GTK_OBJECT(button), "clicked",
GTK_SIGNAL_FUNC(switch_keyword), (gpointer) button);
g_object_set_data(G_OBJECT(button), "key", (gpointer) RFO_OPT);
g_object_set_data(G_OBJECT(button), "ptr", (gpointer) model);
if (model->gulp.optimiser2 == RFO_OPT)
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(button), TRUE);
/* optimiser to use */
frame = gtk_frame_new("Switching critera");
gtk_box_pack_start(GTK_BOX(hbox), frame, TRUE, TRUE, 0);
gtk_container_set_border_width(GTK_CONTAINER(frame), PANEL_SPACING);
vbox = gtk_vbox_new(FALSE, 0);
gtk_container_add(GTK_CONTAINER(frame), vbox);
/* do the first (DEFAULT MODE) radio button */
button = gtk_radio_button_new_with_label(NULL, "cycle");
gtk_box_pack_start(GTK_BOX(vbox), button, FALSE, FALSE, 0);
g_signal_connect(GTK_OBJECT(button), "clicked",
GTK_SIGNAL_FUNC(switch_keyword), (gpointer) button);
g_object_set_data(G_OBJECT(button), "key", (gpointer) CYCLE);
g_object_set_data(G_OBJECT(button), "ptr", (gpointer) model);
if (model->gulp.switch_type == CYCLE)
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(button), TRUE);
/* make a radio group */
keyword[1] = gtk_radio_button_group(GTK_RADIO_BUTTON(button));
/* do the next button */
button = gtk_radio_button_new_with_label(keyword[1], "gnorm");
gtk_box_pack_start(GTK_BOX(vbox), button, FALSE, FALSE, 0);
g_signal_connect(GTK_OBJECT(button), "clicked",
GTK_SIGNAL_FUNC(switch_keyword), (gpointer) button);
g_object_set_data(G_OBJECT(button), "key", (gpointer) GNORM);
g_object_set_data(G_OBJECT(button), "ptr", (gpointer) model);
if (model->gulp.switch_type == GNORM || model->gulp.switch_type < 0)
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(button), TRUE);
entry = gtk_entry_new();
text = g_strdup_printf("%f", model->gulp.switch_value);
gtk_entry_set_text(GTK_ENTRY(entry), text);
g_free(text);
gtk_box_pack_end(GTK_BOX(vbox), entry, TRUE, FALSE, 0);
g_signal_connect(GTK_OBJECT(entry), "changed",
GTK_SIGNAL_FUNC(switch_value_changed), (gpointer) entry);
g_object_set_data(G_OBJECT(entry), "ptr", (gpointer) model);
/* frame */
frame = gtk_frame_new(NULL);
gtk_box_pack_start(GTK_BOX(page), frame, FALSE, FALSE, 0);
gtk_container_set_border_width(GTK_CONTAINER(frame), PANEL_SPACING);
hbox = gtk_hbox_new(FALSE, 0);
gtk_container_add(GTK_CONTAINER(frame),hbox);
gtk_container_set_border_width(GTK_CONTAINER(hbox), PANEL_SPACING);
/* optimization cycles */
label = gtk_label_new(" Maximum cycles ");
gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0);
gui_direct_spin(NULL, &model->gulp.maxcyc, 0, 500, 10, NULL, NULL, hbox);
/* NEW - text box for potentials */
vbox = gtk_vbox_new(FALSE,0);
label = gtk_label_new(" Potentials ");
gtk_notebook_append_page(GTK_NOTEBOOK(notebook), vbox, label);
frame = gtk_frame_new(NULL);
gtk_box_pack_start(GTK_BOX(vbox), frame, TRUE, TRUE, 0);
swin = gui_text_window(&model->gulp.potentials, TRUE);
gtk_container_add(GTK_CONTAINER(frame), swin);
gui_text_entry(" Potential Library", &model->gulp.libfile, TRUE, FALSE, vbox);
/* NEW - text box for element and species data */
hbox = gtk_hbox_new(TRUE, 0);
label = gtk_label_new(" Elements ");
gtk_notebook_append_page(GTK_NOTEBOOK(notebook), hbox, label);
frame = gtk_frame_new("Element");
gtk_box_pack_start(GTK_BOX(hbox), frame, TRUE, TRUE, 0);
swin = gui_text_window(&model->gulp.elements, TRUE);
gtk_container_add(GTK_CONTAINER(frame), swin);
frame = gtk_frame_new("Species");
gtk_box_pack_start(GTK_BOX(hbox), frame, TRUE, TRUE, 0);
swin = gui_text_window(&model->gulp.species, TRUE);
gtk_container_add(GTK_CONTAINER(frame), swin);
/* NEW - text box for "pass through" GULP data */
vbox = gtk_vbox_new(FALSE,0);
label = gtk_label_new(" Unprocessed ");
gtk_notebook_append_page(GTK_NOTEBOOK(notebook), vbox, label);
/* unprocessed keywords */
frame = gtk_frame_new(NULL);
gtk_box_pack_start(GTK_BOX(vbox), frame, FALSE, FALSE, 0);
gtk_container_set_border_width(GTK_CONTAINER(frame), PANEL_SPACING);
vbox1 = gtk_vbox_new(FALSE,0);
gtk_container_add(GTK_CONTAINER(frame), vbox1);
hbox = gtk_hbox_new(TRUE, 0);
gtk_box_pack_start(GTK_BOX(vbox1), hbox, FALSE, FALSE, 0);
gui_direct_check("Pass keywords through to GULP", &model->gulp.output_extra_keywords, NULL, NULL, hbox);
gui_text_entry("Keywords ", &model->gulp.extra_keywords, TRUE, TRUE, vbox1);
/* unprocessed options */
frame = gtk_frame_new(NULL);
gtk_box_pack_start(GTK_BOX(vbox), frame, TRUE, TRUE, 0);
gtk_container_set_border_width(GTK_CONTAINER(frame), PANEL_SPACING);
vbox1 = gtk_vbox_new(FALSE,0);
gtk_container_add(GTK_CONTAINER(frame), vbox1);
hbox = gtk_hbox_new(TRUE, 0);
gtk_box_pack_start(GTK_BOX(vbox1), hbox, FALSE, FALSE, 0);
gui_direct_check("Pass options through to GULP", &model->gulp.output_extra, NULL, NULL, hbox);
swin = gui_text_window(&model->gulp.extra, TRUE);
gtk_box_pack_start(GTK_BOX(vbox1), swin, TRUE, TRUE, 0);
/* vibrational eigenvector display page */
page = gtk_vbox_new(FALSE,0);
label = gtk_label_new (" Vibrational ");
gtk_notebook_append_page(GTK_NOTEBOOK(notebook), page, label);
gulp_phonon_box(page, model);
/* CURRENT - solvation (cosmic) */
/* TODO - only available on some versions of GULP */
page = gtk_vbox_new(FALSE,0);
label = gtk_label_new (" Solvation ");
gtk_notebook_append_page(GTK_NOTEBOOK(notebook), page, label);
gulp_solvation_box(page, dialog);
/* summary details for the model */
frame = gtk_frame_new("Details");
gtk_box_pack_start(GTK_BOX(box),frame,FALSE,FALSE,0);
gtk_container_set_border_width(GTK_CONTAINER(frame), PANEL_SPACING);
hbox = gtk_hbox_new(FALSE, 0);
gtk_container_add (GTK_CONTAINER(frame),hbox);
/* left vbox */
vbox = gtk_vbox_new(TRUE, 2);
gtk_box_pack_start (GTK_BOX (hbox), vbox, TRUE, TRUE, 0);
label = gtk_label_new("Structure name");
gtk_box_pack_start (GTK_BOX (vbox), label, TRUE, TRUE, 0);
label = gtk_label_new("Total energy (eV)");
gtk_box_pack_start (GTK_BOX (vbox), label, TRUE, TRUE, 0);
if (model->periodic == 2)
{
label = gtk_label_new("Surface bulk energy (eV)");
gtk_box_pack_start (GTK_BOX (vbox), label, TRUE, TRUE, 0);
label = gtk_label_new("Surface dipole");
gtk_box_pack_start (GTK_BOX (vbox), label, TRUE, TRUE, 0);
label = gtk_label_new("Surface energy");
gtk_box_pack_start (GTK_BOX (vbox), label, TRUE, TRUE, 0);
label = gtk_label_new("Attachment energy");
gtk_box_pack_start (GTK_BOX (vbox), label, TRUE, TRUE, 0);
}
/* right vbox */
vbox = gtk_vbox_new(TRUE, 2);
gtk_box_pack_start(GTK_BOX(hbox), vbox, TRUE, TRUE, 0);
entry = gtk_entry_new();
gtk_entry_set_text(GTK_ENTRY(entry), model->basename);
gtk_box_pack_start(GTK_BOX(vbox), entry, FALSE, FALSE, 0);
gtk_entry_set_editable(GTK_ENTRY(entry), FALSE);
model->gulp.energy_entry = gtk_entry_new_with_max_length(LINELEN);
if (model->gulp.free)
g_string_sprintf(line,"%f (free energy)",model->gulp.energy);
else
g_string_sprintf(line,"%f",model->gulp.energy);
gtk_entry_set_text(GTK_ENTRY(model->gulp.energy_entry),line->str);
gtk_box_pack_start (GTK_BOX (vbox), model->gulp.energy_entry, TRUE, TRUE, 0);
gtk_entry_set_editable(GTK_ENTRY(model->gulp.energy_entry), FALSE);
if (model->periodic == 2)
{
model->gulp.sbe_entry = gtk_entry_new_with_max_length(LINELEN);
g_string_sprintf(line,"%f",model->gulp.sbulkenergy);
gtk_entry_set_text(GTK_ENTRY(model->gulp.sbe_entry),line->str);
gtk_box_pack_start(GTK_BOX(vbox), model->gulp.sbe_entry, TRUE, TRUE, 0);
/* NEW - sbulkenergy editable */
gtk_entry_set_editable(GTK_ENTRY(model->gulp.sbe_entry), TRUE);
g_signal_connect(GTK_OBJECT(model->gulp.sbe_entry), "changed",
GTK_SIGNAL_FUNC(cb_gulp_keyword), (gpointer) entry);
g_object_set_data(G_OBJECT(model->gulp.sbe_entry), "key", (gpointer) SBULK_ENERGY);
g_object_set_data(G_OBJECT(model->gulp.sbe_entry), "ptr", (gpointer) model);
/* surface dipole */
model->gulp.sdipole_entry = gtk_entry_new_with_max_length(LINELEN);
g_string_sprintf(line,"%f e.Angs", model->gulp.sdipole);
gtk_entry_set_text(GTK_ENTRY(model->gulp.sdipole_entry), line->str);
gtk_box_pack_start(GTK_BOX(vbox), model->gulp.sdipole_entry, TRUE, TRUE, 0);
gtk_entry_set_editable(GTK_ENTRY(model->gulp.sdipole_entry), FALSE);
/* surface energy */
model->gulp.esurf_entry = gtk_entry_new_with_max_length(LINELEN);
if (model->gulp.esurf[1] == 0.0)
g_string_sprintf(line,"%f %s",
model->gulp.esurf[0], model->gulp.esurf_units);
else
g_string_sprintf(line,"%f %s",
model->gulp.esurf[1], model->gulp.esurf_units);
gtk_entry_set_text(GTK_ENTRY(model->gulp.esurf_entry), line->str);
gtk_box_pack_start(GTK_BOX(vbox), model->gulp.esurf_entry, TRUE, TRUE, 0);
gtk_entry_set_editable(GTK_ENTRY(model->gulp.esurf_entry), FALSE);
/* attachment energy */
model->gulp.eatt_entry = gtk_entry_new_with_max_length(LINELEN);
if (model->gulp.eatt[1] == 0.0)
g_string_sprintf(line,"%f %s",
model->gulp.eatt[0], model->gulp.eatt_units);
else
g_string_sprintf(line,"%f %s",
model->gulp.eatt[1], model->gulp.eatt_units);
gtk_entry_set_text(GTK_ENTRY(model->gulp.eatt_entry), line->str);
gtk_box_pack_start(GTK_BOX(vbox), model->gulp.eatt_entry, TRUE, TRUE, 0);
gtk_entry_set_editable(GTK_ENTRY(model->gulp.eatt_entry), FALSE);
}
/* done */
gtk_widget_show_all(box);
g_string_free(line, TRUE);
gui_model_select(model);
}
/****************************************/
/* run the approriate energetics method */
/****************************************/
void gulp_execute(GtkWidget *w, gpointer data)
{
struct model_pak *model = data;
g_assert(model != NULL);
gui_gulp_task(NULL, model);
}
/*********************************/
/* cleanup for energetics dialog */
/*********************************/
void gulp_cleanup(struct model_pak *model)
{
g_assert(model != NULL);
model->gulp.energy_entry = NULL;
model->gulp.sdipole_entry = NULL;
model->gulp.esurf_entry = NULL;
model->gulp.eatt_entry = NULL;
}
/**************************/
/* GULP energetics dialog */
/**************************/
void gulp_dialog(void)
{
gpointer dialog;
GtkWidget *window, *frame, *vbox;
struct model_pak *model;
model = sysenv.active_model;
if (!model)
return;
gulp_files_init(model);
/* request an energetics dialog */
dialog = dialog_request(GULP, "GULP configuration", NULL, gulp_cleanup, model);
if (!dialog)
return;
window = dialog_window(dialog);
frame = gtk_frame_new(NULL);
gtk_box_pack_start(GTK_BOX(GTK_DIALOG(window)->vbox), frame, FALSE, FALSE, 0);
gtk_container_set_border_width(GTK_CONTAINER(frame), PANEL_SPACING);
vbox = gtk_vbox_new(FALSE,0);
gtk_container_add(GTK_CONTAINER(frame), vbox);
gui_gulp_widget(vbox, dialog);
/* terminating button */
gui_stock_button(GTK_STOCK_EXECUTE, gulp_execute, model,
GTK_DIALOG(window)->action_area);
gui_stock_button(GTK_STOCK_CLOSE, dialog_destroy, dialog,
GTK_DIALOG(window)->action_area);
gtk_widget_show_all(window);
}
syntax highlighted by Code2HTML, v. 0.9.1