static int l_uc_C(lua_State* L) { UnitCell* uc = lua_tounitcell(L, 1); if(!uc) return 0; lua_pushvector(L, new Vector(uc->C())); return 1; }
void Crystal::generate_reflections(double min_d) { bp.clear(); UnitCell reciprocal = uc->get_reciprocal(); // set upper limit for iteration of Miller indices // TODO: smarter algorithm, like in uctbx::unit_cell::max_miller_indices() int max_h = 20; int max_k = 20; int max_l = 20; if (fabs(uc->alpha - M_PI/2) < 1e-9 && fabs(uc->beta - M_PI/2) < 1e-9 && fabs(uc->gamma - M_PI/2) < 1e-9) { max_h = (int) (uc->a / min_d); max_k = (int) (uc->b / min_d); max_l = (int) (uc->c / min_d); } // Don't generate too many reflections (it could happen // when user chooses Q instead of 2T, or puts wrong wavelength) if (max_h * max_k * max_l > 8000) max_h = max_k = max_l = 20; for (int h = 0; h != max_h+1; h = inc_neg(h)) for (int k = 0; k != max_k+1; k = inc_neg(k)) for (int l = (h==0 && k==0 ? 1 : 0); l != max_l+1; l = inc_neg(l)) { double d = 1 / reciprocal.calculate_distance(h, k, l); //double d = uc->calculate_d(h, k, l); // the same if (d < min_d) continue; // check for systematic absence if (is_sys_absent(sg_ops, h, k, l)) continue; Miller hkl = { h, k, l }; bool found = false; for (vector<PlanesWithSameD>::iterator i = bp.begin(); i != bp.end(); ++i) { if (fabs(d - i->d) < 1e-9) { i->add(hkl, sg_ops); found = true; break; } } if (!found) { PlanesWithSameD new_p; new_p.planes.push_back(Plane(hkl)); new_p.d = d; new_p.lpf = 0.; new_p.intensity = 0.; new_p.enabled = true; bp.push_back(new_p); } } sort(bp.begin(), bp.end()); old_min_d = min_d; }
/// Returns the lowest and highest d-Value in the list. Uses UnitCell and HKL /// for calculation to prevent problems with potentially inconsistent d-Values /// in Peak. std::pair<double, double> SortHKL::getDLimits(const std::vector<Peak> &peaks, const UnitCell &cell) const { auto dLimitIterators = std::minmax_element( peaks.begin(), peaks.end(), [cell](const Peak &lhs, const Peak &rhs) { return cell.d(lhs.getHKL()) < cell.d(rhs.getHKL()); }); return std::make_pair(cell.d((*dLimitIterators.first).getHKL()), cell.d((*dLimitIterators.second).getHKL())); }
static int l_uc_addatomreduced(lua_State* L) { UnitCell* uc = lua_tounitcell(L, 1); if(!uc) return 0; Atom* a = lua_toatom(L, 2); if(!a) return 0; uc->addAtomReducedCoorinates(a); return 0; }
// Adjust matrix of current model void CellAnglesPopup::adjustCurrentMatrix(int angleIndex, double value) { // Get current model and set new angle in cell Model* model = parent_.aten().currentModelOrFrame(); if (model) { UnitCell cell = model->cell(); cell.setAngle(angleIndex, value); CommandNode::run(Commands::CellAxes, "ddddddddd", cell.parameter(UnitCell::CellAX), cell.parameter(UnitCell::CellAY), cell.parameter(UnitCell::CellAZ), cell.parameter(UnitCell::CellBX), cell.parameter(UnitCell::CellBY), cell.parameter(UnitCell::CellBZ), cell.parameter(UnitCell::CellCX), cell.parameter(UnitCell::CellCY), cell.parameter(UnitCell::CellCZ)); } }
static int l_uc_translate(lua_State* L) { UnitCell* uc = lua_tounitcell(L, 1); if(!uc) return 0; int x = lua_tointeger(L, 2); int y = lua_tointeger(L, 3); int z = lua_tointeger(L, 4); uc->translate(x, y, z); return 0; }
static int l_uc_g2r(lua_State* L) { UnitCell* uc = lua_tounitcell(L, 1); if(!uc) return 0; Vector v; lua_makevector(L, 2, v); Vector b = uc->globalToReduced(v); lua_pushvector(L, new Vector(b)); return 1; }
static int l_uc_applyoperator(lua_State* L) { UnitCell* uc = lua_tounitcell(L, 1); if(!uc) return 0; if(lua_isfunction(L, 2)) { uc->applyOperator(L, 2); return 0; } if(lua_isstring(L, 2)) { if(!uc->applyOperator(lua_tostring(L, 2))) return luaL_error(L, "Failed to apply `%s'\n", lua_tostring(L, 2)); } return 0; }
void general_ewald_sum(UnitCell &uc, const Vector3d &a1, const Vector3d &a2, const Vector3d &a3, const Vector3i &Rcutoff) { int N = uc.size(); const double sigma = M_PI; // renormalize electron occupation double unrenorm_Ne = 0, Ne = 0; for (UnitCell::iterator it = uc.begin(); it < uc.end(); ++it) { unrenorm_Ne += it->ne; Ne += it->C; } for (UnitCell::iterator it = uc.begin(); it < uc.end(); ++it) it->ne *= Ne/unrenorm_Ne; // get reciprocal vectors Vector3d b1, b2, b3; double uc_vol = a1.dot(a2.cross(a3)); b1 = 2*M_PI*a2.cross(a3)/uc_vol; b2 = 2*M_PI*a3.cross(a1)/uc_vol; b3 = 2*M_PI*a1.cross(a2)/uc_vol; // Ewald sum double Vs, Vl; Vector3d k; for (int id = 0; id < N; ++id) { Vs = 0; Vl = 0; for (int m = -Rcutoff[0]; m < Rcutoff[0]; ++m) for (int n = -Rcutoff[1]; n < Rcutoff[1]; ++n) for (int l = -Rcutoff[2]; l < Rcutoff[2]; ++l) { k = n*b1 + m*b2 + l*b3; double ksquare = k.dot(k); for (int i = 0; i < N; ++i) { double dR = (uc[id].r - (uc[i].r + m*a1 + n*a2 + l*a3)).norm(); // for long-range terms if ( !(m == 0 && n == 0 && l == 0) ) Vl += 4*M_PI/uc_vol*(uc[i].C-uc[i].ne)/ksquare * cos(k.dot(uc[id].r-uc[i].r)) * exp(-pow(sigma,2)*ksquare/2.); // for short-range terms if ( !(m == 0 && n == 0 && l == 0 && i == id) ) Vs += (uc[i].C - uc[i].ne) / dR * erfc(dR/sqrt(2)/sigma); } } uc[id].V = Vs + Vl - (uc[id].C - uc[id].ne)*sqrt(2/M_PI)/sigma; } }
static int l_uc_al2bv(lua_State* L) { UnitCell* uc = lua_tounitcell(L, 1); if(!uc) return 0; double v[6]; for(int i=0; i<6; i++) { v[i] = lua_tonumber(L, i+2); if(v[i] == 0) return luaL_error(L, "UnitCell:anglesLengthsToBasisVectors requires 6 numbers"); } uc->anglesLengthsToBasisVectors( v[0], v[1], v[2], v[3], v[4], v[5]); return 0; }
void PawleyFunction::setPeakPositions(std::string centreName, double zeroShift, const UnitCell &cell) const { for (size_t i = 0; i < m_hkls.size(); ++i) { double centre = getTransformedCenter(cell.d(m_hkls[i])); m_peakProfileComposite->getFunction(i) ->setParameter(centreName, centre + zeroShift); } }
void Crystal::toggleUnitCell() { if (m_molecule->unitCell()) { m_molecule->setUnitCell(NULL); m_molecule->emitChanged(Molecule::UnitCell | Molecule::Removed); } else { UnitCell *cell = new UnitCell; cell->setCellParameters(static_cast<Real>(3.0), static_cast<Real>(3.0), static_cast<Real>(3.0), static_cast<Real>(90.0) * DEG_TO_RAD, static_cast<Real>(90.0) * DEG_TO_RAD, static_cast<Real>(90.0) * DEG_TO_RAD); m_molecule->setUnitCell(cell); m_molecule->emitChanged(Molecule::UnitCell | Molecule::Added); editUnitCell(); } }
static int l_uc_copy(lua_State* L) { UnitCell* uc = lua_tounitcell(L, 1); if(!uc) return 0; UnitCell* uc2 = new UnitCell();//uc->A(), uc->B(), uc->C()); uc2->r2g = uc->r2g; uc2->g2r = uc->g2r; uc2->setA(uc->A()); uc2->setB(uc->B()); uc2->setC(uc->C()); for(unsigned int i=0; i<uc->atoms.size(); i++) { uc2->addAtomGlobalCoorinates(new Atom(*uc->atoms[i])); } lua_pushunitcell(L, uc2); return 1; }
// Wrap a vector in an Orthorombic UnitCell static Vector3D wrap_orthorombic(const UnitCell& cell, const Vector3D& vect) { Vector3D res; res[0] = static_cast<float>(vect[0] - round(vect[0]/cell.a())*cell.a()); res[1] = static_cast<float>(vect[1] - round(vect[1]/cell.b())*cell.b()); res[2] = static_cast<float>(vect[2] - round(vect[2]/cell.c())*cell.c()); return res; }
// Wrap a vector in an Orthorombic UnitCell static Vector3D wrap_triclinic(const UnitCell& cell, const Vector3D& vect) { Vector3D res = vect; auto mat = cell.matricial(); for (size_t i=2 ; i != static_cast<size_t>(-1) ; i--) { while (fabs(res[i]) > mat[i][i]/2) { if (res[i] < 0) { res[0] += static_cast<float>(mat[i][0]); res[1] += static_cast<float>(mat[i][1]); res[2] += static_cast<float>(mat[i][2]); } else { res[0] -= static_cast<float>(mat[i][0]); res[1] -= static_cast<float>(mat[i][1]); res[2] -= static_cast<float>(mat[i][2]); } } } return res; }
TEST(UnitCellTest, cellParameters) { Real a = static_cast<Real>(2.0); Real b = static_cast<Real>(3.0); Real c = static_cast<Real>(4.0); Real alpha = static_cast<Real>(70 * DEG_TO_RAD); Real beta = static_cast<Real>(120 * DEG_TO_RAD); Real gamma = static_cast<Real>(85 * DEG_TO_RAD); UnitCell unitCell; unitCell.setCellParameters(a, b, c, alpha, beta, gamma); EXPECT_FLOAT_EQ(static_cast<float>(a), static_cast<float>(unitCell.a())); EXPECT_FLOAT_EQ(static_cast<float>(b), static_cast<float>(unitCell.b())); EXPECT_FLOAT_EQ(static_cast<float>(c), static_cast<float>(unitCell.c())); EXPECT_FLOAT_EQ(static_cast<float>(alpha), static_cast<float>(unitCell.alpha())); EXPECT_FLOAT_EQ(static_cast<float>(beta), static_cast<float>(unitCell.beta())); EXPECT_FLOAT_EQ(static_cast<float>(gamma), static_cast<float>(unitCell.gamma())); }
int main() { UnitCell cell; cout << " orthorhombic cell: " << endl; cell.set(D3vector(4.,0.,0.),D3vector(0.,5.,0.),D3vector(0.,0.,7.)); cout << cell << endl; D3vector v; const int n = 100000; const double d = 10.0; int count; count = 0; for ( int i = 0; i < n; i++ ) { // generate a random vector in a box of size d x d x d double x0 = drand48() - 0.5; double x1 = drand48() - 0.5; double x2 = drand48() - 0.5; v = d * D3vector(x0,x1,x2); if ( cell.in_ws(v) ) count++; cell.fold_in_ws(v); if ( !cell.in_ws(v) ) cout << v << endl; } cout << " volume ratio: " << cell.volume() / (d*d*d) << " computed: " << count/((double) n) << endl << endl;; cout << " FCC cell: " << endl; cell.set(D3vector(4,4,0),D3vector(0,4,4),D3vector(4,0,4)); cout << cell << endl; count = 0; for ( int i = 0; i < n; i++ ) { // generate a random vector in a box of size d x d x d double x0 = drand48() - 0.5; double x1 = drand48() - 0.5; double x2 = drand48() - 0.5; v = d * D3vector(x0,x1,x2); if ( cell.in_ws(v) ) count++; cell.fold_in_ws(v); if ( !cell.in_ws(v) ) cout << v << endl; } cout << " volume ratio: " << cell.volume() / (d*d*d) << " computed: " << count/((double) n) << endl << endl;; cout << " BCC cell: " << endl; cell.set(D3vector(4,4,-4),D3vector(-4, 4,4),D3vector(4,-4,4)); cout << cell << endl; count = 0; for ( int i = 0; i < n; i++ ) { // generate a random vector in a box of size d x d x d double x0 = drand48() - 0.5; double x1 = drand48() - 0.5; double x2 = drand48() - 0.5; v = d * D3vector(x0,x1,x2); if ( cell.in_ws(v) ) count++; cell.fold_in_ws(v); if ( !cell.in_ws(v) ) cout << v << endl; } cout << " volume ratio: " << cell.volume() / (d*d*d) << " computed: " << count/((double) n) << endl << endl;; cout << " Monoclinic cell: " << endl; cell.set(D3vector(4,0,0.1),D3vector(0.2, 4,0),D3vector(0.1,0.3,4)); cout << cell << endl; // Check matrix multiplication function double ztest[9]; cell.matmult3x3(cell.amat(),cell.amat_inv(),ztest); for ( int i = 0; i < 9; i++ ) cout << " ztest[" << i << "]=" << ztest[i] << endl; count = 0; for ( int i = 0; i < n; i++ ) { // generate a random vector in a box of size d x d x d double x0 = drand48() - 0.5; double x1 = drand48() - 0.5; double x2 = drand48() - 0.5; v = d * D3vector(x0,x1,x2); if ( cell.in_ws(v) ) count++; cell.fold_in_ws(v); if ( !cell.in_ws(v) ) cout << v << endl; } cout << " volume ratio: " << cell.volume() / (d*d*d) << " computed: " << count/((double) n) << endl << endl; // test UnitCell::included_in function UnitCell rcell; rcell.set(D3vector(4,4,0),D3vector(0,4,4),D3vector(4,0,4)); cell.set(D3vector(4,5,0),D3vector(0,4,4),D3vector(4,0,4)); cout << " rcell: " << rcell << endl; cout << " cell: " << cell << endl; cout << " cell is"; if ( !rcell.encloses(cell) ) cout << " not"; cout << " included in rcell" << endl; rcell.set(D3vector(4,4,0),D3vector(0,4,4),D3vector(4,0,4)); cout << " rcell: " << rcell << endl; cell.set(D3vector(3.8,3.8,0),D3vector(0,3.8,3.8),D3vector(3.8,0,3.8)); cout << " cell: " << cell << endl; cout << " cell is"; if ( !rcell.encloses(cell) ) cout << " not"; cout << " included in rcell" << endl; }
/** Returns a new UnitCell-object with crystal system constraints taken into *account * * This method constructs a new UnitCell-object based on the values of the *supplied cell, * but takes into account the constraints of the crystal system. For *monoclinic, a unique b-axis is assumed. * * It's useful for "cleaning" user input. * * @param unitCell :: UnitCell-object which should be constrained * @param crystalSystem :: Crystal system which is used for constraints * @return UnitCell-object with applied constraints */ UnitCell PoldiCreatePeaksFromCell::getConstrainedUnitCell( const UnitCell &unitCell, const PointGroup::CrystalSystem &crystalSystem) const { switch (crystalSystem) { case PointGroup::Cubic: return UnitCell(unitCell.a(), unitCell.a(), unitCell.a()); case PointGroup::Tetragonal: return UnitCell(unitCell.a(), unitCell.a(), unitCell.c()); case PointGroup::Orthorhombic: return UnitCell(unitCell.a(), unitCell.b(), unitCell.c()); case PointGroup::Monoclinic: return UnitCell(unitCell.a(), unitCell.b(), unitCell.c(), 90.0, unitCell.beta(), 90.0); case PointGroup::Hexagonal: return UnitCell(unitCell.a(), unitCell.a(), unitCell.c(), 90.0, 90.0, 120.0); case PointGroup::Trigonal: return UnitCell(unitCell.a(), unitCell.a(), unitCell.a(), unitCell.alpha(), unitCell.alpha(), unitCell.alpha()); default: return UnitCell(unitCell); } }
/// Returns the largest possible lattice spacing for the given cell. double PoldiCreatePeaksFromCell::getLargestDValue(const UnitCell &unitCell) const { return std::max(std::max(unitCell.a(), unitCell.b()), unitCell.c()); }
/// Convenience function for checking compatibility of a cell metric with the /// space group, see Group::isInvariant. bool SpaceGroup::isAllowedUnitCell(const UnitCell &cell) const { return isInvariant(cell.getG()); }