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