Develop and Download Open Source Software

Browse Subversion Repository

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

Parent Directory Parent Directory | Revision Log Revision Log


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

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