atomes 1.2.1
atomes: an atomic scale modeling tool box
Loading...
Searching...
No Matches
read_cif.c
Go to the documentation of this file.
1/* This file is part of the 'atomes' software
2
3'atomes' is free software: you can redistribute it and/or modify it under the terms
4of the GNU Affero General Public License as published by the Free Software Foundation,
5either version 3 of the License, or (at your option) any later version.
6
7'atomes' is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
8without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
9See the GNU General Public License for more details.
10
11You should have received a copy of the GNU Affero General Public License along with 'atomes'.
12If not, see <https://www.gnu.org/licenses/>
13
14Copyright (C) 2022-2025 by CNRS and University of Strasbourg */
15
22/*
23* This file: 'read_cif.c'
24*
25* Contains:
26*
27
28 - The functions to read CIF files
29
30*
31* List of functions:
32
33 int get_atom_wyckoff (gchar * line, int wid);
34 int cif_get_value int cif_get_value (gchar * kroot, gchar * keyw, int lstart, int linec, gchar ** cif_word,
35 gboolean rec_val, gboolean all_ligne, gboolean total_num, gboolean record_position, int * line_position)
36 int cif_file_get_data_in_loop (int linec, int lid);
37 int cif_file_get_number_of_atoms (int linec, int lid, int nelem);
38 int get_loop_line_id (int lid);
39 int get_loop_line_for_key (int linec, int conf, gchar * key_a, gchar * key_b);
40 int cif_file_get_number_of_positions (int lid);
41 int get_space_group_from_hm (gchar * hmk);
42 int get_setting_from_hm (gchar * hmk, int end);
43 int group_info_from_hm_key (int spg, gchar * key_hm);
44 int cif_get_space_group (int linec);
45 int open_cif_configuration (int linec, int conf);
46 int open_cif_file (int linec);
47
48 float get_atom_coord (gchar * line, int mid);
49
50 gboolean get_missing_object_from_user ();
51 gboolean cif_file_get_atoms_data (int conf, int lin, int cid[8]);
52 gboolean cif_get_atomic_coordinates (int linec);
53 gboolean cif_get_symmetry_positions (int linec);
54 gboolean cif_get_cell_data (int linec, int conf);
55
56 gchar * get_cif_word (gchar * mot);
57 gchar * get_atom_label (gchar * line, int lid);
58 gchar * get_atom_disorder (gchar * line, int lid);
59 gchar * get_string_from_origin (space_group * spg);
60 gchar * cif_retrieve_value (int linec, int conf, gchar * key_a, gchar * key_b, gboolean all_ligne, gboolean in_loop, gboolean warning);
61
62 G_MODULE_EXPORT void set_cif_to_insert (GtkComboBox * box, gpointer data);
63 void file_get_to_line (int line_id);
64 void check_for_to_lab (int ato, gchar * stlab);
65
66*/
67
68#include "global.h"
69#include "bind.h"
70#include "interface.h"
71#include "project.h"
72#include "atom_edit.h"
73#include "cbuild_edit.h"
74#include "readers.h"
75#include <ctype.h>
76#ifdef OPENMP
77# include <omp.h>
78#endif
79
80extern int get_atom_id_from_periodic_table (atom_search * asearch);
81extern double get_z_from_periodic_table (gchar * lab);
82extern void get_origin (space_group * spg);
83extern void compute_lattice_properties (cell_info * cell, int box_id);
84extern int test_lattice (builder_edition * cbuilder, cell_info * cif_cell);
85extern int read_space_group (builder_edition * cbuilder, int spg);
86extern gchar * wnpos[3];
87extern void get_wyck_char (float val, int ax, int bx);
89extern distance distance_3d (cell_info * cell, int mdstep, atom * at, atom * bt);
90extern void sort (int dim, int * tab);
91
92extern gchar * tmp_pos;
93
94FILE * cifp;
95char * line_ptr;
96int * keylines = NULL;
100int * cif_lot = NULL;
101int * cif_nsps = NULL;
102
103gboolean cif_multiple = FALSE;
104
105gchar ** cif_strings = NULL;
106
107gchar * cif_coord_opts[40][2] = {{"b1", "Monoclinic unique axis b, cell choice 1, abc"}, // 0
108 {"b2", "Monoclinic unique axis b, cell choice 2, abc"}, // 1
109 {"b3", "Monoclinic unique axis b, cell choice 3, abc"}, // 2
110 {"-b1", "Monoclinic unique axis b, cell choice 1, c-ba"}, // 3
111 {"-b2", "Monoclinic unique axis b, cell choice 2, c-ba"}, // 4
112 {"-b3", "Monoclinic unique axis b, cell choice 3, c-ba"}, // 5
113 {"c1", "Monoclinic unique axis c, cell choice 1, abc"}, // 6
114 {"c2", "Monoclinic unique axis c, cell choice 2, abc"}, // 7
115 {"c3", "Monoclinic unique axis c, cell choice 3, abc"}, // 8
116 {"-c1", "Monoclinic unique axis c, cell choice 1, ba-c"}, // 9
117 {"-c2", "Monoclinic unique axis c, cell choice 2, ba-c"}, // 10
118 {"-c3", "Monoclinic unique axis c, cell choice 3, ba-c"}, // 11
119 {"a1", "Monoclinic unique axis a, cell choice 1, abc"}, // 12
120 {"a2", "Monoclinic unique axis a, cell choice 2, abc"}, // 13
121 {"a3", "Monoclinic unique axis a, cell choice 3, abc"}, // 14
122 {"-a1", "Monoclinic unique axis a, cell choice 1, -acb"}, // 15
123 {"-a2", "Monoclinic unique axis a, cell choice 2, -acb"}, // 16
124 {"-a3", "Monoclinic unique axis a, cell choice 3, -acb"}, // 17
125 {"abc", "Orthorhombic"}, // 18
126 {"ba-c", "Orthorhombic"}, // 10
127 {"cab", "Orthorhombic"}, // 20
128 {"-cba", "Orthorhombic"}, // 21
129 {"bca", "Orthorhombic"}, // 22
130 {"a-cb", "Orthorhombic"}, // 23
131 {"1abc", "Orthorhombic origin choice 1"}, // 24
132 {"1ba-c", "Orthorhombic origin choice 1"}, // 25
133 {"1cab", "Orthorhombic origin choice 1"}, // 26
134 {"1-cba", "Orthorhombic origin choice 1"}, // 27
135 {"1bca", "Orthorhombic origin choice 1"}, // 28
136 {"1a-cb", "rthorhombic origin choice 1"}, // 29
137 {"2abc", "Orthorhombic origin choice 2"}, // 30
138 {"2ba-c", "Orthorhombic origin choice 2"}, // 31
139 {"2cab", "Orthorhombic origin choice 2"}, // 32
140 {"2-cba", "Orthorhombic origin choice 2"}, // 33
141 {"2bca", "Orthorhombic origin choice 2"}, // 34
142 {"2a-cb", "Orthorhombic origin choice 2"}, // 35
143 {"1", "Tetragonal or cubic origin choice 1"}, // 36
144 {"2", "Tetragonal or cubic origin choice 2"}, // 37
145 {"h", "Trigonal using hexagonal axes"}, // 38
146 {"r", "Trigonal using rhombohedral axes "}}; // 39
147
148#ifdef G_OS_WIN32
149 typedef intptr_t ssize_t;
150
151 ssize_t getline(char **lineptr, size_t *n, FILE *stream)
152 {
153 size_t pos;
154 int c;
155
156 if (lineptr == NULL || stream == NULL || n == NULL)
157 {
158 errno = EINVAL;
159 return -1;
160 }
161
162 c = getc(stream);
163 if (c == EOF) return -1;
164
165 if (*lineptr == NULL)
166 {
167 *lineptr = malloc(128);
168 if (*lineptr == NULL) return -1;
169 *n = 128;
170 }
171
172 pos = 0;
173 while(c != EOF)
174 {
175 if (pos + 1 >= *n)
176 {
177 size_t new_size = *n + (*n >> 2);
178 if (new_size < 128)
179 {
180 new_size = 128;
181 }
182 char *new_ptr = realloc(*lineptr, new_size);
183 if (new_ptr == NULL) return -1;
184 *n = new_size;
185 *lineptr = new_ptr;
186 }
187
188 ((unsigned char *)(*lineptr))[pos ++] = c;
189 if (c == '\n') break;
190 c = getc(stream);
191 }
192
193 (*lineptr)[pos] = '\0';
194 return pos;
195 }
196#endif // G_OS_WIN_32
197
205gchar * get_cif_word (gchar * mot)
206{
207 gchar * word = substitute_string (mot, "\n", NULL);
208 word = substitute_string (word, "\r", NULL);
209 return word;
210}
211
220float get_atom_coord (gchar * line, int mid)
221{
222 gchar * co_line;
223 gchar * init = g_strdup_printf ("%s", line);
224 char * co_word = strtok_r (init, " ", & co_line);
225 int i;
226 for (i=0; i<mid-1; i++)
227 {
228 co_word = strtok_r (NULL, " ", & co_line);
229 }
230 double v = string_to_double ((gpointer)get_cif_word(co_word));
231 g_free (init);
232 return v;
233}
234
243gchar * get_atom_label (gchar * line, int lid)
244{
245 gchar * at_line;
246 gchar * init = g_strdup_printf ("%s", line);
247 char * at_word = strtok_r (init, " ", & at_line);
248 int i;
249 for (i=0; i<lid-1; i++) at_word = strtok_r (NULL, " ", & at_line);
250 gchar * str;
251 for (i=0; i<10; i++)
252 {
253 str = g_strdup_printf ("%d", i);
254 at_word = substitute_string (at_word, str, NULL);
255 g_free (str);
256 }
257 at_word = get_cif_word (at_word);
258 at_word = substitute_string (at_word, "-", NULL);
259 at_word = substitute_string (at_word, "+", NULL);
260 g_free (init);
261 return g_strdup_printf ("%c%c", at_word[0], tolower(at_word[1]));
262}
263
272int get_atom_wyckoff (gchar * line, int wid)
273{
274 gchar * wy_line;
275 gchar * init = g_strdup_printf ("%s", line);
276 char * wy_word = strtok_r (init, " ", & wy_line);
277 int i, j;
278 j = 0;
279 for (i=0; i<wid-1; i++) wy_word = strtok_r (NULL, " ", & wy_line);
280 for (i=0; i<this_reader -> lattice.sp_group -> numw; i++)
281 {
282 if (g_strcmp0(get_cif_word(wy_word), this_reader -> lattice.sp_group -> wyckoff[i].let) == 0)
283 {
284 j = i;
285 break;
286 }
287 }
288 g_free (init);
289 return j;
290}
291
300gchar * get_atom_disorder (gchar * line, int lid)
301{
302 gchar * at_line;
303 gchar * init = g_strdup_printf ("%s", line);
304 char * at_word = strtok_r (init, " ", & at_line);
305 int i;
306 for (i=0; i<lid-1; i++) at_word = strtok_r (NULL, " ", & at_line);
307 g_free (init);
308 return get_cif_word (at_word);
309}
310
311GtkWidget ** img_cif;
314
323G_MODULE_EXPORT void set_cif_to_insert (GtkComboBox * box, gpointer data)
324{
325 GValue val = {0, };
326 int i, j, k;
327 i = GPOINTER_TO_INT(data);
328 GtkTreeModel * cmodel = gtk_combo_box_get_model (box);
329 GtkTreeIter iter;
330 gchar * str;
331 gboolean done = TRUE;
332 if (gtk_combo_box_get_active_iter (box, & iter))
333 {
334 gtk_tree_model_get_value (cmodel, & iter, 0, & val);
335 str = g_strdup_printf ("%s", (char *)g_value_get_string (& val));
336 j = get_selected_object_id (FALSE, activep, str, cif_search);
338 if (j > 0)
339 {
340 gtk_tree_store_set (GTK_TREE_STORE(cmodel), & iter, 0, periodic_table_info[j].lab, -1);
341 }
342 cif_search -> todo[i] = (! j) ? 0 : 1;
343 if (! j) done = FALSE;
344 cif_search -> in_selection = 0;
345 for (k=0; k<this_reader -> object_to_insert; k++) cif_search -> in_selection += cif_search -> todo[k];
346 }
347 str = (done) ? g_strdup_printf (APPLY) : g_strdup_printf (DELETEB);
349 g_free (str);
350 if (! done) combo_set_active ((GtkWidget *)box, 0);
351}
352
359{
360 cif_search = allocate_atom_search (activep, REPLACE, 0, this_reader -> object_to_insert);
361 cif_object = NULL;
362 GtkWidget * info = dialogmodal ("Error while reading CIF file", GTK_WINDOW(MainWindow));
363 GtkWidget * vbox, * hbox;
364 gchar * str;
366 gchar * labpick = "<b>To continue and build the crystal according to the information of the CIF file\n"
367 "it is required to provide a suitable value for each and every missing parameter(s).</b>"
368 "\n\nPlease select an atom type for the following object(s):";
369 add_box_child_start (GTK_ORIENTATION_VERTICAL, vbox, markup_label (labpick, 200, -1, 0.5, 0.5), FALSE, FALSE, 10);
370 img_cif = g_malloc0(this_reader -> object_to_insert*sizeof*img_cif);
371 GtkWidget * but;
372 GtkCellRenderer * renderer;
373 GtkTreeModel * model;
374 int i;
375 for (i=0; i<this_reader -> object_to_insert; i++)
376 {
377 hbox = create_hbox(0);
378 add_box_child_start (GTK_ORIENTATION_VERTICAL, vbox, hbox, FALSE, FALSE, 5);
379 str = g_strdup_printf ("Type N°%d:\t<b>%s</b>", i+1, this_reader -> label[i]);
380 add_box_child_start (GTK_ORIENTATION_HORIZONTAL, hbox, markup_label(str, 150, -1, 0.0, 0.5), FALSE, FALSE, 20);
381 g_free (str);
384 but = gtk_combo_box_new_with_model (model);
385 g_object_unref (model);
386 renderer = gtk_cell_renderer_combo_new ();
387 gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (but), renderer, TRUE);
388 gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (but), renderer, "text", 0, NULL);
389 combo_set_active (but, 0);
390 g_signal_connect (G_OBJECT(but), "changed", G_CALLBACK(set_cif_to_insert), GINT_TO_POINTER(i));
391 combo_set_markup (but);
392 add_box_child_start (GTK_ORIENTATION_HORIZONTAL, hbox, but, FALSE, FALSE, 0);
393 add_box_child_start (GTK_ORIENTATION_HORIZONTAL, hbox, img_cif[i], FALSE, FALSE, 30);
394 }
395
396 gchar * endpick = "In case of a molecule: insert an extra type of atom and run a substitution afterwards.";
397 add_box_child_start (GTK_ORIENTATION_VERTICAL, vbox, markup_label (endpick, 200, -1, 0.5, 0.5), FALSE, FALSE, 10);
398 run_this_gtk_dialog (info, G_CALLBACK(run_destroy_dialog), NULL);
399 g_free (img_cif);
400 return (cif_search -> in_selection == this_reader -> object_to_insert) ? TRUE : FALSE;
401}
402
403#ifndef OPENMP
411void file_get_to_line (int line_id)
412{
413 int i;
414 tail = head;
415 for (i=0; i<line_id; i++) tail = tail -> next;
416}
417#endif
418
436int cif_get_value (gchar * kroot, gchar * keyw, int lstart, int lend, gchar ** cif_word,
437 gboolean rec_val, gboolean all_ligne, gboolean total_num, gboolean record_position, int * line_position)
438{
439 int res = 0;
440 int i;
441 size_t j, k, l, m;
442 gchar * str;
443 gchar * str_w, * str_a, * str_b;
444 gchar * mot;
445 gchar * saved_line;
446 gchar * the_line;
447 gchar * the_word;
448 j = strlen(kroot);
449 k = strlen(keyw);
450 l = j+k+1;
451
452#ifdef OPENMP
453 int numth = omp_get_max_threads ();
454 #pragma omp parallel for num_threads(numth) private(i,m,the_line,saved_line,the_word,mot,str_a,str_b,str_w) shared(j,k,l,this_reader,coord_line,cif_word,rec_val,all_ligne,kroot,keyw,total_num,record_position,line_position,res)
455 for (i=lstart; i<lend; i++)
456 {
457 the_line = NULL;
458 if (res && ! total_num) goto endi;
459 the_line = g_strdup_printf ("%s", coord_line[i]);
460 the_word = strtok_r (the_line, " ", & saved_line);
461 while (the_word)
462 {
463 str_w = get_cif_word (the_word);
464 str_w = g_ascii_strdown (str_w, strlen(str_w));
465 if (strlen(str_w) == l)
466 {
467 str_a = g_strdup_printf ("%c", str_w[0]);
468 for (m=1; m<j; m++) str_a = g_strdup_printf ("%s%c", str_a, str_w[m]);
469 str_b = g_strdup_printf ("%c", str_w[j+1]);
470 for (m=j+2; m<l; m++) str_b = g_strdup_printf ("%s%c", str_b, str_w[m]);
471 if (g_strcmp0(str_a, kroot) == 0 && g_strcmp0(str_b,keyw) == 0)
472 {
473 the_word = strtok_r (NULL, " ", & saved_line);
474 if (! the_word)
475 {
476 if (rec_val || all_ligne)
477 {
478 str = g_strdup_printf ("Wrong file format: searching for <b>%s</b> - error at line <b>%d</b> !\n", keyw, i+1);
479 add_reader_info (str, 0);
480 g_free (str);
481 g_free (str_w);
482 g_free (str_a);
483 g_free (str_b);
484 res = -1;
485 goto endi;
486 }
487 }
488 if (total_num)
489 {
490 #pragma omp critical
491 {
492 if (record_position)
493 {
494 line_position[res] = i + 1;
495 }
496 res ++;
497 if (this_reader -> steps && res == this_reader -> steps) total_num = FALSE;
498 }
499 }
500 else
501 {
502 res = i + 1;
503 }
504 if (all_ligne)
505 {
506 mot = g_strdup_printf ("%s", the_word);
507 the_word = strtok_r (NULL, " ", & saved_line);
508 while (the_word)
509 {
510 mot = g_strdup_printf ("%s%s", mot, the_word);
511 the_word = strtok_r (NULL, " ", & saved_line);
512 }
513 the_word = g_strdup_printf ("%s", mot);
514 g_free (mot);
515 }
516 if (the_word && rec_val)
517 {
518 * cif_word = get_cif_word (the_word);
519 }
520 g_free (str_w);
521 g_free (str_a);
522 g_free (str_b);
523 goto endi;
524 }
525 g_free (str_a);
526 g_free (str_b);
527 }
528 g_free (str_w);
529 the_word = strtok_r (NULL, " ", & saved_line);
530 }
531 endi:;
532 g_free (the_line);
533 }
534
535 if (res < 0) res = 0;
536#else
537 file_get_to_line (lstart);
538 res = 0;
539 i = lstart;
540 while (tail)
541 {
542 the_line = g_strdup_printf ("%s", tail -> line);
543 the_word = strtok_r (the_line, " ", & saved_line);
544 while (the_word)
545 {
546 str_w = get_cif_word (the_word);
547 str_w = g_ascii_strdown (str_w, strlen(str_w));
548 if (strlen(str_w) == l)
549 {
550 str_a = g_strdup_printf ("%c", str_w[0]);
551 for (m=1; m<j; m++) str_a = g_strdup_printf ("%s%c", str_a, str_w[m]);
552 str_b = g_strdup_printf ("%c", str_w[j+1]);
553 for (m=j+2; m<l; m++) str_b = g_strdup_printf ("%s%c", str_b, str_w[m]);
554 if (g_strcmp0(str_a, kroot) == 0 && g_strcmp0(str_b,keyw) == 0)
555 {
556 the_word = strtok_r (NULL, " ", & saved_line);
557 if (! the_word)
558 {
559 if (rec_val || all_ligne)
560 {
561 str = g_strdup_printf ("Wrong file format: searching for <b>%s</b> - error at line <b>%d</b> !\n", keyw, i+1);
562 add_reader_info (str, 0);
563 g_free (str);
564 g_free (str_w);
565 g_free (str_a);
566 g_free (str_b);
567 g_free (the_line);
568 return 0;
569 }
570 }
571
572 if (all_ligne)
573 {
574 mot = g_strdup_printf ("%s", the_word);
575 the_word = strtok_r (NULL, " ", & saved_line);
576 while (the_word)
577 {
578 mot = g_strdup_printf ("%s%s", mot, the_word);
579 the_word = strtok_r (NULL, " ", & saved_line);
580 }
581 the_word = g_strdup_printf ("%s", mot);
582 g_free (mot);
583 }
584 if (the_word && rec_val)
585 {
586 * cif_word = get_cif_word (the_word);
587 }
588 if (total_num)
589 {
590 if (record_position)
591 {
592 line_position[res] = i + 1;
593 }
594 res ++;
595 if (this_reader -> steps && res == this_reader -> steps)
596 {
597 g_free (str_a);
598 g_free (str_b);
599 g_free (str_w);
600 g_free (the_line);
601 return res;
602 }
603 }
604 else
605 {
606 g_free (str_a);
607 g_free (str_b);
608 g_free (str_w);
609 g_free (the_line);
610 return i + 1;
611 }
612 }
613 g_free (str_a);
614 g_free (str_b);
615 }
616 g_free (str_w);
617 the_word = strtok_r (NULL, " ", & saved_line);
618 }
619 g_free (the_line);
620 tail = tail -> next;
621 i ++;
622 }
623#endif
624 return res;
625}
626
635int cif_file_get_data_in_loop (int linec, int lid)
636{
637 gboolean res = FALSE;
638 int i = 0;
639 gchar * the_word;
640 gchar * the_line;
641 gchar * saved_line;
642#ifdef OPENMP
643 while (! res)
644 {
645 if (lid+i < linec)
646 {
647 the_line = g_strdup_printf ("%s", coord_line[lid+i]);
648 the_word = strtok_r (the_line, " ", & saved_line);
649 if (the_word[0] == '_')
650 {
651 i ++;
652 }
653 else
654 {
655 res = TRUE;
656 }
657 g_free (the_line);
658 }
659 else
660 {
661 res = TRUE;
662 }
663 }
664#else
665 file_get_to_line (lid);
666 while (! res)
667 {
668 if (tail)
669 {
670 the_line = g_strdup_printf ("%s", tail -> line);
671 the_word = strtok_r (the_line, " ", & saved_line);
672 if (the_word[0] == '_')
673 {
674 i ++;
675 tail = tail -> next;
676 }
677 else
678 {
679 res = TRUE;
680 }
681 g_free (the_line);
682 }
683 else
684 {
685 res = TRUE;
686 }
687 }
688#endif
689 return i;
690}
691
699int get_loop_line_id (int lid)
700{
701 int i;
702 gchar * the_word;
703 gchar * the_line;
704 gchar * saved_line;
705 gchar * str_w;
706#ifdef OPENMP
707 for (i=lid-1; i>-1; i--)
708 {
709 the_line = g_strdup_printf ("%s", coord_line[i]);
710 the_word = strtok_r (the_line, " ", & saved_line);
711 if (the_word)
712 {
713 str_w = g_ascii_strdown (the_word, strlen(the_word));
714 if (g_strcmp0 ("loop_", get_cif_word(str_w)) == 0)
715 {
716 g_free (str_w);
717 return i+1;
718 }
719 g_free (str_w);
720 }
721 }
722#else
723 file_get_to_line (lid);
724 i = lid;
725 while (tail)
726 {
727 the_line = g_strdup_printf ("%s", tail -> line);
728 the_word = strtok_r (the_line, " ", & saved_line);
729 if (the_word)
730 {
731 str_w = g_ascii_strdown (the_word, strlen(the_word));
732 if (g_strcmp0 ("loop_", get_cif_word(str_w)) == 0)
733 {
734 g_free (str_w);
735 return i+1;
736 }
737 g_free (str_w);
738 }
739 i --;
740 tail = tail -> prev;
741 }
742#endif
743 return 0;
744}
745
756int get_loop_line_for_key (int linec, int conf, gchar * key_a, gchar * key_b)
757{
758 int lli = 0;
759 int * line_numbers;
760 int steps;
761 if (this_reader -> steps > 1)
762 {
763 line_numbers = allocint (this_reader -> steps);
764 steps = cif_get_value (key_a, key_b, 0, linec, NULL, FALSE, FALSE, TRUE, TRUE, line_numbers);
765 if (steps)
766 {
767 if (steps != this_reader -> steps)
768 {
769 gchar * str = g_strdup_printf ("<b>CIF get loop line</b>: something is wrong for keyword: %s_%s\n"
770 " -> keyword found= %d times\n"
771 " -> configurations in CIF file= %d !\n", key_a, key_b, steps, this_reader -> steps);
772 add_reader_info (str, 0);
773 g_free (str);
774 g_free (line_numbers);
775 return 0;
776 }
777 sort (steps, line_numbers);
778 lli = line_numbers[conf];
779 g_free (line_numbers);
780 }
781 }
782 else
783 {
784 lli = cif_get_value (key_a, key_b, 0, linec, NULL, FALSE, FALSE, FALSE, FALSE, NULL);
785 }
786 return (lli) ? get_loop_line_id (lli) : 0;
787}
788
802gchar * cif_retrieve_value (int linec, int conf, gchar * key_a, gchar * key_b, gboolean all_ligne, gboolean in_loop, gboolean warning)
803{
804 gchar * str;
805 gchar * cif_value = NULL;
806 int loop_pos[2];
807 int * line_numbers;
808 int steps;
809 if (this_reader -> steps > 1)
810 {
811 line_numbers = allocint (this_reader -> steps);
812 // g_debug ("CIF:: retrieve:: linec= %d, conf= %d, key_a= %s, key_b= %s, this_reader -> steps= %d", linec, conf, key_a, key_b, this_reader -> steps);
813 steps = cif_get_value (key_a, key_b, 0, linec, NULL, FALSE, FALSE, TRUE, TRUE, line_numbers);
814 // g_debug ("CIF:: retrieve:: steps= %d", steps);
815 if (steps)
816 {
817 if (steps != this_reader -> steps)
818 {
819 str = g_strdup_printf ("<b>CIF retrieve value</b>: keyword: %s_%s\n"
820 " -> keyword found= %d times\n"
821 " -> configurations in CIF file= %d !\n", key_a, key_b, steps, this_reader -> steps);
822 add_reader_info (str, 0);
823 g_free (str);
824 str = NULL;
825 g_free (line_numbers);
826 line_numbers = NULL;
827 return NULL;
828 }
829 sort (steps, line_numbers);
830 if (in_loop)
831 {
832 // Considering that the loop has not more than a thousand keys
833 loop_pos[0] = get_loop_line_id (line_numbers[conf]);
834 loop_pos[1] = (loop_pos[0] + 1000) > linec ? linec : (loop_pos[0] + 1000);
835 }
836 else
837 {
838 loop_pos[0] = (! line_numbers[conf]) ? line_numbers[conf] : line_numbers[conf] - 1;
839 loop_pos[1] = (loop_pos[0] + 1000) > linec ? linec : (loop_pos[0] + 1000);
840 // loop_pos[1] = (conf == this_reader -> steps - 1) ? linec : line_numbers[conf + 1];
841 }
842 g_free (line_numbers);
843 line_numbers = NULL;
844 }
845 }
846 else
847 {
848 loop_pos[0] = 0;
849 loop_pos[1] = linec;
850 }
851 if (! cif_get_value (key_a, key_b, loop_pos[0], loop_pos[1], & cif_value, TRUE, all_ligne, FALSE, FALSE, NULL) && warning)
852 {
853#ifdef DEBUG
854 g_debug ("CIF:: retrieve:: keyword: %s_%s not found for conf %d between loop_pos[0]= %d and loop_pos[1]= %d\n", key_a, key_b, conf, loop_pos[0], loop_pos[1]);
855#endif
856 str = g_strdup_printf ("<b>Key positions</b>: keyword: %s_%s\n"
857 " -> not found for conf %d between loop_pos[0]= %d and loop_pos[1]= %d\n", key_a, key_b, conf, loop_pos[0], loop_pos[1]);
858 add_reader_info (str, 0);
859 g_free (str);
860 return NULL;
861 }
862 return cif_value;
863}
864
874int cif_file_get_number_of_atoms (int linec, int lid, int nelem)
875{
876 gboolean res = FALSE;
877 int i, j;
878 char init;
879 gchar * the_word;
880 gchar * the_line;
881 gchar * saved_line;
882 i = 0;
883#ifdef OPENMP
884 while (! res && (lid+i) < linec)
885 {
886 the_line = g_strdup_printf ("%s", coord_line[lid+i]);
887 the_word = strtok_r (the_line, " ", & saved_line);
888 j = 0;
889 while (the_word)
890 {
891 if (! j) init = the_word[0];
892 j ++;
893 the_word = strtok_r (NULL, " ", & saved_line);
894 }
895 if (j == nelem && init != '_')
896 {
897 i ++;
898 }
899 else
900 {
901 res = TRUE;
902 }
903 g_free (the_line);
904 }
905#else
906 file_get_to_line (lid);
907 while (! res && tail)
908 {
909 the_line = g_strdup_printf ("%s", tail -> line);
910 the_word = strtok_r (the_line, " ", & saved_line);
911 j = 0;
912 while (the_word)
913 {
914 if (j == 0) init = the_word[0];
915 j ++;
916 the_word = strtok_r (NULL, " ", & saved_line);
917 }
918 if (j == nelem && init != '_')
919 {
920 i ++;
921 }
922 else
923 {
924 res = TRUE;
925 }
926 g_free (the_line);
927 tail = tail -> next;
928 }
929#endif
930 return i;
931}
932
941void check_for_to_lab (int ato, gchar * stlab)
942{
943 int i, j;
944 j = -1;
945 // First is the label of 'ato' already listed
946 for (i=0; i<this_reader -> object_to_insert; i++)
947 {
948 if (g_strcmp0(this_reader -> label[i], stlab) == 0)
949 {
950 j = i;
951 break;
952 }
953 }
954 if (j < 0)
955 {
956 if (this_reader -> label)
957 {
958 this_reader -> label = g_realloc (this_reader -> label, (this_reader -> object_to_insert+1)*sizeof*this_reader -> label);
959 }
960 else
961 {
962 this_reader -> label = g_malloc0 (1*sizeof*this_reader -> label);
963 }
964 this_reader -> label[this_reader -> object_to_insert] = g_strdup_printf ("%s", stlab);
965 this_reader -> object_to_insert ++;
966 j = this_reader -> object_to_insert-1;
967 }
968 if (this_reader -> object_list)
969 {
970 this_reader -> object_list = g_realloc (this_reader -> object_list, (this_reader -> atom_unlabelled+1)*sizeof*this_reader -> object_list);
971 this_reader -> u_atom_list = g_realloc (this_reader -> u_atom_list, (this_reader -> atom_unlabelled+1)*sizeof*this_reader -> u_atom_list);
972 }
973 else
974 {
975 this_reader -> object_list = g_malloc0 (1*sizeof*this_reader -> object_list);
976 this_reader -> u_atom_list = g_malloc0 (1*sizeof*this_reader -> u_atom_list);
977 }
978 this_reader -> object_list[this_reader -> atom_unlabelled] = j;
979 this_reader -> u_atom_list[this_reader -> atom_unlabelled] = ato;
980 this_reader -> atom_unlabelled ++;
981}
982
992gboolean cif_file_get_atoms_data (int conf, int lin, int cid[9])
993{
994 int i, j;
995 double v;
996 gchar * str;
997 gboolean done = TRUE;
998 gchar * cline;
999 int at_step = (active_project -> steps == 1) ? 0 : conf;
1000#ifdef OPENMP
1001 int numth = omp_get_max_threads ();
1002 #pragma omp parallel for num_threads(numth) private(i,j,v,cline,str) shared(this_reader,coord_line,at_step,done,lin,cid)
1003 for (i=0; i<this_reader -> natomes; i++)
1004 {
1005 cline = g_strdup_printf ("%s", coord_line[i+lin]);
1006 str = get_atom_label (cline, (cid[0]) ? cid[0] : cid[1]);
1007 v = get_z_from_periodic_table (str);
1008 #pragma omp critical
1009 {
1010 if (v)
1011 {
1012 check_for_species (v, i);
1013 }
1014 else
1015 {
1016 done = FALSE;
1017 check_for_to_lab (i, str);
1018 }
1019 }
1020 if (this_reader -> cartesian)
1021 {
1022 active_project -> atoms[at_step][i].x = get_atom_coord (cline, cid[2]);
1023 active_project -> atoms[at_step][i].y = get_atom_coord (cline, cid[3]);
1024 active_project -> atoms[at_step][i].z = get_atom_coord (cline, cid[4]);
1025 }
1026 else
1027 {
1028 for (j=0; j<3; j++) this_reader -> coord[i][j] = get_atom_coord (cline, cid[j+2]);
1029 }
1030 if (! this_reader -> cartesian)
1031 {
1032 this_reader -> wyckoff[i] = (cid[5]) ? get_atom_wyckoff (cline, cid[5]) : 0;
1033 this_reader -> occupancy[i] = (cid[6]) ? get_atom_coord (cline, cid[6]) : 1.0;
1034 this_reader -> multi[i] = (cid[7]) ? get_atom_coord (cline, cid[7]) : 0.0;
1035 this_reader -> disorder[i] = (cid[8]) ? (int) get_atom_coord (cline, cid[8]) : 0;
1036 }
1037 if (cline)
1038 {
1039 g_free (cline);
1040 cline = NULL;
1041 }
1042 if (str)
1043 {
1044 g_free (str);
1045 str = NULL;
1046 }
1047 }
1048#else
1049 file_get_to_line (lin);
1050 for (i=0; i<this_reader -> natomes; i++)
1051 {
1052 cline = g_strdup_printf ("%s", tail -> line);
1053 str = get_atom_label (cline, (cid[0]) ? cid[0] : cid[1]);
1054 v = get_z_from_periodic_table (str);
1055 if (v)
1056 {
1057 check_for_species (v, i);
1058 }
1059 else
1060 {
1061 done = FALSE;
1062 check_for_to_lab (i, str);
1063 }
1064 if (this_reader -> cartesian)
1065 {
1066 active_project -> atoms[at_step][i].x = get_atom_coord (cline, cid[2]);
1067 active_project -> atoms[at_step][i].y = get_atom_coord (cline, cid[3]);
1068 active_project -> atoms[at_step][i].z = get_atom_coord (cline, cid[4]);
1069 }
1070 else
1071 {
1072 for (j=0; j<3; j++) this_reader -> coord[i][j] = get_atom_coord (cline, cid[j+2]);
1073 }
1074 if (! this_reader -> cartesian)
1075 {
1076 this_reader -> wyckoff[i] = (cid[5]) ? get_atom_wyckoff (cline, cid[5]) : 0;
1077 this_reader -> occupancy[i] = (cid[6]) ? get_atom_coord (cline, cid[6]) : 1.0;
1078 this_reader -> multi[i] = (cid[7]) ? get_atom_coord (cline, cid[7]) : 0.0;
1079 this_reader -> disorder[i] = (cid[8]) ? get_atom_coord (cline, cid[8]) : 0;
1080 }
1081/* #ifdef DEBUG
1082 j = this_reader -> wyckoff[i];
1083 g_debug ("CIF:: At= %s, w_letter[%d]= %s, occ= %f, x= %f, y= %f, z= %f", this_reader -> label[i],
1084 j, this_reader -> lattice.sp_group -> wyckoff[j].let, this_reader -> occupancy[i],
1085 this_reader -> coord[i][0], this_reader -> coord[i][1], this_reader -> coord[i][2]);
1086#endif */
1087 tail = tail -> next;
1088 }
1089#endif
1090 if (! done)
1091 {
1092 done = (cif_search) ? TRUE : get_missing_object_from_user ();
1093 }
1094 return done;
1095}
1096
1105gboolean cif_get_atomic_coordinates (int linec, int conf)
1106{
1107 gchar * labkeys[2] = {"type_symbol", "label"};
1108 gchar * frackeys[3] = {"fract_x", "fract_y", "fract_z"};
1109 gchar * cartkeys[3] = {"cartn_x", "cartn_y", "cartn_z"};
1110 gchar * symkeys[4] = {"wyckoff_symbol", "occupancy", "symmetry_multiplicity", "disorder_group"};
1111 gchar * str = NULL;
1112 int cid[9];
1113 int loop_line;
1114 int loop_max;
1115 int i, j, k;
1116 double u, v;
1117 int * tmp_nsps;
1118 double * tmp_z;
1119 if (cif_multiple)
1120 {
1121 loop_line = get_loop_line_for_key (linec, conf, "_atom_site", (this_reader -> cartesian) ? cartkeys[0] : frackeys[0]);
1122 if (! loop_line)
1123 {
1124 return FALSE;
1125 }
1126 }
1127 else
1128 {
1129 loop_line = get_loop_line_for_key (linec, 0, "_atom_site", cartkeys[0]);
1130 if (! loop_line)
1131 {
1132 loop_line = get_loop_line_for_key (linec, 0, "_atom_site", frackeys[0]);
1133 if (! loop_line)
1134 {
1135 return FALSE;
1136 }
1137 }
1138 else
1139 {
1140 this_reader -> cartesian = TRUE;
1141 }
1142 }
1143 loop_max = (loop_line + 1000 > linec) ? linec : loop_line + 1000;
1144 i = 0;
1145 for (j=0; j<2; j++)
1146 {
1147 cid[j] = cif_get_value ("_atom_site", labkeys[j], loop_line, loop_max, NULL, FALSE, FALSE, FALSE, FALSE, NULL);
1148 if (cid[j])
1149 {
1150 i ++;
1151 cid[j] -= loop_line;
1152 }
1153 }
1154 if (! i)
1155 {
1156 add_reader_info ("<b>Atomic coordinates</b>: impossible to find atomic label(s) ...", 0);
1157 return FALSE;
1158 }
1159 for (i=0; i<3; i++)
1160 {
1161 cid[i+2] = cif_get_value ("_atom_site", (this_reader -> cartesian) ? cartkeys[i] : frackeys[i], loop_line, loop_max, NULL, FALSE, FALSE, FALSE, FALSE, NULL);
1162 if (cid[i+2])
1163 {
1164 cid[i+2] -= loop_line;
1165 }
1166 else
1167 {
1168 str = g_strdup_printf ("<b>Atomic coordinates</b>: impossible to find '%s' ...", (this_reader -> cartesian) ? cartkeys[i] : frackeys[i]);
1169 add_reader_info (str, 1);
1170 g_free (str);
1171 this_reader -> cartesian = FALSE;
1172 }
1173 }
1174 if (! this_reader -> cartesian)
1175 {
1176 for (i=0; i<4; i++)
1177 {
1178 cid[i+5] = cif_get_value ("_atom_site", symkeys[i], loop_line, loop_max, NULL, FALSE, FALSE, FALSE, FALSE, NULL);
1179 if (cid[i+5])
1180 {
1181 cid[i+5] -= loop_line;
1182 if (i == 1 && this_reader -> rounding < 0)
1183 {
1184 this_reader -> rounding = iask ("Please select how to handle occupancy", "Select how to handle occupancy", 5, MainWindow);
1185 if (this_reader -> rounding < 0 || this_reader -> rounding > 2) this_reader -> rounding = 2;
1187 {
1188 str = g_strdup_printf ("Occupancy %s\n\t%s\n", cif_occ[this_reader -> rounding], cif_sites[cif_use_symmetry_positions]);
1189 add_reader_info (str, 1);
1190 g_free (str);
1191 }
1192 }
1193 }
1194 }
1195 }
1196 i = cif_file_get_data_in_loop (linec, loop_line);
1197 this_reader -> natomes = cif_file_get_number_of_atoms (linec, loop_line+i, i);
1198 if (! this_reader -> natomes) return FALSE;
1199
1200 if (conf && active_project -> steps > 1 && this_reader -> natomes != cif_atoms)
1201 {
1202 // Not the same number of atoms between each configuration
1203 str = g_strdup_printf ("<b>Atomic coordinates</b>: the number of atom(s) changes !\n"
1204 " - configuration N°%d\t :: atoms= %d\n"
1205 " - initialization \t\t :: atoms= %d\n", conf, this_reader -> natomes, cif_atoms);
1206 add_reader_info (str, 0);
1207 g_free (str);
1208 return FALSE;
1209 }
1210 if (this_reader -> cartesian)
1211 {
1212 if (! conf)
1213 {
1214 active_project -> natomes = this_reader -> natomes;
1216 }
1217 }
1218 else
1219 {
1220 this_reader -> coord = allocddouble (this_reader -> natomes*this_reader -> steps, 3);
1221 }
1222
1223 if (! this_reader -> cartesian)
1224 {
1225 this_reader -> lot = allocint (this_reader -> natomes);
1226 this_reader -> wyckoff = allocint (this_reader -> natomes);
1227 this_reader -> occupancy = allocdouble (this_reader -> natomes);
1228 this_reader -> multi = allocint (this_reader -> natomes);
1229 this_reader -> disorder = allocint (this_reader -> natomes);
1230 }
1231 this_reader -> z = allocdouble (1);
1232 this_reader -> nsps = allocint (1);
1233
1234 if (! cif_file_get_atoms_data (conf, loop_line+i, cid)) return FALSE;
1235 if (active_project -> steps > 1)
1236 {
1237 tmp_nsps = duplicate_int (this_reader -> nspec, this_reader -> nsps);
1238 tmp_z = duplicate_double (this_reader -> nspec, this_reader -> z);
1239 for (i=1; i<this_reader -> nspec; i++)
1240 {
1241 v = tmp_z[i];
1242 j = tmp_nsps[i];
1243 for (k=i-1; k>-1; k--)
1244 {
1245 if (tmp_z[k] <= v) break;
1246 tmp_z[k+1] = tmp_z[k];
1247 tmp_nsps[k+1] = tmp_nsps[k];
1248 }
1249 tmp_z[k+1] = v;
1250 tmp_nsps[k+1] = j;
1251 }
1252 g_free (tmp_z);
1253 if (! conf)
1254 {
1255 cif_atoms = this_reader -> natomes;
1256 cif_nspec = this_reader -> nspec;
1257 cif_nsps = duplicate_int (this_reader -> nspec, tmp_nsps);
1258 }
1259 }
1260 if (conf && active_project -> steps > 1)
1261 {
1262 if (this_reader -> nspec != cif_nspec)
1263 {
1264 // Not the same number of chemical species between each configuration
1265 str = g_strdup_printf ("<b>Atomic coordinates</b>: the number of chemical species changes !\n"
1266 " - configuration N°%d\t :: species= %d\n"
1267 " - initialization \t\t :: species= %d\n", conf, this_reader -> nspec, cif_nspec);
1268 add_reader_info (str, 0);
1269 g_free (str);
1270 return FALSE;
1271 }
1272 for (i=0; i<this_reader -> nspec; i++)
1273 {
1274 if (tmp_nsps[i] != cif_nsps[i])
1275 {
1276 // Not the same number of atom(s) by chemical species between each configuration
1277 str = g_strdup_printf ("<b>Atomic coordinates</b>: the number of atom(s) for species %d changes !\n"
1278 " - configuration N°%d\t :: atom(s)= %d\n"
1279 " - initialization \t\t :: atom(s)= %d\n", conf, i+1, this_reader -> nsps[i], cif_nsps[i]);
1280 add_reader_info (str, 0);
1281 g_free (str);
1282 return FALSE;
1283 }
1284 }
1285 g_free (tmp_nsps);
1286 }
1287 if (! this_reader -> cartesian && cif_use_symmetry_positions)
1288 {
1289 // Testing site multiplicity, to ensure that occupancy is not > 1.0
1290 for (i=0; i<this_reader -> natomes; i++)
1291 {
1292 v = this_reader -> occupancy[i];
1293 for (j=0; j<this_reader -> natomes; j++)
1294 {
1295 if (j != i)
1296 {
1297 if (this_reader -> coord[i][0] == this_reader -> coord[j][0]
1298 && this_reader -> coord[i][1] == this_reader -> coord[j][1]
1299 && this_reader -> coord[i][2] == this_reader -> coord[j][2])
1300 {
1301 v += this_reader -> occupancy[j];
1302 if (v > 1.00001)
1303 {
1304 add_reader_info ("<b>Atomic coordinates</b>: a site was found to have an occupancy > 1.0 !\n", 0);
1305 return FALSE;
1306 }
1307 }
1308 }
1309 }
1310 }
1311 }
1312 if (! this_reader -> cartesian && this_reader -> chemical)
1313 {
1314 // Testing the different number of occupancies
1315 double * test_occ = allocdouble (1);
1316 int * num_occ = allocint (1);
1317 int * test_order = allocint (1);
1318 int * num_order = allocint (1);
1319 gboolean new_occ, new_order;
1320 int occupancies = 1;
1321 int disorders = 1;
1322 u = v = test_occ[0] = this_reader -> occupancy[0];
1323 test_order[0] = this_reader -> disorder[0];
1324 num_occ[0] = num_order[0] = 1;
1325 for (i=1; i<this_reader -> natomes; i++)
1326 {
1327 new_occ = new_order = TRUE;
1328 for (j=0; j<occupancies; j++)
1329 {
1330 if (test_occ[j] == this_reader -> occupancy[i])
1331 {
1332 num_occ[j] ++;
1333 new_occ = FALSE;
1334 break;
1335 }
1336 }
1337 if (new_occ)
1338 {
1339 test_occ = g_realloc (test_occ, (occupancies+1)*sizeof*test_occ);
1340 test_occ[occupancies] = this_reader -> occupancy[i];
1341 u = min (u, test_occ[occupancies]);
1342 v = max (v, test_occ[occupancies]);
1343 num_occ = g_realloc (num_occ, (occupancies+1)*sizeof*num_occ);
1344 num_occ[occupancies] = 1;
1345 occupancies ++;
1346 }
1347 for (j=0; j<disorders; j++)
1348 {
1349 if (test_order[j] == this_reader -> disorder[i])
1350 {
1351 num_order[j] ++;
1352 new_order = FALSE;
1353 break;
1354 }
1355 }
1356 if (new_order)
1357 {
1358 test_order = g_realloc (test_order, (disorders+1)*sizeof*test_order);
1359 test_order[disorders] = this_reader -> disorder[i];
1360 num_order = g_realloc (num_order, (disorders+1)*sizeof*num_order);
1361 num_order[disorders] = 1;
1362 disorders ++;
1363 }
1364 }
1365 if (this_reader -> natomes%occupancies == 0 || this_reader -> natomes%disorders == 0)
1366 {
1367 // Atoms can be separated based on site occupancy or site disorder
1368 // We can consider this as a chemical "reaction or trajectory"
1369 // As many lattices near by as occupancies or disorders
1370 new_occ = TRUE;
1371 for (i=0; i<occupancies; i++)
1372 {
1373 if (num_occ[i] != this_reader -> natomes/occupancies)
1374 {
1375 new_occ = FALSE;
1376 break;
1377 }
1378 }
1379 // if (new_occ) add_reader_info ("CIF file is compatible with a chemical reaction: \n\t Reactants can be separated using occupancy\n", 1);
1380 // g_debug ("min= %f, max= %f, max/min= %f", u, v, v/u);
1381 new_order = TRUE;
1382 for (i=0; i<disorders; i++)
1383 {
1384 if (num_order[i] != this_reader -> natomes/disorders)
1385 {
1386 new_order = FALSE;
1387 break;
1388 }
1389 }
1390 // if (new_order) add_reader_info ("CIF file is compatible with a chemical reaction: \n\t Reactants can be separated using disorder site\n", 1);
1391 }
1392 }
1393 return TRUE;
1394}
1395
1404{
1405 gboolean res = FALSE;
1406 gchar * saved_line;
1407 gchar * the_line;
1408 gchar * the_word;
1409 int i = 0;
1410 while (! res)
1411 {
1412#ifdef OPENMP
1413 the_line = g_strdup_printf ("%s", coord_line[lid+i]);
1414#else
1415 file_get_to_line (lid+i);
1416 the_line = g_strdup_printf ("%s", tail -> line);
1417#endif
1418 the_word = strtok_r (the_line, " ", & saved_line);
1419 if (the_word[0] == '_' || g_strcmp0(the_word, "loop_") == 0)
1420 {
1421 res = TRUE;
1422 break;
1423 }
1424 else
1425 {
1426 i ++;
1427 }
1428 }
1429 if (i)
1430 {
1431 this_reader -> sym_pos = g_malloc0(i*sizeof*this_reader -> sym_pos);
1432 int j, k;
1433 gchar * str;
1434 gchar * k_word;
1435 gchar * sym_pos_line;
1436 for (j=0; j<i; j++)
1437 {
1438 this_reader -> sym_pos[j] = g_malloc0(3*sizeof*this_reader -> sym_pos[j]);
1439#ifdef OPENMP
1440 sym_pos_line = g_strdup_printf ("%s", coord_line[lid+j]);
1441#else
1442 file_get_to_line (lid+j);
1443 sym_pos_line = g_strdup_printf ("%s", tail -> line);
1444#endif
1445 the_line = g_strdup_printf ("%s", sym_pos_line);
1446 the_word = strtok_r (the_line, " ", & saved_line);
1447 k_word = g_strdup_printf ("%s", the_word);
1448 str = g_strdup_printf ("%d", j+1);
1449 if (g_strcmp0(k_word, str) == 0)
1450 {
1451 g_free (the_line);
1452 the_line = NULL;
1453 for (k=strlen(k_word); k<strlen(sym_pos_line); k++)
1454 {
1455 if (! this_line)
1456 {
1457 the_line = g_strdup_printf ("%c", sym_pos_line[k]);
1458 }
1459 else
1460 {
1461 the_line = g_strdup_printf ("%s%c", the_line, sym_pos_line[k]);
1462 }
1463 }
1464 }
1465 else
1466 {
1467 the_line = g_strdup_printf ("%s", sym_pos_line);
1468 }
1469 g_free (k_word);
1470 g_free (str);
1471 g_free (sym_pos_line);
1472 the_line = substitute_string (the_line, " ", NULL);
1473 the_line = substitute_string (the_line, "'", NULL);
1474 the_line = substitute_string (the_line, ",", " ");
1475 the_word = strtok_r (the_line, " ", & saved_line);
1476 for (k=0; k<3; k++)
1477 {
1478 this_reader -> sym_pos[j][k] = g_strdup_printf ("%s", the_word);
1479 the_word = strtok_r (NULL, " ", & saved_line);
1480 }
1481#ifdef DEBUG
1482 g_debug ("SYM_POS:: pos= %d, x= %s, y= %s, z= %s", j+1, this_reader -> sym_pos[j][0], this_reader -> sym_pos[j][1], this_reader -> sym_pos[j][2]);
1483#endif // DEBUG
1484 }
1485 }
1486 return i;
1487}
1488
1497gboolean cif_get_symmetry_positions (int linec, int conf)
1498{
1499 gchar * pos_key[2]={"_symmetry_equiv_pos_as", "_space_group_symop_operation"};
1500 int loop_line;
1501 int line_id;
1502 int i;
1503 for (i=0; i<2; i++)
1504 {
1505 loop_line = get_loop_line_for_key (linec, conf, pos_key[i], "xyz");
1506 if (loop_line)
1507 {
1508 line_id = cif_get_value (pos_key[i], "xyz", loop_line, linec, NULL, FALSE, FALSE, FALSE, FALSE, NULL);
1509 break;
1510 }
1511 }
1512 if (! loop_line) return FALSE;
1513 // Read lines after the instruction, as many positions as line until _ or loop
1514 this_reader -> num_sym_pos = cif_file_get_number_of_positions (line_id);
1515 return TRUE;
1516}
1517
1526{
1527 int i;
1528 gchar * str;
1529 gchar * hm = g_strdup_printf ("%s", replace_markup (hmk, "S", NULL));
1530 for (i=0; i<230; i++)
1531 {
1532 str = substitute_string (hmsymbols[i], " ", NULL);
1533 if (g_strcmp0(str, hm) == 0)
1534 {
1535 g_free (str);
1536 g_free (hm);
1537 return i+1;
1538 }
1539 g_free (str);
1540 str = substitute_string (groups[i], "<sub>", NULL);
1541 str = substitute_string (str, "</sub>", NULL);
1542 if (g_strcmp0(str, hm) == 0)
1543 {
1544 g_free (str);
1545 g_free (hm);
1546 return i+1;
1547 }
1548 g_free (str);
1549 }
1550 // Cross checking for erroneus writting in the CIF file
1551 // ie. Fm3m in place of Fm-3m
1552 for (i=0; i<230; i++)
1553 {
1554 str = substitute_string (groups[i], "<sub>", NULL);
1555 str = substitute_string (str, "</sub>", NULL);
1556 if (g_strrstr(str, "-"))
1557 {
1558 str = substitute_string (str, "-", NULL);
1559 if (g_strcmp0(str, hm) == 0)
1560 {
1561 g_free (str);
1562 g_free (hm);
1563 return i+1;
1564 }
1565 }
1566 g_free (str);
1567 }
1568 g_free (hm);
1569 return 0;
1570}
1571
1580{
1581 gchar * str = NULL;
1582 if (wnpos[1])
1583 {
1584 g_free (wnpos[1]);
1585 wnpos[1] = NULL;
1586 }
1587
1588 get_wyck_char (spg -> coord_origin.m01, 1, 0);
1589 get_wyck_char (spg -> coord_origin.m11, 1, 1);
1590 get_wyck_char (spg -> coord_origin.m21, 1, 2);
1591
1592 if (wnpos[1])
1593 {
1594 str = g_strdup_printf ("%s", wnpos[1]);
1595 g_free (wnpos[1]);
1596 wnpos[1] = NULL;
1597 }
1598 return str;
1599}
1600
1609int get_setting_from_hm (gchar * hmk, int end)
1610{
1611 int i, j;
1612 gchar * str;
1613 if (this_reader -> lattice.sp_group)
1614 {
1615 i = this_reader -> lattice.sp_group -> nums;
1616 for (j=0; j<i; j++)
1617 {
1618 str = replace_markup (this_reader -> lattice.sp_group -> settings[j].name, "s", "/");
1619 str = substitute_string (str, "_", NULL);
1620 if (end < 0)
1621 {
1622 if (g_strcmp0(str, hmk) == 0)
1623 {
1624 g_free (str);
1625 return j;
1626 }
1627 }
1628 else
1629 {
1630 if (g_strcmp0(str, hmk) == 0 && this_reader -> lattice.sp_group -> settings[j].origin == end+1)
1631 {
1632 g_free (str);
1633 return j;
1634 }
1635 }
1636 g_free (str);
1637 }
1638 if (this_reader -> lattice.sp_group -> id > 2 && this_reader -> lattice.sp_group -> id < 16)
1639 {
1640 // This is a way around the way this familly of SG is often written,
1641 // using incomplete or inexact hmk keyword, ex: P21/a instead of P121/a1
1642 for (j=0; j<i; j++)
1643 {
1644 str = replace_markup (this_reader -> lattice.sp_group -> settings[j].name, "s", "/");
1645 str = substitute_string (str, "_", NULL);
1646 str = substitute_string (str, "12", "2");
1647 str = substitute_string (str, "/a1", "/a");
1648 str = substitute_string (str, "/b1", "/b");
1649 str = substitute_string (str, "/c1", "/c");
1650 str = substitute_string (str, "/m1", "/m");
1651 str = substitute_string (str, "/n1", "/n");
1652 if (end < 0)
1653 {
1654 if (g_strcmp0(str, hmk) == 0)
1655 {
1656 g_free (str);
1657 str = g_strdup_printf ("<b>Space group</b>: CIF file information could be inaccurate !\n"
1658 " CIF file space group: <b>%s</b>, CIF file H-M symbol: <b>%s</b>\n",
1659 groups[this_reader -> lattice.sp_group -> id-1], hmk);
1660 add_reader_info (str, 1);
1661 g_free (str);
1662 return j;
1663 }
1664 }
1665 else
1666 {
1667 if (g_strcmp0(str, hmk) == 0 && this_reader -> lattice.sp_group -> settings[j].origin == end+1)
1668 {
1669 g_free (str);
1670 str = g_strdup_printf ("<b>Space group</b>: CIF file information could be inaccurate !\n"
1671 " CIF file space group: <b>%s</b>, CIF file H-M symbol: <b>%s</b>\n",
1672 groups[this_reader -> lattice.sp_group -> id-1], hmk);
1673 add_reader_info (str, 1);
1674 g_free (str);
1675 return j;
1676 }
1677 }
1678 g_free (str);
1679 }
1680 }
1681 return -1;
1682 }
1683 else
1684 {
1685 return -1;
1686 }
1687}
1688
1697int group_info_from_hm_key (int spg, gchar * key_hm)
1698{
1699 int i, j;
1700 gchar * str;
1701 gchar * exts[2] = {"h", "r"};
1702 gchar * orig[2] = {"1", "2"};
1703 gchar * key = NULL;
1704 gchar * hmk = NULL;
1705 gchar * hma, * hmb;
1706 gchar * hmkey = substitute_string (key_hm, "'", NULL);
1707 //hmkey = substitute_string (hmkey, "/", "s");
1708 this_reader -> setting = -1;
1709 if (strstr(hmkey,":"))
1710 {
1711 key = g_strdup_printf ("%s", hmkey);
1712 hmk = g_strdup_printf ("%s", strtok (key, ":"));
1713 hma = g_strdup_printf ("%s:", hmk);
1714 hmb = replace_markup (hmkey, hma, NULL);
1715 i = strlen(hmb);
1716 hmb = g_ascii_strdown (hmb, i);
1717 for (i=0; i<2; i++)
1718 {
1719 if (g_strcmp0(hmb, exts[i]) == 0)
1720 {
1721 this_reader -> setting = i;
1722 break;
1723 }
1724 }
1725 g_free (hma);
1726 g_free (key);
1727 if (this_reader -> setting < 0)
1728 {
1729 for (i=0; i<2; i++)
1730 {
1731 if (g_strcmp0(hmb, orig[i]) == 0)
1732 {
1733 j = get_space_group_from_hm (hmk);
1734 this_reader -> setting = (spg) ? get_setting_from_hm (hmk, i) : 0;
1735 if (! j && this_reader -> setting < 0)
1736 {
1737 this_reader -> setting = 0;
1738 str = g_strdup_printf ("<b>Space group</b>: CIF file information could be inaccurate !\n"
1739 " CIF file space group: <b>%s</b>, CIF file H-M symbol: <b>%s</b>\n",
1740 groups[this_reader -> lattice.sp_group -> id-1], key_hm);
1741 add_reader_info (str, 1);
1742 g_free (str);
1743 }
1744 if (this_reader -> setting < 0) this_reader -> setting = 0;
1745 g_free (hmk);
1746 g_free (hmb);
1747 return j;
1748 }
1749 }
1750 }
1751 g_free (hmb);
1752 }
1753 else
1754 {
1755 hmk = g_strdup_printf ("%s", hmkey);
1756 }
1757 j = get_space_group_from_hm (hmk);
1758 this_reader -> setting = (spg || j) ? get_setting_from_hm (hmk, -1) : 0;
1759 g_free (hmk);
1760 if (! j && this_reader -> setting < 0)
1761 {
1762 str = g_strdup_printf ("<b>Space group</b>: CIF file information could be inaccurate !\n"
1763 " CIF file space group: <b>%s</b>, CIF file H-M symbol: <b>%s</b>\n",
1764 groups[this_reader -> lattice.sp_group -> id-1], key_hm);
1765 add_reader_info (str, 1);
1766 g_free (str);
1767 }
1768 if (this_reader -> setting < 0) this_reader -> setting = 0;
1769 return (spg) ? (j) ? j : spg : j;
1770}
1771
1780gboolean cif_get_cell_data (int linec, int conf)
1781{
1782 gchar * cellkeys[3] = {"length_a", "length_b", "length_c"};
1783 gchar * cellangs[3] = {"angle_alpha", "angle_beta", "angle_gamma",};
1784 int i, j;
1785 gchar * str = NULL;
1786 if (! conf || (conf && active_project -> steps == 1))
1787 {
1788 this_reader -> lattice.box = g_malloc0(active_project -> steps*sizeof*this_reader -> lattice.box);
1789 }
1790 i = (conf && active_project -> steps == 1) ? 0 : conf;
1791 for (j=0; j<3; j++)
1792 {
1793 str = cif_retrieve_value (linec, conf, "_cell", cellkeys[j], TRUE, TRUE, TRUE);
1794 if (! str)
1795 {
1796 str = g_strdup_printf ("<b>Lattice parameters</b>: impossible to retrieve the '%s' parameter !\n", box_prop[0][j]);
1797 add_reader_info (str, 0);
1798 g_free (str);
1799 return FALSE;
1800 }
1801 this_reader -> lattice.box[i].param[0][j] = string_to_double ((gpointer)str);
1802 if (i)
1803 {
1804 if (this_reader -> lattice.box[i].param[0][j] != this_reader -> lattice.box[i-1].param[0][j]) active_cell -> npt = TRUE;
1805 }
1806#ifdef DEBUG
1807 g_debug ("CIF:: box[%d][%d]= %f", i, j, this_reader -> lattice.box[i].param[0][j]);
1808#endif
1809 g_free (str);
1810 str = cif_retrieve_value (linec, conf, "_cell", cellangs[j], TRUE, TRUE, TRUE);
1811 if (! str)
1812 {
1813 str = g_strdup_printf ("<b>Lattice parameters</b>: impossible to retrieve the '%s' parameter !\n", box_prop[1][j]);
1814 add_reader_info (str, 0);
1815 g_free (str);
1816 return FALSE;
1817 }
1818 this_reader -> lattice.box[i].param[1][j] = string_to_double ((gpointer)str);
1819 g_free (str);
1820 if (i)
1821 {
1822 if (this_reader -> lattice.box[i].param[1][j] != this_reader -> lattice.box[i-1].param[1][j]) active_cell -> npt = TRUE;
1823 }
1824#ifdef DEBUG
1825 g_debug ("CIF:: angle[%d][%d]= %f", i, j, this_reader -> lattice.box[i].param[1][j]);
1826#endif
1827 }
1828 this_reader -> lattice.ltype = 0;
1830 for (i=0; i<3; i++) this_reader -> lattice.cextra[i] = 1;
1831 return TRUE;
1832}
1833
1842int cif_get_space_group (int linec, int conf)
1843{
1844 gchar * symkey[2] = {"int_tables_number", "group_it_number"};
1845 gchar * str = NULL;
1846 int spg = 0;
1847 int i, j, k, l;
1848
1849 for (i=0; i<2; i++)
1850 {
1851 str = cif_retrieve_value (linec, conf, "_symmetry", symkey[i], TRUE, FALSE, FALSE);
1852 if (str)
1853 {
1854 spg = (int)string_to_double ((gpointer)str);
1855 break;
1856 }
1857 }
1858 if (! spg)
1859 {
1860 str = cif_retrieve_value (linec, conf, "_space_group", "it_number", TRUE, FALSE, FALSE);
1861 if (str)
1862 {
1863 spg = (int)string_to_double ((gpointer)str);
1864 }
1865 }
1866 gchar * hmkey = NULL;
1867
1868 hmkey = cif_retrieve_value (linec, conf, "_symmetry", "space_group_name_h-m", TRUE, FALSE, FALSE);
1869 if (! hmkey)
1870 {
1871 hmkey = cif_retrieve_value (linec, conf, "_symmetry", "name_h-m_alt", TRUE, FALSE, FALSE);
1872 }
1873 if (! hmkey && ! spg)
1874 {
1875 add_reader_info ("<b>Space group</b>: no space group and no H-M symbol found !\n", 1);
1876 return FALSE;
1877 }
1878#ifdef DEBUG
1879 if (spg) g_debug ("CIF:: Space group:: N°= %d, name= %s", spg, groups[spg-1]);
1880 if (hmkey) g_debug ("CIF:: H-M symbol:: %s", hmkey);
1881#endif
1882 if (spg)
1883 {
1884 if (! read_space_group (NULL, spg-1)) return FALSE;
1885 }
1886 if (hmkey)
1887 {
1888 i = group_info_from_hm_key (spg, hmkey);
1889 if (! spg && ! i)
1890 {
1891 add_reader_info ("<b>Space group</b>: no space group found, unknown H-M symbol !\n", 1);
1892#ifdef DEBUG
1893 g_debug ("CIF:: No space group found, unknown H-M symbol !");
1894#endif
1895 }
1896 else if (spg && ! i)
1897 {
1898 str = g_strdup_printf ("<b>Space group</b>: space group and H-M symbol do not match !\n"
1899 " CIF file space group: <b>%s</b>, CIF file H-M symbol: <b>%s</b>\n", groups[spg-1], hmkey);
1900 add_reader_info (str, 1);
1901 g_free (str);
1902#ifdef DEBUG
1903 g_debug ("CIF:: Space group and H-M symbol do not match:: spg= %d, hm= %d", spg, i);
1904#endif
1905 }
1906 else if (i && ! spg)
1907 {
1908 spg = i;
1909 }
1910 if (! this_reader -> lattice.sp_group)
1911 {
1912 if (! read_space_group (NULL, spg-1)) return FALSE;
1913 }
1914 }
1915 gchar * lat;
1916 int res = spg;
1917 if (spg > 1)
1918 {
1919 str = cif_retrieve_value (linec, conf, "_space_group", "it_coordinate_system_code", TRUE, FALSE, FALSE);
1920 if (str)
1921 {
1922 str = substitute_string (str, "'", NULL);
1923 for (i=0; i<40; i++)
1924 {
1925 if (g_strcmp0(str, cif_coord_opts[i][0]) == 0)
1926 {
1927 if (i < 18)
1928 {
1929 if (spg < 3 || spg > 15)
1930 {
1931 res = 0;
1932 break;
1933 }
1934 if (str[0] == '-')
1935 {
1936 k = (int) string_to_double ((gpointer)g_strdup_printf ("%c", str[2]));
1937 str = g_strdup_printf ("%c%c", str[0], str[1]);
1938 }
1939 else
1940 {
1941 k = (int) string_to_double ((gpointer)g_strdup_printf ("%c", str[1]));
1942 str = g_strdup_printf ("%c", str[0]);
1943 }
1944 l = 0;
1945 for (j=0; j< this_reader -> lattice.sp_group -> nums; j++)
1946 {
1947 this_reader -> lattice.sp_group -> sid = j;
1948 get_origin (this_reader -> lattice.sp_group);
1949 lat = get_string_from_origin (this_reader -> lattice.sp_group);
1950 if (g_strcmp0(lat, str) == 0) l ++;
1951 if (l == k)
1952 {
1953 if (j < this_reader -> setting) add_reader_info ("<b>Space group</b>: ambiguous space group setting !\n", 1);
1954 this_reader -> setting = j;
1955 break;
1956 }
1957 }
1958 }
1959 else if (i < 36)
1960 {
1961 if (spg < 16 || spg > 74)
1962 {
1963 res = 0;
1964 break;
1965 }
1966 k = 0;
1967 if (str[0] == '1' || str[0]=='2')
1968 {
1969 k = (int) string_to_double ((gpointer)g_strdup_printf ("%c", str[0]));
1970 str = replace_markup (str, g_strdup_printf("%d", k), NULL);
1971 }
1972 l = 0;
1973 for (j=0; j< this_reader -> lattice.sp_group -> nums; j++)
1974 {
1975 lat = g_strdup_printf ("%s%s%s",
1976 this_reader -> lattice.sp_group -> settings[j].pos[0],
1977 this_reader -> lattice.sp_group -> settings[j].pos[1],
1978 this_reader -> lattice.sp_group -> settings[j].pos[2]);
1979 if (g_strcmp0(lat, str) == 0)
1980 {
1981 if (j < this_reader -> setting || this_reader -> lattice.sp_group -> settings[j].origin != k)
1982 {
1983 add_reader_info ("<b>Space group</b>: ambiguous space group setting !\n", 1);
1984 }
1985 this_reader -> setting = j;
1986 l = 1;
1987 break;
1988 }
1989 }
1990 if (! l) add_reader_info ("<b>Space group</b>: ambiguous space group setting !\n", 1);
1991 }
1992 else if (i < 38)
1993 {
1994 if (spg < 75 || (spg > 142 && spg < 195))
1995 {
1996 res = 0;
1997 break;
1998 }
1999 j = i - 36;
2000 if (j < this_reader -> setting) add_reader_info ("<b>Space group</b>: ambiguous space group setting !\n", 1);
2001 this_reader -> setting = j;
2002 }
2003 else
2004 {
2005 if (spg < 143 || spg > 165)
2006 {
2007 res = 0;
2008 break;
2009 }
2010 j = i - 38;
2011 if (j < this_reader -> setting) add_reader_info ("<b>Space group</b>: ambiguous space group setting !\n", 1);
2012 this_reader -> setting = j;
2013 }
2014 }
2015 }
2016 g_free (str);
2017 }
2018
2019 if (spg > 142 && spg < 168)
2020 {
2021 // Trigonal space group
2022 gboolean correct_this = FALSE;
2023 box_info * box = (conf && active_project -> steps == 1) ? & this_reader -> lattice.box[0] : & this_reader -> lattice.box[conf];
2024 switch (this_reader -> setting)
2025 {
2026 case 0:
2027 if (box -> param[0][0] == box -> param[0][1] && box -> param[0][0] == box -> param[0][2])
2028 {
2029 if (box -> param[1][0] == box -> param[1][1] && box -> param[1][0] == box -> param[1][2])
2030 {
2031 correct_this = TRUE;
2032 }
2033 }
2034 break;
2035 case 1:
2036 if (box -> param[0][0] == box -> param[0][1] && box -> param[0][0] != box -> param[0][2])
2037 {
2038 if (box -> param[1][0] == box -> param[1][1] && box -> param[1][0] == 90.0 && box -> param[1][2] == 120.0)
2039 {
2040 correct_this = TRUE;
2041 }
2042 }
2043 break;
2044 }
2045 if (correct_this)
2046 {
2047 gchar * setc[2] = {"<b>hexagonal</b>", "<b>rhombohedral</b>"};
2048 str = g_strdup_printf ("<b>Space group</b>: found trigonal space group N°%d-%s, %s setting\n"
2049 "but the lattice parameters were found in %s format ...\n"
2050 "\t ... the space group setting was modified accordingly !\n",
2051 spg, groups[spg-1], setc[this_reader -> setting], setc[! this_reader -> setting]);
2052 add_reader_info (str, 1);
2053 g_free (str);
2054 this_reader -> setting = ! this_reader -> setting;
2055 }
2056 }
2057
2058 // Test space group vs. box parameters:
2059 this_reader -> lattice.sp_group -> sid = this_reader -> setting;
2060 if (! test_lattice (NULL, & this_reader -> lattice))
2061 {
2062 str = g_strdup_printf ("<b>Space group</b> and <b>lattice parameters</b> are not compatible !\n"
2063 "\nCheck a, b, c, and &#x3B1;, &#x3B2;, &#x263;, with the type of crystal system.\n");
2064 add_reader_info (str, 0);
2065 g_free (str);
2066 res = -1;
2067 }
2068 }
2069 this_reader -> lattice.sp_group -> sid = this_reader -> setting;
2070 get_origin (this_reader -> lattice.sp_group);
2071 return res;
2072}
2073
2082int open_cif_configuration (int linec, int conf)
2083{
2084 int res;
2085 int i, j, k, l, m, n;
2086 int cid;
2087 if (cif_get_cell_data (linec, conf))
2088 {
2089 i = cif_get_space_group (linec, conf);
2090 if (conf && active_project -> steps > 1 && i != saved_group)
2091 {
2092#ifdef DEBUG
2093 g_debug ("CIF:: SP group changes between configuration:: conf= %d, saved_group= %d, new_group= %d", conf, saved_group, i);
2094#endif
2095 add_reader_info ("Space group changes between configurations !\n", 0);
2096 return 3;
2097 }
2098 else if (i > 0)
2099 {
2100 saved_group = i;
2101#ifdef DEBUG
2102 g_debug ("CIF:: SP setting:: %d, name= %s", this_reader -> setting+1, this_reader -> lattice.sp_group -> settings[this_reader -> setting].name);
2103#endif
2104 if (this_reader -> lattice.sp_group) get_origin (this_reader -> lattice.sp_group);
2105 }
2106 else if (i == 0)
2107 {
2108 // No space group found
2109#ifdef DEBUG
2110 g_debug ("CIF:: Impossible to retrieve space group information !");
2111#endif
2112 }
2113 else if (cif_multiple && ! this_reader -> cartesian)
2114 {
2115 // Error in space group
2116 return 3;
2117 }
2118 }
2119 else if (! this_reader -> cartesian)
2120 {
2121 // Error no cell data using fractional coordinates
2122 return 3;
2123 }
2124
2125 // Reading positions
2126 if (cif_get_symmetry_positions (linec, conf))
2127 {
2128 if (! cif_use_symmetry_positions && this_reader -> num_sym_pos)
2129 {
2130 add_reader_info ("Symmetry position(s) in CIF file\n", 1);
2131 }
2132 }
2133 if (cif_use_symmetry_positions && ! this_reader -> num_sym_pos)
2134 {
2135 add_reader_info ("No symmetry position(s) in CIF file\n", 0);
2136 return 3;
2137 }
2138 if (cif_get_atomic_coordinates (linec, conf))
2139 {
2140 cid = (conf && active_project -> steps == 1) ? 0 : conf;
2141 if (! this_reader -> cartesian)
2142 {
2143 for (i=0; i<3; i++)
2144 {
2145 for (j=0; j<3; j++)
2146 {
2147 if (i < 2)
2148 {
2149 active_cell -> box[cid].param[i][j] = this_reader -> lattice.box[cid].param[i][j];
2150 }
2151 active_cell -> box[cid].vect[i][j] = this_reader -> lattice.box[cid].vect[i][j];
2152 }
2153 }
2154 active_cell -> ltype = 1;
2155 active_cell -> pbc = TRUE;
2156 active_cell -> has_a_box = TRUE;
2157 if (this_reader -> lattice.sp_group)
2158 {
2159 active_cell -> crystal = TRUE;
2160 active_cell -> sp_group = duplicate_space_group (this_reader -> lattice.sp_group);
2161 }
2162 }
2163 res = 0;
2165 {
2166 gchar * str = g_strdup_printf ("<b>Building crystal using symmetry positions: </b> \n"
2167 " 1) evaluate candidate atomic positions using data in CIF file: \n"
2168 " - symmetry positions\n"
2169 " - atomic coordinates + occupancy\n"
2170 " 2) fill each candidate position using the associated occupancy: \n"
2171 " - occupancy %s\n"
2172 " - %s\n", cif_occ[this_reader -> rounding], cif_sites[1]);
2173 add_reader_info (str, 1);
2174 g_free (str);
2175 this_reader -> cartesian = TRUE;
2177 double spgpos[3][4];
2178 int max_pos = this_reader -> num_sym_pos * this_reader -> natomes;
2179 gboolean dist_message = FALSE;
2180 gboolean low_occ = FALSE;
2181 gboolean save_it;
2182 vec3_t f_pos, c_pos;
2183 gboolean * save_pos = allocbool (max_pos);
2184 mat4_t pos_mat;
2185 atom at, bt;
2186 distance dist;
2187 double u;
2188 vec3_t * all_pos = g_malloc0(max_pos*sizeof*all_pos);
2189 int * all_origin = allocint (max_pos);
2190 int * cif_pos = allocint (this_reader -> natomes);
2191 double ** cryst_pos = allocddouble (this_reader -> natomes, 3);
2192 double ** occ_pos = g_malloc0(sizeof*occ_pos);
2193 int ** lot_pos = g_malloc0(sizeof*lot_pos);
2194
2195 double * list_occ = allocdouble (this_reader -> natomes);
2196 double val;
2197 int vbl;
2198 int * list_pos = allocint (this_reader -> natomes);
2199 for (i=0; i<this_reader -> natomes; i++)
2200 {
2201 list_pos[i] = i;
2202 list_occ[i] = this_reader -> occupancy[i];
2203 }
2204 for (i=1; i<this_reader -> natomes; i++)
2205 {
2206 val = list_occ[i];
2207 vbl = list_pos[i];
2208 for (j=i-1; j>-1; j--)
2209 {
2210 if (list_occ[j] >= val) break;
2211 list_occ[j+1] = list_occ[j];
2212 list_pos[j+1] = list_pos[j];
2213 }
2214 list_occ[j+1] = val;
2215 list_pos[j+1] = vbl;
2216 }
2217 int num_pos = 0;
2218 int pos_max = 0;
2219 // The following might be modified for reaction CIF:
2220 // - this_reader -> coord[i] and this_readaer -> coord[j] are not necessarily equal
2221 // - both the disorder group and the occupancy matters in place of the coordinates
2222 for (i=0; i<2; i++)
2223 {
2224 for (j=0; j<this_reader -> natomes; j++)
2225 {
2226 k = list_pos[j];
2227 if (! j)
2228 {
2229 num_pos = 0;
2230 for (l=0; l<3; l++) cryst_pos[num_pos][l] = this_reader -> coord[k][l];
2231 cif_pos[num_pos] = 1;
2232 if (i)
2233 {
2234 occ_pos[num_pos][0] = this_reader -> occupancy[k];
2235 lot_pos[num_pos][0] = this_reader -> lot[k];
2236 }
2237 num_pos ++;
2238 pos_max = 1;
2239 }
2240 else
2241 {
2242 save_it = TRUE;
2243 for (l=0; l<num_pos; l++)
2244 {
2245 if (this_reader -> coord[k][0] == cryst_pos[l][0]
2246 && this_reader -> coord[k][1] == cryst_pos[l][1]
2247 && this_reader -> coord[k][2] == cryst_pos[l][2])
2248 {
2249 save_it = FALSE;
2250 break;
2251 }
2252 }
2253 if (save_it)
2254 {
2255 for (l=0; l<3; l++) cryst_pos[num_pos][l] = this_reader -> coord[k][l];
2256 cif_pos[num_pos] = 1;
2257 if (i)
2258 {
2259 occ_pos[num_pos][0] = this_reader -> occupancy[k];
2260 lot_pos[num_pos][0] = this_reader -> lot[k];
2261 }
2262 num_pos ++;
2263 }
2264 else
2265 {
2266 if (i)
2267 {
2268 occ_pos[l][cif_pos[l]] = this_reader -> occupancy[k];
2269 lot_pos[l][cif_pos[l]] = this_reader -> lot[k];
2270 }
2271 cif_pos[l] ++;
2272 pos_max = max (pos_max, cif_pos[l]);
2273 }
2274 }
2275 }
2276 if (! i)
2277 {
2278 occ_pos = allocddouble (num_pos, pos_max);
2279 lot_pos = allocdint (num_pos, pos_max);
2280 }
2281 }
2282 g_free (list_occ);
2283 g_free (list_pos);
2284 for (i=0; i<num_pos; i++)
2285 {
2286 u = 0;
2287 for (j=0; j<cif_pos[i]; j++)
2288 {
2289 u += occ_pos[i][j];
2290 }
2291 if (u < 1.0)
2292 {
2293 low_occ = TRUE;
2294 break;
2295 }
2296 }
2297 int * all_id = allocint (num_pos);
2298 l = m = 0;
2299 for (i=0; i<this_reader -> num_sym_pos; i++)
2300 {
2301 for (j=0; j<3; j++)
2302 {
2303 tmp_pos = g_strdup_printf ("%s", this_reader -> sym_pos[i][j]);
2304 for (k=0; k<3; k++)
2305 {
2306 spgpos[j][k] = get_val_from_wyckoff (vect_comp[k], this_reader -> sym_pos[i][j]);
2307 }
2308 if (tmp_pos)
2309 {
2310 spgpos[j][3] = get_value_from_pos (tmp_pos);
2311 g_free (tmp_pos);
2312 tmp_pos = NULL;
2313 }
2314 else
2315 {
2316 spgpos[j][3] = 0.0;
2317 }
2318 }
2319 pos_mat = mat4 (spgpos[0][0], spgpos[0][1], spgpos[0][2], spgpos[0][3],
2320 spgpos[1][0], spgpos[1][1], spgpos[1][2], spgpos[1][3],
2321 spgpos[2][0], spgpos[2][1], spgpos[2][2], spgpos[2][3],
2322 0.0, 0.0, 0.0, 1.0);
2323 for (j=0; j<num_pos; j++)
2324 {
2325 f_pos = vec3 (cryst_pos[j][0], cryst_pos[j][1], cryst_pos[j][2]);
2326 f_pos = m4_mul_coord (pos_mat, f_pos);
2327 c_pos = m4_mul_coord (this_reader -> lattice.box[cid].frac_to_cart, f_pos);
2328 all_pos[l].x = c_pos.x;
2329 all_pos[l].y = c_pos.y;
2330 all_pos[l].z = c_pos.z;
2331 all_origin[l] = j;
2332 save_it = TRUE;
2333 if (l)
2334 {
2335 at.x = all_pos[l].x;
2336 at.y = all_pos[l].y;
2337 at.z = all_pos[l].z;
2338 for (k=0; k<l; k++)
2339 {
2340 bt.x = all_pos[k].x;
2341 bt.y = all_pos[k].y;
2342 bt.z = all_pos[k].z;
2343 dist = distance_3d (active_cell, 0, & at, & bt);
2344 if (dist.length < 0.1)
2345 {
2346 dist_message = TRUE;
2347 save_it = FALSE;
2348 break;
2349 }
2350 }
2351 }
2352 save_pos[l] = save_it;
2353 l ++;
2354 if (save_it)
2355 {
2356 all_id[j] ++;
2357 m ++;
2358 }
2359 }
2360 }
2361 double prob;
2362 gboolean pick_it;
2363 gboolean ** taken_pos = g_malloc0 (num_pos*sizeof*taken_pos);
2364 int ** site_lot = g_malloc0 (num_pos*sizeof*site_lot);
2365 clock_t CPU_time;
2366 int tot_pos = 0;
2367 for (i=0; i<num_pos; i++)
2368 {
2369 taken_pos[i] = allocbool(all_id[i]);
2370 site_lot[i] = allocint(all_id[i]);
2371 for (j=0; j<cif_pos[i]; j++)
2372 {
2373 u = occ_pos[i][j]*all_id[i];
2374 if (u < 1.0 && tot_pos < all_id[i]) u = 1.0;
2375 k = lot_pos[i][j];
2376 l = 0;
2377 // Warning for occupancy closest integer value to u:
2378 // - (int)u ?
2379 // - nearbyint (u) : closest integer value ?
2380 while (l < occupancy(u, this_reader -> rounding))
2381 {
2382 CPU_time = clock ();
2383 m = (CPU_time - (j+17)*all_id[i]);
2384 prob = random3_(& m);
2385 m = round (prob * (all_id[i]-1));
2386 pick_it = ! taken_pos[i][m];
2387 if (pick_it)
2388 {
2389 site_lot[i][m] = k;
2390 taken_pos[i][m] = TRUE;
2391 l ++;
2392 tot_pos ++;
2393 }
2394 }
2395 }
2396 }
2397 crystal_data * cryst = allocate_crystal_data (tot_pos, this_reader -> nspec + this_reader -> object_to_insert);
2398 i = 0;
2399 int * cryst_lot = allocint (cryst -> objects);
2400 int * from_origin = allocint (num_pos);
2401 for (j=0; j<max_pos; j++)
2402 {
2403 if (save_pos[j])
2404 {
2405 k = all_origin[j];
2406 l = from_origin[k];
2407 if (taken_pos[k][l])
2408 {
2409 cryst -> coord[i] = g_malloc0(sizeof*cryst -> coord[i]);
2410 cryst -> coord[i][0].x = all_pos[j].x;
2411 cryst -> coord[i][0].y = all_pos[j].y;
2412 cryst -> coord[i][0].z = all_pos[j].z;
2413 cryst -> pos_by_object[i] = 1;
2414 cryst_lot[i] = site_lot[k][l];
2415 if (cryst_lot[i] < 0)
2416 {
2417 cryst -> at_by_object[i] = get_atomic_object_by_origin (cif_object, - cryst_lot[i] - 1, 0) -> atoms;
2418 }
2419 else
2420 {
2421 cryst -> at_by_object[i] = 1;
2422 }
2423 i ++;
2424 }
2425 from_origin[k] ++;
2426 }
2427 }
2428 g_free (site_lot);
2429 g_free (all_origin);
2430 g_free (from_origin);
2431 g_free (all_pos);
2432 g_free (save_pos);
2433 g_free (taken_pos);
2434 g_free (all_id);
2435 i = 0;
2436 for (j=0; j<cryst -> objects; j++)
2437 {
2438 i += cryst -> at_by_object[j] * cryst -> pos_by_object[j];
2439 }
2440 if (! conf || active_project -> steps == 1)
2441 {
2442 active_project -> natomes = i;
2444 }
2445 atomic_object * c_obj;
2446 int * spec_num = allocint (120);
2447 i = 0;
2448 for (j=0; j<cryst -> objects; j++)
2449 {
2450 if (cryst_lot[j] < 0)
2451 {
2452 k = - cryst_lot[j] - 1;
2454 for (l=0; l<c_obj -> atoms; l++)
2455 {
2456 m = c_obj -> at_list[l].sp;
2457 n = c_obj -> old_z[m];
2458 spec_num[n] ++;
2459 active_project -> atoms[cid][i].sp = n;
2460 active_project -> atoms[cid][i].x = cryst -> coord[j][0].x + c_obj -> at_list[l].x;
2461 active_project -> atoms[cid][i].y = cryst -> coord[j][0].y + c_obj -> at_list[l].y;
2462 active_project -> atoms[cid][i].z = cryst -> coord[j][0].z + c_obj -> at_list[l].z;
2463 i ++;
2464 }
2465 }
2466 else
2467 {
2468 k = (int)this_reader -> z[cryst_lot[j]];
2469 spec_num[k] ++;
2470 active_project -> atoms[cid][i].sp = k;
2471 active_project -> atoms[cid][i].x = cryst -> coord[j][0].x;
2472 active_project -> atoms[cid][i].y = cryst -> coord[j][0].y;
2473 active_project -> atoms[cid][i].z = cryst -> coord[j][0].z;
2474 i ++;
2475 }
2476 }
2477 g_free (this_reader -> nsps);
2478 int * tmp_nsps = allocint (120);
2479 int * tmp_spid = allocint (120);
2480 i = 0;
2481 for (j=0; j<120; j++)
2482 {
2483 if (spec_num[j])
2484 {
2485 tmp_nsps[i] = spec_num[j];
2486 tmp_spid[j] = i;
2487 i++;
2488 }
2489 }
2490 this_reader -> nspec = i;
2491 this_reader -> nsps = allocint (i);
2492 for (i=0; i<this_reader -> nspec; i++) this_reader -> nsps[i] = tmp_nsps[i];
2493 g_free (tmp_nsps);
2494 g_free (this_reader -> z);
2495 this_reader -> z = allocdouble(i);
2496 i = 0;
2497 for (j=0; j<120; j++)
2498 {
2499 if (spec_num[j])
2500 {
2501 this_reader -> z[i] = (double)j;
2502 i ++;
2503 }
2504 }
2505 for (i=0; i<active_project -> natomes; i++)
2506 {
2507 j = active_project -> atoms[cid][i].sp;
2508 k = tmp_spid[j];
2509 active_project -> atoms[cid][i].sp = k;
2510 }
2511 g_free (tmp_spid);
2512 if (low_occ)
2513 {
2514 add_reader_info ("The crystal will be created however some objects might be missing,\n"
2515 "Occupancy is too low compared to the number of site(s) per cell.\n\n"
2516 "<b>To build a crystal matching the defined occupancy</b>:\n"
2517 "\t <b>1)</b> If you are trying to read a CIF file, use the crystal builder instead.\n"
2518 "\t <b>2)</b> Modify the occupancy set-up to 'Completely random'.\n"
2519 "\t <b>3)</b> Increase the number of unit cells up to get rid of this message.\n\n", 1);
2520 }
2521 if (dist_message)
2522 {
2523 add_reader_info ("Object(s) at equivalent positions have been removed\n"
2524 "to ensure the consistency of the model\n"
2525 "when using <b>P</b>eriodic <b>B</b>oundary <b>C</b>onditions\n ", 1);
2526 }
2527 }
2528 }
2529 else
2530 {
2531 // No coordinates found
2532#ifdef DEBUG
2533 g_debug ("CIF:: Impossible to retrieve atomic coordinates !");
2534#endif
2535 res = 2;
2536 }
2537 return res;
2538}
2539
2547int open_cif_file (int linec)
2548{
2549 gchar * frackeys[3] = {"fract_x", "fract_y", "fract_z"};
2550 gchar * cartkeys[3] = {"cartn_x", "cartn_y", "cartn_z"};
2551 gchar * str = NULL;
2552 int cif_action = 0;
2553 int cif_step = 1;
2554 int cif_site;
2555 int cif_occup = 0;
2556 int i, j;
2557
2558 cif_multiple = TRUE;
2559 // Determine the number of configuration(s) by checking the presence
2560 // of the instruction used to declare atomic coordinates
2561 this_reader -> steps = cif_get_value ("_atom_site", frackeys[0], 0, linec, NULL, FALSE, FALSE, TRUE, FALSE, NULL);
2562 if (! this_reader -> steps)
2563 {
2564 this_reader -> steps = cif_get_value ("_atom_site", cartkeys[0], 0, linec, NULL, FALSE, FALSE, TRUE, FALSE, NULL);
2565 this_reader -> cartesian = TRUE;
2566 }
2567 else
2568 {
2569 // How to treat occupancy
2570 cif_occup = cif_get_value ("_atom_site", "occupancy", 0, linec, NULL, FALSE, FALSE, TRUE, FALSE, NULL);
2571 if (cif_occup)
2572 {
2573 this_reader -> rounding = iask ("Please select how to handle occupancy", "Select how to handle occupancy", 5, MainWindow);
2574 if (this_reader -> rounding < 0 || this_reader -> rounding > 2) this_reader -> rounding = 2;
2576 {
2577 str = g_strdup_printf ("Occupancy %s\n\t%s\n", cif_occ[this_reader -> rounding], cif_sites[cif_use_symmetry_positions]);
2578 add_reader_info (str, 1);
2579 g_free (str);
2580 }
2581 }
2582 }
2583
2584 if (this_reader -> steps > 1)
2585 {
2586 str = g_strdup_printf ("It seems the CIF file contains <b>%d</b> distinct configurations\n", this_reader -> steps);
2587 add_reader_info (str, 1);
2588 g_free (str);
2590 {
2591 str = g_strdup_printf ("Impossible to use symmetry positions with multiple configurations\n");
2592 add_reader_info (str, 1);
2593 g_free (str);
2594 }
2595 }
2596
2597 if (this_reader -> steps > 1 && ! cif_use_symmetry_positions)
2598 {
2599 cif_site = cif_get_value ("_atom_site", "disorder_group", 0, linec, NULL, FALSE, FALSE, TRUE, FALSE, NULL);
2600 if (cif_occup == this_reader -> steps && cif_occup == cif_site)
2601 {
2602 add_reader_info ("This CIF file could be describing a trajectory or a chemical reaction.\n", 1);
2603 // This is where to ask what to do !
2604 // Read like a chemical reaction: read one configuration sort coordinates by occupancy
2605 // Read all as trajectory CIF file: forget about using occupancy to sort coordinates
2606 // - possible if the number of atom(s) by configuration remains constant
2607 // Read only a selected configuration and:
2608 // - read as normal CIF file, forget about using occupancy to sort coordinates
2609 // Because what follow will depend on this choice
2610 /* cif_action = iask ("Please select how to process the data in the CIF file", "Select how to process data", 3, MainWindow);
2611 this_reader -> chemical = ! cif_action;
2612 cif_action = (cif_action == 1) ? 0 : 1; */
2613 cif_action = iask ("Please select how to process the data in the CIF file", "Select how to process data", 4, MainWindow);
2614 }
2615 else
2616 {
2617 add_reader_info ("This CIF file could be describing a trajectory.\n", 1);
2618 cif_action = iask ("Please select how to process the data in the CIF file", "Select how to process data", 4, MainWindow);
2619 }
2620 }
2621 else
2622 {
2623 cif_action = 1;
2624 }
2625
2626 if (cif_action && this_reader -> steps > 1)
2627 {
2628 // We need to select the step to work on
2629 str = g_strdup_printf ("Select the configuration, in [1- %d]", this_reader -> steps);
2630 cif_step = 0;
2631 while (! cif_step)
2632 {
2633 cif_step = iask ("Please select the configuration to work on", str, 0, MainWindow);
2634 if (cif_step < 1 || cif_step > this_reader -> steps) cif_step = 0;
2635 }
2636 g_free (str);
2637 }
2638 if (cif_action)
2639 {
2640 active_project -> steps = 1;
2641 if (this_reader -> steps > 1)
2642 {
2643 str = g_strdup_printf ("Working on configuration N°%d\n", cif_step);
2644 add_reader_info (str, 1);
2645 g_free (str);
2646 }
2647 }
2648
2649 if (cif_action)
2650 {
2651 return open_cif_configuration (linec, cif_step - 1);
2652 }
2653 else
2654 {
2655 active_project -> steps = this_reader -> steps;
2656 g_free (active_cell -> box);
2657 active_cell -> box = g_malloc0(this_reader -> steps*sizeof*active_cell -> box);
2658 // For each configuration open it:
2659 i = 0;
2660 for (j=0; j<active_project -> steps; j++)
2661 {
2662 this_reader -> nspec = 0;
2663 if (this_reader -> nsps)
2664 {
2665 g_free (this_reader -> nsps);
2666 this_reader -> nsps = NULL;
2667 }
2668 i = open_cif_configuration (linec, j);
2669 if (i) return i;
2670 }
2671 return 0;
2672 }
2673}
atom_search * allocate_atom_search(int proj, int action, int searchid, int tsize)
allocate atom search data structure
Definition atom_edit.c:386
Function declarations for the mode edition window.
GtkTreeModel * replace_combo_tree(gboolean insert, int proj)
replace combo box in the tree view
Definition w_search.c:2626
int get_selected_object_id(gboolean visible, int p, gchar *str, atom_search *asearch)
get the id of the object selected (in contextual menu, or in combo box)
Definition w_search.c:2396
gchar * mot[2][2]
Definition popup.c:3298
void to_insert_in_project(int stat, int orig, project *this_proj, atom_search *asearch, gboolean visible)
to insert object in project
atomic_object * get_atomic_object_by_origin(atomic_object *first, int oid, int aid)
get insert object from a list by id
Definition w_search.c:474
Binding to the Fortran90 subroutines.
double random3_(int *)
gchar * substitute_string(gchar *init, gchar *o_motif, gchar *n_motif)
substitute all patterns in string
Definition w_library.c:372
double get_val_from_wyckoff(gchar *pos, gchar *wval)
get point value from wyckoff position
int occupancy(double occ, int cif_occ)
handle occupancy integer rouding
crystal_data * allocate_crystal_data(int objects, int species)
allocate crystal data pointer
double get_value_from_pos(gchar *pos)
get position double value from string description
Function declarations for the crystal builder.
gchar * groups[230]
Definition cbuild_sg.c:43
void allocatoms(project *this_proj)
allocate project data
Definition open_p.c:163
gchar * hmsymbols[230]
Definition cbuild_sg.c:274
gchar * replace_markup(char *init, char *key, char *rep)
replace pattern in string
Definition w_library.c:339
gchar * param[2]
double ax
Definition curve.c:70
void label(cairo_t *cr, double val, int axe, int p, project *this_proj)
draw axis label
Definition labels.c:56
double dist
Definition d_measures.c:73
int atoms[NUM_STYLES][2]
float val
Definition dlp_init.c:117
int * duplicate_int(int num, int *old_val)
copy a list of int
Definition global.c:560
int multi
Definition dlp_init.c:121
char * box_prop[2][3]
Definition edit_menu.c:74
int ** allocdint(int xal, int yal)
allocate an int ** pointer
Definition global.c:330
double * duplicate_double(int num, double *old_val)
copy a list of double
Definition global.c:608
int activep
Definition global.c:159
gboolean * allocbool(int val)
allocate a gboolean * pointer
Definition global.c:254
double ** allocddouble(int xal, int yal)
allocate a double ** pointer
Definition global.c:475
double * allocdouble(int val)
allocate a double * pointer
Definition global.c:459
GtkWidget * MainWindow
Definition global.c:201
int * allocint(int val)
allocate an int * pointer
Definition global.c:314
gboolean cif_use_symmetry_positions
Definition global.c:189
double string_to_double(gpointer string)
convert string to double
Definition global.c:624
Global variable declarations Global convenience function declarations Global data structure defin...
void run_this_gtk_dialog(GtkWidget *dial, GCallback handler, gpointer data)
run a GTK (3 and 4) basic GtkDialog
Definition gtk-misc.c:501
GtkWidget * dialogmodal(gchar *str, GtkWindow *parent)
Create a new dialog modal window.
Definition gtk-misc.c:520
cell_info * active_cell
Definition project.c:50
void combo_set_markup(GtkWidget *combo)
use pango markup in combo widget
Definition gtk-misc.c:944
element_data periodic_table_info[]
Definition w_library.c:71
void combo_set_active(GtkWidget *combo, int pos)
set the active item's position
Definition gtk-misc.c:932
GtkWidget * stock_image(const gchar *stock_id)
create a GtkImage for the Gtk database
Definition gtk-misc.c:1425
#define APPLY
Definition global.h:222
GtkWidget * dialog_get_content_area(GtkWidget *widg)
prepare GtkWidget to insert content in a GtkDialog window
Definition gtk-misc.c:835
GtkWidget * markup_label(gchar *text, int dimx, int dimy, float ax, float ay)
create a GtkLabel with pango markup
Definition gtk-misc.c:1646
void add_box_child_start(int orientation, GtkWidget *widg, GtkWidget *child, gboolean expand, gboolean fill, int padding)
Add a GtkWidget in a GtkBox at the initial position.
Definition gtk-misc.c:308
#define DELETEB
Definition global.h:224
GtkWidget * create_hbox(int spacing)
create a GtkBox with horizontal orientation
Definition gtk-misc.c:823
G_MODULE_EXPORT void run_destroy_dialog(GtkDialog *dialog, gint response_id, gpointer data)
to destroy a GtkDialog when the dialog emit the closing signal
Definition gtk-misc.c:2237
#define min(a, b)
Definition global.h:81
void set_image_from_icon_name(GtkWidget *widg, gchar *icon)
set a image from a stock icon name
Definition gtk-misc.c:1986
struct model model
data structure to describe the topology
Definition global.h:830
project * active_project
Definition project.c:47
#define max(a, b)
Definition global.h:80
@ REPLACE
Definition glview.h:234
int objects[3]
Definition selection.c:212
int iask(char *question, char *lab, int id, GtkWidget *win)
enter an integer value - prepare the dialog
Definition interface.c:556
gchar * cif_occ[3]
Definition interface.c:478
gchar * cif_sites[2]
Definition interface.c:481
Messaging function declarations.
char * vect_comp[3]
Definition edit_menu.c:83
integer(kind=c_int) function lattice(totl, lid, vectors, vmod, angles, lat, cfrac, apbc)
Definition lattice.F90:162
double z
Definition ogl_draw.c:61
Function declarations for reading atomes project file Function declarations for saving atomes proje...
void check_for_species(double v, int ato)
Fill the species for each atom and the associated data.
Definition read_coord.c:220
int cif_atoms
Definition read_cif.c:98
gchar * get_atom_disorder(gchar *line, int lid)
read atom disorder group from CIF file
Definition read_cif.c:300
gboolean cif_get_atomic_coordinates(int linec, int conf)
Definition read_cif.c:1105
void file_get_to_line(int line_id)
reach line in CIF file
Definition read_cif.c:411
int * keylines
Definition read_cif.c:96
gchar * get_string_from_origin(space_group *spg)
get the space group origin from its name
Definition read_cif.c:1579
gboolean cif_multiple
Definition read_cif.c:103
int cif_file_get_number_of_positions(int lid)
get the number of symmetry positions
Definition read_cif.c:1403
G_MODULE_EXPORT void set_cif_to_insert(GtkComboBox *box, gpointer data)
change the object to insert at an empty cif position
Definition read_cif.c:323
int cif_get_space_group(int linec, int conf)
get the space group from the CIF file
Definition read_cif.c:1842
int * cif_nsps
Definition read_cif.c:101
double get_z_from_periodic_table(gchar *lab)
get Z from atom label
Definition w_library.c:304
gboolean cif_file_get_atoms_data(int conf, int lin, int cid[9])
Definition read_cif.c:992
void compute_lattice_properties(cell_info *cell, int box_id)
compute lattice parameters following cell description
void check_for_to_lab(int ato, gchar *stlab)
check atom label
Definition read_cif.c:941
GtkWidget ** img_cif
Definition read_cif.c:311
int saved_group
Definition read_cif.c:97
int get_atom_wyckoff(gchar *line, int wid)
read Wyckoff position from CIF file
Definition read_cif.c:272
int * cif_lot
Definition read_cif.c:100
space_group * duplicate_space_group(space_group *spg)
duplicate space ground information
int group_info_from_hm_key(int spg, gchar *key_hm)
get the space group information using the HM key from the CIF file
Definition read_cif.c:1697
gboolean cif_get_symmetry_positions(int linec, int conf)
read the symmetry positions from the CIF file
Definition read_cif.c:1497
gboolean cif_get_cell_data(int linec, int conf)
get the cell data from the CIF file
Definition read_cif.c:1780
int read_space_group(builder_edition *cbuilder, int spg)
read space group N°spg data from file
gchar * tmp_pos
int cif_file_get_data_in_loop(int linec, int lid)
get the number of "_" motifs in a line
Definition read_cif.c:635
void get_wyck_char(float val, int ax, int bx)
convert wyckoff value to string
int get_loop_line_id(int lid)
reach a line in the CIF file
Definition read_cif.c:699
float get_atom_coord(gchar *line, int mid)
read atom coordinates from CIF file
Definition read_cif.c:220
int cif_file_get_number_of_atoms(int linec, int lid, int nelem)
get the number of atom(s) in a CIF file
Definition read_cif.c:874
int cif_get_value(gchar *kroot, gchar *keyw, int lstart, int lend, gchar **cif_word, gboolean rec_val, gboolean all_ligne, gboolean total_num, gboolean record_position, int *line_position)
read pattern in CIF file
Definition read_cif.c:436
FILE * cifp
Definition read_cif.c:94
gboolean get_missing_object_from_user()
get missing atomic number in CIF file from the user
Definition read_cif.c:358
char * line_ptr
Definition read_cif.c:95
int get_setting_from_hm(gchar *hmk, int end)
Getting the space group parameters using the HM Key.
Definition read_cif.c:1609
int get_loop_line_for_key(int linec, int conf, gchar *key_a, gchar *key_b)
search a string
Definition read_cif.c:756
void get_origin(space_group *spg)
get space group origin matrices
int open_cif_file(int linec)
open CIF file
Definition read_cif.c:2547
gchar * cif_coord_opts[40][2]
Definition read_cif.c:107
gchar * get_atom_label(gchar *line, int lid)
read atom label from CIF file
Definition read_cif.c:243
int get_atom_id_from_periodic_table(atom_search *asearch)
get atom Z from selection in the periodic table
Definition w_periodic.c:672
gchar * cif_retrieve_value(int linec, int conf, gchar *key_a, gchar *key_b, gboolean all_ligne, gboolean in_loop, gboolean warning)
retrieve a field value as string in the CIF file
Definition read_cif.c:802
int open_cif_configuration(int linec, int conf)
Definition read_cif.c:2082
int test_lattice(builder_edition *cbuilder, cell_info *cif_cell)
test lattice parameters
int get_space_group_from_hm(gchar *hmk)
retrieve space group using the HM Key
Definition read_cif.c:1525
atom_search * cif_search
Definition read_cif.c:312
gchar ** cif_strings
Definition read_cif.c:105
gchar * wnpos[3]
Definition cbuild_info.c:74
int cif_nspec
Definition read_cif.c:99
void sort(int dim, int *tab)
sort, nim to max, a table by integer value
Definition glview.c:391
gchar * get_cif_word(gchar *mot)
get string from CIF file, EOL can be ugly
Definition read_cif.c:205
atomic_object * cif_object
Definition read_cif.c:313
distance distance_3d(cell_info *cell, int mdstep, atom *at, atom *bt)
distance between atom a and b in 3D
Definition ogl_utils.c:81
line_node * head
Definition read_coord.c:77
gchar ** coord_line
Definition read_coord.c:74
coord_file * this_reader
Definition read_coord.c:73
line_node * tail
Definition read_coord.c:78
void add_reader_info(gchar *info, int mid)
append information message to the reader information
Definition read_coord.c:88
gchar * this_line
Definition read_coord.c:75
Functions declaration to read atomic coordinates.
Definition global.h:891
double z
Definition global.h:897
double y
Definition global.h:896
double x
Definition global.h:895
Definition glwin.h:351
double * z
Definition cbuild_edit.h:42
float y
Definition math_3d.h:130
float x
Definition math_3d.h:130
float z
Definition math_3d.h:130
int c
Definition tab-1.c:95
GtkWidget * res[2]
Definition w_encode.c:212
GtkWidget * hbox
Definition workspace.c:71
GtkWidget * vbox
Definition workspace.c:72
GtkWidget * lab
Definition workspace.c:73