1 /* Copyright (C) 2008 Atsushi Togo */
2 /* All rights reserved. */
3 
4 /* This file is part of spglib. */
5 
6 /* Redistribution and use in source and binary forms, with or without */
7 /* modification, are permitted provided that the following conditions */
8 /* are met: */
9 
10 /* * Redistributions of source code must retain the above copyright */
11 /*   notice, this list of conditions and the following disclaimer. */
12 
13 /* * Redistributions in binary form must reproduce the above copyright */
14 /*   notice, this list of conditions and the following disclaimer in */
15 /*   the documentation and/or other materials provided with the */
16 /*   distribution. */
17 
18 /* * Neither the name of the spglib project nor the names of its */
19 /*   contributors may be used to endorse or promote products derived */
20 /*   from this software without specific prior written permission. */
21 
22 /* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */
23 /* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT */
24 /* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS */
25 /* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE */
26 /* COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, */
27 /* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, */
28 /* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; */
29 /* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER */
30 /* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT */
31 /* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN */
32 /* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE */
33 /* POSSIBILITY OF SUCH DAMAGE. */
34 
35 #include <stdio.h>
36 #include <stdlib.h>
37 #include <string.h>
38 #include <stddef.h>
39 #include "arithmetic.h"
40 #include "cell.h"
41 #include "debug.h"
42 #include "delaunay.h"
43 #include "determination.h"
44 #include "kgrid.h"
45 #include "kpoint.h"
46 #include "mathfunc.h"
47 #include "niggli.h"
48 #include "pointgroup.h"
49 #include "spglib.h"
50 #include "primitive.h"
51 #include "refinement.h"
52 #include "spacegroup.h"
53 #include "spg_database.h"
54 #include "spin.h"
55 #include "symmetry.h"
56 #include "version.h"
57 
58 /*-------*/
59 /* error */
60 /*-------*/
61 static SpglibError spglib_error_code = SPGLIB_SUCCESS;
62 
63 typedef struct {
64   SpglibError error;
65   char *message;
66 } SpglibErrorMessage;
67 
68 static SpglibErrorMessage spglib_error_message[] = {
69   {SPGLIB_SUCCESS, "no error"},
70   {SPGERR_SPACEGROUP_SEARCH_FAILED, "spacegroup search failed"},
71   {SPGERR_CELL_STANDARDIZATION_FAILED, "cell standardization failed"},
72   {SPGERR_SYMMETRY_OPERATION_SEARCH_FAILED, "symmetry operation search failed"},
73   {SPGERR_ATOMS_TOO_CLOSE, "too close distance between atoms"},
74   {SPGERR_POINTGROUP_NOT_FOUND, "pointgroup not found"},
75   {SPGERR_NIGGLI_FAILED, "Niggli reduction failed"},
76   {SPGERR_DELAUNAY_FAILED, "Delaunay reduction failed"},
77   {SPGERR_ARRAY_SIZE_SHORTAGE, "array size shortage"},
78   {SPGERR_NONE, ""},
79 };
80 
81 /*---------*/
82 /* general */
83 /*---------*/
84 static SpglibDataset * get_dataset(SPGCONST double lattice[3][3],
85                                    SPGCONST double position[][3],
86                                    const int types[],
87                                    const int num_atom,
88                                    const int hall_number,
89                                    const double symprec,
90                                    const double angle_tolerance);
91 static SpglibDataset * init_dataset(void);
92 static int set_dataset(SpglibDataset * dataset,
93                        const Cell * cell,
94                        const Primitive * primitive,
95                        SPGCONST Spacegroup * spacegroup,
96                        ExactStructure *exstr);
97 static int get_symmetry_from_dataset(int rotation[][3][3],
98                                      double translation[][3],
99                                      const int max_size,
100                                      SPGCONST double lattice[3][3],
101                                      SPGCONST double position[][3],
102                                      const int types[],
103                                      const int num_atom,
104                                      const double symprec,
105                                      const double angle_tolerance);
106 static int get_symmetry_with_site_tensors(int rotation[][3][3],
107                                           double translation[][3],
108                                           int equivalent_atoms[],
109                                           double primitive_lattice[3][3],
110                                           int *spin_flips,
111                                           const int run_symmetry_search,
112                                           const int num_operations,
113                                           SPGCONST double lattice[3][3],
114                                           SPGCONST double position[][3],
115                                           const int types[],
116                                           const double *tensors,
117                                           const int tensor_rank,
118                                           const int num_atom,
119                                           const int is_magnetic,
120                                           const double symprec,
121                                           const double angle_tolerance);
122 static int get_multiplicity(SPGCONST double lattice[3][3],
123                             SPGCONST double position[][3],
124                             const int types[],
125                             const int num_atom,
126                             const double symprec,
127                             const double angle_tolerance);
128 static int standardize_primitive(double lattice[3][3],
129                                  double position[][3],
130                                  int types[],
131                                  const int num_atom,
132                                  const double symprec,
133                                  const double angle_tolerance);
134 static int standardize_cell(double lattice[3][3],
135                             double position[][3],
136                             int types[],
137                             const int num_atom,
138                             const int num_array_size,
139                             const double symprec,
140                             const double angle_tolerance);
141 static int get_standardized_cell(double lattice[3][3],
142                                  double position[][3],
143                                  int types[],
144                                  const int num_atom,
145                                  const int num_array_size,
146                                  const int to_primitive,
147                                  const double symprec,
148                                  const double angle_tolerance);
149 static Centering get_centering(int hall_number);
150 static void set_cell(double lattice[3][3],
151                      double position[][3],
152                      int types[],
153                      Cell * cell);
154 static int get_international(char symbol[11],
155                              SPGCONST double lattice[3][3],
156                              SPGCONST double position[][3],
157                              const int types[],
158                              const int num_atom,
159                              const double symprec,
160                              const double angle_tolerance);
161 static int get_schoenflies(char symbol[7],
162                            SPGCONST double lattice[3][3],
163                            SPGCONST double position[][3],
164                            const int types[], const int num_atom,
165                            const double symprec,
166                            const double angle_tolerance);
167 
168 /*---------*/
169 /* kpoints */
170 /*---------*/
171 static int get_ir_reciprocal_mesh(int grid_address[][3],
172                                   int ir_mapping_table[],
173                                   const int mesh[3],
174                                   const int is_shift[3],
175                                   const int is_time_reversal,
176                                   SPGCONST double lattice[3][3],
177                                   SPGCONST double position[][3],
178                                   const int types[],
179                                   const int num_atom,
180                                   const double symprec,
181                                   const double angle_tolerance);
182 static size_t get_dense_ir_reciprocal_mesh(int grid_address[][3],
183                                            size_t ir_mapping_table[],
184                                            const int mesh[3],
185                                            const int is_shift[3],
186                                            const int is_time_reversal,
187                                            SPGCONST double lattice[3][3],
188                                            SPGCONST double position[][3],
189                                            const int types[],
190                                            const size_t num_atom,
191                                            const double symprec,
192                                            const double angle_tolerance);
193 
194 static int get_stabilized_reciprocal_mesh(int grid_address[][3],
195                                           int ir_mapping_table[],
196                                           const int mesh[3],
197                                           const int is_shift[3],
198                                           const int is_time_reversal,
199                                           const int num_rot,
200                                           SPGCONST int rotations[][3][3],
201                                           const size_t num_q,
202                                           SPGCONST double qpoints[][3]);
203 static size_t get_dense_stabilized_reciprocal_mesh(int grid_address[][3],
204                                                    size_t ir_mapping_table[],
205                                                    const int mesh[3],
206                                                    const int is_shift[3],
207                                                    const int is_time_reversal,
208                                                    const size_t num_rot,
209                                                    SPGCONST int rotations[][3][3],
210                                                    const size_t num_q,
211                                                    SPGCONST double qpoints[][3]);
212 
213 /*========*/
214 /* global */
215 /*========*/
216 
217 /*-----------------------------------------*/
218 /* Version: spglib-[major].[minor].[micro] */
219 /*-----------------------------------------*/
spg_get_major_version(void)220 int spg_get_major_version(void)
221 {
222   spglib_error_code = SPGLIB_SUCCESS;
223   return SPGLIB_MAJOR_VERSION;
224 }
225 
spg_get_minor_version(void)226 int spg_get_minor_version(void)
227 {
228   spglib_error_code = SPGLIB_SUCCESS;
229   return SPGLIB_MINOR_VERSION;
230 }
231 
spg_get_micro_version(void)232 int spg_get_micro_version(void)
233 {
234   spglib_error_code = SPGLIB_SUCCESS;
235   return SPGLIB_MICRO_VERSION;
236 }
237 
238 /*-------*/
239 /* error */
240 /*-------*/
spg_get_error_code(void)241 SpglibError spg_get_error_code(void)
242 {
243   return spglib_error_code;
244 }
245 
spg_get_error_message(SpglibError error)246 char * spg_get_error_message(SpglibError error)
247 {
248   int i;
249 
250   for (i = 0; i < 100; i++) {
251     if (SPGERR_NONE == spglib_error_message[i].error) {
252       break;
253     }
254 
255     if (error == spglib_error_message[i].error) {
256       return spglib_error_message[i].message;
257     }
258   }
259 
260   return NULL;
261 }
262 
263 /*---------*/
264 /* general */
265 /*---------*/
266 /* Return NULL if failed */
spg_get_dataset(SPGCONST double lattice[3][3],SPGCONST double position[][3],const int types[],const int num_atom,const double symprec)267 SpglibDataset * spg_get_dataset(SPGCONST double lattice[3][3],
268                                 SPGCONST double position[][3],
269                                 const int types[],
270                                 const int num_atom,
271                                 const double symprec)
272 {
273   return get_dataset(lattice,
274                      position,
275                      types,
276                      num_atom,
277                      0,
278                      symprec,
279                      -1.0);
280 }
281 
282 /* Return NULL if failed */
spgat_get_dataset(SPGCONST double lattice[3][3],SPGCONST double position[][3],const int types[],const int num_atom,const double symprec,const double angle_tolerance)283 SpglibDataset * spgat_get_dataset(SPGCONST double lattice[3][3],
284                                   SPGCONST double position[][3],
285                                   const int types[],
286                                   const int num_atom,
287                                   const double symprec,
288                                   const double angle_tolerance)
289 {
290   return get_dataset(lattice,
291                      position,
292                      types,
293                      num_atom,
294                      0,
295                      symprec,
296                      angle_tolerance);
297 }
298 
299 /* Return NULL if failed */
spg_get_dataset_with_hall_number(SPGCONST double lattice[3][3],SPGCONST double position[][3],const int types[],const int num_atom,const int hall_number,const double symprec)300 SpglibDataset * spg_get_dataset_with_hall_number(SPGCONST double lattice[3][3],
301                                                  SPGCONST double position[][3],
302                                                  const int types[],
303                                                  const int num_atom,
304                                                  const int hall_number,
305                                                  const double symprec)
306 {
307   return get_dataset(lattice,
308                      position,
309                      types,
310                      num_atom,
311                      hall_number,
312                      symprec,
313                      -1.0);
314 }
315 
316 /* Return NULL if failed */
317 SpglibDataset *
spgat_get_dataset_with_hall_number(SPGCONST double lattice[3][3],SPGCONST double position[][3],const int types[],const int num_atom,const int hall_number,const double symprec,const double angle_tolerance)318 spgat_get_dataset_with_hall_number(SPGCONST double lattice[3][3],
319                                    SPGCONST double position[][3],
320                                    const int types[],
321                                    const int num_atom,
322                                    const int hall_number,
323                                    const double symprec,
324                                    const double angle_tolerance)
325 {
326   return get_dataset(lattice,
327                      position,
328                      types,
329                      num_atom,
330                      hall_number,
331                      symprec,
332                      angle_tolerance);
333 }
334 
spg_free_dataset(SpglibDataset * dataset)335 void spg_free_dataset(SpglibDataset *dataset)
336 {
337   if (dataset->n_operations > 0) {
338     free(dataset->rotations);
339     dataset->rotations = NULL;
340     free(dataset->translations);
341     dataset->translations = NULL;
342     dataset->n_operations = 0;
343   }
344 
345   if (dataset->n_atoms > 0) {
346     free(dataset->wyckoffs);
347     dataset->wyckoffs = NULL;
348     free(dataset->equivalent_atoms);
349     dataset->equivalent_atoms = NULL;
350     free(dataset->crystallographic_orbits);
351     dataset->crystallographic_orbits = NULL;
352     free(dataset->site_symmetry_symbols);
353     dataset->site_symmetry_symbols = NULL;
354     free(dataset->mapping_to_primitive);
355     dataset->mapping_to_primitive = NULL;
356     dataset->n_atoms = 0;
357   }
358 
359   if (dataset->n_std_atoms > 0) {
360     free(dataset->std_positions);
361     dataset->std_positions = NULL;
362     free(dataset->std_types);
363     dataset->std_types = NULL;
364     free(dataset->std_mapping_to_primitive);
365     dataset->std_mapping_to_primitive = NULL;
366     dataset->n_std_atoms = 0;
367   }
368 
369   dataset->spacegroup_number = 0;
370   dataset->hall_number = 0;
371   strcpy(dataset->international_symbol, "");
372   strcpy(dataset->hall_symbol, "");
373   strcpy(dataset->choice, "");
374 
375   free(dataset);
376 }
377 
378 /* Return 0 if failed */
spg_get_symmetry(int rotation[][3][3],double translation[][3],const int max_size,SPGCONST double lattice[3][3],SPGCONST double position[][3],const int types[],const int num_atom,const double symprec)379 int spg_get_symmetry(int rotation[][3][3],
380                      double translation[][3],
381                      const int max_size,
382                      SPGCONST double lattice[3][3],
383                      SPGCONST double position[][3],
384                      const int types[],
385                      const int num_atom,
386                      const double symprec)
387 {
388   return get_symmetry_from_dataset(rotation,
389                                    translation,
390                                    max_size,
391                                    lattice,
392                                    position,
393                                    types,
394                                    num_atom,
395                                    symprec,
396                                    -1.0);
397 }
398 
399 /* Return 0 if failed */
spgat_get_symmetry(int rotation[][3][3],double translation[][3],const int max_size,SPGCONST double lattice[3][3],SPGCONST double position[][3],const int types[],const int num_atom,const double symprec,const double angle_tolerance)400 int spgat_get_symmetry(int rotation[][3][3],
401                        double translation[][3],
402                        const int max_size,
403                        SPGCONST double lattice[3][3],
404                        SPGCONST double position[][3],
405                        const int types[],
406                        const int num_atom,
407                        const double symprec,
408                        const double angle_tolerance)
409 {
410   return get_symmetry_from_dataset(rotation,
411                                    translation,
412                                    max_size,
413                                    lattice,
414                                    position,
415                                    types,
416                                    num_atom,
417                                    symprec,
418                                    angle_tolerance);
419 }
420 
421 /* Return 0 if failed */
spg_get_symmetry_with_collinear_spin(int rotation[][3][3],double translation[][3],int equivalent_atoms[],const int max_size,SPGCONST double lattice[3][3],SPGCONST double position[][3],const int types[],const double spins[],const int num_atom,const double symprec)422 int spg_get_symmetry_with_collinear_spin(int rotation[][3][3],
423                                          double translation[][3],
424                                          int equivalent_atoms[],
425                                          const int max_size,
426                                          SPGCONST double lattice[3][3],
427                                          SPGCONST double position[][3],
428                                          const int types[],
429                                          const double spins[],
430                                          const int num_atom,
431                                          const double symprec)
432 {
433   int succeeded;
434   double primitive_lattice[3][3];
435   int *spin_flips;
436 
437   if ((spin_flips = (int*) malloc(sizeof(int) * max_size))
438       == NULL) {
439     warning_print("spglib: Memory could not be allocated.");
440     return 0;
441   }
442 
443   succeeded = get_symmetry_with_site_tensors(rotation,
444                                              translation,
445                                              equivalent_atoms,
446                                              primitive_lattice,
447                                              spin_flips,
448                                              1,
449                                              max_size,
450                                              lattice,
451                                              position,
452                                              types,
453                                              spins,
454                                              0,
455                                              num_atom,
456                                              1,
457                                              symprec,
458                                              -1.0);
459   free(spin_flips);
460   spin_flips = NULL;
461 
462   return succeeded;
463 }
464 
465 /* Return 0 if failed */
spgat_get_symmetry_with_collinear_spin(int rotation[][3][3],double translation[][3],int equivalent_atoms[],const int max_size,SPGCONST double lattice[3][3],SPGCONST double position[][3],const int types[],const double spins[],const int num_atom,const double symprec,const double angle_tolerance)466 int spgat_get_symmetry_with_collinear_spin(int rotation[][3][3],
467                                            double translation[][3],
468                                            int equivalent_atoms[],
469                                            const int max_size,
470                                            SPGCONST double lattice[3][3],
471                                            SPGCONST double position[][3],
472                                            const int types[],
473                                            const double spins[],
474                                            const int num_atom,
475                                            const double symprec,
476                                            const double angle_tolerance)
477 {
478   int succeeded;
479   double primitive_lattice[3][3];
480   int *spin_flips;
481 
482   if ((spin_flips = (int*) malloc(sizeof(int) * max_size))
483       == NULL) {
484     warning_print("spglib: Memory could not be allocated.");
485     return 0;
486   }
487 
488   succeeded = get_symmetry_with_site_tensors(rotation,
489                                              translation,
490                                              equivalent_atoms,
491                                              primitive_lattice,
492                                              spin_flips,
493                                              1,
494                                              max_size,
495                                              lattice,
496                                              position,
497                                              types,
498                                              spins,
499                                              0,
500                                              num_atom,
501                                              1,
502                                              symprec,
503                                              angle_tolerance);
504 
505   free(spin_flips);
506   spin_flips = NULL;
507 
508   return succeeded;
509 }
510 
511 /* Return 0 if failed */
spg_get_symmetry_with_site_tensors(int rotation[][3][3],double translation[][3],int equivalent_atoms[],double primitive_lattice[3][3],int * spin_flips,const int num_operations,SPGCONST double lattice[3][3],SPGCONST double position[][3],const int types[],const double * tensors,const int tensor_rank,const int num_atom,const int is_magnetic,const double symprec)512 int spg_get_symmetry_with_site_tensors(int rotation[][3][3],
513                                        double translation[][3],
514                                        int equivalent_atoms[],
515                                        double primitive_lattice[3][3],
516                                        int *spin_flips,
517                                        const int num_operations,
518                                        SPGCONST double lattice[3][3],
519                                        SPGCONST double position[][3],
520                                        const int types[],
521                                        const double *tensors,
522                                        const int tensor_rank,
523                                        const int num_atom,
524                                        const int is_magnetic,
525                                        const double symprec)
526 {
527   return get_symmetry_with_site_tensors(rotation,
528                                         translation,
529                                         equivalent_atoms,
530                                         primitive_lattice,
531                                         spin_flips,
532                                         0,
533                                         num_operations,
534                                         lattice,
535                                         position,
536                                         types,
537                                         tensors,
538                                         tensor_rank,
539                                         num_atom,
540                                         is_magnetic,
541                                         symprec,
542                                         -1.0);
543 }
544 
spgat_get_symmetry_with_site_tensors(int rotation[][3][3],double translation[][3],int equivalent_atoms[],double primitive_lattice[3][3],int * spin_flips,const int num_operations,SPGCONST double lattice[3][3],SPGCONST double position[][3],const int types[],const double * tensors,const int tensor_rank,const int num_atom,const int is_magnetic,const double symprec,const double angle_tolerance)545 int spgat_get_symmetry_with_site_tensors(int rotation[][3][3],
546                                          double translation[][3],
547                                          int equivalent_atoms[],
548                                          double primitive_lattice[3][3],
549                                          int *spin_flips,
550                                          const int num_operations,
551                                          SPGCONST double lattice[3][3],
552                                          SPGCONST double position[][3],
553                                          const int types[],
554                                          const double *tensors,
555                                          const int tensor_rank,
556                                          const int num_atom,
557                                          const int is_magnetic,
558                                          const double symprec,
559                                          const double angle_tolerance)
560 {
561   return get_symmetry_with_site_tensors(rotation,
562                                         translation,
563                                         equivalent_atoms,
564                                         primitive_lattice,
565                                         spin_flips,
566                                         0,
567                                         num_operations,
568                                         lattice,
569                                         position,
570                                         types,
571                                         tensors,
572                                         tensor_rank,
573                                         num_atom,
574                                         is_magnetic,
575                                         symprec,
576                                         angle_tolerance);
577 }
578 
spg_get_hall_number_from_symmetry(SPGCONST int rotation[][3][3],SPGCONST double translation[][3],const int num_operations,const double symprec)579 int spg_get_hall_number_from_symmetry(SPGCONST int rotation[][3][3],
580                                       SPGCONST double translation[][3],
581                                       const int num_operations,
582                                       const double symprec)
583 {
584   int i, hall_number;
585   Symmetry *symmetry;
586   Symmetry *prim_symmetry;
587 
588   symmetry = NULL;
589   prim_symmetry = NULL;
590   hall_number = 0;
591 
592   if ((symmetry = sym_alloc_symmetry(num_operations)) == NULL) {
593     return 0;
594   }
595 
596   for (i = 0; i < num_operations; i++) {
597     mat_copy_matrix_i3(symmetry->rot[i], rotation[i]);
598     mat_copy_vector_d3(symmetry->trans[i], translation[i]);
599   }
600 
601   prim_symmetry = prm_get_primitive_symmetry(symmetry, symprec);
602   sym_free_symmetry(symmetry);
603   symmetry = NULL;
604 
605   if (prim_symmetry == NULL) {
606     return 0;
607   }
608 
609   hall_number = spa_search_spacegroup_with_symmetry(prim_symmetry, symprec);
610 
611   if (hall_number) {
612     spglib_error_code = SPGLIB_SUCCESS;
613   } else {
614     spglib_error_code = SPGERR_SPACEGROUP_SEARCH_FAILED;
615   }
616 
617   sym_free_symmetry(prim_symmetry);
618   prim_symmetry = NULL;
619 
620   return hall_number;
621 }
622 
623 /* Return 0 if failed */
spg_get_multiplicity(SPGCONST double lattice[3][3],SPGCONST double position[][3],const int types[],const int num_atom,const double symprec)624 int spg_get_multiplicity(SPGCONST double lattice[3][3],
625                          SPGCONST double position[][3],
626                          const int types[],
627                          const int num_atom,
628                          const double symprec)
629 {
630   return get_multiplicity(lattice,
631                           position,
632                           types,
633                           num_atom,
634                           symprec,
635                           -1.0);
636 }
637 
638 /* Return 0 if failed */
spgat_get_multiplicity(SPGCONST double lattice[3][3],SPGCONST double position[][3],const int types[],const int num_atom,const double symprec,const double angle_tolerance)639 int spgat_get_multiplicity(SPGCONST double lattice[3][3],
640                            SPGCONST double position[][3],
641                            const int types[],
642                            const int num_atom,
643                            const double symprec,
644                            const double angle_tolerance)
645 {
646   return get_multiplicity(lattice,
647                           position,
648                           types,
649                           num_atom,
650                           symprec,
651                           angle_tolerance);
652 }
653 
654 /* Return 0 if failed */
spg_get_international(char symbol[11],SPGCONST double lattice[3][3],SPGCONST double position[][3],const int types[],const int num_atom,const double symprec)655 int spg_get_international(char symbol[11],
656                           SPGCONST double lattice[3][3],
657                           SPGCONST double position[][3],
658                           const int types[],
659                           const int num_atom,
660                           const double symprec)
661 {
662   return get_international(symbol,
663                            lattice,
664                            position,
665                            types,
666                            num_atom,
667                            symprec,
668                            -1.0);
669 }
670 
671 /* Return 0 if failed */
spgat_get_international(char symbol[11],SPGCONST double lattice[3][3],SPGCONST double position[][3],const int types[],const int num_atom,const double symprec,const double angle_tolerance)672 int spgat_get_international(char symbol[11],
673                             SPGCONST double lattice[3][3],
674                             SPGCONST double position[][3],
675                             const int types[],
676                             const int num_atom,
677                             const double symprec,
678                             const double angle_tolerance)
679 {
680   return get_international(symbol,
681                            lattice,
682                            position,
683                            types,
684                            num_atom,
685                            symprec,
686                            angle_tolerance);
687 }
688 
689 /* Return 0 if failed */
spg_get_schoenflies(char symbol[7],SPGCONST double lattice[3][3],SPGCONST double position[][3],const int types[],const int num_atom,const double symprec)690 int spg_get_schoenflies(char symbol[7],
691                         SPGCONST double lattice[3][3],
692                         SPGCONST double position[][3],
693                         const int types[],
694                         const int num_atom,
695                         const double symprec)
696 {
697   return get_schoenflies(symbol,
698                          lattice,
699                          position,
700                          types,
701                          num_atom,
702                          symprec,
703                          -1.0);
704 }
705 
706 /* Return 0 if failed */
spgat_get_schoenflies(char symbol[7],SPGCONST double lattice[3][3],SPGCONST double position[][3],const int types[],const int num_atom,const double symprec,const double angle_tolerance)707 int spgat_get_schoenflies(char symbol[7],
708                           SPGCONST double lattice[3][3],
709                           SPGCONST double position[][3],
710                           const int types[],
711                           const int num_atom,
712                           const double symprec,
713                           const double angle_tolerance)
714 {
715   return get_schoenflies(symbol,
716                          lattice,
717                          position,
718                          types,
719                          num_atom,
720                          symprec,
721                          angle_tolerance);
722 }
723 
724 /* Return 0 if failed */
spg_get_pointgroup(char symbol[6],int transform_mat[3][3],SPGCONST int rotations[][3][3],const int num_rotations)725 int spg_get_pointgroup(char symbol[6],
726                        int transform_mat[3][3],
727                        SPGCONST int rotations[][3][3],
728                        const int num_rotations)
729 {
730   Pointgroup pointgroup;
731 
732   pointgroup = ptg_get_transformation_matrix(transform_mat,
733                                              rotations,
734                                              num_rotations);
735 
736   if (pointgroup.number == 0) {
737     spglib_error_code = SPGERR_POINTGROUP_NOT_FOUND;
738     return 0;
739   }
740 
741   memcpy(symbol, pointgroup.symbol, 6);
742 
743   spglib_error_code = SPGLIB_SUCCESS;
744   return pointgroup.number;
745 }
746 
747 /* Return 0 if failed */
spg_get_symmetry_from_database(int rotations[192][3][3],double translations[192][3],const int hall_number)748 int spg_get_symmetry_from_database(int rotations[192][3][3],
749                                    double translations[192][3],
750                                    const int hall_number)
751 {
752   int i, size;
753   Symmetry *symmetry;
754 
755   symmetry = NULL;
756 
757   if ((symmetry = spgdb_get_spacegroup_operations(hall_number)) == NULL) {
758     goto err;
759   }
760 
761   for (i = 0; i < symmetry->size; i++) {
762     mat_copy_matrix_i3(rotations[i], symmetry->rot[i]);
763     mat_copy_vector_d3(translations[i], symmetry->trans[i]);
764   }
765   size = symmetry->size;
766 
767   sym_free_symmetry(symmetry);
768   symmetry = NULL;
769 
770   spglib_error_code = SPGLIB_SUCCESS;
771   return size;
772 
773  err:
774   spglib_error_code = SPGERR_SPACEGROUP_SEARCH_FAILED;
775   return 0;
776 }
777 
778 /* Return spglibtype.number = 0 if failed */
spg_get_spacegroup_type(const int hall_number)779 SpglibSpacegroupType spg_get_spacegroup_type(const int hall_number)
780 {
781   SpglibSpacegroupType spglibtype;
782   SpacegroupType spgtype;
783   Pointgroup pointgroup;
784   int arth_number;
785   char arth_symbol[7];
786 
787   spglibtype.number = 0;
788   strcpy(spglibtype.schoenflies, "");
789   strcpy(spglibtype.hall_symbol, "");
790   strcpy(spglibtype.choice, "");
791   strcpy(spglibtype.international, "");
792   strcpy(spglibtype.international_full, "");
793   strcpy(spglibtype.international_short, "");
794   strcpy(spglibtype.pointgroup_international, "");
795   strcpy(spglibtype.pointgroup_schoenflies, "");
796   spglibtype.arithmetic_crystal_class_number = 0;
797   strcpy(spglibtype.arithmetic_crystal_class_symbol, "");
798 
799   if (0 < hall_number && hall_number < 531) {
800     spgtype = spgdb_get_spacegroup_type(hall_number);
801     spglibtype.number = spgtype.number;
802     memcpy(spglibtype.schoenflies, spgtype.schoenflies, 7);
803     memcpy(spglibtype.hall_symbol, spgtype.hall_symbol, 17);
804     memcpy(spglibtype.choice, spgtype.choice, 6);
805     memcpy(spglibtype.international, spgtype.international, 32);
806     memcpy(spglibtype.international_full, spgtype.international_full, 20);
807     memcpy(spglibtype.international_short, spgtype.international_short, 11);
808     pointgroup = ptg_get_pointgroup(spgtype.pointgroup_number);
809     memcpy(spglibtype.pointgroup_international, pointgroup.symbol, 6);
810     memcpy(spglibtype.pointgroup_schoenflies, pointgroup.schoenflies, 4);
811     arth_number = arth_get_symbol(arth_symbol, spgtype.number);
812     spglibtype.arithmetic_crystal_class_number = arth_number;
813     memcpy(spglibtype.arithmetic_crystal_class_symbol, arth_symbol, 7);
814     spglib_error_code = SPGLIB_SUCCESS;
815   } else {
816     spglib_error_code = SPGERR_SPACEGROUP_SEARCH_FAILED;
817   }
818 
819   return spglibtype;
820 }
821 
822 /* Return 0 if failed */
spg_standardize_cell(double lattice[3][3],double position[][3],int types[],const int num_atom,const int to_primitive,const int no_idealize,const double symprec)823 int spg_standardize_cell(double lattice[3][3],
824                          double position[][3],
825                          int types[],
826                          const int num_atom,
827                          const int to_primitive,
828                          const int no_idealize,
829                          const double symprec)
830 {
831   return spgat_standardize_cell(lattice,
832                                 position,
833                                 types,
834                                 num_atom,
835                                 to_primitive,
836                                 no_idealize,
837                                 symprec,
838                                 -1.0);
839 }
840 
841 /* Return 0 if failed */
spgat_standardize_cell(double lattice[3][3],double position[][3],int types[],const int num_atom,const int to_primitive,const int no_idealize,const double symprec,const double angle_tolerance)842 int spgat_standardize_cell(double lattice[3][3],
843                            double position[][3],
844                            int types[],
845                            const int num_atom,
846                            const int to_primitive,
847                            const int no_idealize,
848                            const double symprec,
849                            const double angle_tolerance)
850 {
851   if (to_primitive) {
852     if (no_idealize) {
853       return get_standardized_cell(lattice,
854                                    position,
855                                    types,
856                                    num_atom,
857                                    0,
858                                    1,
859                                    symprec,
860                                    angle_tolerance);
861     } else {
862       return standardize_primitive(lattice,
863                                    position,
864                                    types,
865                                    num_atom,
866                                    symprec,
867                                    angle_tolerance);
868     }
869   } else {
870     if (no_idealize) {
871       return get_standardized_cell(lattice,
872                                    position,
873                                    types,
874                                    num_atom,
875                                    0,
876                                    0,
877                                    symprec,
878                                    angle_tolerance);
879     } else {
880       return standardize_cell(lattice,
881                               position,
882                               types,
883                               num_atom,
884                               0,
885                               symprec,
886                               angle_tolerance);
887     }
888   }
889 }
890 
891 /* Return 0 if failed */
spg_find_primitive(double lattice[3][3],double position[][3],int types[],const int num_atom,const double symprec)892 int spg_find_primitive(double lattice[3][3],
893                        double position[][3],
894                        int types[],
895                        const int num_atom,
896                        const double symprec)
897 {
898   return standardize_primitive(lattice,
899                                position,
900                                types,
901                                num_atom,
902                                symprec,
903                                -1.0);
904 }
905 
906 /* Return 0 if failed */
spgat_find_primitive(double lattice[3][3],double position[][3],int types[],const int num_atom,const double symprec,const double angle_tolerance)907 int spgat_find_primitive(double lattice[3][3],
908                          double position[][3],
909                          int types[],
910                          const int num_atom,
911                          const double symprec,
912                          const double angle_tolerance)
913 {
914   return standardize_primitive(lattice,
915                                position,
916                                types,
917                                num_atom,
918                                symprec,
919                                angle_tolerance);
920 }
921 
922 /* Return 0 if failed */
spg_refine_cell(double lattice[3][3],double position[][3],int types[],const int num_atom,const double symprec)923 int spg_refine_cell(double lattice[3][3],
924                     double position[][3],
925                     int types[],
926                     const int num_atom,
927                     const double symprec)
928 {
929   return standardize_cell(lattice,
930                           position,
931                           types,
932                           num_atom,
933                           0,
934                           symprec,
935                           -1.0);
936 }
937 
938 /* Return 0 if failed */
spgat_refine_cell(double lattice[3][3],double position[][3],int types[],const int num_atom,const double symprec,const double angle_tolerance)939 int spgat_refine_cell(double lattice[3][3],
940                       double position[][3],
941                       int types[],
942                       const int num_atom,
943                       const double symprec,
944                       const double angle_tolerance)
945 {
946   return standardize_cell(lattice,
947                           position,
948                           types,
949                           num_atom,
950                           0,
951                           symprec,
952                           angle_tolerance);
953 }
954 
spg_delaunay_reduce(double lattice[3][3],const double symprec)955 int spg_delaunay_reduce(double lattice[3][3], const double symprec)
956 {
957   int i, j, succeeded;
958   double red_lattice[3][3];
959 
960   succeeded = del_delaunay_reduce(red_lattice, lattice, symprec);
961 
962   if (succeeded) {
963     for (i = 0; i < 3; i++) {
964       for (j = 0; j < 3; j++) {
965         lattice[i][j] = red_lattice[i][j];
966       }
967     }
968     spglib_error_code = SPGLIB_SUCCESS;
969   } else {
970     spglib_error_code = SPGERR_DELAUNAY_FAILED;
971   }
972 
973   return succeeded;
974 }
975 
976 /*---------*/
977 /* kpoints */
978 /*---------*/
spg_get_grid_point_from_address(const int grid_address[3],const int mesh[3])979 int spg_get_grid_point_from_address(const int grid_address[3],
980                                     const int mesh[3])
981 {
982   int address_double[3];
983   int is_shift[3];
984 
985   is_shift[0] = 0;
986   is_shift[1] = 0;
987   is_shift[2] = 0;
988   kgd_get_grid_address_double_mesh(address_double,
989                                    grid_address,
990                                    mesh,
991                                    is_shift);
992   return kgd_get_grid_point_double_mesh(address_double, mesh);
993 }
994 
spg_get_dense_grid_point_from_address(const int grid_address[3],const int mesh[3])995 size_t spg_get_dense_grid_point_from_address(const int grid_address[3],
996                                              const int mesh[3])
997 {
998   int address_double[3];
999   int is_shift[3];
1000 
1001   is_shift[0] = 0;
1002   is_shift[1] = 0;
1003   is_shift[2] = 0;
1004   kgd_get_grid_address_double_mesh(address_double,
1005                                    grid_address,
1006                                    mesh,
1007                                    is_shift);
1008   return kgd_get_dense_grid_point_double_mesh(address_double, mesh);
1009 }
1010 
spg_get_ir_reciprocal_mesh(int grid_address[][3],int ir_mapping_table[],const int mesh[3],const int is_shift[3],const int is_time_reversal,SPGCONST double lattice[3][3],SPGCONST double position[][3],const int types[],const int num_atom,const double symprec)1011 int spg_get_ir_reciprocal_mesh(int grid_address[][3],
1012                                int ir_mapping_table[],
1013                                const int mesh[3],
1014                                const int is_shift[3],
1015                                const int is_time_reversal,
1016                                SPGCONST double lattice[3][3],
1017                                SPGCONST double position[][3],
1018                                const int types[],
1019                                const int num_atom,
1020                                const double symprec)
1021 {
1022   return get_ir_reciprocal_mesh(grid_address,
1023                                 ir_mapping_table,
1024                                 mesh,
1025                                 is_shift,
1026                                 is_time_reversal,
1027                                 lattice,
1028                                 position,
1029                                 types,
1030                                 num_atom,
1031                                 symprec,
1032                                 -1.0);
1033 }
1034 
spg_get_dense_ir_reciprocal_mesh(int grid_address[][3],size_t ir_mapping_table[],const int mesh[3],const int is_shift[3],const int is_time_reversal,SPGCONST double lattice[3][3],SPGCONST double position[][3],const int types[],const int num_atom,const double symprec)1035 size_t spg_get_dense_ir_reciprocal_mesh(int grid_address[][3],
1036                                         size_t ir_mapping_table[],
1037                                         const int mesh[3],
1038                                         const int is_shift[3],
1039                                         const int is_time_reversal,
1040                                         SPGCONST double lattice[3][3],
1041                                         SPGCONST double position[][3],
1042                                         const int types[],
1043                                         const int num_atom,
1044                                         const double symprec)
1045 {
1046   return get_dense_ir_reciprocal_mesh(grid_address,
1047                                      ir_mapping_table,
1048                                      mesh,
1049                                      is_shift,
1050                                      is_time_reversal,
1051                                      lattice,
1052                                      position,
1053                                      types,
1054                                      num_atom,
1055                                      symprec,
1056                                      -1.0);
1057 }
1058 
spg_get_stabilized_reciprocal_mesh(int grid_address[][3],int ir_mapping_table[],const int mesh[3],const int is_shift[3],const int is_time_reversal,const int num_rot,SPGCONST int rotations[][3][3],const int num_q,SPGCONST double qpoints[][3])1059 int spg_get_stabilized_reciprocal_mesh(int grid_address[][3],
1060                                        int ir_mapping_table[],
1061                                        const int mesh[3],
1062                                        const int is_shift[3],
1063                                        const int is_time_reversal,
1064                                        const int num_rot,
1065                                        SPGCONST int rotations[][3][3],
1066                                        const int num_q,
1067                                        SPGCONST double qpoints[][3])
1068 {
1069   return get_stabilized_reciprocal_mesh(grid_address,
1070                                         ir_mapping_table,
1071                                         mesh,
1072                                         is_shift,
1073                                         is_time_reversal,
1074                                         num_rot,
1075                                         rotations,
1076                                         num_q,
1077                                         qpoints);
1078 }
1079 
spg_get_dense_stabilized_reciprocal_mesh(int grid_address[][3],size_t ir_mapping_table[],const int mesh[3],const int is_shift[3],const int is_time_reversal,const int num_rot,SPGCONST int rotations[][3][3],const int num_q,SPGCONST double qpoints[][3])1080 size_t spg_get_dense_stabilized_reciprocal_mesh(int grid_address[][3],
1081                                                 size_t ir_mapping_table[],
1082                                                 const int mesh[3],
1083                                                 const int is_shift[3],
1084                                                 const int is_time_reversal,
1085                                                 const int num_rot,
1086                                                 SPGCONST int rotations[][3][3],
1087                                                 const int num_q,
1088                                                 SPGCONST double qpoints[][3])
1089 {
1090   return get_dense_stabilized_reciprocal_mesh(grid_address,
1091                                               ir_mapping_table,
1092                                               mesh,
1093                                               is_shift,
1094                                               is_time_reversal,
1095                                               num_rot,
1096                                               rotations,
1097                                               num_q,
1098                                               qpoints);
1099 }
1100 
spg_get_dense_grid_points_by_rotations(size_t rot_grid_points[],const int address_orig[3],const int num_rot,SPGCONST int rot_reciprocal[][3][3],const int mesh[3],const int is_shift[3])1101 void spg_get_dense_grid_points_by_rotations(size_t rot_grid_points[],
1102                                             const int address_orig[3],
1103                                             const int num_rot,
1104                                             SPGCONST int rot_reciprocal[][3][3],
1105                                             const int mesh[3],
1106                                             const int is_shift[3])
1107 {
1108   kpt_get_dense_grid_points_by_rotations(rot_grid_points,
1109                                          address_orig,
1110                                          rot_reciprocal,
1111                                          num_rot,
1112                                          mesh,
1113                                          is_shift);
1114 }
1115 
spg_get_dense_BZ_grid_points_by_rotations(size_t rot_grid_points[],const int address_orig[3],const int num_rot,SPGCONST int rot_reciprocal[][3][3],const int mesh[3],const int is_shift[3],const size_t bz_map[])1116 void spg_get_dense_BZ_grid_points_by_rotations(size_t rot_grid_points[],
1117                                                const int address_orig[3],
1118                                                const int num_rot,
1119                                                SPGCONST int rot_reciprocal[][3][3],
1120                                                const int mesh[3],
1121                                                const int is_shift[3],
1122                                                const size_t bz_map[])
1123 {
1124   kpt_get_dense_BZ_grid_points_by_rotations(rot_grid_points,
1125                                             address_orig,
1126                                             rot_reciprocal,
1127                                             num_rot,
1128                                             mesh,
1129                                             is_shift,
1130                                             bz_map);
1131 }
1132 
spg_relocate_BZ_grid_address(int bz_grid_address[][3],int bz_map[],SPGCONST int grid_address[][3],const int mesh[3],SPGCONST double rec_lattice[3][3],const int is_shift[3])1133 int spg_relocate_BZ_grid_address(int bz_grid_address[][3],
1134                                  int bz_map[],
1135                                  SPGCONST int grid_address[][3],
1136                                  const int mesh[3],
1137                                  SPGCONST double rec_lattice[3][3],
1138                                  const int is_shift[3])
1139 {
1140   return kpt_relocate_BZ_grid_address(bz_grid_address,
1141                                       bz_map,
1142                                       grid_address,
1143                                       mesh,
1144                                       rec_lattice,
1145                                       is_shift);
1146 }
1147 
spg_relocate_dense_BZ_grid_address(int bz_grid_address[][3],size_t bz_map[],SPGCONST int grid_address[][3],const int mesh[3],SPGCONST double rec_lattice[3][3],const int is_shift[3])1148 size_t spg_relocate_dense_BZ_grid_address(int bz_grid_address[][3],
1149                                           size_t bz_map[],
1150                                           SPGCONST int grid_address[][3],
1151                                           const int mesh[3],
1152                                           SPGCONST double rec_lattice[3][3],
1153                                           const int is_shift[3])
1154 {
1155   return kpt_relocate_dense_BZ_grid_address(bz_grid_address,
1156                                             bz_map,
1157                                             grid_address,
1158                                             mesh,
1159                                             rec_lattice,
1160                                             is_shift);
1161 }
1162 
1163 /*--------*/
1164 /* Niggli */
1165 /*--------*/
1166 /* Return 0 if failed */
spg_niggli_reduce(double lattice[3][3],const double symprec)1167 int spg_niggli_reduce(double lattice[3][3], const double symprec)
1168 {
1169   int i, j, succeeded;
1170   double vals[9];
1171 
1172   for (i = 0; i < 3; i++) {
1173     for (j = 0; j < 3; j++) {
1174       vals[i * 3 + j] = lattice[i][j];
1175     }
1176   }
1177 
1178   succeeded = niggli_reduce(vals, symprec);
1179 
1180   if (succeeded) {
1181     for (i = 0; i < 3; i++) {
1182       for (j = 0; j < 3; j++) {
1183         lattice[i][j] = vals[i * 3 + j];
1184       }
1185     }
1186     spglib_error_code = SPGLIB_SUCCESS;
1187   } else {
1188     spglib_error_code = SPGERR_NIGGLI_FAILED;
1189   }
1190 
1191   return succeeded;
1192 }
1193 
1194 
1195 
1196 
1197 /*=======*/
1198 /* local */
1199 /*=======*/
1200 
1201 /*---------*/
1202 /* general */
1203 /*---------*/
1204 /* Return NULL if failed */
get_dataset(SPGCONST double lattice[3][3],SPGCONST double position[][3],const int types[],const int num_atom,const int hall_number,const double symprec,const double angle_tolerance)1205 static SpglibDataset * get_dataset(SPGCONST double lattice[3][3],
1206                                    SPGCONST double position[][3],
1207                                    const int types[],
1208                                    const int num_atom,
1209                                    const int hall_number,
1210                                    const double symprec,
1211                                    const double angle_tolerance)
1212 {
1213   SpglibDataset *dataset;
1214   Cell *cell;
1215   DataContainer *container;
1216 
1217   dataset = NULL;
1218   cell = NULL;
1219   container = NULL;
1220 
1221   if ((dataset = init_dataset()) == NULL) {
1222     goto not_found;
1223   }
1224 
1225   if ((cell = cel_alloc_cell(num_atom)) == NULL) {
1226     free(dataset);
1227     dataset = NULL;
1228     goto not_found;
1229   }
1230 
1231   cel_set_cell(cell, lattice, position, types);
1232   if (cel_any_overlap_with_same_type(cell, symprec)) {
1233     cel_free_cell(cell);
1234     cell = NULL;
1235     free(dataset);
1236     dataset = NULL;
1237     goto atoms_too_close;
1238   }
1239 
1240   if ((container = det_determine_all(cell,
1241                                      hall_number,
1242                                      symprec,
1243                                      angle_tolerance))
1244       != NULL) {
1245     if (set_dataset(dataset,
1246                     cell,
1247                     container->primitive,
1248                     container->spacegroup,
1249                     container->exact_structure)) {
1250       det_free_container(container);
1251       container = NULL;
1252       cel_free_cell(cell);
1253       cell = NULL;
1254       goto found;
1255     }
1256     det_free_container(container);
1257     container = NULL;
1258   }
1259 
1260   cel_free_cell(cell);
1261   cell = NULL;
1262   free(dataset);
1263   dataset = NULL;
1264 
1265  not_found:
1266   spglib_error_code = SPGERR_SPACEGROUP_SEARCH_FAILED;
1267   return NULL;
1268 
1269  atoms_too_close:
1270   spglib_error_code = SPGERR_ATOMS_TOO_CLOSE;
1271   return NULL;
1272 
1273  found:
1274 
1275   spglib_error_code = SPGLIB_SUCCESS;
1276   return dataset;
1277 }
1278 
init_dataset(void)1279 static SpglibDataset * init_dataset(void)
1280 {
1281   int i, j;
1282   SpglibDataset *dataset;
1283 
1284   dataset = NULL;
1285 
1286   if ((dataset = (SpglibDataset*) malloc(sizeof(SpglibDataset))) == NULL) {
1287     warning_print("spglib: Memory could not be allocated.");
1288     return NULL;
1289   }
1290 
1291   dataset->spacegroup_number = 0;
1292   dataset->hall_number = 0;
1293   strcpy(dataset->international_symbol, "");
1294   strcpy(dataset->hall_symbol, "");
1295   strcpy(dataset->choice, "");
1296   dataset->origin_shift[0] = 0;
1297   dataset->origin_shift[1] = 0;
1298   dataset->origin_shift[2] = 0;
1299   dataset->n_atoms = 0;
1300   dataset->wyckoffs = NULL;
1301   dataset->equivalent_atoms = NULL;
1302   dataset->crystallographic_orbits = NULL;
1303   dataset->mapping_to_primitive = NULL;
1304   dataset->n_operations = 0;
1305   dataset->rotations = NULL;
1306   dataset->translations = NULL;
1307   dataset->n_std_atoms = 0;
1308   dataset->std_positions = NULL;
1309   dataset->std_types = NULL;
1310   for (i = 0; i < 3; i++) {
1311     for (j = 0; j < 3; j++) {
1312       dataset->std_rotation_matrix[i][j] = 0;
1313     }
1314   }
1315   dataset->std_mapping_to_primitive = NULL;
1316   /* dataset->pointgroup_number = 0; */
1317   strcpy(dataset->pointgroup_symbol, "");
1318 
1319   return dataset;
1320 }
1321 
1322 /* Return 0 if failed */
set_dataset(SpglibDataset * dataset,const Cell * cell,const Primitive * primitive,SPGCONST Spacegroup * spacegroup,ExactStructure * exstr)1323 static int set_dataset(SpglibDataset * dataset,
1324                        const Cell * cell,
1325                        const Primitive * primitive,
1326                        SPGCONST Spacegroup * spacegroup,
1327                        ExactStructure *exstr)
1328 {
1329   int i, j;
1330   double inv_lat[3][3];
1331   Pointgroup pointgroup;
1332 
1333   /* Spacegroup type, transformation matrix, origin shift */
1334   dataset->n_atoms = cell->size;
1335   dataset->spacegroup_number = spacegroup->number;
1336   dataset->hall_number = spacegroup->hall_number;
1337   memcpy(dataset->international_symbol, spacegroup->international_short, 11);
1338   memcpy(dataset->hall_symbol, spacegroup->hall_symbol, 17);
1339   memcpy(dataset->choice, spacegroup->choice, 6);
1340   mat_inverse_matrix_d3(inv_lat, spacegroup->bravais_lattice, 0);
1341   mat_multiply_matrix_d3(dataset->transformation_matrix,
1342                          inv_lat, cell->lattice);
1343   mat_copy_vector_d3(dataset->origin_shift, spacegroup->origin_shift);
1344 
1345   dataset->n_operations = exstr->symmetry->size;
1346 
1347   if ((dataset->rotations =
1348        (int (*)[3][3]) malloc(sizeof(int[3][3]) * dataset->n_operations))
1349       == NULL) {
1350     warning_print("spglib: Memory could not be allocated.");
1351     goto err;
1352   }
1353 
1354   if ((dataset->translations =
1355        (double (*)[3]) malloc(sizeof(double[3]) * dataset->n_operations))
1356       == NULL) {
1357     warning_print("spglib: Memory could not be allocated.");
1358     goto err;
1359   }
1360 
1361   for (i = 0; i < exstr->symmetry->size; i++) {
1362     mat_copy_matrix_i3(dataset->rotations[i], exstr->symmetry->rot[i]);
1363     mat_copy_vector_d3(dataset->translations[i], exstr->symmetry->trans[i]);
1364   }
1365 
1366   /* Wyckoff positions */
1367   if ((dataset->wyckoffs = (int*) malloc(sizeof(int) * dataset->n_atoms))
1368       == NULL) {
1369     warning_print("spglib: Memory could not be allocated.");
1370     goto err;
1371   }
1372 
1373   if ((dataset->site_symmetry_symbols =
1374        (char(*)[7]) malloc(sizeof(char[7]) * dataset->n_atoms)) == NULL) {
1375     warning_print("spglib: Memory could not be allocated.");
1376     goto err;
1377   }
1378 
1379   if ((dataset->equivalent_atoms =
1380        (int*) malloc(sizeof(int) * dataset->n_atoms)) == NULL) {
1381     warning_print("spglib: Memory could not be allocated.");
1382     goto err;
1383   }
1384 
1385   if ((dataset->crystallographic_orbits =
1386        (int*) malloc(sizeof(int) * dataset->n_atoms)) == NULL) {
1387     warning_print("spglib: Memory could not be allocated.");
1388     goto err;
1389   }
1390 
1391   for (i = 0; i < dataset->n_atoms; i++) {
1392     dataset->wyckoffs[i] = exstr->wyckoffs[i];
1393     for (j = 0; j < 7; j++) {
1394       dataset->site_symmetry_symbols[i][j] = exstr->site_symmetry_symbols[i][j];
1395     }
1396     dataset->equivalent_atoms[i] = exstr->equivalent_atoms[i];
1397     dataset->crystallographic_orbits[i] = exstr->crystallographic_orbits[i];
1398   }
1399 
1400   if ((dataset->mapping_to_primitive =
1401        (int*) malloc(sizeof(int) * dataset->n_atoms)) == NULL) {
1402     warning_print("spglib: Memory could not be allocated.");
1403     goto err;
1404   }
1405 
1406   debug_print("[line %d, %s]\n", __LINE__, __FILE__);
1407   debug_print("refined cell after ref_get_Wyckoff_positions\n");
1408   debug_print_matrix_d3(exstr->bravais->lattice);
1409 #ifdef SPGDEBUG
1410   for (i = 0; i < exstr->bravais->size; i++) {
1411     printf("%d: %f %f %f\n",
1412            exstr->bravais->types[i],
1413            exstr->bravais->position[i][0],
1414            exstr->bravais->position[i][1],
1415            exstr->bravais->position[i][2]);
1416   }
1417 #endif
1418 
1419   mat_copy_matrix_d3(dataset->primitive_lattice, primitive->cell->lattice);
1420   for (i = 0; i < dataset->n_atoms; i++) {
1421     dataset->mapping_to_primitive[i] = primitive->mapping_table[i];
1422   }
1423 
1424   dataset->n_std_atoms = exstr->bravais->size;
1425   mat_copy_matrix_d3(dataset->std_lattice, exstr->bravais->lattice);
1426 
1427   if ((dataset->std_positions =
1428        (double (*)[3]) malloc(sizeof(double[3]) * dataset->n_std_atoms))
1429       == NULL) {
1430     warning_print("spglib: Memory could not be allocated.");
1431     goto err;
1432   }
1433 
1434   if ((dataset->std_types = (int*) malloc(sizeof(int) * dataset->n_std_atoms))
1435       == NULL) {
1436     warning_print("spglib: Memory could not be allocated.");
1437     goto err;
1438   }
1439 
1440   if ((dataset->std_mapping_to_primitive =
1441        (int*) malloc(sizeof(int) * dataset->n_std_atoms)) == NULL) {
1442     warning_print("spglib: Memory could not be allocated.");
1443     goto err;
1444   }
1445 
1446   for (i = 0; i < dataset->n_std_atoms; i++) {
1447     mat_copy_vector_d3(dataset->std_positions[i], exstr->bravais->position[i]);
1448     dataset->std_types[i] = exstr->bravais->types[i];
1449     dataset->std_mapping_to_primitive[i] = exstr->std_mapping_to_primitive[i];
1450   }
1451 
1452   mat_copy_matrix_d3(dataset->std_rotation_matrix, exstr->rotation);
1453 
1454   /* dataset->pointgroup_number = spacegroup->pointgroup_number; */
1455   pointgroup = ptg_get_pointgroup(spacegroup->pointgroup_number);
1456   memcpy(dataset->pointgroup_symbol, pointgroup.symbol, 6);
1457 
1458   return 1;
1459 
1460  err:
1461   if (dataset->std_positions != NULL) {
1462     free(dataset->std_positions);
1463     dataset->std_positions = NULL;
1464   }
1465   if (dataset->std_mapping_to_primitive != NULL) {
1466     free(dataset->std_mapping_to_primitive);
1467     dataset->std_mapping_to_primitive = NULL;
1468   }
1469   if (dataset->equivalent_atoms != NULL) {
1470     free(dataset->equivalent_atoms);
1471     dataset->equivalent_atoms = NULL;
1472   }
1473   if (dataset->crystallographic_orbits != NULL) {
1474     free(dataset->crystallographic_orbits);
1475     dataset->crystallographic_orbits = NULL;
1476   }
1477   if (dataset->mapping_to_primitive != NULL) {
1478     free(dataset->mapping_to_primitive);
1479     dataset->mapping_to_primitive = NULL;
1480   }
1481   if (dataset->site_symmetry_symbols != NULL) {
1482     free(dataset->site_symmetry_symbols);
1483     dataset->site_symmetry_symbols = NULL;
1484   }
1485   if (dataset->wyckoffs != NULL) {
1486     free(dataset->wyckoffs);
1487     dataset->wyckoffs = NULL;
1488   }
1489   if (dataset->translations != NULL) {
1490     free(dataset->translations);
1491     dataset->translations = NULL;
1492   }
1493   if (dataset->rotations != NULL) {
1494     free(dataset->rotations);
1495     dataset->rotations = NULL;
1496   }
1497 
1498   return 0;
1499 }
1500 
1501 /* Return 0 if failed */
get_symmetry_from_dataset(int rotation[][3][3],double translation[][3],const int max_size,SPGCONST double lattice[3][3],SPGCONST double position[][3],const int types[],const int num_atom,const double symprec,const double angle_tolerance)1502 static int get_symmetry_from_dataset(int rotation[][3][3],
1503                                      double translation[][3],
1504                                      const int max_size,
1505                                      SPGCONST double lattice[3][3],
1506                                      SPGCONST double position[][3],
1507                                      const int types[],
1508                                      const int num_atom,
1509                                      const double symprec,
1510                                      const double angle_tolerance)
1511 {
1512   int i, num_sym;
1513   SpglibDataset *dataset;
1514 
1515   num_sym = 0;
1516   dataset = NULL;
1517 
1518   if ((dataset = get_dataset(lattice,
1519                              position,
1520                              types,
1521                              num_atom,
1522                              0,
1523                              symprec,
1524                              angle_tolerance)) == NULL) {
1525     return 0;
1526   }
1527 
1528   if (dataset->n_operations > max_size) {
1529     fprintf(stderr,
1530             "spglib: Indicated max size(=%d) is less than number ", max_size);
1531     fprintf(stderr,
1532             "spglib: of symmetry operations(=%d).\n", dataset->n_operations);
1533     goto err;
1534   }
1535 
1536   num_sym = dataset->n_operations;
1537   for (i = 0; i < num_sym; i++) {
1538     mat_copy_matrix_i3(rotation[i], dataset->rotations[i]);
1539     mat_copy_vector_d3(translation[i], dataset->translations[i]);
1540   }
1541 
1542   spg_free_dataset(dataset);
1543   dataset = NULL;
1544   return num_sym;
1545 
1546  err:
1547   spg_free_dataset(dataset);
1548   dataset = NULL;
1549   spglib_error_code = SPGERR_ARRAY_SIZE_SHORTAGE;
1550   return 0;
1551 }
1552 
1553 /* Return 0 if failed */
get_symmetry_with_site_tensors(int rotation[][3][3],double translation[][3],int equivalent_atoms[],double primitive_lattice[3][3],int * spin_flips,const int run_symmetry_search,const int num_operations,SPGCONST double lattice[3][3],SPGCONST double position[][3],const int types[],const double * tensors,const int tensor_rank,const int num_atom,const int is_magnetic,const double symprec,const double angle_tolerance)1554 static int get_symmetry_with_site_tensors(int rotation[][3][3],
1555                                           double translation[][3],
1556                                           int equivalent_atoms[],
1557                                           double primitive_lattice[3][3],
1558                                           int *spin_flips,
1559                                           const int run_symmetry_search,
1560                                           const int num_operations,
1561                                           SPGCONST double lattice[3][3],
1562                                           SPGCONST double position[][3],
1563                                           const int types[],
1564                                           const double *tensors,
1565                                           const int tensor_rank,
1566                                           const int num_atom,
1567                                           const int is_magnetic,
1568                                           const double symprec,
1569                                           const double angle_tolerance)
1570 {
1571   int i, size;
1572   Symmetry *symmetry, *sym_nonspin;
1573   Cell *cell;
1574   SpglibDataset *dataset;
1575 
1576   size = 0;
1577   symmetry = NULL;
1578   sym_nonspin = NULL;
1579   cell = NULL;
1580   dataset = NULL;
1581 
1582   if (run_symmetry_search) {
1583     if ((dataset = get_dataset(lattice,
1584                                position,
1585                                types,
1586                                num_atom,
1587                                0,
1588                                symprec,
1589                                angle_tolerance)) == NULL) {
1590       goto err;
1591     }
1592 
1593     if ((sym_nonspin = sym_alloc_symmetry(dataset->n_operations)) == NULL) {
1594       spg_free_dataset(dataset);
1595       dataset = NULL;
1596       goto err;
1597     }
1598 
1599     for (i = 0; i < dataset->n_operations; i++) {
1600       mat_copy_matrix_i3(sym_nonspin->rot[i], dataset->rotations[i]);
1601       mat_copy_vector_d3(sym_nonspin->trans[i], dataset->translations[i]);
1602     }
1603     spg_free_dataset(dataset);
1604     dataset = NULL;
1605   } else {
1606     if ((sym_nonspin = sym_alloc_symmetry(num_operations)) == NULL) {
1607       goto err;
1608     }
1609     for (i = 0; i < num_operations; i++) {
1610       mat_copy_matrix_i3(sym_nonspin->rot[i], rotation[i]);
1611       mat_copy_vector_d3(sym_nonspin->trans[i], translation[i]);
1612     }
1613   }
1614 
1615   if ((cell = cel_alloc_cell(num_atom)) == NULL) {
1616     goto err;
1617   }
1618   cel_set_cell(cell, lattice, position, types);
1619   symmetry = spn_get_operations_with_site_tensors(equivalent_atoms,
1620                                                   primitive_lattice,
1621                                                   spin_flips,
1622                                                   sym_nonspin,
1623                                                   cell,
1624                                                   tensors,
1625                                                   tensor_rank,
1626                                                   is_magnetic,
1627                                                   symprec,
1628                                                   angle_tolerance);
1629 
1630   sym_free_symmetry(sym_nonspin);
1631   sym_nonspin = NULL;
1632   cel_free_cell(cell);
1633   cell = NULL;
1634 
1635   if (symmetry == NULL) {
1636     goto err;
1637   }
1638 
1639   if (symmetry->size > num_operations) {
1640     fprintf(stderr, "spglib: Indicated max size(=%d) is less than number ",
1641             num_operations);
1642     fprintf(stderr, "spglib: of symmetry operations(=%d).\n", symmetry->size);
1643     sym_free_symmetry(symmetry);
1644     symmetry = NULL;
1645     goto array_size_shortage_err;
1646   }
1647 
1648   for (i = 0; i < symmetry->size; i++) {
1649     mat_copy_matrix_i3(rotation[i], symmetry->rot[i]);
1650     mat_copy_vector_d3(translation[i], symmetry->trans[i]);
1651   }
1652   size = symmetry->size;
1653 
1654   sym_free_symmetry(symmetry);
1655   symmetry = NULL;
1656   spglib_error_code = SPGLIB_SUCCESS;
1657 
1658   return size;
1659 
1660  err:
1661   spglib_error_code = SPGERR_SYMMETRY_OPERATION_SEARCH_FAILED;
1662   return 0;
1663 
1664 array_size_shortage_err:
1665   spglib_error_code = SPGERR_ARRAY_SIZE_SHORTAGE;
1666   return 0;
1667 
1668 }
1669 
1670 /* Return 0 if failed */
get_multiplicity(SPGCONST double lattice[3][3],SPGCONST double position[][3],const int types[],const int num_atom,const double symprec,const double angle_tolerance)1671 static int get_multiplicity(SPGCONST double lattice[3][3],
1672                             SPGCONST double position[][3],
1673                             const int types[],
1674                             const int num_atom,
1675                             const double symprec,
1676                             const double angle_tolerance)
1677 {
1678   int size;
1679   SpglibDataset *dataset;
1680 
1681   size = 0;
1682   dataset = NULL;
1683 
1684   if ((dataset = get_dataset(lattice,
1685                              position,
1686                              types,
1687                              num_atom,
1688                              0,
1689                              symprec,
1690                              angle_tolerance)) == NULL) {
1691     return 0;
1692   }
1693 
1694   size = dataset->n_operations;
1695   spg_free_dataset(dataset);
1696   dataset = NULL;
1697 
1698   return size;
1699 }
1700 
standardize_primitive(double lattice[3][3],double position[][3],int types[],const int num_atom,const double symprec,const double angle_tolerance)1701 static int standardize_primitive(double lattice[3][3],
1702                                  double position[][3],
1703                                  int types[],
1704                                  const int num_atom,
1705                                  const double symprec,
1706                                  const double angle_tolerance)
1707 {
1708   int i, num_prim_atom;
1709   int *mapping_table;
1710   Centering centering;
1711   SpglibDataset *dataset;
1712   Cell *primitive, *bravais;
1713 
1714   double identity[3][3] = {{ 1, 0, 0 },
1715                            { 0, 1, 0 },
1716                            { 0, 0, 1 }};
1717 
1718   num_prim_atom = 0;
1719   mapping_table = NULL;
1720   dataset = NULL;
1721   primitive = NULL;
1722   bravais = NULL;
1723 
1724   if ((dataset = get_dataset(lattice,
1725                              position,
1726                              types,
1727                              num_atom,
1728                              0,
1729                              symprec,
1730                              angle_tolerance)) == NULL) {
1731     return 0;
1732   }
1733 
1734   if ((centering = get_centering(dataset->hall_number)) == CENTERING_ERROR) {
1735     spg_free_dataset(dataset);
1736     dataset = NULL;
1737     goto err;
1738   }
1739 
1740   if ((bravais = cel_alloc_cell(dataset->n_std_atoms)) == NULL) {
1741     spg_free_dataset(dataset);
1742     dataset = NULL;
1743     goto err;
1744   }
1745 
1746   cel_set_cell(bravais,
1747                dataset->std_lattice,
1748                dataset->std_positions,
1749                dataset->std_types);
1750 
1751   spg_free_dataset(dataset);
1752   dataset = NULL;
1753 
1754   if ((mapping_table = (int*) malloc(sizeof(int) * bravais->size)) == NULL) {
1755     warning_print("spglib: Memory could not be allocated ");
1756     cel_free_cell(bravais);
1757     bravais = NULL;
1758     goto err;
1759   }
1760 
1761   primitive = spa_transform_to_primitive(mapping_table,
1762                                          bravais,
1763                                          identity,
1764                                          centering,
1765                                          symprec);
1766 
1767   for (i = 0; i < primitive->size; i++) {
1768     /* This is an assertion. */
1769     if (mapping_table[i] != i) {
1770       warning_print("spglib: spa_transform_to_primitive failed.");
1771       warning_print("Unexpected atom index mapping to primitive (%d != %d).\n",
1772                     mapping_table[i], i);
1773       warning_print(" (line %d, %s).\n", __LINE__, __FILE__);
1774       free(mapping_table);
1775       mapping_table = NULL;
1776       cel_free_cell(bravais);
1777       bravais = NULL;
1778       goto err;
1779     }
1780   }
1781 
1782   free(mapping_table);
1783   mapping_table = NULL;
1784   cel_free_cell(bravais);
1785   bravais = NULL;
1786 
1787   if (primitive == NULL) {
1788     goto err;
1789   }
1790 
1791   set_cell(lattice, position, types, primitive);
1792   num_prim_atom = primitive->size;
1793 
1794   cel_free_cell(primitive);
1795   primitive = NULL;
1796 
1797   return num_prim_atom;
1798 
1799  err:
1800   spglib_error_code = SPGERR_CELL_STANDARDIZATION_FAILED;
1801   return 0;
1802 }
1803 
standardize_cell(double lattice[3][3],double position[][3],int types[],const int num_atom,const int num_array_size,const double symprec,const double angle_tolerance)1804 static int standardize_cell(double lattice[3][3],
1805                             double position[][3],
1806                             int types[],
1807                             const int num_atom,
1808                             const int num_array_size,
1809                             const double symprec,
1810                             const double angle_tolerance)
1811 {
1812   int i, n_std_atoms;
1813   SpglibDataset *dataset;
1814 
1815   n_std_atoms = 0;
1816   dataset = NULL;
1817 
1818   if ((dataset = get_dataset(lattice,
1819                              position,
1820                              types,
1821                              num_atom,
1822                              0,
1823                              symprec,
1824                              angle_tolerance)) == NULL) {
1825     goto err;
1826   }
1827 
1828   if (num_array_size > 0) {
1829     if (num_atom < dataset->n_std_atoms) {
1830       goto array_size_shortage_err;
1831     }
1832   }
1833 
1834   n_std_atoms = dataset->n_std_atoms;
1835   mat_copy_matrix_d3(lattice, dataset->std_lattice);
1836   for (i = 0; i < dataset->n_std_atoms; i++) {
1837     types[i] = dataset->std_types[i];
1838     mat_copy_vector_d3(position[i], dataset->std_positions[i]);
1839   }
1840 
1841   spg_free_dataset(dataset);
1842   dataset = NULL;
1843 
1844   return n_std_atoms;
1845 
1846 err:
1847   spglib_error_code = SPGERR_CELL_STANDARDIZATION_FAILED;
1848   return 0;
1849 
1850 array_size_shortage_err:
1851   spglib_error_code = SPGERR_ARRAY_SIZE_SHORTAGE;
1852   return 0;
1853 }
1854 
get_standardized_cell(double lattice[3][3],double position[][3],int types[],const int num_atom,const int num_array_size,const int to_primitive,const double symprec,const double angle_tolerance)1855 static int get_standardized_cell(double lattice[3][3],
1856                                  double position[][3],
1857                                  int types[],
1858                                  const int num_atom,
1859                                  const int num_array_size,
1860                                  const int to_primitive,
1861                                  const double symprec,
1862                                  const double angle_tolerance)
1863 {
1864   int i, num_std_atom, num_prim_atom;
1865   int *mapping_table;
1866   SpglibDataset *dataset;
1867   Cell *std_cell, *cell, *primitive;
1868   Centering centering;
1869 
1870   num_std_atom = 0;
1871   mapping_table = NULL;
1872   dataset = NULL;
1873   std_cell = NULL;
1874   cell = NULL;
1875   primitive = NULL;
1876 
1877   if ((dataset = get_dataset(lattice,
1878                              position,
1879                              types,
1880                              num_atom,
1881                              0,
1882                              symprec,
1883                              angle_tolerance)) == NULL) {
1884     goto err;
1885   }
1886 
1887   if ((centering = get_centering(dataset->hall_number)) == CENTERING_ERROR) {
1888     goto err;
1889   }
1890 
1891   if ((cell = cel_alloc_cell(num_atom)) == NULL) {
1892     spg_free_dataset(dataset);
1893     dataset = NULL;
1894     goto err;
1895   }
1896 
1897   cel_set_cell(cell, lattice, position, types);
1898 
1899   if ((mapping_table = (int*) malloc(sizeof(int) * cell->size)) == NULL) {
1900     warning_print("spglib: Memory could not be allocated ");
1901     cel_free_cell(cell);
1902     cell = NULL;
1903     spg_free_dataset(dataset);
1904     dataset = NULL;
1905     goto err;
1906   }
1907 
1908   if ((primitive = spa_transform_to_primitive(mapping_table,
1909                                               cell,
1910                                               dataset->transformation_matrix,
1911                                               centering,
1912                                               symprec)) == NULL) {
1913     warning_print("spglib: spa_transform_to_primitive failed.");
1914     warning_print(" (line %d, %s).\n", __LINE__, __FILE__);
1915   }
1916 
1917   for (i = 0; i < cell->size; i++) {
1918     /* This is an assertion. */
1919     if (mapping_table[i] != dataset->mapping_to_primitive[i]) {
1920       warning_print("spglib: spa_transform_to_primitive failed.");
1921       warning_print("Unexpected atom index mapping to primitive (%d != %d).\n",
1922                     mapping_table[i], dataset->mapping_to_primitive[i]);
1923       warning_print(" (line %d, %s).\n", __LINE__, __FILE__);
1924       free(mapping_table);
1925       mapping_table = NULL;
1926       cel_free_cell(cell);
1927       cell = NULL;
1928       spg_free_dataset(dataset);
1929       dataset = NULL;
1930       goto err;
1931     }
1932   }
1933 
1934   free(mapping_table);
1935   mapping_table = NULL;
1936   cel_free_cell(cell);
1937   cell = NULL;
1938   spg_free_dataset(dataset);
1939   dataset = NULL;
1940 
1941   if (primitive == NULL) {
1942     goto err;
1943   }
1944 
1945   if (to_primitive || centering == PRIMITIVE) {
1946     set_cell(lattice, position, types, primitive);
1947     num_prim_atom = primitive->size;
1948     cel_free_cell(primitive);
1949     primitive = NULL;
1950     return num_prim_atom;
1951   }
1952 
1953   if ((std_cell = spa_transform_from_primitive(primitive, centering, symprec))
1954       == NULL) {
1955     warning_print("spglib: spa_transform_from_primitive failed.");
1956     warning_print(" (line %d, %s).\n", __LINE__, __FILE__);
1957   }
1958   cel_free_cell(primitive);
1959   primitive = NULL;
1960 
1961   if (std_cell == NULL) {
1962     goto err;
1963   }
1964 
1965   if (num_array_size > 0) {
1966     if (num_array_size < std_cell->size) {
1967       cel_free_cell(std_cell);
1968       std_cell = NULL;
1969       goto array_size_shortage_err;
1970     }
1971   }
1972 
1973   num_std_atom = std_cell->size;
1974   set_cell(lattice, position, types, std_cell);
1975   cel_free_cell(std_cell);
1976   std_cell = NULL;
1977   return num_std_atom;
1978 
1979 err:
1980   spglib_error_code = SPGERR_CELL_STANDARDIZATION_FAILED;
1981   return 0;
1982 
1983 array_size_shortage_err:
1984   spglib_error_code = SPGERR_ARRAY_SIZE_SHORTAGE;
1985   return 0;
1986 }
1987 
set_cell(double lattice[3][3],double position[][3],int types[],Cell * cell)1988 static void set_cell(double lattice[3][3],
1989                      double position[][3],
1990                      int types[],
1991                      Cell * cell)
1992 {
1993   int i;
1994 
1995   mat_copy_matrix_d3(lattice, cell->lattice);
1996   for (i = 0; i < cell->size; i++) {
1997     types[i] = cell->types[i];
1998     mat_copy_vector_d3(position[i], cell->position[i]);
1999   }
2000 }
2001 
get_centering(int hall_number)2002 static Centering get_centering(int hall_number)
2003 {
2004   SpacegroupType spgtype;
2005 
2006   spgtype = spgdb_get_spacegroup_type(hall_number);
2007 
2008   return spgtype.centering;
2009 }
2010 
get_international(char symbol[11],SPGCONST double lattice[3][3],SPGCONST double position[][3],const int types[],const int num_atom,const double symprec,const double angle_tolerance)2011 static int get_international(char symbol[11],
2012                              SPGCONST double lattice[3][3],
2013                              SPGCONST double position[][3],
2014                              const int types[],
2015                              const int num_atom,
2016                              const double symprec,
2017                              const double angle_tolerance)
2018 {
2019   SpglibDataset *dataset;
2020   int number;
2021 
2022   dataset = NULL;
2023 
2024   if ((dataset = get_dataset(lattice,
2025                              position,
2026                              types,
2027                              num_atom,
2028                              0,
2029                              symprec,
2030                              angle_tolerance)) == NULL) {
2031     goto err;
2032   }
2033 
2034   if (dataset->spacegroup_number > 0) {
2035     number = dataset->spacegroup_number;
2036     memcpy(symbol, dataset->international_symbol, 11);
2037 
2038     spg_free_dataset(dataset);
2039     dataset = NULL;
2040   } else {
2041     spg_free_dataset(dataset);
2042     dataset = NULL;
2043     goto err;
2044   }
2045 
2046   spglib_error_code = SPGLIB_SUCCESS;
2047   return number;
2048 
2049  err:
2050   spglib_error_code = SPGERR_SPACEGROUP_SEARCH_FAILED;
2051   return 0;
2052 }
2053 
get_schoenflies(char symbol[7],SPGCONST double lattice[3][3],SPGCONST double position[][3],const int types[],const int num_atom,const double symprec,const double angle_tolerance)2054 static int get_schoenflies(char symbol[7],
2055                            SPGCONST double lattice[3][3],
2056                            SPGCONST double position[][3],
2057                            const int types[],
2058                            const int num_atom,
2059                            const double symprec,
2060                            const double angle_tolerance)
2061 {
2062   SpglibDataset *dataset;
2063   SpglibSpacegroupType spgtype;
2064   int number;
2065 
2066   dataset = NULL;
2067 
2068   if ((dataset = get_dataset(lattice,
2069                              position,
2070                              types,
2071                              num_atom,
2072                              0,
2073                              symprec,
2074                              angle_tolerance)) == NULL) {
2075     goto err;
2076   }
2077 
2078   if (dataset->spacegroup_number > 0) {
2079     number = dataset->spacegroup_number;
2080     spgtype = spg_get_spacegroup_type(dataset->hall_number);
2081     memcpy(symbol, spgtype.schoenflies, 7);
2082     spg_free_dataset(dataset);
2083     dataset = NULL;
2084   } else {
2085     spg_free_dataset(dataset);
2086     dataset = NULL;
2087     goto err;
2088   }
2089 
2090   spglib_error_code = SPGLIB_SUCCESS;
2091   return number;
2092 
2093  err:
2094   spglib_error_code = SPGERR_SPACEGROUP_SEARCH_FAILED;
2095   return 0;
2096 }
2097 
2098 
2099 /*---------*/
2100 /* kpoints */
2101 /*---------*/
get_ir_reciprocal_mesh(int grid_address[][3],int ir_mapping_table[],const int mesh[3],const int is_shift[3],const int is_time_reversal,SPGCONST double lattice[3][3],SPGCONST double position[][3],const int types[],const int num_atom,const double symprec,const double angle_tolerance)2102 static int get_ir_reciprocal_mesh(int grid_address[][3],
2103                                   int ir_mapping_table[],
2104                                   const int mesh[3],
2105                                   const int is_shift[3],
2106                                   const int is_time_reversal,
2107                                   SPGCONST double lattice[3][3],
2108                                   SPGCONST double position[][3],
2109                                   const int types[],
2110                                   const int num_atom,
2111                                   const double symprec,
2112                                   const double angle_tolerance)
2113 {
2114   SpglibDataset *dataset;
2115   int num_ir, i;
2116   MatINT *rotations, *rot_reciprocal;
2117 
2118   if ((dataset = get_dataset(lattice,
2119                              position,
2120                              types,
2121                              num_atom,
2122                              0,
2123                              symprec,
2124                              angle_tolerance)) == NULL) {
2125     return 0;
2126   }
2127 
2128   if ((rotations = mat_alloc_MatINT(dataset->n_operations)) == NULL) {
2129     spg_free_dataset(dataset);
2130     dataset = NULL;
2131     return 0;
2132   }
2133 
2134   for (i = 0; i < dataset->n_operations; i++) {
2135     mat_copy_matrix_i3(rotations->mat[i], dataset->rotations[i]);
2136   }
2137   rot_reciprocal = kpt_get_point_group_reciprocal(rotations, is_time_reversal);
2138   num_ir = kpt_get_irreducible_reciprocal_mesh(grid_address,
2139                                                ir_mapping_table,
2140                                                mesh,
2141                                                is_shift,
2142                                                rot_reciprocal);
2143   mat_free_MatINT(rot_reciprocal);
2144   rot_reciprocal = NULL;
2145   mat_free_MatINT(rotations);
2146   rotations = NULL;
2147   spg_free_dataset(dataset);
2148   dataset = NULL;
2149   return num_ir;
2150 }
2151 
get_dense_ir_reciprocal_mesh(int grid_address[][3],size_t ir_mapping_table[],const int mesh[3],const int is_shift[3],const int is_time_reversal,SPGCONST double lattice[3][3],SPGCONST double position[][3],const int types[],const size_t num_atom,const double symprec,const double angle_tolerance)2152 static size_t get_dense_ir_reciprocal_mesh(int grid_address[][3],
2153                                            size_t ir_mapping_table[],
2154                                            const int mesh[3],
2155                                            const int is_shift[3],
2156                                            const int is_time_reversal,
2157                                            SPGCONST double lattice[3][3],
2158                                            SPGCONST double position[][3],
2159                                            const int types[],
2160                                            const size_t num_atom,
2161                                            const double symprec,
2162                                            const double angle_tolerance)
2163 {
2164   SpglibDataset *dataset;
2165   int i;
2166   size_t num_ir;
2167   MatINT *rotations, *rot_reciprocal;
2168 
2169   if ((dataset = get_dataset(lattice,
2170                              position,
2171                              types,
2172                              num_atom,
2173                              0,
2174                              symprec,
2175                              angle_tolerance)) == NULL) {
2176     return 0;
2177   }
2178 
2179   if ((rotations = mat_alloc_MatINT(dataset->n_operations)) == NULL) {
2180     spg_free_dataset(dataset);
2181     dataset = NULL;
2182     return 0;
2183   }
2184 
2185   for (i = 0; i < dataset->n_operations; i++) {
2186     mat_copy_matrix_i3(rotations->mat[i], dataset->rotations[i]);
2187   }
2188   rot_reciprocal = kpt_get_point_group_reciprocal(rotations, is_time_reversal);
2189   num_ir = kpt_get_dense_irreducible_reciprocal_mesh(grid_address,
2190                                                      ir_mapping_table,
2191                                                      mesh,
2192                                                      is_shift,
2193                                                      rot_reciprocal);
2194   mat_free_MatINT(rot_reciprocal);
2195   rot_reciprocal = NULL;
2196   mat_free_MatINT(rotations);
2197   rotations = NULL;
2198   spg_free_dataset(dataset);
2199   dataset = NULL;
2200   return num_ir;
2201 }
2202 
get_stabilized_reciprocal_mesh(int grid_address[][3],int map[],const int mesh[3],const int is_shift[3],const int is_time_reversal,const int num_rot,SPGCONST int rotations[][3][3],const size_t num_q,SPGCONST double qpoints[][3])2203 static int get_stabilized_reciprocal_mesh(int grid_address[][3],
2204                                           int map[],
2205                                           const int mesh[3],
2206                                           const int is_shift[3],
2207                                           const int is_time_reversal,
2208                                           const int num_rot,
2209                                           SPGCONST int rotations[][3][3],
2210                                           const size_t num_q,
2211                                           SPGCONST double qpoints[][3])
2212 {
2213   MatINT *rot_real;
2214   int i, num_ir;
2215 
2216   rot_real = NULL;
2217 
2218   if ((rot_real = mat_alloc_MatINT(num_rot)) == NULL) {
2219     return 0;
2220   }
2221 
2222   for (i = 0; i < num_rot; i++) {
2223     mat_copy_matrix_i3(rot_real->mat[i], rotations[i]);
2224   }
2225 
2226   num_ir = kpt_get_stabilized_reciprocal_mesh(grid_address,
2227                                               map,
2228                                               mesh,
2229                                               is_shift,
2230                                               is_time_reversal,
2231                                               rot_real,
2232                                               num_q,
2233                                               qpoints);
2234 
2235   mat_free_MatINT(rot_real);
2236   rot_real = NULL;
2237 
2238   return num_ir;
2239 }
2240 
get_dense_stabilized_reciprocal_mesh(int grid_address[][3],size_t ir_mapping_table[],const int mesh[3],const int is_shift[3],const int is_time_reversal,const size_t num_rot,SPGCONST int rotations[][3][3],const size_t num_q,SPGCONST double qpoints[][3])2241 static size_t get_dense_stabilized_reciprocal_mesh(int grid_address[][3],
2242                                                    size_t ir_mapping_table[],
2243                                                    const int mesh[3],
2244                                                    const int is_shift[3],
2245                                                    const int is_time_reversal,
2246                                                    const size_t num_rot,
2247                                                    SPGCONST int rotations[][3][3],
2248                                                    const size_t num_q,
2249                                                    SPGCONST double qpoints[][3])
2250 {
2251   MatINT *rot_real;
2252   size_t i, num_ir;
2253 
2254   rot_real = NULL;
2255 
2256   if ((rot_real = mat_alloc_MatINT(num_rot)) == NULL) {
2257     return 0;
2258   }
2259 
2260   for (i = 0; i < num_rot; i++) {
2261     mat_copy_matrix_i3(rot_real->mat[i], rotations[i]);
2262   }
2263 
2264   num_ir = kpt_get_dense_stabilized_reciprocal_mesh(grid_address,
2265                                                     ir_mapping_table,
2266                                                     mesh,
2267                                                     is_shift,
2268                                                     is_time_reversal,
2269                                                     rot_real,
2270                                                     num_q,
2271                                                     qpoints);
2272 
2273   mat_free_MatINT(rot_real);
2274   rot_real = NULL;
2275 
2276   return num_ir;
2277 }
2278