1 /* Copyright (C) 2017 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 <stdlib.h>
36 #include "cell.h"
37 #include "determination.h"
38 #include "primitive.h"
39 #include "refinement.h"
40 #include "spacegroup.h"
41
42 #include "debug.h"
43
44 #define REDUCE_RATE_OUTER 0.9
45 #define NUM_ATTEMPT_OUTER 10
46 #define REDUCE_RATE 0.95
47 #define ANGLE_REDUCE_RATE 0.95
48 #define NUM_ATTEMPT 20
49
50 static DataContainer * get_spacegroup_and_primitive(const Cell * cell,
51 const int hall_number,
52 const double symprec,
53 const double angle_symprec);
54
det_determine_all(const Cell * cell,const int hall_number,const double symprec,const double angle_symprec)55 DataContainer * det_determine_all(const Cell * cell,
56 const int hall_number,
57 const double symprec,
58 const double angle_symprec)
59 {
60 int attempt;
61 double tolerance;
62 DataContainer *container;
63
64 container = NULL;
65
66 if (hall_number < 0 || hall_number > 530) {
67 return NULL;
68 }
69
70 tolerance = symprec;
71 for (attempt = 0; attempt < NUM_ATTEMPT_OUTER; attempt++) {
72 if ((container = get_spacegroup_and_primitive(cell,
73 hall_number,
74 tolerance,
75 angle_symprec)) != NULL) {
76 if ((container->exact_structure = ref_get_exact_structure_and_symmetry(
77 container->spacegroup,
78 container->primitive->cell,
79 cell,
80 container->primitive->mapping_table,
81 container->primitive->tolerance)) != NULL) {
82 goto found;
83 }
84 warning_print("spglib: ref_get_exact_structure_and_symmetry failed.");
85 warning_print(" (line %d, %s).\n", __LINE__, __FILE__);
86 det_free_container(container);
87 container = NULL;
88 }
89 tolerance *= REDUCE_RATE_OUTER;
90 }
91
92 found:
93 return container;
94 }
95
det_free_container(DataContainer * container)96 void det_free_container(DataContainer * container)
97 {
98 if (container != NULL) {
99 if (container->spacegroup != NULL) {
100 free(container->spacegroup);
101 container->spacegroup = NULL;
102 }
103 if (container->primitive != NULL) {
104 prm_free_primitive(container->primitive);
105 container->primitive = NULL;
106 }
107 if (container->exact_structure != NULL) {
108 ref_free_exact_structure(container->exact_structure);
109 container->exact_structure = NULL;
110 }
111 free(container);
112 }
113 }
114
115 /* NULL is returned if failed */
get_spacegroup_and_primitive(const Cell * cell,const int hall_number,const double symprec,const double angle_symprec)116 static DataContainer * get_spacegroup_and_primitive(const Cell * cell,
117 const int hall_number,
118 const double symprec,
119 const double angle_symprec)
120 {
121 int attempt;
122 double tolerance, angle_tolerance;
123 DataContainer *container;
124
125 debug_print("get_spacegroup_and_primitive (tolerance = %f):\n", symprec);
126
127 container = NULL;
128
129 if ((container = (DataContainer*) malloc(sizeof(DataContainer))) == NULL) {
130 warning_print("spglib: Memory could not be allocated.");
131 return NULL;
132 }
133
134 container->primitive = NULL;
135 container->spacegroup = NULL;
136 container->exact_structure = NULL;
137
138 tolerance = symprec;
139 angle_tolerance = angle_symprec;
140
141 for (attempt = 0; attempt < NUM_ATTEMPT; attempt++) {
142 if ((container->primitive = prm_get_primitive(cell,
143 tolerance,
144 angle_tolerance)) != NULL) {
145
146 debug_print("[line %d, %s]\n", __LINE__, __FILE__);
147 debug_print("primitive lattice\n");
148 debug_print_matrix_d3(container->primitive->cell->lattice);
149
150 if ((container->spacegroup = spa_search_spacegroup(
151 container->primitive,
152 hall_number,
153 container->primitive->tolerance,
154 container->primitive->angle_tolerance)) != NULL) {
155 goto found;
156 }
157
158 prm_free_primitive(container->primitive);
159 container->primitive = NULL;
160 }
161
162 warning_print("spglib: Attempt %d tolerance = %f failed.",
163 attempt, tolerance);
164 warning_print(" (line %d, %s).\n", __LINE__, __FILE__);
165
166 tolerance *= REDUCE_RATE;
167 if (angle_tolerance > 0) {
168 angle_tolerance *= ANGLE_REDUCE_RATE;
169 }
170 }
171
172 det_free_container(container);
173 container = NULL;
174
175 return NULL;
176
177 found:
178 return container;
179 }
180