1 /* EXTRAITS DE LA LICENCE
2 Copyright CEA, contributeurs : Luc BILLARD et Damien
3 CALISTE, laboratoire L_Sim, (2001-2005)
4
5 Adresse m�l :
6 BILLARD, non joignable par m�l ;
7 CALISTE, damien P caliste AT cea P fr.
8
9 Ce logiciel est un programme informatique servant � visualiser des
10 structures atomiques dans un rendu pseudo-3D.
11
12 Ce logiciel est r�gi par la licence CeCILL soumise au droit fran�ais et
13 respectant les principes de diffusion des logiciels libres. Vous pouvez
14 utiliser, modifier et/ou redistribuer ce programme sous les conditions
15 de la licence CeCILL telle que diffus�e par le CEA, le CNRS et l'INRIA
16 sur le site "http://www.cecill.info".
17
18 Le fait que vous puissiez acc�der � cet en-t�te signifie que vous avez
19 pris connaissance de la licence CeCILL, et que vous en avez accept� les
20 termes (cf. le fichier Documentation/licence.fr.txt fourni avec ce logiciel).
21 */
22
23 /* LICENCE SUM UP
24 Copyright CEA, contributors : Luc BILLARD et Damien
25 CALISTE, laboratoire L_Sim, (2001-2005)
26
27 E-mail address:
28 BILLARD, not reachable any more ;
29 CALISTE, damien P caliste AT cea P fr.
30
31 This software is a computer program whose purpose is to visualize atomic
32 configurations in 3D.
33
34 This software is governed by the CeCILL license under French law and
35 abiding by the rules of distribution of free software. You can use,
36 modify and/ or redistribute the software under the terms of the CeCILL
37 license as circulated by CEA, CNRS and INRIA at the following URL
38 "http://www.cecill.info".
39
40 The fact that you are presently reading this means that you have had
41 knowledge of the CeCILL license and that you accept its terms. You can
42 find a copy of this licence shipped with this software at Documentation/licence.en.txt.
43 */
44
45 #include <gtk/gtk.h>
46 #include <math.h>
47
48 #include <abinit.h>
49
50 #include <support.h>
51 #include <visu_gtk.h>
52 #include <gtk_main.h>
53 #include <gtk_interactive.h>
54 #include <gtk_renderingWindowWidget.h>
55 #include <extensions/marks.h>
56 #include <openGLFunctions/interactive.h>
57
58 #include "abinit.h"
59
60 #define ABINIT_SYMMETRIES_INFO \
61 _("left-button\t\t: select one atom to get the equivalent ones\n" \
62 "right-button\t\t: switch to observe")
63
64 enum
65 {
66 SYM_ID,
67 SYM_MATRIX_00,
68 SYM_MATRIX_01,
69 SYM_MATRIX_02,
70 SYM_MATRIX_10,
71 SYM_MATRIX_11,
72 SYM_MATRIX_12,
73 SYM_MATRIX_20,
74 SYM_MATRIX_21,
75 SYM_MATRIX_22,
76 SYM_TRANS_0,
77 SYM_TRANS_1,
78 SYM_TRANS_2,
79 SYM_COMMENT,
80 SYM_N_COLS
81 };
82
83 static gulong onSpin_id;
84 static AbSymmetry *sym;
85 static GtkWidget *lblSymName, *lblSymId, *lblSymWarning, *spinTol;
86 static GtkWidget *spinNode, *vbox, *vboxSym;
87 static guint timeout = 0;
88 static VisuInteractive *inter;
89 static GtkListStore *symList;
90
91 static void onSelection(VisuInteractive *inter, VisuInteractivePick pick,
92 VisuNodeArray *array, VisuNode *node0,
93 VisuNode *node1, VisuNode *node2, gpointer data);
94 static void onSymmetryToggled(GtkToggleButton *toggle, gpointer data);
95 static void onSymmetryClicked(GtkButton *button, gpointer data);
96 static void onTolChanged(GtkSpinButton *spin, gpointer data);
97 static void onVisuDataChanged(VisuUiMain *visu, VisuData *dataObj, gpointer data);
98 static void onSpinNode(GtkSpinButton *button, gpointer data);
99
100 static gchar* symAnalyse(AbSymmetry *sym, int iSym);
101 static void getEquivalents(VisuData *dataObj, VisuNode *node);
102 static void updateSymmetries(VisuData *dataObj, gdouble tol);
103 static void formatSymOperators(GtkTreeViewColumn *column, GtkCellRenderer *cell,
104 GtkTreeModel *model, GtkTreeIter *iter, gpointer data);
105
buildTab(VisuUiMain * main,gchar ** label,gchar ** help,GtkWidget ** radio)106 GtkWidget* buildTab(VisuUiMain *main, gchar **label,
107 gchar **help, GtkWidget **radio)
108 {
109 GtkWidget *wd, *hbox, *bt, *scroll;
110 VisuData *data;
111 VisuUiRenderingWindow *window;
112 VisuGlNodeScene *scene;
113 GtkCellRenderer *renderer;
114 GtkTreeViewColumn *column;
115
116 window = visu_ui_main_class_getDefaultRendering();
117 scene = visu_ui_rendering_window_getGlScene(window);
118 data = visu_gl_node_scene_getData(scene);
119 g_return_val_if_fail(data, (GtkWidget*)0);
120
121 inter = visu_interactive_new(interactive_pick);
122 g_signal_connect_swapped(G_OBJECT(inter), "stop",
123 G_CALLBACK(visu_ui_interactive_toggle), (gpointer)0);
124 g_signal_connect(G_OBJECT(inter), "node-selection",
125 G_CALLBACK(onSelection), (gpointer)0);
126
127 *label = _("Symmetries");
128 *help = g_strdup(ABINIT_SYMMETRIES_INFO);
129
130 symList = gtk_list_store_new(SYM_N_COLS, G_TYPE_INT,
131 G_TYPE_INT, G_TYPE_INT, G_TYPE_INT,
132 G_TYPE_INT, G_TYPE_INT, G_TYPE_INT,
133 G_TYPE_INT, G_TYPE_INT, G_TYPE_INT,
134 G_TYPE_FLOAT, G_TYPE_FLOAT, G_TYPE_FLOAT,
135 G_TYPE_STRING);
136
137 vbox = gtk_vbox_new(FALSE, 0);
138 g_signal_connect_swapped(vbox, "destroy", G_CALLBACK(g_object_unref), inter);
139
140 sym = (AbSymmetry*)0;
141
142 hbox = gtk_hbox_new(FALSE, 0);
143 gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0);
144
145 *radio = gtk_radio_button_new_with_mnemonic
146 (NULL, _("Analyse the symmetries"));
147 gtk_box_pack_start(GTK_BOX(hbox), *radio, FALSE, FALSE, 0);
148 gtk_widget_set_name(*radio, "message_radio");
149 g_signal_connect(G_OBJECT(*radio), "toggled",
150 G_CALLBACK(onSymmetryToggled), (gpointer)0);
151 wd = gtk_button_new_with_mnemonic(_("Compute symmetries"));
152 bt = wd;
153 gtk_box_pack_end(GTK_BOX(hbox), wd, FALSE, FALSE, 0);
154 wd = gtk_label_new(") ");
155 gtk_box_pack_end(GTK_BOX(hbox), wd, FALSE, FALSE, 0);
156 wd = gtk_spin_button_new_with_range(-10, -2, 1);
157 gtk_entry_set_width_chars(GTK_ENTRY(wd), 2);
158 gtk_spin_button_set_value(GTK_SPIN_BUTTON(wd), -6);
159 g_signal_connect(G_OBJECT(wd), "value-changed",
160 G_CALLBACK(onTolChanged), (gpointer)0);
161 g_signal_connect(G_OBJECT(bt), "clicked",
162 G_CALLBACK(onSymmetryClicked), (gpointer)wd);
163 gtk_box_pack_end(GTK_BOX(hbox), wd, FALSE, FALSE, 0);
164 spinTol = wd;
165 wd = gtk_label_new("(tolsym = 10^");
166 gtk_box_pack_end(GTK_BOX(hbox), wd, FALSE, FALSE, 0);
167
168 vboxSym = gtk_vbox_new(FALSE, 0);
169 gtk_widget_set_sensitive(vboxSym, FALSE);
170 gtk_box_pack_start(GTK_BOX(vbox), vboxSym, TRUE, TRUE, 0);
171
172 /* A message for ABINIT. */
173 wd = gtk_label_new(_("<span size=\"smaller\">The symmetry routines"
174 " are provided by ABINIT ("
175 "<span font_desc=\"courier\" color=\"blue\">"
176 "http://www.abinit.org</span>).</span>"));
177 gtk_widget_set_halign(wd, 1.0);
178 gtk_label_set_use_markup(GTK_LABEL(wd), TRUE);
179 gtk_box_pack_end(GTK_BOX(vbox), wd, FALSE, FALSE, 5);
180
181 /* The labels showing the symmetry. */
182 hbox = gtk_hbox_new(FALSE, 0);
183 gtk_box_pack_start(GTK_BOX(vboxSym), hbox, FALSE, FALSE, 10);
184 wd = gtk_label_new(_("<b>Space group:</b>"));
185 gtk_label_set_use_markup(GTK_LABEL(wd), TRUE);
186 gtk_widget_set_margin_start(wd, 10);
187 gtk_box_pack_start(GTK_BOX(hbox), wd, FALSE, FALSE, 0);
188 wd = gtk_label_new(_("<span font_desc=\"courier\" color=\"blue\">"
189 "http://en.wikipedia.org/wiki/Space_group</span>"));
190 gtk_label_set_selectable(GTK_LABEL(wd), TRUE);
191 gtk_label_set_use_markup(GTK_LABEL(wd), TRUE);
192 gtk_box_pack_end(GTK_BOX(hbox), wd, FALSE, FALSE, 10);
193 wd = gtk_image_new_from_icon_name("help-browser", GTK_ICON_SIZE_MENU);
194 gtk_box_pack_end(GTK_BOX(hbox), wd, FALSE, FALSE, 0);
195 hbox = gtk_hbox_new(FALSE, 0);
196 gtk_box_pack_start(GTK_BOX(vboxSym), hbox, FALSE, FALSE, 0);
197 wd = gtk_label_new(_("Crystal system:"));
198 gtk_box_pack_start(GTK_BOX(hbox), wd, FALSE, FALSE, 0);
199 lblSymName = gtk_label_new("");
200 gtk_widget_set_halign(lblSymName, 0.);
201 gtk_box_pack_start(GTK_BOX(hbox), lblSymName, TRUE, TRUE, 5);
202 wd = gtk_label_new(_("space group:"));
203 gtk_box_pack_start(GTK_BOX(hbox), wd, FALSE, FALSE, 0);
204 lblSymId = gtk_label_new("");
205 gtk_label_set_use_markup(GTK_LABEL(lblSymId), TRUE);
206 gtk_widget_set_halign(lblSymId, 0.);
207 gtk_box_pack_start(GTK_BOX(hbox), lblSymId, TRUE, TRUE, 5);
208 lblSymWarning = gtk_label_new(_("<span color=\"red\">Warning:</span> the Bravais lattice determined from the primitive vectors is more symmetric than the real one obtained from coordinates (printed)."));
209 gtk_label_set_use_markup(GTK_LABEL(lblSymWarning), TRUE);
210 gtk_label_set_line_wrap(GTK_LABEL(lblSymWarning), TRUE);
211 gtk_label_set_line_wrap_mode(GTK_LABEL(lblSymWarning), PANGO_WRAP_WORD);
212 gtk_box_pack_start(GTK_BOX(vboxSym), lblSymWarning, FALSE, FALSE, 0);
213 wd = gtk_label_new(_("List of symmetry operations:"));
214 gtk_widget_set_halign(wd, 0.);
215 gtk_box_pack_start(GTK_BOX(vboxSym), wd, FALSE, FALSE, 3);
216 scroll = gtk_scrolled_window_new(NULL, NULL);
217 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scroll),
218 GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS);
219 gtk_box_pack_start(GTK_BOX(vboxSym), scroll, TRUE, TRUE, 0);
220 wd = gtk_tree_view_new_with_model(GTK_TREE_MODEL(symList));
221 gtk_container_add(GTK_CONTAINER(scroll), wd);
222 renderer = gtk_cell_renderer_text_new();
223 column = gtk_tree_view_column_new_with_attributes(_("Id"), renderer,
224 "text", SYM_ID, NULL);
225 gtk_tree_view_append_column(GTK_TREE_VIEW(wd), column);
226 renderer = gtk_cell_renderer_text_new ();
227 column = gtk_tree_view_column_new();
228 gtk_tree_view_column_set_title(column, _("operation"));
229 gtk_tree_view_column_pack_start(column, renderer, TRUE);
230 gtk_tree_view_column_set_cell_data_func
231 (column, renderer, formatSymOperators,
232 GINT_TO_POINTER(SYM_MATRIX_00), (GDestroyNotify)0);
233 gtk_tree_view_append_column(GTK_TREE_VIEW(wd), column);
234 renderer = gtk_cell_renderer_text_new ();
235 column = gtk_tree_view_column_new();
236 gtk_tree_view_column_set_title(column, _("translation"));
237 gtk_tree_view_column_pack_start(column, renderer, TRUE);
238 gtk_tree_view_column_set_cell_data_func
239 (column, renderer, formatSymOperators,
240 GINT_TO_POINTER(SYM_TRANS_0), (GDestroyNotify)0);
241 gtk_tree_view_append_column(GTK_TREE_VIEW(wd), column);
242 renderer = gtk_cell_renderer_text_new();
243 column = gtk_tree_view_column_new_with_attributes(_("comment"), renderer,
244 "text", SYM_COMMENT, NULL);
245 gtk_tree_view_append_column(GTK_TREE_VIEW(wd), column);
246
247 /* The interface to choose one atom to select. */
248 wd = gtk_label_new(_("<b>Equivalent atoms:</b>"));
249 gtk_label_set_use_markup(GTK_LABEL(wd), TRUE);
250 gtk_widget_set_halign(wd, 0.);
251 gtk_widget_set_margin_start(wd, 10);
252 gtk_box_pack_start(GTK_BOX(vboxSym), wd, FALSE, FALSE, 10);
253 hbox = gtk_hbox_new(FALSE, 0);
254 gtk_box_pack_start(GTK_BOX(vboxSym), hbox, FALSE, FALSE, 0);
255 wd = gtk_label_new(_("Visualise the equivalent nodes of node:"));
256 gtk_box_pack_start(GTK_BOX(hbox), wd, FALSE, FALSE, 0);
257 spinNode = gtk_spin_button_new_with_range(0, 1, 1);
258 onSpin_id = g_signal_connect(G_OBJECT(spinNode), "value-changed",
259 G_CALLBACK(onSpinNode), (gpointer)0);
260 gtk_box_pack_start(GTK_BOX(hbox), spinNode, FALSE, FALSE, 5);
261 wd = gtk_label_new(_(" or pick directly."));
262 gtk_box_pack_start(GTK_BOX(hbox), wd, FALSE, FALSE, 0);
263
264 gtk_widget_show_all(vbox);
265 gtk_widget_hide(lblSymWarning);
266
267 g_signal_connect(main, "DataFocused", G_CALLBACK(onVisuDataChanged), (gpointer)0);
268 onVisuDataChanged((VisuUiMain*)0, data, (gpointer)0);
269
270 return vbox;
271 }
formatSymOperators(GtkTreeViewColumn * column _U_,GtkCellRenderer * cell,GtkTreeModel * model,GtkTreeIter * iter,gpointer data)272 static void formatSymOperators(GtkTreeViewColumn *column _U_, GtkCellRenderer *cell,
273 GtkTreeModel *model, GtkTreeIter *iter, gpointer data)
274 {
275 gchar *str;
276 gfloat valf[3];
277 gint vali[9];
278
279 str = (gchar*)0;
280 if (GPOINTER_TO_INT(data) == SYM_MATRIX_00)
281 {
282 gtk_tree_model_get(model, iter, SYM_MATRIX_00, vali,
283 SYM_MATRIX_01, vali + 1,
284 SYM_MATRIX_02, vali + 2,
285 SYM_MATRIX_10, vali + 3,
286 SYM_MATRIX_11, vali + 4,
287 SYM_MATRIX_12, vali + 5,
288 SYM_MATRIX_20, vali + 6,
289 SYM_MATRIX_21, vali + 7,
290 SYM_MATRIX_22, vali + 8,
291 -1);
292 str = g_strdup_printf("[ %2d %2d %2d\n"
293 " %2d %2d %2d\n"
294 " %2d %2d %2d ]", vali[0], vali[1], vali[2],
295 vali[3], vali[4], vali[5], vali[6], vali[7], vali[8]);
296 }
297 else if (GPOINTER_TO_INT(data) == SYM_TRANS_0)
298 {
299 gtk_tree_model_get(model, iter, SYM_TRANS_0, valf,
300 SYM_TRANS_1, valf + 1,
301 SYM_TRANS_2, valf + 2,
302 -1);
303 str = g_strdup_printf("[ %2f\n"
304 " %2f\n"
305 " %2f ]", valf[0], valf[1], valf[2]);
306 }
307 if (str)
308 {
309 g_object_set(G_OBJECT(cell), "text", str, NULL);
310 g_free(str);
311 }
312 }
313
startSelect(VisuUiRenderingWindow * window)314 void startSelect(VisuUiRenderingWindow *window)
315 {
316 visu_ui_rendering_window_pushInteractive(window, inter);
317 }
stopSelect(VisuUiRenderingWindow * window)318 void stopSelect(VisuUiRenderingWindow *window)
319 {
320 visu_ui_rendering_window_popInteractive(window, inter);
321 }
322
onSelection(VisuInteractive * inter _U_,VisuInteractivePick pick _U_,VisuNodeArray * array,VisuNode * node0,VisuNode * node1 _U_,VisuNode * node2 _U_,gpointer data _U_)323 static void onSelection(VisuInteractive *inter _U_, VisuInteractivePick pick _U_,
324 VisuNodeArray *array, VisuNode *node0,
325 VisuNode *node1 _U_, VisuNode *node2 _U_, gpointer data _U_)
326 {
327 getEquivalents(VISU_DATA(array), node0);
328 g_signal_handler_block(G_OBJECT(spinNode), onSpin_id);
329 gtk_spin_button_set_value(GTK_SPIN_BUTTON(spinNode), node0->number + 1);
330 g_signal_handler_unblock(G_OBJECT(spinNode), onSpin_id);
331 }
332
onSymmetryToggled(GtkToggleButton * toggle _U_,gpointer data _U_)333 static void onSymmetryToggled(GtkToggleButton *toggle _U_, gpointer data _U_)
334 {
335 }
onSymmetryClicked(GtkButton * button _U_,gpointer spin)336 static void onSymmetryClicked(GtkButton *button _U_, gpointer spin)
337 {
338 VisuData *dataObj;
339
340 /* Get the current VisuData object. */
341 dataObj = visu_gl_node_scene_getData(visu_ui_rendering_window_getGlScene(visu_ui_main_class_getDefaultRendering()));
342
343 updateSymmetries(dataObj, gtk_spin_button_get_value(GTK_SPIN_BUTTON(spin)));
344 }
onTolChanged(GtkSpinButton * spin,gpointer data _U_)345 static void onTolChanged(GtkSpinButton *spin, gpointer data _U_)
346 {
347 VisuData *dataObj;
348
349 /* Get the current VisuData object. */
350 dataObj = visu_gl_node_scene_getData(visu_ui_rendering_window_getGlScene(visu_ui_main_class_getDefaultRendering()));
351
352 updateSymmetries(dataObj, gtk_spin_button_get_value(spin));
353 }
onVisuDataChanged(VisuUiMain * visu _U_,VisuData * dataObj,gpointer data _U_)354 static void onVisuDataChanged(VisuUiMain *visu _U_, VisuData *dataObj,
355 gpointer data _U_)
356 {
357 VisuNodeArrayIter iter;
358
359 gtk_widget_set_sensitive(vbox, (dataObj !=(VisuData*)0));
360
361 updateSymmetries((VisuData*)0, 0);
362
363 if (dataObj)
364 {
365 visu_node_array_iter_new(VISU_NODE_ARRAY(dataObj), &iter);
366 gtk_spin_button_set_range(GTK_SPIN_BUTTON(spinNode), 0, iter.idMax + 1);
367 }
368 }
onSpinNode(GtkSpinButton * button,gpointer data _U_)369 static void onSpinNode(GtkSpinButton *button, gpointer data _U_)
370 {
371 VisuData *dataObj;
372 VisuNode *node;
373
374 if (gtk_spin_button_get_value(button) == 0)
375 return;
376
377 /* Get the current VisuData object. */
378 dataObj = visu_gl_node_scene_getData(visu_ui_rendering_window_getGlScene(visu_ui_main_class_getDefaultRendering()));
379 node = visu_node_array_getFromId(VISU_NODE_ARRAY(dataObj),
380 (int)gtk_spin_button_get_value(button) - 1);
381
382 getEquivalents(dataObj, node);
383 }
onRemoveEquivalents(gpointer data _U_)384 static gboolean onRemoveEquivalents(gpointer data _U_)
385 {
386 timeout = 0;
387 return FALSE;
388 }
389
removeEquivalents(gpointer data)390 static void removeEquivalents(gpointer data)
391 {
392 VisuGlExtMarks *marks;
393 GArray *ids;
394
395 ids = (GArray*)data;
396
397 /* Get the current VisuData object. */
398 marks = visu_gl_node_scene_getMarks(visu_ui_rendering_window_getGlScene(visu_ui_main_class_getDefaultRendering()));
399
400 visu_gl_ext_marks_setHighlight(marks, ids, MARKS_STATUS_TOGGLE);
401 g_array_unref(ids);
402 }
getEquivalents(VisuData * dataObj,VisuNode * node)403 static void getEquivalents(VisuData *dataObj, VisuNode *node)
404 {
405 guint j;
406 int i, nSym;
407 int *nodes;
408 GArray *ids;
409 gboolean found;
410 #if GLIB_MINOR_VERSION > 13
411 #define fact 1
412 #define G_TIMEOUT_ADD_FULL g_timeout_add_seconds_full
413 #else
414 #define fact 1000
415 #define G_TIMEOUT_ADD_FULL g_timeout_add_full
416 #endif
417
418 if (!sym)
419 updateSymmetries(dataObj, gtk_spin_button_get_value(GTK_SPIN_BUTTON(spinTol)));
420 g_return_if_fail(sym);
421
422 if (ab_symmetry_get_equivalent_atom(sym, &nodes, &nSym, node->number + 1) ==
423 AB_NO_ERROR)
424 {
425 ids = g_array_new(FALSE, FALSE, sizeof(guint));
426 for (i = 0; i < nSym; i++)
427 {
428 found = FALSE;
429 for ( j = 0; j < ids->len && !found; j++)
430 found = (nodes[i * 4 + 3] == g_array_index(ids, int, j) + 1);
431 if (!found)
432 {
433 j = nodes[i * 4 + 3] - 1;
434 g_array_append_val(ids, j);
435 }
436 }
437 g_free(nodes);
438
439 /* We remove possible earlier timeout. */
440 if (timeout > 0)
441 g_source_remove(timeout);
442
443 /* Set the new highlights. */
444 visu_gl_ext_marks_setHighlight
445 (visu_gl_node_scene_getMarks(visu_ui_rendering_window_getGlScene(visu_ui_main_class_getDefaultRendering())),
446 ids, MARKS_STATUS_SET);
447
448 /* Add the new timeout. */
449 timeout = G_TIMEOUT_ADD_FULL(G_PRIORITY_DEFAULT, 3 * fact,
450 onRemoveEquivalents, ids, removeEquivalents);
451 /* ids will be freed in the timeout. */
452 }
453 }
454
startThreadSymmetry(gpointer data _U_)455 gpointer startThreadSymmetry(gpointer data _U_)
456 {
457 float xred0[3], xyz[3];
458 char *spGrp;
459 double box[3][3], genAfm[3], *xred;
460 int i, *typat, grpId, grpMagnId;
461 AbError error;
462 VisuNodeArrayIter iter;
463
464 AbinitData *dt;
465
466 DBG_fprintf(stderr, "AB symmetry(%p): starting symmetry detection.\n",
467 (gpointer)g_thread_self());
468 dt = abinit_getDt();
469
470 visu_box_getCellMatrix(visu_boxed_getBox(VISU_BOXED(dt->data)), box);
471 ab_symmetry_set_lattice(dt->sym, box);
472
473 visu_node_array_iter_new(VISU_NODE_ARRAY(dt->data), &iter);
474 i = 0;
475 typat = g_malloc(sizeof(int) * iter.nAllStoredNodes);
476 xred = g_malloc(sizeof(double) * 3 * iter.nAllStoredNodes);
477 for (visu_node_array_iterStart(VISU_NODE_ARRAY(dt->data), &iter); iter.node;
478 visu_node_array_iterNext(VISU_NODE_ARRAY(dt->data), &iter))
479 {
480 typat[i] = iter.iElement;
481 visu_data_getNodePosition(dt->data, iter.node, xyz);
482 visu_box_convertXYZtoBoxCoordinates(visu_boxed_getBox(VISU_BOXED(dt->data)), xred0, xyz);
483 xred[3 * i + 0] = (double)xred0[0];
484 xred[3 * i + 1] = (double)xred0[1];
485 xred[3 * i + 2] = (double)xred0[2];
486 i += 1;
487 }
488 ab_symmetry_set_structure(dt->sym, iter.nAllStoredNodes, typat, xred);
489 g_free(typat);
490 g_free(xred);
491
492 /* Ask for the calculation of the symmetries. */
493 DBG_fprintf(stderr, "AB symmetry(%p): Ready to get symmetries from ABINIT.\n",
494 (gpointer)g_thread_self());
495 error = ab_symmetry_get_group(dt->sym, &spGrp, &grpId,
496 &grpMagnId, genAfm);
497 DBG_fprintf(stderr, "AB symmetry(%p): return from ABINIT (%d).\n",
498 (gpointer)g_thread_self(), error);
499 if (error == AB_NO_ERROR || errno == AB_ERROR_SYM_BRAVAIS_XRED)
500 g_free(spGrp);
501 else if (error != AB_ERROR_SYM_NOT_PRIMITIVE)
502 dt->error = g_error_new(TOOL_FILE_FORMAT_ERROR, TOOL_FILE_FORMAT_ERROR_METHOD,
503 "An error occured in ABINIT plug-in.");
504 abinit_mutexUnlock();
505
506 return (gpointer)0;
507 }
508
updateSymmetries(VisuData * dataObj,gdouble tol)509 static void updateSymmetries(VisuData *dataObj, gdouble tol)
510 {
511 double genAfm[3];
512 int grpId, grpMagnId, centerId, nbrv;
513 char *spGrp;
514 gchar *str;
515 AbSymmetryMat *brvSyms;
516 int brvMat[3][3];
517 gchar *bravais[7] = {"triclinic", "monoclinic", "orthorhombic",
518 "tetragonal", "trigonal", "hexagonal", "cubic"};
519 gchar *center[7] = {"F", "F", "I", "P", "A", "B", "C"};
520 AbError error;
521 #ifdef G_THREADS_ENABLED
522 GThread *ld_thread;
523 #endif
524 int nSym, *amf, iSym;
525 AbSymmetryMat *symOps;
526 AbSymmetryTrans *trans;
527 GtkTreeIter iter;
528
529 AbinitData *dt;
530
531 DBG_fprintf(stderr, "Abinit: upadte symmetries from %p.\n", (gpointer)dataObj);
532
533 if (sym)
534 ab_symmetry_free(sym);
535 sym = (AbSymmetry*)0;
536 gtk_list_store_clear(symList);
537
538 if (dataObj)
539 {
540 dt = abinit_getDirectDt();
541 dt->data = dataObj;
542 dt->sym = ab_symmetry_new();
543 dt->getMessages = FALSE;
544 dt->useSignals = FALSE;
545 DBG_fprintf(stderr, "AB symmetry: set tolerance to 10^%g.\n", tol);
546 ab_symmetry_set_tolerance(dt->sym, pow(10., tol));
547 #ifdef G_THREADS_ENABLED
548 abinit_mutexInit();
549 dt->error = (GError*)0;
550 #if GLIB_MINOR_VERSION < 32
551 ld_thread = g_thread_create(startThreadSymmetry, (gpointer)0,
552 TRUE, &(dt->error));
553 #else
554 ld_thread = g_thread_new(NULL, startThreadSymmetry, (gpointer)0);
555 #endif
556 DBG_fprintf(stderr, "AB symmetry: run ABINIT symmetry into a thread (%p).\n",
557 (gpointer)ld_thread);
558 if (ld_thread)
559 g_thread_join(ld_thread);
560 else
561 g_warning("Can't run thread for ABINIT symmetry.");
562 abinit_mutexRelease();
563 #else
564 startThreadSymmetry((gpointer)(&dt));
565 #endif
566 DBG_fprintf(stderr, "AB symmetry: return after thread exec (%p).\n",
567 (gpointer)dt->error);
568 if (!dt->error)
569 {
570 sym = dt->sym;
571
572 /* We get then the space group. */
573 DBG_fprintf(stderr, "AB symmetry: get group.\n");
574 error = ab_symmetry_get_group(sym, &spGrp, &grpId,
575 &grpMagnId, genAfm);
576 if (error == AB_NO_ERROR || errno == AB_ERROR_SYM_BRAVAIS_XRED)
577 {
578 str = g_strdup_printf("%s (#%d)", spGrp, grpId);
579 gtk_label_set_text(GTK_LABEL(lblSymId), str);
580 g_free(str);
581 g_free(spGrp);
582
583 DBG_fprintf(stderr, "AB symmetry: get matrices.\n");
584 if (ab_symmetry_get_matrices(sym, &nSym, &symOps, &trans, &amf) ==
585 AB_NO_ERROR)
586 {
587 for (iSym = 0; iSym < nSym; iSym++)
588 {
589 str = symAnalyse(dt->sym, iSym + 1);
590 gtk_list_store_append(symList, &iter);
591 gtk_list_store_set(symList, &iter, SYM_ID, iSym + 1,
592 SYM_MATRIX_00, symOps[iSym].mat[0][0],
593 SYM_MATRIX_01, symOps[iSym].mat[0][1],
594 SYM_MATRIX_02, symOps[iSym].mat[0][2],
595 SYM_MATRIX_10, symOps[iSym].mat[1][0],
596 SYM_MATRIX_11, symOps[iSym].mat[1][1],
597 SYM_MATRIX_12, symOps[iSym].mat[1][2],
598 SYM_MATRIX_20, symOps[iSym].mat[2][0],
599 SYM_MATRIX_21, symOps[iSym].mat[2][1],
600 SYM_MATRIX_22, symOps[iSym].mat[2][2],
601 SYM_TRANS_0, trans[iSym].vect[0],
602 SYM_TRANS_1, trans[iSym].vect[1],
603 SYM_TRANS_2, trans[iSym].vect[2],
604 SYM_COMMENT, str,
605 -1);
606 g_free(str);
607 }
608 g_free(symOps);
609 g_free(trans);
610 g_free(amf);
611 }
612 }
613 else
614 {
615 gtk_label_set_markup(GTK_LABEL(lblSymId), _("<i>not primitive</i>"));
616 }
617 DBG_fprintf(stderr, "AB symmetry: get bravais.\n");
618 if (ab_symmetry_get_bravais(sym, brvMat, &grpId,
619 ¢erId, &nbrv, &brvSyms) == AB_NO_ERROR)
620 {
621 g_free(brvSyms);
622 str = g_strdup_printf("%s (%s)", _(bravais[grpId - 1]),
623 center[centerId+3]);
624 gtk_label_set_text(GTK_LABEL(lblSymName), str);
625 g_free(str);
626 }
627 else
628 gtk_label_set_text(GTK_LABEL(lblSymName), "!");
629
630 /* If the bravais lattice doesn't match with the xred bravais
631 lattice, we print a message. */
632 if (error == AB_ERROR_SYM_BRAVAIS_XRED)
633 gtk_widget_show(lblSymWarning);
634 else
635 gtk_widget_hide(lblSymWarning);
636
637 gtk_widget_set_sensitive(vboxSym, (dataObj != (VisuData*)0));
638 }
639 else
640 {
641 visu_ui_raiseWarning(_("ABINIT symmetry calculation"),
642 dt->error->message, (GtkWindow*)0);
643 g_error_free(dt->error);
644 ab_symmetry_free(dt->sym);
645 sym = (AbSymmetry*)0;
646
647 gtk_widget_set_sensitive(vboxSym, FALSE);
648 }
649 }
650 else
651 {
652 gtk_label_set_text(GTK_LABEL(lblSymName), "");
653 gtk_label_set_text(GTK_LABEL(lblSymId), "");
654 }
655 }
656
symAnalyse(AbSymmetry * sym,int iSym)657 static gchar* symAnalyse(AbSymmetry *sym, int iSym)
658 {
659 AbError error;
660 int type;
661 gchar *label;
662
663
664 error = ab_symmetry_get_type(sym, &type, &label, iSym);
665 if (error == AB_NO_ERROR)
666 return label;
667 else
668 return g_strdup(_("Unknown symmetry"));
669 }
670