32Unit_cell::Unit_cell(Simulation_parameters
const& parameters__, mpi::Communicator
const& comm__)
33 : parameters_(parameters__)
38Unit_cell::~Unit_cell() =
default;
41Unit_cell::find_mt_radii(
int auto_rmt__,
bool inflate__)
43 if (nearest_neighbours_.size() == 0) {
44 RTE_THROW(
"array of nearest neighbours is empty");
47 std::vector<double> Rmt(num_atom_types(), 1e10);
49 if (auto_rmt__ == 1) {
50 for (
int ia = 0; ia < num_atoms(); ia++) {
51 int id1 = atom(ia).type_id();
52 if (nearest_neighbours_[ia].size() > 1) {
53 int ja = nearest_neighbours_[ia][1].atom_id;
54 int id2 = atom(ja).type_id();
56 double R = std::min(parameters_.rmt_max(), 0.95 * nearest_neighbours_[ia][1].distance / 2);
58 Rmt[id1] = std::min(R, Rmt[id1]);
59 Rmt[id2] = std::min(R, Rmt[id2]);
61 Rmt[id1] = parameters_.rmt_max();
66 if (auto_rmt__ == 2) {
67 std::vector<double> scale(num_atom_types(), 1e10);
69 for (
int ia = 0; ia < num_atoms(); ia++) {
70 int id1 = atom(ia).type_id();
71 if (nearest_neighbours_[ia].size() > 1) {
72 int ja = nearest_neighbours_[ia][1].atom_id;
73 int id2 = atom(ja).type_id();
75 double d = nearest_neighbours_[ia][1].distance;
76 double s = 0.95 * d / (atom_type(id1).mt_radius() + atom_type(id2).mt_radius());
77 scale[id1] = std::min(s, scale[id1]);
78 scale[id2] = std::min(s, scale[id2]);
80 scale[id1] = parameters_.rmt_max() / atom_type(id1).mt_radius();
84 for (
int iat = 0; iat < num_atom_types(); iat++) {
85 Rmt[iat] = std::min(parameters_.rmt_max(), atom_type(iat).mt_radius() * scale[iat]);
94 std::vector<bool> scale_Rmt(num_atom_types(),
true);
95 for (
int ia = 0; ia < num_atoms(); ia++) {
96 int id1 = atom(ia).type_id();
98 if (nearest_neighbours_[ia].size() > 1) {
99 int ja = nearest_neighbours_[ia][1].atom_id;
100 int id2 = atom(ja).type_id();
101 double dist = nearest_neighbours_[ia][1].distance;
103 if (Rmt[id1] + Rmt[id2] > dist * 0.94) {
104 scale_Rmt[id1] =
false;
105 scale_Rmt[id2] =
false;
110 std::vector<double> Rmt_infl(num_atom_types(), 1e10);
112 for (
int ia = 0; ia < num_atoms(); ia++) {
113 int id1 = atom(ia).type_id();
114 if (nearest_neighbours_[ia].size() > 1) {
115 int ja = nearest_neighbours_[ia][1].atom_id;
116 int id2 = atom(ja).type_id();
117 double dist = nearest_neighbours_[ia][1].distance;
119 if (scale_Rmt[id1] && !scale_Rmt[id2]) {
120 Rmt_infl[id1] = std::min(Rmt_infl[id1], std::min(parameters_.rmt_max(), 0.95 * (dist - Rmt[id2])));
122 Rmt_infl[id1] = Rmt[id1];
126 for (
int iat = 0; iat < num_atom_types(); iat++) {
127 Rmt[iat] = Rmt_infl[iat];
131 for (
int i = 0; i < num_atom_types(); i++) {
134 s <<
"muffin-tin radius for atom type " << i <<
" (" << atom_type(i).label()
135 <<
") is too small: " << Rmt[i];
144Unit_cell::check_mt_overlap(
int& ia__,
int& ja__)
146 if (num_atoms() != 0 && nearest_neighbours_.size() == 0) {
147 RTE_THROW(
"array of nearest neighbours is empty");
150 for (
int ia = 0; ia < num_atoms(); ia++) {
152 if (nearest_neighbours_[ia].size() <= 1) {
156 int ja = nearest_neighbours_[ia][1].atom_id;
157 double dist = nearest_neighbours_[ia][1].distance;
159 if (atom(ia).mt_radius() + atom(ja).mt_radius() >= dist) {
170Unit_cell::print_info(std::ostream& out__,
int verbosity__)
const
172 out__ <<
"lattice vectors" << std::endl;
173 for (
int i = 0; i < 3; i++) {
174 out__ <<
" a" << i + 1 <<
" : ";
175 for (
int x: {0, 1, 2}) {
176 out__ <<
ffmt(18, 10) << lattice_vectors_(x, i);
180 out__ <<
"reciprocal lattice vectors" << std::endl;
181 for (
int i = 0; i < 3; i++) {
182 out__ <<
" b" << i + 1 <<
" : ";
183 for (
int x: {0, 1, 2}) {
184 out__ <<
ffmt(18, 10) << reciprocal_lattice_vectors_(x, i);
189 <<
"unit cell volume : " <<
ffmt(18, 8) << omega() <<
" [a.u.^3]" << std::endl
190 <<
"1/sqrt(omega) : " <<
ffmt(18, 8) << 1.0 / sqrt(omega()) << std::endl
191 <<
"MT volume : " <<
ffmt(18, 8) << volume_mt()
192 <<
" (" <<
ffmt(5, 2) << volume_mt() * 100 / omega() <<
"%)" << std::endl
193 <<
"IT volume : " <<
ffmt(18, 8) << volume_it()
194 <<
" (" <<
ffmt(5, 2) << volume_it() * 100 / omega() <<
"%)" << std::endl
196 <<
"number of atom types : " << num_atom_types() << std::endl;
197 for (
int i = 0; i < num_atom_types(); i++) {
198 int id = atom_type(i).id();
199 out__ <<
"type id : " <<
id <<
" symbol : " << std::setw(2) << atom_type(i).symbol() <<
" mt_radius : "
200 <<
ffmt(10, 6) << atom_type(i).mt_radius() <<
" num_atoms : " << atom_type(i).num_atoms() << std::endl;
203 out__ <<
"total number of atoms : " << num_atoms() << std::endl
204 <<
"number of symmetry classes : " << num_atom_symmetry_classes() << std::endl;
205 if (!parameters_.full_potential()) {
206 out__ <<
"number of PAW atoms : " << num_paw_atoms() << std::endl;
207 if (num_paw_atoms() != 0) {
208 out__ <<
"PAW atoms :";
209 for (
auto ia : paw_atom_index_) {
215 if (verbosity__ >= 2) {
217 <<
"atom id type id class id position vector_field" << std::endl
218 <<
hbar(90,
'-') << std::endl;
219 for (
int i = 0; i < num_atoms(); i++) {
220 auto pos = atom(i).position();
221 auto vf = atom(i).vector_field();
222 out__ << std::setw(6) << i
223 << std::setw(9) << atom(i).type_id()
224 << std::setw(9) << atom(i).symmetry_class_id()
226 for (
int x: {0, 1, 2}) {
227 out__ <<
ffmt(10, 5) << pos[x];
230 for (
int x: {0, 1, 2}) {
231 out__ <<
ffmt(10, 5) << vf[x];
236 <<
"atom id position (Cartesian, a.u.)" << std::endl
237 <<
hbar(45,
'-') << std::endl;
238 for (
int i = 0; i < num_atoms(); i++) {
239 auto pos = atom(i).position();
240 auto vc = get_cartesian_coordinates(pos);
241 out__ << std::setw(6) << i <<
" ";
242 for (
int x: {0, 1 ,2}) {
243 out__ <<
ffmt(12, 6) << vc[x];
248 for (
int ic = 0; ic < num_atom_symmetry_classes(); ic++) {
249 out__ <<
"class id : " << ic <<
" atom id : ";
250 for (
int i = 0; i < atom_symmetry_class(ic).num_atoms(); i++) {
251 out__ << atom_symmetry_class(ic).atom_id(i) <<
" ";
257 <<
"minimum bond length: " <<
ffmt(12, 6) << min_bond_length() << std::endl;
258 if (!parameters_.full_potential()) {
260 <<
"total number of pseudo wave-functions: " << this->num_ps_atomic_wf().first << std::endl;
266Unit_cell::print_geometry_info(std::ostream& out__,
int verbosity__)
const
268 if (verbosity__ >= 1) {
270 <<
"lattice vectors" << std::endl;
271 for (
int i = 0; i < 3; i++) {
272 out__ <<
" a" << i + 1 <<
" : ";
273 for (
int x: {0, 1, 2}) {
274 out__ << ffmt(18, 10) << lattice_vectors_(x, i);
279 <<
"unit cell volume : " << ffmt(18, 8) << omega() <<
" [a.u.^3]" << std::endl;
282 if (verbosity__ >= 2) {
284 <<
"atom id type id class id position vector_field" << std::endl
285 << hbar(90,
'-') << std::endl;
286 for (
int i = 0; i < num_atoms(); i++) {
287 auto pos = atom(i).position();
288 auto vf = atom(i).vector_field();
289 out__ << std::setw(6) << i
290 << std::setw(9) << atom(i).type_id()
291 << std::setw(9) << atom(i).symmetry_class_id()
293 for (
int x: {0, 1, 2}) {
294 out__ << ffmt(10, 5) << pos[x];
297 for (
int x: {0, 1, 2}) {
298 out__ << ffmt(10, 5) << vf[x];
303 <<
"atom id position (Cartesian, a.u.)" << std::endl
304 << hbar(45,
'-') << std::endl;
305 for (
int i = 0; i < num_atoms(); i++) {
306 auto pos = atom(i).position();
307 auto vc = get_cartesian_coordinates(pos);
308 out__ << std::setw(6) << i <<
" ";
309 for (
int x: {0, 1 ,2}) {
310 out__ << ffmt(12, 6) << vc[x];
315 if (verbosity__ >= 1) {
317 <<
"minimum bond length: " << ffmt(12, 6) << min_bond_length() << std::endl;
321unit_cell_parameters_descriptor
322Unit_cell::unit_cell_parameters()
324 unit_cell_parameters_descriptor d;
326 r3::vector<double> v0(lattice_vectors_(0, 0), lattice_vectors_(1, 0), lattice_vectors_(2, 0));
327 r3::vector<double> v1(lattice_vectors_(0, 1), lattice_vectors_(1, 1), lattice_vectors_(2, 1));
328 r3::vector<double> v2(lattice_vectors_(0, 2), lattice_vectors_(1, 2), lattice_vectors_(2, 2));
334 d.alpha = std::acos(dot(v1, v2) / d.b / d.c) * 180 /
pi;
335 d.beta = std::acos(dot(v0, v2) / d.a / d.c) * 180 /
pi;
336 d.gamma = std::acos(dot(v0, v1) / d.a / d.b) * 180 /
pi;
342Unit_cell::write_cif()
344 if (comm_.rank() == 0) {
345 FILE* fout = fopen(
"unit_cell.cif",
"w");
347 auto d = unit_cell_parameters();
349 fprintf(fout,
"_cell_length_a %f\n", d.a);
350 fprintf(fout,
"_cell_length_b %f\n", d.b);
351 fprintf(fout,
"_cell_length_c %f\n", d.c);
352 fprintf(fout,
"_cell_angle_alpha %f\n", d.alpha);
353 fprintf(fout,
"_cell_angle_beta %f\n", d.beta);
354 fprintf(fout,
"_cell_angle_gamma %f\n", d.gamma);
359 fprintf(fout,
"loop_\n");
360 fprintf(fout,
"_atom_site_label\n");
361 fprintf(fout,
"_atom_type_symbol\n");
362 fprintf(fout,
"_atom_site_fract_x\n");
363 fprintf(fout,
"_atom_site_fract_y\n");
364 fprintf(fout,
"_atom_site_fract_z\n");
365 for (
int ia = 0; ia < num_atoms(); ia++) {
366 auto pos = atom(ia).position();
367 fprintf(fout,
"%i %s %f %f %f\n", ia + 1, atom(ia).type().label().c_str(), pos[0], pos[1], pos[2]);
374Unit_cell::serialize(
bool cart_pos__)
const
378 dict[
"lattice_vectors"] = {{lattice_vectors_(0, 0), lattice_vectors_(1, 0), lattice_vectors_(2, 0)},
379 {lattice_vectors_(0, 1), lattice_vectors_(1, 1), lattice_vectors_(2, 1)},
380 {lattice_vectors_(0, 2), lattice_vectors_(1, 2), lattice_vectors_(2, 2)}};
381 dict[
"lattice_vectors_scale"] = 1.0;
383 dict[
"atom_coordinate_units"] =
"au";
385 dict[
"atom_coordinate_units"] =
"lattice";
388 for (
int iat = 0; iat < num_atom_types(); iat++) {
389 dict[
"atom_types"].push_back(atom_type(iat).label());
392 for (
int iat = 0; iat < num_atom_types(); iat++) {
393 dict[
"atom_files"][atom_type(iat).label()] = atom_type(iat).file_name();
396 for (
int iat = 0; iat < num_atom_types(); iat++) {
397 dict[
"atoms"][atom_type(iat).label()] =
json::array();
398 for (
int i = 0; i < atom_type(iat).num_atoms(); i++) {
399 int ia = atom_type(iat).atom_id(i);
400 auto v = atom(ia).position();
403 v = dot(lattice_vectors_, v);
405 dict[
"atoms"][atom_type(iat).label()].push_back({v[0], v[1], v[2]});
412Unit_cell::find_nearest_neighbours(
double cluster_radius)
414 PROFILE(
"sirius::Unit_cell::find_nearest_neighbours");
418 nearest_neighbours_.clear();
419 nearest_neighbours_.resize(num_atoms());
421 #pragma omp parallel for default(shared)
422 for (
int ia = 0; ia < num_atoms(); ia++) {
424 std::vector<nearest_neighbour_descriptor> nn;
426 std::vector<std::pair<double, int>> nn_sort;
428 for (
int i0 = -max_frac_coord[0]; i0 <= max_frac_coord[0]; i0++) {
429 for (
int i1 = -max_frac_coord[1]; i1 <= max_frac_coord[1]; i1++) {
430 for (
int i2 = -max_frac_coord[2]; i2 <= max_frac_coord[2]; i2++) {
436 for (
int ja = 0; ja < num_atoms(); ja++) {
438 auto rc = get_cartesian_coordinates(v1);
444 if (nnd.
distance <= cluster_radius) {
447 nn_sort.push_back(std::pair<double, int>(nnd.
distance, (
int)nn.size() - 1));
454 std::sort(nn_sort.begin(), nn_sort.end());
455 nearest_neighbours_[ia].resize(nn.size());
456 for (
int i = 0; i < (int)nn.size(); i++) {
457 nearest_neighbours_[ia][i] = nn[nn_sort[i].second];
463Unit_cell::print_nearest_neighbours(std::ostream& out__)
const
465 out__ <<
"Nearest neighbors" << std::endl
466 <<
hbar(17,
'-') << std::endl;
467 for (
int ia = 0; ia < num_atoms(); ia++) {
468 out__ <<
"Central atom: " << atom(ia).type().symbol() <<
"(" << ia <<
")" << std::endl
469 <<
hbar(80,
'-') << std::endl;
470 out__ <<
"atom (ia) D [a.u.] T r_local" << std::endl;
471 for (
int i = 0; i < (int)nearest_neighbours_[ia].size(); i++) {
472 int ja = nearest_neighbours_[ia][i].atom_id;
473 auto ja_symbol = atom(ja).type().symbol();
474 auto ja_d = nearest_neighbours_[ia][i].distance;
475 auto T = nearest_neighbours_[ia][i].translation;
476 auto r_loc = nearest_neighbours_[ia][i].rc;
477 out__ << std::setw(4) << ja_symbol <<
" (" << std::setw(5) << ja <<
")"
478 << std::setw(12) << std::setprecision(5) << ja_d
479 << std::setw(5) << T[0] << std::setw(5) << T[1] << std::setw(5) << T[2]
480 << std::setw(13) << std::setprecision(5) << std::fixed << r_loc[0]
481 << std::setw(10) << std::setprecision(5) << std::fixed << r_loc[1]
482 << std::setw(10) << std::setprecision(5) << std::fixed << r_loc[2] << std::endl;
489Unit_cell::is_point_in_mt(r3::vector<double> vc,
int& ja,
int& jr,
double& dr,
double tp[2])
const
494 for (
int ia = 0; ia < num_atoms(); ia++) {
495 for (
int i0 = -1; i0 <= 1; i0++) {
496 for (
int i1 = -1; i1 <= 1; i1++) {
497 for (
int i2 = -1; i2 <= 1; i2++) {
499 r3::vector<double> posf = r3::vector<double>(i0, i1, i2) + atom(ia).position();
502 r3::vector<double> vf = vr.first - posf;
507 if (vs[0] < atom(ia).mt_radius()) {
512 if (vs[0] < atom(ia).type().radial_grid(0)) {
516 for (
int ir = 0; ir < atom(ia).num_mt_points() - 1; ir++) {
517 if (vs[0] >= atom(ia).type().radial_grid(ir) &&
518 vs[0] < atom(ia).type().radial_grid(ir + 1)) {
520 dr = vs[0] - atom(ia).type().radial_grid(ir);
538Unit_cell::generate_radial_functions(std::ostream& out__)
540 PROFILE(
"sirius::Unit_cell::generate_radial_functions");
542 for (
auto it : spl_num_atom_symmetry_classes()) {
543 atom_symmetry_class(it.i).generate_radial_functions(parameters_.valence_relativity());
546 for (
int ic = 0; ic < num_atom_symmetry_classes(); ic++) {
547 int rank = spl_num_atom_symmetry_classes().location(
typename atom_symmetry_class_index_t::global(ic)).ib;
548 atom_symmetry_class(ic).sync_radial_functions(comm_, rank);
551 if (parameters_.verbosity() >= 2) {
552 mpi::pstdout pout(comm_);
553 if (comm_.rank() == 0) {
554 pout << std::endl <<
"Linearization energies" << std::endl;
557 for (
auto it : spl_num_atom_symmetry_classes()) {
558 atom_symmetry_class(it.i).write_enu(pout);
560 RTE_OUT(out__) << pout.flush(0);
562 if (parameters_.verbosity() >= 4 && comm_.rank() == 0) {
563 for (
int ic = 0; ic < num_atom_symmetry_classes(); ic++) {
564 atom_symmetry_class(ic).dump_lo();
570Unit_cell::generate_radial_integrals()
572 PROFILE(
"sirius::Unit_cell::generate_radial_integrals");
575 for (
auto it : spl_num_atom_symmetry_classes()) {
576 atom_symmetry_class(it.i).generate_radial_integrals(parameters_.valence_relativity());
579 for (
int ic = 0; ic < num_atom_symmetry_classes(); ic++) {
580 int rank = spl_num_atom_symmetry_classes().location(
typename atom_symmetry_class_index_t::global(ic)).ib;
581 atom_symmetry_class(ic).sync_radial_integrals(comm_, rank);
583 }
catch(std::exception
const& e) {
585 s << e.what() << std::endl;
586 s <<
"Error in generating atom_symmetry_class radial integrals";
591 for (
auto it : spl_num_atoms_) {
592 atom(it.i).generate_radial_integrals(parameters_.processing_unit(), mpi::Communicator::self());
595 for (
int ia = 0; ia < num_atoms(); ia++) {
596 int rank = spl_num_atoms().location(
typename atom_index_t::global(ia)).ib;
597 atom(ia).sync_radial_integrals(comm_, rank);
599 }
catch(std::exception
const& e) {
601 s << e.what() << std::endl;
602 s <<
"Error in generating atom radial integrals";
608Unit_cell::chemical_formula()
611 for (
int iat = 0; iat < num_atom_types(); iat++) {
612 name += atom_type(iat).symbol();
614 for (
int ia = 0; ia < num_atoms(); ia++) {
615 if (atom(ia).type_id() == atom_type(iat).id())
621 name = (name + s.str());
629Unit_cell::add_atom_type(
const std::string label__,
const std::string file_name__)
631 int id = next_atom_type_id(label__);
632 atom_types_.push_back(std::shared_ptr<Atom_type>(
new Atom_type(parameters_,
id, label__, file_name__)));
633 return *atom_types_.back();
639 if (atom_type_id_map_.count(label) == 0) {
641 s <<
"atom type with label " << label <<
" is not found";
644 if (atom_id_by_position(position) >= 0) {
646 s <<
"atom with the same position is already in list" << std::endl
647 <<
" position : " << position[0] <<
" " << position[1] <<
" " << position[2];
651 atoms_.push_back(std::shared_ptr<Atom>(
new Atom(atom_type(label), position, vector_field)));
652 atom_type(label).add_atom_id(
static_cast<int>(atoms_.size()) - 1);
656Unit_cell::min_bond_length()
const
660 for (
int ia = 0; ia < num_atoms(); ia++) {
661 if (nearest_neighbours_[ia].size() > 1) {
662 len = std::min(len, nearest_neighbours_[ia][1].distance);
671 PROFILE(
"sirius::Unit_cell::initialize");
677 for (
int iat = 0; iat < num_atom_types(); iat++) {
678 atom_type(iat).init();
682 for (
int ia = 0; ia < num_atoms(); ia++) {
688 for (
int iat = 0; iat < num_atom_types(); iat++) {
689 int nat = atom_type(iat).num_atoms();
692 if (parameters_.processing_unit() == sddk::device_t::GPU) {
693 atom_coord_.back().allocate(sddk::memory_t::device);
700 std::vector<int> offs(this->num_atoms(), -1);
705 for (
auto ia = 0; ia < this->num_atoms(); ia++) {
706 auto& atom = this->atom(ia);
707 if (atom.type().hubbard_correction()) {
709 counter += atom.type().indexb_hub().size();
712 num_hubbard_wf_ = std::make_pair(counter, offs);
726Unit_cell::get_symmetry()
728 PROFILE(
"sirius::Unit_cell::get_symmetry");
730 if (num_atoms() == 0) {
734 if (atom_symmetry_classes_.size() != 0) {
735 atom_symmetry_classes_.clear();
736 for (
int ia = 0; ia < num_atoms(); ia++) {
737 atom(ia).set_symmetry_class(
nullptr);
743 std::vector<int> types(num_atoms());
744 for (
int ia = 0; ia < num_atoms(); ia++) {
745 auto vp = atom(ia).position();
746 auto vf = atom(ia).vector_field();
747 for (
int x : {0, 1, 2}) {
748 positions(x, ia) = vp[x];
749 spins(x, ia) = vf[x];
751 types[ia] = atom(ia).type_id();
754 symmetry_ = std::unique_ptr<Crystal_symmetry>(
755 new Crystal_symmetry(lattice_vectors_, num_atoms(), num_atom_types(), types, positions, spins,
756 parameters_.so_correction(), parameters_.spglib_tolerance(), parameters_.use_symmetry()));
758 int atom_class_id{-1};
759 std::vector<int> asc(num_atoms(), -1);
760 for (
int i = 0; i < num_atoms(); i++) {
765 atom_symmetry_classes_.push_back(std::shared_ptr<Atom_symmetry_class>(
769 for (
int j = 0; j < num_atoms(); j++) {
770 bool is_equal = (equivalent_atoms_.size())
771 ? (equivalent_atoms_[j] == equivalent_atoms_[i])
772 : (symmetry_->atom_symmetry_class(j) == symmetry_->atom_symmetry_class(i));
775 asc[j] = atom_class_id;
776 atom_symmetry_classes_.back()->add_atom_id(j);
782 for (
auto e : atom_symmetry_classes_) {
783 for (
int i = 0; i < e->num_atoms(); i++) {
784 int ia = e->atom_id(i);
785 atom(ia).set_symmetry_class(e);
789 assert(num_atom_symmetry_classes() != 0);
810 add_atom_type(label, fname);
813 for (
auto v : inp__.
atoms(label)) {
821 for (
int x : {0, 1, 2}) {
826 if (units ==
"au" || units ==
"A") {
829 for (
int x : {0, 1, 2}) {
833 add_atom(label, p, f);
841 PROFILE(
"sirius::Unit_cell::update");
843 auto v0 = lattice_vector(0);
844 auto v1 = lattice_vector(1);
845 auto v2 = lattice_vector(2);
848 if (parameters_.cfg().parameters().nn_radius() < 0) {
849 r = std::max(v0.length(), std::max(v1.length(), v2.length()));
851 r = parameters_.cfg().parameters().nn_radius();
854 find_nearest_neighbours(r);
856 if (parameters_.full_potential()) {
858 if (parameters_.auto_rmt()) {
859 auto rg = get_radial_grid_t(parameters_.cfg().settings().radial_grid());
860 auto Rmt = find_mt_radii(parameters_.auto_rmt(),
true);
861 for (
int iat = 0; iat < num_atom_types(); iat++) {
862 double r0 = atom_type(iat).radial_grid().first();
864 atom_type(iat).set_radial_grid(rg.first, atom_type(iat).num_mt_points(), r0, Rmt[iat], rg.second);
869 if (check_mt_overlap(ia, ja)) {
871 s <<
"overlaping muffin-tin spheres for atoms " << ia <<
"(" << atom(ia).type().symbol() <<
")"
872 <<
" and " << ja <<
"(" << atom(ja).type().symbol() <<
")" << std::endl
873 <<
" radius of atom " << ia <<
" : " << atom(ia).mt_radius() << std::endl
874 <<
" radius of atom " << ja <<
" : " << atom(ja).mt_radius() << std::endl
875 <<
" distance : " << nearest_neighbours_[ia][1].distance <<
" " << nearest_neighbours_[ja][1].distance;
886 if (parameters_.full_potential()) {
887 for (
int ia = 0; ia < num_atoms(); ia++) {
888 volume_mt_ +=
fourpi * std::pow(atom(ia).mt_radius(), 3) / 3.0;
892 volume_it_ = omega() - volume_mt_;
894 for (
int iat = 0; iat < num_atom_types(); iat++) {
895 int nat = atom_type(iat).num_atoms();
897 for (
int i = 0; i < nat; i++) {
898 int ia = atom_type(iat).atom_id(i);
899 for (
int x: {0, 1, 2}) {
900 atom_coord_[iat](i, x) = atom(ia).position()[x];
903 if (parameters_.processing_unit() == sddk::device_t::GPU) {
904 atom_coord_[iat].copy_to(sddk::memory_t::device);
913 lattice_vectors_ = lattice_vectors__;
914 inverse_lattice_vectors_ =
inverse(lattice_vectors_);
915 omega_ = std::abs(lattice_vectors_.det());
923 for (
int x : {0, 1, 2}) {
928 set_lattice_vectors(lv);
934 for (
int ia = 0; ia < num_atoms(); ia++) {
935 auto vd = atom(ia).position() - position__;
936 if (vd.length() < 1e-10) {
944Unit_cell::next_atom_type_id(std::string label__)
947 if (atom_type_id_map_.count(label__) != 0) {
949 s <<
"atom type with label " << label__ <<
" is already in list";
953 atom_type_id_map_[label__] =
static_cast<int>(atom_types_.size());
954 return atom_type_id_map_[label__];
960 for (
int ia = 0; ia < num_atoms(); ia++) {
961 if (atom(ia).type().is_paw()) {
962 paw_atom_index_.push_back(ia);
970std::pair<int, std::vector<int>>
971Unit_cell::num_ps_atomic_wf()
const
973 std::vector<int> offs(this->num_atoms(), -1);
975 for (
auto ia = 0; ia < this->num_atoms(); ia++) {
976 auto& atom = this->atom(ia);
978 counter += atom.type().indexb_wfs().size();
980 return std::make_pair(counter, offs);
static JSON_HEDLEY_WARN_UNUSED_RESULT basic_json object(initializer_list_t init={})
explicitly create an object from an initializer list
array_t * array
array (stored with pointer to save storage)
Data and methods specific to the symmetry class of the atom.
Defines the properties of atom type.
Data and methods specific to the actual atom in the unit cell.
Representation of the crystal symmetry.
Unit cell representation.
auto lattice_vectors_scale() const
Scaling factor for the lattice vectors.
auto atom_coordinate_units() const
Type of atomic coordinates: lattice, atomic units or Angstroms.
auto atom_files(std::string label__) const
Mapping between atom type labels and atomic files.
auto atom_types() const
List of atom type labels.
auto lattice_vectors() const
Three non-collinear vectors of the primitive unit cell.
auto atoms(std::string label__) const
Atomic coordinates.
Floating-point formatting (precision and width).
Simple implementation of 3d vector.
Contains definition and partial implementation of sirius::Crystal_symmetry class.
auto transpose(matrix< T > src)
Return transpose of the matrix.
auto find_translations(double radius__, matrix< double > const &lattice_vectors__)
Find supercell that circumscribes the sphere with a given radius.
auto inverse(matrix< int > src)
Return inverse of the integer matrix.
auto spherical_coordinates(vector< double > vc)
Transform Cartesian coordinates [x,y,z] to spherical coordinates [r,theta,phi].
auto reduce_coordinates(vector< double > coord__)
Reduce the coordinates to the first unit cell.
Namespace of the SIRIUS library.
const double bohr_radius
Bohr radius in angstroms.
void initialize(bool call_mpi_init__=true)
Initialize the library.
strong_type< int, struct __n_blocks_tag > n_blocks
Number of blocks to which the global index is split.
Descriptor of an atom in a list of nearest neighbours for each atom.
std::array< double, 3 > rc
Vector connecting central atom with the neighbour in Cartesian coordinates.
double distance
Distance from the central atom.
std::array< int, 3 > translation
Translation in fractional coordinates.
int atom_id
Index of the neighbouring atom.
Contains definition and partial implementation of sirius::Unit_cell class.