Skip to content

Commit f520f0e

Browse files
committed
Migrate more derivative methods to the DerivativeIFC class
1 parent eb6bede commit f520f0e

File tree

4 files changed

+361
-412
lines changed

4 files changed

+361
-412
lines changed

anphon/ifc_derivative.cpp

Lines changed: 318 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,15 @@
11
#include "ifc_derivative.h"
2+
#include <boost/sort/block_indirect_sort/block_indirect_sort.hpp>
23
#include <cstdlib>
34
#include <iomanip>
45
#include <iostream>
56
#include <sstream>
7+
#include "anharmonic_core.h"
68
#include "constants.h"
9+
#include "dynamical.h"
710
#include "error.h"
811
#include "mpi_common.h"
12+
#include "scph.h"
913
#include "system.h"
1014

1115
using namespace PHON_NS;
@@ -141,6 +145,320 @@ bool are_same_fcs_array_with_cell_verbose(const std::vector<FcsArrayWithCell> &l
141145
DerivativeIFC::DerivativeIFC(PHON *phon): Pointers(phon)
142146
{}
143147

148+
void DerivativeIFC::compute_del_v1_del_umn(std::complex<double> **del_v1_del_umn,
149+
const std::complex<double> *const *const *const evec_harmonic) const
150+
{
151+
const auto natmin = system->get_primcell().number_of_atoms;
152+
const auto ns = dynamical->neval;
153+
const auto invsqrt_mass = system->get_invsqrt_mass();
154+
Eigen::MatrixXd del_v1_del_umn_in_real_space(9, ns);
155+
156+
int ixyz1;
157+
158+
del_v1_del_umn_in_real_space.setZero();
159+
160+
for (const auto &it: fcs_phonon->force_constant_with_cell[0]) {
161+
const int ind1 = it.pairs[0].index;
162+
for (ixyz1 = 0; ixyz1 < 3; ixyz1++) {
163+
del_v1_del_umn_in_real_space(it.coords[1] * 3 + ixyz1, ind1) += it.fcs_val * it.relvecs_velocity[0][ixyz1];
164+
}
165+
}
166+
167+
for (int ixyz = 0; ixyz < 9; ixyz++) {
168+
for (int is1 = 0; is1 < ns; is1++) {
169+
del_v1_del_umn[ixyz][is1] = 0.0;
170+
for (int i = 0; i < natmin; i++) {
171+
for (ixyz1 = 0; ixyz1 < 3; ixyz1++) {
172+
del_v1_del_umn[ixyz][is1] += evec_harmonic[0][is1][i * 3 + ixyz1] * invsqrt_mass[i] *
173+
del_v1_del_umn_in_real_space(ixyz, i * 3 + ixyz1);
174+
}
175+
}
176+
}
177+
}
178+
}
179+
180+
void DerivativeIFC::compute_del2_v1_del_umn2(std::complex<double> **del2_v1_del_umn2,
181+
const std::complex<double> *const *const *const evec_harmonic) const
182+
{
183+
const auto natmin = system->get_primcell().number_of_atoms;
184+
const auto ns = dynamical->neval;
185+
const auto invsqrt_mass = system->get_invsqrt_mass();
186+
Eigen::MatrixXd del2_v1_del_umn2_in_real_space(81, ns);
187+
188+
int ixyz1;
189+
190+
del2_v1_del_umn2_in_real_space.setZero();
191+
192+
for (auto &it: fcs_phonon->force_constant_with_cell[1]) {
193+
194+
const int ind1 = it.pairs[0].index;
195+
196+
for (ixyz1 = 0; ixyz1 < 3; ixyz1++) {
197+
for (int ixyz2 = 0; ixyz2 < 3; ixyz2++) {
198+
int const ixyz_comb = it.coords[1] * 27 + ixyz1 * 9 + it.coords[2] * 3 + ixyz2;
199+
del2_v1_del_umn2_in_real_space(ixyz_comb, ind1) +=
200+
it.fcs_val * it.relvecs_velocity[0][ixyz1] * it.relvecs_velocity[1][ixyz2];
201+
}
202+
}
203+
}
204+
205+
for (int ixyz = 0; ixyz < 81; ixyz++) {
206+
for (int is1 = 0; is1 < ns; is1++) {
207+
del2_v1_del_umn2[ixyz][is1] = 0.0;
208+
for (int i = 0; i < natmin; i++) {
209+
for (ixyz1 = 0; ixyz1 < 3; ixyz1++) {
210+
del2_v1_del_umn2[ixyz][is1] += evec_harmonic[0][is1][i * 3 + ixyz1] * invsqrt_mass[i] *
211+
del2_v1_del_umn2_in_real_space(ixyz, i * 3 + ixyz1);
212+
}
213+
}
214+
}
215+
}
216+
}
217+
218+
void DerivativeIFC::compute_del3_v1_del_umn3(std::complex<double> **del3_v1_del_umn3,
219+
const std::complex<double> *const *const *const evec_harmonic) const
220+
{
221+
const auto natmin = system->get_primcell().number_of_atoms;
222+
const auto ns = dynamical->neval;
223+
const auto invsqrt_mass = system->get_invsqrt_mass();
224+
Eigen::MatrixXd del3_v1_del_umn3_in_real_space(729, ns);
225+
226+
int ixyz1;
227+
228+
del3_v1_del_umn3_in_real_space.setZero();
229+
230+
for (auto &it: fcs_phonon->force_constant_with_cell[2]) {
231+
232+
int ind1 = it.pairs[0].index;
233+
234+
for (ixyz1 = 0; ixyz1 < 3; ixyz1++) {
235+
for (int ixyz2 = 0; ixyz2 < 3; ixyz2++) {
236+
for (int ixyz3 = 0; ixyz3 < 3; ixyz3++) {
237+
const int ixyz_comb =
238+
it.coords[1] * 243 + ixyz1 * 81 + it.coords[2] * 27 + ixyz2 * 9 + it.coords[3] * 3 + ixyz3;
239+
del3_v1_del_umn3_in_real_space(ixyz_comb, ind1) += it.fcs_val * it.relvecs_velocity[0][ixyz1] *
240+
it.relvecs_velocity[1][ixyz2] *
241+
it.relvecs_velocity[2][ixyz3];
242+
}
243+
}
244+
}
245+
}
246+
247+
for (int ixyz = 0; ixyz < 729; ixyz++) {
248+
for (int is1 = 0; is1 < ns; is1++) {
249+
del3_v1_del_umn3[ixyz][is1] = 0.0;
250+
for (int i = 0; i < natmin; i++) {
251+
for (ixyz1 = 0; ixyz1 < 3; ixyz1++) {
252+
del3_v1_del_umn3[ixyz][is1] += evec_harmonic[0][is1][i * 3 + ixyz1] * invsqrt_mass[i] *
253+
del3_v1_del_umn3_in_real_space(ixyz, i * 3 + ixyz1);
254+
}
255+
}
256+
}
257+
}
258+
}
259+
260+
void DerivativeIFC::compute_del_v2_del_umn(std::complex<double> ***del_v2_del_umn,
261+
const std::complex<double> *const *const *const evec_harmonic,
262+
const unsigned int nk,
263+
double **xk_in) const
264+
{
265+
using namespace Eigen;
266+
267+
const auto ns = dynamical->neval;
268+
int is1, is2;
269+
270+
std::vector<FcsArrayWithCell> delta_fcs;
271+
272+
std::complex<double> **mat_tmp;
273+
allocate(mat_tmp, ns, ns);
274+
275+
MatrixXcd Dymat(ns, ns);
276+
MatrixXcd evec_tmp(ns, ns);
277+
278+
std::vector<FcsArrayWithCell> fcs_aligned;
279+
280+
fcs_aligned.clear();
281+
282+
for (const auto &it: fcs_phonon->force_constant_with_cell[1]) {
283+
fcs_aligned.emplace_back(it);
284+
}
285+
sort_by_heading_indices const operator_fcs(1);
286+
boost::sort::block_indirect_sort(fcs_aligned.begin(), fcs_aligned.end(), operator_fcs);
287+
288+
for (int ixyz1 = 0; ixyz1 < 3; ixyz1++) {
289+
for (int ixyz2 = 0; ixyz2 < 3; ixyz2++) {
290+
compute_del_v_strain_in_real_space1(fcs_aligned, delta_fcs, ixyz1, ixyz2);
291+
292+
for (int ik = 0; ik < nk; ik++) {
293+
294+
dynamical->calc_analytic_k(xk_in[ik], delta_fcs, mat_tmp);
295+
296+
for (is1 = 0; is1 < ns; is1++) {
297+
for (is2 = 0; is2 < ns; is2++) {
298+
Dymat(is1, is2) = mat_tmp[is1][is2];
299+
evec_tmp(is1, is2) = evec_harmonic[ik][is2][is1];
300+
}
301+
}
302+
Dymat = evec_tmp.adjoint() * Dymat * evec_tmp;
303+
304+
for (is1 = 0; is1 < ns; is1++) {
305+
for (is2 = 0; is2 < ns; is2++) {
306+
del_v2_del_umn[ixyz1 * 3 + ixyz2][ik][is1 * ns + is2] = Dymat(is1, is2);
307+
}
308+
}
309+
}
310+
}
311+
}
312+
313+
deallocate(mat_tmp);
314+
}
315+
316+
void DerivativeIFC::compute_del2_v2_del_umn2(std::complex<double> ***del2_v2_del_umn2,
317+
const std::complex<double> *const *const *const evec_harmonic,
318+
const unsigned int nk,
319+
double **xk_in) const
320+
{
321+
using namespace Eigen;
322+
323+
const auto ns = dynamical->neval;
324+
325+
std::vector<FcsArrayWithCell> fcs_aligned;
326+
fcs_aligned.clear();
327+
for (const auto &it: fcs_phonon->force_constant_with_cell[2]) {
328+
fcs_aligned.emplace_back(it);
329+
}
330+
sort_by_heading_indices const operator_fcs(2);
331+
boost::sort::block_indirect_sort(fcs_aligned.begin(), fcs_aligned.end(), operator_fcs);
332+
333+
#pragma omp parallel
334+
{
335+
int ixyz;
336+
int is1, is2;
337+
std::vector<FcsArrayWithCell> delta_fcs;
338+
339+
std::complex<double> **mat_tmp;
340+
allocate(mat_tmp, ns, ns);
341+
342+
MatrixXcd Dymat(ns, ns);
343+
MatrixXcd evec_tmp(ns, ns);
344+
345+
#pragma omp for
346+
for (ixyz = 0; ixyz < 81; ixyz++) {
347+
int itmp = ixyz;
348+
const int ixyz22 = itmp % 3;
349+
itmp /= 3;
350+
const int ixyz21 = itmp % 3;
351+
itmp /= 3;
352+
const int ixyz12 = itmp % 3;
353+
const int ixyz11 = itmp / 3;
354+
355+
compute_del_v_strain_in_real_space2(fcs_aligned, delta_fcs, ixyz11, ixyz12, ixyz21, ixyz22);
356+
357+
for (int ik = 0; ik < nk; ik++) {
358+
dynamical->calc_analytic_k(xk_in[ik], delta_fcs, mat_tmp);
359+
360+
for (is1 = 0; is1 < ns; is1++) {
361+
for (is2 = 0; is2 < ns; is2++) {
362+
Dymat(is1, is2) = mat_tmp[is1][is2];
363+
evec_tmp(is1, is2) = evec_harmonic[ik][is2][is1];
364+
}
365+
}
366+
Dymat = evec_tmp.adjoint() * Dymat * evec_tmp;
367+
368+
for (is1 = 0; is1 < ns; is1++) {
369+
for (is2 = 0; is2 < ns; is2++) {
370+
del2_v2_del_umn2[ixyz][ik][is1 * ns + is2] = Dymat(is1, is2);
371+
}
372+
}
373+
}
374+
}
375+
376+
deallocate(mat_tmp);
377+
}
378+
}
379+
380+
void DerivativeIFC::compute_del_v3_del_umn(std::complex<double> ****del_v3_del_umn,
381+
double **omega2_harmonic,
382+
const std::complex<double> *const *const *const evec_harmonic,
383+
const KpointMeshUniform *kmesh_coarse_in,
384+
const KpointMeshUniform *kmesh_dense_in,
385+
const PhaseFactorStorage *phase_storage_in) const
386+
{
387+
int ngroup_tmp;
388+
double *invmass_v3_tmp;
389+
int **evec_index_v3_tmp;
390+
std::vector<double> *fcs_group_tmp;
391+
std::vector<RelativeVector> *relvec_tmp;
392+
std::complex<double> *phi3_reciprocal_tmp;
393+
394+
int i;
395+
int ixyz1, ixyz2;
396+
397+
double *invsqrt_mass_p;
398+
allocate(invsqrt_mass_p, system->get_primcell().number_of_atoms);
399+
for (i = 0; i < system->get_primcell().number_of_atoms; ++i) {
400+
invsqrt_mass_p[i] = std::sqrt(1.0 / system->get_mass_prim()[i]);
401+
}
402+
403+
std::vector<FcsArrayWithCell> delta_fcs;
404+
std::vector<FcsArrayWithCell> fcs_aligned;
405+
fcs_aligned.clear();
406+
for (const auto &it: fcs_phonon->force_constant_with_cell[2]) {
407+
fcs_aligned.emplace_back(it);
408+
}
409+
const sort_by_heading_indices operator_fcs(1);
410+
boost::sort::block_indirect_sort(fcs_aligned.begin(), fcs_aligned.end(), operator_fcs);
411+
412+
for (ixyz1 = 0; ixyz1 < 3; ixyz1++) {
413+
for (ixyz2 = 0; ixyz2 < 3; ixyz2++) {
414+
415+
compute_del_v_strain_in_real_space1(fcs_aligned, delta_fcs, ixyz1, ixyz2);
416+
417+
boost::sort::block_indirect_sort(delta_fcs.begin(), delta_fcs.end());
418+
419+
anharmonic_core->prepare_group_of_force_constants(delta_fcs, ngroup_tmp, fcs_group_tmp);
420+
421+
allocate(invmass_v3_tmp, ngroup_tmp);
422+
allocate(evec_index_v3_tmp, ngroup_tmp, 3);
423+
allocate(relvec_tmp, ngroup_tmp);
424+
allocate(phi3_reciprocal_tmp, ngroup_tmp);
425+
426+
anharmonic_core->prepare_relative_vector(delta_fcs, ngroup_tmp, fcs_group_tmp, relvec_tmp);
427+
428+
int k = 0;
429+
for (i = 0; i < ngroup_tmp; ++i) {
430+
for (int j = 0; j < 3; ++j) {
431+
evec_index_v3_tmp[i][j] = delta_fcs[k].pairs[j].index;
432+
}
433+
invmass_v3_tmp[i] = invsqrt_mass_p[evec_index_v3_tmp[i][0] / 3] *
434+
invsqrt_mass_p[evec_index_v3_tmp[i][1] / 3] *
435+
invsqrt_mass_p[evec_index_v3_tmp[i][2] / 3];
436+
k += fcs_group_tmp[i].size();
437+
}
438+
439+
scph->compute_V3_elements_for_given_IFCs(del_v3_del_umn[ixyz1 * 3 + ixyz2],
440+
omega2_harmonic,
441+
ngroup_tmp,
442+
fcs_group_tmp,
443+
relvec_tmp,
444+
invmass_v3_tmp,
445+
evec_index_v3_tmp,
446+
evec_harmonic,
447+
true,
448+
kmesh_coarse_in,
449+
kmesh_dense_in,
450+
phase_storage_in);
451+
452+
deallocate(fcs_group_tmp);
453+
deallocate(invmass_v3_tmp);
454+
deallocate(evec_index_v3_tmp);
455+
deallocate(relvec_tmp);
456+
deallocate(phi3_reciprocal_tmp);
457+
}
458+
}
459+
deallocate(invsqrt_mass_p);
460+
}
461+
144462
bool DerivativeIFC::check_del_v_strain_in_real_space_equivalence(
145463
const std::vector<FcsArrayWithCell> &fcs_aligned,
146464
const std::vector<std::pair<int, int>> &strain_components) const

anphon/ifc_derivative.h

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,9 @@
1111
namespace PHON_NS
1212
{
1313

14+
class KpointMeshUniform;
15+
class PhaseFactorStorage;
16+
1417
class DerivativeIFC: protected Pointers
1518
{
1619
public:
@@ -52,6 +55,32 @@ class DerivativeIFC: protected Pointers
5255
int ixyz12,
5356
int ixyz21,
5457
int ixyz22) const;
58+
59+
void compute_del_v1_del_umn(std::complex<double> **del_v1_del_umn,
60+
const std::complex<double> *const *const *const evec_harmonic) const;
61+
62+
void compute_del2_v1_del_umn2(std::complex<double> **del2_v1_del_umn2,
63+
const std::complex<double> *const *const *const evec_harmonic) const;
64+
65+
void compute_del3_v1_del_umn3(std::complex<double> **del3_v1_del_umn3,
66+
const std::complex<double> *const *const *const evec_harmonic) const;
67+
68+
void compute_del_v2_del_umn(std::complex<double> ***del_v2_del_umn,
69+
const std::complex<double> *const *const *const evec_harmonic,
70+
unsigned int nk,
71+
double **xk_in) const;
72+
73+
void compute_del2_v2_del_umn2(std::complex<double> ***del2_v2_del_umn2,
74+
const std::complex<double> *const *const *const evec_harmonic,
75+
unsigned int nk,
76+
double **xk_in) const;
77+
78+
void compute_del_v3_del_umn(std::complex<double> ****del_v3_del_umn,
79+
double **omega2_harmonic,
80+
const std::complex<double> *const *const *const evec_harmonic,
81+
const KpointMeshUniform *kmesh_coarse_in,
82+
const KpointMeshUniform *kmesh_dense_in,
83+
const PhaseFactorStorage *phase_storage_in) const;
5584
};
5685

5786
} // namespace PHON_NS

0 commit comments

Comments
 (0)