Develop and Download Open Source Software

Browse Subversion Repository

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 33 - (hide annotations) (download) (as text)
Wed Sep 7 04:38:51 2016 UTC (7 years, 6 months ago) by rtomiyasu
File MIME type: text/x-c++src
File size: 8140 byte(s)
The output format for base-centered monoclinic cells was corrected.
1 rtomiyasu 25 /*
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     void gatherQcal(const SymMat<Double>& S_super,
178     const Double& maxQ,
179     vector<HKL_Q>& qcal_tray
180     )
181     {
182     qcal_tray.clear();
183    
184     const Int4 ISIZE = S_super.size() - 1;
185     assert( 1 <= ISIZE && ISIZE <= 4 );
186    
187     SymMat<Int4> max_range(ISIZE);
188     set_max_range(S_super, maxQ, max_range);
189     arrange_max_range(max_range);
190    
191     NRVec<Int4> vec_ZN(ISIZE);
192     set_candidate_Q(0, S_super, maxQ, max_range, vec_ZN, qcal_tray);
193    
194     sort( qcal_tray.begin(), qcal_tray.end() );
195     }
196    
197    
198 rtomiyasu 33 inline VecDat3<Int4> product_hkl(const VecDat3<Int4>& lhs, const NRMat<Int4>& rhs)
199     {
200     assert( rhs.nrows() >= 3 && rhs.ncols() == 3 );
201    
202     VecDat3<Int4> ans;
203     ans[0] = lhs[0]*rhs[0][0] + lhs[1]*rhs[1][0] + lhs[2]*rhs[2][0];
204     ans[1] = lhs[0]*rhs[0][1] + lhs[1]*rhs[1][1] + lhs[2]*rhs[2][1];
205     ans[2] = lhs[0]*rhs[0][2] + lhs[1]*rhs[1][2] + lhs[2]*rhs[2][2];
206     return ans;
207     }
208    
209    
210     // On input, S_super = TransMat * S * transpose(TransMat).
211     void gatherQcal(const SymMat<Double>& S_super,
212     const Double& maxQ,
213     const NRMat<Int4>& transform_hkl,
214     vector<HKL_Q>& qcal_tray
215     )
216     {
217     gatherQcal(S_super, maxQ, qcal_tray);
218    
219     for(vector<HKL_Q>::iterator it=qcal_tray.begin(); it<qcal_tray.end(); it++)
220     {
221     it->setHKL( product_hkl(it->HKL(), transform_hkl) );
222     }
223     }
224    
225    
226 rtomiyasu 25 bool associateQcalWithQobs(
227     const vector<HKL_Q>::const_iterator& it_begin,
228     const vector<HKL_Q>::const_iterator& it_end,
229     const Int4& scale_of_qcal,
230     const vector<Double>& qobs_tray,
231     const Double& resol)
232     {
233     vector<Double>::const_iterator it_begin2, it_end2;
234     for(vector<HKL_Q>::const_iterator it=it_begin; it<it_end; it++)
235     {
236     it_begin2 = lower_bound( qobs_tray.begin(), qobs_tray.end(), it->Q()*scale_of_qcal*(1.0 - resol) );
237     it_end2 = upper_bound( it_begin2, qobs_tray.end(), it->Q()*scale_of_qcal*(1.0 + resol) );
238     if( it_begin2 >= it_end2 ) return false;
239     }
240     return true;
241     }
242    
243    
244     void associateQobsWithQcal(
245     vector<Double>::const_iterator it_begin, vector<Double>::const_iterator it_end,
246     const vector<HKL_Q>& qcal_tray,
247     vector< vector<HKL_Q>::const_iterator >& closest_qcal_tray)
248     {
249     closest_qcal_tray.clear();
250    
251     for(vector<Double>::const_iterator it=it_begin; it<it_end; it++)
252     {
253     closest_qcal_tray.push_back( closest_data(qcal_tray.begin(), qcal_tray.end(), *it) );
254     }
255     }
256    
257    
258     vector<Double>::const_iterator associateQobsWithQcal(
259     const vector<Double>::const_iterator& it_begin,
260     const vector<Double>::const_iterator& it_end,
261     const vector<HKL_Q>& qcal_tray, const Double& resol,
262     vector< vector<HKL_Q>::const_iterator >& closest_qcal_tray)
263     {
264     closest_qcal_tray.clear();
265    
266     vector<HKL_Q>::const_iterator it_begin2, it_end2;
267     for(vector<Double>::const_iterator it=it_begin; it<it_end; it++)
268     {
269     it_begin2 = lower_bound( qcal_tray.begin(), qcal_tray.end(), HKL_Q(NRVec<Int4>(), *it*(1.0 - resol) ) );
270     it_end2 = upper_bound( it_begin2, qcal_tray.end(), HKL_Q(NRVec<Int4>(), *it*(1.0 + resol) ) );
271     if( it_begin2 >= it_end2 ) return it;
272     else closest_qcal_tray.push_back( closest_data(it_begin2, it_end2, *it) );
273     }
274     return it_end;
275     }

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