atomes 1.1.14
atomes: an atomic scale modeling tool box
Loading...
Searching...
No Matches
atom_geo.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: 'atom_geo.c'
24*
25* Contains:
26*
27
28 - The functions to check for the appropriate atomic coordinations
29
30*
31* List of functions:
32
33 int is_this_a_new_geo (int id, coord_info * obj, int * old_z, int old_geo, int old_sp, int new_sp, coord_info * coord, double * new_z);
34
35 gboolean is_in_atom_list (int aid, atom * new_list);
36
37 void sort_partial_geo (int ** geom, int num_a);
38 void check_coord_modification (project * this_proj, int * old_id, atom * new_list,
39 atomic_object * this_object, gboolean movtion, gboolean passivating);
40*/
41
42#include "atom_edit.h"
43
52void sort_partial_geo (int ** geom, int num_a)
53{
54 int i, j, k, l;
55
56 for(i=0;i<num_a;i++)
57 {
58 for(j=i+1;j<num_a;j++)
59 {
60 if(geom[i][0] > geom[j][0])
61 {
62 for (k=0; k<2; k++)
63 {
64 l = geom[i][k];
65 geom[i][k] = geom[j][k];
66 geom[j][k] = l;
67 }
68 }
69 }
70 }
71}
72
87int is_this_a_new_geo (int gid, coord_info * obj, int * old_z, int old_geo, int old_sp, int new_sp, coord_info * coord, double * new_z)
88{
89 int i, j, k, l, m, n, o;
90 int ** n_part, ** o_part;
91
92 // Number of coord of type id for spec new_sp
93 i = coord -> ntg[gid][new_sp];
94 // Using j to store the total number of neighbor(s) for the coordination to test
95 // Using k to store the number of type(s) of neighbor(s) for the coordination to test
96 j = k = 0;
97 for (l=0; l<obj -> species; l++)
98 {
99 if (obj -> partial_geo[old_sp][old_geo][l])
100 {
101 k ++;
102 j += obj -> partial_geo[old_sp][old_geo][l];
103 }
104 }
105 // Then comparing with already stored data in coord
106 for (l=0; l<i; l++)
107 {
108 switch (gid)
109 {
110 case 0:
111 if (coord -> geolist[gid][new_sp][l] == obj -> geolist[gid][old_sp][old_geo]) return l;
112 break;
113 case 1:
114 m = 0;
115 n = 0;
116 for (o=0; o<coord -> species; o++)
117 {
118 if (coord -> partial_geo[new_sp][l][o])
119 {
120 m ++;
121 n += coord -> partial_geo[new_sp][l][o];
122 }
123 }
124 if (j == n && k == m)
125 {
126 // Same number of atoms in the coordination for the spec
127 // 2 structures of size l: [0]= Z, [1] = nato
128 // Sort by Z, then comparing
129 n_part = allocdint (m, 2);
130 o_part = allocdint (m, 2);
131 m = 0;
132 for (n=0; n<coord -> species; n++)
133 {
134 if (coord -> partial_geo[new_sp][l][n])
135 {
136 n_part[m][0] = (int)new_z[n];
137 n_part[m][1] = coord -> partial_geo[new_sp][l][n];
138 m ++;
139 }
140 }
141 if (m > 1) sort_partial_geo (n_part, m);
142 m = 0;
143 for (n=0; n<obj -> species; n++)
144 {
145 if (obj -> partial_geo[old_sp][old_geo][n])
146 {
147 o_part[m][0] = old_z[n];
148 o_part[m][1] = obj -> partial_geo[old_sp][old_geo][n];
149 m ++;
150 }
151 }
152 if (m > 1) sort_partial_geo (o_part, m);
153 n = 1;
154 for (o=0; o<m; o++)
155 {
156 if (o_part[o][0] != n_part[o][0] || o_part[o][1] != n_part[o][1])
157 {
158 n = 0;
159 break;
160 }
161 }
162 g_free (n_part);
163 g_free (o_part);
164 if (n) return l;
165 }
166 break;
167 }
168 }
169
170 // If we keep going then this is a new type of coordination sphere
171 j = coord -> ntg[gid][new_sp];
172 if (! gid)
173 {
174 coord -> geolist[gid][new_sp] = g_realloc (coord -> geolist[gid][new_sp], (j+1)*sizeof*coord -> geolist[gid][new_sp]);
175 coord -> geolist[gid][new_sp][coord -> ntg[gid][new_sp]] = obj -> geolist[gid][old_sp][old_geo];
176 }
177 else
178 {
179 coord -> partial_geo[new_sp] = g_realloc (coord -> partial_geo[new_sp], (j+1)*sizeof*coord -> partial_geo[new_sp]);
180 coord -> partial_geo[new_sp][j] = allocint (coord -> species);
181 for (k=0; k<obj -> species; k++)
182 {
183 if (old_z[k])
184 {
185 l = find_spec_id (coord -> species, old_z[k], new_z);
186 coord -> partial_geo[new_sp][j][l] = obj -> partial_geo[old_sp][old_geo][k];
187 }
188 }
189 }
190 coord -> ntg[gid][new_sp] ++;
191 coord -> totcoord[gid] ++;
192 return i;
193}
194
209int find_this_geo_id (int gid, coord_info * obj, int * old_z, int old_geo, int old_sp, int new_sp, coord_info * coord, double * new_z)
210{
211 int i, j, k, l, m, n, o;
212 int ** n_part, ** o_part;
213
214 // Number of coord of type id for spec new_sp
215 i = coord -> ntg[gid][new_sp];
216 if (gid)
217 {
218 // Using j to store the total number of neighbor(s) for the coordination to test
219 // Using k to store the number of type(s) of neighbor(s) for the coordination to test
220 j = k = 0;
221 for (l=0; l<obj -> species; l++)
222 {
223 if (obj -> partial_geo[old_sp][old_geo][l])
224 {
225 k ++;
226 j += obj -> partial_geo[old_sp][old_geo][l];
227 }
228 }
229 }
230
231 // Then comparing with already stored data in coord
232 for (l=0; l<coord -> ntg[gid][new_sp]; l++)
233 {
234 switch (gid)
235 {
236 case 0:
237 if (coord -> geolist[0][new_sp][l] == obj -> geolist[0][old_sp][old_geo]) return l;
238 break;
239 case 1:
240 m = 0;
241 n = 0;
242 for (o=0; o<coord -> species; o++)
243 {
244 if (coord -> partial_geo[new_sp][l][o])
245 {
246 m ++;
247 n += coord -> partial_geo[new_sp][l][o];
248 }
249 }
250 if (j == n && k == m)
251 {
252 // Same number of atoms in the coordination for the spec
253 // 2 structures of size l: [0]= Z, [1] = nato
254 // Sort by Z, then comparing
255 n_part = allocdint (m, 2);
256 o_part = allocdint (m, 2);
257 m = 0;
258 for (n=0; n<coord -> species; n++)
259 {
260 if (coord -> partial_geo[new_sp][l][n])
261 {
262 n_part[m][0] = (int)new_z[n];
263 n_part[m][1] = coord -> partial_geo[new_sp][l][n];
264 m ++;
265 }
266 }
267 if (m > 1) sort_partial_geo (n_part, m);
268 m = 0;
269 for (n=0; n<obj -> species; n++)
270 {
271 if (obj -> partial_geo[old_sp][old_geo][n])
272 {
273 o_part[m][0] = old_z[n];
274 o_part[m][1] = obj -> partial_geo[old_sp][old_geo][n];
275 m ++;
276 }
277 }
278 if (m > 1) sort_partial_geo (o_part, m);
279 n = 1;
280 for (o=0; o<m; o++)
281 {
282 if (o_part[o][0] != n_part[o][0] || o_part[o][1] != n_part[o][1])
283 {
284 n = 0;
285 break;
286 }
287 }
288 g_free (n_part);
289 g_free (o_part);
290 if (n) return l;
291 }
292 break;
293 }
294 }
295
296 // If we keep going then this is a new type of coordination sphere
297 j = coord -> ntg[gid][new_sp];
298 coord -> geolist[gid][new_sp] = g_realloc (coord -> geolist[gid][new_sp], (j+1)*sizeof*coord -> geolist[gid][new_sp]);
299 coord -> geolist[gid][new_sp][j] = obj -> geolist[gid][old_sp][old_geo];
300 if (gid)
301 {
302 coord -> partial_geo[new_sp] = g_realloc (coord -> partial_geo[new_sp], (j+1)*sizeof*coord -> partial_geo[new_sp]);
303 coord -> partial_geo[new_sp][j] = allocint (coord -> species);
304 for (k=0; k<obj -> species; k++)
305 {
306 if (old_z[k])
307 {
308 l = find_spec_id (coord -> species, old_z[k], new_z);
309 coord -> partial_geo[new_sp][j][l] = obj -> partial_geo[old_sp][old_geo][k];
310 }
311 }
312 }
313 coord -> ntg[gid][new_sp] ++;
314 coord -> totcoord[gid] ++;
315 return i;
316}
317
331void check_coord_modification (project * this_proj, int * old_id, atom * new_list,
332 atomic_object * this_object, gboolean movtion, gboolean passivating)
333{
334 atom * tmp_new;
335 int g, h, i, j, k, l, m, n;
336 gboolean correct_it;
337 int * new_z = allocint (this_proj -> nspec);
338 double * old_z;
339 if (this_object) old_z = duplicate_double (this_proj -> nspec, this_proj -> chemistry -> chem_prop[CHEM_Z]);
340 int * new_old_id;
341 int * nvois = allocint (this_proj -> nspec);
342 if (passivating) new_old_id = duplicate_int (this_proj -> natomes, old_id);
343 for (i=0; i<this_proj -> nspec; i++)
344 {
345 new_z[i] = (int)this_proj -> chemistry -> chem_prop[CHEM_Z][i];
346 }
347
348 // first create a dummy coord structure to store an atom individual data
349 coord_info * new_coord = g_malloc0 (sizeof*new_coord);
350 for (i=0; i<2; i++)
351 {
352 new_coord -> totcoord[i] = 1;
353 new_coord -> ntg[i] = allocint (this_proj -> nspec);
354 for (j=0; j<this_proj -> nspec; j++) new_coord -> ntg[i][j] = 1;
355 new_coord -> geolist[i] = allocdint (this_proj -> nspec, 1);
356 }
357 new_coord -> species = this_proj -> nspec;
358 new_coord -> partial_geo = alloctint (this_proj -> nspec, 1, this_proj -> nspec);
359 g = (passivating) ? 2 : 1;
360 for (h=0; h<g; h++)
361 {
362 tmp_new = new_list;
363 while (tmp_new)
364 {
365 i = tmp_new -> sp;
366 // Fill the dummy coord with the new atom information
367 for (j=0; j<2; j++) new_coord -> geolist[j][i][0] = tmp_new -> numv;
368 k = tmp_new -> coord[1];
369 for (j=0; j<this_proj -> nspec; j++)
370 {
371 new_coord -> partial_geo[i][0][j] = this_proj -> coord -> partial_geo[i][k][j];
372 }
373 j = tmp_new -> id;
374 correct_it = FALSE;
375 if (movtion)
376 {
377 for (k=0; k<tmp_new -> numv; k++)
378 {
379 l = tmp_new -> vois[k];
380 if ((old_id[j] > 0 && old_id[l] < 0) || (old_id[j] < 0 && old_id[l] > 0))
381 {
382 correct_it = TRUE;
383 // This neighbor will be moved / removed
384 if (! passivating || h)
385 {
386 m = this_proj -> atoms[0][l].sp;
387 // For the atom studied reduce the number of neighbors of that species:
388 new_coord -> partial_geo[i][0][m] --;
389 for (n=0; n<2; n++) new_coord -> geolist[n][i][0] --;
390 }
391 }
392 }
393 }
394 else
395 {
396 for (k=0; k<this_proj -> nspec; k++) nvois[k]=0;
397 for (k=0; k<tmp_new -> numv; k++)
398 {
399 l = tmp_new -> vois[k];
400 m = this_object -> at_list[l].sp;
401 nvois[m] ++;
402 }
403 l = 0;
404 for (k=0; k<this_proj -> nspec; k++)
405 {
406 if (nvois[k] != new_coord -> partial_geo[i][0][k])
407 {
408 correct_it = TRUE;
409 new_coord -> partial_geo[i][0][k] = nvois[k];
410 }
411 l += nvois[k];
412 }
413 for (k=0; k<2; k++) new_coord -> geolist[k][i][0] = l;
414 }
415
416 if (correct_it)
417 {
418 if (passivating && ! h)
419 {
420 if (old_id[j])
421 {
422 switch (this_proj -> modelgl -> search_widg[8] -> filter)
423 {
424 case 0:
425 l = i;
426 break;
427 case 1:
428 l = tmp_new -> numv;
429 break;
430 case 2:
431 l = tmp_new -> coord[1];
432 for (m=0; m<i; m++) l += this_proj -> coord -> ntg[1][m];
433 break;
434 default:
435 l = tmp_new -> coord[this_proj -> modelgl -> search_widg[8] -> filter-1];
436 break;
437 }
438 if (get_atomic_object_by_origin (this_proj -> modelgl -> atom_win -> to_be_inserted[3], l, 0)) new_old_id[j] = abs(old_id[j]);
439 }
440 }
441 else
442 {
443 for (j=0; j<2; j++)
444 {
445 if (this_object)
446 {
447 tmp_new -> coord[j] = find_this_geo_id (j, new_coord, new_z, 0, i, i, this_object -> coord, old_z);
448 }
449 else
450 {
451 tmp_new -> coord[j] = find_this_geo_id (j, new_coord, new_z, 0, i, i, this_proj -> modelgl -> atom_win -> coord, this_proj -> modelgl -> atom_win -> new_z);
452 }
453 }
454 }
455 correct_it = FALSE;
456 }
457 tmp_new = tmp_new -> next;
458 }
459 if (passivating && ! h)
460 {
461 for (i=0; i<this_proj -> natomes; i++) old_id[i] = new_old_id[i];
462 g_free (new_old_id);
463 }
464 }
465 if (this_object) g_free (old_z);
466 g_free (new_coord);
467 g_free (nvois);
468}
Function declarations for the mode edition window.
int find_spec_id(int s, int z, double *list_z)
find species id based on Z
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
int find_this_geo_id(int gid, coord_info *obj, int *old_z, int old_geo, int old_sp, int new_sp, coord_info *coord, double *new_z)
if required create a new geometry, stored in coord, for coordination type 'gid' and chemical species ...
Definition atom_geo.c:209
int is_this_a_new_geo(int gid, coord_info *obj, int *old_z, int old_geo, int old_sp, int new_sp, coord_info *coord, double *new_z)
if required create a new geometry, stored in coord, for coordination type 'gid' and chemical species ...
Definition atom_geo.c:87
void sort_partial_geo(int **geom, int num_a)
sort partial geometries
Definition atom_geo.c:52
void check_coord_modification(project *this_proj, int *old_id, atom *new_list, atomic_object *this_object, gboolean movtion, gboolean passivating)
check atom coordination modification on edition
Definition atom_geo.c:331
GtkFileFilter * filter[NCFORMATS+1]
Definition callbacks.c:1406
integer(kind=c_int) function chemistry()
Definition chemistry.F90:22
int atoms[NUM_STYLES][2]
int * duplicate_int(int num, int *old_val)
copy a list of int
Definition global.c:572
int ** allocdint(int xal, int yal)
allocate an int ** pointer
Definition global.c:342
double * duplicate_double(int num, double *old_val)
copy a list of double
Definition global.c:620
int *** alloctint(int xal, int yal, int zal)
allocate an int *** pointer
Definition global.c:365
int * allocint(int val)
allocate an int * pointer
Definition global.c:326
#define CHEM_Z
Definition global.h:269
Definition global.h:839