Develop and Download Open Source Software

Browse Subversion Repository

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 25 - (hide 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: 32770 byte(s)
Source codes of version 0.9.99
1 rtomiyasu 3 /*
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 rtomiyasu 25 #include "../utility_data_structure/FracMat.hh"
28 rtomiyasu 3 #include "../utility_func/chToDouble.hh"
29 rtomiyasu 25 #include "../utility_lattice_reduction/put_Selling_reduced_lattice.hh"
30     #include "../utility_lattice_reduction/put_Buerger_reduced_lattice.hh"
31 rtomiyasu 3 #include "../laue_group/LaueGroup.hh"
32     #include "../point_group/PGNormalSeriesTray.hh"
33     #include "../model_function/LatticeDistanceModel.hh"
34     #include "../zlog/zlog.hh"
35 rtomiyasu 25 #include "gather_q_of_3D_lattice.hh"
36     #include "gather_q_of_Ndim_lattice.hh"
37     #include "ReducedLatticeToCheckBravais.hh"
38 rtomiyasu 3 #include "LatticeFigureOfMerit.hh"
39    
40     const Double LatticeFigureOfMerit::m_cv2 = 9.0;
41    
42     const NRMat<Int4> LatticeFigureOfMerit::m_tmat_prim_to_face = put_transform_matrix_row3to4( transpose( BravaisType::putTransformMatrixFromPrimitiveToFace() ) );
43     const NRMat<Int4> LatticeFigureOfMerit::m_tmat_prim_to_body = put_transform_matrix_row3to4( BravaisType::putTransformMatrixFromBodyToPrimitive() );
44     const NRMat<Int4> LatticeFigureOfMerit::m_tmat_prim_to_rhomhex = put_transform_matrix_row3to4( transpose( BravaisType::putTransformMatrixFromPrimitiveToRhomHex() ) );
45     const NRMat<Int4> LatticeFigureOfMerit::m_tmat_prim_to_base[3] =
46     {
47     put_transform_matrix_row3to4( transpose( BravaisType::putTransformMatrixFromPrimitiveToBase(BaseA_Axis) ) ),
48     put_transform_matrix_row3to4( transpose( BravaisType::putTransformMatrixFromPrimitiveToBase(BaseB_Axis) ) ),
49     put_transform_matrix_row3to4( transpose( BravaisType::putTransformMatrixFromPrimitiveToBase(BaseC_Axis) ) )
50     };
51     const NRMat<Int4> LatticeFigureOfMerit::m_tmat_prim_to_prim = put_transform_matrix_row3to4();
52    
53     LatticeFigureOfMerit::LatticeFigureOfMerit()
54     : m_S_optimized( SymMat43_Double( SymMat<Double>(3), NRMat<Int4>(4,3) ) ), m_S_red(3),
55     m_determ_S_red(0.0)
56     {
57     }
58    
59    
60     LatticeFigureOfMerit::LatticeFigureOfMerit(const Double& rhs)
61     : m_S_optimized( SymMat43_Double( SymMat<Double>(3), NRMat<Int4>(4,3) ) ), m_S_red(3),
62     m_determ_S_red(rhs)
63     {
64     }
65    
66    
67     LatticeFigureOfMerit::LatticeFigureOfMerit(const BravaisType& brat,
68     const SymMat43_Double& S)
69     : m_S_optimized( SymMat43_Double( SymMat<Double>(3), NRMat<Int4>(4,3) ) ), m_S_red(3)
70     {
71     this->setLatticeConstants43(brat, S);
72     }
73    
74     #ifdef DEBUG
75     static bool checkInitialLatticeParameters(
76     const BravaisType& brat,
77     const SymMat<Double>& S_red)
78     {
79     const SymMat<Double> inv_S_red( Inverse3(S_red) );
80    
81 rtomiyasu 25 if( brat.enumLaueGroup() == C2h_Y && brat.enumCentringType() == Prim )
82 rtomiyasu 3 {
83     assert( inv_S_red(0,2) <= 0.0 &&
84     inv_S_red(0,0) * 0.9999 < inv_S_red(2,2)
85     && fabs( inv_S_red(0,2) ) * 1.9999 < inv_S_red(2,2)
86     && fabs( inv_S_red(0,2) ) * 1.9999 < inv_S_red(0,0) );
87     }
88 rtomiyasu 25 else if( brat.enumLaueGroup() == C2h_Z && brat.enumCentringType() == Prim )
89 rtomiyasu 3 {
90     assert( inv_S_red(0,1) <= 0.0
91     && inv_S_red(0,0) * 0.9999 < inv_S_red(1,1)
92     && fabs( inv_S_red(0,1) ) * 1.9999 < inv_S_red(0,0)
93     && fabs( inv_S_red(0,1) ) * 1.9999 < inv_S_red(1,1) );
94     }
95 rtomiyasu 25 else if( brat.enumLaueGroup() == C2h_X && brat.enumCentringType() == Prim )
96 rtomiyasu 3 {
97     assert( inv_S_red(1,2) <= 0.0
98     && inv_S_red(1,1) * 0.9999 < inv_S_red(2,2)
99     && fabs( inv_S_red(1,2) ) * 1.9999 < inv_S_red(1,1)
100     && fabs( inv_S_red(1,2) ) * 1.9999 < inv_S_red(2,2) );
101     }
102 rtomiyasu 25 else if( brat.enumLaueGroup() == C2h_Y && brat.enumCentringType() == BaseZ )
103 rtomiyasu 3 {
104     assert( inv_S_red(0,2) <= 0.0
105     && fabs( inv_S_red(0,2) ) * 0.9999 < inv_S_red(2,2)
106     && fabs( inv_S_red(0,2) ) * 1.9999 < inv_S_red(0,0) );
107     }
108 rtomiyasu 25 else if( brat.enumLaueGroup() == C2h_Z && brat.enumCentringType() == BaseX )
109 rtomiyasu 3 {
110     assert( inv_S_red(0,1) <= 0.0
111     && fabs( inv_S_red(0,1) ) * 0.9999 < inv_S_red(0,0)
112     && fabs( inv_S_red(0,1) ) * 1.9999 < inv_S_red(1,1) );
113     }
114 rtomiyasu 25 else if( brat.enumLaueGroup() == C2h_X && brat.enumCentringType() == BaseY )
115 rtomiyasu 3 {
116     assert( inv_S_red(1,2) <= 0.0
117     && fabs( inv_S_red(1,2) ) * 0.9999 < inv_S_red(1,1)
118     && fabs( inv_S_red(1,2) ) * 1.9999 < inv_S_red(2,2) );
119     }
120 rtomiyasu 25 else if( brat.enumBravaisType() == Orthorhombic_C )
121 rtomiyasu 3 {
122 rtomiyasu 25 assert( brat.enumCentringType() == BaseZ );
123 rtomiyasu 3 assert( inv_S_red(0,0) * 0.9999 < inv_S_red(1,1) );
124     }
125 rtomiyasu 25 else if( brat.enumLaueGroup() == D2h && brat.enumCentringType() == Prim )
126 rtomiyasu 3 {
127     assert( inv_S_red(0,0) * 0.9999 < inv_S_red(1,1)
128     && inv_S_red(1,1) * 0.9999 < inv_S_red(2,2) );
129     }
130     return true;
131     }
132     #endif
133    
134 rtomiyasu 25 void putTransformMatrixToBuergerReduced(const SymMat<Double>& S, NRMat<Int4>& trans_mat)
135 rtomiyasu 3 {
136     assert( S.size() == 3 );
137    
138     SymMat<Double> S_super_obtuse(4);
139 rtomiyasu 25 put_Selling_reduced_dim_less_than_4(S, S_super_obtuse, trans_mat);
140     moveSmallerDiagonalLeftUpper(S_super_obtuse, trans_mat);
141 rtomiyasu 3
142     // S_red = trans_mat * S_super_obtuse * transpose(trans_mat).
143     SymMat<Double> S_red(3);
144     NRMat<Int4> trans_mat2;
145 rtomiyasu 25 putBuergerReducedMatrix(S_super_obtuse, S_red, trans_mat2);
146 rtomiyasu 3 trans_mat = mprod( trans_mat2, put_transform_matrix_row4to3(trans_mat) );
147     }
148    
149    
150 rtomiyasu 25 void LatticeFigureOfMerit::setInverseOfBuergerReducedForm(NRMat<Int4>& trans_mat)
151 rtomiyasu 3 {
152 rtomiyasu 25 if( m_brat.enumBravaisType() == Triclinic )
153 rtomiyasu 3 {
154 rtomiyasu 25 // trans_mat * Inverse(m_S_optimized.first) * transpose(trans_mat) is Buerger-reduced
155     // <=> Inverse of transpose(Inverse(trans_mat)) * m_S_optimized.first * Inverse(trans_mat) is Buerger-reduced.
156     putTransformMatrixToBuergerReduced(Inverse3(m_S_optimized.first), trans_mat);
157 rtomiyasu 3 transpose_square_matrix(trans_mat);
158     m_S_red = transform_sym_matrix(Inverse3(trans_mat), m_S_optimized.first);
159     }
160     else
161     {
162     m_S_red = m_S_optimized.first;
163     trans_mat = identity_matrix<Int4>(3);
164 rtomiyasu 25 if( m_brat.enumBravaisType() == Monoclinic_P )
165 rtomiyasu 3 {
166 rtomiyasu 17 if( m_brat.enumLaueGroup() == C2h_X )
167 rtomiyasu 3 {
168 rtomiyasu 25 putBuergerReducedMonoclinicP(1, 2, m_S_red, trans_mat);
169 rtomiyasu 3 }
170 rtomiyasu 17 else if( m_brat.enumLaueGroup() == C2h_Y )
171 rtomiyasu 3 {
172 rtomiyasu 25 putBuergerReducedMonoclinicP(0, 2, m_S_red, trans_mat);
173 rtomiyasu 3 }
174 rtomiyasu 17 else //if( m_brat.enumLaueGroup() == C2h_Z )
175 rtomiyasu 3 {
176 rtomiyasu 25 putBuergerReducedMonoclinicP(0, 1, m_S_red, trans_mat);
177 rtomiyasu 3 }
178     }
179 rtomiyasu 25 else if( m_brat.enumBravaisType() == Monoclinic_B )
180 rtomiyasu 3 {
181     m_S_red = m_S_optimized.first;
182 rtomiyasu 25 putBuergerReducedMonoclinicB(m_brat, m_S_red, trans_mat);
183 rtomiyasu 3 }
184 rtomiyasu 17 else if( m_brat.enumLaueGroup() == D2h )
185 rtomiyasu 3 {
186     m_S_red = m_S_optimized.first;
187 rtomiyasu 25 putBuergerReducedOrthorhombic(m_brat.enumCentringType(), m_S_red, trans_mat);
188 rtomiyasu 3 }
189     }
190    
191     assert( checkInitialLatticeParameters(m_brat, m_S_red) );
192     }
193    
194    
195     // This method assumes that S.second * S.first * Transpose(S.second) is obtuse.
196     void LatticeFigureOfMerit::setLatticeConstants43(const BravaisType& brat, const SymMat43_Double& S)
197     {
198     m_brat = brat;
199     m_S_optimized = S;
200    
201     NRMat<Int4> trans_mat;
202 rtomiyasu 25 setInverseOfBuergerReducedForm(trans_mat); // Set m_S_red from m_S_optimized.
203 rtomiyasu 3
204     m_determ_S_red = Determinant3( m_S_optimized.first );
205     m_figures_of_merit.reset();
206     }
207    
208    
209     ZErrorMessage LatticeFigureOfMerit::setLatticeConstants(const BravaisType& brat, const SymMat<Double>& Sval)
210     {
211     assert( Sval.size()==3 );
212    
213     SymMat43_Double S_red_optimized = SymMat43_Double(Sval, NRMat<Int4>(4,3));
214 rtomiyasu 17 cal_average_crystal_system(brat.enumLaueGroup(), S_red_optimized.first);
215 rtomiyasu 25 if( brat.enumCentringType() == Face )
216 rtomiyasu 3 {
217     S_red_optimized.second = m_tmat_prim_to_face;
218     }
219 rtomiyasu 25 else if( brat.enumCentringType() == Inner )
220 rtomiyasu 3 {
221     S_red_optimized.second = m_tmat_prim_to_body;
222     }
223 rtomiyasu 25 else if( brat.enumCentringType() == BaseX
224     || brat.enumCentringType() == BaseY
225     || brat.enumCentringType() == BaseZ )
226 rtomiyasu 3 {
227 rtomiyasu 25 S_red_optimized.second = m_tmat_prim_to_base[ (size_t)brat.enumBASEaxis() ];
228 rtomiyasu 3 }
229 rtomiyasu 25 else if( brat.enumCentringType() == Rhom_hex )
230 rtomiyasu 3 {
231     S_red_optimized.second = m_tmat_prim_to_rhomhex;
232     }
233 rtomiyasu 25 else // if( brat.enumCentringType() == Prim )
234 rtomiyasu 3 {
235     S_red_optimized.second = m_tmat_prim_to_prim;
236     }
237    
238     // S_super_obtuse = trans_mat * S_red.first * Transpose(trans_mat).
239     SymMat<Double> S_super_obtuse = transform_sym_matrix(S_red_optimized.second, S_red_optimized.first);
240 rtomiyasu 25 if( !put_Selling_reduced_dim_less_than_4(S_super_obtuse, S_red_optimized.second) )
241 rtomiyasu 3 {
242     return ZErrorMessage(ZErrorArgument, "The argument matrix is not positive definite" __FILE__, __LINE__, __FUNCTION__);
243     }
244 rtomiyasu 25 moveSmallerDiagonalLeftUpper(S_super_obtuse, S_red_optimized.second);
245 rtomiyasu 3
246     setLatticeConstants43(brat, S_red_optimized);
247    
248     return ZErrorMessage();
249     }
250    
251    
252     inline bool checkIfFirstEntryIsPositive(const VecDat3<Int4>& rhs)
253     {
254     for(Int4 i=0; i<3; i++)
255     {
256     if( rhs[i] == 0 ) continue;
257     if( rhs[i] > 0 ) return true;
258     else return false;
259     }
260     return false;
261     }
262    
263    
264 rtomiyasu 25 static bool cmp_func(const HKL_Q& lhs, const HKL_Q& rhs)
265     {
266     if( lhs.Q() < rhs.Q() ) return true;
267     else if( lhs.Q() > rhs.Q() ) return false;
268     return abs(lhs.HKL()[0])+abs(lhs.HKL()[1])+abs(lhs.HKL()[2]) < abs(rhs.HKL()[0])+abs(rhs.HKL()[1])+abs(rhs.HKL()[2]);
269     };
270    
271    
272     void LatticeFigureOfMerit::putMillerIndicesInRange(const Double& qend,
273 rtomiyasu 3 vector<HKL_Q>& cal_hkl_tray) const
274     {
275     cal_hkl_tray.clear();
276    
277     vector<HKL_Q> cal_hkl_tray2;
278 rtomiyasu 25 gatherQcal(this->putSellingReducedForm(), qend, cal_hkl_tray2);
279 rtomiyasu 3
280     set< VecDat3<Int4> > found_hkl_tray;
281     vector<MillerIndex3> equiv_hkl_tray;
282     VecDat3<Int4> hkl;
283    
284 rtomiyasu 17 PGNormalSeriesTray normal_tray(m_brat.enumLaueGroup());
285     LaueGroup lg(m_brat.enumLaueGroup());
286 rtomiyasu 3
287 rtomiyasu 25 for(vector<HKL_Q>::const_iterator it=upper_bound(cal_hkl_tray2.begin(), cal_hkl_tray2.end(), HKL_Q(NRVec<Int4>(), 0.0));
288 rtomiyasu 3 it<cal_hkl_tray2.end(); it++)
289     {
290     hkl = product_hkl(it->HKL(), m_S_optimized.second);
291     if( found_hkl_tray.find(hkl) != found_hkl_tray.end() )
292     {
293     continue;
294     }
295     if( !checkIfFirstEntryIsPositive(hkl) ) hkl *= -1;
296    
297     normal_tray.putHKLEquiv(MillerIndex3(hkl[0], hkl[1], hkl[2]), equiv_hkl_tray);
298     #ifdef DEBUG
299     if( (Int4)equiv_hkl_tray.size() != lg->LaueMultiplicity(hkl) )
300     {
301     ZLOG_INFO( num2str(hkl[0]) + " "
302     + num2str(hkl[1]) + " "
303     + num2str(hkl[2]) + "\n"
304     + num2str( equiv_hkl_tray.size() ) + "\n"
305     + num2str( lg->LaueMultiplicity(hkl) ) + "\n" );
306     }
307     #endif
308    
309     for(vector<MillerIndex3>::const_iterator ithkl=equiv_hkl_tray.begin(); ithkl<equiv_hkl_tray.end(); ithkl++)
310     {
311     found_hkl_tray.insert( VecDat3<Int4>( (*ithkl)[0], (*ithkl)[1], (*ithkl)[2] ) );
312     }
313    
314     cal_hkl_tray.push_back( HKL_Q(hkl, it->Q()) );
315     }
316 rtomiyasu 25 sort( cal_hkl_tray.begin(), cal_hkl_tray.end(), cmp_func );
317 rtomiyasu 3 }
318    
319    
320     void LatticeFigureOfMerit::setFigureOfMerit(const Int4& num_ref_figure_of_merit,
321     const vector<QData>& qdata,
322     vector< VecDat3<Int4> >& closest_hkl_tray,
323     Vec_BOOL& Q_observed_flag)
324     {
325     assert( num_ref_figure_of_merit <= (Int4)qdata.size() );
326    
327     // Qdata is sorted into ascended order.
328     m_figures_of_merit.reset();
329     m_figures_of_merit.putNumberOfReflectionsForFigureOfMerit() = num_ref_figure_of_merit;
330    
331     const Int4& num_Q = m_figures_of_merit.putNumberOfReflectionsForFigureOfMerit();
332     closest_hkl_tray.clear();
333     Q_observed_flag.clear();
334     closest_hkl_tray.resize(num_Q, 0);
335     Q_observed_flag.resize(num_Q, false);
336    
337     if( num_Q <= 0 ) return;
338    
339 rtomiyasu 25 // const Double MinQ = qdata[0].q - sqrt( m_cv2 * qdata[0].q_var );
340 rtomiyasu 3 const Double MaxQ = qdata[num_Q-1].q + sqrt( m_cv2 * qdata[num_Q-1].q_var );
341     const SymMat<Double> S_sup( this->putSellingReducedForm() );
342    
343     vector<HKL_Q> cal_hkl_tray;
344 rtomiyasu 25 gatherQcal(S_sup, MaxQ, cal_hkl_tray);
345 rtomiyasu 3 if( cal_hkl_tray.empty() ) return;
346    
347     vector< vector<HKL_Q>::const_iterator > closest_hkl_q_tray;
348 rtomiyasu 25 associateQobsWithQcal(qdata.begin(), qdata.begin()+num_Q, cal_hkl_tray, closest_hkl_q_tray);
349 rtomiyasu 3 const vector<HKL_Q>::const_iterator it_begin = closest_hkl_q_tray[0];
350     const vector<HKL_Q>::const_iterator it_end = closest_hkl_q_tray[num_Q-1] + 1;
351     assert( it_end <= cal_hkl_tray.end() );
352     if( it_begin + 1 >= it_end ) return;
353    
354     Double diff;
355     Double actually_disc = 0.0;
356     Int4 num_q_observed = 0;
357     for(Int4 k=0; k<num_Q; k++)
358     {
359     closest_hkl_tray[k] = product_hkl( closest_hkl_q_tray[k]->HKL(), m_S_optimized.second);
360     diff = qdata[k].q - closest_hkl_q_tray[k]->Q();
361     actually_disc += fabs( diff );
362     if( diff * diff <= m_cv2 * qdata[k].q_var )
363     {
364     Q_observed_flag[k] = true;
365     num_q_observed++;
366     }
367     else Q_observed_flag[k] = false;
368     }
369     actually_disc /= num_Q;
370     m_figures_of_merit.putNumQobsAssociatedWithCloseHKL() = num_q_observed;
371    
372     vector< vector<QData>::const_iterator > closest_q_tray;
373 rtomiyasu 25 associateQcalWithQobs(it_begin, it_end, qdata, closest_q_tray);
374 rtomiyasu 3
375 rtomiyasu 17 const LaueGroup lg(m_brat.enumLaueGroup());
376 rtomiyasu 3
377     Double inv_mult = 2.0 / lg->LaueMultiplicity( product_hkl(it_begin->HKL(), m_S_optimized.second) );
378     Double num_total_hkl = inv_mult;
379     Double rev_actually_disc = fabs( it_begin->Q() - closest_q_tray[0]->q ) * inv_mult;
380    
381     Double sum_diff = 0.0;
382     Int4 index = 1;
383     for(vector<HKL_Q>::const_iterator it=it_begin+1; it<it_end; it++, index++)
384     {
385     inv_mult = 2.0 / lg->LaueMultiplicity( product_hkl(it->HKL(), m_S_optimized.second) );
386     num_total_hkl += inv_mult;
387     rev_actually_disc += fabs( it->Q() - closest_q_tray[index]->q ) * inv_mult;
388    
389     diff = it->Q() - (it-1)->Q();
390     sum_diff += diff * diff;
391     }
392     m_figures_of_merit.putContinuousNumberOfHKLInRange() = num_total_hkl;
393     rev_actually_disc /= num_total_hkl;
394    
395     // Calculate the symmetric figures of merit by Wolff.
396     m_figures_of_merit.putFigureOfMeritWolff() = ( (it_end - 1)->Q() - it_begin->Q() ) / ( 2.0*actually_disc*num_total_hkl );
397     m_figures_of_merit.putFigureOfMeritWu() = sum_diff / ( 4.0 * actually_disc * ( (it_end - 1)->Q() - it_begin->Q() ) );
398     m_figures_of_merit.putReversedFigureOfMerit() = ( qdata[num_Q-1].q - qdata[0].q ) / ( 2.0*rev_actually_disc*num_Q );
399 rtomiyasu 25 }
400 rtomiyasu 3
401 rtomiyasu 25
402    
403    
404     void LatticeFigureOfMerit::setDeWolffFigureOfMerit(const Int4& num_ref_figure_of_merit,
405     const vector<QData>& qdata)
406     {
407     assert( num_ref_figure_of_merit <= (Int4)qdata.size() );
408    
409     // Qdata is sorted into ascended order.
410     m_figures_of_merit.reset();
411     m_figures_of_merit.putNumberOfReflectionsForFigureOfMerit() = num_ref_figure_of_merit;
412    
413     const Int4& num_Q = m_figures_of_merit.putNumberOfReflectionsForFigureOfMerit();
414     if( num_Q <= 0 ) return;
415    
416     const Double MaxQ = qdata[num_Q-1].q + sqrt( m_cv2 * qdata[num_Q-1].q_var );
417     const SymMat<Double> S_sup( this->putSellingReducedForm() );
418    
419     vector<HKL_Q> cal_hkl_tray;
420     gatherQcal(S_sup, MaxQ, cal_hkl_tray);
421     if( cal_hkl_tray.empty() ) return;
422    
423     vector< vector<HKL_Q>::const_iterator > closest_hkl_q_tray;
424     associateQobsWithQcal(qdata.begin(), qdata.begin()+num_Q, cal_hkl_tray, closest_hkl_q_tray);
425     const vector<HKL_Q>::const_iterator it_begin = closest_hkl_q_tray[0];
426     const vector<HKL_Q>::const_iterator it_end = closest_hkl_q_tray[num_Q-1] + 1;
427     assert( it_end <= cal_hkl_tray.end() );
428     if( it_begin + 1 >= it_end ) return;
429    
430     Double actually_disc = 0.0;
431     for(Int4 k=0; k<num_Q; k++)
432     {
433     actually_disc += fabs( qdata[k].q - closest_hkl_q_tray[k]->Q() );
434     }
435     actually_disc /= num_Q;
436    
437     const LaueGroup lg(m_brat.enumLaueGroup());
438     Double num_total_hkl = 0.0;
439     for(vector<HKL_Q>::const_iterator it=it_begin; it<it_end; it++)
440     {
441     num_total_hkl += 2.0 / lg->LaueMultiplicity( product_hkl(it->HKL(), m_S_optimized.second) );
442     }
443    
444     // Calculate the symmetric figures of merit by Wolff.
445     m_figures_of_merit.putFigureOfMeritWolff() = ( (it_end - 1)->Q() - it_begin->Q() ) / ( 2.0*actually_disc*num_total_hkl );
446 rtomiyasu 3 }
447    
448    
449    
450     void LatticeFigureOfMerit::setWuFigureOfMerit(const Int4& num_ref_figure_of_merit,
451     const vector<QData>& qdata,
452     const Double& min_thred_num_hkl,
453     const Double& max_thred_num_hkl)
454     {
455     m_figures_of_merit.reset();
456     m_figures_of_merit.putNumberOfReflectionsForFigureOfMerit() = min( num_ref_figure_of_merit, (Int4)qdata.size() );
457     const Int4& num_Q = m_figures_of_merit.putNumberOfReflectionsForFigureOfMerit();
458     if( num_Q <= 0 ) return;
459    
460     const Double MinQ = qdata[0].q - sqrt( m_cv2 * qdata[0].q_var );
461     const Double MaxQ = qdata[num_Q-1].q + sqrt( m_cv2 * qdata[num_Q-1].q_var );
462    
463     const SymMat<Double> S_sup( this->putSellingReducedForm() );
464    
465     vector<HKL_Q> cal_hkl_tray;
466 rtomiyasu 25 gatherQcal(S_sup, MaxQ, cal_hkl_tray);
467     const Double num_hkl_in_range = distance( lower_bound(cal_hkl_tray.begin(), cal_hkl_tray.end(), HKL_Q(0,MinQ)), cal_hkl_tray.end() );
468     if( num_hkl_in_range < num_Q * min_thred_num_hkl ) return;
469     if( num_hkl_in_range > num_Q * max_thred_num_hkl ) return;
470 rtomiyasu 3
471     vector< vector<HKL_Q>::const_iterator > closest_hkl_q_tray;
472 rtomiyasu 25 associateQobsWithQcal(qdata.begin(), qdata.begin()+num_Q, cal_hkl_tray, closest_hkl_q_tray);
473 rtomiyasu 3 const vector<HKL_Q>::const_iterator it_begin = closest_hkl_q_tray[0];
474     const vector<HKL_Q>::const_iterator it_end = closest_hkl_q_tray[num_Q-1] + 1;
475     assert( it_end <= cal_hkl_tray.end() );
476     if( it_begin + 1 >= it_end ) return;
477    
478     Double actually_disc = 0.0;
479     for(Int4 k=0; k<num_Q; k++)
480     {
481     actually_disc += fabs( qdata[k].q - closest_hkl_q_tray[k]->Q() );
482     }
483     actually_disc /= num_Q;
484    
485     Double sum_diff = 0.0, diff;
486     for(vector<HKL_Q>::const_iterator it=it_begin+1; it<it_end; it++)
487     {
488     diff = it->Q() - (it-1)->Q();
489     sum_diff += diff * diff;
490     }
491    
492     // Calculate the figure of merit by Wu.
493     m_figures_of_merit.putFigureOfMeritWu() = sum_diff / ( 4.0 * actually_disc * ( (it_end - 1)->Q() - it_begin->Q() ) );
494     }
495    
496    
497     pair<bool, ZErrorMessage> LatticeFigureOfMerit::fitLatticeParameterLinear(
498     const vector<QData>& qdata,
499     const vector< VecDat3<Int4> >& hkl_to_fit,
500     const vector<bool>& fix_or_fit_flag, const bool& output_view_flag)
501     {
502 rtomiyasu 25 const size_t isize = hkl_to_fit.size();
503 rtomiyasu 3
504     assert( hkl_to_fit.size() == fix_or_fit_flag.size() );
505     assert( hkl_to_fit.size() <= qdata.size() );
506    
507     Vec_DP ydata(isize), ydata_err(isize);
508     Vec_BOOL nxfit(isize);
509     Int4 data_num=0;
510    
511 rtomiyasu 25 for(size_t i=0; i<isize; i++)
512 rtomiyasu 3 {
513     ydata[i] = qdata[i].q;
514     ydata_err[i] = sqrt_d( qdata[i].q_var );
515     if( ydata_err[i] <= 0.0 )
516     {
517     nxfit[i] = false;
518     }
519     else
520     {
521     nxfit[i] = fix_or_fit_flag[i];
522     if( nxfit[i] ) data_num++;
523     }
524     }
525    
526 rtomiyasu 17 LaueGroup lg(m_brat.enumLaueGroup());
527 rtomiyasu 3 Mat_DP_constr cmat;
528     lg->putLatticeConstantFlag(cmat);
529     if( data_num <= countNumberOfIndependentParam(cmat.begin(),cmat.end()) )
530     {
531     return pair<bool, ZErrorMessage>(false, ZErrorMessage("NUMBER OF DATA IS TOO SMALL", __FILE__, __LINE__, __FUNCTION__));
532     }
533     setIndex(cmat);
534    
535     vector<Double> init_param(6);
536     const SymMat<Double>& S_val = this->putOptimizedForm().first;
537     init_param[0] = S_val(0,0);
538     init_param[1] = S_val(1,1);
539     init_param[2] = S_val(2,2);
540     init_param[3] = S_val(1,2);
541     init_param[4] = S_val(0,2);
542     init_param[5] = S_val(0,1);
543    
544     LatticeDistanceModel latModel;
545     latModel.setConstraint(&cmat[0]);
546     Double chisq_all;
547     pair<bool, ZErrorMessage> ans = latModel.setFittedParam(hkl_to_fit, ydata, ydata_err, nxfit,
548     output_view_flag, 0.0, 1, init_param, chisq_all);
549     if( !(ans.first)) return ans;
550    
551     LatticeFigureOfMerit new_lat(*this);
552     SymMat<Double> S_red_optimized(3);
553     latModel.putResult(S_red_optimized);
554     new_lat.setLatticeConstants(m_brat, S_red_optimized);
555     new_lat.setFigureOfMerit( m_figures_of_merit.putNumberOfReflectionsForFigureOfMerit(), qdata );
556    
557     if( cmpFOMdeWolff(new_lat, *this) )
558     {
559     *this = new_lat;
560     return pair<bool, ZErrorMessage>(true, ZErrorMessage());
561     }
562     else return pair<bool, ZErrorMessage>(false, ZErrorMessage());
563     }
564    
565    
566 rtomiyasu 25 void LatticeFigureOfMerit::putEquivalentLatticeConstantsDegreeWithOtherCentring(
567     const eABCaxis& abc_axis, const eRHaxis& rh_axis, const Double& resol,
568     vector< pair< eBravaisType, SymMat<Double> > >& ans) const
569     {
570     ans.clear();
571    
572     // Calculate figures of merit as triclinic
573     const ReducedLatticeToCheckBravais RLCB(abc_axis, rh_axis, false, resol, this->putSellingReducedForm());
574     const SymMat<Double> S_obtuse = this->putSellingReducedForm();
575    
576     if( this->enumBravaisType() != Rhombohedral )
577     {
578     const map< SymMat<Double>, NRMat<Int4> >& S_red_tray = RLCB.checkCentringType(BravaisType(Rhombohedral, abc_axis, rh_axis));
579     for(map< SymMat<Double>, NRMat<Int4> >::const_iterator it=S_red_tray.begin(); it!=S_red_tray.end(); it++)
580     {
581     ans.push_back( pair< eBravaisType, SymMat<Double> >(Rhombohedral, it->first) );
582     }
583     }
584     if( this->enumCentringType() != Face )
585     {
586     const map< SymMat<Double>, NRMat<Int4> >& S_red_tray = RLCB.checkCentringType(BravaisType(Orthorhombic_F, abc_axis, rh_axis));
587     for(map< SymMat<Double>, NRMat<Int4> >::const_iterator it=S_red_tray.begin(); it!=S_red_tray.end(); it++)
588     {
589     ans.push_back( pair< eBravaisType, SymMat<Double> >(Orthorhombic_F, it->first) );
590     }
591     }
592     if( this->enumCentringType() != Inner )
593     {
594     const map< SymMat<Double>, NRMat<Int4> >& S_red_tray = RLCB.checkCentringType(BravaisType(Orthorhombic_I, abc_axis, rh_axis));
595     for(map< SymMat<Double>, NRMat<Int4> >::const_iterator it=S_red_tray.begin(); it!=S_red_tray.end(); it++)
596     {
597     ans.push_back( pair< eBravaisType, SymMat<Double> >(Orthorhombic_I, it->first) );
598     }
599     }
600     if( this->enumCentringType() != BaseX && this->enumCentringType() != BaseY && this->enumCentringType() != BaseZ )
601     {
602     const map< SymMat<Double>, NRMat<Int4> >& S_red_tray = RLCB.checkCentringType(BravaisType(Monoclinic_B, abc_axis, rh_axis));
603     for(map< SymMat<Double>, NRMat<Int4> >::const_iterator it=S_red_tray.begin(); it!=S_red_tray.end(); it++)
604     {
605     ans.push_back( pair< eBravaisType, SymMat<Double> >(Monoclinic_B, it->first) );
606     }
607     }
608    
609     NRMat<Int4> trans_mat;
610     SymMat<Double> S_red(3);
611     if( this->enumBravaisType() == Rhombohedral || this->enumCentringType() != Prim )
612     {
613     const SymMat<Double> S_super = put_sym_matrix_sizeNplus1toN(this->putSellingReducedForm());
614     putTransformMatrixToBuergerReduced(Inverse3(S_super), trans_mat);
615     transpose_square_matrix(trans_mat);
616     ans.push_back( pair< eBravaisType, SymMat<Double> >(Triclinic, transform_sym_matrix(Inverse3(trans_mat), S_super) ) );
617     }
618     }
619    
620    
621     void LatticeFigureOfMerit::putEquivalentLatticeConstantsDegreeWithOtherCentring(
622     const eABCaxis& abc_axis, const eRHaxis& rh_axis, const Double& resol,
623     vector< pair< eBravaisType, pair< VecDat3<Double>, VecDat3<Double> > > >& ans) const
624     {
625     vector< pair< eBravaisType, SymMat<Double> > > ans0;
626     putEquivalentLatticeConstantsDegreeWithOtherCentring(abc_axis, rh_axis, resol, ans0);
627    
628     ans.clear();
629     ans.resize( ans0.size() );
630     vector< pair< eBravaisType, pair< VecDat3<Double>, VecDat3<Double> > > >::iterator it2 = ans.begin();
631     for(vector< pair< eBravaisType, SymMat<Double> > >::const_iterator it=ans0.begin(); it<ans0.end(); it++, it2++)
632     {
633     it2->first = it->first;
634     LatticeFigureOfMerit::putLatticeConstantsDegree( BravaisType(it->first, abc_axis, rh_axis), it->second, abc_axis, rh_axis, it2->second.first, it2->second.second );
635     }
636     }
637    
638    
639 rtomiyasu 3 void LatticeFigureOfMerit::printLatticeInformation(
640     const eABCaxis& abc_axis,
641     const eRHaxis& rh_axis,
642 rtomiyasu 25 const Double& resol,
643 rtomiyasu 3 const Int4& label_start0,
644     ostream* os) const
645     {
646     Int4 label_start = label_start0;
647     os->width(label_start);
648     *os << "" << "<CrystalSystem>";
649     os->width(17);
650 rtomiyasu 25 *os << put_bravais_type_name(this->enumBravaisType(), abc_axis);
651 rtomiyasu 3 *os << " </CrystalSystem>\n\n";
652    
653     os->width(label_start); *os << "";
654     *os << "<!-- a, b, c(angstrom), alpha, beta, gamma(deg.)-->\n";
655    
656     VecDat3<Double> length_axis, angle_axis;
657 rtomiyasu 25 if( this->enumBravaisType() == Rhombohedral )
658 rtomiyasu 3 {
659     this->putReducedLatticeConstantsDegree(abc_axis, Rho_Axis, length_axis, angle_axis);
660    
661     os->width(label_start); *os << "";
662     *os << "<ReducedLatticeParameters axis=\"Rhombohedral\">";
663     os->width(14);
664     *os << length_axis[0];
665     os->width(14);
666     *os << length_axis[1];
667     os->width(14);
668     *os << length_axis[2];
669     os->width(14);
670     *os << angle_axis[0];
671     os->width(14);
672     *os << angle_axis[1];
673     os->width(14);
674     *os << angle_axis [2];
675     *os << " </ReducedLatticeParameters>\n";
676    
677     this->putReducedLatticeConstantsDegree(abc_axis, Hex_Axis, length_axis, angle_axis);
678    
679     os->width(label_start); *os << "";
680     *os << "<ReducedLatticeParameters axis=\"Hexagonal\">";
681     os->width(14);
682     *os << length_axis[0];
683     os->width(14);
684     *os << length_axis[1];
685     os->width(14);
686     *os << length_axis[2];
687     os->width(14);
688     *os << angle_axis[0];
689     os->width(14);
690     *os << angle_axis[1];
691     os->width(14);
692     *os << angle_axis[2];
693     *os << " </ReducedLatticeParameters>\n\n";
694     }
695     else
696     {
697     this->putReducedLatticeConstantsDegree(abc_axis, Rho_Axis, length_axis, angle_axis);
698    
699     os->width(label_start); *os << "";
700     *os << "<ReducedLatticeParameters>";
701     os->width(14);
702     *os << length_axis[0];
703     os->width(14);
704     *os << length_axis[1];
705     os->width(14);
706     *os << length_axis[2];
707     os->width(14);
708     *os << angle_axis[0];
709     os->width(14);
710     *os << angle_axis[1];
711     os->width(14);
712     *os << angle_axis[2];
713     *os << " </ReducedLatticeParameters>\n";
714     }
715    
716     this->putOptimizedLatticeConstantsDegree(abc_axis, rh_axis, length_axis, angle_axis);
717    
718     os->width(label_start); *os << "";
719     *os << "<OptimizedLatticeParameters>";
720     os->width(14);
721     *os << length_axis[0];
722     os->width(14);
723     *os << length_axis[1];
724     os->width(14);
725     *os << length_axis[2];
726     os->width(14);
727     *os << angle_axis[0];
728     os->width(14);
729     *os << angle_axis[1];
730     os->width(14);
731     *os << angle_axis[2];
732     *os << " </OptimizedLatticeParameters>\n\n";
733    
734     os->width(label_start); *os << "";
735 rtomiyasu 25 if( this->enumBravaisType() == Rhombohedral )
736 rtomiyasu 3 {
737     if( rh_axis == Hex_Axis )
738     {
739     *os << "<VolumeOfUnitCell axis=\"Hexagonal\">";
740     os->width(14);
741     *os << this->putLatticeVolume();
742     }
743     else // if( rh_axis == Rho_Axis )
744     {
745     *os << "<VolumeOfUnitCell axis=\"Rhombohedral\">";
746     os->width(14);
747     *os << this->putLatticeVolume() / 3.0;
748     }
749     }
750     else{
751     *os << "<VolumeOfUnitCell>";
752     os->width(14);
753     *os << this->putLatticeVolume();
754     }
755     *os << " </VolumeOfUnitCell>\n";
756    
757     const SetOfFigureOfMerit& critical_value = this->putFiguresOfMerit();
758    
759     os->width(label_start); *os << "";
760     *os << "<FigureOfMeritWolff name=\"" << critical_value.putLabel_FigureOfMeritWolff() << "\">";
761     os->width(14);
762     *os << critical_value.putFigureOfMeritWolff();
763     *os << " </FigureOfMeritWolff>\n";
764    
765     os->width(label_start);
766     *os << "" << "<FigureOfMeritWu name=\"" << critical_value.putLabel_FigureOfMeritWu() << "\">";
767     os->width(14);
768     *os << critical_value.putFigureOfMeritWu();
769     *os << " </FigureOfMeritWu>\n";
770    
771     os->width(label_start);
772     *os << "" << "<ReversedFigureOfMeritWolff name=\"" << critical_value.putLabel_ReversedFigureOfMeritWolff() << "\">";
773     os->width(14);
774     *os << critical_value.putReversedFigureOfMerit();
775     *os << " </ReversedFigureOfMeritWolff>\n";
776    
777     os->width(label_start);
778     *os << "" << "<SymmetricFigureOfMeritWolff name=\"" << critical_value.putLabel_SymmetricFigureOfMeritWolff() << "\">";
779     os->width(14);
780     *os << critical_value.putSymmetricFigureOfMerit();
781     *os << " </SymmetricFigureOfMeritWolff>\n";
782    
783     os->width(label_start);
784     *os << "" << "<!-- Number of reflections up to the ";
785     *os << critical_value.putNumberOfReflectionsForFigureOfMerit() << "th reflection. (The multiplicity of peaks is considered.)-->\n";
786     os->width(label_start);
787     *os << "" << "<NumberOfMillerIndicesInRange>";
788     os->width(14);
789     *os << critical_value.putContinuousNumberOfHKLInRange();
790     *os << " </NumberOfMillerIndicesInRange>\n";
791    
792     os->width(label_start);
793     *os << "" << "<NumberOfIndexedPeaks>";
794     os->width(14);
795     *os << critical_value.putNumQobsAssociatedWithCloseHKL();
796     *os << " </NumberOfIndexedPeaks>\n";
797    
798     os->width(label_start);
799     *os << "" << "<NumberOfPeaksNecessaryToResolveDominantZone>";
800     os->width(14);
801     *os << this->checkDominantZone();
802     *os << " </NumberOfPeaksNecessaryToResolveDominantZone>\n\n";
803 rtomiyasu 25
804    
805    
806     os->width(label_start);
807     *os << "" << "<EquivalentLatticeCandidates>\n";
808     *os << "" << "<!-- Almost equivalent unitcell parameters of different centring types. -->\n";
809     label_start++;
810    
811     vector< pair< eBravaisType, pair< VecDat3<Double>, VecDat3<Double> > > > lattice_equiv;
812     this->putEquivalentLatticeConstantsDegreeWithOtherCentring(abc_axis, rh_axis, resol, lattice_equiv);
813    
814     for(vector< pair< eBravaisType, pair< VecDat3<Double>, VecDat3<Double> > > >::const_iterator it=lattice_equiv.begin(); it<lattice_equiv.end(); it++)
815     {
816     os->width(label_start); *os << "";
817     *os << "<LatticeCandidate>\n";
818     label_start++;
819    
820     os->width(label_start); *os << "";
821     *os << "<Centring>";
822     os->width(17);
823     if( it->first == Rhombohedral && rh_axis == Rho_Axis )
824     {
825     *os << "Rhombohedral(rhombohedral-axis)";
826     }
827     else *os << put_centring_name( BravaisType(it->first, abc_axis, rh_axis).enumCentringType() );
828     *os << " </Centring>\n";
829    
830     os->width(label_start);
831     *os << "" << "<LatticeParameters>";
832     os->width(14);
833     *os << it->second.first[0];
834     os->width(14);
835     *os << it->second.first[1];
836     os->width(14);
837     *os << it->second.first[2];
838     os->width(14);
839     *os << it->second.second[0];
840     os->width(14);
841     *os << it->second.second[1];
842     os->width(14);
843     *os << it->second.second[2];
844     *os << " </LatticeParameters>\n";
845    
846     label_start--;
847     os->width(label_start); *os << "";
848     *os << "</LatticeCandidate>\n";
849     }
850    
851     label_start--;
852     os->width(label_start); *os << "";
853     *os << "</EquivalentLatticeCandidates>\n\n";
854 rtomiyasu 3 }
855    
856    
857     void LatticeFigureOfMerit::putLatticeConstantsDegree(const BravaisType& brat, const SymMat<Double>& S0,
858     const eABCaxis& axis1,
859     const eRHaxis& axis2, VecDat3<Double>& length_axis, VecDat3<Double>& angle_axis)
860     {
861     SymMat<Double> S = S0;
862 rtomiyasu 25 if( brat.enumBravaisType() == Rhombohedral && axis2 != brat.enumRHaxis() )
863 rtomiyasu 3 {
864     if( axis2 == Hex_Axis ) // Rho -> Hex.
865     {
866     static const FracMat matrix_rho2hex = FInverse3( transpose(BravaisType::putTransformMatrixFromPrimitiveToRhomHex() ) );
867     S = transform_sym_matrix(matrix_rho2hex.mat, S)/(matrix_rho2hex.denom*matrix_rho2hex.denom);
868     }
869     else // if( axis2 == RhoAxis ) // Hex -> Rho.
870     {
871     static const NRMat<Int4> matrix_hex2rho = transpose( BravaisType::putTransformMatrixFromPrimitiveToRhomHex() );
872     S = transform_sym_matrix(matrix_hex2rho, S);
873     }
874     }
875 rtomiyasu 25 else if( brat.enumBravaisType() == Monoclinic_B )
876 rtomiyasu 3 {
877     const NRMat<Int4> this2output = put_transform_matrix_monoclinic_b(brat.enumABCaxis(), axis1);
878     S = transform_sym_matrix(this2output, S);
879     }
880    
881     calLatticeConstant( S, length_axis, angle_axis );
882     }
883    
884    
885    
886     Int4 LatticeFigureOfMerit::checkDominantZone() const
887     {
888     const vector<QData> qdata = VCData::putPeakQData();
889     if( qdata.empty() )
890     {
891 rtomiyasu 17 if( this->enumLaueGroup() == Ci ) return 6;
892     else if( this->enumLaueGroup() == C2h_X || this->enumLaueGroup() == C2h_Y || this->enumLaueGroup() == C2h_Z ) return 4;
893     else if( this->enumLaueGroup() == D2h ) return 3;
894     else if( this->enumLaueGroup() == D4h_Z || this->enumLaueGroup() == D31d_rho || this->enumLaueGroup() == D6h ) return 2;
895     else if( this->enumLaueGroup() == Oh ) return 1;
896 rtomiyasu 3 assert(false);
897     }
898    
899     const SymMat<Double> S_super = this->putSellingReducedForm();
900     const Double max_q = max(
901     max( max( S_super(0,0), S_super(1,1) ), max( S_super(2,2), S_super(3,3) ) ),
902     max( max( S_super(0,0) + S_super(1,1) + S_super(0,1)*2.0,
903     S_super(0,0) + S_super(2,2) + S_super(0,2)*2.0 ),
904     S_super(1,1) + S_super(2,2) + S_super(1,2)*2.0 ) );
905    
906     return distance( qdata.begin(), lower_bound( qdata.begin(), qdata.end(), QData( qdata.begin()->q + max_q, 0.0 ) ) ) + 1;
907     }

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