Develop and Download Open Source Software

Browse Subversion Repository

Contents of /Conograph/trunk/src/lattice_symmetry/gather_q_of_Ndim_lattice.cc

Parent Directory Parent Directory | Revision Log Revision Log


Revision 25 - (show annotations) (download) (as text)
Mon Jul 7 02:35:51 2014 UTC (9 years, 8 months ago) by rtomiyasu
File MIME type: text/x-c++src
File size: 7424 byte(s)
Source codes of version 0.9.99
1 /*
2 * The MIT License
3
4 Conograph (powder auto-indexing program)
5
6 Copyright (c) <2012> <Ryoko Oishi-Tomiyasu, KEK>
7
8 Permission is hereby granted, free of charge, to any person obtaining a copy
9 of this software and associated documentation files (the "Software"), to deal
10 in the Software without restriction, including without limitation the rights
11 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12 copies of the Software, and to permit persons to whom the Software is
13 furnished to do so, subject to the following conditions:
14
15 The above copyright notice and this permission notice shall be included in
16 all copies or substantial portions of the Software.
17
18 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
24 THE SOFTWARE.
25 *
26 */
27 #include <limits>
28 #include <algorithm>
29 #include "gather_q_of_Ndim_lattice.hh"
30 #include "../utility_func/zmath.hh"
31
32
33 // S_super is a Selling-reduced positive definite symmetric matrix.
34 // - sum_{i != j} (ci-cj)^2*Sij <= maxQ
35 static void set_max_range(const SymMat<Double>& S_super, const Double& maxQ,
36 SymMat<Int4>& max_range)
37 {
38 const Int4 ISIZE = max_range.size();
39 assert( S_super.size() == ISIZE + 1 );
40 assert( 1 <= ISIZE && ISIZE <= 4 );
41
42 static const Int4 MAX_INT = numeric_limits<Int4>::max();
43 static const Int4 SQUARE_MAX_INT = ifloor( sqrt( (Double)MAX_INT ) );
44 const Double min_dp = - maxQ / Double(MAX_INT);
45 max_range = SQUARE_MAX_INT;
46
47 // From (ci-cj)^2 <= (ci-ck)^2 + (cj-ck)^2 + (ci-cl)^2 + (cj-cl)^2,
48 // Sij > 0
49 // => -Sij*(ci-cj)^2 >= -Sij * { (ci-ck)^2 + (cj-ck)^2 + (ci-cl)^2 + (cj-cl)^2 }.
50 // Sij > 0, Skl > 0 for distinct 1 <= i, j, k, l, m <= 5
51 // => -Sij*(ci-cj)^2 - Skl*(ck-cl)^2 >= -(Sij + Skl) * { (ci-ck)^2 + (cj-ck)^2 + (ci-cl)^2 + (cj-cl)^2 },
52 // -Sij*(ci-cj)^2 - Skl*(ck-cl)^2 >= -Sij * { (ci-cm)^2 + (cj-cm)^2 + (ci-cl)^2 } - Skl * { (cm-ck)^2 + (cj-ck)^2 + (cm-cl)^2 } - (Sij + Skl) * (cj-cl)^2
53 for(Int4 n=0; n<ISIZE; n++)
54 {
55 for(Int4 n2=n+1; n2<ISIZE; n2++)
56 {
57 if( S_super(n, n2) < min_dp ) max_range(n, n2) = ifloor( sqrt( - maxQ / S_super(n, n2) ) );
58 }
59 if( S_super(n, ISIZE) < min_dp ) max_range(n, n) = ifloor( sqrt( - maxQ / S_super(n, ISIZE) ) );
60 }
61 }
62
63
64 static void arrange_max_range(SymMat<Int4>& max_range)
65 {
66 const Int4 ISIZE = max_range.size();
67
68 Int4 num;
69 bool flag = true;
70 while( flag )
71 {
72 flag = false;
73
74 for(Int4 i=0; i<ISIZE; i++)
75 {
76 for(Int4 i2=0; i2<i; i2++)
77 {
78 num = max_range(i,i)+max_range(i2,i2);
79 for(Int4 k=0; k<ISIZE; k++)
80 {
81 // |ci - ci2| <= |ci - ck| + |ci2 - ck|
82 num = min( max_range(i,k)+max_range(i2,k), num);
83 }
84 if( num < max_range(i,i2) )
85 {
86 max_range(i,i2) = num;
87 flag = true;
88 }
89 }
90
91 num = max_range(i,i);
92 for(Int4 k=0; k<ISIZE; k++)
93 {
94 // |ci| <= |ci - ck| + |ck|
95 num = min( max_range(i,k)+max_range(k,k), num );
96 }
97 if( num < max_range(i,i) )
98 {
99 max_range(i,i) = num;
100 flag = true;
101 }
102
103 }
104 }
105 }
106
107
108 inline Double norm(const NRVec<Int4>& vec_Zn, const SymMat<Double>& S_super)
109 {
110 const Int4 ISIZE = vec_Zn.size();
111 assert( ISIZE + 1 == S_super.size() );
112
113 Double ans = 0.0;
114 for(Int4 i=0; i<ISIZE; i++)
115 {
116 for(Int4 j=0; j<i; j++)
117 {
118 ans += S_super(i,j)*(vec_Zn[i]*vec_Zn[j]*2);
119 }
120 ans += S_super(i,i)*(vec_Zn[i]*vec_Zn[i]);
121 }
122 return ans;
123 }
124
125 static void set_candidate_Q(const Int4& index,
126 const SymMat<Double>& S_super,
127 const Double& maxQ,
128 const SymMat<Int4>& max_range,
129 NRVec<Int4>& vec_Zn, vector<HKL_Q>& qcal_tray)
130 {
131 const Int4 ISIZE = vec_Zn.size();
132 assert( ISIZE + 1 == S_super.size() );
133
134 if( index >= ISIZE ) // coef is determined.
135 {
136 const Double Q = norm( vec_Zn, S_super );
137 if( maxQ >= Q )
138 {
139 qcal_tray.push_back(HKL_Q(vec_Zn, Q));
140 }
141 return;
142 }
143
144 // vec_Zn[index] <= max_coef
145 // vec_Zn[index] >= min_coef
146 Int4 max_coef = max_range(index,index);
147 Int4 min_coef = -max_range(index,index);
148 for(Int4 k=0; k<index; k++)
149 {
150 // vec_Zn[index] - vec_Zn[k] <= max_range(k,index).
151 max_coef = min( max_coef, max_range(k,index) + vec_Zn[k] );
152
153 // -max_range(k,index) <= vec_Zn[index] - vec_Zn[k].
154 min_coef = max( min_coef, -max_range(k,index) + vec_Zn[k] );
155 }
156
157 // First non-zero entry should be positive.
158 bool non_zero_entry = false;
159 for(Int4 i=0; i<index; i++)
160 {
161 if( vec_Zn[i] != 0 )
162 {
163 non_zero_entry = true;
164 break;
165 }
166 }
167 if( !non_zero_entry ) min_coef = 0;
168
169 for(Int4 ic=max_coef; ic>=min_coef; ic--)
170 {
171 vec_Zn[index] = ic;
172 set_candidate_Q(index+1, S_super, maxQ, max_range, vec_Zn, qcal_tray);
173 }
174 }
175
176
177 // On input, S_super = TransMat * S * transpose(TransMat).
178 void gatherQcal(const SymMat<Double>& S_super,
179 const Double& maxQ,
180 vector<HKL_Q>& qcal_tray
181 )
182 {
183 qcal_tray.clear();
184
185 const Int4 ISIZE = S_super.size() - 1;
186 assert( 1 <= ISIZE && ISIZE <= 4 );
187
188 SymMat<Int4> max_range(ISIZE);
189 set_max_range(S_super, maxQ, max_range);
190 arrange_max_range(max_range);
191
192 NRVec<Int4> vec_ZN(ISIZE);
193 set_candidate_Q(0, S_super, maxQ, max_range, vec_ZN, qcal_tray);
194
195 sort( qcal_tray.begin(), qcal_tray.end() );
196 }
197
198
199 bool associateQcalWithQobs(
200 const vector<HKL_Q>::const_iterator& it_begin,
201 const vector<HKL_Q>::const_iterator& it_end,
202 const Int4& scale_of_qcal,
203 const vector<Double>& qobs_tray,
204 const Double& resol)
205 {
206 vector<Double>::const_iterator it_begin2, it_end2;
207 for(vector<HKL_Q>::const_iterator it=it_begin; it<it_end; it++)
208 {
209 it_begin2 = lower_bound( qobs_tray.begin(), qobs_tray.end(), it->Q()*scale_of_qcal*(1.0 - resol) );
210 it_end2 = upper_bound( it_begin2, qobs_tray.end(), it->Q()*scale_of_qcal*(1.0 + resol) );
211 if( it_begin2 >= it_end2 ) return false;
212 }
213 return true;
214 }
215
216
217 void associateQobsWithQcal(
218 vector<Double>::const_iterator it_begin, vector<Double>::const_iterator it_end,
219 const vector<HKL_Q>& qcal_tray,
220 vector< vector<HKL_Q>::const_iterator >& closest_qcal_tray)
221 {
222 closest_qcal_tray.clear();
223
224 for(vector<Double>::const_iterator it=it_begin; it<it_end; it++)
225 {
226 closest_qcal_tray.push_back( closest_data(qcal_tray.begin(), qcal_tray.end(), *it) );
227 }
228 }
229
230
231 vector<Double>::const_iterator associateQobsWithQcal(
232 const vector<Double>::const_iterator& it_begin,
233 const vector<Double>::const_iterator& it_end,
234 const vector<HKL_Q>& qcal_tray, const Double& resol,
235 vector< vector<HKL_Q>::const_iterator >& closest_qcal_tray)
236 {
237 closest_qcal_tray.clear();
238
239 vector<HKL_Q>::const_iterator it_begin2, it_end2;
240 for(vector<Double>::const_iterator it=it_begin; it<it_end; it++)
241 {
242 it_begin2 = lower_bound( qcal_tray.begin(), qcal_tray.end(), HKL_Q(NRVec<Int4>(), *it*(1.0 - resol) ) );
243 it_end2 = upper_bound( it_begin2, qcal_tray.end(), HKL_Q(NRVec<Int4>(), *it*(1.0 + resol) ) );
244 if( it_begin2 >= it_end2 ) return it;
245 else closest_qcal_tray.push_back( closest_data(it_begin2, it_end2, *it) );
246 }
247 return it_end;
248 }

Back to OSDN">Back to OSDN
ViewVC Help
Powered by ViewVC 1.1.26