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 3 - (hide annotations) (download) (as text)
Fri Feb 22 04:51:31 2013 UTC (11 years, 1 month ago) by rtomiyasu
File MIME type: text/x-c++src
File size: 28145 byte(s)


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     #ifdef _OPENMP
28     # include <omp.h>
29     #endif
30     #include "../utility_func/chToDouble.hh"
31     #include "../utility_lattice_reduction/super_basis3.hh"
32     #include "../utility_lattice_reduction/put_Minkowski_reduced_lattice.hh"
33     #include "../laue_group/LaueGroup.hh"
34     #include "../point_group/PGNormalSeriesTray.hh"
35     #include "../model_function/LatticeDistanceModel.hh"
36     #include "../zlog/zlog.hh"
37     #include "gather_additional_Q.hh"
38     #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     if( brat.enumPointGroup() == C2h_Y && brat.enumBravaisLattice() == Prim )
82     {
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     else if( brat.enumPointGroup() == C2h_Z && brat.enumBravaisLattice() == Prim )
89     {
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     else if( brat.enumPointGroup() == C2h_X && brat.enumBravaisLattice() == Prim )
96     {
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     else if( brat.enumPointGroup() == C2h_Y && brat.enumBravaisLattice() == BaseZ )
103     {
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     else if( brat.enumPointGroup() == C2h_Z && brat.enumBravaisLattice() == BaseX )
109     {
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     else if( brat.enumPointGroup() == C2h_X && brat.enumBravaisLattice() == BaseY )
115     {
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     else if( brat.enumCrystalSystem() == Orthorhombic_C )
121     {
122     assert( brat.enumBravaisLattice() == BaseZ );
123     assert( inv_S_red(0,0) * 0.9999 < inv_S_red(1,1) );
124     }
125     else if( brat.enumPointGroup() == D2h && brat.enumBravaisLattice() == Prim )
126     {
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     //static Double put_minimum_lattice_point_distance(const SymMat<Double>& S_super)
135     //{
136     // Double ans = S_super(0,0);
137     // if( S_super(1,1) < ans ) ans = S_super(1,1);
138     // if( S_super(2,2) < ans ) ans = S_super(2,2);
139     // if( S_super(3,3) < ans ) ans = S_super(3,3);
140     // const Double S_super01 = S_super(0,0)+S_super(1,1)+S_super(0,1)*2.0;
141     // if( S_super01 < ans ) ans = S_super01;
142     // const Double S_super02 = S_super(0,0)+S_super(2,2)+S_super(0,2)*2.0;
143     // if( S_super02 < ans ) ans = S_super02;
144     // const Double S_super12 = S_super(1,1)+S_super(2,2)+S_super(1,2)*2.0;
145     // if( S_super12 < ans ) ans = S_super12;
146     // return ans;
147     //}
148    
149    
150     void putTransformMatrixToMinkowskiReduced(const SymMat<Double>& S, NRMat<Int4>& trans_mat)
151     {
152     assert( S.size() == 3 );
153    
154     SymMat<Double> S_super_obtuse(4);
155     put_super_Gram_matrix_obtuse_angle<Double, SymMat<Double> >(S, S_super_obtuse, trans_mat);
156     moveSmallerDiagonalLeftUpper<Double, SymMat<Double> >(S_super_obtuse, trans_mat);
157    
158     // S_red = trans_mat * S_super_obtuse * transpose(trans_mat).
159     SymMat<Double> S_red(3);
160     NRMat<Int4> trans_mat2;
161     putMinkowskiReduced(S_super_obtuse, S_red, trans_mat2);
162     trans_mat = mprod( trans_mat2, put_transform_matrix_row4to3(trans_mat) );
163     }
164    
165    
166     void LatticeFigureOfMerit::setInverseOfMinkowskiReducedForm(NRMat<Int4>& trans_mat)
167     {
168     if( m_brat.enumCrystalSystem() == Triclinic )
169     {
170     // trans_mat * Inverse(m_S_optimized.first) * transpose(trans_mat) is Minkowski reduced
171     // <=> Inverse of transpose(Inverse(trans_mat)) * m_S_optimized.first * Inverse(trans_mat) is Minkowski reduced.
172     putTransformMatrixToMinkowskiReduced(Inverse3(m_S_optimized.first), trans_mat);
173     transpose_square_matrix(trans_mat);
174     m_S_red = transform_sym_matrix(Inverse3(trans_mat), m_S_optimized.first);
175     }
176     else
177     {
178     m_S_red = m_S_optimized.first;
179     trans_mat = identity_matrix<Int4>(3);
180     if( m_brat.enumCrystalSystem() == Monoclinic_P )
181     {
182     if( m_brat.enumPointGroup() == C2h_X )
183     {
184     putMinkowskiReducedMonoclinicP(1, 2, m_S_red, trans_mat);
185     }
186     else if( m_brat.enumPointGroup() == C2h_Y )
187     {
188     putMinkowskiReducedMonoclinicP(0, 2, m_S_red, trans_mat);
189     }
190     else //if( m_brat.enumPointGroup() == C2h_Z )
191     {
192     putMinkowskiReducedMonoclinicP(0, 1, m_S_red, trans_mat);
193     }
194     }
195     else if( m_brat.enumCrystalSystem() == Monoclinic_B )
196     {
197     m_S_red = m_S_optimized.first;
198     putMinkowskiReducedMonoclinicB(m_brat, m_S_red, trans_mat);
199     }
200     else if( m_brat.enumPointGroup() == D2h )
201     {
202     m_S_red = m_S_optimized.first;
203     putMinkowskiReducedOrthorhombic(m_brat.enumBravaisLattice(), m_S_red, trans_mat);
204     }
205     }
206    
207     assert( checkInitialLatticeParameters(m_brat, m_S_red) );
208     }
209    
210    
211     // This method assumes that S.second * S.first * Transpose(S.second) is obtuse.
212     void LatticeFigureOfMerit::setLatticeConstants43(const BravaisType& brat, const SymMat43_Double& S)
213     {
214     m_brat = brat;
215     m_S_optimized = S;
216    
217     NRMat<Int4> trans_mat;
218     setInverseOfMinkowskiReducedForm(trans_mat); // Set m_S_red from m_S_optimized.
219    
220     m_determ_S_red = Determinant3( m_S_optimized.first );
221     m_figures_of_merit.reset();
222     }
223    
224    
225     ZErrorMessage LatticeFigureOfMerit::setLatticeConstants(const BravaisType& brat, const SymMat<Double>& Sval)
226     {
227     assert( Sval.size()==3 );
228    
229     SymMat43_Double S_red_optimized = SymMat43_Double(Sval, NRMat<Int4>(4,3));
230     cal_average_crystal_system(brat.enumPointGroup(), S_red_optimized.first);
231     if( brat.enumBravaisLattice() == Face )
232     {
233     S_red_optimized.second = m_tmat_prim_to_face;
234     }
235     else if( brat.enumBravaisLattice() == Inner )
236     {
237     S_red_optimized.second = m_tmat_prim_to_body;
238     }
239     else if( brat.enumBravaisLattice() == BaseX
240     || brat.enumBravaisLattice() == BaseY
241     || brat.enumBravaisLattice() == BaseZ )
242     {
243     S_red_optimized.second = m_tmat_prim_to_base[ (ArrayIndex)brat.enumBASEaxis() ];
244     }
245     else if( brat.enumBravaisLattice() == Rhom_hex )
246     {
247     S_red_optimized.second = m_tmat_prim_to_rhomhex;
248     }
249     else // if( brat.enumBravaisLattice() == Prim )
250     {
251     S_red_optimized.second = m_tmat_prim_to_prim;
252     }
253    
254     // S_super_obtuse = trans_mat * S_red.first * Transpose(trans_mat).
255     SymMat<Double> S_super_obtuse = transform_sym_matrix(S_red_optimized.second, S_red_optimized.first);
256     Int4 itnum;
257     if( !put_super_Gram_matrix_obtuse_angle< Double, SymMat<Double> >(S_red_optimized.second, S_super_obtuse, itnum) )
258     {
259     return ZErrorMessage(ZErrorArgument, "The argument matrix is not positive definite" __FILE__, __LINE__, __FUNCTION__);
260     }
261     moveSmallerDiagonalLeftUpper< Double, SymMat<Double> >(S_super_obtuse, S_red_optimized.second);
262    
263     setLatticeConstants43(brat, S_red_optimized);
264    
265     return ZErrorMessage();
266     }
267    
268    
269     inline bool checkIfFirstEntryIsPositive(const VecDat3<Int4>& rhs)
270     {
271     for(Int4 i=0; i<3; i++)
272     {
273     if( rhs[i] == 0 ) continue;
274     if( rhs[i] > 0 ) return true;
275     else return false;
276     }
277     return false;
278     }
279    
280    
281     void LatticeFigureOfMerit::putMillerIndicesInRange(const Double& qbegin, const Double& qend,
282     vector<HKL_Q>& cal_hkl_tray) const
283     {
284     cal_hkl_tray.clear();
285    
286     vector<HKL_Q> cal_hkl_tray2;
287     gatherQcal(this->putSellingReducedForm(),
288     qbegin, qend,
289     40, cal_hkl_tray2);
290    
291     set< VecDat3<Int4> > found_hkl_tray;
292     vector<MillerIndex3> equiv_hkl_tray;
293     VecDat3<Int4> hkl;
294    
295     PGNormalSeriesTray normal_tray(m_brat.enumPointGroup());
296     LaueGroup lg(m_brat.enumPointGroup());
297    
298     for(vector<HKL_Q>::const_iterator it=upper_bound(cal_hkl_tray2.begin(), cal_hkl_tray2.end(), HKL_Q(0, 0.0));
299     it<cal_hkl_tray2.end(); it++)
300     {
301     hkl = product_hkl(it->HKL(), m_S_optimized.second);
302     if( found_hkl_tray.find(hkl) != found_hkl_tray.end() )
303     {
304     continue;
305     }
306     if( !checkIfFirstEntryIsPositive(hkl) ) hkl *= -1;
307    
308     normal_tray.putHKLEquiv(MillerIndex3(hkl[0], hkl[1], hkl[2]), equiv_hkl_tray);
309     #ifdef DEBUG
310     if( (Int4)equiv_hkl_tray.size() != lg->LaueMultiplicity(hkl) )
311     {
312     ZLOG_INFO( num2str(hkl[0]) + " "
313     + num2str(hkl[1]) + " "
314     + num2str(hkl[2]) + "\n"
315     + num2str( equiv_hkl_tray.size() ) + "\n"
316     + num2str( lg->LaueMultiplicity(hkl) ) + "\n" );
317     }
318     #endif
319    
320     for(vector<MillerIndex3>::const_iterator ithkl=equiv_hkl_tray.begin(); ithkl<equiv_hkl_tray.end(); ithkl++)
321     {
322     found_hkl_tray.insert( VecDat3<Int4>( (*ithkl)[0], (*ithkl)[1], (*ithkl)[2] ) );
323     }
324    
325     cal_hkl_tray.push_back( HKL_Q(hkl, it->Q()) );
326     }
327     sort( cal_hkl_tray.begin(), cal_hkl_tray.end() );
328     }
329    
330    
331     void LatticeFigureOfMerit::setFigureOfMerit(const Int4& num_ref_figure_of_merit,
332     const vector<QData>& qdata,
333     vector< VecDat3<Int4> >& closest_hkl_tray,
334     Vec_BOOL& Q_observed_flag)
335     {
336     assert( num_ref_figure_of_merit <= (Int4)qdata.size() );
337    
338     // Qdata is sorted into ascended order.
339     m_figures_of_merit.reset();
340     m_figures_of_merit.putNumberOfReflectionsForFigureOfMerit() = num_ref_figure_of_merit;
341    
342     const Int4& num_Q = m_figures_of_merit.putNumberOfReflectionsForFigureOfMerit();
343     closest_hkl_tray.clear();
344     Q_observed_flag.clear();
345     closest_hkl_tray.resize(num_Q, 0);
346     Q_observed_flag.resize(num_Q, false);
347    
348     if( num_Q <= 0 ) return;
349    
350     const Double MinQ = qdata[0].q - sqrt( m_cv2 * qdata[0].q_var );
351     const Double MaxQ = qdata[num_Q-1].q + sqrt( m_cv2 * qdata[num_Q-1].q_var );
352     const SymMat<Double> S_sup( this->putSellingReducedForm() );
353    
354     vector<HKL_Q> cal_hkl_tray;
355     gatherQcal(S_sup, MinQ, MaxQ, num_Q+1, cal_hkl_tray);
356     if( cal_hkl_tray.empty() ) return;
357    
358     vector< vector<HKL_Q>::const_iterator > closest_hkl_q_tray;
359     associateQcalWithQobs(cal_hkl_tray, qdata.begin(), qdata.begin()+num_Q, closest_hkl_q_tray);
360     const vector<HKL_Q>::const_iterator it_begin = closest_hkl_q_tray[0];
361     const vector<HKL_Q>::const_iterator it_end = closest_hkl_q_tray[num_Q-1] + 1;
362     assert( it_end <= cal_hkl_tray.end() );
363     if( it_begin + 1 >= it_end ) return;
364    
365     Double diff;
366     Double actually_disc = 0.0;
367     // Double norm_actually_disc = 0.0;
368     Int4 num_q_observed = 0;
369     for(Int4 k=0; k<num_Q; k++)
370     {
371     closest_hkl_tray[k] = product_hkl( closest_hkl_q_tray[k]->HKL(), m_S_optimized.second);
372     diff = qdata[k].q - closest_hkl_q_tray[k]->Q();
373     actually_disc += fabs( diff );
374     // norm_actually_disc += fabs( sqrt3_2(qdata[k].q) - sqrt3_2((*closest_hkl_q_tray[k].rbegin())->Q()) );
375     if( diff * diff <= m_cv2 * qdata[k].q_var )
376     {
377     Q_observed_flag[k] = true;
378     num_q_observed++;
379     }
380     else Q_observed_flag[k] = false;
381     }
382     actually_disc /= num_Q;
383     // norm_actually_disc /= num_Q;
384     m_figures_of_merit.putNumQobsAssociatedWithCloseHKL() = num_q_observed;
385    
386     vector< vector<QData>::const_iterator > closest_q_tray;
387     associateQobsWithQcal(qdata, it_begin, it_end, closest_q_tray);
388    
389     const LaueGroup lg(m_brat.enumPointGroup());
390    
391     Double inv_mult = 2.0 / lg->LaueMultiplicity( product_hkl(it_begin->HKL(), m_S_optimized.second) );
392     Double num_total_hkl = inv_mult;
393     Double rev_actually_disc = fabs( it_begin->Q() - closest_q_tray[0]->q ) * inv_mult;
394    
395     Double sum_diff = 0.0;
396     Int4 index = 1;
397     for(vector<HKL_Q>::const_iterator it=it_begin+1; it<it_end; it++, index++)
398     {
399     inv_mult = 2.0 / lg->LaueMultiplicity( product_hkl(it->HKL(), m_S_optimized.second) );
400     num_total_hkl += inv_mult;
401     rev_actually_disc += fabs( it->Q() - closest_q_tray[index]->q ) * inv_mult;
402    
403     diff = it->Q() - (it-1)->Q();
404     sum_diff += diff * diff;
405     }
406     m_figures_of_merit.putContinuousNumberOfHKLInRange() = num_total_hkl;
407     rev_actually_disc /= num_total_hkl;
408    
409     // Double sum_diff = 0.0;
410     // Int4 disc_num_total_hkl = 1;
411     // for(vector<HKL_Q>::const_iterator it=it_begin+1; it<it_end; it++)
412     // {
413     // diff = it->Q() - (it-1)->Q();
414     // sum_diff += diff * diff;
415     //
416     // if( it->Q() <= (it-1)->Q() ) continue;
417     // disc_num_total_hkl += 1;
418     // }
419     // m_figures_of_merit.putDiscreteNumberOfHKLInRange() = disc_num_total_hkl;
420     //
421     // Double rev_sum_diff = 0.0;
422     // for(Int4 k=1; k<num_Q; k++)
423     // {
424     // diff = qdata[k].q - qdata[k-1].q;
425     // rev_sum_diff += diff * diff;
426     // }
427    
428     // Calculate the symmetric figures of merit by Wolff.
429     m_figures_of_merit.putFigureOfMeritWolff() = ( (it_end - 1)->Q() - it_begin->Q() ) / ( 2.0*actually_disc*num_total_hkl );
430     // m_figures_of_merit.putNormalizedFigureOfMeritWolff() = ( sqrt3_2((it_end - 1)->Q()) - sqrt3_2(it_begin->Q()) ) / ( 2.0*norm_actually_disc*num_total_hkl );
431     m_figures_of_merit.putFigureOfMeritWu() = sum_diff / ( 4.0 * actually_disc * ( (it_end - 1)->Q() - it_begin->Q() ) );
432     m_figures_of_merit.putReversedFigureOfMerit() = ( qdata[num_Q-1].q - qdata[0].q ) / ( 2.0*rev_actually_disc*num_Q );
433    
434     // sum_diff = 0.0;
435     // disc_num_total_hkl = 0;
436     // for(vector<HKL_Q>::const_iterator it=cal_hkl_tray.begin()+1; it<it_end; it++)
437     // {
438     // diff = it->Q() - (it-1)->Q();
439     // sum_diff += diff * diff;
440     //
441     // if( (it-1)->Q() < it->Q() ) disc_num_total_hkl++;
442     // }
443     //
444     // m_figures_of_merit.putFigureOfMeritWolff_Original() = qdata[num_Q-1].q / ( 2.0*actually_disc*disc_num_total_hkl );
445     // m_figures_of_merit.putFigureOfMeritWu_Original() = sum_diff / ( 4.0 * actually_disc * (it_end - 1)->Q() );
446     }
447    
448    
449    
450    
451     void LatticeFigureOfMerit::setWuFigureOfMerit(const Int4& num_ref_figure_of_merit,
452     const vector<QData>& qdata,
453     const Double& min_thred_num_hkl,
454     const Double& max_thred_num_hkl)
455     {
456     m_figures_of_merit.reset();
457     m_figures_of_merit.putNumberOfReflectionsForFigureOfMerit() = min( num_ref_figure_of_merit, (Int4)qdata.size() );
458     const Int4& num_Q = m_figures_of_merit.putNumberOfReflectionsForFigureOfMerit();
459     if( num_Q <= 0 ) return;
460    
461     const Double MinQ = qdata[0].q - sqrt( m_cv2 * qdata[0].q_var );
462     const Double MaxQ = qdata[num_Q-1].q + sqrt( m_cv2 * qdata[num_Q-1].q_var );
463    
464     const SymMat<Double> S_sup( this->putSellingReducedForm() );
465    
466     vector<HKL_Q> cal_hkl_tray;
467     gatherQcal(S_sup, MinQ, MaxQ, num_Q+1, cal_hkl_tray);
468     if( (Double)cal_hkl_tray.size() < num_Q * min_thred_num_hkl ) return;
469     if( (Double)cal_hkl_tray.size() > num_Q * max_thred_num_hkl ) return;
470    
471     vector< vector<HKL_Q>::const_iterator > closest_hkl_q_tray;
472     associateQcalWithQobs(cal_hkl_tray, qdata.begin(), qdata.begin()+num_Q, closest_hkl_q_tray);
473     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     const ArrayIndex isize = hkl_to_fit.size();
503    
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     for(ArrayIndex i=0; i<isize; i++)
512     {
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     LaueGroup lg(m_brat.enumPointGroup());
527     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     void LatticeFigureOfMerit::printLatticeInformation(
567     const eABCaxis& abc_axis,
568     const eRHaxis& rh_axis,
569     const Int4& label_start0,
570     ostream* os) const
571     {
572     Int4 label_start = label_start0;
573     os->width(label_start);
574     *os << "" << "<CrystalSystem>";
575     os->width(17);
576     *os << put_cs_name(this->enumCrystalSystem(), abc_axis);
577     *os << " </CrystalSystem>\n\n";
578    
579     os->width(label_start); *os << "";
580     *os << "<!-- a, b, c(angstrom), alpha, beta, gamma(deg.)-->\n";
581    
582     VecDat3<Double> length_axis, angle_axis;
583     if( this->enumCrystalSystem() == Rhombohedral )
584     {
585     this->putReducedLatticeConstantsDegree(abc_axis, Rho_Axis, length_axis, angle_axis);
586    
587     os->width(label_start); *os << "";
588     *os << "<ReducedLatticeParameters axis=\"Rhombohedral\">";
589     os->width(14);
590     *os << length_axis[0];
591     os->width(14);
592     *os << length_axis[1];
593     os->width(14);
594     *os << length_axis[2];
595     os->width(14);
596     *os << angle_axis[0];
597     os->width(14);
598     *os << angle_axis[1];
599     os->width(14);
600     *os << angle_axis [2];
601     *os << " </ReducedLatticeParameters>\n";
602    
603     this->putReducedLatticeConstantsDegree(abc_axis, Hex_Axis, length_axis, angle_axis);
604    
605     os->width(label_start); *os << "";
606     *os << "<ReducedLatticeParameters axis=\"Hexagonal\">";
607     os->width(14);
608     *os << length_axis[0];
609     os->width(14);
610     *os << length_axis[1];
611     os->width(14);
612     *os << length_axis[2];
613     os->width(14);
614     *os << angle_axis[0];
615     os->width(14);
616     *os << angle_axis[1];
617     os->width(14);
618     *os << angle_axis[2];
619     *os << " </ReducedLatticeParameters>\n\n";
620     }
621     else
622     {
623     this->putReducedLatticeConstantsDegree(abc_axis, Rho_Axis, length_axis, angle_axis);
624    
625     os->width(label_start); *os << "";
626     *os << "<ReducedLatticeParameters>";
627     os->width(14);
628     *os << length_axis[0];
629     os->width(14);
630     *os << length_axis[1];
631     os->width(14);
632     *os << length_axis[2];
633     os->width(14);
634     *os << angle_axis[0];
635     os->width(14);
636     *os << angle_axis[1];
637     os->width(14);
638     *os << angle_axis[2];
639     *os << " </ReducedLatticeParameters>\n";
640     }
641    
642     this->putOptimizedLatticeConstantsDegree(abc_axis, rh_axis, length_axis, angle_axis);
643    
644     os->width(label_start); *os << "";
645     *os << "<OptimizedLatticeParameters>";
646     os->width(14);
647     *os << length_axis[0];
648     os->width(14);
649     *os << length_axis[1];
650     os->width(14);
651     *os << length_axis[2];
652     os->width(14);
653     *os << angle_axis[0];
654     os->width(14);
655     *os << angle_axis[1];
656     os->width(14);
657     *os << angle_axis[2];
658     *os << " </OptimizedLatticeParameters>\n\n";
659    
660     os->width(label_start); *os << "";
661     if( this->enumCrystalSystem() == Rhombohedral )
662     {
663     if( rh_axis == Hex_Axis )
664     {
665     *os << "<VolumeOfUnitCell axis=\"Hexagonal\">";
666     os->width(14);
667     *os << this->putLatticeVolume();
668     }
669     else // if( rh_axis == Rho_Axis )
670     {
671     *os << "<VolumeOfUnitCell axis=\"Rhombohedral\">";
672     os->width(14);
673     *os << this->putLatticeVolume() / 3.0;
674     }
675     }
676     else{
677     *os << "<VolumeOfUnitCell>";
678     os->width(14);
679     *os << this->putLatticeVolume();
680     }
681     *os << " </VolumeOfUnitCell>\n";
682    
683     const SetOfFigureOfMerit& critical_value = this->putFiguresOfMerit();
684    
685     os->width(label_start); *os << "";
686     *os << "<FigureOfMeritWolff name=\"" << critical_value.putLabel_FigureOfMeritWolff() << "\">";
687     os->width(14);
688     *os << critical_value.putFigureOfMeritWolff();
689     // *os << " (" << critical_value.putFigureOfMeritWolff_Original() << ")";
690     *os << " </FigureOfMeritWolff>\n";
691    
692     os->width(label_start);
693     *os << "" << "<FigureOfMeritWu name=\"" << critical_value.putLabel_FigureOfMeritWu() << "\">";
694     os->width(14);
695     *os << critical_value.putFigureOfMeritWu();
696     // *os << " (" << critical_value.putFigureOfMeritWu_Original() << ")";
697     *os << " </FigureOfMeritWu>\n";
698    
699     // os->width(label_start); *os << "";
700     // *os << "<NormalizedFigureOfMeritWolff name=\"" << critical_value.putLabel_NormalizedFigureOfMeritWolff() << "\">";
701     // os->width(14);
702     // *os << critical_value.putNormalizedFigureOfMeritWolff();
703     // *os << " </NormalizedFigureOfMeritWolff>\n";
704    
705     os->width(label_start);
706     *os << "" << "<ReversedFigureOfMeritWolff name=\"" << critical_value.putLabel_ReversedFigureOfMeritWolff() << "\">";
707     os->width(14);
708     *os << critical_value.putReversedFigureOfMerit();
709     *os << " </ReversedFigureOfMeritWolff>\n";
710    
711     os->width(label_start);
712     *os << "" << "<SymmetricFigureOfMeritWolff name=\"" << critical_value.putLabel_SymmetricFigureOfMeritWolff() << "\">";
713     os->width(14);
714     *os << critical_value.putSymmetricFigureOfMerit();
715     *os << " </SymmetricFigureOfMeritWolff>\n";
716    
717     os->width(label_start);
718     *os << "" << "<!-- Number of reflections up to the ";
719     *os << critical_value.putNumberOfReflectionsForFigureOfMerit() << "th reflection. (The multiplicity of peaks is considered.)-->\n";
720     os->width(label_start);
721     *os << "" << "<NumberOfMillerIndicesInRange>";
722     os->width(14);
723     *os << critical_value.putContinuousNumberOfHKLInRange();
724     *os << " </NumberOfMillerIndicesInRange>\n";
725    
726     os->width(label_start);
727     *os << "" << "<NumberOfIndexedPeaks>";
728     os->width(14);
729     *os << critical_value.putNumQobsAssociatedWithCloseHKL();
730     *os << " </NumberOfIndexedPeaks>\n";
731    
732     os->width(label_start);
733     *os << "" << "<NumberOfPeaksNecessaryToResolveDominantZone>";
734     os->width(14);
735     *os << this->checkDominantZone();
736     *os << " </NumberOfPeaksNecessaryToResolveDominantZone>\n\n";
737     }
738    
739    
740     void LatticeFigureOfMerit::putLatticeConstantsDegree(const BravaisType& brat, const SymMat<Double>& S0,
741     const eABCaxis& axis1,
742     const eRHaxis& axis2, VecDat3<Double>& length_axis, VecDat3<Double>& angle_axis)
743     {
744     SymMat<Double> S = S0;
745     if( brat.enumCrystalSystem() == Rhombohedral && axis2 != brat.enumRHaxis() )
746     {
747     if( axis2 == Hex_Axis ) // Rho -> Hex.
748     {
749     static const FracMat matrix_rho2hex = FInverse3( transpose(BravaisType::putTransformMatrixFromPrimitiveToRhomHex() ) );
750     S = transform_sym_matrix(matrix_rho2hex.mat, S)/(matrix_rho2hex.denom*matrix_rho2hex.denom);
751     }
752     else // if( axis2 == RhoAxis ) // Hex -> Rho.
753     {
754     static const NRMat<Int4> matrix_hex2rho = transpose( BravaisType::putTransformMatrixFromPrimitiveToRhomHex() );
755     S = transform_sym_matrix(matrix_hex2rho, S);
756     }
757     }
758     else if( brat.enumCrystalSystem() == Monoclinic_B )
759     {
760     const NRMat<Int4> this2output = put_transform_matrix_monoclinic_b(brat.enumABCaxis(), axis1);
761     S = transform_sym_matrix(this2output, S);
762     }
763    
764     calLatticeConstant( S, length_axis, angle_axis );
765     }
766    
767    
768    
769     Int4 LatticeFigureOfMerit::checkDominantZone() const
770     {
771     const vector<QData> qdata = VCData::putPeakQData();
772     if( qdata.empty() )
773     {
774     if( this->enumPointGroup() == Ci ) return 6;
775     else if( this->enumPointGroup() == C2h_X || this->enumPointGroup() == C2h_Y || this->enumPointGroup() == C2h_Z ) return 4;
776     else if( this->enumPointGroup() == D2h ) return 3;
777     else if( this->enumPointGroup() == D4h_Z || this->enumPointGroup() == D31d_rho || this->enumPointGroup() == D6h ) return 2;
778     else if( this->enumPointGroup() == Oh ) return 1;
779     assert(false);
780     }
781    
782     const SymMat<Double> S_super = this->putSellingReducedForm();
783     const Double max_q = max(
784     max( max( S_super(0,0), S_super(1,1) ), max( S_super(2,2), S_super(3,3) ) ),
785     max( max( S_super(0,0) + S_super(1,1) + S_super(0,1)*2.0,
786     S_super(0,0) + S_super(2,2) + S_super(0,2)*2.0 ),
787     S_super(1,1) + S_super(2,2) + S_super(1,2)*2.0 ) );
788    
789     return distance( qdata.begin(), lower_bound( qdata.begin(), qdata.end(), QData( qdata.begin()->q + max_q, 0.0 ) ) ) + 1;
790     }

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