/** Get the UB matrix corresponding to the real space edge vectors a,b,c. The inverse of the matrix with vectors a,b,c as rows will be stored in UB. @param UB A 3x3 matrix that will be set to the UB matrix. @param a_dir The real space edge vector for side a of the unit cell @param b_dir The real space edge vector for side b of the unit cell @param c_dir The real space edge vector for side c of the unit cell @return true if UB was set to the new matrix and false if UB could not be set since the matrix with a,b,c as rows could not be inverted. */ bool OrientedLattice::GetUB(DblMatrix &UB, const V3D &a_dir, const V3D &b_dir, const V3D &c_dir) { if (UB.numRows() != 3 || UB.numCols() != 3) { throw std::invalid_argument("Find_UB(): UB matrix NULL or not 3X3"); } UB.setRow(0, a_dir); UB.setRow(1, b_dir); UB.setRow(2, c_dir); try { UB.Invert(); } catch (...) { return false; } return true; }
/** @param inname Name of workspace containing peaks @param params optimized cell parameters @param out residuals from optimization */ void OptimizeLatticeForCellType::optLattice(std::string inname, std::vector<double> ¶ms, double *out) { PeaksWorkspace_sptr ws = boost::dynamic_pointer_cast<PeaksWorkspace>( AnalysisDataService::Instance().retrieve(inname)); const std::vector<Peak> &peaks = ws->getPeaks(); size_t n_peaks = ws->getNumberPeaks(); std::vector<V3D> q_vector; std::vector<V3D> hkl_vector; for (size_t i = 0; i < params.size(); i++) params[i] = std::abs(params[i]); for (size_t i = 0; i < n_peaks; i++) { q_vector.push_back(peaks[i].getQSampleFrame()); hkl_vector.push_back(peaks[i].getHKL()); } Mantid::API::IAlgorithm_sptr alg = createChildAlgorithm("CalculateUMatrix"); alg->setPropertyValue("PeaksWorkspace", inname); alg->setProperty("a", params[0]); alg->setProperty("b", params[1]); alg->setProperty("c", params[2]); alg->setProperty("alpha", params[3]); alg->setProperty("beta", params[4]); alg->setProperty("gamma", params[5]); alg->executeAsChildAlg(); ws = alg->getProperty("PeaksWorkspace"); OrientedLattice latt = ws->mutableSample().getOrientedLattice(); DblMatrix UB = latt.getUB(); DblMatrix A = aMatrix(params); DblMatrix Bc = A; Bc.Invert(); DblMatrix U1_B1 = UB * A; OrientedLattice o_lattice; o_lattice.setUB(U1_B1); DblMatrix U1 = o_lattice.getU(); DblMatrix U1_Bc = U1 * Bc; for (size_t i = 0; i < hkl_vector.size(); i++) { V3D error = U1_Bc * hkl_vector[i] - q_vector[i] / (2.0 * M_PI); out[i] = error.norm2(); } return; }
/** gets a vector in the horizontal plane, perpendicular to the beam direction when goniometers are at 0. Note, this vector is not unique, but all vectors can be obtaineb by multiplying with a scalar @return v :: V3D vector perpendicular to the beam direction, in the horizontal plane*/ Kernel::V3D OrientedLattice::getvVector() { V3D x(1, 0, 0); DblMatrix UBinv = UB; UBinv.Invert(); return UBinv * x; }
/** gets a vector along beam direction when goniometers are at 0. Note, this vector is not unique, but all vectors can be obtaineb by multiplying with a scalar @return u :: V3D vector along beam direction*/ Kernel::V3D OrientedLattice::getuVector() { V3D z(0, 0, 1); DblMatrix UBinv = UB; UBinv.Invert(); return UBinv * z; }
/** Calculate the hkl corresponding to a given Q-vector * @param Q :: Q-vector in $AA^-1 in the sample frame * @return a V3D with H,K,L */ V3D OrientedLattice::hklFromQ(const V3D &Q) const { DblMatrix UBinv = this->getUB(); UBinv.Invert(); V3D out = UBinv * Q / TWO_PI; // transform back to HKL return out; }