30#include "error_codes.hpp"
33#include "nlcglib/nlcglib.hpp"
35#include "nlcglib/overlap.hpp"
50 void* handler_ptr_{
nullptr};
55 void* handler_ptr_{
nullptr};
60 void* handler_ptr_{
nullptr};
65enum class option_type_t :
int
73 INTEGER_ARRAY_TYPE = 7,
74 LOGICAL_ARRAY_TYPE = 8,
75 NUMBER_ARRAY_TYPE = 9,
76 STRING_ARRAY_TYPE = 10,
77 OBJECT_ARRAY_TYPE = 11,
83sirius_option_set_value(
Simulation_context& sim_ctx__, std::string section__, std::string name__,
84 T
const* values__,
int const* max_length__)
86 std::transform(section__.begin(), section__.end(), section__.begin(), ::tolower);
88 auto& conf_dict =
const_cast<nlohmann::json&
>(sim_ctx__.cfg().dict());
92 if (!section_schema.count(name__)) {
93 std::transform(name__.begin(), name__.end(), name__.begin(), ::tolower);
95 if (!section_schema.count(name__)) {
96 RTE_THROW(
"section : " + section__ +
", option : " + name__ +
" is invalid");
99 if (section_schema[name__][
"type"] ==
"array") {
100 if (max_length__ ==
nullptr) {
101 RTE_THROW(
"maximum length of the input buffer is not provided");
103 std::vector<T> v(values__, values__ + *max_length__);
104 conf_dict[section__][name__] = v;
106 conf_dict[section__][name__] = *values__;
111sirius_option_set_value(
Simulation_context& sim_ctx__, std::string section__, std::string name__,
112 char const* values__,
int const* max_length__,
bool append__)
114 std::transform(section__.begin(), section__.end(), section__.begin(), ::tolower);
116 auto& conf_dict =
const_cast<nlohmann::json&
>(sim_ctx__.cfg().dict());
120 if (!section_schema.count(name__)) {
121 std::transform(name__.begin(), name__.end(), name__.begin(), ::tolower);
123 if (!section_schema.count(name__)) {
124 RTE_THROW(
"section : " + section__ +
", option : " + name__ +
" is invalid");
127 if (max_length__ ==
nullptr) {
128 RTE_THROW(
"maximum length of the input string is not provided");
130 auto st = std::string(values__, *max_length__);
132 conf_dict[section__][name__] = st;
134 conf_dict[section__][name__].push_back(st);
140sirius_option_get_value(std::string section__, std::string name__, T* default_value__,
int const* max_length__)
144 if (!section_schema.count(name__)) {
145 std::transform(name__.begin(), name__.end(), name__.begin(), ::tolower);
147 if (!section_schema.count(name__)) {
148 RTE_THROW(
"section : " + section__ +
", option : " + name__ +
" is invalid");
151 if (!section_schema[name__].count(
"default")) {
152 RTE_THROW(
"default value for '" + name__ +
"' is missing");
155 if (section_schema[name__][
"type"] ==
"array") {
156 if (max_length__ ==
nullptr) {
157 RTE_THROW(
"maximum length of the output buffer is not provided");
159 if (section_schema[name__][
"items"] !=
"array") {
160 std::vector<T> v = section_schema[name__][
"default"].get<std::vector<T>>();
161 int l =
static_cast<int>(v.size());
162 if (l > *max_length__) {
163 RTE_THROW(
"not enough space to store '" + name__ +
"' values");
165 std::copy(v.begin(), v.end(), default_value__);
168 *default_value__ = section_schema[name__][
"default"].get<T>();
173sirius_option_get_value(std::string section__, std::string name__,
char* default_value__,
int const* max_length__,
174 int const* enum_idx__)
178 if (!section_schema.count(name__)) {
179 std::transform(name__.begin(), name__.end(), name__.begin(), ::tolower);
181 if (!section_schema.count(name__)) {
182 RTE_THROW(
"section : " + section__ +
", option : " + name__ +
" is invalid");
185 if (!section_schema[name__].count(
"default")) {
186 RTE_THROW(
"default value for '" + name__ +
"' is missing");
189 if (section_schema[name__][
"type"] ==
"array") {
190 RTE_THROW(
"array of strings is not supported");
192 if (section_schema[name__][
"type"] !=
"string") {
193 RTE_THROW(
"not a string type");
196 if (enum_idx__ ==
nullptr) {
197 v = section_schema[name__][
"default"].get<std::string>();
199 if (section_schema[name__].count(
"enum")) {
200 v = section_schema[name__][
"enum"][*enum_idx__ - 1].get<std::string>();
202 RTE_THROW(
"not an enum type");
205 if (max_length__ ==
nullptr) {
206 RTE_THROW(
"length of the string is not provided");
208 if (
static_cast<int>(v.size()) > *max_length__) {
210 s <<
"option '" << name__ <<
"' is too large to fit into output string of size " << *max_length__;
213 std::fill(default_value__, default_value__ + *max_length__,
' ');
214 std::copy(v.begin(), v.end(), default_value__);
219sirius_print_error(
int error_code__, std::string msg__ =
"")
221 switch (error_code__) {
222 case SIRIUS_ERROR_UNKNOWN: {
223 printf(
"SIRIUS: unknown error\n");
226 case SIRIUS_ERROR_RUNTIME: {
227 printf(
"SIRIUS: run-time error\n");
230 case SIRIUS_ERROR_EXCEPTION: {
231 printf(
"SIRIUS: exception\n");
235 printf(
"SIRIUS: unknown error code: %i\n", error_code__);
241 printf(
"%s\n", msg__.c_str());
244 std::cout << std::flush;
248sirius_exit(
int error_code__, std::string msg__ =
"")
250 sirius_print_error(error_code__, msg__);
251 if (!mpi::Communicator::is_finalized()) {
252 mpi::Communicator::world().abort(error_code__);
254 std::exit(error_code__);
260call_sirius(F&& f__,
int* error_code__)
265 *error_code__ = SIRIUS_SUCCESS;
268 }
catch (std::runtime_error
const& e) {
270 *error_code__ = SIRIUS_ERROR_RUNTIME;
271 sirius_print_error(*error_code__, e.what());
274 sirius_exit(SIRIUS_ERROR_RUNTIME, e.what());
276 }
catch (std::exception
const& e) {
278 *error_code__ = SIRIUS_ERROR_EXCEPTION;
279 sirius_print_error(*error_code__, e.what());
282 sirius_exit(SIRIUS_ERROR_EXCEPTION, e.what());
286 *error_code__ = SIRIUS_ERROR_UNKNOWN;
287 sirius_print_error(*error_code__);
290 sirius_exit(SIRIUS_ERROR_UNKNOWN);
296auto get_value(T
const* ptr__, T v0__ = T())
298 return (ptr__) ? *ptr__ : v0__;
302get_sim_ctx(
void*
const* h)
304 if (h ==
nullptr || *h ==
nullptr) {
305 RTE_THROW(
"Non-existing simulation context handler");
311get_gs(
void*
const* h)
313 if (h ==
nullptr || *h ==
nullptr) {
314 RTE_THROW(
"Non-existing DFT ground state handler");
320get_ks(
void*
const* h)
322 if (h ==
nullptr || *h ==
nullptr) {
323 RTE_THROW(
"Non-existing K-point set handler");
332 return (m__ > 0) ? 2 * m__ - 1 : -2 * m__;
336static inline std::vector<int>
341 std::vector<int> idx_map(nbf);
342 for (
int xi = 0; xi < nbf; xi++) {
343 int m = type__.indexb(xi).m;
344 auto idxrf = type__.indexb(xi).idxrf;
352phase_Rlm_QE(
Atom_type const& type__,
int xi__)
354 return (type__.indexb(xi__).m < 0 && (-type__.indexb(xi__).m) % 2 == 0) ? -1 : 1;
409sirius_finalize(
bool const* call_mpi_fin__,
bool const* call_device_reset__,
bool const* call_fftw_fin__,
418 bool device_reset{
true};
421 if (call_mpi_fin__ !=
nullptr) {
422 mpi_fin = *call_mpi_fin__;
425 if (call_device_reset__ !=
nullptr) {
426 device_reset = *call_device_reset__;
429 if (call_fftw_fin__ !=
nullptr) {
430 fftw_fin = *call_fftw_fin__;
456 call_sirius([&]() { global_rtgraph_timer.start(name__); }, error_code__);
477 call_sirius([&]() { global_rtgraph_timer.stop(name__); }, error_code__);
500 auto timing_result = global_rtgraph_timer.process();
502 timing_result = timing_result.flatten(1).sort_nodes();
504 std::cout << timing_result.print({rt_graph::Stat::Count, rt_graph::Stat::Total, rt_graph::Stat::Percentage,
505 rt_graph::Stat::SelfPercentage, rt_graph::Stat::Median,
506 rt_graph::Stat::Min, rt_graph::Stat::Max});
531 auto timing_result = global_rtgraph_timer.process();
532 std::ofstream ofs(fname__, std::ofstream::out | std::ofstream::trunc);
533 ofs << timing_result.json();
562 auto& sim_ctx = get_sim_ctx(handler__);
563 *status__ = sim_ctx.initialized();
601sirius_create_context(
int fcomm__,
void** handler__,
int* fcomm_k__,
int* fcomm_band__,
int* error_code__)
605 auto& comm = mpi::Communicator::map_fcomm(fcomm__);
606 auto& comm_k = (fcomm_k__) ? mpi::Communicator::map_fcomm(*fcomm_k__) :
mpi::Communicator();
607 auto const& comm_band =
608 (fcomm_band__) ? mpi::Communicator::map_fcomm(*fcomm_band__) :
mpi::Communicator();
638 auto& sim_ctx = get_sim_ctx(handler__);
639 sim_ctx.import(std::string(str__));
772sirius_set_parameters(
void*
const* handler__,
int const* lmax_apw__,
int const* lmax_rho__,
int const* lmax_pot__,
773 int const* num_fv_states__,
int const* num_bands__,
int const* num_mag_dims__,
774 double const* pw_cutoff__,
double const* gk_cutoff__,
int const* fft_grid_size__,
775 int const* auto_rmt__,
bool const* gamma_point__,
bool const* use_symmetry__,
776 bool const* so_correction__,
char const* valence_rel__,
char const* core_rel__,
777 double const* iter_solver_tol_empty__,
778 char const* iter_solver_type__,
int const* verbosity__,
bool const* hubbard_correction__,
779 int const* hubbard_correction_kind__,
bool const* hubbard_full_orthogonalization__,
780 char const* hubbard_orbitals__,
int const* sht_coverage__,
double const* min_occupancy__,
781 char const* smearing__,
double const* smearing_width__,
double const* spglib_tol__,
782 char const* electronic_structure_method__,
int* error_code__)
786 auto& sim_ctx = get_sim_ctx(handler__);
787 if (lmax_apw__ !=
nullptr) {
788 sim_ctx.lmax_apw(*lmax_apw__);
790 if (lmax_rho__ !=
nullptr) {
791 sim_ctx.lmax_rho(*lmax_rho__);
793 if (lmax_pot__ !=
nullptr) {
794 sim_ctx.lmax_pot(*lmax_pot__);
796 if (num_fv_states__ !=
nullptr) {
797 sim_ctx.num_fv_states(*num_fv_states__);
799 if (num_bands__ !=
nullptr) {
800 sim_ctx.num_bands(*num_bands__);
802 if (num_mag_dims__ !=
nullptr) {
803 sim_ctx.set_num_mag_dims(*num_mag_dims__);
805 if (pw_cutoff__ !=
nullptr) {
806 sim_ctx.pw_cutoff(*pw_cutoff__);
808 if (gk_cutoff__ !=
nullptr) {
809 sim_ctx.gk_cutoff(*gk_cutoff__);
811 if (auto_rmt__ !=
nullptr) {
812 sim_ctx.set_auto_rmt(*auto_rmt__);
814 if (gamma_point__ !=
nullptr) {
815 sim_ctx.gamma_point(*gamma_point__);
817 if (use_symmetry__ !=
nullptr) {
818 sim_ctx.use_symmetry(*use_symmetry__);
820 if (so_correction__ !=
nullptr) {
821 sim_ctx.so_correction(*so_correction__);
823 if (valence_rel__ !=
nullptr) {
824 sim_ctx.valence_relativity(valence_rel__);
826 if (core_rel__ !=
nullptr) {
827 sim_ctx.core_relativity(core_rel__);
829 if (iter_solver_tol_empty__ !=
nullptr) {
830 sim_ctx.empty_states_tolerance(*iter_solver_tol_empty__);
832 if (iter_solver_type__ !=
nullptr) {
833 sim_ctx.iterative_solver_type(std::string(iter_solver_type__));
835 if (verbosity__ !=
nullptr) {
836 sim_ctx.verbosity(*verbosity__);
838 if (hubbard_correction__ !=
nullptr) {
839 sim_ctx.set_hubbard_correction(*hubbard_correction__);
841 if (hubbard_correction_kind__ !=
nullptr) {
842 if (*hubbard_correction_kind__ == 0) {
843 sim_ctx.cfg().hubbard().simplified(
true);
846 if (hubbard_full_orthogonalization__ !=
nullptr) {
847 if (*hubbard_full_orthogonalization__) {
848 sim_ctx.cfg().hubbard().full_orthogonalization(
true);
851 if (hubbard_orbitals__ !=
nullptr) {
852 std::string s(hubbard_orbitals__);
854 if (s ==
"ortho-atomic") {
855 sim_ctx.cfg().hubbard().orthogonalize(
true);
856 sim_ctx.cfg().hubbard().full_orthogonalization(
true);
858 if (s ==
"norm-atomic") {
859 sim_ctx.cfg().hubbard().normalize(
true);
862 if (fft_grid_size__ !=
nullptr) {
863 sim_ctx.fft_grid_size({fft_grid_size__[0], fft_grid_size__[1], fft_grid_size__[2]});
865 if (sht_coverage__ !=
nullptr) {
866 sim_ctx.sht_coverage(*sht_coverage__);
868 if (min_occupancy__ !=
nullptr) {
869 sim_ctx.min_occupancy(*min_occupancy__);
871 if (smearing__ !=
nullptr) {
872 sim_ctx.smearing(smearing__);
874 if (smearing_width__ !=
nullptr) {
875 sim_ctx.smearing_width(*smearing_width__);
877 if (spglib_tol__ !=
nullptr) {
878 sim_ctx.cfg().control().spglib_tolerance(*spglib_tol__);
880 if (electronic_structure_method__ !=
nullptr) {
881 sim_ctx.cfg().parameters().electronic_structure_method(electronic_structure_method__);
991sirius_get_parameters(
void*
const* handler__,
int* lmax_apw__,
int* lmax_rho__,
int* lmax_pot__,
int* num_fv_states__,
992 int* num_bands__,
int* num_spins__,
int* num_mag_dims__,
double* pw_cutoff__,
double* gk_cutoff__,
993 int* fft_grid_size__,
int* auto_rmt__,
bool* gamma_point__,
bool* use_symmetry__,
994 bool* so_correction__,
double* iter_solver_tol__,
double* iter_solver_tol_empty__,
995 int* verbosity__,
bool* hubbard_correction__,
double* evp_work_count__,
int* num_loc_op_applied__,
996 int* num_sym_op__,
char* electronic_structure_method__,
int* error_code__)
1000 auto& sim_ctx = get_sim_ctx(handler__);
1002 *lmax_apw__ = sim_ctx.unit_cell().lmax_apw();
1005 *lmax_rho__ = sim_ctx.lmax_rho();
1008 *lmax_pot__ = sim_ctx.lmax_pot();
1010 if (num_fv_states__) {
1011 *num_fv_states__ = sim_ctx.num_fv_states();
1014 *num_bands__ = sim_ctx.num_bands();
1017 *num_spins__ = sim_ctx.num_spins();
1019 if (num_mag_dims__) {
1020 *num_mag_dims__ = sim_ctx.num_mag_dims();
1023 *pw_cutoff__ = sim_ctx.pw_cutoff();
1026 *gk_cutoff__ = sim_ctx.gk_cutoff();
1029 *auto_rmt__ = sim_ctx.auto_rmt();
1031 if (gamma_point__) {
1032 *gamma_point__ = sim_ctx.gamma_point();
1034 if (use_symmetry__) {
1035 *use_symmetry__ = sim_ctx.use_symmetry();
1037 if (so_correction__) {
1038 *so_correction__ = sim_ctx.so_correction();
1040 if (iter_solver_tol_empty__) {
1041 *iter_solver_tol_empty__ = sim_ctx.cfg().iterative_solver().empty_states_tolerance();
1044 *verbosity__ = sim_ctx.verbosity();
1046 if (hubbard_correction__) {
1047 *hubbard_correction__ = sim_ctx.hubbard_correction();
1049 if (fft_grid_size__) {
1050 for (
int x : {0, 1, 2}) {
1051 fft_grid_size__[x] = sim_ctx.fft_grid()[x];
1054 if (evp_work_count__) {
1055 *evp_work_count__ = sim_ctx.evp_work_count();
1057 if (num_loc_op_applied__) {
1058 *num_loc_op_applied__ = sim_ctx.num_loc_op_applied();
1061 if (sim_ctx.use_symmetry()) {
1062 *num_sym_op__ = sim_ctx.unit_cell().symmetry().size();
1067 if (electronic_structure_method__) {
1068 auto str = sim_ctx.cfg().parameters().electronic_structure_method();
1069 std::copy(str.c_str(), str.c_str() + str.length() + 1, electronic_structure_method__);
1099 auto& sim_ctx = get_sim_ctx(handler__);
1100 sim_ctx.add_xc_functional(std::string(name__));
1133 RTE_ASSERT(*ndims__ > 0);
1134 auto& sim_ctx = get_sim_ctx(handler__);
1135 std::vector<int> dims(dims__, dims__ + *ndims__);
1136 sim_ctx.mpi_grid_dims(dims);
1174 auto& sim_ctx = get_sim_ctx(handler__);
1201 auto& sim_ctx = get_sim_ctx(handler__);
1202 sim_ctx.initialize();
1228 auto& sim_ctx = get_sim_ctx(handler__);
1255 auto& sim_ctx = get_sim_ctx(handler__);
1256 sim_ctx.print_info(sim_ctx.out());
1282 if (*handler__ !=
nullptr) {
1283 delete static_cast<any_ptr*
>(*handler__);
1285 *handler__ =
nullptr;
1347 int const* nrmtmax__,
int const* num_atoms__,
double* f_rg__,
int const* size_x__,
int const* size_y__,
1348 int const* size_z__,
int const* offset_z__,
int* error_code__)
1352 auto& sim_ctx = get_sim_ctx(handler__);
1353 std::string label(label__);
1355 int lmmax = get_value(lmmax__);
1356 int nrmtmax = get_value(nrmtmax__);
1357 int num_atoms = get_value(num_atoms__);
1358 int size_x = get_value(size_x__);
1359 int size_y = get_value(size_y__);
1360 int size_z = get_value(size_z__);
1361 int offset_z = get_value(offset_z__, -1);
1428 int const* nrmtmax__,
int const* num_atoms__,
double* f_rg__,
int const* size_x__,
1429 int const* size_y__,
int const* size_z__,
int const* offset_z__,
int* error_code__)
1433 auto& gs = get_gs(handler__);
1434 std::string label(label__);
1435 std::map<std::string, Periodic_function<double>*> func_map = {
1436 {
"rho", &gs.density().component(0)}, {
"magz", &gs.density().component(1)},
1437 {
"magx", &gs.density().component(2)}, {
"magy", &gs.density().component(3)},
1438 {
"veff", &gs.potential().component(0)}, {
"bz", &gs.potential().component(1)},
1439 {
"bx", &gs.potential().component(2)}, {
"by", &gs.potential().component(3)},
1440 {
"vha", &gs.potential().hartree_potential()}};
1442 if (!func_map.count(label)) {
1443 RTE_THROW(
"wrong label (" + label +
") for the periodic function");
1446 int lmmax = get_value(lmmax__);
1447 int nrmtmax = get_value(nrmtmax__);
1448 int num_atoms = get_value(num_atoms__);
1449 int size_x = get_value(size_x__);
1450 int size_y = get_value(size_y__);
1451 int size_z = get_value(size_z__);
1452 int offset_z = get_value(offset_z__, -1);
1456 copy(mt_ptr, func_map[label]->mt());
1460 copy(rg_ptr, func_map[label]->rg());
1523 int const* nrmtmax__,
int const* num_atoms__,
double* f_rg__,
int const* size_x__,
1524 int const* size_y__,
int const* size_z__,
int const* offset_z__,
int* error_code__)
1528 auto& gs = get_gs(handler__);
1529 std::string label(label__);
1530 std::map<std::string, Periodic_function<double>*> func_map = {
1531 {
"rho", &gs.density().component(0)}, {
"magz", &gs.density().component(1)},
1532 {
"magx", &gs.density().component(2)}, {
"magy", &gs.density().component(3)},
1533 {
"veff", &gs.potential().component(0)}, {
"bz", &gs.potential().component(1)},
1534 {
"bx", &gs.potential().component(2)}, {
"by", &gs.potential().component(3)},
1535 {
"vha", &gs.potential().hartree_potential()}, {
"exc", &gs.potential().xc_energy_density()},
1536 {
"vxc", &gs.potential().xc_potential()}};
1538 if (!func_map.count(label)) {
1539 RTE_THROW(
"wrong label (" + label +
") for the periodic function");
1542 int lmmax = get_value(lmmax__);
1543 int nrmtmax = get_value(nrmtmax__);
1544 int num_atoms = get_value(num_atoms__);
1545 int size_x = get_value(size_x__);
1546 int size_y = get_value(size_y__);
1547 int size_z = get_value(size_z__);
1548 int offset_z = get_value(offset_z__, -1);
1552 copy(func_map[label]->mt(), mt_ptr);
1556 copy(func_map[label]->rg(), rg_ptr);
1598sirius_create_kset(
void*
const* handler__,
int const* num_kpoints__,
double* kpoints__,
double const* kpoint_weights__,
1599 bool const* init_kset__,
void** kset_handler__,
int* error_code__)
1603 auto& sim_ctx = get_sim_ctx(handler__);
1612 *kset_handler__ =
new any_ptr(new_kset);
1650 bool const* use_symmetry,
void** kset_handler__,
int* error_code__)
1654 auto& sim_ctx = get_sim_ctx(handler__);
1655 std::vector<int> k_grid(3);
1656 std::vector<int> k_shift(3);
1658 k_grid[0] = k_grid__[0];
1659 k_grid[1] = k_grid__[1];
1660 k_grid[2] = k_grid__[2];
1662 k_shift[0] = k_shift__[0];
1663 k_shift[1] = k_shift__[1];
1664 k_shift[2] = k_shift__[2];
1668 *kset_handler__ =
new any_ptr(new_kset);
1697 auto& ks = get_ks(ks_handler__);
1728 auto& ks = get_ks(ks_handler__);
1730 std::vector<int> count(count__, count__ + ks.comm().size());
1731 ks.initialize(count);
1792 double const* iter_solver_tol__,
bool const* initial_guess__,
int const* max_niter__,
1793 bool const* save_state__,
bool* converged__,
int* niter__,
double* rho_min__,
1798 auto& gs = get_gs(gs_handler__);
1799 auto& ctx = gs.ctx();
1800 auto& inp = ctx.cfg().parameters();
1802 bool initial_guess = (initial_guess__) ? *initial_guess__ :
true;
1803 if (initial_guess) {
1807 double rho_tol = (density_tol__) ? *density_tol__ : inp.density_tol();
1809 double etol = (energy_tol__) ? *energy_tol__ : inp.energy_tol();
1811 double iter_solver_tol = (iter_solver_tol__) ? *iter_solver_tol__
1812 : ctx.cfg().iterative_solver().energy_tolerance();
1814 int max_niter = (max_niter__) ? * max_niter__ : inp.num_dft_iter();
1816 bool save = (save_state__) ? *save_state__ :
false;
1818 auto result = gs.find(rho_tol, etol, iter_solver_tol, max_niter, save);
1820 if (result[
"converged"].get<bool>()) {
1822 *converged__ =
true;
1825 *niter__ = result[
"num_scf_iterations"].get<
int>();
1828 *rho_min__ = result[
"rho_min"].get<
double>();
1832 *converged__ =
false;
1835 *niter__ = max_niter;
1865 auto& gs = get_gs(gs_handler__);
1866 gs.check_scf_density();
1892 auto& gs = get_gs(handler__);
1938sirius_add_atom_type(
void*
const* handler__,
char const* label__,
char const* fname__,
int const* zn__,
1939 char const* symbol__,
double const* mass__,
bool const* spin_orbit__,
int* error_code__)
1943 auto& sim_ctx = get_sim_ctx(handler__);
1945 std::string label = std::string(label__);
1946 std::string fname = (fname__ ==
nullptr) ? std::string(
"") : std::string(fname__);
1947 sim_ctx.unit_cell().add_atom_type(label, fname);
1949 auto& type = sim_ctx.unit_cell().atom_type(label);
1950 if (zn__ !=
nullptr) {
1953 if (symbol__ !=
nullptr) {
1954 type.set_symbol(std::string(symbol__));
1956 if (mass__ !=
nullptr) {
1957 type.set_mass(*mass__);
1959 if (spin_orbit__ !=
nullptr) {
1960 type.spin_orbit_coupling(*spin_orbit__);
1997 double const* radial_points__,
int* error_code__)
2001 auto& sim_ctx = get_sim_ctx(handler__);
2003 auto& type = sim_ctx.unit_cell().atom_type(std::string(label__));
2004 type.set_radial_grid(*num_radial_points__, radial_points__);
2038 double const* radial_points__,
int* error_code__)
2042 auto& sim_ctx = get_sim_ctx(handler__);
2044 auto& type = sim_ctx.unit_cell().atom_type(std::string(label__));
2045 type.set_free_atom_radial_grid(*num_radial_points__, radial_points__);
2103 double const* rf__,
int const* num_points__,
int const* n__,
int const* l__,
2104 int const* idxrf1__,
int const* idxrf2__,
double const* occ__,
int* error_code__)
2108 auto& sim_ctx = get_sim_ctx(handler__);
2110 auto& type = sim_ctx.unit_cell().atom_type(std::string(atom_type__));
2111 std::string label(label__);
2113 if (label ==
"beta") {
2114 if (l__ ==
nullptr) {
2115 RTE_THROW(
"orbital quantum number must be provided for beta-projector");
2118 if (type.spin_orbit_coupling()) {
2120 type.add_beta_radial_function(
angular_momentum(l, 1), std::vector<double>(rf__, rf__ + *num_points__));
2122 type.add_beta_radial_function(
angular_momentum(-l, -1), std::vector<double>(rf__, rf__ + *num_points__));
2125 type.add_beta_radial_function(
angular_momentum(l), std::vector<double>(rf__, rf__ + *num_points__));
2127 }
else if (label ==
"ps_atomic_wf") {
2128 if (l__ ==
nullptr) {
2129 RTE_THROW(
"orbital quantum number must be provided for pseudo-atomic radial function");
2131 int n = (n__) ? *n__ : -1;
2132 double occ = (occ__) ? *occ__ : 0.0;
2134 std::vector<double>(rf__, rf__ + *num_points__), occ);
2135 }
else if (label ==
"ps_rho_core") {
2136 type.ps_core_charge_density(std::vector<double>(rf__, rf__ + *num_points__));
2137 }
else if (label ==
"ps_rho_total") {
2138 type.ps_total_charge_density(std::vector<double>(rf__, rf__ + *num_points__));
2139 }
else if (label ==
"vloc") {
2140 type.local_potential(std::vector<double>(rf__, rf__ + *num_points__));
2141 }
else if (label ==
"q_aug") {
2142 if (l__ ==
nullptr) {
2143 RTE_THROW(
"orbital quantum number must be provided for augmentation charge radial function");
2145 if (idxrf1__ ==
nullptr || idxrf2__ ==
nullptr) {
2146 RTE_THROW(
"both radial-function indices must be provided for augmentation charge radial function");
2148 type.add_q_radial_function(*idxrf1__ - 1, *idxrf2__ - 1, *l__,
2149 std::vector<double>(rf__, rf__ + *num_points__));
2150 }
else if (label ==
"ae_paw_wf") {
2151 type.add_ae_paw_wf(std::vector<double>(rf__, rf__ + *num_points__));
2152 }
else if (label ==
"ps_paw_wf") {
2153 type.add_ps_paw_wf(std::vector<double>(rf__, rf__ + *num_points__));
2154 }
else if (label ==
"ae_paw_core") {
2155 type.paw_ae_core_charge_density(std::vector<double>(rf__, rf__ + *num_points__));
2156 }
else if (label ==
"ae_rho") {
2157 type.free_atom_density(std::vector<double>(rf__, rf__ + *num_points__));
2159 std::stringstream s;
2160 s <<
"wrong label of radial function: " << label__;
2220 double const* occ__,
double const* U__,
double const* J__,
double const* alpha__,
2221 double const* beta__,
double const* J0__,
int* error_code__)
2225 auto& sim_ctx = get_sim_ctx(handler__);
2226 auto& type = sim_ctx.unit_cell().atom_type(std::string(label__));
2227 type.hubbard_correction(
true);
2228 type.add_hubbard_orbital(*n__, *l__, *occ__, *U__, J__[1], J__, *alpha__, *beta__, *J0__,
2229 std::vector<double>(),
true);
2267 auto& sim_ctx = get_sim_ctx(handler__);
2268 auto& type = sim_ctx.unit_cell().atom_type(std::string(label__));
2270 type.d_mtrx_ion(dion);
2308 double const* occupations__,
int const* num_occ__,
int* error_code__)
2312 auto& sim_ctx = get_sim_ctx(handler__);
2314 auto& type = sim_ctx.unit_cell().atom_type(std::string(label__));
2316 if (*num_occ__ != type.num_beta_radial_functions()) {
2317 RTE_THROW(
"PAW error: different number of occupations and wave functions!");
2323 type.paw_core_energy(*core_energy__);
2325 type.paw_wf_occ(std::vector<double>(occupations__, occupations__ + type.num_beta_radial_functions()));
2358sirius_add_atom(
void*
const* handler__,
char const* label__,
double const* position__,
double const* vector_field__,
2363 auto& sim_ctx = get_sim_ctx(handler__);
2364 if (vector_field__ !=
nullptr) {
2365 sim_ctx.unit_cell().add_atom(std::string(label__), std::vector<double>(position__, position__ + 3),
2368 sim_ctx.unit_cell().add_atom(std::string(label__), std::vector<double>(position__, position__ + 3));
2402 auto& sim_ctx = get_sim_ctx(handler__);
2403 sim_ctx.unit_cell().atom(*ia__ - 1).set_position(std::vector<double>(position__, position__ + 3));
2448sirius_set_pw_coeffs(
void*
const* handler__,
char const* label__, std::complex<double>
const* pw_coeffs__,
2449 bool const* transform_to_rg__,
int const* ngv__,
int* gvl__,
int const* comm__,
int* error_code__)
2451 PROFILE(
"sirius_api::sirius_set_pw_coeffs");
2454 auto& gs = get_gs(handler__);
2456 std::string label(label__);
2458 if (gs.ctx().full_potential()) {
2459 if (label ==
"veff") {
2460 gs.potential().set_veff_pw(pw_coeffs__);
2461 }
else if (label ==
"rm_inv") {
2462 gs.potential().set_rm_inv_pw(pw_coeffs__);
2463 }
else if (label ==
"rm2_inv") {
2464 gs.potential().set_rm2_inv_pw(pw_coeffs__);
2466 RTE_THROW(
"wrong label: " + label);
2469 RTE_ASSERT(ngv__ !=
nullptr);
2470 RTE_ASSERT(gvl__ !=
nullptr);
2471 RTE_ASSERT(comm__ !=
nullptr);
2476 std::vector<std::complex<double>> v(gs.ctx().gvec().num_gvec(), 0);
2477 #pragma omp parallel for schedule(static)
2478 for (
int i = 0; i < *ngv__; i++) {
2484 int ig = gs.ctx().gvec().index_by_gvec(G);
2486 v[ig] = pw_coeffs__[i];
2488 if (gs.ctx().gamma_point()) {
2489 ig = gs.ctx().gvec().index_by_gvec(G * (-1));
2491 std::stringstream s;
2492 auto gvc = dot(gs.ctx().unit_cell().reciprocal_lattice_vectors(),
2494 s <<
"wrong index of G-vector" << std::endl
2495 <<
"input G-vector: " << G <<
" (length: " << gvc.length() <<
" [a.u.^-1])"
2504 comm.allreduce(v.data(), gs.ctx().gvec().num_gvec());
2506 std::map<std::string, Smooth_periodic_function<double>*> func = {
2507 {
"rho", &gs.density().rho().rg()},
2508 {
"rhoc", &gs.density().rho_pseudo_core()},
2509 {
"magz", &gs.density().mag(0).rg()},
2510 {
"magx", &gs.density().mag(1).rg()},
2511 {
"magy", &gs.density().mag(2).rg()},
2512 {
"veff", &gs.potential().effective_potential().rg()},
2513 {
"bz", &gs.potential().effective_magnetic_field(0).rg()},
2514 {
"bx", &gs.potential().effective_magnetic_field(1).rg()},
2515 {
"by", &gs.potential().effective_magnetic_field(2).rg()},
2516 {
"vloc", &gs.potential().local_potential()},
2517 {
"vxc", &gs.potential().xc_potential().rg()},
2518 {
"dveff", &gs.potential().dveff()},
2521 if (!func.count(label)) {
2522 RTE_THROW(
"wrong label: " + label);
2525 func.at(label)->scatter_f_pw(v);
2527 if (transform_to_rg__ && *transform_to_rg__) {
2528 func.at(label)->fft_transform(1);
2571sirius_get_pw_coeffs(
void*
const* handler__,
char const* label__, std::complex<double>* pw_coeffs__,
int const* ngv__,
2572 int* gvl__,
int const* comm__,
int* error_code__)
2574 PROFILE(
"sirius_api::sirius_get_pw_coeffs");
2578 auto& gs = get_gs(handler__);
2580 std::string label(label__);
2581 if (gs.ctx().full_potential()) {
2582 RTE_THROW(
"not implemented");
2584 RTE_ASSERT(ngv__ != NULL);
2585 RTE_ASSERT(gvl__ != NULL);
2586 RTE_ASSERT(comm__ != NULL);
2591 std::map<std::string, Smooth_periodic_function<double>*> func = {
2592 {
"rho", &gs.density().rho().rg()},
2593 {
"magz", &gs.density().mag(0).rg()},
2594 {
"magx", &gs.density().mag(1).rg()},
2595 {
"magy", &gs.density().mag(2).rg()},
2596 {
"veff", &gs.potential().effective_potential().rg()},
2597 {
"vloc", &gs.potential().local_potential()},
2598 {
"rhoc", &gs.density().rho_pseudo_core()}};
2600 if (!func.count(label)) {
2601 RTE_THROW(
"wrong label: " + label);
2603 auto v = func.at(label)->gather_f_pw();
2605 for (
int i = 0; i < *ngv__; i++) {
2614 bool is_inverse{
false};
2615 int ig = gs.ctx().gvec().index_by_gvec(G);
2616 if (ig == -1 && gs.ctx().gvec().reduced()) {
2617 ig = gs.ctx().gvec().index_by_gvec(G * (-1));
2621 std::stringstream s;
2623 dot(gs.ctx().unit_cell().reciprocal_lattice_vectors(),
r3::vector<double>(G[0], G[1], G[2]));
2624 s <<
"wrong index of G-vector" << std::endl
2625 <<
"input G-vector: " << G <<
" (length: " << gvc.length() <<
" [a.u.^-1])" << std::endl;
2633 pw_coeffs__[i] = v[ig];
2666 auto& gs = get_gs(gs_handler__);
2667 auto& ks = get_ks(ks_handler__);
2711 bool const* precompute_rf__,
bool const* precompute_ri__,
double const* iter_solver_tol__,
2716 auto& gs = get_gs(gs_handler__);
2717 auto& ks = get_ks(ks_handler__);
2718 double tol = (iter_solver_tol__) ? *iter_solver_tol__ : ks.ctx().cfg().iterative_solver().energy_tolerance();
2719 if (precompute_pw__ && *precompute_pw__) {
2720 gs.potential().generate_pw_coefs();
2722 if ((precompute_rf__ && *precompute_rf__) || (precompute_ri__ && *precompute_ri__)) {
2723 gs.potential().update_atomic_potential();
2725 if (precompute_rf__ && *precompute_rf__) {
2726 const_cast<Unit_cell&
>(gs.ctx().unit_cell()).generate_radial_functions(gs.ctx().out());
2728 if (precompute_ri__ && *precompute_ri__) {
2729 const_cast<Unit_cell&
>(gs.ctx().unit_cell()).generate_radial_integrals();
2732 diagonalize<double, double>(H0, ks, tol);
2757 auto& gs = get_gs(handler__);
2758 gs.density().initial_density();
2783 auto& gs = get_gs(handler__);
2784 gs.potential().generate(gs.density(), gs.ctx().use_symmetry(),
false);
2818 bool const* paw_only__,
int* error_code__)
2822 auto& gs = get_gs(gs_handler__);
2823 auto add_core = get_value<bool>(add_core__,
false);
2824 auto transform_to_rg = get_value<bool>(transform_to_rg__,
false);
2825 auto paw_only = get_value<bool>(paw_only__,
false);
2828 gs.density().generate_paw_density();
2830 gs.density().generate<
double>(gs.k_point_set(), gs.ctx().use_symmetry(), add_core, transform_to_rg);
2865 double const* band_occupancies__,
int* error_code__)
2869 auto& ks = get_ks(ks_handler__);
2871 for (
int i = 0; i < ks.ctx().
num_bands(); i++) {
2872 ks.get<
double>(ik)->band_occupancy(i, *ispn__ - 1, band_occupancies__[i]);
2911 auto& ks = get_ks(ks_handler__);
2913 for (
int i = 0; i < ks.ctx().
num_bands(); i++) {
2914 band_occupancies__[i] = ks.get<
double>(ik)->band_occupancy(i, *ispn__ - 1);
2953 auto& ks = get_ks(ks_handler__);
2955 for (
int i = 0; i < ks.ctx().
num_bands(); i++) {
2956 band_energies__[i] = ks.get<
double>(ik)->band_energy(i, *ispn__ - 1);
2986sirius_get_energy(
void*
const* handler__,
char const* label__,
double* energy__,
int* error_code__)
2990 auto& gs = get_gs(handler__);
2992 auto& kset = gs.k_point_set();
2993 auto& ctx = kset.ctx();
2994 auto& unit_cell = kset.unit_cell();
2995 auto& potential = gs.potential();
2996 auto& density = gs.density();
2998 std::string label(label__);
3000 std::map<std::string, std::function<double()>> func = {
3001 {
"total", [&]() {
return sirius::total_energy(ctx, kset, density, potential, gs.ewald_energy()); }},
3011 {
"one-el", [&]() {
return sirius::one_electron_energy(density, potential); }},
3012 {
"descf", [&]() {
return gs.scf_correction_energy(); }},
3013 {
"demet", [&]() {
return kset.entropy_sum(); }},
3014 {
"paw-one-el", [&]() {
return potential.PAW_one_elec_energy(density); }},
3015 {
"paw", [&]() {
return potential.PAW_total_energy(density); }},
3016 {
"fermi", [&]() {
return kset.energy_fermi(); }},
3017 {
"hubbard", [&]() {
return sirius::hubbard_energy(density); }}};
3019 if (!func.count(label)) {
3020 RTE_THROW(
"wrong label: " + label);
3023 *energy__ = func.at(label)();
3052sirius_get_forces(
void*
const* handler__,
char const* label__,
double* forces__,
int* error_code__)
3056 std::string label(label__);
3058 auto& gs = get_gs(handler__);
3061 for (
size_t i = 0; i < sirius_forces__.size(); i++) {
3062 forces__[i] = sirius_forces__[i];
3066 auto& forces = gs.forces();
3068 std::map<std::string, sddk::mdarray<double, 2>
const& (
sirius::Force::*)(
void)> func = {
3069 {
"total", &sirius::Force::calc_forces_total}, {
"vloc", &sirius::Force::calc_forces_vloc},
3070 {
"core", &sirius::Force::calc_forces_core}, {
"ewald", &sirius::Force::calc_forces_ewald},
3071 {
"nonloc", &sirius::Force::calc_forces_nonloc}, {
"us", &sirius::Force::calc_forces_us},
3073 {
"hubbard", &sirius::Force::calc_forces_hubbard}, {
"ibs", &sirius::Force::calc_forces_ibs},
3074 {
"hf", &sirius::Force::calc_forces_hf}, {
"rho", &sirius::Force::calc_forces_rho}};
3076 if (!func.count(label)) {
3077 RTE_THROW(
"wrong label (" + label +
") for the component of forces");
3080 get_forces((forces.*func.at(label))());
3113 std::string label(label__);
3115 auto& gs = get_gs(handler__);
3117 auto& stress_tensor = gs.stress();
3119 std::map<std::string, r3::matrix<double> (
sirius::Stress::*)(void)> func = {
3122 {
"kin", &sirius::Stress::calc_stress_kin}, {
"nonloc", &sirius::Stress::calc_stress_nonloc},
3127 if (!func.count(label)) {
3128 RTE_THROW(
"wrong label (" + label +
") for the component of stress tensor");
3133 s = (stress_tensor.*func.at(label))();
3135 for (
int mu = 0; mu < 3; mu++) {
3136 for (
int nu = 0; nu < 3; nu++) {
3137 stress_tensor__[nu + mu * 3] = s(mu, nu);
3172 auto& sim_ctx = get_sim_ctx(handler__);
3174 auto& type = sim_ctx.unit_cell().atom_type(std::string(label__));
3176 *num_bp__ = type.mt_basis_size();
3226 int const* num_gvec_loc__,
int const* gvec_loc__, std::complex<double>* evec__,
3227 int const* ld__,
int const* num_spin_comp__,
int* error_code__)
3229 PROFILE(
"sirius_api::sirius_get_wave_functions");
3234 std::vector<int> igm(*num_gvec_loc__);
3239 for (
int ig = 0; ig < *num_gvec_loc__; ig++) {
3246 int ig1 = gkvec.index_by_gvec({gv(0, ig), gv(1, ig), gv(2, ig)});
3250 ig1 = gkvec.index_by_gvec({-gv(0, ig), -gv(1, ig), -gv(2, ig)});
3253 RTE_THROW(
"index of G-vector is not found");
3267 auto& ks = get_ks(ks_handler__);
3269 auto& sim_ctx = ks.ctx();
3271 std::vector<int> buf(ks.comm().size());
3275 jk = ks.find_kpoint(vkl__);
3277 std::stringstream s;
3278 s <<
"k-point is not found";
3282 ks.comm().allgather(&jk, buf.data(), 1, ks.comm().rank());
3284 for (
int i = 0; i < ks.comm().size(); i++) {
3291 int num_spin_comp{-1};
3292 if (num_spin_comp__) {
3293 num_spin_comp = *num_spin_comp__;
3294 if (!(num_spin_comp == 1 || num_spin_comp == 2)) {
3295 RTE_THROW(
"wrong number of spin components");
3298 ks.comm().bcast(&num_spin_comp, 1, dest_rank);
3299 if ((sim_ctx.num_mag_dims() == 3 && num_spin_comp != 2) ||
3300 (sim_ctx.num_mag_dims() != 3 && num_spin_comp == 2)) {
3301 RTE_THROW(
"inconsistent number of spin components");
3307 if (!(spin == 0 || spin == 1)) {
3308 RTE_THROW(
"wrong spin index");
3311 ks.comm().bcast(&spin, 1, dest_rank);
3316 if (ks.comm().rank() == src_rank || ks.comm().rank() == dest_rank) {
3321 if (ks.comm().rank() == dest_rank) {
3323 int ngk = *num_gvec_loc__;
3324 gkvec.comm().allreduce(&ngk, 1);
3325 if (ngk != gkvec.num_gvec()) {
3327 std::stringstream s;
3328 s <<
"wrong number of G+k vectors for k-point " << vkl <<
", jk = " << jk << std::endl
3329 <<
"expected number : " << gkvec.num_gvec() << std::endl
3330 <<
"actual number : " << ngk << std::endl
3331 <<
"local number of G+k vectors passed by rank " << gkvec.comm().rank() <<
" is "
3341 if (sim_ctx.num_mag_dims() != 3) {
3342 ispn0 = ispn1 = spin;
3345 for (
int s = ispn0; s <= ispn1; s++) {
3346 int tag = mpi::Communicator::get_tag(src_rank, dest_rank) + s;
3350 if (ks.comm().rank() == src_rank) {
3351 auto kp = ks.get<
double>(jk);
3352 int count = kp->spinor_wave_functions().ld();
3353 req = ks.comm().isend(kp->spinor_wave_functions().at(sddk::memory_t::host, 0,
3357 if (ks.comm().rank() == dest_rank) {
3358 int count = gkvec.count();
3360 ks.comm().recv(&wf(0, 0), count * sim_ctx.num_bands(), src_rank, tag);
3362 std::vector<std::complex<double>> wf_tmp(gkvec.num_gvec());
3363 int offset = gkvec.offset();
3366 auto igmap = gvec_mapping(gkvec);
3368 auto store_wf = [&](std::vector<std::complex<double>>& wf_tmp,
int i,
int s) {
3370 if (sim_ctx.num_mag_dims() == 1) {
3373 for (
int ig = 0; ig < *num_gvec_loc__; ig++) {
3374 int ig1 = igmap[ig];
3375 std::complex<double> z;
3381 evec(ig, ispn, i) = z;
3386 for (
int i = 0; i < sim_ctx.num_bands(); i++) {
3388 sim_ctx.comm_band().allgather(&wf(0, i), wf_tmp.data(), count, offset);
3389 store_wf(wf_tmp, i, s);
3392 if (ks.comm().rank() == src_rank) {
3442 double const* enu__,
int const* dme__,
bool const* auto_enu__,
int* error_code__)
3446 auto& sim_ctx = get_sim_ctx(handler__);
3447 auto& type = sim_ctx.unit_cell().atom_type(std::string(label__));
3448 type.add_aw_descriptor(*n__, *l__, *enu__, *dme__, *auto_enu__);
3498 int const* l__,
double const* enu__,
int const* dme__,
bool const* auto_enu__,
3503 auto& sim_ctx = get_sim_ctx(handler__);
3504 auto& type = sim_ctx.unit_cell().atom_type(std::string(label__));
3505 type.add_lo_descriptor(*ilo__ - 1, *n__, *l__, *enu__, *dme__, *auto_enu__);
3551 int const* k__,
double const* occupancy__,
bool const* core__,
int* error_code__)
3555 auto& sim_ctx = get_sim_ctx(handler__);
3556 auto& type = sim_ctx.unit_cell().atom_type(std::string(label__));
3557 type.set_configuration(*n__, *l__, *k__, *occupancy__, *core__);
3586 auto& gs = get_gs(handler__);
3588 gs.density().rho().rg().fft_transform(-1);
3589 gs.potential().poisson(gs.density().rho());
3592 for (
int ia = 0; ia < gs.ctx().unit_cell().num_atoms(); ia++) {
3593 vh_el__[ia] = gs.potential().vh_el(ia);
3620 auto& gs = get_gs(handler__);
3621 gs.potential().xc(gs.density());
3650 auto& sim_ctx = get_sim_ctx(handler__);
3651 *fcomm__ = MPI_Comm_c2f(sim_ctx.comm_k().native());
3680 auto& sim_ctx = get_sim_ctx(handler__);
3681 *fcomm__ = MPI_Comm_c2f(sim_ctx.comm_band().native());
3710 auto& sim_ctx = get_sim_ctx(handler__);
3711 *fcomm__ = MPI_Comm_c2f(sim_ctx.comm_fft().native());
3740 auto& sim_ctx = get_sim_ctx(handler__);
3741 *num_gvec__ = sim_ctx.gvec().num_gvec();
3779 int* index_by_gvec__,
int* error_code__)
3783 auto& sim_ctx = get_sim_ctx(handler__);
3785 if (gvec__ !=
nullptr) {
3787 for (
int ig = 0; ig < sim_ctx.gvec().num_gvec(); ig++) {
3788 auto gv = sim_ctx.gvec().gvec<index_domain_t::global>(ig);
3789 for (
int x : {0, 1, 2}) {
3790 gvec(x, ig) = gv[x];
3794 if (gvec_cart__ !=
nullptr) {
3796 for (
int ig = 0; ig < sim_ctx.gvec().num_gvec(); ig++) {
3797 auto gvc = sim_ctx.gvec().gvec_cart<index_domain_t::global>(ig);
3798 for (
int x : {0, 1, 2}) {
3799 gvec_cart(x, ig) = gvc[x];
3803 if (gvec_len__ !=
nullptr) {
3804 for (
int ig = 0; ig < sim_ctx.gvec().num_gvec(); ig++) {
3805 gvec_len__[ig] = sim_ctx.gvec().gvec_len<index_domain_t::global>(ig);
3808 if (index_by_gvec__ !=
nullptr) {
3809 auto d0 = sim_ctx.fft_grid().limits(0);
3810 auto d1 = sim_ctx.fft_grid().limits(1);
3811 auto d2 = sim_ctx.fft_grid().limits(2);
3814 std::fill(index_by_gvec.at(sddk::memory_t::host), index_by_gvec.at(sddk::memory_t::host) + index_by_gvec.size(),
3817 for (
int ig = 0; ig < sim_ctx.gvec().num_gvec(); ig++) {
3818 auto G = sim_ctx.gvec().gvec<index_domain_t::global>(ig);
3820 index_by_gvec(G[0], G[1], G[2]) = ig + 1;
3851 auto& sim_ctx = get_sim_ctx(handler__);
3852 *num_fft_grid_points__ = sim_ctx.spfft<
double>().local_slice_size();
3881 auto& sim_ctx = get_sim_ctx(handler__);
3882 for (
int ig = 0; ig < sim_ctx.gvec().num_gvec(); ig++) {
3883 auto G = sim_ctx.gvec().gvec<index_domain_t::global>(ig);
3884 fft_index__[ig] = sim_ctx.fft_grid().index_by_freq(G[0], G[1], G[2]) + 1;
3914 auto& ks = get_ks(ks_handler__);
3915 *max_num_gkvec__ = ks.max_num_gkvec();
3964sirius_get_gkvec_arrays(
void*
const* ks_handler__,
int* ik__,
int* num_gkvec__,
int* gvec_index__,
double* gkvec__,
3965 double* gkvec_cart__,
double* gkvec_len,
double* gkvec_tp__,
int* error_code__)
3970 auto& ks = get_ks(ks_handler__);
3972 auto kp = ks.get<
double>(*ik__ - 1);
3977 auto& comm_k = ks.ctx().comm_k();
3979 if (rank == comm_k.rank()) {
3980 *num_gkvec__ = kp->num_gkvec();
3985 for (
int igk = 0; igk < kp->num_gkvec(); igk++) {
3986 auto gkc = kp->gkvec().gkvec_cart<index_domain_t::global>(igk);
3987 auto G = kp->gkvec().gvec<index_domain_t::global>(igk);
3989 gvec_index__[igk] = ks.ctx().gvec().index_by_gvec(G) + 1;
3990 for (
int x : {0, 1, 2}) {
3991 gkvec(x, igk) = kp->gkvec().template gkvec<index_domain_t::global>(igk)[x];
3992 gkvec_cart(x, igk) = gkc[x];
3995 gkvec_len[igk] = rtp[0];
3996 gkvec_tp(0, igk) = rtp[1];
3997 gkvec_tp(1, igk) = rtp[2];
4000 comm_k.bcast(num_gkvec__, 1, rank);
4001 comm_k.bcast(gvec_index__, *num_gkvec__, rank);
4002 comm_k.bcast(gkvec__, *num_gkvec__ * 3, rank);
4003 comm_k.bcast(gkvec_cart__, *num_gkvec__ * 3, rank);
4004 comm_k.bcast(gkvec_len, *num_gkvec__, rank);
4005 comm_k.bcast(gkvec_tp__, *num_gkvec__ * 2, rank);
4038sirius_get_step_function(
void*
const* handler__, std::complex<double>* cfunig__,
double* cfunrg__,
int* num_rg_points__,
4043 auto& sim_ctx = get_sim_ctx(handler__);
4044 for (
int ig = 0; ig < sim_ctx.gvec().num_gvec(); ig++) {
4045 cfunig__[ig] = sim_ctx.theta_pw(ig);
4047 auto& fft = sim_ctx.spfft<
double>();
4051 is_local_rg =
false;
4055 RTE_THROW(
"wrong number of real space points");
4058 int offs = (is_local_rg) ? 0 : fft.dim_x() * fft.dim_y() * fft.local_z_offset();
4059 if (fft.local_slice_size()) {
4060 for (
int i = 0; i < fft.local_slice_size(); i++) {
4061 cfunrg__[offs + i] = sim_ctx.theta(i);
4124 int* ilo1__,
int* l2__,
int* o2__,
int* ilo2__,
int* error_code__)
4128 auto& sim_ctx = get_sim_ctx(handler__);
4132 if ((l1__ !=
nullptr && o1__ !=
nullptr && ilo1__ !=
nullptr) ||
4133 (l2__ !=
nullptr && o2__ !=
nullptr && ilo2__ !=
nullptr)) {
4134 RTE_THROW(
"wrong combination of radial function indices");
4136 if (l1__ !=
nullptr && o1__ !=
nullptr) {
4137 idxrf1 = sim_ctx.unit_cell().atom(ia).type().indexr_by_l_order(*l1__, *o1__ - 1);
4138 }
else if (ilo1__ !=
nullptr) {
4139 idxrf1 = sim_ctx.unit_cell().atom(ia).type().indexr_by_idxlo(*ilo1__ - 1);
4141 RTE_THROW(
"1st radial function index is not valid");
4144 if (l2__ !=
nullptr && o2__ !=
nullptr) {
4145 idxrf2 = sim_ctx.unit_cell().atom(ia).type().indexr_by_l_order(*l2__, *o2__ - 1);
4146 }
else if (ilo2__ !=
nullptr) {
4147 idxrf2 = sim_ctx.unit_cell().atom(ia).type().indexr_by_idxlo(*ilo2__ - 1);
4149 RTE_THROW(
"2nd radial function index is not valid");
4152 for (
int lm = 0;
lm < *lmmax__;
lm++) {
4153 sim_ctx.unit_cell().atom(ia).h_radial_integrals(idxrf1, idxrf2)[
lm] = val__[
lm];
4204 int* o2__,
int* ilo2__,
int* error_code__)
4209 auto& sim_ctx = get_sim_ctx(handler__);
4211 if ((o1__ !=
nullptr && ilo1__ !=
nullptr) || (o2__ !=
nullptr && ilo2__ !=
nullptr)) {
4212 RTE_THROW(
"wrong combination of radial function indices");
4215 if (o1__ !=
nullptr && ilo2__ !=
nullptr) {
4216 int idxrf2 = sim_ctx.unit_cell().atom(ia).type().indexr_by_idxlo(*ilo2__ - 1);
4217 int order2 = sim_ctx.unit_cell().atom(ia).type().indexr(idxrf2).order;
4218 sim_ctx.unit_cell().atom(ia).symmetry_class().set_o_radial_integral(*l__, *o1__ - 1, order2, *val__);
4221 if (o2__ !=
nullptr && ilo1__ !=
nullptr) {
4222 int idxrf1 = sim_ctx.unit_cell().atom(ia).type().indexr_by_idxlo(*ilo1__ - 1);
4223 int order1 = sim_ctx.unit_cell().atom(ia).type().indexr(idxrf1).order;
4224 sim_ctx.unit_cell().atom(ia).symmetry_class().set_o_radial_integral(*l__, order1, *o2__ - 1, *val__);
4227 if (ilo1__ !=
nullptr && ilo2__ !=
nullptr) {
4228 int idxrf1 = sim_ctx.unit_cell().atom(ia).type().indexr_by_idxlo(*ilo1__ - 1);
4229 int order1 = sim_ctx.unit_cell().atom(ia).type().indexr(idxrf1).order;
4230 int idxrf2 = sim_ctx.unit_cell().atom(ia).type().indexr_by_idxlo(*ilo2__ - 1);
4231 int order2 = sim_ctx.unit_cell().atom(ia).type().indexr(idxrf2).order;
4232 sim_ctx.unit_cell().atom(ia).symmetry_class().set_o_radial_integral(*l__, order1, order2, *val__);
4287 int* l2__,
int* o2__,
int* ilo2__,
int* error_code__)
4291 auto& sim_ctx = get_sim_ctx(handler__);
4295 if ((l1__ !=
nullptr && o1__ !=
nullptr && ilo1__ !=
nullptr) ||
4296 (l2__ !=
nullptr && o2__ !=
nullptr && ilo2__ !=
nullptr)) {
4297 RTE_THROW(
"wrong combination of radial function indices");
4299 if (l1__ !=
nullptr && o1__ !=
nullptr) {
4300 idxrf1 = sim_ctx.unit_cell().atom(ia).type().indexr_by_l_order(*l1__, *o1__ - 1);
4301 }
else if (ilo1__ !=
nullptr) {
4302 idxrf1 = sim_ctx.unit_cell().atom(ia).type().indexr_by_idxlo(*ilo1__ - 1);
4304 RTE_THROW(
"1st radial function index is not valid");
4307 if (l2__ !=
nullptr && o2__ !=
nullptr) {
4308 idxrf2 = sim_ctx.unit_cell().atom(ia).type().indexr_by_l_order(*l2__, *o2__ - 1);
4309 }
else if (ilo2__ !=
nullptr) {
4310 idxrf2 = sim_ctx.unit_cell().atom(ia).type().indexr_by_idxlo(*ilo2__ - 1);
4312 RTE_THROW(
"2nd radial function index is not valid");
4314 sim_ctx.unit_cell().atom(ia).symmetry_class().set_o1_radial_integral(idxrf1, idxrf2, *val__);
4360 int const* l__,
int const* o__,
int const* ilo__,
int* error_code__)
4364 auto& sim_ctx = get_sim_ctx(handler__);
4368 auto& atom = sim_ctx.unit_cell().atom(ia);
4369 int n = atom.num_mt_points();
4371 if (l__ !=
nullptr && o__ !=
nullptr && ilo__ !=
nullptr) {
4372 RTE_THROW(
"wrong combination of radial function indices");
4374 if (!(*deriv_order__ == 0 || *deriv_order__ == 1)) {
4375 RTE_THROW(
"wrond radial derivative order");
4379 if (l__ !=
nullptr && o__ !=
nullptr) {
4380 idxrf = atom.type().indexr_by_l_order(*l__, *o__ - 1);
4381 }
else if (ilo__ !=
nullptr) {
4382 idxrf = atom.type().indexr_by_idxlo(*ilo__ - 1);
4384 RTE_THROW(
"radial function index is not valid");
4387 if (*deriv_order__ == 0) {
4388 atom.symmetry_class().radial_function(idxrf, std::vector<double>(f__, f__ + n));
4390 std::vector<double> f(n);
4391 for (
int ir = 0; ir < n; ir++) {
4392 f[ir] = f__[ir] * atom.type().radial_grid()[ir];
4394 atom.symmetry_class().radial_function_derivative(idxrf, f);
4396 if (l__ !=
nullptr && o__ !=
nullptr) {
4397 atom.symmetry_class().aw_surface_deriv(*l__, *o__ - 1, *deriv_order__, f__[n - 1]);
4427 auto& sim_ctx = get_sim_ctx(handler__);
4428 sim_ctx.unit_cell().set_equivalent_atoms(equivalent_atoms__);
4453 auto& gs = get_gs(handler__);
4454 gs.potential().update_atomic_potential();
4480 *length__ =
static_cast<int>(dict[
"properties"].size());
4517 std::fill(section_name__, section_name__ + section_name_length__, 0);
4518 auto it = dict[
"properties"].begin();
4520 for (
int i = 0; i < elem__ - 1; i++, it++);
4521 auto key = it.key();
4522 if (
static_cast<int>(
key.size()) > section_name_length__ - 1) {
4523 std::stringstream s;
4524 s <<
"section name '" <<
key <<
"' is too large to fit into output string of size " << section_name_length__;
4555 auto section = std::string(section__);
4556 std::transform(section.begin(), section.end(), section.begin(), ::tolower);
4558 *length__ =
static_cast<int>(parser.size());
4619sirius_option_get_info(
char const* section__,
int elem__,
char* key_name__,
int key_name_len__,
int* type__,
4620 int* length__,
int* enum_size__,
char* title__,
int title_len__,
char* description__,
4621 int description_len__,
int *error_code__)
4625 auto section = std::string(section__);
4626 std::transform(section.begin(), section.end(), section.begin(), ::tolower);
4629 std::map<std::string, option_type_t> type_list = {
4630 {
"string", option_type_t::STRING_TYPE},
4631 {
"number", option_type_t::NUMBER_TYPE},
4632 {
"integer", option_type_t::INTEGER_TYPE},
4633 {
"boolean", option_type_t::LOGICAL_TYPE},
4634 {
"array", option_type_t::ARRAY_TYPE},
4635 {
"object", option_type_t::OBJECT_TYPE},
4636 {
"number_array_type", option_type_t::NUMBER_ARRAY_TYPE},
4637 {
"boolean_array_type", option_type_t::LOGICAL_ARRAY_TYPE},
4638 {
"integer_array_type", option_type_t::INTEGER_ARRAY_TYPE},
4639 {
"string_array_type", option_type_t::STRING_ARRAY_TYPE},
4640 {
"object_array_type", option_type_t::OBJECT_ARRAY_TYPE},
4641 {
"array_array_type", option_type_t::ARRAY_ARRAY_TYPE}
4644 std::fill(key_name__, key_name__ + key_name_len__, 0);
4645 std::fill(title__, title__ + title_len__, 0);
4646 std::fill(description__, description__ + description_len__, 0);
4648 auto it = dict.begin();
4650 for (
int i = 0; i < elem__ - 1; i++, it++);
4651 auto key = it.key();
4652 if (!dict[key].count(
"default")) {
4653 RTE_THROW(
"the default value is missing for key '" + key +
"' in section '" + section +
"'");
4655 if (dict[key][
"type"] ==
"array") {
4656 std::string tmp = dict[
key][
"items"][
"type"].get<std::string>() +
"_array_type";
4657 *type__ =
static_cast<int>(type_list[tmp]);
4658 *length__ =
static_cast<int>(dict[
key][
"default"].size());
4661 *type__ =
static_cast<int>(type_list[dict[
key][
"type"].get<std::string>()]);
4663 if (dict[key].count(
"enum")) {
4664 *enum_size__ =
static_cast<int>(dict[
key][
"enum"].size());
4669 if (
static_cast<int>(
key.size()) < key_name_len__ - 1) {
4672 RTE_THROW(
"the key_name string variable needs to be large enough to contain the full option name");
4675 if (dict[key].count(
"title")) {
4676 auto title = dict[
key].value<std::string>(
"title",
"");
4678 if (
static_cast<int>(title.size()) < title_len__ - 1) {
4679 std::copy(title.begin(), title.end(), title__);
4681 std::copy(title.begin(), title.begin() + title_len__ - 1, title__);
4686 if (dict[key].count(
"description")) {
4687 auto description = dict[
key].value<std::string>(
"description",
"");
4688 if (description.size()) {
4689 if (
static_cast<int>(description.size()) < description_len__ - 1) {
4690 std::copy(description.begin(), description.end(), description__);
4692 std::copy(description.begin(), description.begin() + description_len__ - 1, description__);
4735sirius_option_get(
char const* section__,
char const* name__,
int const* type__,
void* data_ptr__,
4736 int const* max_length__,
int const* enum_idx__,
int* error_code__)
4742 auto t =
static_cast<option_type_t
>(*type__);
4743 std::string section(section__);
4744 std::string name(name__);
4746 case option_type_t::INTEGER_TYPE:
4747 case option_type_t::INTEGER_ARRAY_TYPE: {
4748 sirius_option_get_value<int>(section, name,
static_cast<int*
>(data_ptr__), max_length__);
4751 case option_type_t::NUMBER_TYPE:
4752 case option_type_t::NUMBER_ARRAY_TYPE: {
4753 sirius_option_get_value<double>(section, name,
static_cast<double*
>(data_ptr__), max_length__);
4756 case option_type_t::LOGICAL_TYPE:
4757 case option_type_t::LOGICAL_ARRAY_TYPE: {
4758 sirius_option_get_value<bool>(section, name,
static_cast<bool*
>(data_ptr__), max_length__);
4761 case option_type_t::STRING_TYPE: {
4762 sirius_option_get_value(section, name,
static_cast<char*
>(data_ptr__), max_length__, enum_idx__);
4766 RTE_THROW(
"wrong option type");
4813sirius_option_set(
void*
const* handler__,
char const* section__,
char const* name__,
int const* type__,
4814 void const* data_ptr__,
int const* max_length__,
bool const* append__,
int* error_code__)
4818 auto& sim_ctx = get_sim_ctx(handler__);
4819 auto t =
static_cast<option_type_t
>(*type__);
4820 std::string section(section__);
4821 std::string name(name__);
4823 case option_type_t::INTEGER_TYPE:
4824 case option_type_t::INTEGER_ARRAY_TYPE: {
4825 sirius_option_set_value<int>(sim_ctx, section, name,
static_cast<int const*
>(data_ptr__), max_length__);
4828 case option_type_t::NUMBER_TYPE:
4829 case option_type_t::NUMBER_ARRAY_TYPE: {
4830 sirius_option_set_value<double>(sim_ctx, section, name,
static_cast<double const*
>(data_ptr__), max_length__);
4833 case option_type_t::LOGICAL_TYPE:
4834 case option_type_t::LOGICAL_ARRAY_TYPE: {
4835 sirius_option_set_value<bool>(sim_ctx, section, name,
static_cast<bool const*
>(data_ptr__), max_length__);
4838 case option_type_t::STRING_TYPE: {
4839 bool append = (append__ !=
nullptr) ? *append__ :
false;
4840 sirius_option_set_value(sim_ctx, section, name,
static_cast<char const*
>(data_ptr__), max_length__, append);
4844 RTE_THROW(
"wrong option type");
4875 auto& sim_ctx = get_sim_ctx(handler__);
4876 std::ofstream fi(filename__, std::ofstream::out | std::ofstream::trunc);
4877 auto conf_dict = sim_ctx.serialize();
4878 fi << conf_dict.dump(4);
4916 int const* num_fv_states__,
int* error_code__)
4920 auto& ks = get_ks(handler__);
4923 ks.get<
double>(ik)->get_fv_eigen_vectors(fv_evec);
4961 auto& ks = get_ks(handler__);
4962 if (*num_fv_states__ != ks.ctx().num_fv_states()) {
4963 RTE_THROW(
"wrong number of first-variational states");
4966 for (
int i = 0; i < *num_fv_states__; i++) {
4967 fv_eval__[i] = ks.get<
double>(ik)->fv_eigen_value(i);
5002 int const* num_bands__,
int* error_code__)
5006 auto& ks = get_ks(handler__);
5009 ks.get<
double>(ik)->get_sv_eigen_vectors(sv_evec);
5058sirius_set_rg_values(
void*
const* handler__,
char const* label__,
int const* grid_dims__,
int const* local_box_origin__,
5059 int const* local_box_size__,
int const* fcomm__,
double const* values__,
5060 bool const* transform_to_pw__,
int* error_code__)
5062 PROFILE(
"sirius_api::sirius_set_rg_values");
5066 auto& gs = get_gs(handler__);
5068 std::string label(label__);
5070 for (
int x : {0, 1, 2}) {
5071 if (grid_dims__[x] != gs.ctx().fft_grid()[x]) {
5072 std::stringstream s;
5073 s <<
"wrong FFT grid size\n"
5074 " SIRIUS internal: "
5075 << gs.ctx().fft_grid()[0] <<
" " << gs.ctx().fft_grid()[1] <<
" " << gs.ctx().fft_grid()[2]
5078 << grid_dims__[0] <<
" " << grid_dims__[1] <<
" " << grid_dims__[2];
5083 std::map<std::string, sirius::Smooth_periodic_function<double>*> func = {
5084 {
"rho", &gs.density().rho().rg()},
5085 {
"magz", &gs.density().mag(0).rg()},
5086 {
"magx", &gs.density().mag(1).rg()},
5087 {
"magy", &gs.density().mag(2).rg()},
5088 {
"veff", &gs.potential().effective_potential().rg()},
5089 {
"bz", &gs.potential().effective_magnetic_field(0).rg()},
5090 {
"bx", &gs.potential().effective_magnetic_field(1).rg()},
5091 {
"by", &gs.potential().effective_magnetic_field(2).rg()},
5092 {
"vxc", &gs.potential().xc_potential().rg()},
5094 if (!func.count(label)) {
5095 RTE_THROW(
"wrong label: " + label);
5098 auto& f = func.at(label);
5100 auto& comm = mpi::Communicator::map_fcomm(*fcomm__);
5105 for (
int rank = 0; rank < comm.size(); rank++) {
5107 int nx = local_box_size(0, rank);
5108 int ny = local_box_size(1, rank);
5109 int nz = local_box_size(2, rank);
5113 if (comm.rank() == rank) {
5115 std::copy(values__, values__ + nx * ny * nz, &buf[0]);
5118 comm.bcast(&buf[0], nx * ny * nz, rank);
5120 for (
int iz = 0; iz < nz; iz++) {
5122 int z = local_box_origin(2, rank) + iz - 1;
5124 if (z >= gs.ctx().spfft<
double>().local_z_offset() &&
5125 z < gs.ctx().spfft<
double>().local_z_offset() + gs.ctx().spfft<
double>().local_z_length()) {
5127 z -= gs.ctx().spfft<
double>().local_z_offset();
5128 for (
int iy = 0; iy < ny; iy++) {
5130 int y = local_box_origin(1, rank) + iy - 1;
5131 for (
int ix = 0; ix < nx; ix++) {
5133 int x = local_box_origin(0, rank) + ix - 1;
5134 f->value(gs.ctx().fft_grid().index_by_coord(x, y, z)) = buf(ix, iy, iz);
5140 if (transform_to_pw__ && *transform_to_pw__) {
5141 f->fft_transform(-1);
5191sirius_get_rg_values(
void*
const* handler__,
char const* label__,
int const* grid_dims__,
int const* local_box_origin__,
5192 int const* local_box_size__,
int const* fcomm__,
double* values__,
bool const* transform_to_rg__,
5195 PROFILE(
"sirius_api::sirius_get_rg_values");
5199 auto& gs = get_gs(handler__);
5201 std::string label(label__);
5203 for (
int x : {0, 1, 2}) {
5204 if (grid_dims__[x] != gs.ctx().fft_grid()[x]) {
5205 RTE_THROW(
"wrong FFT grid size");
5209 std::map<std::string, sirius::Smooth_periodic_function<double>*> func = {
5210 {
"rho", &gs.density().rho().rg()},
5211 {
"magz", &gs.density().mag(0).rg()},
5212 {
"magx", &gs.density().mag(1).rg()},
5213 {
"magy", &gs.density().mag(2).rg()},
5214 {
"veff", &gs.potential().effective_potential().rg()},
5215 {
"bz", &gs.potential().effective_magnetic_field(0).rg()},
5216 {
"bx", &gs.potential().effective_magnetic_field(1).rg()},
5217 {
"by", &gs.potential().effective_magnetic_field(2).rg()},
5218 {
"vxc", &gs.potential().xc_potential().rg()},
5221 if (!func.count(label)) {
5222 RTE_THROW(
"wrong label: " + label);
5225 auto& f = func.at(label);
5227 auto& comm = mpi::Communicator::map_fcomm(*fcomm__);
5229 if (transform_to_rg__ && *transform_to_rg__) {
5230 f->fft_transform(1);
5233 auto& fft_comm = gs.ctx().comm_fft();
5239 for (
int rank = 0; rank < fft_comm.size(); rank++) {
5242 if (rank == fft_comm.rank()) {
5243 std::copy(&f->value(0), &f->value(0) + f->spfft().local_slice_size(), &buf[0]);
5245 fft_comm.bcast(&buf[0],
static_cast<int>(buf.size()), rank);
5248 int r = comm.rank();
5251 int nx = local_box_size(0, r);
5252 int ny = local_box_size(1, r);
5253 int nz = local_box_size(2, r);
5256 for (
int iz = 0; iz < nz; iz++) {
5258 int z = local_box_origin(2, r) + iz - 1;
5259 if (z >= spl_z.global_offset(
block_id(rank)) && z < spl_z.global_offset(
block_id(rank)) +
5260 spl_z.local_size(
block_id(rank))) {
5262 z -= spl_z.global_offset(
block_id(rank));
5263 for (
int iy = 0; iy < ny; iy++) {
5265 int y = local_box_origin(1, r) + iy - 1;
5266 for (
int ix = 0; ix < nx; ix++) {
5268 int x = local_box_origin(0, r) + ix - 1;
5269 values(ix, iy, iz) = buf(x, y, z);
5303 auto& gs = get_gs(handler__);
5308 auto result = gs.density().mag(j).integrate();
5309 total_mag[j] = std::get<0>(result);
5311 if (gs.ctx().num_mag_dims() == 3) {
5313 std::swap(total_mag[0], total_mag[1]);
5315 std::swap(total_mag[1], total_mag[2]);
5346 auto& ks = get_ks(handler__);
5347 *num_kpoints__ = ks.num_kpoints();
5385 auto& ks = get_ks(handler__);
5387 *weight__ = ks.get<
double>(ik)->weight();
5389 if (coordinates__) {
5390 coordinates__[0] = ks.get<
double>(ik)->vk()[0];
5391 coordinates__[1] = ks.get<
double>(ik)->vk()[1];
5392 coordinates__[2] = ks.get<
double>(ik)->vk()[2];
5426 auto label = std::string(label__);
5427 std::transform(label.begin(), label.end(), label.begin(), ::tolower);
5428 auto& sim_ctx = get_sim_ctx(handler__);
5429 if (label ==
"beta_ri") {
5430 sim_ctx.cb().beta_ri_ =
reinterpret_cast<void (*)(
int,
double,
double*,
int)
>(fptr__);
5431 }
else if (label ==
"beta_ri_djl") {
5432 sim_ctx.cb().beta_ri_djl_ =
reinterpret_cast<void (*)(
int,
double,
double*,
int)
>(fptr__);
5433 }
else if (label ==
"aug_ri") {
5434 sim_ctx.cb().aug_ri_ =
reinterpret_cast<void (*)(
int,
double,
double*,
int,
int)
>(fptr__);
5435 }
else if (label ==
"aug_ri_djl") {
5436 sim_ctx.cb().aug_ri_djl_ =
reinterpret_cast<void (*)(
int,
double,
double*,
int,
int)
>(fptr__);
5437 }
else if (label ==
"vloc_ri") {
5438 sim_ctx.cb().vloc_ri_ =
reinterpret_cast<void (*)(
int,
int,
double*,
double*)
>(fptr__);
5439 }
else if (label ==
"vloc_ri_djl") {
5440 sim_ctx.cb().vloc_ri_djl_ =
reinterpret_cast<void (*)(
int,
int,
double*,
double*)
>(fptr__);
5441 }
else if (label ==
"rhoc_ri") {
5442 sim_ctx.cb().rhoc_ri_ =
reinterpret_cast<void (*)(
int,
int,
double*,
double*)
>(fptr__);
5443 }
else if (label ==
"rhoc_ri_djl") {
5444 sim_ctx.cb().rhoc_ri_djl_ =
reinterpret_cast<void (*)(
int,
int,
double*,
double*)
>(fptr__);
5445 }
else if (label ==
"band_occ") {
5446 sim_ctx.cb().band_occ_ =
reinterpret_cast<void (*)(
void)
>(fptr__);
5447 }
else if (label ==
"veff") {
5448 sim_ctx.cb().veff_ =
reinterpret_cast<void (*)(
void)
>(fptr__);
5449 }
else if (label ==
"ps_rho_ri") {
5450 sim_ctx.cb().ps_rho_ri_ =
reinterpret_cast<void (*)(
int,
int,
double*,
double*)
>(fptr__);
5451 }
else if (label ==
"ps_atomic_wf_ri") {
5452 sim_ctx.cb().ps_atomic_wf_ri_ =
reinterpret_cast<void (*)(
int,
double,
double*,
int)
>(fptr__);
5453 }
else if (label ==
"ps_atomic_wf_ri_djl") {
5454 sim_ctx.cb().ps_atomic_wf_ri_djl_ =
reinterpret_cast<void (*)(
int,
double,
double*,
int)
>(fptr__);
5456 RTE_THROW(
"Wrong label of the callback function: " + label);
5483sirius_nlcg(
void*
const* handler__,
void*
const* ks_handler__,
int* error_code__)
5487#if defined(SIRIUS_NLCGLIB)
5489 auto& gs = get_gs(handler__);
5490 auto& potential = gs.potential();
5491 auto& density = gs.density();
5493 auto& kset = get_ks(ks_handler__);
5494 auto& ctx = kset.ctx();
5496 auto nlcg_params = ctx.cfg().nlcg();
5497 double temp = nlcg_params.T();
5498 double tol = nlcg_params.tol();
5499 double kappa = nlcg_params.kappa();
5500 double tau = nlcg_params.tau();
5501 int maxiter = nlcg_params.maxiter();
5502 int restart = nlcg_params.restart();
5503 std::string smear = ctx.cfg().parameters().smearing();
5504 std::string pu = ctx.cfg().control().processing_unit();
5506 nlcglib::smearing_type smearing;
5507 if (smear.compare(
"FD") == 0) {
5508 smearing = nlcglib::smearing_type::FERMI_DIRAC;
5509 }
else if (smear.compare(
"GS") == 0) {
5510 smearing = nlcglib::smearing_type::GAUSSIAN_SPLINE;
5512 RTE_THROW(
"invalid smearing type given: " + smear);
5517 if (pu.empty() || pu.compare(
"gpu") == 0) {
5518 nlcglib::nlcg_mvp2_device(energy, smearing, temp, tol, kappa, tau, maxiter, restart);
5519 }
else if (pu.compare(
"cpu") == 0) {
5520 nlcglib::nlcg_mvp2_device_cpu(energy, smearing, temp, tol, kappa, tau, maxiter, restart);
5522 RTE_THROW(
"invalid processing unit for nlcg given: " + pu);
5525 if (pu.empty() || pu.compare(
"gpu") == 0) {
5526 nlcglib::nlcg_mvp2_cpu(energy, smearing, temp, tol, kappa, tau, maxiter, restart);
5527 }
else if (pu.compare(
"cpu") == 0) {
5528 nlcglib::nlcg_mvp2_cpu_device(energy, smearing, temp, tol, kappa, tau, maxiter, restart);
5530 RTE_THROW(
"invalid processing unit for nlcg given: " + pu);
5534 RTE_THROW(
"SIRIUS was not compiled with NLCG option.");
5598sirius_nlcg_params(
void*
const* handler__,
void*
const* ks_handler__,
double const* temp__,
char const* smearing__,
5599 double const* kappa__,
double const* tau__,
double const* tol__,
int const* maxiter__,
5600 int const* restart__,
char const* processing_unit__,
bool* converged__,
int* error_code__)
5604#if defined(SIRIUS_NLCGLIB)
5605 PROFILE(
"sirius::nlcglib");
5607 auto& gs = get_gs(handler__);
5608 auto& potential = gs.potential();
5609 auto& density = gs.density();
5611 auto& kset = get_ks(ks_handler__);
5612 auto& ctx = kset.ctx();
5614 double temp = *temp__;
5615 double kappa = *kappa__;
5616 double tau = *tau__;
5617 double tol = *tol__;
5618 int maxiter = *maxiter__;
5619 int restart = *restart__;
5621 std::string smear(smearing__);
5622 std::string pu(processing_unit__);
5626 if (pu.compare(
"none") != 0) {
5627 processing_unit = sddk::get_device_t(pu);
5630 nlcglib::smearing_type smearing_t;
5631 if (smear.compare(
"FD") == 0) {
5632 smearing_t = nlcglib::smearing_type::FERMI_DIRAC;
5633 }
else if (smear.compare(
"GS") == 0) {
5634 smearing_t = nlcglib::smearing_type::GAUSSIAN_SPLINE;
5635 }
else if (smear.compare(
"GAUSS") == 0) {
5636 smearing_t = nlcglib::smearing_type::GAUSS;
5637 }
else if (smear.compare(
"MP") == 0) {
5638 smearing_t = nlcglib::smearing_type::METHFESSEL_PAXTON;
5639 }
else if (smear.compare(
"COLD") == 0) {
5640 smearing_t = nlcglib::smearing_type::COLD;
5642 RTE_THROW(
"invalid smearing type given: " + smear);
5645 if (pu.compare(
"none") == 0) {
5647 pu = ctx.cfg().control().processing_unit();
5654 sirius::UltrasoftPrecond us_precond(kset, ctx, H0.Q());
5655 sirius::Overlap_operators<sirius::S_k<std::complex<double>>> S(kset, ctx, H0.Q());
5658 nlcglib::nlcg_info info;
5659 switch (processing_unit) {
5660 case sddk::device_t::CPU: {
5661 info = nlcglib::nlcg_us_cpu(energy, us_precond, S, smearing_t, temp, tol, kappa, tau, maxiter, restart);
5664 case sddk::device_t::GPU: {
5665 info = nlcglib::nlcg_us_device(energy, us_precond, S, smearing_t, temp, tol, kappa, tau, maxiter, restart);
5671 *converged__ = info.converged;
5673 RTE_THROW(
"SIRIUS was not compiled with NLCG option.");
5717 int*
const l__,
const double*
const coupling__,
int *error_code__)
5721 auto& sim_ctx = get_sim_ctx(handler__);
5722 auto conf_dict = sim_ctx.cfg().hubbard();
5725 std::vector<int> atom_pair(atom_pair__, atom_pair__ + 2);
5729 std::vector<int> n(n__, n__ + 2);
5730 std::vector<int> l(l__, l__ + 2);
5731 std::vector<int> translation(translation__, translation__ + 3);
5733 elem[
"atom_pair"] = atom_pair;
5734 elem[
"T"] = translation;
5737 elem[
"V"] = *coupling__;
5741 auto v = conf_dict.nonlocal();
5743 for (
int idx = 0; idx < v.size(); idx++) {
5744 auto v = conf_dict.nonlocal(idx);
5745 auto at_pr = v.atom_pair();
5747 if ((at_pr[0] == atom_pair[0]) && (at_pr[1] == atom_pair[1])) {
5749 if ((tr[0] = translation[0]) && (tr[1] = translation[1]) && (tr[2] = translation[2])) {
5751 if ((lvl[0] == n[0]) && (lvl[0] == n[1])) {
5753 if ((li[0] == l[0]) && (li[1] == l[1])) {
5763 conf_dict.nonlocal().append(elem);
5765 RTE_THROW(
"Atom pair for hubbard correction is already present");
5786void sirius_create_H0(
void*
const* handler__,
int* error_code__)
5790 auto& gs = get_gs(handler__);
5866void sirius_linear_solver(
void*
const* handler__,
double const* vkq__,
int const* num_gvec_kq_loc__,
5867 int const* gvec_kq_loc__, std::complex<double>* dpsi__, std::complex<double> * psi__,
double* eigvals__,
5868 std::complex<double>* dvpsi__,
int const* ld__,
int const* num_spin_comp__,
double const * alpha_pv__,
5869 int const* spin__,
int const* nbnd_occ__,
double const* tol__,
int* niter__,
int* error_code__)
5872 PROFILE(
"sirius_api::sirius_linear_solver");
5876 RTE_ASSERT(*num_spin_comp__ == 1);
5878 int nbnd_occ = *nbnd_occ__;
5880 if (nbnd_occ == 0) {
5884 auto& gs = get_gs(handler__);
5885 auto& sctx = gs.ctx();
5888 if (sctx.num_mag_dims() == 1) {
5889 if (!(*spin__ == 1 || *spin__ == 2)) {
5890 RTE_THROW(
"wrong spin channel");
5895 std::shared_ptr<fft::Gvec> gvkq_in;
5897 sctx.unit_cell().reciprocal_lattice_vectors(), *num_gvec_kq_loc__, gvec_kq_loc__,
5898 sctx.comm_band(),
false);
5900 int num_gvec_kq_loc = *num_gvec_kq_loc__;
5901 int num_gvec_kq = num_gvec_kq_loc;
5902 sctx.comm_band().allreduce(&num_gvec_kq, 1);
5904 if (num_gvec_kq != gvkq_in->num_gvec()) {
5905 RTE_THROW(
"wrong number of G+k vectors for k");
5908 auto& H0 = gs.get_H0();
5916 std::vector<double> eigvals_vec(eigvals__, eigvals__ + nbnd_occ);
5917 for (
auto &val : eigvals_vec) {
5931 for (
int ispn = 0; ispn < *num_spin_comp__; ispn++) {
5932 for (
int i = 0; i < nbnd_occ; i++) {
5933 for (
int ig = 0; ig < kp.gkvec().count(); ig++) {
5944 if (sctx.cfg().control().verification() >= 1) {
5948 sirius::check_wave_functions<double, std::complex<double>>(Hk, *psi_wf, sr,
wf::band_range(0, nbnd_occ),
5949 eigvals_vec.data());
5959 auto mem = sctx.processing_unit_memory_t();
5961 std::vector<wf::device_memory_guard> mg;
5963 mg.emplace_back(psi_wf->memory_guard(mem, wf::copy_to::device));
5964 mg.emplace_back(dpsi_wf->memory_guard(mem, wf::copy_to::device | wf::copy_to::host));
5965 mg.emplace_back(dvpsi_wf->memory_guard(mem, wf::copy_to::device));
5966 mg.emplace_back(tmp_wf->memory_guard(mem, wf::copy_to::device));
5968 mg.emplace_back(U->memory_guard(mem, wf::copy_to::device));
5969 mg.emplace_back(C->memory_guard(mem, wf::copy_to::device));
5970 mg.emplace_back(Hphi_wf->memory_guard(mem, wf::copy_to::device));
5971 mg.emplace_back(Sphi_wf->memory_guard(mem, wf::copy_to::device));
5992 auto h_o_diag = Hk.get_h_o_diag_pw<double, 3>();
5994 eigvals_mdarray = [&](sddk::mdarray_index_descriptor::index_type i) {
5995 return eigvals_vec[i];
5999 eigvals_mdarray.allocate(mem).copy_to(mem);
6003 std::move(h_o_diag.first),
6004 std::move(h_o_diag.second),
6005 std::move(eigvals_mdarray),
6013 auto result = sirius::cg::multi_cg(
6016 X_wrap, B_wrap, U_wrap, C_wrap,
6020 *niter__ = result.niter_eff;
6025 for (
int ispn = 0; ispn < *num_spin_comp__; ispn++) {
6026 for (
int i = 0; i < nbnd_occ; i++) {
6027 for (
int ig = 0; ig < kp.gkvec().count(); ig++) {
6055 auto& gs = get_gs(handler__);
6056 gs.potential().generate_D_operator_matrix();
6084 auto& gs = get_gs(handler__);
6085 std::string file_name(file_name__);
6086 gs.ctx().create_storage_file(file_name);
6087 gs.potential().save(file_name);
6088 gs.density().save(file_name);
6117 auto& gs = get_gs(handler__);
6118 std::string file_name(file_name__);
6119 gs.potential().load(file_name);
6120 gs.density().load(file_name);
6153sirius_set_density_matrix(
void** handler__,
int const* ia__, std::complex<double>* dm__,
int const* ld__,
int* error_code__)
6157 auto& gs = get_gs(handler__);
6160 auto& atom = gs.ctx().unit_cell().atom(ia);
6162 int nbf = atom.mt_basis_size();
6163 RTE_ASSERT(nbf <= *ld__);
6165 for (
int icomp = 0; icomp < gs.ctx().num_mag_comp(); icomp++) {
6166 for (
int xi1 = 0; xi1 < nbf; xi1++) {
6167 int p1 = phase_Rlm_QE(atom.type(), xi1);
6168 for (
int xi2 = 0; xi2 < nbf; xi2++) {
6169 int p2 = phase_Rlm_QE(atom.type(), xi2);
6170 gs.density().density_matrix(ia)(xi1, xi2, icomp) = dm(idx_map[xi1], idx_map[xi2], icomp) *
6171 static_cast<double>(p1 * p2);
Contains defintion of nlcglib interface.
Implementation of pointer to any object.
Check orthogonality of wave-functions and their residuals.
namespace for Niels Lohmann
Defines the properties of atom type.
int mt_basis_size() const
Total number of muffin-tin basis functions (APW + LO).
The whole DFT ground state implementation.
sddk::mdarray< double, 2 > const & calc_forces_scf_corr()
Calculate SCF correction to the forces.
void initialize(std::vector< int > const &counts={})
Initialize the k-point set.
void add_kpoints(sddk::mdarray< double, 2 > const &kpoints__, double const *weights__)
Add multiple k-points to the set.
Simulation context is a set of parameters and objects describing a single simulation.
r3::matrix< double > calc_stress_xc()
XC contribution to stress.
r3::matrix< double > calc_stress_ewald()
Ewald energy contribution to stress.
r3::matrix< double > calc_stress_us()
Contribution to the stress tensor from the augmentation operator.
r3::matrix< double > calc_stress_vloc()
Local potential contribution to stress.
r3::matrix< double > calc_stress_har()
Hartree energy contribution to stress.
r3::matrix< double > calc_stress_core()
Non-linear core correction to stress tensor.
Representation of a unit cell.
Angular momentum quantum number.
Handle deallocation of a poiniter to an object of any type.
T & get() const
Cast pointer to a given type and return a reference.
A set of G-vectors for FFTs and G+k basis functions.
MPI communicator wrapper.
void allgather(T *buffer__, int const *recvcounts__, int const *displs__) const
In-place MPI_Allgatherv.
Describe a range of bands.
Describe a range of spins.
Contains definition and partial implementation of sirius::Crystal_symmetry class.
Contains definition and partial implementation of sirius::DFT_ground_state class.
Entry point for Hamiltonain diagonalization.
Contains declaration and definition of sirius::Hamiltonian class.
Create intial subspace from atomic-like wave-functions.
Memory management functions and classes.
device_t
Type of the main processing unit.
bool is_device_memory(memory_t mem__)
Check if this is a valid device memory (memory, accessible by the device).
Linear response functionality.
@ key
the parser read a key of a value in an object
void copy(T *target__, T const *source__, size_t n__)
Copy memory inside a device.
size_t spfft_grid_size_local(T const &spfft__)
Local size of the SpFFT transformation grid.
size_t spfft_grid_size(T const &spfft__)
Total size of the SpFFT transformation grid.
auto split_z_dimension(int size_z__, mpi::Communicator const &comm_fft__)
Split z-dimenstion of size_z between MPI ranks of the FFT communicator.
auto spherical_coordinates(vector< double > vc)
Transform Cartesian coordinates [x,y,z] to spherical coordinates [r,theta,phi].
int lmmax(int lmax)
Maximum number of combinations for a given .
int lm(int l, int m)
Get composite lm index by angular index l and azimuthal index m.
std::enable_if_t< std::is_same< T, real_type< F > >::value, void > transform(::spla::Context &spla_ctx__, sddk::memory_t mem__, la::dmatrix< F > const &M__, int irow0__, int jcol0__, real_type< F > alpha__, Wave_functions< T > const &wf_in__, spin_index s_in__, band_range br_in__, real_type< F > beta__, Wave_functions< T > &wf_out__, spin_index s_out__, band_range br_out__)
Apply linear transformation to the wave-functions.
Namespace of the SIRIUS library.
subroutine sirius_get_max_num_gkvec(ks_handler, max_num_gkvec, error_code)
Get maximum number of G+k vectors across all k-points in the set.
subroutine sirius_set_atom_position(handler, ia, position, error_code)
Set new atomic position.
subroutine sirius_set_callback_function(handler, label, fptr, error_code)
Set callback function to compute various radial integrals.
subroutine sirius_option_get(section, name, type, data_ptr, max_length, enum_idx, error_code)
Return the default value of the option as defined in the JSON schema.
subroutine sirius_generate_xc_potential(handler, error_code)
Generate XC potential using LibXC.
subroutine sirius_set_density_matrix(handler, ia, dm, ld, error_code)
Set density matrix.
subroutine sirius_create_kset_from_grid(handler, k_grid, k_shift, use_symmetry, kset_handler, error_code)
Create k-point set from a grid.
subroutine sirius_get_kpoint_properties(handler, ik, weight, coordinates, error_code)
Get the kpoint properties.
subroutine sirius_set_o_radial_integral(handler, ia, val, l, o1, ilo1, o2, ilo2, error_code)
Set LAPW overlap radial integral.
double total_energy(Simulation_context const &ctx, K_point_set const &kset, Density const &density, Potential const &potential, double ewald_energy)
Total energy of the electronic subsystem.
subroutine sirius_serialize_timers(fname, error_code)
Save all timers to JSON file.
subroutine sirius_linear_solver(handler, vkq, num_gvec_kq_loc, gvec_kq_loc, dpsi, psi, eigvals, dvpsi, ld, num_spin_comp, alpha_pv, spin, nbnd_occ, tol, niter, error_code)
Interface to linear solver.
subroutine sirius_get_num_fft_grid_points(handler, num_fft_grid_points, error_code)
Get local number of FFT grid points.
subroutine sirius_set_equivalent_atoms(handler, equivalent_atoms, error_code)
Set equivalent atoms.
subroutine sirius_option_get_number_of_sections(length, error_code)
Return the total number of sections defined in the input JSON schema.
subroutine sirius_get_fv_eigen_vectors(handler, ik, fv_evec, ld, num_fv_states, error_code)
Get the first-variational eigen vectors.
subroutine sirius_get_fft_index(handler, fft_index, error_code)
Get mapping between G-vector index and FFT index.
subroutine sirius_set_radial_function(handler, ia, deriv_order, f, l, o, ilo, error_code)
Set LAPW radial functions.
subroutine sirius_stop_timer(name, error_code)
Stop the running timer.
subroutine sirius_add_atom_type_radial_function(handler, atom_type, label, rf, num_points, n, l, idxrf1, idxrf2, occ, error_code)
Add one of the radial functions.
double energy_veff(Density const &density, Potential const &potential)
TODO doc.
subroutine sirius_update_ground_state(gs_handler, error_code)
Update a ground state object after change of atomic coordinates or lattice vectors.
subroutine sirius_update_context(handler, error_code)
Update simulation context after changing lattice or atomic positions.
subroutine sirius_initialize_context(handler, error_code)
Initialize simulation context.
subroutine sirius_get_gkvec_arrays(ks_handler, ik, num_gkvec, gvec_index, gkvec, gkvec_cart, gkvec_len, gkvec_tp, error_code)
Get all G+k vector related arrays.
subroutine sirius_get_fft_comm(handler, fcomm, error_code)
Get communicator which is used to parallise FFT.
subroutine sirius_create_kset(handler, num_kpoints, kpoints, kpoint_weights, init_kset, kset_handler, error_code)
Create k-point set from the list of k-points.
subroutine sirius_create_context(fcomm, handler, fcomm_k, fcomm_band, error_code)
Create context of the simulation.
subroutine sirius_set_atom_type_radial_grid(handler, label, num_radial_points, radial_points, error_code)
Set radial grid of the atom type.
subroutine sirius_generate_effective_potential(handler, error_code)
Generate effective potential and magnetic field.
subroutine sirius_nlcg(handler, ks_handler, error_code)
Robust wave function optimizer.
subroutine sirius_set_mpi_grid_dims(handler, ndims, dims, error_code)
Set dimensions of the MPI grid.
subroutine sirius_add_atom_type(handler, label, fname, zn, symbol, mass, spin_orbit, error_code)
Add new atom type to the unit cell.
subroutine sirius_create_ground_state(ks_handler, gs_handler, error_code)
Create a ground state object.
subroutine sirius_get_band_occupancies(ks_handler, ik, ispn, band_occupancies, error_code)
Set band occupancies.
double eval_sum(Unit_cell const &unit_cell, K_point_set const &kset)
TODO doc.
subroutine sirius_generate_d_operator_matrix(handler, error_code)
Generate D-operator matrix.
subroutine sirius_get_num_gvec(handler, num_gvec, error_code)
Get total number of G-vectors on the fine grid.
strong_type< int, struct __block_id_tag > block_id
ID of the block.
subroutine sirius_get_fv_eigen_values(handler, ik, fv_eval, num_fv_states, error_code)
Get the first-variational eigen values.
subroutine sirius_print_info(handler, error_code)
Print basic info.
subroutine sirius_get_forces(handler, label, forces, error_code)
Get one of the total force components.
subroutine sirius_finalize(call_mpi_fin, call_device_reset, call_fftw_fin, error_code)
Shut down the SIRIUS library.
subroutine sirius_check_scf_density(gs_handler, error_code)
Check the self-consistent density.
subroutine sirius_add_atom_type_aw_descriptor(handler, label, n, l, enu, dme, auto_enu, error_code)
Add descriptor of the augmented wave radial function.
subroutine sirius_option_get_section_length(section, length, error_code)
Return the number of options in a given section.
subroutine sirius_get_num_beta_projectors(handler, label, num_bp, error_code)
Get the number of beta-projectors for an atom type.
subroutine sirius_update_atomic_potential(handler, error_code)
Set the new spherical potential.
subroutine sirius_set_atom_type_radial_grid_inf(handler, label, num_radial_points, radial_points, error_code)
Set radial grid of the free atom (up to effectice infinity).
subroutine sirius_import_parameters(handler, str, error_code)
Import parameters of simulation from a JSON string.
subroutine sirius_set_parameters(handler, lmax_apw, lmax_rho, lmax_pot, num_fv_states, num_bands, num_mag_dims, pw_cutoff, gk_cutoff, fft_grid_size, auto_rmt, gamma_point, use_symmetry, so_correction, valence_rel, core_rel, iter_solver_tol_empty, iter_solver_type, verbosity, hubbard_correction, hubbard_correction_kind, hubbard_full_orthogonalization, hubbard_orbitals, sht_coverage, min_occupancy, smearing, smearing_width, spglib_tol, electronic_structure_method, error_code)
Set parameters of the simulation.
strong_type< int, struct __rf_index_tag > rf_index
Radial function index.
subroutine sirius_get_gvec_arrays(handler, gvec, gvec_cart, gvec_len, index_by_gvec, error_code)
Get G-vector arrays.
subroutine sirius_save_state(gs_handler, file_name, error_code)
Save DFT ground state (density and potential)
subroutine sirius_set_atom_type_paw(handler, label, core_energy, occupations, num_occ, error_code)
Set PAW related data.
subroutine sirius_set_o1_radial_integral(handler, ia, val, l1, o1, ilo1, l2, o2, ilo2, error_code)
Set a correction to LAPW overlap radial integral.
subroutine sirius_dump_runtime_setup(handler, filename, error_code)
Dump the runtime setup in a file.
subroutine sirius_option_get_info(section, elem, key_name, key_name_len, type, length, enum_size, title, title_len, description, description_len, error_code)
Return information about the option.
void initialize(bool call_mpi_init__=true)
Initialize the library.
subroutine sirius_get_band_energies(ks_handler, ik, ispn, band_energies, error_code)
Get band energies.
subroutine sirius_get_num_kpoints(handler, num_kpoints, error_code)
Get the total number of kpoints.
subroutine sirius_set_atom_type_dion(handler, label, num_beta, dion, error_code)
Set ionic part of D-operator matrix.
double energy_vxc(Density const &density, Potential const &potential)
Returns exchange correlation potential.
subroutine sirius_get_periodic_function(handler, label, f_mt, lmmax, nrmtmax, num_atoms, f_rg, size_x, size_y, size_z, offset_z, error_code)
Get values of the periodic function.
subroutine sirius_option_set(handler, section, name, type, data_ptr, max_length, append, error_code)
Set the value of the option name in a (internal) json dictionary.
subroutine sirius_context_initialized(handler, status, error_code)
Check if the simulation context is initialized.
subroutine sirius_load_state(handler, file_name, error_code)
Save DFT ground state (density and potential)
subroutine sirius_option_get_section_name(elem, section_name, section_name_length, error_code)
Return the name of a given section.
subroutine sirius_print_timers(flatten, error_code)
Print all timers.
subroutine sirius_set_periodic_function(handler, label, f_mt, lmmax, nrmtmax, num_atoms, f_rg, size_x, size_y, size_z, offset_z, error_code)
Set values of the periodic function.
double energy_vloc(Density const &density, Potential const &potential)
TODO doc.
subroutine sirius_get_stress_tensor(handler, label, stress_tensor, error_code)
Get one of the stress tensor components.
subroutine sirius_set_band_occupancies(ks_handler, ik, ispn, band_occupancies, error_code)
Set band occupancies.
subroutine sirius_add_atom(handler, label, position, vector_field, error_code)
Add atom to the unit cell.
subroutine sirius_add_hubbard_atom_pair(handler, atom_pair, translation, n, l, coupling, error_code)
Add a non-local Hubbard interaction V for a pair of atoms.
subroutine sirius_set_lattice_vectors(handler, a1, a2, a3, error_code)
Set vectors of the unit cell.
double energy_vha(Potential const &potential)
Returns Hatree potential.
subroutine sirius_get_parameters(handler, lmax_apw, lmax_rho, lmax_pot, num_fv_states, num_bands, num_spins, num_mag_dims, pw_cutoff, gk_cutoff, fft_grid_size, auto_rmt, gamma_point, use_symmetry, so_correction, iter_solver_tol, iter_solver_tol_empty, verbosity, hubbard_correction, evp_work_count, num_loc_op_applied, num_sym_op, electronic_structure_method, error_code)
Get parameters of the simulation.
subroutine sirius_add_atom_type_lo_descriptor(handler, label, ilo, n, l, enu, dme, auto_enu, error_code)
Add descriptor of the local orbital radial function.
subroutine sirius_free_object_handler(handler, error_code)
Free any object handler created by SIRIUS.
subroutine sirius_add_xc_functional(handler, name, error_code)
Add one of the XC functionals.
double energy_kin(Simulation_context const &ctx, K_point_set const &kset, Density const &density, Potential const &potential)
Return kinetic energy.
subroutine sirius_set_rg_values(handler, label, grid_dims, local_box_origin, local_box_size, fcomm, values, transform_to_pw, error_code)
Set the values of the function on the regular grid.
subroutine sirius_initialize(call_mpi_init, error_code)
Initialize the SIRIUS library.
subroutine sirius_get_step_function(handler, cfunig, cfunrg, num_rg_points, error_code)
Get the unit-step function.
double energy_enuc(Simulation_context const &ctx, Potential const &potential)
Return nucleus energy in the electrostatic field.
subroutine sirius_set_periodic_function_ptr(handler, label, f_mt, lmmax, nrmtmax, num_atoms, f_rg, size_x, size_y, size_z, offset_z, error_code)
Set pointer to density or magnetization.
subroutine sirius_set_atom_type_hubbard(handler, label, l, n, occ, U, J, alpha, beta, J0, error_code)
Set the hubbard correction for the atomic type.
subroutine sirius_get_kpoint_inter_comm(handler, fcomm, error_code)
Get communicator which is used to split k-points.
void initialize_subspace(Hamiltonian_k< T > const &Hk__, K_point< T > &kp__, int num_ao__)
Initialize the wave-functions subspace at a given k-point.
double energy_bxc(const Density &density, const Potential &potential)
TODO doc.
subroutine sirius_start_timer(name, error_code)
Start the timer.
subroutine sirius_get_total_magnetization(handler, mag, error_code)
Get the total magnetization of the system.
void finalize(bool call_mpi_fin__=true, bool reset_device__=true, bool fftw_cleanup__=true)
Shut down the library.
auto conj(double x__)
Return complex conjugate of a number. For a real value this is the number itself.
subroutine sirius_generate_coulomb_potential(handler, vh_el, error_code)
Generate Coulomb potential by solving Poisson equation.
subroutine sirius_get_sv_eigen_vectors(handler, ik, sv_evec, num_bands, error_code)
Get the second-variational eigen vectors.
subroutine sirius_get_rg_values(handler, label, grid_dims, local_box_origin, local_box_size, fcomm, values, transform_to_rg, error_code)
Get the values of the function on the regular grid.
subroutine sirius_find_ground_state(gs_handler, density_tol, energy_tol, iter_solver_tol, initial_guess, max_niter, save_state, converged, niter, rho_min, error_code)
Find the ground state.
nlohmann::json const & get_section_options(std::string const §ion__)
Get all possible options of a given input section. It is a json dictionary.
subroutine sirius_get_energy(handler, label, energy, error_code)
Get one of the total energy components.
subroutine sirius_set_atom_type_configuration(handler, label, n, l, k, occupancy, core, error_code)
Set configuration of atomic levels.
subroutine sirius_generate_density(gs_handler, add_core, transform_to_rg, paw_only, error_code)
Generate charge density and magnetization.
subroutine sirius_nlcg_params(handler, ks_handler, temp, smearing, kappa, tau, tol, maxiter, restart, processing_unit, converged, error_code)
Robust wave function optimizer.
double energy_exc(Density const &density, Potential const &potential)
Returns exchange correlation energy.
subroutine sirius_set_h_radial_integrals(handler, ia, lmmax, val, l1, o1, ilo1, l2, o2, ilo2, error_code)
Set LAPW Hamiltonian radial integrals.
subroutine sirius_generate_initial_density(handler, error_code)
Generate initial density.
subroutine sirius_get_kpoint_inner_comm(handler, fcomm, error_code)
Get communicator which is used to parallise band problem.
subroutine sirius_set_pw_coeffs(handler, label, pw_coeffs, transform_to_rg, ngv, gvl, comm, error_code)
Set plane-wave coefficients of a periodic function.
subroutine sirius_get_pw_coeffs(handler, label, pw_coeffs, ngv, gvl, comm, error_code)
Get plane-wave coefficients of a periodic function.
subroutine sirius_find_eigen_states(gs_handler, ks_handler, precompute_pw, precompute_rf, precompute_ri, iter_solver_tol, error_code)
Find eigen-states of the Hamiltonian.
subroutine sirius_initialize_subspace(gs_handler, ks_handler, error_code)
Initialize the subspace of wave-functions.
nlohmann::json const & get_options_dictionary()
Get all possible options for initializing sirius. It is a json dictionary.
subroutine sirius_initialize_kset(ks_handler, count, error_code)
Initialize k-point set.
"All-in-one" include file.
void sirius_get_wave_functions(void *const *ks_handler__, double const *vkl__, int const *spin__, int const *num_gvec_loc__, int const *gvec_loc__, std::complex< double > *evec__, int const *ld__, int const *num_spin_comp__, int *error_code__)
static int idx_m_qe(int m__)
Index of Rlm in QE in the block of lm coefficients for a given l.
static std::vector< int > atomic_orbital_index_map_QE(Atom_type const &type__)
Mapping of atomic indices from SIRIUS to QE order.
Describe external pointers to periodic function.
Provides preconditioner for ultrasoft case.