atomes 1.1.14
atomes: an atomic scale modeling tool box
Loading...
Searching...
No Matches
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-2024 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)==0) return 1.0;
91 gchar * sym[8]={"-1/3", "+1/3", "1/3", "-2/3", "+2/3", "2/3", "-", "+"};
92 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};
93 gchar * ksym = NULL;
94 int i;
95 for (i=0; i<8; i++)
96 {
97 ksym = g_strdup_printf ("%s%s", sym[i], pos);
98 if (strstr(sval, ksym))
99 {
100 tmp_pos = g_strdup_printf ("%s", replace_markup (tmp_pos, ksym, NULL));
101 g_free (ksym);
102 ksym = NULL;
103 return vals[i];
104 }
105 g_free (ksym);
106 ksym = NULL;
107 }
108
109 tmp_pos = g_strdup_printf ("%s", replace_markup (tmp_pos, pos, NULL));
110 return 1.0;
111 }
112}
113
121double get_value_from_pos (gchar * pos)
122{
123 if (strstr(pos, "/"))
124 {
125 char * p = NULL;
126 double u, v;
127 p = strtok(pos, "/");
128 u = atof(p);
129 p = strtok(NULL, "/");
130 v = atof(p);
131 return u/v;
132 }
133 else
134 {
135 return atof(pos);
136 }
137}
138
147{
148 char * vinit[3]={"a", "b", "c"};
149 double spinit[3][4];
150 int i, j, k;
151 i = spg -> sid;
152 for (j=0; j<3; j++)
153 {
154 tmp_pos = g_strdup_printf ("%s", spg -> settings[i].pos[j]);
155 for (k=0; k<3; k++)
156 {
157 spinit[j][k] = get_val_from_setting (vinit[k], spg -> settings[i].pos[j]);
158 }
159 if (tmp_pos)
160 {
161 spinit[j][3] = get_value_from_pos (tmp_pos);
162 g_free (tmp_pos);
163 tmp_pos = NULL;
164 }
165 else
166 {
167 spinit[j][3] = 0.0;
168 }
169 }
170 spg -> coord_origin = mat4 (spinit[0][0], spinit[1][0], spinit[2][0], 0.0,
171 spinit[0][1], spinit[1][1], spinit[2][1], 0.0,
172 spinit[0][2], spinit[1][2], spinit[2][2], 0.0,
173 0.0, 0.0, 0.0, 1.0);
174 spg -> wyck_origin = m4_invert_affine (spg -> coord_origin);
175 spg -> coord_origin.m30 = spg -> wyck_origin.m30 = spinit[0][3];
176 spg -> coord_origin.m31 = spg -> wyck_origin.m31 = spinit[1][3];
177 spg -> coord_origin.m32 = spg -> wyck_origin.m32 = spinit[2][3];
178#ifdef DEBUG
179 g_debug ("Coord origin:");
180 m4_print (spg -> coord_origin);
181 g_debug ("Wyck origin:");
182 m4_print (spg -> wyck_origin);
183#endif
184}
185
194{
195 int i;
196 box_info * box = & cell -> box[0];
197 double ltemp;
198 double angle[3];
199 double sangle[3], cangle[3];
200
201 if (! cell -> ltype)
202 {
203 for (i=0; i<3; i++)
204 {
205 if (box -> param[1][i] == 90.0)
206 {
207 angle[i] = pi/2.0;
208 sangle[i] = 1.0;
209 cangle[i] = 0.0;
210 }
211 else
212 {
213 angle[i] = box -> param[1][i]*pi/180.0;
214 sangle[i] = sin(angle[i]);
215 cangle[i] = cos(angle[i]);
216 }
217 }
218 box -> vect[0][0] = box -> param[0][0];
219 box -> vect[0][1] = box -> vect[0][2] = 0.0;
220 box -> vect[1][0] = box -> param[0][1] * cangle[2];
221 box -> vect[1][1] = box -> param[0][1] * sangle[2];
222 box -> vect[1][2] = 0.0;
223 box -> vect[2][0] = box -> param[0][2] * cangle[1];
224 ltemp = (cangle[0] - cangle[1]*cangle[2]) / sangle[2];
225 box -> vect[2][1] = box -> param[0][2] * ltemp;
226 box -> vect[2][2] = box -> param[0][2] * sqrt(sangle[1]*sangle[1] - ltemp*ltemp);
227 }
228 else
229 {
230 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]));
231 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]);
232 box -> param[1][0] /= (box -> param[0][1] * box -> param[0][2]);
233 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]);
234 box -> param[1][1] /= (box -> param[0][0] * box -> param[0][2]);
235 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]);
236 box -> param[1][2] /= (box -> param[0][0] * box -> param[0][1]);
237
238 for (i=0; i<3; i++)
239 {
240 if (box -> param[1][i] == 0.0)
241 {
242 box -> param[1][i] = 90.0;
243 sangle[i] = 1.0;
244 cangle[i] = 0.0;
245 }
246 else
247 {
248 angle[i] = acos(box -> param[1][i]);
249 sangle[i] = sin(angle[i]);
250 cangle[i] = cos(angle[i]);
251 box -> param[1][i] = angle[i]*180.0/pi;
252 }
253 }
254 }
255
256#ifdef DEBUG
257 g_debug (" a= %f, b= %f, c= %f", box -> param[0][0], box -> param[0][1], box -> param[0][2]);
258 g_debug (" alpha= %f, beta= %f, gamma= %f", box -> param[1][0], box -> param[1][1], box -> param[1][2]);
259 g_debug (" a.x= %f, a.y= %f, a.z= %f", box -> vect[0][0], box -> vect[0][1], box -> vect[0][2]);
260 g_debug (" b.x= %f, b.y= %f, b.z= %f", box -> vect[1][0], box -> vect[1][1], box -> vect[1][2]);
261 g_debug (" c.x= %f, c.y= %f, c.z= %f", box -> vect[2][0], box -> vect[2][1], box -> vect[2][2]);
262#endif
263 box -> vol = (box -> vect[0][1]*box -> vect[1][2] - box -> vect[0][2]*box -> vect[1][1])*box -> vect[2][0];
264 box -> vol += (box -> vect[0][2]*box -> vect[1][0] - box -> vect[0][0]*box -> vect[1][2])*box -> vect[2][1];
265 box -> vol += (box -> vect[0][0]*box -> vect[1][1] - box -> vect[0][1]*box -> vect[1][0])*box -> vect[2][2];
266 box -> vol = fabs(box -> vol);
267 cell -> volume = box -> vol;
268#ifdef DEBUG
269 g_debug ("Lattice volume= %f", box -> vol);
270#endif
271 double z = sqrt(fabs(1 - cangle[0]*cangle[0]-cangle[1]*cangle[1]-cangle[2]*cangle[2] + 2*cangle[0]*cangle[1]*cangle[2]));
272
273 float ** ftc;
274 ftc = allocdfloat (4,4);
275 ftc[0][0]=box -> param[0][0];
276 ftc[0][1]=box -> param[0][1]*cangle[2];
277 ftc[0][2]=box -> param[0][2]*cangle[1];
278 ftc[1][1]=box -> param[0][1]*sangle[2];
279 ftc[1][2]=box -> param[0][2]*((cangle[0]-cangle[1]*cangle[2])/sangle[2]);
280 ftc[2][2]=box -> param[0][2]*z/sangle[2];
281 box -> frac_to_cart = mat4(ftc[0][0], ftc[0][1], ftc[0][2], ftc[0][3],
282 ftc[1][0], ftc[1][1], ftc[1][2], ftc[1][3],
283 ftc[2][0], ftc[2][1], ftc[2][2], ftc[2][3],
284 ftc[3][0], ftc[3][1], ftc[3][2], ftc[3][3]);
285 ftc[0][0]=1.0/box -> frac_to_cart.m00;
286 ftc[0][1]=-cangle[2]/(sangle[2]*box -> param[0][0]);
287 ftc[0][2]=box -> param[0][1]*box -> param[0][2]/box -> vol;
288 ftc[0][2]=ftc[0][2]*(cangle[0]*cangle[2] - cangle[1])/sangle[0];
289 ftc[1][1]=1.0/box -> frac_to_cart.m11;
290 ftc[1][2]=(box -> param[0][0]*box -> param[0][2])/box -> vol;
291 ftc[1][2]=ftc[1][2]*(cangle[1]*cangle[2] - cangle[0])/sangle[2];
292 ftc[2][2]=1.0/box -> frac_to_cart.m22;
293 box -> cart_to_frac = mat4 (ftc[0][0], ftc[0][1], ftc[0][2], ftc[0][3],
294 ftc[1][0], ftc[1][1], ftc[1][2], ftc[1][3],
295 ftc[2][0], ftc[2][1], ftc[2][2], ftc[2][3],
296 ftc[3][0], ftc[3][1], ftc[3][2], ftc[3][3]);
297 g_free (ftc);
298#ifdef DEBUG
299 m4_print (box -> frac_to_cart);
300 m4_print (box -> cart_to_frac);
301#endif
302}
303
312int test_lattice (builder_edition * cbuilder, cell_info * cif_cell)
313{
314 int i, j;
315 cell_info * cell = (cbuilder) ? & cbuilder -> cell : cif_cell;
316 box_info * box = & cell -> box[0];
317 i = cell -> sp_group -> id;
318 j = get_crystal_id (i);
319
320 if (cbuilder)
321 {
322 if (! cell -> ltype)
323 {
324 // Adjust a,b,c,alpha,beta,gamma and compute vectors
325 if (j == 3 || j == 4 || j == 6)
326 {
327 box -> param[1][1] = box -> param[1][2] = box -> param[1][0];
328 }
329 if (j == 3 || (j == 4 && cell -> sp_group -> name[0] == 'P') || j == 5)
330 {
331 box -> param[0][1] = box -> param[0][0];
332 }
333 else if ((j == 4 && cell -> sp_group -> name[0] == 'R') || j == 6)
334 {
335 box -> param[0][1] = box -> param[0][2] = box -> param[0][0];
336 }
337 }
338 if (! test_vol(box -> param, box -> vect))
339 {
340 show_warning ("Please describe properly the lattice parameters", cbuilder -> win);
341 return 0;
342 }
344 }
345
346 // Strictly different or possibly different ?
347 /*if (j < 3)
348 {
349 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])
350 {
351 // Box error: a, b, c not all different
352 return 0;
353 }
354 }*/
355
356 if (j == 3 || j == 4 || j == 5)
357 {
358 if (box -> param[0][0] != box -> param[0][1])
359 {
360 // Box error: a and b must be equal
361 return 0;
362 }
363 }
364 if (j == 2 || j == 3 || j == 6)
365 {
366 if (box -> param[1][0] != 90.0 || box -> param[1][1] != 90.0 || box -> param[1][2] != 90.0)
367 {
368 // Angle error: alpha, beta and gamma must be = 90
369 return 0;
370 }
371 }
372
373 switch (j)
374 {
375 // Strictly different or possibly different ?
376 /*
377 case 0:
378 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]))
379 {
380 // Angle error: alpha, beta, gamma not all different
381 return 0;
382 }
383 break;
384 */
385 case 1:
386 if (box -> param[1][0] != 90.0)
387 {
388 // Angle error: alpha must be = 90
389 return 0;
390 }
391 else if (box -> param[1][1] != 90.0 && box -> param[1][2] != 90.0)
392 {
393 // Angle error: beta or gamma must be = 90
394 return 0;
395 }
396 break;
397 case 4:
398 if (cell -> sp_group -> name[0] != 'R')
399 {
400 if (box -> param[1][0] != 90.0 || box -> param[1][1] != 90.0 || box -> param[1][2] != 120.0)
401 {
402 // Angle error: alpha and beta must be equal= 90, gamma must be = 120
403 return 0;
404 }
405 }
406 else
407 {
408 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])
409 {
410 // Angle error: alpha, beta, gamma must all be equal
411 return 0;
412 }
413 else if (box -> param[0][0] != box -> param[0][2])
414 {
415 // Box error: a, b and c must all be equal
416 return 0;
417 }
418 }
419 break;
420 case 5:
421 if (box -> param[1][0] != 90.0 || box -> param[1][1] != 90.0 || box -> param[1][2] != 120.0)
422 {
423 // Angle error: alpha and beta must be = 90, gamma must be = 120
424 return 0;
425 }
426 break;
427 case 6:
428 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])
429 {
430 // Box error: a, b, c not all equal
431 return 0;
432 }
433 break;
434 }
435 return 1;
436}
437
446double get_val_from_wyckoff (gchar * pos, gchar * wval)
447{
448 if (! strstr(wval, pos))
449 {
450 return 0.0;
451 }
452 else
453 {
454 if (g_strcmp0(wval, pos)==0) return 1.0;
455 gchar * sym[4]={"-2", "2", "-", "+"};
456 double sval[4]={-2.0, 2.0, -1.0, 1.0};
457 gchar * ksym = NULL;
458 int i;
459 for (i=0; i<4; i++)
460 {
461 ksym = g_strdup_printf ("%s%s", sym[i], pos);
462 if (strstr(wval, ksym))
463 {
464 tmp_pos = g_strdup_printf ("%s", replace_markup (tmp_pos, ksym, NULL));
465 g_free (ksym);
466 ksym = NULL;
467 return sval[i];
468 }
469 g_free (ksym);
470 ksym = NULL;
471 }
472 tmp_pos = g_strdup_printf ("%s", replace_markup (tmp_pos, pos, NULL));
473 return 1.0;
474 }
475}
476
485void clean_this_proj (project * this_proj, gboolean newp)
486{
487 int i, j;
488 if (newp)
489 {
490 close_project(this_proj);
491 }
492 else
493 {
494 for (i=0; i<3; i++)
495 {
496 for (j=0; j<3; j++)
497 {
498 if (i < 2) this_proj -> cell.box[0].param[i][j] = 0.0;
499 this_proj -> cell.box[0].vect[i][j] = 0.0;
500 }
501 }
502 this_proj -> cell.ltype = 0;
503 this_proj -> cell.pbc = FALSE;
504 }
505}
506
515gboolean same_coords (float a, float b)
516{
517 int i;
518 for (i=0; i<10; i++) if (fabs(fabs(a-b) - i) < 0.0001) return TRUE;
519 return FALSE;
520}
521
531{
532 if (same_coords(u.x, v.x) && same_coords(u.y, v.y) && same_coords(u.z, v.z))
533 {
534 return TRUE;
535 }
536 return FALSE;
537}
538
548int pos_not_saved (vec3_t * all_pos, int num_pos, vec3_t pos)
549{
550 int i;
551 for (i=0; i<num_pos; i++)
552 {
553 if (are_equal_vectors(all_pos[i], pos)) return -(i+1);
554 }
555 return 1;
556}
557
566{
567 space_group * new_spg = g_malloc0(sizeof*new_spg);
568 new_spg -> id = spg -> id;
569 new_spg -> hms = g_strdup_printf ("%s", spg -> hms);
570 new_spg -> bravais = g_strdup_printf ("%s", spg -> bravais);
571 if (spg -> settings[spg -> sid].origin)
572 {
573 new_spg -> setting = g_strdup_printf ("%s:%d", spg -> settings[spg -> sid].name, spg -> settings[spg -> sid].origin);
574 }
575 else
576 {
577 new_spg -> setting = g_strdup_printf ("%s", spg -> settings[spg -> sid].name);
578 }
579 return new_spg;
580}
581
591{
592 crystal_data * cryst = g_malloc0(sizeof*cryst);
593 cryst -> objects = objects;
594 cryst -> spec = species;
595 cryst -> at_by_object = allocint(cryst -> objects);
596 cryst -> pos_by_object = allocint(cryst -> objects);
597 cryst -> occupancy = allocdouble(cryst -> objects);
598 cryst -> sites = g_malloc0(cryst -> objects*sizeof*cryst -> sites);
599 cryst -> insert = g_malloc0(cryst -> objects*sizeof*cryst -> insert);
600 cryst -> position = g_malloc0(cryst -> objects*sizeof*cryst -> position);
601 cryst -> coord = g_malloc0(cryst -> objects*sizeof*cryst -> coord);
602 cryst -> lot = g_malloc0(cryst -> objects*sizeof*cryst -> lot);
603 cryst -> at_type = g_malloc0(cryst -> objects*sizeof*cryst -> at_type);
604 cryst -> z = allocdouble (species);
605 cryst -> nsps = allocint (species);
606 cryst -> holes = allocbool (cryst -> objects);
607 return cryst;
608}
609
618{
619 if (cryst -> at_by_object) g_free (cryst -> at_by_object);
620 if (cryst -> pos_by_object) g_free (cryst -> pos_by_object);
621 if (cryst -> occupancy) g_free (cryst -> occupancy);
622 if (cryst -> sites) g_free (cryst -> sites);
623 if (cryst -> insert) g_free (cryst -> insert);
624 if (cryst -> position) g_free (cryst -> position);
625 if (cryst -> coord) g_free (cryst -> coord);
626 if (cryst -> lot) g_free (cryst -> lot);
627 if (cryst -> at_type) g_free (cryst -> at_type);
628 if (cryst -> z) g_free (cryst -> z);
629 if (cryst -> nsps) g_free (cryst -> nsps);
630 if (cryst -> holes) g_free (cryst -> holes);
631 g_free (cryst);
632 return NULL;
633}
634
644gboolean pos_not_taken (int pos, int dim, int * tab)
645{
646 int i;
647 for (i=0; i<dim; i++) if (tab[i] == pos) return FALSE;
648 return TRUE;
649}
650
665gboolean adjust_object_occupancy (crystal_data * cryst, int occupying, int tot_cell)
666{
667 int h, i, j, k, l, m, n, o, p, q, r, s, t;
668 double v;
669 double prob;
670 gboolean * taken_pos = NULL;
671 gboolean ** holes_pos = NULL;
672 int * pos_order = NULL;
673 int * site_pos = NULL;
674 int num_to_save;
675 int pos_bs, num_bs, site_bs;
676 gboolean pick_it;
677 clock_t CPU_time;
678 gboolean low_occ = FALSE;
679 gboolean with_holes = FALSE;
680 gboolean occ_sym = (occupying == 0 || occupying > 2) ? TRUE : FALSE;
681
682 // position ordering must be used to ensure proper overlapping with holes
683 pos_order = allocint (cryst -> objects);
684 i = j = 0;
685 for (k=0; k<cryst -> objects; k++)
686 {
687 if (cryst -> holes[k])
688 {
689 pos_order[i] = k;
690 j = max (j, cryst -> pos_by_object[i]);
691 i ++;
692 }
693 }
694 if (i)
695 {
696 with_holes = TRUE;
697 holes_pos = allocdbool (cryst -> objects, j);
698 }
699 for (j=0; j<cryst -> objects; j++)
700 {
701 if (! cryst -> holes[j])
702 {
703 pos_order[i] = j;
704 i ++;
705 }
706 }
707
708 for (h=0; h<cryst -> objects; h++)
709 {
710 i = pos_order[h];
711#ifdef DEBUG
712 g_debug ("i= %d, occ[%d]= %f, pbo[%d]= %d", i+1, i+1, cryst -> occupancy[i], i+1, cryst -> pos_by_object[i]);
713#endif
714 if (cryst -> sites[i][0] > 0 && cryst -> occupancy[i]*cryst -> pos_by_object[i] < 1.0 && ! cryst -> holes[i]) low_occ = TRUE;
715
716 if (cryst -> sites[i][0] > 0 && cryst -> occupancy[i] < 1.0 && cryst -> pos_by_object[i] > 1)
717 {
718 v = 0.0;
719 pos_bs = cryst -> pos_by_object[i];
720 site_bs = (cryst -> holes[i]) ? 1 : cryst -> sites[i][0];
721 num_bs = cryst -> sites[i][0];
722 taken_pos = allocbool (pos_bs);
723#ifdef DEBUG
724 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);
725#endif
726 for (j=0; j<cryst -> sites[i][0]; j++)
727 {
728 k = cryst -> sites[i][j+1];
729 v += cryst -> occupancy[k];
730 }
731 l = 0;
732 if (with_holes)
733 {
734 for (j=0; j<site_bs; j++)
735 {
736 if (holes_pos[i][j]) l ++;
737 }
738 }
739 for (j=0; j<site_bs; j++)
740 {
741 k = cryst -> sites[i][j+1];
742#ifdef DEBUG
743 g_debug ("\tj= %d, k= %d, sites[%d][0]= %d, occ[%d]= %f, pos_by_objects[%d]= %d",
744 j+1, k+1, k+1, cryst -> sites[k][0], k+1, cryst -> occupancy[k], k+1, cryst -> pos_by_object[k]);
745#endif
746 if (cryst -> sites[k][0] > -1)
747 {
748 num_to_save = round (pos_bs*cryst -> occupancy[k]);
749 l += num_to_save;
750#ifdef DEBUG
751 g_debug ("\tnum_to_save= %d, l= %d", num_to_save, l);
752#endif
753 if (j == num_bs-1)
754 {
755 if ((v == 1.0 && l != pos_bs) || l > pos_bs) num_to_save += (pos_bs-l);
756 }
757 site_pos = allocint (num_to_save);
758 m = 0;
759 while (m < num_to_save)
760 {
761 pick_it = TRUE;
762 if (occupying < 3)
763 {
764 CPU_time = clock();
765 n = (CPU_time - (k+17)*pos_bs) + (3*cryst -> at_by_object[i]);
766 prob = random3_(& n);
767 p = round (prob * (pos_bs-1));
768 if (with_holes)
769 {
770 pick_it = (taken_pos[p] || holes_pos[i][p]) ? FALSE : TRUE;
771 }
772 else
773 {
774 pick_it = ! taken_pos[p];
775 }
776 }
777 else if (occupying == 3)
778 {
779 p = 0;
780 if (with_holes)
781 {
782 while (taken_pos[p] || holes_pos[i][p]) p ++;
783 }
784 else
785 {
786 while (taken_pos[p]) p ++;
787 }
788 }
789 else
790 {
791#ifdef DEBUG
792 g_debug ("\t\tp= %d, m= %d, sites[i][0]= %d", p, m, cryst -> sites[k][0]);
793#endif
794 p = j + m*cryst -> sites[k][0];
795 if (p > cryst -> pos_by_object[k]-1)
796 {
797 p -= (cryst -> pos_by_object[k]-1);
798 }
799#ifdef DEBUG
800 g_debug ("\t\tp= %d", p);
801#endif
802 for (n=0; n<m; n++)
803 {
804 if (site_pos[n] == p)
805 {
806 n = p ++;
807 if (n == cryst -> pos_by_object[k]) n = 0;
808 pick_it = FALSE;
809 while (! pick_it)
810 {
811 pick_it = TRUE;
812 for (o=0; o<m; o++)
813 {
814 if (site_pos[o] == n)
815 {
816 pick_it = FALSE;
817 n ++;
818 }
819 }
820 }
821 p = n;
822 break;
823 }
824 }
825 }
826 if (pick_it)
827 {
828 site_pos[m] = p;
829 taken_pos[p] = TRUE;
830 m ++;
831 }
832 }
833#ifdef DEBUG
834 sort (num_to_save, site_pos);
835 for (m=0; m<num_to_save; m++)
836 {
837 g_debug ("\t\tm= %d, site_pos[%d]= %d", m+1, m+1, site_pos[m]);
838 }
839#endif
840 for (m=0; m<num_to_save; m++)
841 {
842 n = site_pos[m];
843 cryst -> coord[k][m] = cryst -> coord[k][n];
844 if (occ_sym && tot_cell > 1)
845 {
846 for (o=1; o<tot_cell; o++)
847 {
848 p = k+o*(cryst -> objects/tot_cell);
849 cryst -> coord[p][m] = cryst -> coord[p][n];
850 }
851 }
852 }
853
854 cryst -> pos_by_object[k] = num_to_save;
855 cryst -> sites[k][0] = -1;
856 if (occ_sym && tot_cell > 1)
857 {
858 for (o=1; o<tot_cell; o++)
859 {
860 p = k+o*(cryst -> objects/tot_cell);
861 cryst -> pos_by_object[p] = num_to_save;
862 cryst -> sites[p][0] = -1;
863 }
864 }
865 if (cryst -> holes[i])
866 {
867 for (o=0; o<num_bs; o++)
868 {
869 p = cryst -> sites[i][o+1];
870 for (q=0; q<num_to_save; q++)
871 {
872 r = site_pos[q];
873 holes_pos[p][r] = TRUE;
874 if (occ_sym && tot_cell > 1)
875 {
876 for (s=1; s<tot_cell; s++)
877 {
878 t = p+s*(cryst -> objects/tot_cell);
879 holes_pos[t][r] = TRUE;
880 }
881 }
882 }
883 }
884 }
885 g_free (site_pos);
886 }
887 }
888 g_free (taken_pos);
889 }
890 }
891 if (holes_pos) g_free (holes_pos);
892 return low_occ;
893}
894
907int build_crystal (gboolean visible, project * this_proj, gboolean to_wrap, gboolean show_clones, cell_info * cell, GtkWidget * widg)
908{
909 int h, i, j, k, l, m, n, o, p, q;
910 int build_res = 1;
911 space_group * sp_group = cell -> sp_group;
912 box_info * box = & cell -> box[0];
913 gchar * str;
914 mat4_t ** wyckpos = g_malloc0 (sp_group -> numw*sizeof*wyckpos);
915 double spgpos[3][4];
916 for (i=0; i<1; i++)//sp_group -> numw; i++)
917 {
918 wyckpos[i] = g_malloc0 (sp_group -> wyckoff[i].multi*sizeof*wyckpos[i]);
919 for (j=0; j<sp_group -> wyckoff[i].multi; j++)
920 {
921 for (k=0; k<3; k++)
922 {
923 tmp_pos = g_strdup_printf ("%s", sp_group -> wyckoff[i].pos[j][k]);
924 for (l=0; l<3; l++)
925 {
926 spgpos[k][l] = get_val_from_wyckoff (vect_comp[l], sp_group -> wyckoff[i].pos[j][k]);
927 }
928 if (tmp_pos)
929 {
930 spgpos[k][3] = get_value_from_pos (tmp_pos);
931 g_free (tmp_pos);
932 tmp_pos = NULL;
933 }
934 else
935 {
936 spgpos[k][3] = 0.0;
937 }
938 }
939
940 wyckpos[i][j] = mat4 (spgpos[0][0], spgpos[0][1], spgpos[0][2], spgpos[0][3],
941 spgpos[1][0], spgpos[1][1], spgpos[1][2], spgpos[1][3],
942 spgpos[2][0], spgpos[2][1], spgpos[2][2], spgpos[2][3],
943 0.0, 0.0, 0.0, 1.0);
944 wyckpos[i][j] = m43_mul(sp_group -> wyck_origin, wyckpos[i][j]);
945#ifdef DEBUG
946// g_debug ("w_id= %d, w_mul= %d", i+1, j+1);
947// m4_print (wyckpos[i][j]);
948#endif
949 }
950 }
951 double copos[3];
952 int npoints;
953 vec3_t * points;
954 h = sp_group -> sid;
955 if (sp_group -> settings[h].nump)
956 {
957 points = g_malloc0(sp_group -> settings[h].nump*sizeof*points);
958 for (i=0; i<sp_group -> settings[h].nump; i++)
959 {
960 for (j=0; j<3; j++)
961 {
962 tmp_pos = g_strdup_printf ("%s", sp_group -> settings[h].points[i][j]);
963 copos[j] = get_value_from_pos (tmp_pos);
964 g_free (tmp_pos);
965 tmp_pos = NULL;
966 }
967 points[i] = vec3(copos[0], copos[1], copos[2]);
968 //m4_mul_coord (sp_group -> coord_origin, vec3(copos[0], copos[1], copos[2]));
969#ifdef DEBUG
970// g_debug ("point=%d, p.x= %f, p.y= %f, p.z= %f", i+1, points[i].x, points[i].y ,points[i].z);
971#endif
972 }
973 npoints = sp_group -> settings[h].nump;
974 }
975 else
976 {
977 points = g_malloc0(1*sizeof*points);
978 points[0] = vec3(0.0, 0.0, 0.0);
979 npoints = 1;
980 }
981
982 vec3_t pos;
983 atomic_object * object = NULL;
984 gboolean done;
985 crystal_data * cdata = NULL;
986 int occupying;
987 double amin = box -> param[0][0];
988 for (i=1; i<3; i++) amin = min(amin, box -> param[0][i]);;
989 if (! visible)
990 {
991 tint point;
992 point.a = this_proj -> id;
993 point.b = point.c = 0;
994 this_proj -> modelgl = g_malloc0(sizeof*this_proj -> modelgl);
995 prepare_atom_edition (& point, FALSE);
996 this_proj -> modelgl -> search_widg[7] = allocate_atom_search (this_proj -> id, INSERT, 7, this_reader -> natomes);
997 gboolean do_obj;
998 for (i=0; i<this_reader -> natomes; i++)
999 {
1000 do_obj = FALSE;
1001 for (j=0; j<this_reader -> atom_unlabelled; j++)
1002 {
1003 if (this_reader -> u_atom_list[j] == i)
1004 {
1005 do_obj = TRUE;
1006 break;
1007 }
1008 }
1009 if (do_obj)
1010 {
1011 if (! object)
1012 {
1013 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));
1014 object = this_proj -> modelgl -> atom_win -> to_be_inserted[2];
1015 }
1016 else
1017 {
1018 object -> next = duplicate_atomic_object (get_atomic_object_by_origin (cif_object, this_reader -> object_list[j], 0));
1019 }
1020 }
1021 else
1022 {
1023 j = this_reader -> lot[i];
1024 to_insert_in_project ((int)this_reader -> z[j], -1, this_proj, this_proj -> modelgl -> search_widg[7], FALSE);
1025 }
1026 this_proj -> modelgl -> search_widg[7] -> todo[i] = 1;
1027 if (! object)
1028 {
1029 object = this_proj -> modelgl -> atom_win -> to_be_inserted[2];
1030 }
1031 else
1032 {
1033 object = object -> next;
1034 }
1035 object -> occ = this_reader -> occupancy[i];
1036 for (j=0; j<3; j++) object -> baryc[j] = this_reader -> coord[i][j];
1037 }
1038 occupying = 0;
1039 }
1040 else
1041 {
1042 occupying = this_proj -> modelgl -> builder_win -> occupancy;
1043 }
1044 for (h=0; h<2; h++)
1045 {
1046 object = this_proj -> modelgl -> atom_win -> to_be_inserted[2];
1047 i = j = k = 0;
1048 while (object)
1049 {
1050 l = object -> id;
1051 if (this_proj -> modelgl -> search_widg[7] -> todo[l])
1052 {
1053 if (h)
1054 {
1055 for (m=0; m<object -> species; m++)
1056 {
1057 done = FALSE;
1058 for (l=0; l<k; l++)
1059 {
1060 if (object -> old_z[m] == cdata -> z[l])
1061 {
1062 done = TRUE;
1063 break;
1064 }
1065 }
1066 if (! done && object -> old_z[m] > 0.0)
1067 {
1068 cdata -> z[k] = object -> old_z[m];
1069 k ++;
1070 }
1071 if (object -> old_z[m] == 0.0)
1072 {
1073 cdata -> holes[i] = TRUE;
1074 cdata -> with_holes = TRUE;
1075 }
1076 }
1077 n = sp_group -> wyckoff[0].multi*npoints;
1078 cdata -> at_type[i] = allocint(n);
1079 cdata -> coord[i] = g_malloc0(n*sizeof*cdata -> coord[i]);
1080 cdata -> insert[i] = m4_mul_coord (sp_group -> coord_origin, vec3(object -> baryc[0], object -> baryc[1], object -> baryc[2]));
1081#ifdef DEBUG
1082 // 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]);
1083 // 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);
1084#endif
1085 n = 0;
1086 for (o=0; o<npoints; o++)
1087 {
1088 for (p=0; p<sp_group -> wyckoff[0].multi; p++)
1089 {
1090 pos = v3_add (m4_mul_coord (wyckpos[0][p], cdata -> insert[i]), points[o]);
1091 q = pos_not_saved (cdata -> coord[i], n, pos);
1092 if (q > 0)
1093 {
1094 cdata -> coord[i][n].x = pos.x;
1095 cdata -> coord[i][n].y = pos.y;
1096 cdata -> coord[i][n].z = pos.z;
1097#ifdef DEBUG
1098 // 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);
1099#endif
1100 cdata -> at_type[i][n] = 1;
1101 n ++;
1102 }
1103 else if (q < 0)
1104 {
1105 cdata -> at_type[i][-(q+1)] ++;
1106 }
1107 }
1108 }
1109 cdata -> pos_by_object[i] = n;
1110 cdata -> occupancy[i] = object -> occ;
1111 if (! cdata -> holes[i]) cdata -> lot[i] = allocint(object -> atoms);
1112 cdata -> position[i] = g_malloc0(object -> atoms*sizeof*cdata -> position[i]);
1113 for (l=0; l<object -> atoms; l++)
1114 {
1115 n = object -> at_list[l].sp;
1116 cdata -> position[i][l].x = object -> at_list[l].x;
1117 cdata -> position[i][l].y = object -> at_list[l].y;
1118 cdata -> position[i][l].z = object -> at_list[l].z;
1119 if (! cdata -> holes[i])
1120 {
1121 for (o=0; o<k; o++)
1122 {
1123 if (cdata -> z[o] == object -> old_z[n])
1124 {
1125 cdata -> lot[i][l] = o;
1126 break;
1127 }
1128 }
1129 }
1130 }
1131 cdata -> at_by_object[i] = object -> atoms;
1132 i ++;
1133 }
1134 else
1135 {
1136 if (object -> dim > amin)
1137 {
1138 str = g_strdup_printf ("%s size (%f Ang.) is bigger than the min(<b><i>a,b,c</i></b>)\n"
1139 "If you build the crystal the final structure is likely to be crowded !\n"
1140 "Continue anyway ?", object -> name, object -> dim);
1141 build_res = 2;
1142 if (! ask_yes_no("This object might be too big !" , str, GTK_MESSAGE_WARNING, widg))
1143 {
1144 g_free (str);
1145 if (points) g_free (points);
1146 if (wyckpos) g_free (wyckpos);
1147 if (cdata) cdata = free_crystal_data (cdata);
1148 if (! visible)
1149 {
1150 this_proj -> modelgl -> search_widg[7] = free_this_search_data (this_proj -> modelgl -> search_widg[7]);
1151 g_free (this_proj -> modelgl);
1152 this_proj -> modelgl = NULL;
1153 active_glwin = NULL;
1154 }
1155 return 0;
1156 }
1157 g_free (str);
1158 }
1159 i ++;
1160 j += object -> species;
1161 k += object -> atoms;
1162 }
1163 }
1164 object = object -> next;
1165 }
1166 if (! h)
1167 {
1168 if (k)
1169 {
1170 cdata = allocate_crystal_data (i, j);
1171 cdata -> overlapping = (visible) ? this_proj -> modelgl -> builder_win -> overlapping : FALSE;
1172 }
1173 else
1174 {
1175 if (points) g_free (points);
1176 if (wyckpos) g_free (wyckpos);
1177 if (cdata) cdata = free_crystal_data (cdata);
1178 if (! visible)
1179 {
1180 this_proj -> modelgl -> search_widg[7] = free_this_search_data (this_proj -> modelgl -> search_widg[7]);
1181 g_free (this_proj -> modelgl);
1182 this_proj -> modelgl = NULL;
1183 active_glwin = NULL;
1184 }
1185 return 0;
1186 }
1187 }
1188 }
1189
1190 if (points) g_free (points);
1191 if (wyckpos) g_free (wyckpos);
1192
1193 cdata -> spec = k;
1194
1195 double u, v;
1196 m = 0;
1197 for (i=0; i<cdata -> objects; i++)
1198 {
1199 m += (cdata -> holes[i]) ? 1 : 0;
1200 u = v = 0.0;
1201 for (j=0; j<2; j++)
1202 {
1203 k = 1;
1204 if (! cdata -> overlapping || cdata -> holes[i])
1205 {
1206 u = cdata -> occupancy[i];
1207 }
1208 else
1209 {
1210 v = cdata -> occupancy[i];
1211 }
1212 if (u+v > 1.0 || u+v < 0.0)
1213 {
1214 if (cdata) cdata = free_crystal_data (cdata);
1215 show_warning ("Impossible to build crystal: check occupancy !", widg);
1216 return 0;
1217 }
1218 else if (cdata -> overlapping && ! cdata -> with_holes)
1219 {
1220 if (j) cdata -> sites[i][k] = i;
1221 }
1222 else
1223 {
1224 for (l=0; l<cdata -> objects; l++)
1225 {
1226 if (l != i)
1227 {
1228 if (cdata -> insert[i].x == cdata -> insert[l].x
1229 && cdata -> insert[i].y == cdata -> insert[l].y
1230 && cdata -> insert[i].z == cdata -> insert[l].z)
1231 {
1232 if (j)
1233 {
1234 if (! cdata -> overlapping || cdata -> holes[i])
1235 {
1236 k ++;
1237 cdata -> sites[i][k] = l;
1238 }
1239 }
1240 else
1241 {
1242 if (! cdata -> overlapping || cdata -> holes[i]) k ++;
1243 if (! cdata -> overlapping || cdata -> holes[l])
1244 {
1245 u += cdata -> occupancy[l];
1246 }
1247 else
1248 {
1249 v = max(v, cdata -> occupancy[l]);
1250 }
1251 if (u+v > 1.00001)
1252 {
1253 show_warning ("Impossible to build crystal: site total occupancy > 1.0", widg);
1254 if (cdata) cdata = free_crystal_data (cdata);
1255 return 0;
1256 }
1257 }
1258 }
1259 }
1260 }
1261 }
1262 if (! j)
1263 {
1264 cdata -> sites[i] = allocint (k+1);
1265 cdata -> sites[i][0] = k;
1266 cdata -> sites[i][1] = i;
1267 if (k > 1) cdata -> shared_sites = TRUE;
1268 }
1269 }
1270 }
1271#ifdef DEBUG
1272 /*for (i=0; i<cdata -> objects; i++)
1273 {
1274 g_debug ("i= %d, site[%d]= %d", i+1, i+1, cdata -> sites[i][0]);
1275 for (j=0; j<cdata -> sites[i][0]; j++)
1276 {
1277 g_debug ("\t j= %d, co-site[%d][%d]= %d", j+1, i+1, j+1, cdata -> sites[i][j+1]+1);
1278 }
1279 }*/
1280#endif // DEBUG
1281
1282 if (m == cdata -> objects)
1283 {
1284 if (cdata) cdata = free_crystal_data (cdata);
1285 show_warning ("Impossible to build crystal: empty site(s) only !", widg);
1286 return 0;
1287 }
1288 gboolean new_proj = (this_proj -> natomes && visible) ? TRUE : FALSE;
1289
1290 if (new_proj)
1291 {
1292 init_project(TRUE);
1293 }
1294 else if (visible)
1295 {
1296 active_project_changed (this_proj -> id);
1297 }
1298 for (i=0; i<3; i++)
1299 {
1300 for (j=0; j<3; j++)
1301 {
1302 if (i < 2)
1303 {
1304 active_box -> param[i][j] = box -> param[i][j];
1305 if (! i) active_box -> param[i][j] *= cell -> cextra[j];
1306 }
1307 active_box -> vect[i][j] *= cell -> cextra[i];
1308 }
1309 }
1311 active_cell -> ltype = 1;
1312 active_cell -> pbc = TRUE;
1313 int tot_cell = 1;
1314 for (i=0; i<3; i++)
1315 {
1316 tot_cell *= cell -> cextra[i];
1317 }
1318 vec3_t vx, vy, vz, shift;
1319 h = 0;
1320 i = (occupying == 2) ? 0 : 1;
1321 j = (occupying == 2) ? 1 : tot_cell;
1322 crystal_data * cryst = allocate_crystal_data (j*cdata -> objects, cdata -> spec);
1323 g_free (cryst -> z);
1324 cryst -> z = duplicate_double (cdata -> spec, cdata -> z);
1325 cryst -> shared_sites = cdata -> shared_sites;
1326 cryst -> overlapping = cdata -> overlapping;
1327 cryst -> with_holes = cdata -> with_holes;
1328 if (occupying == 2)
1329 {
1330 for (k=0; k<cdata -> objects; k++)
1331 {
1332 cryst -> pos_by_object[k] = tot_cell*cdata -> pos_by_object[k];
1333 cryst -> at_by_object[k] = cdata -> at_by_object[k];
1334 cryst -> at_type[k] = duplicate_int (sp_group -> wyckoff[0].multi*npoints, cdata -> at_type[k]);
1335 cryst -> holes = duplicate_bool (cdata -> objects, cdata -> holes);
1336 if (! cdata -> holes[k]) cryst -> lot[k] = duplicate_int (cdata -> at_by_object[k], cdata -> lot[k]);
1337 cryst -> occupancy[k] = cdata -> occupancy[k];
1338 cryst -> sites[k] = duplicate_int (cdata -> sites[k][0]+1, cdata -> sites[k]);
1339 cryst -> position[k] = g_malloc0 (cdata -> at_by_object[k]*sizeof*cryst -> position[k]);
1340 for (l=0; l<cdata -> at_by_object[k]; l++) cryst -> position[k][l] = cdata -> position[k][l];
1341 cryst -> coord[k] = g_malloc0(cryst -> pos_by_object[k]*sizeof*cryst -> coord[k]);
1342 }
1343 }
1344
1345 for (k=0; k<cell -> cextra[0]; k++)
1346 {
1347 vx = v3_muls(vec3(box -> vect[0][0], box -> vect[0][1], box -> vect[0][2]), k);
1348 for (l=0; l<cell -> cextra[1]; l++)
1349 {
1350 vy = v3_muls(vec3(box -> vect[1][0], box -> vect[1][1], box -> vect[1][2]), l);
1351 for (m=0; m<cell -> cextra[2]; m++)
1352 {
1353 vz = v3_muls(vec3(box -> vect[2][0], box -> vect[2][1], box -> vect[2][2]), m);
1354 shift = v3_add (vx, v3_add(vy, vz));
1355 for (n=0; n<cdata -> objects; n++)
1356 {
1357 if (occupying != 2)
1358 {
1359 cryst -> coord[n+h] = g_malloc0(cdata -> pos_by_object[n]*sizeof*cryst -> coord[n+h]);
1360 cryst -> pos_by_object[n+h] = cdata -> pos_by_object[n];
1361 cryst -> at_by_object[n+h] = cdata -> at_by_object[n];
1362 cryst -> holes[n+h] = cdata -> holes[n];
1363 cryst -> at_type[n+h] = duplicate_int (sp_group -> wyckoff[0].multi*npoints, cdata -> at_type[n]);
1364 if (! cdata -> holes[n]) cryst -> lot[n+h] = duplicate_int (cdata -> at_by_object[n], cdata -> lot[n]);
1365 cryst -> occupancy[n+h] = cdata -> occupancy[n];
1366 cryst -> sites[n+h] = duplicate_int (cdata -> sites[n][0]+1, cdata -> sites[n]);
1367 for (o=0; o<cryst -> sites[n+h][0]; o++) cryst -> sites[n+h][o+1] += h;
1368 cryst -> position[n+h] = g_malloc0 (cdata -> at_by_object[n]*sizeof*cryst -> position[n+h]);
1369 for (o=0; o<cdata -> at_by_object[n]; o++) cryst -> position[n+h][o] = cdata -> position[n][o];
1370 }
1371 o = cdata -> pos_by_object[n];
1372 for (p=0; p<o; p++)
1373 {
1374 cryst -> coord[n+i*h][p+(!i)*h*o] = v3_add(m4_mul_coord (box -> frac_to_cart, cdata -> coord[n][p]), shift);
1375 }
1376 }
1377 h += (occupying != 2) ? cdata -> objects : 1;
1378 }
1379 }
1380 }
1381 cdata = free_crystal_data (cdata);
1382 gboolean low_occ = adjust_object_occupancy (cryst, occupying, tot_cell);
1383 atom at, bt;
1384 distance dist;
1385 gboolean dist_chk = TRUE;
1386
1387 if (! cryst -> overlapping)
1388 {
1389 for (i=0; i<cryst -> objects; i++)
1390 {
1391 if (! cryst -> holes[i])
1392 {
1393 for (j=0; j<cryst -> pos_by_object[i]; j++)
1394 {
1395 at.x = cryst -> coord[i][j].x;
1396 at.y = cryst -> coord[i][j].y;
1397 at.z = cryst -> coord[i][j].z;
1398 for (k=i; k<cryst -> objects; k++)
1399 {
1400 if (! cryst -> holes[k])
1401 {
1402 if (k != i || j < cryst -> pos_by_object[i]-1)
1403 {
1404 l = (k == i) ? j+1 : 0;
1405 for (m=l; m<cryst -> pos_by_object[k]; m++)
1406 {
1407 bt.x = cryst -> coord[k][m].x;
1408 bt.y = cryst -> coord[k][m].y;
1409 bt.z = cryst -> coord[k][m].z;
1410 dist = distance_3d (active_cell, 0, & at, & bt);
1411 if (dist.length < 0.5)
1412 {
1413 // g_print ("i= %d, j= %d, k= %d, m= %d, d= %f\n", i, j, k, m, dist.length);
1414 if (dist_chk)
1415 {
1416 build_res = 3;
1417 if (ask_yes_no ("Inter-object distance(s) < 0.5 Ang. !",
1418 "Inter-object distance(s) &lt; 0.5 Ang. !\n\n\t\tContinue and leave a single object at each position ?", GTK_MESSAGE_WARNING, widg))
1419 {
1420 dist_chk = FALSE;
1421 }
1422 else
1423 {
1424 clean_this_proj (active_project, new_proj);
1425 cryst = free_crystal_data (cryst);
1426 return 0;
1427 }
1428 }
1429 if (! dist_chk)
1430 {
1431 if (dist.length < 0.1)
1432 {
1433 cryst -> at_type[i][j] += cryst -> at_type[k][m];
1434 for (n=m; n<cryst -> pos_by_object[k]-1; n++)
1435 {
1436 cryst -> coord[k][n].x = cryst -> coord[k][n+1].x;
1437 cryst -> coord[k][n].y = cryst -> coord[k][n+1].y;
1438 cryst -> coord[k][n].z = cryst -> coord[k][n+1].z;
1439 cryst -> at_type[k][n] += cryst -> at_type[k][n+1];
1440 }
1441 cryst -> pos_by_object[k] --;
1442 m --;
1443 }
1444 }
1445 }
1446 }
1447 }
1448 }
1449 }
1450 }
1451 }
1452 }
1453 }
1454
1455 int tot_new_at = 0;
1456 for (i=0; i<cryst -> objects; i++)
1457 {
1458 if (! cryst -> holes[i]) tot_new_at += cryst -> pos_by_object[i]*cryst -> at_by_object[i];
1459 }
1460 int * tot_new_lot = allocint(tot_new_at);
1461 vec3_t * ncc = g_malloc0(tot_new_at*sizeof*ncc);
1462 i = 0;
1463 for (j=0; j<cryst -> objects; j++)
1464 {
1465 if (! cryst -> holes[j])
1466 {
1467 for (k=0; k<cryst -> at_by_object[j]; k++)
1468 {
1469 for (l=0; l<cryst -> pos_by_object[j]; l++)
1470 {
1471 ncc[i] = v3_add (cryst -> coord[j][l], cryst -> position[j][k]);
1472 m = tot_new_lot[i] = cryst -> lot[j][k];
1473 cryst -> nsps[m] ++;
1474 i ++;
1475 }
1476 }
1477 }
1478 }
1479 active_project -> steps = 1;
1480 active_project -> natomes = tot_new_at;
1481 if (low_occ)
1482 {
1483 i = 0;
1484 for (j=0; j<cryst -> spec; j++)
1485 {
1486 if (cryst -> nsps[j]) i ++;
1487 }
1488 active_project -> nspec = i;
1489 }
1490 else
1491 {
1492 active_project -> nspec = cryst -> spec;
1493 }
1494#ifdef DEBUG
1495 g_debug ("CRYSTAL:: atoms= %d, species= %d", active_project -> natomes, active_project -> nspec);
1496#endif
1499 k = l = 0;
1500 for (i=0; i<cryst -> spec; i++)
1501 {
1502 if (! cryst -> nsps[i])
1503 {
1504 if (! low_occ)
1505 {
1506 if (ncc) g_free (ncc);
1507 if (tot_new_lot) g_free (tot_new_lot);
1508#ifdef DEBUG
1509 g_debug ("CRYSTAL:: spec= %d, label= %s, nsps= %d", i+1, periodic_table_info[j].lab, 0);
1510#endif
1511 return 0;
1512 }
1513 }
1514 else
1515 {
1516 j = (int)cryst -> z[i];
1517 active_chem -> label[k] = g_strdup_printf ("%s", periodic_table_info[j].lab);
1518 active_chem -> element[k] = g_strdup_printf ("%s", periodic_table_info[j].name);
1519 active_chem -> nsps[k] = cryst -> nsps[i];
1520 active_chem -> chem_prop[CHEM_Z][k] = cryst -> z[i];
1521 active_chem -> chem_prop[CHEM_M][k] = set_mass_ (& j);
1522 active_chem -> chem_prop[CHEM_R][k] = set_radius_ (& j, & l);
1523 active_chem -> chem_prop[CHEM_N][k] = set_neutron_ (& j);
1524 active_chem -> chem_prop[CHEM_X][k] = active_chem -> chem_prop[CHEM_Z][k];
1525#ifdef DEBUG
1526 g_debug ("CRYSTAL:: spec= %d, label= %s, nsps= %d", k+1, active_chem -> label[k], active_chem -> nsps[k]);
1527#endif
1528 for (m=0; m<tot_new_at;m++)
1529 {
1530 if (tot_new_lot[m] == i) tot_new_lot[m] = k;
1531 }
1532 k ++;
1533 }
1534 }
1535 cryst = free_crystal_data (cryst);
1536 copos[0] = copos[1] = copos[2] = 0.0;
1537 if (visible && ! new_proj)
1538 {
1539 for (i=0; i<3; i++)
1540 {
1541 for (j=0; j<3; j++) copos[i] -= active_box -> vect[j][i]/2.0;
1542 }
1543 }
1544 for (i=0; i<tot_new_at; i++)
1545 {
1546 active_project -> atoms[0][i].id = i;
1547 j = tot_new_lot[i];
1548 active_project -> atoms[0][i].sp = j;
1549 active_project -> atoms[0][i].x = ncc[i].x + copos[0];
1550 active_project -> atoms[0][i].y = ncc[i].y + copos[1];
1551 active_project -> atoms[0][i].z = ncc[i].z + copos[2];
1552 active_project -> atoms[0][i].show[0] = TRUE;
1553 active_project -> atoms[0][i].show[1] = TRUE;
1554 active_project -> atoms[0][i].label[0] = FALSE;
1555 active_project -> atoms[0][i].label[1] = FALSE;
1556 active_project -> atoms[0][i].pick[0] = FALSE;
1557 active_project -> atoms[0][i].cloned = FALSE;
1558#ifdef DEBUG
1559 // g_debug ("sp= %d, %s %f %f %f", j+1, active_chem -> label[j], ncc[i].x, ncc[i].y, ncc[i].z);
1560#endif
1561 }
1562 if (ncc) g_free (ncc);
1563 if (tot_new_lot) g_free (tot_new_lot);
1564
1565 active_cell -> has_a_box = TRUE;
1566 active_cell -> crystal = TRUE;
1567
1568 if (visible)
1569 {
1570 for (i=0; i<3; i=i+2) active_project -> runok[i] = TRUE;
1571 active_project -> runok[BD] = TRUE;
1572 active_project -> runok[RI] = TRUE;
1573 active_project -> runok[CH] = TRUE;
1574 active_project -> runok[SP] = TRUE;
1576 if (new_proj)
1577 {
1579 apply_project (TRUE);
1580 }
1581 else
1582 {
1583 active_project -> run = TRUE;
1586 initcwidgets ();
1592#ifdef GTK3
1593 // GTK3 Menu Action To Check
1594 for (j=1; j<OGL_COORDS; j++) active_glwin -> ogl_coord[j] = NULL;
1595 for (j=0; j<OGL_RINGS; j++) active_glwin -> ogl_rings[j] = NULL;
1596 for (j=0; j<2; j++) active_glwin -> ogl_mode[2+j+NINPUTS] = NULL;
1597 active_glwin -> ogl_chains[0] = NULL;
1598#endif
1601 frag_update = (active_project -> natomes > ATOM_LIMIT) ? 0 : 1;
1602 mol_update = (frag_update) ? ((active_project -> steps > STEP_LIMIT) ? 0 : 1) : 0;
1603 bonds_update = 1;
1604 active_project -> runc[0] = FALSE;
1605 on_calc_bonds_released (NULL, NULL);
1606 if (active_glwin -> mode == EDITION)
1607 {
1608#ifdef GTK4
1609 set_mode (NULL, & active_glwin -> colorp[0][0]);
1610#else
1611 // GTK3 Menu Action To Check
1612 gtk_check_menu_item_set_active ((GtkCheckMenuItem *)active_glwin -> ogl_mode[0], TRUE);
1613 set_mode (active_glwin -> ogl_mode[0], & active_glwin -> colorp[0][0]);
1614#endif
1615 }
1616 gtk_widget_show (active_glwin -> win);
1617 gtk_button_set_label (GTK_BUTTON(active_glwin -> builder_win -> pbut), "Build (new project)");
1618 if (active_glwin -> atom_win)
1619 {
1620 if (active_glwin -> atom_win -> win)
1621 {
1622 clean_all_trees (active_glwin -> search_widg[7], active_project);
1623 }
1624 }
1625 }
1627 active_image -> box_axis[0] = 1;
1628 if (to_wrap)
1629 {
1630 shift_it (vec3(0.0,0.0,0.0), 1, activep);
1631 active_glwin -> wrapped = TRUE;
1632 }
1633 active_image -> draw_clones = (active_glwin -> allbonds[1]) ? show_clones : FALSE;
1635#ifdef GTK3
1636 // GTK3 Menu Action To Check
1637 for (i=0; i<2; i++)
1638 {
1639 if (active_glwin -> ogl_box[i] != NULL)
1640 {
1641 widget_set_sensitive (active_glwin -> ogl_box[i], active_cell -> ltype);
1642 }
1643 }
1644 gtk_check_menu_item_set_active ((GtkCheckMenuItem *)active_glwin -> ogl_rep[0], TRUE);
1645 set_rep (active_glwin -> ogl_rep[0], & active_glwin -> colorp[0][0]);
1646#endif
1649 chemistry_ ();
1650 }
1651 else
1652 {
1653 active_project -> modelgl -> search_widg[7] = free_this_search_data (active_project -> modelgl -> search_widg[7]);
1654 g_free (active_project -> modelgl);
1655 active_project -> modelgl = NULL;
1656 active_glwin = NULL;
1657 }
1659 active_cell -> sp_group = duplicate_space_group (sp_group);
1660 if (low_occ)
1661 {
1662 gchar * low_warning = "The crystal will be created however some objects might be missing,\n"
1663 "Occupancy is too low compared to the number of site(s) per cell.\n\n"
1664 "<b>To build a crystal matching the defined occupancy</b>:\n"
1665 "\t <b>1)</b> If you are trying to read a CIF file, use the crystal builder instead.\n"
1666 "\t <b>2)</b> Modify the occupancy set-up to 'Completely random'.\n"
1667 "\t <b>3)</b> Increase the number of unit cells up to get rid of this message.";
1668 show_warning (low_warning, widg);
1669 }
1670 return build_res;
1671}
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:1584
void prepare_opengl_menu_bar(glwin *view)
update the OpenGL window menu bar
Definition glwindow.c:457
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:1187
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:280
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:1249
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:572
gboolean * duplicate_bool(int num, gboolean *old_val)
copy a list of gboolean
Definition global.c:588
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:426
int mol_update
Definition global.c:171
double * duplicate_double(int num, double *old_val)
copy a list of double
Definition global.c:620
double pi
Definition global.c:195
int activep
Definition global.c:159
gboolean * allocbool(int val)
allocate a gboolean * pointer
Definition global.c:266
int frag_update
Definition global.c:170
double * allocdouble(int val)
allocate a double * pointer
Definition global.c:471
int bonds_update
Definition global.c:169
int * allocint(int val)
allocate an int * pointer
Definition global.c:326
gboolean ** allocdbool(int xal, int yal)
allocate a gboolean ** pointer
Definition global.c:282
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:272
chemical_data * active_chem
Definition project.c:48
#define STEP_LIMIT
Definition global.h:249
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:271
#define RI
Definition global.h:300
box_info * active_box
Definition project.c:51
#define BD
Definition global.h:298
void widget_set_sensitive(GtkWidget *widg, gboolean sensitive)
Set sensitivity for a GtkWidget, ensuring it is a GtkWidget.
Definition gtk-misc.c:186
#define CHEM_M
Definition global.h:270
#define min(a, b)
Definition global.h:75
#define CHEM_X
Definition global.h:273
#define CHEM_Z
Definition global.h:269
#define SP
Definition global.h:302
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:301
image * active_image
Definition project.c:52
#define max(a, b)
Definition global.h:74
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:1129
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:284
void update_all_menus(glwin *view, int nats)
update all menus of the OpenGL window
Definition glwindow.c:239
int check_label_numbers(project *this_proj, int types)
check how many atom label(s) are visible
Definition popup.c:1039
void init_shaders(glwin *view)
initialize all the OpenGL shaders
@ EDITION
Definition glview.h:158
@ INSERT
Definition glview.h:227
#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:69
Functions declaration to read atomic coordinates.
Definition glwin.h:114
Definition global.h:839
double z
Definition global.h:845
double y
Definition global.h:844
double x
Definition global.h:843
double * z
Definition cbuild_edit.h:42
int id
Definition global.h:893
Definition global.h:98
int b
Definition global.h:100
int c
Definition global.h:101
int a
Definition global.h:99
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.