/* Copyright (C) 2005 by Menno Deij m.deij@science.ru.nl 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 #include #include #include #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 "numeric.h" #define DEBUG_MONTY_GUI 0 extern struct sysenv_pak sysenv; extern struct elem_pak elements[]; void init_monty_settings(struct model_pak * model) { /* for now we set up manually for the mac * eventually this should be set by g_find_program_in_path */ g_free(sysenv.monty_path); sysenv.monty_path = g_strdup("/Users/menno/src/Monty2/Monty2_GNU_MAC"); g_free(model->monty.input_cgf); model->monty.input_cgf = g_strdup(model->filename); /* init has moved to model.c */ return; } /* Unfortunately GTK+ 2.2 and older don't have GtkFileChooserDialog so for them a file dialog without GtkFileChooserDialog is given the disadvantage is that this has no easy file filter */ #if GTK_MAJOR_VERSION >= 2 && GTK_MINOR_VERSION >= 4 void select_cgf_file_dialog(GtkButton *button, gpointer data) { GtkFileChooserDialog *file_chooser; GtkFileFilter *cgf_filter; struct model_pak *model = sysenv.active_model; file_chooser = gtk_file_chooser_dialog_new("Select a CGF File", NULL, /* parent window, seems to work without valid pointer */ GTK_FILE_CHOOSER_ACTION_OPEN, GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT, NULL); cgf_filter = gtk_file_filter_new(); gtk_file_filter_add_pattern(cgf_filter, "*.cgf"); gtk_file_filter_add_pattern(cgf_filter, "*.CGF"); g_object_set(file_chooser, "filter", cgf_filter, NULL); if (gtk_dialog_run (GTK_DIALOG (file_chooser)) == GTK_RESPONSE_ACCEPT) { char *filename; filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (file_chooser)); g_free(model->monty.input_cgf); model->monty.input_cgf = g_strdup(filename); gui_relation_update_widget(&model->monty.input_cgf); g_free (filename); } gtk_widget_destroy (GTK_WIDGET(file_chooser)); } void select_surface_file_dialog(GtkButton *button, gpointer data) { GtkFileChooserDialog *file_chooser; GtkFileFilter *surface_filter; struct model_pak *model = sysenv.active_model; /* todo: file filter */ file_chooser = gtk_file_chooser_dialog_new("Select a CGF File", NULL, /* parent window, seems to work without valid pointer */ GTK_FILE_CHOOSER_ACTION_OPEN, GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT, NULL); surface_filter = gtk_file_filter_new(); gtk_file_filter_add_pattern(surface_filter, "*.monty2"); if (gtk_dialog_run (GTK_DIALOG (file_chooser)) == GTK_RESPONSE_ACCEPT) { char *filename; filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (file_chooser)); g_free(model->monty.input_surface); model->monty.input_surface = g_strdup(filename); gui_relation_update_widget(&model->monty.input_surface); g_free (filename); } gtk_widget_destroy (GTK_WIDGET(file_chooser)); } /* gtk+-2 version < 2.4 */ #else GtkFileSelection *file_browser; void select_input_cgf_filename(GtkButton *button, gpointer data) { gchar *filename; /* get the filename from the file_browser object */ g_object_get(file_browser, "filename", &filename, NULL); struct model_pak *model = sysenv.active_model; /* free and then set the filename */ g_free(model->monty.input_cgf); model->monty.input_cgf = g_strdup(filename); /* update the widget displaying the input cgf filename */ gui_relation_update_widget(&model->monty.input_cgf); g_free(filename); } void select_cgf_file_dialog(GtkButton *button, gpointer data) { /* create a new file browser */ file_browser = g_object_new(GTK_TYPE_FILE_SELECTION, NULL); /* set the title of the browser what about a file filter for CGF's? */ gtk_window_set_title(GTK_WINDOW(file_browser), "Select a CGF File"); /* connect signals */ g_signal_connect(file_browser->ok_button, "clicked", G_CALLBACK(select_input_cgf_filename), NULL); g_signal_connect_swapped(file_browser->ok_button, "clicked", G_CALLBACK(gtk_widget_destroy), file_browser); g_signal_connect_swapped(file_browser->cancel_button, "clicked", G_CALLBACK(gtk_widget_destroy), file_browser); /* show window */ gtk_widget_show(GTK_WIDGET(file_browser)); } void select_input_surface_filename(GtkButton *button, gpointer data) { gchar *filename; /* get the filename from the file_browser */ g_object_get(file_browser, "filename", &filename, NULL); struct model_pak *model = sysenv.active_model; /* free and set the filename selected */ g_free(model->monty.input_surface); model->monty.input_surface = g_strdup(filename); /* update the widget displaying the input cgf filename */ gui_relation_update_widget(&model->monty.input_surface); g_free(filename); } void select_surface_file_dialog(GtkButton *button, gpointer data) { /* create a new file browser */ file_browser = g_object_new(GTK_TYPE_FILE_SELECTION, NULL); /* set the title of the browser (how about file filter? */ gtk_window_set_title(GTK_WINDOW(file_browser), "Select a Surface File"); /* connect signals */ g_signal_connect(file_browser->ok_button, "clicked", G_CALLBACK(select_input_surface_filename), NULL); g_signal_connect_swapped(file_browser->ok_button, "clicked", G_CALLBACK(gtk_widget_destroy), file_browser); g_signal_connect_swapped(file_browser->cancel_button, "clicked", G_CALLBACK(gtk_widget_destroy), file_browser); /* show window */ gtk_widget_show(GTK_WIDGET(file_browser)); } #endif /* a callback function to set the energy unit to kcal/mol */ void energy_unit_kcal(GtkButton *button, gpointer data) { struct model_pak *model; model = sysenv.active_model; g_free(model->monty.energy_unit); model->monty.energy_unit = g_strdup("kcal/mol"); } /* a callback function to set the energy unit to kcal/mol */ void energy_unit_kJ(GtkButton *button, gpointer data) { struct model_pak *model; model = sysenv.active_model; g_free(model->monty.energy_unit); model->monty.energy_unit = g_strdup("kJ/mol"); } void run_crystal_graph(GtkButton *button, gpointer data) { struct model_pak *model = sysenv.active_model; calculate_crystal_graph(model); } void monty_crystal_graph_box(GtkWidget *box, struct model_pak *data) { GtkWidget *vbox, *wdgt, *hsep; gint size = 15; vbox = gtk_vbox_new(FALSE, 0); gtk_box_pack_start(GTK_BOX(box), vbox, TRUE, TRUE, 0); gtk_container_set_border_width(GTK_CONTAINER(vbox), PANEL_SPACING); wdgt = gui_direct_spin("Cutoff in a-direction", &data->monty.image_x, 1.0, DBL_MAX, 1.0, NULL, NULL, vbox); gtk_widget_set_size_request(wdgt, sysenv.gtk_fontsize*size, -1); wdgt = gui_direct_spin("Cutoff in b-direction", &data->monty.image_y, 1.0, DBL_MAX, 1.0, NULL, NULL, vbox); gtk_widget_set_size_request(wdgt, sysenv.gtk_fontsize*size, -1); wdgt = gui_direct_spin("Cutoff in c-direction", &data->monty.image_z, 1.0, DBL_MAX, 1.0, NULL, NULL, vbox); gtk_widget_set_size_request(wdgt, sysenv.gtk_fontsize*size, -1); wdgt = GTK_WIDGET(g_object_new(GTK_TYPE_BUTTON, "label", "Calculate crystal graph", NULL)); g_signal_connect(GTK_BUTTON(wdgt), "clicked", G_CALLBACK(run_crystal_graph), NULL); gtk_box_pack_start(GTK_BOX(vbox), wdgt, FALSE, FALSE, 0); } /*******************************************/ /* following five functions create the */ /* five pages in the notebook of the monty */ /* setttings dialog */ /*******************************************/ void monty_input_box(GtkWidget *box, struct model_pak *data) { GtkWidget *vbox, *table, *frame_hkl, *frame_dirs, *frame_deltamu, *hbox, *h_sep, *wdgt; gint size = 15; /* the top-level vbox, in which all other widgets are packed */ vbox = gtk_vbox_new(FALSE, 0); gtk_box_pack_start(GTK_BOX(box), vbox, TRUE, TRUE, 0); gtk_container_set_border_width(GTK_CONTAINER(vbox), PANEL_SPACING); /* a table with four widgets, two gui_text_entries showing the input cgf filename and the input surface filename next to them there are two file dialog buttons for selecting the files */ table = g_object_new(GTK_TYPE_TABLE, "n-rows", 2, "n-columns", 2, "homogeneous", FALSE, NULL); gtk_box_pack_start(GTK_BOX(vbox), table, TRUE, TRUE, 0); /* as the gui_text_entry and gui_stock_button require a box to pack their widgets, we create a hbox for each of the four widgets, and pack the hboxes into the table */ hbox = gtk_hbox_new(FALSE, 0); wdgt = gui_text_entry("Input CGF Filename", &data->monty.input_cgf, TRUE, FALSE, hbox); gtk_table_attach_defaults(GTK_TABLE(table), hbox, 0,1,0,1); hbox = gtk_hbox_new(FALSE, 0); wdgt = gui_text_entry("Input Surface Filename", &data->monty.input_surface, TRUE, FALSE, hbox); gtk_table_attach_defaults(GTK_TABLE(table), hbox, 0,1,1,2); hbox = gtk_hbox_new(FALSE, 0); wdgt = gui_stock_button(GTK_STOCK_OPEN, select_cgf_file_dialog, NULL, hbox); gtk_table_attach_defaults(GTK_TABLE(table), hbox, 1,2,0,1); hbox = gtk_hbox_new(FALSE, 0); wdgt = gui_stock_button(GTK_STOCK_OPEN, select_surface_file_dialog, NULL, hbox); gtk_table_attach_defaults(GTK_TABLE(table), hbox, 1,2,1,2); h_sep = GTK_WIDGET(g_object_new(GTK_TYPE_HSEPARATOR, NULL)); gtk_widget_set_size_request(h_sep, -1, size); gtk_box_pack_start(GTK_BOX(vbox), GTK_WIDGET(h_sep), FALSE, FALSE, 0); /* up next are three gui_text_windows for entering hkl values output directories and driving forces. each gui_text_window is packed in a frame showing the gui_text_window's purpose */ hbox = gtk_hbox_new(FALSE, 0); gtk_box_pack_start(GTK_BOX(vbox), hbox, TRUE, TRUE, 0); frame_hkl = gtk_frame_new("HKL Values"); gtk_box_pack_start(GTK_BOX(hbox), frame_hkl, TRUE, TRUE, 0); wdgt = gui_text_window(&data->monty.hkls, TRUE); gtk_container_add(GTK_CONTAINER(frame_hkl), wdgt); frame_dirs = gtk_frame_new("Output directories"); gtk_box_pack_start(GTK_BOX(hbox), frame_dirs, TRUE, TRUE, 0); wdgt = gui_text_window(&data->monty.output_dirs, TRUE); gtk_container_add(GTK_CONTAINER(frame_dirs), wdgt); frame_deltamu = gtk_frame_new("Driving forces"); gtk_box_pack_start(GTK_BOX(hbox), frame_deltamu, TRUE, TRUE, 0); wdgt = gui_text_window(&data->monty.supersaturations, TRUE); gtk_container_add(GTK_CONTAINER(frame_deltamu), wdgt); /* next we create a radiobutton group containing two radiobuttons to switch between kcal/mol and kJ/mol energies in the crystal graph */ new_radio_group(0, vbox, TT); wdgt = add_radio_button("kcal/mol", (gpointer) energy_unit_kcal, data); if (data->monty.energy_unit == "kcal/mol") gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(wdgt), TRUE); wdgt = add_radio_button("kJ/mol", (gpointer) energy_unit_kJ, data); if (data->monty.energy_unit == "kJ/mol") gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(wdgt), TRUE); wdgt = gui_text_entry("Solvation energy", &data->monty.esolv, TRUE, FALSE, vbox); h_sep = GTK_WIDGET(g_object_new(GTK_TYPE_HSEPARATOR, NULL)); gtk_widget_set_size_request(h_sep, -1, size); gtk_box_pack_start(GTK_BOX(vbox), GTK_WIDGET(h_sep), FALSE, FALSE, 0); hbox = gtk_hbox_new(FALSE, 0); gtk_box_pack_start(GTK_BOX(vbox), hbox, TRUE, TRUE, 0); gui_direct_check("Run 3D nucleation", &data->monty.run_nucleation, NULL, NULL, hbox); wdgt = gui_direct_spin("Initial nucleus size", &data->monty.nucleus_size, 1.0, DBL_MAX, 1.0, NULL, NULL, hbox); // gui_direct_check("Run diffusion controlled simulation", &data->monty.run_diffusion, NULL, NULL, vbox); } void monty_output_box(GtkWidget *box, struct model_pak *data) { GtkWidget *vbox, *wdgt, *h_sep; gint size = 15; vbox = gtk_vbox_new(FALSE, 0); gtk_box_pack_start(GTK_BOX(box), vbox, TRUE, TRUE, 0); gtk_container_set_border_width(GTK_CONTAINER(vbox), PANEL_SPACING); /* a text entry for entering the output extension */ wdgt = gui_text_entry("File extension", &data->monty.output_extension, TRUE, FALSE, vbox); gtk_widget_set_size_request(wdgt, sysenv.gtk_fontsize*size, -1); h_sep = GTK_WIDGET(g_object_new(GTK_TYPE_HSEPARATOR, NULL)); gtk_widget_set_size_request(h_sep, -1, size); gtk_box_pack_start(GTK_BOX(vbox), GTK_WIDGET(h_sep), FALSE, FALSE, 0); /* four output options to write different types of surface file types */ gui_direct_check("Write Monty surface", &data->monty.write_surface, NULL, NULL, vbox); gui_direct_check("Write XYZ surface", &data->monty.write_xyz, NULL, NULL, vbox); gui_direct_check("Write Matlab surface", &data->monty.write_matlab, NULL, NULL, vbox); gui_direct_check("Write MSI surface", &data->monty.write_msi, NULL, NULL, vbox); // gui_direct_check("Write Gaussian Cube file", &data->monty.write_cube, NULL, NULL, vbox); } void monty_model_box(GtkWidget *box, struct model_pak *data) { GtkWidget *vbox, *wdgt; gint size = 15; vbox = gtk_vbox_new(FALSE, 0); gtk_box_pack_start(GTK_BOX(box), vbox, TRUE, TRUE, 0); gtk_container_set_border_width(GTK_CONTAINER(vbox), PANEL_SPACING); /* a checkbox for selecting the spiral growth mechanism */ gui_direct_check("Spiral growth", &data->monty.spiral, NULL, NULL, vbox); /* four spinners selecting the number of x-steps, y-steps, the temperature and the kinetics factor */ wdgt = gui_direct_spin("X-steps", &data->monty.xsteps, -DBL_MAX, DBL_MAX, 1.0, NULL, NULL, vbox); gtk_widget_set_size_request(wdgt, sysenv.gtk_fontsize*size, -1); wdgt = gui_direct_spin("Y-steps", &data->monty.ysteps, -DBL_MAX, DBL_MAX, 1.0, NULL, NULL, vbox); gtk_widget_set_size_request(wdgt, sysenv.gtk_fontsize*size, -1); wdgt = gui_direct_spin("Temperature", &data->monty.temperature, 0.0, DBL_MAX, 1.0, NULL, NULL, vbox); gtk_widget_set_size_request(wdgt, sysenv.gtk_fontsize*size, -1); wdgt = gui_direct_spin("Kinetics", &data->monty.xsteps, 0.0, 1.0, 0.01, NULL, NULL, vbox); gtk_widget_set_size_request(wdgt, sysenv.gtk_fontsize*size, -1); } void monty_monitor_box(GtkWidget *box, struct model_pak *data) { GtkWidget *vbox; vbox = gtk_vbox_new(FALSE, 0); gtk_box_pack_start(GTK_BOX(box), vbox, TRUE, TRUE, 0); gtk_container_set_border_width(GTK_CONTAINER(vbox), PANEL_SPACING); /* three different surface monitoring options */ gui_direct_check("Create a multi-frame .xyz file", &data->monty.multi_frame_xyz, NULL, NULL, vbox); gui_direct_check("Monitor average height", &data->monty.monitor_height, NULL, NULL, vbox); gui_direct_check("Monitor surface energy", &data->monty.monitor_energy, NULL, NULL, vbox); gui_direct_check("Monitor height correlation", &data->monty.monitor_hhcorr, NULL, NULL, vbox); gui_direct_check("Monitor diffusion profile", &data->monty.monitor_diffusion_profile, NULL, NULL, vbox); } void monty_run_box(GtkWidget *box, struct model_pak *data) { GtkWidget *vbox, *wdgt; /* general width of entry widgets */ gint size = 15; vbox = gtk_vbox_new(FALSE, 0); gtk_box_pack_start(GTK_BOX(box), vbox, TRUE, TRUE, 0); gtk_container_set_border_width(GTK_CONTAINER(vbox), PANEL_SPACING); wdgt = gui_text_entry("Random Seed", &data->monty.random_seed, TRUE, FALSE, vbox); gtk_widget_set_size_request(wdgt, sysenv.gtk_fontsize*size, -1); wdgt = gui_direct_spin("Rows", &data->monty.rows, 5.0, DBL_MAX, 1.0, NULL, NULL, vbox); gtk_widget_set_size_request(wdgt, sysenv.gtk_fontsize*size, -1); wdgt = gui_direct_spin("Columns", &data->monty.cols, 5.0, DBL_MAX, 1.0, NULL, NULL, vbox); gtk_widget_set_size_request(wdgt, sysenv.gtk_fontsize*size, -1); wdgt = gui_direct_spin("Layers", &data->monty.layers, 5.0, DBL_MAX, 1.0, NULL, NULL, vbox); gtk_widget_set_size_request(wdgt, sysenv.gtk_fontsize*size, -1); wdgt = gui_direct_spin("Increment", &data->monty.increment, 2.0, DBL_MAX, 1.0, NULL, NULL, vbox); gtk_widget_set_size_request(wdgt, sysenv.gtk_fontsize*size, -1); wdgt = gui_direct_spin("Relaxation", &data->monty.relax, 0.0, DBL_MAX, 1000.0, NULL, NULL, vbox); gtk_widget_set_size_request(wdgt, sysenv.gtk_fontsize*size, -1); wdgt = gui_direct_spin("Cycles", &data->monty.cycles, 0.0, DBL_MAX, 1000.0, NULL, NULL, vbox); gtk_widget_set_size_request(wdgt, sysenv.gtk_fontsize*size, -1); wdgt = gui_direct_spin("Moves", &data->monty.moves, 0.0, DBL_MAX, 1000.0, NULL, NULL, vbox); gtk_widget_set_size_request(wdgt, sysenv.gtk_fontsize*size, -1); } void write_input_file(gchar *input_file, gpointer data) { FILE *fp; struct model_pak *model = data; gchar *last_dirsep, *yes, *no; gchar **hkls, **supersats, **out_dirs; gint i; yes = g_strdup("yes"); no = g_strdup("no"); unlink(input_file ); fp = fopen(input_file, "wt"); if (!fp) { gui_text_show(ERROR, "Unable to open Monty input file for writing"); return; } fprintf(fp, "#Monty input file generated by GDIS %f\n", VERSION); fprintf(fp, "&INPUT\n"); /* remove any whitespace, this also includes trailing \n characters */ g_strstrip(model->monty.hkls); /* split the string by endline characters */ hkls = g_strsplit(model->monty.hkls, "\n", INT_MAX); /* print all hkl values to the file */ for (i = 0; *(hkls+i); ++i) { fprintf(fp, " -hkl %s\n", *(hkls+i)); } /* remove any whitespace, this also includes trailing \n characters */ g_strstrip(model->monty.supersaturations); supersats = g_strsplit(model->monty.supersaturations, "\n", INT_MAX); for (i = 0; *(supersats+i); ++i) { fprintf(fp, " -supersat %s\n", *(supersats +i)); } g_strfreev(supersats); last_dirsep = g_strrstr(model->monty.input_surface, DIR_SEP); if (last_dirsep) fprintf(fp, " -surface %s\n", (last_dirsep + 1)); else { /* TODO: make this work when no complete path is selected */ fprintf(fp, "# -surface\n"); } last_dirsep = g_strrstr(model->monty.input_cgf, DIR_SEP); fprintf(fp, " -cgf %s\n", (last_dirsep + 1)); fprintf(fp, " -directory %s\n", g_strndup(model->monty.input_cgf, (last_dirsep - model->monty.input_cgf))); fprintf(fp, " -energy_unit %s\n", model->monty.energy_unit); fprintf(fp, " -esolv %s\n", model->monty.esolv); fprintf(fp, "&END\n\n&OUTPUT\n"); /* remove any whitespace, this also includes trailing \n characters */ g_strstrip(model->monty.output_dirs); out_dirs = g_strsplit(model->monty.output_dirs, "\n", INT_MAX); for (i = 0; *(out_dirs + i); ++i) { fprintf(fp, " -directory %s %s\n", *(hkls + i), *(out_dirs + i)); } g_strfreev(hkls); g_strfreev(out_dirs); fprintf(fp, " -extension %s\n", model->monty.output_extension); fprintf(fp, " -surface %s\n", (model->monty.write_surface ? yes : no)); fprintf(fp, " -xmm %s\n", (model->monty.write_xyz ? yes : no)); fprintf(fp, " -xyz %s\n", (model->monty.write_matlab ? yes : no)); fprintf(fp, " -msi %s\n", (model->monty.write_msi ? yes : no)); fprintf(fp, "&END\n\n&MODEL\n"); fprintf(fp, " -spiral %s\n", (model->monty.write_matlab ? yes : no)); fprintf(fp, " -xsteps %d\n", nearest_int(model->monty.xsteps)); fprintf(fp, " -ysteps %d\n", nearest_int(model->monty.ysteps)); fprintf(fp, " -kinetics %2.2f\n", model->monty.kinetics); fprintf(fp, " -temperature %10.2f\n", model->monty.temperature); fprintf(fp, "&END\n\n&MONITOR\n"); fprintf(fp, " -height %s\n", (model->monty.monitor_height ? yes : no)); fprintf(fp, " -energy %s\n", (model->monty.monitor_energy ? yes : no)); fprintf(fp, " -hhcorr %s\n", (model->monty.monitor_hhcorr ? yes : no)); fprintf(fp, " -gdis %s\n", (model->monty.multi_frame_xyz ? yes : no)); fprintf(fp, "&END\n\n&RUN\n"); fprintf(fp, " -randomseed %s\n", model->monty.random_seed); fprintf(fp, " -rows %d\n", nearest_int(model->monty.rows)); fprintf(fp, " -cols %d\n", nearest_int(model->monty.cols)); fprintf(fp, " -layers %d\n", nearest_int(model->monty.layers)); fprintf(fp, " -increment %d\n", nearest_int(model->monty.increment)); fprintf(fp, " -relaxation %d\n", nearest_int(model->monty.relax)); fprintf(fp, " -cycles %d\n", nearest_int(model->monty.cycles)); fprintf(fp, " -moves %d\n", nearest_int(model->monty.moves)); fprintf(fp, "&END\n"); g_free(yes); g_free(no); fclose(fp); } gint exec_monty(const gchar *input) { gint status=0; gchar *cmd; /* checks */ if (!sysenv.monty_path) return(-1); /* delete the old file to be sure output is only data from current run */ #if _WIN32 /* NB: must enclose paths with single quotes */ cmd = g_strdup_printf("'%s'", sysenv.monty_path); #else cmd = g_strdup_printf("%s %s", sysenv.monty_path, input); #endif #if DEBUG_MONTY_GUI printf("executing: [%s]\n",cmd); #endif task_sync(cmd); /* done */ g_free(cmd); return(status); } void exec_monty_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, "input.monty2", NULL); /* no status file for the moment, as there are multiple output files for a monty simulation, so unable to follow a single one * task->status_file = g_build_filename(sysenv.cwd, "gulp.got", NULL); */ #else inpfile = g_build_filename(sysenv.cwd, "input.monty2", NULL); /* no status file for the moment, as there are multiple output files for a monty simulation, so unable to follow a single one * task->status_file = g_build_filename(sysenv.cwd, model->gulp.out_file, NULL); */ #endif #if DEBUG_MONTY_GUI printf(" input file: %s\n", inpfile); #endif write_input_file(inpfile, model); g_free(inpfile); exec_monty("input.monty2"); } void gui_monty_task(GtkWidget *w, gpointer data) { if (!sysenv.monty_path) { gui_text_show(ERROR, "Monty executable was not found.\n"); return; } /* put a task that runs monty. for now, no postprocessing */ task_new("Monty", &exec_monty_task, data, NULL, NULL, data); } void monty_execute(GtkWidget *w, gpointer data) { struct model_pak *model = sysenv.active_model; if (model) { #if DEBUG_MONTY_GUI /* &INPUT */ g_message("HKLs %s", model->monty.hkls); g_message("Driving forces %s", model->monty.supersaturations); g_message("Input surface %s", model->monty.input_surface); /* TODO: use DIRSEP */ g_message("Input directory %s", model->monty.input_dir); g_message("Input CGF %s", model->monty.input_cgf); g_message("Energy unit %s", model->monty.energy_unit); g_message("Esolv %s", model->monty.esolv); /* &OUTPUT */ g_message("Output directories %s", model->monty.output_dirs); g_message("Output extension %s", model->monty.output_extension); g_message("Write surface %s", model->monty.write_surface ? "yes" : "no"); g_message("Write xyz %s", model->monty.write_xyz ? "yes" : "no"); g_message("Write matlab %s",model->monty.write_matlab ? "yes" : "no"); g_message("Write MSI %s", model->monty.write_msi ? "yes" : "no"); /* &MODEL */ g_message("Spiral growth %s", model->monty.spiral ? "yes" : "no"); g_message("x steps %2f", model->monty.xsteps); g_message("y steps %2f", model->monty.ysteps); g_message("kinetics %2f", model->monty.kinetics); g_message("temperature %2f", model->monty.temperature); /* &MONITOR */ g_message("Monitor height %s", model->monty.monitor_height ? "yes" : "no"); g_message("Monitor energy %s", model->monty.monitor_energy ? "yes" : "no"); g_message("Monitor hhcorr %s", model->monty.monitor_hhcorr ? "yes" : "no"); /* &RUN */ g_message("random seed %s", model->monty.random_seed); g_message("Number rows %10f", model->monty.rows); g_message("Number cols %10f", model->monty.cols); g_message("Number layers %10f", model->monty.layers); g_message("Increment %10f", model->monty.increment); g_message("Relaxations %10f", model->monty.relax); g_message("Cycles %10f", model->monty.cycles); g_message("Moves %10f", model->monty.moves); #endif gui_monty_task(NULL, model); } else g_message("no model active"); } void gui_monty_widget(GtkWidget *box, struct model_pak *data) { GString *line; GtkWidget *page; GtkWidget *label, *notebook; /* 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); page = gtk_vbox_new(FALSE,0); label = gtk_label_new (" Crystal Graph "); gtk_notebook_append_page(GTK_NOTEBOOK(notebook), page, label); monty_crystal_graph_box(page, data); page = gtk_vbox_new(FALSE,0); label = gtk_label_new (" Input "); gtk_notebook_append_page(GTK_NOTEBOOK(notebook), page, label); monty_input_box(page, data); page = gtk_vbox_new(FALSE,0); label = gtk_label_new (" Output "); gtk_notebook_append_page(GTK_NOTEBOOK(notebook), page, label); monty_output_box(page, data); page = gtk_vbox_new(FALSE,0); label = gtk_label_new (" Model "); gtk_notebook_append_page(GTK_NOTEBOOK(notebook), page, label); monty_model_box(page, data); page = gtk_vbox_new(FALSE,0); label = gtk_label_new (" Monitor "); gtk_notebook_append_page(GTK_NOTEBOOK(notebook), page, label); monty_monitor_box(page, data); page = gtk_vbox_new(FALSE,0); label = gtk_label_new (" Run "); gtk_notebook_append_page(GTK_NOTEBOOK(notebook), page, label); monty_run_box(page, data); /* done */ gtk_widget_show_all(box); g_string_free(line, TRUE); gui_model_select(data); } void monty_dialog(void) { gpointer dialog; GtkWidget *window, *frame, *vbox; struct model_pak *model; model = sysenv.active_model; if (!model) return; if (!model->monty.input_cgf) init_monty_settings(model); /* request a MONTY dialog */ dialog = dialog_request(MONTY, "MONTY configuration", NULL, NULL, 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_monty_widget(vbox, model); /* terminating button */ gui_stock_button(GTK_STOCK_EXECUTE, monty_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); }