atomes 1.1.17
atomes: an atomic scale modeling tool box
All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
cbuild_action.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: 'cbuild_action.c'
24*
25* Contains:
26*
27
28 - The functions to build a crystal using space group, crystallographic position(s) and object(s) to insert
29
30*
31* List of functions:
32
33 int test_lattice (builder_edition * cbuilder, cell_info * cif_cell);
34 int pos_not_saved (vec3_t * all_pos, int num_pos, vec3_t pos);
35 int build_crystal (gboolean visible, project * this_proj, gboolean to_wrap, gboolean show_clones, cell_info * cell, GtkWidget * widg);
36
37 double get_val_from_setting (gchar * pos, gchar * sval);
38 double get_value_from_pos (gchar * pos);
39 double get_val_from_wyckoff (gchar * pos, gchar * wval);
40
41 gboolean same_coords (float a, float b);
42 gboolean are_equal_vectors (vec3_t u, vec3_t v);
43 gboolean pos_not_taken (int pos, int dim, int * tab);
44 gboolean adjust_object_occupancy (crystal_data * cryst, int occupying, int tot_cell);
45
46 void get_origin (space_group * spg);
47 void compute_lattice_properties (cell_info * cell);
48 void clean_this_proj (project * this_proj, gboolean newp);
49
50 space_group * duplicate_space_group (space_group * spg);
51
52 crystal_data * allocate_crystal_data (int objects, int species);
53 crystal_data * free_crystal_data (crystal_data * cryst);
54
55*/
56
57#include "global.h"
58#include "callbacks.h"
59#include "interface.h"
60#include "glview.h"
61#include "bind.h"
62#include "project.h"
63#include "workspace.h"
64#include "atom_edit.h"
65#include "cbuild_edit.h"
66#include "readers.h"
67#include <ctype.h>
68
69extern int get_crystal_id (int spg);
71
72gchar * tmp_pos = NULL;
73
82double get_val_from_setting (gchar * pos, gchar * sval)
83{
84 if (! strstr(sval, pos))
85 {
86 return 0.0;
87 }
88 else
89 {
90 if (! g_strcmp0(sval, pos))
91 {
92 g_free (tmp_pos);
93 tmp_pos = NULL;
94 return 1.0;
95 }
96 gchar * sym[8]={"-1/3", "+1/3", "1/3", "-2/3", "+2/3", "2/3", "-", "+"};
97 double vals[8]={-1.0/3.0, 1.0/3.0, 1.0/3.0, -2.0/3.0, 2.0/3.0, 2.0/3.0, -1.0, 1.0};
98 gchar * ksym = NULL;
99 int i;
100 for (i=0; i<8; i++)
101 {
102 ksym = g_strdup_printf ("%s%s", sym[i], pos);
103 if (strstr(sval, ksym))
104 {
105 tmp_pos = g_strdup_printf ("%s", replace_markup (tmp_pos, ksym, NULL));
106 g_free (ksym);
107 ksym = NULL;
108 if (! strlen(tmp_pos))
109 {
110 g_free (tmp_pos);
111 tmp_pos = NULL;
112 }
113 return vals[i];
114 }
115 g_free (ksym);
116 ksym = NULL;
117 }
118 tmp_pos = g_strdup_printf ("%s", replace_markup (tmp_pos, pos, NULL));
119 if (! strlen(tmp_pos))
120 {
121 g_free (tmp_pos);
122 tmp_pos = NULL;
123 }
124 return 1.0;
125 }
126}
127
135double get_value_from_pos (gchar * pos)
136{
137 if (strstr(pos, "/"))
138 {
139 char * p = NULL;
140 double u, v;
141 p = strtok(pos, "/");
142 u = string_to_double ((gpointer)p);
143 p = strtok(NULL, "/");
144 v = string_to_double ((gpointer)p);
145 return u/v;
146 }
147 else
148 {
149 return string_to_double ((gpointer)pos);
150 }
151}
152
161{
162 char * vinit[3]={"a", "b", "c"};
163 double spinit[3][4];
164 int i, j, k;
165 i = spg -> sid;
166 for (j=0; j<3; j++)
167 {
168 tmp_pos = g_strdup_printf ("%s", spg -> settings[i].pos[j]);
169 for (k=0; k<3; k++)
170 {
171 spinit[j][k] = get_val_from_setting (vinit[k], spg -> settings[i].pos[j]);
172 }
173 if (tmp_pos)
174 {
175 spinit[j][3] = get_value_from_pos (tmp_pos);
176 g_free (tmp_pos);
177 tmp_pos = NULL;
178 }
179 else
180 {
181 spinit[j][3] = 0.0;
182 }
183 }
184 spg -> coord_origin = mat4 (spinit[0][0], spinit[1][0], spinit[2][0], 0.0,
185 spinit[0][1], spinit[1][1], spinit[2][1], 0.0,
186 spinit[0][2], spinit[1][2], spinit[2][2], 0.0,
187 0.0, 0.0, 0.0, 1.0);
188 spg -> wyck_origin = m4_invert_affine (spg -> coord_origin);
189 spg -> coord_origin.m30 = spg -> wyck_origin.m30 = spinit[0][3];
190 spg -> coord_origin.m31 = spg -> wyck_origin.m31 = spinit[1][3];
191 spg -> coord_origin.m32 = spg -> wyck_origin.m32 = spinit[2][3];
192#ifdef DEBUG
193 g_debug ("Coord origin:");
194 m4_print (spg -> coord_origin);
195 g_debug ("Wyck origin:");
196 m4_print (spg -> wyck_origin);
197#endif
198}
199
208{
209 int i;
210 box_info * box = & cell -> box[0];
211 double ltemp;
212 double angle[3];
213 double sangle[3], cangle[3];
214
215 if (! cell -> ltype)
216 {
217 for (i=0; i<3; i++)
218 {
219 if (box -> param[1][i] == 90.0)
220 {
221 angle[i] = pi/2.0;
222 sangle[i] = 1.0;
223 cangle[i] = 0.0;
224 }
225 else
226 {
227 angle[i] = box -> param[1][i]*pi/180.0;
228 sangle[i] = sin(angle[i]);
229 cangle[i] = cos(angle[i]);
230 }
231 }
232 box -> vect[0][0] = box -> param[0][0];
233 box -> vect[0][1] = box -> vect[0][2] = 0.0;
234 box -> vect[1][0] = box -> param[0][1] * cangle[2];
235 box -> vect[1][1] = box -> param[0][1] * sangle[2];
236 box -> vect[1][2] = 0.0;
237 box -> vect[2][0] = box -> param[0][2] * cangle[1];
238 ltemp = (cangle[0] - cangle[1]*cangle[2]) / sangle[2];
239 box -> vect[2][1] = box -> param[0][2] * ltemp;
240 box -> vect[2][2] = box -> param[0][2] * sqrt(sangle[1]*sangle[1] - ltemp*ltemp);
241 }
242 else
243 {
244 for (i=0; i<3; i++) box -> param[0][i] = v3_length(vec3(box -> vect[i][0], box -> vect[i][1], box -> vect[i][2]));
245 box -> param[1][0] = (box -> vect[2][0]*box -> vect[1][0] + box -> vect[2][1]*box -> vect[1][1] + box -> vect[2][2]*box -> vect[1][2]);
246 box -> param[1][0] /= (box -> param[0][1] * box -> param[0][2]);
247 box -> param[1][1] = (box -> vect[0][0]*box -> vect[2][0] + box -> vect[0][1]*box -> vect[2][1] + box -> vect[0][2]*box -> vect[2][2]);
248 box -> param[1][1] /= (box -> param[0][0] * box -> param[0][2]);
249 box -> param[1][2] = (box -> vect[0][0]*box -> vect[1][0] + box -> vect[0][1]*box -> vect[1][1] + box -> vect[0][2]*box -> vect[1][2]);
250 box -> param[1][2] /= (box -> param[0][0] * box -> param[0][1]);
251
252 for (i=0; i<3; i++)
253 {
254 if (box -> param[1][i] == 0.0)
255 {
256 box -> param[1][i] = 90.0;
257 sangle[i] = 1.0;
258 cangle[i] = 0.0;
259 }
260 else
261 {
262 angle[i] = acos(box -> param[1][i]);
263 sangle[i] = sin(angle[i]);
264 cangle[i] = cos(angle[i]);
265 box -> param[1][i] = angle[i]*180.0/pi;
266 }
267 }
268 }
269
270#ifdef DEBUG
271 g_debug (" a= %f, b= %f, c= %f", box -> param[0][0], box -> param[0][1], box -> param[0][2]);
272 g_debug (" alpha= %f, beta= %f, gamma= %f", box -> param[1][0], box -> param[1][1], box -> param[1][2]);
273 g_debug (" a.x= %f, a.y= %f, a.z= %f", box -> vect[0][0], box -> vect[0][1], box -> vect[0][2]);
274 g_debug (" b.x= %f, b.y= %f, b.z= %f", box -> vect[1][0], box -> vect[1][1], box -> vect[1][2]);
275 g_debug (" c.x= %f, c.y= %f, c.z= %f", box -> vect[2][0], box -> vect[2][1], box -> vect[2][2]);
276#endif
277 box -> vol = (box -> vect[0][1]*box -> vect[1][2] - box -> vect[0][2]*box -> vect[1][1])*box -> vect[2][0];
278 box -> vol += (box -> vect[0][2]*box -> vect[1][0] - box -> vect[0][0]*box -> vect[1][2])*box -> vect[2][1];
279 box -> vol += (box -> vect[0][0]*box -> vect[1][1] - box -> vect[0][1]*box -> vect[1][0])*box -> vect[2][2];
280 box -> vol = fabs(box -> vol);
281 cell -> volume = box -> vol;
282#ifdef DEBUG
283 g_debug ("Lattice volume= %f", box -> vol);
284#endif
285 double z = sqrt(fabs(1 - cangle[0]*cangle[0]-cangle[1]*cangle[1]-cangle[2]*cangle[2] + 2*cangle[0]*cangle[1]*cangle[2]));
286
287 float ** ftc;
288 ftc = allocdfloat (4,4);
289 ftc[0][0]=box -> param[0][0];
290 ftc[0][1]=box -> param[0][1]*cangle[2];
291 ftc[0][2]=box -> param[0][2]*cangle[1];
292 ftc[1][1]=box -> param[0][1]*sangle[2];
293 ftc[1][2]=box -> param[0][2]*((cangle[0]-cangle[1]*cangle[2])/sangle[2]);
294 ftc[2][2]=box -> param[0][2]*z/sangle[2];
295 box -> frac_to_cart = mat4(ftc[0][0], ftc[0][1], ftc[0][2], ftc[0][3],
296 ftc[1][0], ftc[1][1], ftc[1][2], ftc[1][3],
297 ftc[2][0], ftc[2][1], ftc[2][2], ftc[2][3],
298 ftc[3][0], ftc[3][1], ftc[3][2], ftc[3][3]);
299 ftc[0][0]=1.0/box -> frac_to_cart.m00;
300 ftc[0][1]=-cangle[2]/(sangle[2]*box -> param[0][0]);
301 ftc[0][2]=box -> param[0][1]*box -> param[0][2]/box -> vol;
302 ftc[0][2]=ftc[0][2]*(cangle[0]*cangle[2] - cangle[1])/sangle[0];
303 ftc[1][1]=1.0/box -> frac_to_cart.m11;
304 ftc[1][2]=(box -> param[0][0]*box -> param[0][2])/box -> vol;
305 ftc[1][2]=ftc[1][2]*(cangle[1]*cangle[2] - cangle[0])/sangle[2];
306 ftc[2][2]=1.0/box -> frac_to_cart.m22;
307 box -> cart_to_frac = mat4 (ftc[0][0], ftc[0][1], ftc[0][2], ftc[0][3],
308 ftc[1][0], ftc[1][1], ftc[1][2], ftc[1][3],
309 ftc[2][0], ftc[2][1], ftc[2][2], ftc[2][3],
310 ftc[3][0], ftc[3][1], ftc[3][2], ftc[3][3]);
311 g_free (ftc);
312#ifdef DEBUG
313 m4_print (box -> frac_to_cart);
314 m4_print (box -> cart_to_frac);
315#endif
316}
317
326int test_lattice (builder_edition * cbuilder, cell_info * cif_cell)
327{
328 int i, j;
329 cell_info * cell = (cbuilder) ? & cbuilder -> cell : cif_cell;
330 box_info * box = & cell -> box[0];
331 i = cell -> sp_group -> id;
332 j = get_crystal_id (i);
333
334 if (cbuilder)
335 {
336 if (! cell -> ltype)
337 {
338 // Adjust a,b,c,alpha,beta,gamma and compute vectors
339 if (j == 3 || j == 4 || j == 6)
340 {
341 box -> param[1][1] = box -> param[1][2] = box -> param[1][0];
342 }
343 if (j == 3 || (j == 4 && cell -> sp_group -> name[0] == 'P') || j == 5)
344 {
345 box -> param[0][1] = box -> param[0][0];
346 }
347 else if ((j == 4 && cell -> sp_group -> name[0] == 'R') || j == 6)
348 {
349 box -> param[0][1] = box -> param[0][2] = box -> param[0][0];
350 }
351 }
352 if (! test_vol(box -> param, box -> vect))
353 {
354 show_warning ("Please describe properly the lattice parameters", cbuilder -> win);
355 return 0;
356 }
358 }
359
360 // Strictly different or possibly different ?
361 /*if (j < 3)
362 {
363 if (box -> param[0][0] == box -> param[0][1] || box -> param[0][0] == box -> param[0][2] || box -> param[0][1] == box -> param[0][2])
364 {
365 // Box error: a, b, c not all different
366 return 0;
367 }
368 }*/
369
370 if (j == 3 || j == 4 || j == 5)
371 {
372 if (box -> param[0][0] != box -> param[0][1])
373 {
374 // Box error: a and b must be equal
375 return 0;
376 }
377 }
378 if (j == 2 || j == 3 || j == 6)
379 {
380 if (box -> param[1][0] != 90.0 || box -> param[1][1] != 90.0 || box -> param[1][2] != 90.0)
381 {
382 // Angle error: alpha, beta and gamma must be = 90
383 return 0;
384 }
385 }
386
387 switch (j)
388 {
389 // Strictly different or possibly different ?
390 /*
391 case 0:
392 if (! (box -> param[1][0] != box -> param[1][1] && box -> param[1][0] != box -> param[1][2] && box -> param[1][1] != box -> param[1][2]))
393 {
394 // Angle error: alpha, beta, gamma not all different
395 return 0;
396 }
397 break;
398 */
399 case 1:
400 if (box -> param[1][0] != 90.0)
401 {
402 // Angle error: alpha must be = 90
403 return 0;
404 }
405 else if (box -> param[1][1] != 90.0 && box -> param[1][2] != 90.0)
406 {
407 // Angle error: beta or gamma must be = 90
408 return 0;
409 }
410 break;
411 case 4:
412 if (cell -> sp_group -> name[0] != 'R')
413 {
414 if (box -> param[1][0] != 90.0 || box -> param[1][1] != 90.0 || box -> param[1][2] != 120.0)
415 {
416 // Angle error: alpha and beta must be equal= 90, gamma must be = 120
417 return 0;
418 }
419 }
420 else
421 {
422 if (box -> param[1][0] != box -> param[1][1] || box -> param[1][0] != box -> param[1][2] || box -> param[1][1] != box -> param[1][2])
423 {
424 // Angle error: alpha, beta, gamma must all be equal
425 return 0;
426 }
427 else if (box -> param[0][0] != box -> param[0][2])
428 {
429 // Box error: a, b and c must all be equal
430 return 0;
431 }
432 }
433 break;
434 case 5:
435 if (box -> param[1][0] != 90.0 || box -> param[1][1] != 90.0 || box -> param[1][2] != 120.0)
436 {
437 // Angle error: alpha and beta must be = 90, gamma must be = 120
438 return 0;
439 }
440 break;
441 case 6:
442 if (box -> param[0][0] != box -> param[0][1] || box -> param[0][0] != box -> param[0][2] || box -> param[0][1] != box -> param[0][2])
443 {
444 // Box error: a, b, c not all equal
445 return 0;
446 }
447 break;
448 }
449 return 1;
450}
451
460double get_val_from_wyckoff (gchar * pos, gchar * wval)
461{
462 if (! strstr(wval, pos))
463 {
464 return 0.0;
465 }
466 else
467 {
468 if (! g_strcmp0(wval, pos))
469 {
470 g_free (tmp_pos);
471 tmp_pos = NULL;
472 return 1.0;
473 }
474 gchar * sym[4]={"-2", "2", "-", "+"};
475 double sval[4]={-2.0, 2.0, -1.0, 1.0};
476 gchar * ksym = NULL;
477 int i;
478 for (i=0; i<4; i++)
479 {
480 ksym = g_strdup_printf ("%s%s", sym[i], pos);
481 if (strstr(wval, ksym))
482 {
483 tmp_pos = g_strdup_printf ("%s", replace_markup (tmp_pos, ksym, NULL));
484 g_free (ksym);
485 ksym = NULL;
486 if (! strlen(tmp_pos))
487 {
488 g_free (tmp_pos);
489 tmp_pos = NULL;
490 }
491 return sval[i];
492 }
493 g_free (ksym);
494 ksym = NULL;
495 }
496 tmp_pos = g_strdup_printf ("%s", replace_markup (tmp_pos, pos, NULL));
497 if (! strlen(tmp_pos))
498 {
499 g_free (tmp_pos);
500 tmp_pos = NULL;
501 }
502 return 1.0;
503 }
504}
505
514void clean_this_proj (project * this_proj, gboolean newp)
515{
516 int i, j;
517 if (newp)
518 {
519 close_project(this_proj);
520 }
521 else
522 {
523 for (i=0; i<3; i++)
524 {
525 for (j=0; j<3; j++)
526 {
527 if (i < 2) this_proj -> cell.box[0].param[i][j] = 0.0;
528 this_proj -> cell.box[0].vect[i][j] = 0.0;
529 }
530 }
531 this_proj -> cell.ltype = 0;
532 this_proj -> cell.pbc = FALSE;
533 }
534}
535
544gboolean same_coords (float a, float b)
545{
546 int i;
547 for (i=0; i<10; i++) if (fabs(fabs(a-b) - i) < 0.0001) return TRUE;
548 return FALSE;
549}
550
560{
561 if (same_coords(u.x, v.x) && same_coords(u.y, v.y) && same_coords(u.z, v.z))
562 {
563 return TRUE;
564 }
565 return FALSE;
566}
567
577int pos_not_saved (vec3_t * all_pos, int num_pos, vec3_t pos)
578{
579 int i;
580 for (i=0; i<num_pos; i++)
581 {
582 if (are_equal_vectors(all_pos[i], pos)) return -(i+1);
583 }
584 return 1;
585}
586
595{
596 space_group * new_spg = g_malloc0(sizeof*new_spg);
597 new_spg -> id = spg -> id;
598 new_spg -> hms = g_strdup_printf ("%s", spg -> hms);
599 new_spg -> bravais = g_strdup_printf ("%s", spg -> bravais);
600 if (spg -> settings[spg -> sid].origin)
601 {
602 new_spg -> setting = g_strdup_printf ("%s:%d", spg -> settings[spg -> sid].name, spg -> settings[spg -> sid].origin);
603 }
604 else
605 {
606 new_spg -> setting = g_strdup_printf ("%s", spg -> settings[spg -> sid].name);
607 }
608 return new_spg;
609}
610
620{
621 crystal_data * cryst = g_malloc0(sizeof*cryst);
622 cryst -> objects = objects;
623 cryst -> spec = species;
624 cryst -> at_by_object = allocint(cryst -> objects);
625 cryst -> pos_by_object = allocint(cryst -> objects);
626 cryst -> occupancy = allocdouble(cryst -> objects);
627 cryst -> sites = g_malloc0(cryst -> objects*sizeof*cryst -> sites);
628 cryst -> insert = g_malloc0(cryst -> objects*sizeof*cryst -> insert);
629 cryst -> position = g_malloc0(cryst -> objects*sizeof*cryst -> position);
630 cryst -> coord = g_malloc0(cryst -> objects*sizeof*cryst -> coord);
631 cryst -> lot = g_malloc0(cryst -> objects*sizeof*cryst -> lot);
632 cryst -> at_type = g_malloc0(cryst -> objects*sizeof*cryst -> at_type);
633 cryst -> z = allocdouble (species);
634 cryst -> nsps = allocint (species);
635 cryst -> holes = allocbool (cryst -> objects);
636 return cryst;
637}
638
647{
648 if (cryst -> at_by_object) g_free (cryst -> at_by_object);
649 if (cryst -> pos_by_object) g_free (cryst -> pos_by_object);
650 if (cryst -> occupancy) g_free (cryst -> occupancy);
651 if (cryst -> sites) g_free (cryst -> sites);
652 if (cryst -> insert) g_free (cryst -> insert);
653 if (cryst -> position) g_free (cryst -> position);
654 if (cryst -> coord) g_free (cryst -> coord);
655 if (cryst -> lot) g_free (cryst -> lot);
656 if (cryst -> at_type) g_free (cryst -> at_type);
657 if (cryst -> z) g_free (cryst -> z);
658 if (cryst -> nsps) g_free (cryst -> nsps);
659 if (cryst -> holes) g_free (cryst -> holes);
660 g_free (cryst);
661 return NULL;
662}
663
673gboolean pos_not_taken (int pos, int dim, int * tab)
674{
675 int i;
676 for (i=0; i<dim; i++) if (tab[i] == pos) return FALSE;
677 return TRUE;
678}
679
694gboolean adjust_object_occupancy (crystal_data * cryst, int occupying, int tot_cell)
695{
696 int h, i, j, k, l, m, n, o, p, q, r, s, t;
697 double v;
698 double prob;
699 gboolean * taken_pos = NULL;
700 gboolean ** holes_pos = NULL;
701 int * pos_order = NULL;
702 int * site_pos = NULL;
703 int num_to_save;
704 int pos_bs, num_bs, site_bs;
705 gboolean pick_it;
706 clock_t CPU_time;
707 gboolean low_occ = FALSE;
708 gboolean with_holes = FALSE;
709 gboolean occ_sym = (occupying == 0 || occupying > 2) ? TRUE : FALSE;
710
711 // position ordering must be used to ensure proper overlapping with holes
712 pos_order = allocint (cryst -> objects);
713 i = j = 0;
714 for (k=0; k<cryst -> objects; k++)
715 {
716 if (cryst -> holes[k])
717 {
718 pos_order[i] = k;
719 j = max (j, cryst -> pos_by_object[i]);
720 i ++;
721 }
722 }
723 if (i)
724 {
725 with_holes = TRUE;
726 holes_pos = allocdbool (cryst -> objects, j);
727 }
728 for (j=0; j<cryst -> objects; j++)
729 {
730 if (! cryst -> holes[j])
731 {
732 pos_order[i] = j;
733 i ++;
734 }
735 }
736
737 for (h=0; h<cryst -> objects; h++)
738 {
739 i = pos_order[h];
740#ifdef DEBUG
741 g_debug ("i= %d, occ[%d]= %f, pbo[%d]= %d", i+1, i+1, cryst -> occupancy[i], i+1, cryst -> pos_by_object[i]);
742#endif
743 if (cryst -> sites[i][0] > 0 && cryst -> occupancy[i]*cryst -> pos_by_object[i] < 1.0 && ! cryst -> holes[i]) low_occ = TRUE;
744
745 if (cryst -> sites[i][0] > 0 && cryst -> occupancy[i] < 1.0 && cryst -> pos_by_object[i] > 1)
746 {
747 v = 0.0;
748 pos_bs = cryst -> pos_by_object[i];
749 site_bs = (cryst -> holes[i]) ? 1 : cryst -> sites[i][0];
750 num_bs = cryst -> sites[i][0];
751 taken_pos = allocbool (pos_bs);
752#ifdef DEBUG
753 g_debug ("i= %d, site[%d][0]= %d, pos_bs= %d, num_bs= %d", i+1, i+1, cryst -> sites[i][0], pos_bs, num_bs);
754#endif
755 for (j=0; j<cryst -> sites[i][0]; j++)
756 {
757 k = cryst -> sites[i][j+1];
758 v += cryst -> occupancy[k];
759 }
760 l = 0;
761 if (with_holes)
762 {
763 for (j=0; j<site_bs; j++)
764 {
765 if (holes_pos[i][j]) l ++;
766 }
767 }
768 for (j=0; j<site_bs; j++)
769 {
770 k = cryst -> sites[i][j+1];
771#ifdef DEBUG
772 g_debug ("\tj= %d, k= %d, sites[%d][0]= %d, occ[%d]= %f, pos_by_objects[%d]= %d",
773 j+1, k+1, k+1, cryst -> sites[k][0], k+1, cryst -> occupancy[k], k+1, cryst -> pos_by_object[k]);
774#endif
775 if (cryst -> sites[k][0] > -1)
776 {
777 num_to_save = round (pos_bs*cryst -> occupancy[k]);
778 l += num_to_save;
779#ifdef DEBUG
780 g_debug ("\tnum_to_save= %d, l= %d", num_to_save, l);
781#endif
782 if (j == num_bs-1)
783 {
784 if ((v == 1.0 && l != pos_bs) || l > pos_bs) num_to_save += (pos_bs-l);
785 }
786 site_pos = allocint (num_to_save);
787 m = 0;
788 while (m < num_to_save)
789 {
790 pick_it = TRUE;
791 if (occupying < 3)
792 {
793 CPU_time = clock();
794 n = (CPU_time - (k+17)*pos_bs) + (3*cryst -> at_by_object[i]);
795 prob = random3_(& n);
796 p = round (prob * (pos_bs-1));
797 if (with_holes)
798 {
799 pick_it = (taken_pos[p] || holes_pos[i][p]) ? FALSE : TRUE;
800 }
801 else
802 {
803 pick_it = ! taken_pos[p];
804 }
805 }
806 else if (occupying == 3)
807 {
808 p = 0;
809 if (with_holes)
810 {
811 while (taken_pos[p] || holes_pos[i][p]) p ++;
812 }
813 else
814 {
815 while (taken_pos[p]) p ++;
816 }
817 }
818 else
819 {
820#ifdef DEBUG
821 g_debug ("\t\tp= %d, m= %d, sites[i][0]= %d", p, m, cryst -> sites[k][0]);
822#endif
823 p = j + m*cryst -> sites[k][0];
824 if (p > cryst -> pos_by_object[k]-1)
825 {
826 p -= (cryst -> pos_by_object[k]-1);
827 }
828#ifdef DEBUG
829 g_debug ("\t\tp= %d", p);
830#endif
831 for (n=0; n<m; n++)
832 {
833 if (site_pos[n] == p)
834 {
835 n = p ++;
836 if (n == cryst -> pos_by_object[k]) n = 0;
837 pick_it = FALSE;
838 while (! pick_it)
839 {
840 pick_it = TRUE;
841 for (o=0; o<m; o++)
842 {
843 if (site_pos[o] == n)
844 {
845 pick_it = FALSE;
846 n ++;
847 }
848 }
849 }
850 p = n;
851 break;
852 }
853 }
854 }
855 if (pick_it)
856 {
857 site_pos[m] = p;
858 taken_pos[p] = TRUE;
859 m ++;
860 }
861 }
862#ifdef DEBUG
863 sort (num_to_save, site_pos);
864 for (m=0; m<num_to_save; m++)
865 {
866 g_debug ("\t\tm= %d, site_pos[%d]= %d", m+1, m+1, site_pos[m]);
867 }
868#endif
869 for (m=0; m<num_to_save; m++)
870 {
871 n = site_pos[m];
872 cryst -> coord[k][m] = cryst -> coord[k][n];
873 if (occ_sym && tot_cell > 1)
874 {
875 for (o=1; o<tot_cell; o++)
876 {
877 p = k+o*(cryst -> objects/tot_cell);
878 cryst -> coord[p][m] = cryst -> coord[p][n];
879 }
880 }
881 }
882
883 cryst -> pos_by_object[k] = num_to_save;
884 cryst -> sites[k][0] = -1;
885 if (occ_sym && tot_cell > 1)
886 {
887 for (o=1; o<tot_cell; o++)
888 {
889 p = k+o*(cryst -> objects/tot_cell);
890 cryst -> pos_by_object[p] = num_to_save;
891 cryst -> sites[p][0] = -1;
892 }
893 }
894 if (cryst -> holes[i])
895 {
896 for (o=0; o<num_bs; o++)
897 {
898 p = cryst -> sites[i][o+1];
899 for (q=0; q<num_to_save; q++)
900 {
901 r = site_pos[q];
902 holes_pos[p][r] = TRUE;
903 if (occ_sym && tot_cell > 1)
904 {
905 for (s=1; s<tot_cell; s++)
906 {
907 t = p+s*(cryst -> objects/tot_cell);
908 holes_pos[t][r] = TRUE;
909 }
910 }
911 }
912 }
913 }
914 g_free (site_pos);
915 }
916 }
917 g_free (taken_pos);
918 }
919 }
920 if (holes_pos) g_free (holes_pos);
921 return low_occ;
922}
923
936int build_crystal (gboolean visible, project * this_proj, gboolean to_wrap, gboolean show_clones, cell_info * cell, GtkWidget * widg)
937{
938 int h, i, j, k, l, m, n, o, p, q;
939 int build_res = 1;
940 space_group * sp_group = cell -> sp_group;
941 box_info * box = & cell -> box[0];
942 gchar * str;
943 mat4_t ** wyckpos = g_malloc0 (sp_group -> numw*sizeof*wyckpos);
944 double spgpos[3][4];
945 for (i=0; i<1; i++)//sp_group -> numw; i++)
946 {
947 wyckpos[i] = g_malloc0 (sp_group -> wyckoff[i].multi*sizeof*wyckpos[i]);
948 for (j=0; j<sp_group -> wyckoff[i].multi; j++)
949 {
950 for (k=0; k<3; k++)
951 {
952 tmp_pos = g_strdup_printf ("%s", sp_group -> wyckoff[i].pos[j][k]);
953 for (l=0; l<3; l++)
954 {
955 spgpos[k][l] = get_val_from_wyckoff (vect_comp[l], sp_group -> wyckoff[i].pos[j][k]);
956 }
957 if (tmp_pos)
958 {
959 spgpos[k][3] = get_value_from_pos (tmp_pos);
960 g_free (tmp_pos);
961 tmp_pos = NULL;
962 }
963 else
964 {
965 spgpos[k][3] = 0.0;
966 }
967 }
968
969 wyckpos[i][j] = mat4 (spgpos[0][0], spgpos[0][1], spgpos[0][2], spgpos[0][3],
970 spgpos[1][0], spgpos[1][1], spgpos[1][2], spgpos[1][3],
971 spgpos[2][0], spgpos[2][1], spgpos[2][2], spgpos[2][3],
972 0.0, 0.0, 0.0, 1.0);
973 wyckpos[i][j] = m43_mul(sp_group -> wyck_origin, wyckpos[i][j]);
974#ifdef DEBUG
975// g_debug ("w_id= %d, w_mul= %d", i+1, j+1);
976// m4_print (wyckpos[i][j]);
977#endif
978 }
979 }
980 double copos[3];
981 int npoints;
982 vec3_t * points;
983 h = sp_group -> sid;
984 if (sp_group -> settings[h].nump)
985 {
986 points = g_malloc0(sp_group -> settings[h].nump*sizeof*points);
987 for (i=0; i<sp_group -> settings[h].nump; i++)
988 {
989 for (j=0; j<3; j++)
990 {
991 tmp_pos = g_strdup_printf ("%s", sp_group -> settings[h].points[i][j]);
992 copos[j] = get_value_from_pos (tmp_pos);
993 g_free (tmp_pos);
994 tmp_pos = NULL;
995 }
996 points[i] = vec3(copos[0], copos[1], copos[2]);
997 //m4_mul_coord (sp_group -> coord_origin, vec3(copos[0], copos[1], copos[2]));
998#ifdef DEBUG
999// g_debug ("point=%d, p.x= %f, p.y= %f, p.z= %f", i+1, points[i].x, points[i].y ,points[i].z);
1000#endif
1001 }
1002 npoints = sp_group -> settings[h].nump;
1003 }
1004 else
1005 {
1006 points = g_malloc0(1*sizeof*points);
1007 points[0] = vec3(0.0, 0.0, 0.0);
1008 npoints = 1;
1009 }
1010
1011 vec3_t pos;
1012 atomic_object * object = NULL;
1013 gboolean done;
1014 crystal_data * cdata = NULL;
1015 int occupying;
1016 double amin = box -> param[0][0];
1017 for (i=1; i<3; i++) amin = min(amin, box -> param[0][i]);;
1018 if (! visible)
1019 {
1020 tint point;
1021 point.a = this_proj -> id;
1022 point.b = point.c = 0;
1023 this_proj -> modelgl = g_malloc0(sizeof*this_proj -> modelgl);
1024 prepare_atom_edition (& point, FALSE);
1025 this_proj -> modelgl -> search_widg[7] = allocate_atom_search (this_proj -> id, INSERT, 7, this_reader -> natomes);
1026 gboolean do_obj;
1027 for (i=0; i<this_reader -> natomes; i++)
1028 {
1029 do_obj = FALSE;
1030 for (j=0; j<this_reader -> atom_unlabelled; j++)
1031 {
1032 if (this_reader -> u_atom_list[j] == i)
1033 {
1034 do_obj = TRUE;
1035 break;
1036 }
1037 }
1038 if (do_obj)
1039 {
1040 if (! object)
1041 {
1042 this_proj -> modelgl -> atom_win -> to_be_inserted[2] = duplicate_atomic_object (get_atomic_object_by_origin (cif_object, this_reader -> object_list[j], 0));
1043 object = this_proj -> modelgl -> atom_win -> to_be_inserted[2];
1044 }
1045 else
1046 {
1047 object -> next = duplicate_atomic_object (get_atomic_object_by_origin (cif_object, this_reader -> object_list[j], 0));
1048 }
1049 }
1050 else
1051 {
1052 j = this_reader -> lot[i];
1053 to_insert_in_project ((int)this_reader -> z[j], -1, this_proj, this_proj -> modelgl -> search_widg[7], FALSE);
1054 }
1055 this_proj -> modelgl -> search_widg[7] -> todo[i] = 1;
1056 if (! object)
1057 {
1058 object = this_proj -> modelgl -> atom_win -> to_be_inserted[2];
1059 }
1060 else
1061 {
1062 object = object -> next;
1063 }
1064 object -> occ = this_reader -> occupancy[i];
1065 for (j=0; j<3; j++) object -> baryc[j] = this_reader -> coord[i][j];
1066 }
1067 occupying = 0;
1068 }
1069 else
1070 {
1071 occupying = this_proj -> modelgl -> builder_win -> occupancy;
1072 }
1073 for (h=0; h<2; h++)
1074 {
1075 object = this_proj -> modelgl -> atom_win -> to_be_inserted[2];
1076 i = j = k = 0;
1077 while (object)
1078 {
1079 l = object -> id;
1080 if (this_proj -> modelgl -> search_widg[7] -> todo[l])
1081 {
1082 if (h)
1083 {
1084 for (m=0; m<object -> species; m++)
1085 {
1086 done = FALSE;
1087 for (l=0; l<k; l++)
1088 {
1089 if (object -> old_z[m] == cdata -> z[l])
1090 {
1091 done = TRUE;
1092 break;
1093 }
1094 }
1095 if (! done && object -> old_z[m] > 0.0)
1096 {
1097 cdata -> z[k] = object -> old_z[m];
1098 k ++;
1099 }
1100 if (object -> old_z[m] == 0.0)
1101 {
1102 cdata -> holes[i] = TRUE;
1103 cdata -> with_holes = TRUE;
1104 }
1105 }
1106 n = sp_group -> wyckoff[0].multi*npoints;
1107 cdata -> at_type[i] = allocint(n);
1108 cdata -> coord[i] = g_malloc0(n*sizeof*cdata -> coord[i]);
1109 cdata -> insert[i] = m4_mul_coord (sp_group -> coord_origin, vec3(object -> baryc[0], object -> baryc[1], object -> baryc[2]));
1110#ifdef DEBUG
1111 // g_debug ("at_orig= %d, pos.x= %f, pos.y= %f, pos.z= %f", i+1, object -> baryc[0], object -> baryc[1], object -> baryc[2]);
1112 // g_debug ("at_calc= %d, pos.x= %f, pos.y= %f, pos.z= %f", i+1, cdata -> insert[i].x, cdata -> insert[i].y, cdata -> insert[i].z);
1113#endif
1114 n = 0;
1115 for (o=0; o<npoints; o++)
1116 {
1117 for (p=0; p<sp_group -> wyckoff[0].multi; p++)
1118 {
1119 pos = v3_add (m4_mul_coord (wyckpos[0][p], cdata -> insert[i]), points[o]);
1120 q = pos_not_saved (cdata -> coord[i], n, pos);
1121 if (q > 0)
1122 {
1123 cdata -> coord[i][n].x = pos.x;
1124 cdata -> coord[i][n].y = pos.y;
1125 cdata -> coord[i][n].z = pos.z;
1126#ifdef DEBUG
1127 // g_debug (" c.x= %f, c.y= %f, c.z= %f", cdata -> coord[i][n].x, cdata -> coord[i][n].y, cdata -> coord[i][n].z);
1128#endif
1129 cdata -> at_type[i][n] = 1;
1130 n ++;
1131 }
1132 else if (q < 0)
1133 {
1134 cdata -> at_type[i][-(q+1)] ++;
1135 }
1136 }
1137 }
1138 cdata -> pos_by_object[i] = n;
1139 cdata -> occupancy[i] = object -> occ;
1140 if (! cdata -> holes[i]) cdata -> lot[i] = allocint(object -> atoms);
1141 cdata -> position[i] = g_malloc0(object -> atoms*sizeof*cdata -> position[i]);
1142 for (l=0; l<object -> atoms; l++)
1143 {
1144 n = object -> at_list[l].sp;
1145 cdata -> position[i][l].x = object -> at_list[l].x;
1146 cdata -> position[i][l].y = object -> at_list[l].y;
1147 cdata -> position[i][l].z = object -> at_list[l].z;
1148 if (! cdata -> holes[i])
1149 {
1150 for (o=0; o<k; o++)
1151 {
1152 if (cdata -> z[o] == object -> old_z[n])
1153 {
1154 cdata -> lot[i][l] = o;
1155 break;
1156 }
1157 }
1158 }
1159 }
1160 cdata -> at_by_object[i] = object -> atoms;
1161 i ++;
1162 }
1163 else
1164 {
1165 if (object -> dim > amin)
1166 {
1167 str = g_strdup_printf ("%s size (%f Ang.) is bigger than the min(<b><i>a,b,c</i></b>)\n"
1168 "If you build the crystal the final structure is likely to be crowded !\n"
1169 "Continue anyway ?", object -> name, object -> dim);
1170 build_res = 2;
1171 if (! ask_yes_no("This object might be too big !" , str, GTK_MESSAGE_WARNING, widg))
1172 {
1173 g_free (str);
1174 if (points) g_free (points);
1175 if (wyckpos) g_free (wyckpos);
1176 if (cdata) cdata = free_crystal_data (cdata);
1177 if (! visible)
1178 {
1179 this_proj -> modelgl -> search_widg[7] = free_this_search_data (this_proj -> modelgl -> search_widg[7]);
1180 g_free (this_proj -> modelgl);
1181 this_proj -> modelgl = NULL;
1182 active_glwin = NULL;
1183 }
1184 return 0;
1185 }
1186 g_free (str);
1187 }
1188 i ++;
1189 j += object -> species;
1190 k += object -> atoms;
1191 }
1192 }
1193 object = object -> next;
1194 }
1195 if (! h)
1196 {
1197 if (k)
1198 {
1199 cdata = allocate_crystal_data (i, j);
1200 cdata -> overlapping = (visible) ? this_proj -> modelgl -> builder_win -> overlapping : FALSE;
1201 }
1202 else
1203 {
1204 if (points) g_free (points);
1205 if (wyckpos) g_free (wyckpos);
1206 if (cdata) cdata = free_crystal_data (cdata);
1207 if (! visible)
1208 {
1209 this_proj -> modelgl -> search_widg[7] = free_this_search_data (this_proj -> modelgl -> search_widg[7]);
1210 g_free (this_proj -> modelgl);
1211 this_proj -> modelgl = NULL;
1212 active_glwin = NULL;
1213 }
1214 return 0;
1215 }
1216 }
1217 }
1218
1219 if (points) g_free (points);
1220 if (wyckpos) g_free (wyckpos);
1221
1222 cdata -> spec = k;
1223
1224 double u, v;
1225 m = 0;
1226 for (i=0; i<cdata -> objects; i++)
1227 {
1228 m += (cdata -> holes[i]) ? 1 : 0;
1229 u = v = 0.0;
1230 for (j=0; j<2; j++)
1231 {
1232 k = 1;
1233 if (! cdata -> overlapping || cdata -> holes[i])
1234 {
1235 u = cdata -> occupancy[i];
1236 }
1237 else
1238 {
1239 v = cdata -> occupancy[i];
1240 }
1241 if (u+v > 1.0 || u+v < 0.0)
1242 {
1243 if (cdata) cdata = free_crystal_data (cdata);
1244 show_warning ("Impossible to build crystal: check occupancy !", widg);
1245 return 0;
1246 }
1247 else if (cdata -> overlapping && ! cdata -> with_holes)
1248 {
1249 if (j) cdata -> sites[i][k] = i;
1250 }
1251 else
1252 {
1253 for (l=0; l<cdata -> objects; l++)
1254 {
1255 if (l != i)
1256 {
1257 if (cdata -> insert[i].x == cdata -> insert[l].x
1258 && cdata -> insert[i].y == cdata -> insert[l].y
1259 && cdata -> insert[i].z == cdata -> insert[l].z)
1260 {
1261 if (j)
1262 {
1263 if (! cdata -> overlapping || cdata -> holes[i])
1264 {
1265 k ++;
1266 cdata -> sites[i][k] = l;
1267 }
1268 }
1269 else
1270 {
1271 if (! cdata -> overlapping || cdata -> holes[i]) k ++;
1272 if (! cdata -> overlapping || cdata -> holes[l])
1273 {
1274 u += cdata -> occupancy[l];
1275 }
1276 else
1277 {
1278 v = max(v, cdata -> occupancy[l]);
1279 }
1280 if (u+v > 1.00001)
1281 {
1282 show_warning ("Impossible to build crystal: site total occupancy > 1.0", widg);
1283 if (cdata) cdata = free_crystal_data (cdata);
1284 return 0;
1285 }
1286 }
1287 }
1288 }
1289 }
1290 }
1291 if (! j)
1292 {
1293 cdata -> sites[i] = allocint (k+1);
1294 cdata -> sites[i][0] = k;
1295 cdata -> sites[i][1] = i;
1296 if (k > 1) cdata -> shared_sites = TRUE;
1297 }
1298 }
1299 }
1300#ifdef DEBUG
1301 /*for (i=0; i<cdata -> objects; i++)
1302 {
1303 g_debug ("i= %d, site[%d]= %d", i+1, i+1, cdata -> sites[i][0]);
1304 for (j=0; j<cdata -> sites[i][0]; j++)
1305 {
1306 g_debug ("\t j= %d, co-site[%d][%d]= %d", j+1, i+1, j+1, cdata -> sites[i][j+1]+1);
1307 }
1308 }*/
1309#endif // DEBUG
1310
1311 if (m == cdata -> objects)
1312 {
1313 if (cdata) cdata = free_crystal_data (cdata);
1314 show_warning ("Impossible to build crystal: empty site(s) only !", widg);
1315 return 0;
1316 }
1317 gboolean new_proj = (this_proj -> natomes && visible) ? TRUE : FALSE;
1318
1319 if (new_proj)
1320 {
1321 init_project(TRUE);
1322 }
1323 else if (visible)
1324 {
1325 active_project_changed (this_proj -> id);
1326 }
1327 for (i=0; i<3; i++)
1328 {
1329 for (j=0; j<3; j++)
1330 {
1331 if (i < 2)
1332 {
1333 active_box -> param[i][j] = box -> param[i][j];
1334 if (! i) active_box -> param[i][j] *= cell -> cextra[j];
1335 }
1336 active_box -> vect[i][j] *= cell -> cextra[i];
1337 }
1338 }
1340 active_cell -> ltype = 1;
1341 active_cell -> pbc = TRUE;
1342 int tot_cell = 1;
1343 for (i=0; i<3; i++)
1344 {
1345 tot_cell *= cell -> cextra[i];
1346 }
1347 vec3_t vx, vy, vz, shift;
1348 h = 0;
1349 i = (occupying == 2) ? 0 : 1;
1350 j = (occupying == 2) ? 1 : tot_cell;
1351 crystal_data * cryst = allocate_crystal_data (j*cdata -> objects, cdata -> spec);
1352 g_free (cryst -> z);
1353 cryst -> z = duplicate_double (cdata -> spec, cdata -> z);
1354 cryst -> shared_sites = cdata -> shared_sites;
1355 cryst -> overlapping = cdata -> overlapping;
1356 cryst -> with_holes = cdata -> with_holes;
1357 if (occupying == 2)
1358 {
1359 for (k=0; k<cdata -> objects; k++)
1360 {
1361 cryst -> pos_by_object[k] = tot_cell*cdata -> pos_by_object[k];
1362 cryst -> at_by_object[k] = cdata -> at_by_object[k];
1363 cryst -> at_type[k] = duplicate_int (sp_group -> wyckoff[0].multi*npoints, cdata -> at_type[k]);
1364 cryst -> holes = duplicate_bool (cdata -> objects, cdata -> holes);
1365 if (! cdata -> holes[k]) cryst -> lot[k] = duplicate_int (cdata -> at_by_object[k], cdata -> lot[k]);
1366 cryst -> occupancy[k] = cdata -> occupancy[k];
1367 cryst -> sites[k] = duplicate_int (cdata -> sites[k][0]+1, cdata -> sites[k]);
1368 cryst -> position[k] = g_malloc0 (cdata -> at_by_object[k]*sizeof*cryst -> position[k]);
1369 for (l=0; l<cdata -> at_by_object[k]; l++) cryst -> position[k][l] = cdata -> position[k][l];
1370 cryst -> coord[k] = g_malloc0(cryst -> pos_by_object[k]*sizeof*cryst -> coord[k]);
1371 }
1372 }
1373
1374 for (k=0; k<cell -> cextra[0]; k++)
1375 {
1376 vx = v3_muls(vec3(box -> vect[0][0], box -> vect[0][1], box -> vect[0][2]), k);
1377 for (l=0; l<cell -> cextra[1]; l++)
1378 {
1379 vy = v3_muls(vec3(box -> vect[1][0], box -> vect[1][1], box -> vect[1][2]), l);
1380 for (m=0; m<cell -> cextra[2]; m++)
1381 {
1382 vz = v3_muls(vec3(box -> vect[2][0], box -> vect[2][1], box -> vect[2][2]), m);
1383 shift = v3_add (vx, v3_add(vy, vz));
1384 for (n=0; n<cdata -> objects; n++)
1385 {
1386 if (occupying != 2)
1387 {
1388 cryst -> coord[n+h] = g_malloc0(cdata -> pos_by_object[n]*sizeof*cryst -> coord[n+h]);
1389 cryst -> pos_by_object[n+h] = cdata -> pos_by_object[n];
1390 cryst -> at_by_object[n+h] = cdata -> at_by_object[n];
1391 cryst -> holes[n+h] = cdata -> holes[n];
1392 cryst -> at_type[n+h] = duplicate_int (sp_group -> wyckoff[0].multi*npoints, cdata -> at_type[n]);
1393 if (! cdata -> holes[n]) cryst -> lot[n+h] = duplicate_int (cdata -> at_by_object[n], cdata -> lot[n]);
1394 cryst -> occupancy[n+h] = cdata -> occupancy[n];
1395 cryst -> sites[n+h] = duplicate_int (cdata -> sites[n][0]+1, cdata -> sites[n]);
1396 for (o=0; o<cryst -> sites[n+h][0]; o++) cryst -> sites[n+h][o+1] += h;
1397 cryst -> position[n+h] = g_malloc0 (cdata -> at_by_object[n]*sizeof*cryst -> position[n+h]);
1398 for (o=0; o<cdata -> at_by_object[n]; o++) cryst -> position[n+h][o] = cdata -> position[n][o];
1399 }
1400 o = cdata -> pos_by_object[n];
1401 for (p=0; p<o; p++)
1402 {
1403 cryst -> coord[n+i*h][p+(!i)*h*o] = v3_add(m4_mul_coord (box -> frac_to_cart, cdata -> coord[n][p]), shift);
1404 }
1405 }
1406 h += (occupying != 2) ? cdata -> objects : 1;
1407 }
1408 }
1409 }
1410 cdata = free_crystal_data (cdata);
1411 gboolean low_occ = adjust_object_occupancy (cryst, occupying, tot_cell);
1412 atom at, bt;
1413 distance dist;
1414 gboolean dist_chk = TRUE;
1415
1416 if (! cryst -> overlapping)
1417 {
1418 for (i=0; i<cryst -> objects; i++)
1419 {
1420 if (! cryst -> holes[i])
1421 {
1422 for (j=0; j<cryst -> pos_by_object[i]; j++)
1423 {
1424 at.x = cryst -> coord[i][j].x;
1425 at.y = cryst -> coord[i][j].y;
1426 at.z = cryst -> coord[i][j].z;
1427 for (k=i; k<cryst -> objects; k++)
1428 {
1429 if (! cryst -> holes[k])
1430 {
1431 if (k != i || j < cryst -> pos_by_object[i]-1)
1432 {
1433 l = (k == i) ? j+1 : 0;
1434 for (m=l; m<cryst -> pos_by_object[k]; m++)
1435 {
1436 bt.x = cryst -> coord[k][m].x;
1437 bt.y = cryst -> coord[k][m].y;
1438 bt.z = cryst -> coord[k][m].z;
1439 dist = distance_3d (active_cell, 0, & at, & bt);
1440 if (dist.length < 0.5)
1441 {
1442 // g_print ("i= %d, j= %d, k= %d, m= %d, d= %f\n", i, j, k, m, dist.length);
1443 if (dist_chk)
1444 {
1445 build_res = 3;
1446 if (ask_yes_no ("Inter-object distance(s) < 0.5 Ang. !",
1447 "Inter-object distance(s) &lt; 0.5 Ang. !\n\n\t\tContinue and leave a single object at each position ?", GTK_MESSAGE_WARNING, widg))
1448 {
1449 dist_chk = FALSE;
1450 }
1451 else
1452 {
1453 clean_this_proj (active_project, new_proj);
1454 cryst = free_crystal_data (cryst);
1455 return 0;
1456 }
1457 }
1458 if (! dist_chk)
1459 {
1460 if (dist.length < 0.1)
1461 {
1462 cryst -> at_type[i][j] += cryst -> at_type[k][m];
1463 for (n=m; n<cryst -> pos_by_object[k]-1; n++)
1464 {
1465 cryst -> coord[k][n].x = cryst -> coord[k][n+1].x;
1466 cryst -> coord[k][n].y = cryst -> coord[k][n+1].y;
1467 cryst -> coord[k][n].z = cryst -> coord[k][n+1].z;
1468 cryst -> at_type[k][n] += cryst -> at_type[k][n+1];
1469 }
1470 cryst -> pos_by_object[k] --;
1471 m --;
1472 }
1473 }
1474 }
1475 }
1476 }
1477 }
1478 }
1479 }
1480 }
1481 }
1482 }
1483
1484 int tot_new_at = 0;
1485 for (i=0; i<cryst -> objects; i++)
1486 {
1487 if (! cryst -> holes[i]) tot_new_at += cryst -> pos_by_object[i]*cryst -> at_by_object[i];
1488 }
1489 int * tot_new_lot = allocint(tot_new_at);
1490 vec3_t * ncc = g_malloc0(tot_new_at*sizeof*ncc);
1491 i = 0;
1492 for (j=0; j<cryst -> objects; j++)
1493 {
1494 if (! cryst -> holes[j])
1495 {
1496 for (k=0; k<cryst -> at_by_object[j]; k++)
1497 {
1498 for (l=0; l<cryst -> pos_by_object[j]; l++)
1499 {
1500 ncc[i] = v3_add (cryst -> coord[j][l], cryst -> position[j][k]);
1501 m = tot_new_lot[i] = cryst -> lot[j][k];
1502 cryst -> nsps[m] ++;
1503 i ++;
1504 }
1505 }
1506 }
1507 }
1508 active_project -> steps = 1;
1509 active_project -> natomes = tot_new_at;
1510 if (low_occ)
1511 {
1512 i = 0;
1513 for (j=0; j<cryst -> spec; j++)
1514 {
1515 if (cryst -> nsps[j]) i ++;
1516 }
1517 active_project -> nspec = i;
1518 }
1519 else
1520 {
1521 active_project -> nspec = cryst -> spec;
1522 }
1523#ifdef DEBUG
1524 g_debug ("CRYSTAL:: atoms= %d, species= %d", active_project -> natomes, active_project -> nspec);
1525#endif
1528 k = l = 0;
1529 for (i=0; i<cryst -> spec; i++)
1530 {
1531 if (! cryst -> nsps[i])
1532 {
1533 if (! low_occ)
1534 {
1535 if (ncc) g_free (ncc);
1536 if (tot_new_lot) g_free (tot_new_lot);
1537#ifdef DEBUG
1538 g_debug ("CRYSTAL:: spec= %d, label= %s, nsps= %d", i+1, periodic_table_info[j].lab, 0);
1539#endif
1540 return 0;
1541 }
1542 }
1543 else
1544 {
1545 j = (int)cryst -> z[i];
1546 active_chem -> label[k] = g_strdup_printf ("%s", periodic_table_info[j].lab);
1547 active_chem -> element[k] = g_strdup_printf ("%s", periodic_table_info[j].name);
1548 active_chem -> nsps[k] = cryst -> nsps[i];
1549 active_chem -> chem_prop[CHEM_Z][k] = cryst -> z[i];
1550 active_chem -> chem_prop[CHEM_M][k] = set_mass_ (& j);
1551 active_chem -> chem_prop[CHEM_R][k] = set_radius_ (& j, & l);
1552 active_chem -> chem_prop[CHEM_N][k] = set_neutron_ (& j);
1553 active_chem -> chem_prop[CHEM_X][k] = active_chem -> chem_prop[CHEM_Z][k];
1554#ifdef DEBUG
1555 g_debug ("CRYSTAL:: spec= %d, label= %s, nsps= %d", k+1, active_chem -> label[k], active_chem -> nsps[k]);
1556#endif
1557 for (m=0; m<tot_new_at;m++)
1558 {
1559 if (tot_new_lot[m] == i) tot_new_lot[m] = k;
1560 }
1561 k ++;
1562 }
1563 }
1564 cryst = free_crystal_data (cryst);
1565 copos[0] = copos[1] = copos[2] = 0.0;
1566 if (visible && ! new_proj)
1567 {
1568 for (i=0; i<3; i++)
1569 {
1570 for (j=0; j<3; j++) copos[i] -= active_box -> vect[j][i]/2.0;
1571 }
1572 }
1573 for (i=0; i<tot_new_at; i++)
1574 {
1575 active_project -> atoms[0][i].id = i;
1576 j = tot_new_lot[i];
1577 active_project -> atoms[0][i].sp = j;
1578 active_project -> atoms[0][i].x = ncc[i].x + copos[0];
1579 active_project -> atoms[0][i].y = ncc[i].y + copos[1];
1580 active_project -> atoms[0][i].z = ncc[i].z + copos[2];
1581 active_project -> atoms[0][i].show[0] = TRUE;
1582 active_project -> atoms[0][i].show[1] = TRUE;
1583 active_project -> atoms[0][i].label[0] = FALSE;
1584 active_project -> atoms[0][i].label[1] = FALSE;
1585 active_project -> atoms[0][i].pick[0] = FALSE;
1586 active_project -> atoms[0][i].cloned = FALSE;
1587#ifdef DEBUG
1588 // g_debug ("sp= %d, %s %f %f %f", j+1, active_chem -> label[j], ncc[i].x, ncc[i].y, ncc[i].z);
1589#endif
1590 }
1591 if (ncc) g_free (ncc);
1592 if (tot_new_lot) g_free (tot_new_lot);
1593
1594 active_cell -> has_a_box = TRUE;
1595 active_cell -> crystal = TRUE;
1596
1597 if (visible)
1598 {
1599 for (i=0; i<3; i=i+2) active_project -> runok[i] = TRUE;
1600 active_project -> runok[BD] = TRUE;
1601 active_project -> runok[RI] = TRUE;
1602 active_project -> runok[CH] = TRUE;
1603 active_project -> runok[SP] = TRUE;
1605 if (new_proj)
1606 {
1608 apply_project (TRUE);
1609 }
1610 else
1611 {
1612 active_project -> run = TRUE;
1613 active_image -> style = (active_project -> natomes <= 1000) ? BALL_AND_STICK : DEFAULT_STYLE;
1616 initcwidgets ();
1622#ifdef GTK3
1623 // GTK3 Menu Action To Check
1624 for (j=1; j<OGL_COORDS; j++) active_glwin -> ogl_coord[j] = NULL;
1625 for (j=0; j<OGL_RINGS; j++) active_glwin -> ogl_rings[j] = NULL;
1626 for (j=0; j<2; j++) active_glwin -> ogl_mode[2+j+NINPUTS] = NULL;
1627 active_glwin -> ogl_chains[0] = NULL;
1628#endif
1631 frag_update = (active_project -> natomes > ATOM_LIMIT) ? 0 : 1;
1632 mol_update = (frag_update) ? ((active_project -> steps > STEP_LIMIT) ? 0 : 1) : 0;
1633 bonds_update = 1;
1634 active_project -> runc[0] = FALSE;
1635 on_calc_bonds_released (NULL, NULL);
1636 if (active_glwin -> mode == EDITION)
1637 {
1638#ifdef GTK4
1639 set_mode (NULL, & active_glwin -> colorp[0][0]);
1640#else
1641 // GTK3 Menu Action To Check
1642 gtk_check_menu_item_set_active ((GtkCheckMenuItem *)active_glwin -> ogl_mode[0], TRUE);
1643 set_mode (active_glwin -> ogl_mode[0], & active_glwin -> colorp[0][0]);
1644#endif
1645 }
1647 gtk_button_set_label (GTK_BUTTON(active_glwin -> builder_win -> pbut), "Build (new project)");
1648 if (active_glwin -> atom_win)
1649 {
1650 if (active_glwin -> atom_win -> win)
1651 {
1652 clean_all_trees (active_glwin -> search_widg[7], active_project);
1653 }
1654 }
1655 }
1657 active_image -> box_axis[0] = 1;
1658 if (to_wrap)
1659 {
1660 shift_it (vec3(0.0,0.0,0.0), 1, activep);
1661 active_glwin -> wrapped = TRUE;
1662 }
1663 active_image -> draw_clones = (active_glwin -> allbonds[1]) ? show_clones : FALSE;
1665#ifdef GTK3
1666 // GTK3 Menu Action To Check
1667 for (i=0; i<2; i++)
1668 {
1669 if (active_glwin -> ogl_box[i] != NULL)
1670 {
1671 widget_set_sensitive (active_glwin -> ogl_box[i], active_cell -> ltype);
1672 }
1673 }
1674 gtk_check_menu_item_set_active ((GtkCheckMenuItem *)active_glwin -> ogl_rep[0], TRUE);
1675 set_rep (active_glwin -> ogl_rep[0], & active_glwin -> colorp[0][0]);
1676#endif
1679 chemistry_ ();
1680 }
1681 else
1682 {
1683 active_project -> modelgl -> search_widg[7] = free_this_search_data (active_project -> modelgl -> search_widg[7]);
1684 g_free (active_project -> modelgl);
1685 active_project -> modelgl = NULL;
1686 active_glwin = NULL;
1687 }
1689 active_cell -> sp_group = duplicate_space_group (sp_group);
1690 if (low_occ)
1691 {
1692 gchar * low_warning = "The crystal will be created however some objects might be missing,\n"
1693 "Occupancy is too low compared to the number of site(s) per cell.\n\n"
1694 "<b>To build a crystal matching the defined occupancy</b>:\n"
1695 "\t <b>1)</b> If you are trying to read a CIF file, use the crystal builder instead.\n"
1696 "\t <b>2)</b> Modify the occupancy set-up to 'Completely random'.\n"
1697 "\t <b>3)</b> Increase the number of unit cells up to get rid of this message.";
1698 show_warning (low_warning, widg);
1699 }
1700 return build_res;
1701}
void clean_all_trees(atom_search *asearch, project *this_proj)
clean all tree models in the 'model edition' window
void prepare_atom_edition(gpointer data, gboolean visible)
prepare atom edition
Definition atom_edit.c:459
atom_search * allocate_atom_search(int proj, int action, int searchid, int tsize)
allocate atom search data structure
Definition atom_edit.c:392
Function declarations for the mode edition window.
void glwin_init_spec_data(project *this_proj, int nspec)
initialize the glwin chemical species related pointers
Definition glview.c:1588
void prepare_opengl_menu_bar(glwin *view)
update the OpenGL window menu bar
Definition glwindow.c:600
atomic_object * duplicate_atomic_object(atomic_object *old_obj)
duplicate an insert object
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
void image_init_spec_data(image *img, project *this_proj, int nsp)
initialize the chemical species related pointers in an image data structure
Definition glview.c:1190
Binding to the Fortran90 subroutines.
double random3_(int *)
double set_radius_(int *, int *)
int chemistry_()
double set_neutron_(int *)
double set_mass_(int *)
void initcwidgets()
initializing curve values
Definition initc.c:104
void apply_project(gboolean showtools)
get project ready for calculation and initialize the OpenGL window
Definition callbacks.c:665
Callback declarations for main window.
gboolean pos_not_taken(int pos, int dim, int *tab)
is this position already taken ?
double get_val_from_wyckoff(gchar *pos, gchar *wval)
get point value from wyckoff position
int build_crystal(gboolean visible, project *this_proj, gboolean to_wrap, gboolean show_clones, cell_info *cell, GtkWidget *widg)
build crystal
gboolean adjust_object_occupancy(crystal_data *cryst, int occupying, int tot_cell)
adjust the crystallograpĥic sites occupancy
space_group * duplicate_space_group(space_group *spg)
duplicate space ground information
int get_crystal_id(int spg)
get the bravais lattice id from space group id
gboolean are_equal_vectors(vec3_t u, vec3_t v)
comparing atomic coordinates vectors
gchar * tmp_pos
void get_origin(space_group *spg)
get space group origin matrices
int pos_not_saved(vec3_t *all_pos, int num_pos, vec3_t pos)
was this position already saved ?
crystal_data * free_crystal_data(crystal_data *cryst)
free crystal data pointer
void compute_lattice_properties(cell_info *cell)
compute lattice parameters following cell description
crystal_data * allocate_crystal_data(int objects, int species)
allocate crystal data pointer
void clean_this_proj(project *this_proj, gboolean newp)
clean project and/or associated cell parameters
int test_lattice(builder_edition *cbuilder, cell_info *cif_cell)
test lattice parameters
double get_val_from_setting(gchar *pos, gchar *sval)
get value from space group setting
double get_value_from_pos(gchar *pos)
get position double value from string description
gboolean same_coords(float a, float b)
test if values are similar, allowing a 0.0001 difference
atomic_object * cif_object
Definition read_cif.c:282
GtkWidget * builder_win(project *this_proj, gpointer data)
create crystal builder window
Function declarations for the crystal builder.
void set_img_lights(project *this_proj, image *img)
initialize lightning for an image data structure
Definition glview.c:1252
gchar * replace_markup(char *init, char *key, char *rep)
replace pattern in string
Definition w_library.c:339
void shift_it(vec3_t shift, int refresh, int proj)
shift atomic coordinates
Definition cell_shift.c:206
void close_project(project *to_close)
close a project
Definition close_p.c:96
void update_insert_combos()
update some GtkComboBox in the workspace if a project is removed
Definition close_p.c:60
color colorp[64]
gchar * param[2]
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 * shift
Definition d_measures.c:72
int atoms[NUM_STYLES][2]
int * duplicate_int(int num, int *old_val)
copy a list of int
Definition global.c:560
gboolean * duplicate_bool(int num, gboolean *old_val)
copy a list of gboolean
Definition global.c:576
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
int multi
Definition dlp_init.c:121
gboolean test_vol(double box[2][3], double vect[3][3])
is the cell properly described to use PBC ?
Definition edit_menu.c:498
float ** allocdfloat(int xal, int yal)
allocate a float ** pointer
Definition global.c:414
int mol_update
Definition global.c:171
double * duplicate_double(int num, double *old_val)
copy a list of double
Definition global.c:608
double pi
Definition global.c:195
int activep
Definition global.c:159
gboolean * allocbool(int val)
allocate a gboolean * pointer
Definition global.c:254
int frag_update
Definition global.c:170
double * allocdouble(int val)
allocate a double * pointer
Definition global.c:459
int bonds_update
Definition global.c:169
int * allocint(int val)
allocate an int * pointer
Definition global.c:314
gboolean ** allocdbool(int xal, int yal)
allocate a gboolean ** pointer
Definition global.c:270
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...
glwin * active_glwin
Definition project.c:53
#define ATOM_LIMIT
atom number limit to compute fragment(s) and molecule(s) analysis automatically
cell_info * active_cell
Definition project.c:50
element_data periodic_table_info[]
Definition w_library.c:71
#define CHEM_N
Definition global.h:300
chemical_data * active_chem
Definition project.c:48
#define STEP_LIMIT
Definition global.h:277
G_MODULE_EXPORT void on_calc_bonds_released(GtkWidget *widg, gpointer data)
compute bonding properties
Definition bdcall.c:471
#define CHEM_R
Definition global.h:299
#define RI
Definition global.h:328
box_info * active_box
Definition project.c:51
#define BD
Definition global.h:326
void widget_set_sensitive(GtkWidget *widg, gboolean sensitive)
Set sensitivity for a GtkWidget, ensuring it is a GtkWidget.
Definition gtk-misc.c:206
#define CHEM_M
Definition global.h:298
#define min(a, b)
Definition global.h:81
#define CHEM_X
Definition global.h:301
#define CHEM_Z
Definition global.h:297
#define SP
Definition global.h:330
project * active_project
Definition project.c:47
void initcutoffs(chemical_data *chem, int species)
initialize bond cutoffs
Definition bdcall.c:207
#define CH
Definition global.h:329
image * active_image
Definition project.c:52
void show_the_widgets(GtkWidget *widg)
show GtkWidget
Definition gtk-misc.c:173
#define max(a, b)
Definition global.h:80
void update(glwin *view)
update the rendering of the OpenGL window
Definition glview.c:439
void init_camera(project *this_proj, int get_depth)
intialize the OpenGL camera settings
Definition glview.c:1132
void sort(int dim, int *tab)
sort, nim to max, a table by integer value
Definition glview.c:380
Variable declarations related to the OpenGL window Function declarations related to the OpenGL wind...
atom_search * free_this_search_data(atom_search *this_search)
free atom search data structure
Definition popup.c:285
void update_all_menus(glwin *view, int nats)
update all menus of the OpenGL window
Definition glwindow.c:337
int check_label_numbers(project *this_proj, int types)
check how many atom label(s) are visible
Definition popup.c:1040
void init_shaders(glwin *view)
initialize all the OpenGL shaders
@ EDITION
Definition glview.h:158
#define DEFAULT_STYLE
Default OpenGL style: ball and stick.
Definition glview.h:43
@ INSERT
Definition glview.h:227
@ BALL_AND_STICK
Definition glview.h:173
#define OGL_COORDS
Definition glwin.h:63
#define OGL_RINGS
Definition glwin.h:64
#define NINPUTS
Definition glwin.h:66
int objects[3]
Definition selection.c:212
void init_curves_and_calc(project *this_proj)
for a project reset analysis, curves, data to not performed
Definition init_p.c:54
void init_project(gboolean alloc_box)
initialize a new project
Definition init_p.c:72
void show_warning(char *warning, GtkWidget *win)
show warning
Definition interface.c:260
gboolean ask_yes_no(gchar *title, gchar *text, int type, GtkWidget *widg)
ask yes or no for something: prepare dialog
Definition interface.c:356
Messaging function declarations.
char * vect_comp[3]
Definition edit_menu.c:82
position
Definition m_proj.c:47
G_MODULE_EXPORT void set_rep(GtkWidget *widg, gpointer data)
change representation callback - GTK3
Definition m_rep.c:367
double z
Definition ogl_draw.c:57
double y
Definition ogl_draw.c:57
double x
Definition ogl_draw.c:57
void alloc_proj_data(project *this_proj, int cid)
allocate data
Definition open_p.c:206
Function declarations for reading atomes project file Function declarations for saving atomes proje...
void active_project_changed(int id)
change the active project
Definition update_p.c:175
coord_file * this_reader
Definition read_coord.c:71
Functions declaration to read atomic coordinates.
Definition glwin.h:114
Definition global.h:884
double z
Definition global.h:890
double y
Definition global.h:889
double x
Definition global.h:888
double * z
Definition cbuild_edit.h:42
int id
Definition global.h:939
Definition global.h:104
int b
Definition global.h:106
int c
Definition global.h:107
int a
Definition global.h:105
float y
Definition math_3d.h:130
float x
Definition math_3d.h:130
float z
Definition math_3d.h:130
int b
Definition tab-1.c:95
int a
Definition tab-1.c:95
gchar * settings[3][10]
Definition w_advance.c:119
int element
Definition w_periodic.c:61
G_MODULE_EXPORT void set_mode(GtkWidget *widg, gpointer data)
set mouse mode callback
Definition m_tools.c:172
void add_project_to_workspace()
add project(s) to the workspace tree
Definition workspace.c:594
GtkWidget * lab
Definition workspace.c:73
Function declarations for workspace managment.