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 17 - (show annotations) (download) (as text)
Tue Apr 30 05:04:41 2013 UTC (10 years, 10 months ago) by rtomiyasu
File MIME type: text/x-c++src
File size: 28120 byte(s)
他のソフトウェアと使用するライブラリの共通化(ブラベー格子に関わる部分)
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 #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.enumLaueGroup() == 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.enumLaueGroup() == 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.enumLaueGroup() == 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.enumLaueGroup() == 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.enumLaueGroup() == 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.enumLaueGroup() == 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.enumLaueGroup() == 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.enumLaueGroup() == C2h_X )
183 {
184 putMinkowskiReducedMonoclinicP(1, 2, m_S_red, trans_mat);
185 }
186 else if( m_brat.enumLaueGroup() == C2h_Y )
187 {
188 putMinkowskiReducedMonoclinicP(0, 2, m_S_red, trans_mat);
189 }
190 else //if( m_brat.enumLaueGroup() == 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.enumLaueGroup() == 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.enumLaueGroup(), 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.enumLaueGroup());
296 LaueGroup lg(m_brat.enumLaueGroup());
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.enumLaueGroup());
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.enumLaueGroup());
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->enumLaueGroup() == Ci ) return 6;
775 else if( this->enumLaueGroup() == C2h_X || this->enumLaueGroup() == C2h_Y || this->enumLaueGroup() == C2h_Z ) return 4;
776 else if( this->enumLaueGroup() == D2h ) return 3;
777 else if( this->enumLaueGroup() == D4h_Z || this->enumLaueGroup() == D31d_rho || this->enumLaueGroup() == D6h ) return 2;
778 else if( this->enumLaueGroup() == 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