1use crate::error::{Result, TbError};
115use crate::kpoints::{gen_kmesh, gen_krange};
116use crate::math::*;
117use crate::phy_const::mu_B;
118use crate::{Gauge, Model};
119use ndarray::linalg::kron;
120use ndarray::prelude::*;
121use ndarray::*;
122use ndarray_linalg::conjugate;
123use ndarray_linalg::*;
124use num_complex::Complex;
125use rayon::prelude::*;
126use std::f64::consts::PI;
127use std::ops::AddAssign;
128use std::ops::MulAssign;
129
130#[inline(always)]
147pub fn adapted_integrate_quick(
148 f0: &dyn Fn(&Array1<f64>) -> f64,
149 k_range: &Array2<f64>,
150 re_err: f64,
151 ab_err: f64,
152) -> f64 {
153 let dim = k_range.len_of(Axis(0));
154 match dim {
155 1 => {
156 let mut use_range = vec![(k_range.clone(), re_err, ab_err)];
158 let mut result = 0.0;
159 while let Some((k_range, re_err, ab_err)) = use_range.pop() {
160 let kvec_l: Array1<f64> = arr1(&[k_range[[0, 0]]]);
161 let kvec_r: Array1<f64> = arr1(&[k_range[[0, 1]]]);
162 let kvec_m: Array1<f64> = arr1(&[(k_range[[0, 1]] + k_range[[0, 0]]) / 2.0]);
163 let dk: f64 = k_range[[0, 1]] - k_range[[0, 0]];
164 let y_l: f64 = f0(&kvec_l);
165 let y_r: f64 = f0(&kvec_r);
166 let y_m: f64 = f0(&kvec_m);
167 let all: f64 = (y_l + y_r) * dk / 2.0;
168 let all_1 = (y_l + y_m) * dk / 4.0;
169 let all_2 = (y_r + y_m) * dk / 4.0;
170 let err = all_1 + all_2 - all;
171 let abs_err = if ab_err > all * re_err {
172 ab_err
173 } else {
174 all * re_err
175 };
176 if err < abs_err {
177 result += all_1 + all_2;
178 } else {
179 let k_range_l = arr2(&[[kvec_l[[0]], kvec_m[[0]]]]);
180 let k_range_r = arr2(&[[kvec_m[[0]], kvec_r[[0]]]]);
181 use_range.push((k_range_l, re_err, ab_err / 2.0));
182 use_range.push((k_range_r, re_err, ab_err / 2.0));
183 }
184 }
185 return result;
186 }
187 2 => {
188 let area_1: Array2<f64> = arr2(&[
190 [k_range.row(0)[0], k_range.row(1)[0]],
191 [k_range.row(0)[1], k_range.row(1)[0]],
192 [k_range.row(0)[0], k_range.row(1)[1]],
193 ]); let area_2: Array2<f64> = arr2(&[
195 [k_range.row(0)[1], k_range.row(1)[1]],
196 [k_range.row(0)[1], k_range.row(1)[0]],
197 [k_range.row(0)[0], k_range.row(1)[1]],
198 ]); #[inline(always)]
200 fn adapt_integrate_triangle(
201 f0: &dyn Fn(&Array1<f64>) -> f64,
202 kvec: &Array2<f64>,
203 re_err: f64,
204 ab_err: f64,
205 s1: f64,
206 s2: f64,
207 s3: f64,
208 S: f64,
209 ) -> f64 {
210 let mut result = 0.0;
212 let mut use_kvec = vec![(kvec.clone(), re_err, ab_err, s1, s2, s3, S)];
213 while let Some((kvec, re_err, ab_err, s1, s2, s3, S)) = use_kvec.pop() {
214 let kvec_m = kvec.mean_axis(Axis(0)).unwrap();
215 let sm: f64 = f0(&kvec_m.to_owned());
216
217 let mut new_kvec = kvec.to_owned();
218 new_kvec.push_row(kvec_m.view());
219 let kvec_1 = new_kvec.select(Axis(0), &[0, 1, 3]);
220 let kvec_2 = new_kvec.select(Axis(0), &[0, 3, 2]);
221 let kvec_3 = new_kvec.select(Axis(0), &[3, 1, 2]);
222 let all: f64 = (s1 + s2 + s3) * S / 6.0;
223 let all_new: f64 = all / 3.0 * 2.0 + sm * S / 6.0;
224 let abs_err: f64 = if ab_err > all * re_err {
225 ab_err
226 } else {
227 all * re_err
228 };
229 if (all_new - all).abs() > abs_err && S > 1e-8 {
230 let S1 = S / 3.0;
231 use_kvec.push((kvec_1, re_err, ab_err / 3.0, s1, s2, sm, S1));
232 use_kvec.push((kvec_2, re_err, ab_err / 3.0, s1, sm, s3, S1));
233 use_kvec.push((kvec_3, re_err, ab_err / 3.0, sm, s2, s3, S1));
234 } else {
235 result += all_new;
236 }
237 }
238 result
239 }
240 let S = (k_range[[0, 1]] - k_range[[0, 0]]) * (k_range[[1, 1]] - k_range[[1, 0]]);
241 let s1 = f0(&arr1(&[k_range.row(0)[0], k_range.row(1)[0]]));
242 let s2 = f0(&arr1(&[k_range.row(0)[1], k_range.row(1)[0]]));
243 let s3 = f0(&arr1(&[k_range.row(0)[0], k_range.row(1)[1]]));
244 let s4 = f0(&arr1(&[k_range.row(0)[1], k_range.row(1)[1]]));
245 let all_1 = adapt_integrate_triangle(f0, &area_1, re_err, ab_err / 2.0, s1, s2, s3, S);
246 let all_2 = adapt_integrate_triangle(f0, &area_2, re_err, ab_err / 2.0, s4, s2, s3, S);
247 return all_1 + all_2;
248 }
249 3 => {
250 #[inline(always)]
252 fn adapt_integrate_tetrahedron(
253 f0: &dyn Fn(&Array1<f64>) -> f64,
254 kvec: &Array2<f64>,
255 re_err: f64,
256 ab_err: f64,
257 s1: f64,
258 s2: f64,
259 s3: f64,
260 s4: f64,
261 S: f64,
262 ) -> f64 {
263 let mut result = 0.0;
265 let mut use_kvec = vec![(kvec.clone(), re_err, ab_err, s1, s2, s3, s4, S)];
266 while let Some((kvec, re_err, ab_err, s1, s2, s3, s4, S)) = use_kvec.pop() {
267 let kvec_m = kvec.mean_axis(Axis(0)).unwrap();
268 let sm = f0(&kvec_m.to_owned());
269 let mut new_kvec = kvec.to_owned();
270 new_kvec.push_row(kvec_m.view());
271 let kvec_1 = new_kvec.select(Axis(0), &[0, 1, 2, 4]);
272 let kvec_2 = new_kvec.select(Axis(0), &[0, 1, 4, 3]);
273 let kvec_3 = new_kvec.select(Axis(0), &[0, 4, 2, 3]);
274 let kvec_4 = new_kvec.select(Axis(0), &[4, 1, 2, 3]);
275
276 let all = (s1 + s2 + s3 + s4) * S / 24.0;
277 let all_new = all * 0.75 + sm * S / 24.0;
278 let S1 = S * 0.25;
279 let abs_err = if ab_err > all * re_err {
280 ab_err
281 } else {
282 all * re_err
283 };
284 if (all_new - all).abs() > abs_err && S > 1e-9 {
285 use_kvec.push((kvec_1, re_err, ab_err * 0.25, s1, s2, s3, sm, S1));
286 use_kvec.push((kvec_2, re_err, ab_err * 0.25, s1, s2, sm, s4, S1));
287 use_kvec.push((kvec_3, re_err, ab_err * 0.25, s1, sm, s3, s4, S1));
288 use_kvec.push((kvec_4, re_err, ab_err * 0.25, sm, s2, s3, s4, S1));
289 } else {
290 result += all_new;
291 }
292 }
293 result
294 }
295
296 let k_points: Array2<f64> = arr2(&[
297 [k_range.row(0)[0], k_range.row(1)[0], k_range.row(2)[0]],
298 [k_range.row(0)[1], k_range.row(1)[0], k_range.row(2)[0]],
299 [k_range.row(0)[0], k_range.row(1)[1], k_range.row(2)[0]],
300 [k_range.row(0)[1], k_range.row(1)[1], k_range.row(2)[0]],
301 [k_range.row(0)[0], k_range.row(1)[0], k_range.row(2)[1]],
302 [k_range.row(0)[1], k_range.row(1)[0], k_range.row(2)[1]],
303 [k_range.row(0)[0], k_range.row(1)[1], k_range.row(2)[1]],
304 [k_range.row(0)[1], k_range.row(1)[1], k_range.row(2)[1]],
305 ]); let area_1 = k_points.select(Axis(0), &[0, 1, 2, 5]);
308 let area_2 = k_points.select(Axis(0), &[0, 2, 4, 5]);
309 let area_3 = k_points.select(Axis(0), &[6, 2, 4, 5]);
310 let area_4 = k_points.select(Axis(0), &[1, 2, 3, 5]);
311 let area_5 = k_points.select(Axis(0), &[7, 2, 3, 5]);
312 let area_6 = k_points.select(Axis(0), &[7, 2, 6, 5]);
313 let s0 = f0(&k_points.row(0).to_owned());
314 let s1 = f0(&k_points.row(1).to_owned());
315 let s2 = f0(&k_points.row(2).to_owned());
316 let s3 = f0(&k_points.row(3).to_owned());
317 let s4 = f0(&k_points.row(4).to_owned());
318 let s5 = f0(&k_points.row(5).to_owned());
319 let s6 = f0(&k_points.row(6).to_owned());
320 let s7 = f0(&k_points.row(7).to_owned());
321 let V = (k_range[[0, 1]] - k_range[[0, 0]])
322 * (k_range[[1, 1]] - k_range[[1, 0]])
323 * (k_range[[2, 1]] - k_range[[2, 0]]);
324 let all_1 =
325 adapt_integrate_tetrahedron(f0, &area_1, re_err, ab_err / 6.0, s0, s1, s2, s5, V);
326 let all_2 =
327 adapt_integrate_tetrahedron(f0, &area_2, re_err, ab_err / 6.0, s0, s2, s4, s5, V);
328 let all_3 =
329 adapt_integrate_tetrahedron(f0, &area_3, re_err, ab_err / 6.0, s6, s2, s4, s5, V);
330 let all_4 =
331 adapt_integrate_tetrahedron(f0, &area_4, re_err, ab_err / 6.0, s1, s2, s3, s5, V);
332 let all_5 =
333 adapt_integrate_tetrahedron(f0, &area_5, re_err, ab_err / 6.0, s7, s2, s3, s5, V);
334 let all_6 =
335 adapt_integrate_tetrahedron(f0, &area_5, re_err, ab_err / 6.0, s7, s2, s6, s5, V);
336 return all_1 + all_2 + all_3 + all_4 + all_5 + all_6;
337 }
338 _ => {
339 panic!(
340 "wrong, the row_dim if k_range must be 1,2 or 3, but you's give {}",
341 dim
342 );
343 }
344 }
345}
346
347#[allow(non_snake_case)]
348impl Model {
349 #[allow(non_snake_case)]
354 #[inline(always)]
355 pub fn berry_curvature_n_onek<S: Data<Elem = f64>>(
356 &self,
357 k_vec: &ArrayBase<S, Ix1>,
358 dir_1: &Array1<f64>,
359 dir_2: &Array1<f64>,
360 spin: usize,
361 eta: f64,
362 ) -> (Array1<f64>, Array1<f64>) {
363 let li: Complex<f64> = 1.0 * Complex::i();
364 let (mut v, hamk): (Array3<Complex<f64>>, Array2<Complex<f64>>) =
366 self.gen_v(&k_vec, Gauge::Atom); let (band, evec) = if let Ok((eigvals, eigvecs)) = hamk.eigh(UPLO::Lower) {
368 (eigvals, eigvecs)
369 } else {
370 todo!()
371 };
372 let mut J = v.view();
373 let (J, v) = if self.spin {
374 let J = match spin {
375 0 => {
376 let J = J
377 .outer_iter()
378 .zip(dir_1.iter())
379 .fold(Array2::zeros((self.nsta(), self.nsta())), |acc, (x, d)| {
380 acc + &x * (*d + 0.0 * li)
381 });
382 J
383 }
384 1 => {
385 let pauli = arr2(&[
386 [0.0 + 0.0 * li, 1.0 + 0.0 * li],
387 [1.0 + 0.0 * li, 0.0 + 0.0 * li],
388 ]) / 2.0;
389 let mut X: Array2<Complex<f64>> = Array2::eye(self.nsta());
390 X = kron(&pauli, &Array2::eye(self.norb()));
391 let J = J
392 .outer_iter()
393 .zip(dir_1.iter())
394 .fold(Array2::zeros((self.nsta(), self.nsta())), |acc, (x, d)| {
395 acc + &anti_comm(&X, &x) * (*d * 0.5 + 0.0 * li)
396 });
397 J
398 }
399 2 => {
400 let pauli = arr2(&[
401 [0.0 + 0.0 * li, 0.0 - 1.0 * li],
402 [0.0 + 1.0 * li, 0.0 + 0.0 * li],
403 ]) / 2.0;
404 let mut X: Array2<Complex<f64>> = Array2::eye(self.nsta());
405 X = kron(&pauli, &Array2::eye(self.norb()));
406 let J = J
407 .outer_iter()
408 .zip(dir_1.iter())
409 .fold(Array2::zeros((self.nsta(), self.nsta())), |acc, (x, d)| {
410 acc + &anti_comm(&X, &x) * (*d * 0.5 + 0.0 * li)
411 });
412 J
413 }
414 3 => {
415 let pauli = arr2(&[
416 [1.0 + 0.0 * li, 0.0 + 0.0 * li],
417 [0.0 + 0.0 * li, -1.0 + 0.0 * li],
418 ]) / 2.0;
419 let mut X: Array2<Complex<f64>> = Array2::eye(self.nsta());
420 X = kron(&pauli, &Array2::eye(self.norb()));
421 let J = J
422 .outer_iter()
423 .zip(dir_1.iter())
424 .fold(Array2::zeros((self.nsta(), self.nsta())), |acc, (x, d)| {
425 acc + &anti_comm(&X, &x) * (*d * 0.5 + 0.0 * li)
426 });
427 J
428 }
429 _ => panic!("Wrong, spin should be 0, 1, 2, 3, but you input {}", spin),
430 };
431 let v = v
432 .outer_iter()
433 .zip(dir_2.iter())
434 .fold(Array2::zeros((self.nsta(), self.nsta())), |acc, (x, d)| {
435 acc + &x * (*d + 0.0 * li)
436 });
437 (J, v)
438 } else {
439 if spin != 0 {
440 println!("Warning, the model haven't got spin, so the spin input will be ignord");
441 }
442
443 let J = J
444 .outer_iter()
445 .zip(dir_1.iter())
446 .fold(Array2::zeros((self.nsta(), self.nsta())), |acc, (x, d)| {
447 acc + &x * (*d + 0.0 * li)
448 });
449 let v = v
450 .outer_iter()
451 .zip(dir_2.iter())
452 .fold(Array2::zeros((self.nsta(), self.nsta())), |acc, (x, d)| {
453 acc + &x * (*d + 0.0 * li)
454 });
455 (J, v)
456 };
457
458 let evec_conj = evec.t();
459 let evec = evec.mapv(|x| x.conj());
460 let A1 = J.dot(&evec);
461 let A1 = &evec_conj.dot(&A1);
462 let A2 = v.dot(&evec);
463 let A2 = evec_conj.dot(&A2);
464 let A2 = A2.reversed_axes();
465 let AA = A1 * A2;
466 let Complex { re, im } = AA.view().split_complex();
467 let im = im.mapv(|x| -2.0 * x);
468 assert_eq!(
469 band.len(),
470 self.nsta(),
471 "this is strange for band's length is not equal to self.nsta()"
472 );
473 let mut UU = Array2::<f64>::zeros((self.nsta(), self.nsta()));
474 for i in 0..self.nsta() {
475 for j in 0..self.nsta() {
476 let a = band[[i]] - band[[j]];
477 UU[[i, j]] = 1.0 / (a.powi(2) + eta.powi(2));
479 }
487 }
488 let omega_n = im
489 .outer_iter()
490 .zip(UU.outer_iter())
491 .map(|(a, b)| a.dot(&b))
492 .collect();
493 let omega_n = Array1::from_vec(omega_n);
494 (omega_n, band)
495 }
496
497 #[allow(non_snake_case)]
498 pub fn berry_curvature_onek<S: Data<Elem = f64>>(
499 &self,
500 k_vec: &ArrayBase<S, Ix1>,
501 dir_1: &Array1<f64>,
502 dir_2: &Array1<f64>,
503 mu: f64,
504 T: f64,
505 spin: usize,
506 eta: f64,
507 ) -> f64 {
508 let (omega_n, band) = self.berry_curvature_n_onek(&k_vec, &dir_1, &dir_2, spin, eta);
516 let mut omega: f64 = 0.0;
517 let fermi_dirac = if T == 0.0 {
518 band.mapv(|x| if x > mu { 0.0 } else { 1.0 })
519 } else {
520 let beta = 1.0 / T / 8.617e-5;
521 band.mapv(|x| ((beta * (x - mu)).exp() + 1.0).recip())
522 };
523 let omega = omega_n.dot(&fermi_dirac);
524 omega
525 }
526 #[allow(non_snake_case)]
527 pub fn berry_curvature<S: Data<Elem = f64>>(
528 &self,
529 k_vec: &ArrayBase<S, Ix2>,
530 dir_1: &Array1<f64>,
531 dir_2: &Array1<f64>,
532 mu: f64,
533 T: f64,
534 spin: usize,
535 eta: f64,
536 ) -> Array1<f64> {
537 if dir_1.len() != self.dim_r() || dir_2.len() != self.dim_r() {
540 panic!(
541 "Wrong, the dir_1 or dir_2 you input has wrong length, it must equal to dim_r={}, but you input {},{}",
542 self.dim_r(),
543 dir_1.len(),
544 dir_2.len()
545 )
546 }
547 let nk = k_vec.len_of(Axis(0));
548 let omega: Vec<f64> = k_vec
549 .axis_iter(Axis(0))
550 .into_par_iter()
551 .map(|x| {
552 let omega_one =
553 self.berry_curvature_onek(&x.to_owned(), &dir_1, &dir_2, mu, T, spin, eta);
554 omega_one
555 })
556 .collect();
557 let omega = arr1(&omega);
558 omega
559 }
560 #[allow(non_snake_case)]
562 pub fn Hall_conductivity(
563 &self,
564 k_mesh: &Array1<usize>,
565 dir_1: &Array1<f64>,
566 dir_2: &Array1<f64>,
567 mu: f64,
568 T: f64,
569 spin: usize,
570 eta: f64,
571 ) -> Result<f64> {
572 let kvec: Array2<f64> = gen_kmesh(&k_mesh)?;
576 let nk: usize = kvec.len_of(Axis(0));
577 let omega = self.berry_curvature(&kvec, &dir_1, &dir_2, mu, T, spin, eta);
578 let conductivity: f64 = omega.sum() / (nk as f64) / self.lat.det().unwrap();
582 Ok(conductivity)
583 }
584 #[allow(non_snake_case)]
585 pub fn Hall_conductivity_adapted(
587 &self,
588 k_mesh: &Array1<usize>,
589 dir_1: &Array1<f64>,
590 dir_2: &Array1<f64>,
591 mu: f64,
592 T: f64,
593 spin: usize,
594 eta: f64,
595 re_err: f64,
596 ab_err: f64,
597 ) -> Result<f64> {
598 let mut k_range = gen_krange(k_mesh)?; let n_range = k_range.len_of(Axis(0));
600 let ab_err = ab_err / (n_range as f64);
601 let use_fn =
602 |k0: &Array1<f64>| self.berry_curvature_onek(k0, &dir_1, &dir_2, mu, T, spin, eta);
603 let inte = |k_range| adapted_integrate_quick(&use_fn, &k_range, re_err, ab_err);
604 let omega: Vec<f64> = k_range
605 .axis_iter(Axis(0))
606 .into_par_iter()
607 .map(|x| inte(x.to_owned()))
608 .collect();
609 let omega: Array1<f64> = arr1(&omega);
610 let conductivity: f64 = omega.sum() / self.lat.det().unwrap();
611 Ok(conductivity)
612 }
613 pub fn Hall_conductivity_mu(
615 &self,
616 k_mesh: &Array1<usize>,
617 dir_1: &Array1<f64>,
618 dir_2: &Array1<f64>,
619 mu: &Array1<f64>,
620 T: f64,
621 spin: usize,
622 eta: f64,
623 ) -> Result<Array1<f64>> {
624 let kvec: Array2<f64> = gen_kmesh(&k_mesh)?;
625 let nk: usize = kvec.len_of(Axis(0));
626 let (omega_n, band): (Vec<_>, Vec<_>) = kvec
627 .axis_iter(Axis(0))
628 .into_par_iter()
629 .map(|x| {
630 let (omega_n, band) =
631 self.berry_curvature_n_onek(&x.to_owned(), &dir_1, &dir_2, spin, eta);
632 (omega_n, band)
633 })
634 .collect();
635 let omega_n = Array2::<f64>::from_shape_vec(
636 (nk, self.nsta()),
637 omega_n.into_iter().flatten().collect(),
638 )
639 .unwrap();
640 let band =
641 Array2::<f64>::from_shape_vec((nk, self.nsta()), band.into_iter().flatten().collect())
642 .unwrap();
643 let n_mu: usize = mu.len();
644 let conductivity = if T == 0.0 {
645 let conductivity_new: Vec<f64> = mu
646 .into_par_iter()
647 .map(|x| {
648 let mut omega = Array1::<f64>::zeros(nk);
649 for k in 0..nk {
650 for i in 0..self.nsta() {
651 omega[[k]] += if band[[k, i]] > *x {
652 0.0
653 } else {
654 omega_n[[k, i]]
655 };
656 }
657 }
658 omega.sum() / self.lat.det().unwrap() / (nk as f64)
659 })
660 .collect();
661 Array1::<f64>::from_vec(conductivity_new)
662 } else {
663 let beta = 1.0 / (T * 8.617e-5);
664 let conductivity_new: Vec<f64> = mu
665 .into_par_iter()
666 .map(|x| {
667 let fermi_dirac = band.mapv(|x0| 1.0 / ((beta * (x0 - x)).exp() + 1.0));
668 let omega: Vec<f64> = omega_n
669 .axis_iter(Axis(0))
670 .zip(fermi_dirac.axis_iter(Axis(0)))
671 .map(|(a, b)| (&a * &b).sum())
672 .collect();
673 let omega: Array1<f64> = arr1(&omega);
674 omega.sum() / self.lat.det().unwrap() / (nk as f64)
675 })
676 .collect();
677 Array1::<f64>::from_vec(conductivity_new)
678 };
679 Ok(conductivity)
680 }
681
682 pub fn berry_curvature_dipole_n_onek(
683 &self,
684 k_vec: &Array1<f64>,
685 dir_1: &Array1<f64>,
686 dir_2: &Array1<f64>,
687 dir_3: &Array1<f64>,
688 og: f64,
689 spin: usize,
690 eta: f64,
691 ) -> (Array1<f64>, Array1<f64>) {
692 let li: Complex<f64> = 1.0 * Complex::i();
705 let (mut v, hamk): (Array3<Complex<f64>>, Array2<Complex<f64>>) =
707 self.gen_v(&k_vec, Gauge::Atom); let mut J: Array3<Complex<f64>> = v.clone();
709 let mut v0 = Array2::<Complex<f64>>::zeros((self.nsta(), self.nsta())); for r in 0..self.dim_r() {
711 v0 = v0 + v.slice(s![r, .., ..]).to_owned() * dir_3[[r]];
712 }
713 if self.spin {
714 let mut X: Array2<Complex<f64>> = Array2::eye(self.nsta());
715 let pauli: Array2<Complex<f64>> = match spin {
716 0 => arr2(&[
717 [1.0 + 0.0 * li, 0.0 + 0.0 * li],
718 [0.0 + 0.0 * li, 1.0 + 0.0 * li],
719 ]),
720 1 => {
721 arr2(&[
722 [0.0 + 0.0 * li, 1.0 + 0.0 * li],
723 [1.0 + 0.0 * li, 0.0 + 0.0 * li],
724 ]) / 2.0
725 }
726 2 => {
727 arr2(&[
728 [0.0 + 0.0 * li, 0.0 - 1.0 * li],
729 [0.0 + 1.0 * li, 0.0 + 0.0 * li],
730 ]) / 2.0
731 }
732 3 => {
733 arr2(&[
734 [1.0 + 0.0 * li, 0.0 + 0.0 * li],
735 [0.0 + 0.0 * li, -1.0 + 0.0 * li],
736 ]) / 2.0
737 }
738 _ => panic!("Wrong, spin should be 0, 1, 2, 3, but you input {}", spin),
739 };
740 X = kron(&pauli, &Array2::eye(self.norb()));
741 for i in 0..self.dim_r() {
742 let j = J.slice(s![i, .., ..]).to_owned();
743 let j = anti_comm(&X, &j) / 2.0; J.slice_mut(s![i, .., ..]).assign(&(j * dir_1[[i]]));
745 v.slice_mut(s![i, .., ..])
746 .mul_assign(Complex::new(dir_2[[i]], 0.0));
747 }
748 } else {
749 if spin != 0 {
750 println!("Warning, the model haven't got spin, so the spin input will be ignord");
751 }
752 for i in 0..self.dim_r() {
753 J.slice_mut(s![i, .., ..])
754 .mul_assign(Complex::new(dir_1[[i]], 0.0));
755 v.slice_mut(s![i, .., ..])
756 .mul_assign(Complex::new(dir_2[[i]], 0.0));
757 }
758 };
759
760 let J: Array2<Complex<f64>> = J.sum_axis(Axis(0));
761 let v: Array2<Complex<f64>> = v.sum_axis(Axis(0));
762
763 let (band, evec) = if let Ok((eigvals, eigvecs)) = hamk.eigh(UPLO::Lower) {
764 (eigvals, eigvecs)
765 } else {
766 todo!()
767 };
768 let evec_conj = evec.t();
769 let evec = evec.mapv(|x| x.conj());
770
771 let v0 = v0.dot(&evec.t());
772 let v0 = &evec_conj.dot(&v0);
773 let partial_ve = v0.diag().map(|x| x.re);
774 let A1 = J.dot(&evec.t());
775 let A1 = &evec_conj.dot(&A1);
776 let A2 = v.dot(&evec.t());
777 let A2 = &evec_conj.dot(&A2);
778 let mut U0 = Array2::<Complex<f64>>::zeros((self.nsta(), self.nsta()));
779 for i in 0..self.nsta() {
780 for j in 0..self.nsta() {
781 if i != j {
782 U0[[i, j]] = 1.0 / ((band[[i]] - band[[j]]).powi(2) - (og + li * eta).powi(2));
783 } else {
784 U0[[i, j]] = Complex::new(0.0, 0.0);
785 }
786 }
787 }
788 let mut omega_n = Array1::<f64>::zeros(self.nsta());
790 let A1 = A1 * U0;
791 for i in 0..self.nsta() {
792 omega_n[[i]] = -2.0 * A1.slice(s![i, ..]).dot(&A2.slice(s![.., i])).im;
793 }
794
795 let omega_n: Array1<f64> = omega_n * partial_ve;
797 (omega_n, band) }
799 pub fn berry_curvature_dipole_n(
800 &self,
801 k_vec: &Array2<f64>,
802 dir_1: &Array1<f64>,
803 dir_2: &Array1<f64>,
804 dir_3: &Array1<f64>,
805 og: f64,
806 spin: usize,
807 eta: f64,
808 ) -> (Array2<f64>, Array2<f64>) {
809 if dir_1.len() != self.dim_r() || dir_2.len() != self.dim_r() || dir_3.len() != self.dim_r()
814 {
815 panic!(
816 "Wrong, the dir_1 or dir_2 you input has wrong length, it must equal to dim_r={}, but you input {},{}",
817 self.dim_r(),
818 dir_1.len(),
819 dir_2.len()
820 )
821 }
822 let nk = k_vec.len_of(Axis(0));
823 let (omega, band): (Vec<_>, Vec<_>) = k_vec
824 .axis_iter(Axis(0))
825 .into_par_iter()
826 .map(|x| {
827 let (omega_one, band) = self.berry_curvature_dipole_n_onek(
828 &x.to_owned(),
829 &dir_1,
830 &dir_2,
831 &dir_3,
832 og,
833 spin,
834 eta,
835 );
836 (omega_one, band)
837 })
838 .collect();
839 let omega =
840 Array2::<f64>::from_shape_vec((nk, self.nsta()), omega.into_iter().flatten().collect())
841 .unwrap();
842 let band =
843 Array2::<f64>::from_shape_vec((nk, self.nsta()), band.into_iter().flatten().collect())
844 .unwrap();
845 (omega, band)
846 }
847 pub fn Nonlinear_Hall_conductivity_Extrinsic(
848 &self,
849 k_mesh: &Array1<usize>,
850 dir_1: &Array1<f64>,
851 dir_2: &Array1<f64>,
852 dir_3: &Array1<f64>,
853 mu: &Array1<f64>,
854 T: f64,
855 og: f64,
856 spin: usize,
857 eta: f64,
858 ) -> Result<Array1<f64>> {
859 if dir_1.len() != self.dim_r() || dir_2.len() != self.dim_r() || dir_3.len() != self.dim_r()
871 {
872 panic!(
873 "Wrong, the dir_1 or dir_2 you input has wrong length, it must equal to dim_r={}, but you input {},{}",
874 self.dim_r(),
875 dir_1.len(),
876 dir_2.len()
877 )
878 }
879 let kvec: Array2<f64> = gen_kmesh(&k_mesh)?;
880 let nk: usize = kvec.len_of(Axis(0));
881 let (omega, band) =
883 self.berry_curvature_dipole_n(&kvec, &dir_1, &dir_2, &dir_3, og, spin, eta);
884 let omega = omega.into_raw_vec();
885 let band = band.into_raw_vec();
886 let n_e = mu.len();
887 let mut conductivity = Array1::<f64>::zeros(n_e);
888 if T != 0.0 {
889 let beta = 1.0 / T / (8.617e-5);
890 let use_iter = band.iter().zip(omega.iter()).par_bridge();
891 conductivity = use_iter
892 .fold(
893 || Array1::<f64>::zeros(n_e),
894 |acc, (energy, omega0)| {
895 let f = 1.0 / (beta * (mu - *energy)).mapv(|x| x.exp() + 1.0);
896 acc + &f * (1.0 - &f) * beta * *omega0
897 },
898 )
899 .reduce(|| Array1::<f64>::zeros(n_e), |acc, x| acc + x);
900 conductivity = conductivity.clone() / (nk as f64) / self.lat.det().unwrap();
901 } else {
902 panic!("When T=0, the algorithm have not been writed, please wait for next version");
906 }
907 Ok(conductivity)
908 }
909
910 pub fn berry_connection_dipole_onek(
911 &self,
912 k_vec: &Array1<f64>,
913 dir_1: &Array1<f64>,
914 dir_2: &Array1<f64>,
915 dir_3: &Array1<f64>,
916 spin: usize,
917 ) -> (Array1<f64>, Array1<f64>, Option<Array1<f64>>) {
918 let (mut v, hamk): (Array3<Complex<f64>>, Array2<Complex<f64>>) =
924 self.gen_v(&k_vec, Gauge::Atom); let mut J = v.clone();
926 let (band, evec) = if let Ok((eigvals, eigvecs)) = hamk.eigh(UPLO::Lower) {
928 (eigvals, eigvecs)
929 } else {
930 todo!()
931 };
932 let evec_conj = evec.t();
933 let evec = evec.mapv(|x| x.conj());
934 for i in 0..self.dim_r() {
935 let v_s = v.slice(s![i, .., ..]).to_owned();
936 let v_s = evec_conj
937 .clone()
938 .dot(&(v_s.dot(&evec.clone().reversed_axes()))); v.slice_mut(s![i, .., ..]).assign(&v_s); }
941 let mut v_1 = Array2::<Complex<f64>>::zeros((self.nsta(), self.nsta())); let mut v_2 = Array2::<Complex<f64>>::zeros((self.nsta(), self.nsta()));
944 let mut v_3 = Array2::<Complex<f64>>::zeros((self.nsta(), self.nsta()));
945 for i in 0..self.dim_r() {
946 v_1 = v_1.clone() + v.slice(s![i, .., ..]).to_owned() * Complex::new(dir_1[[i]], 0.0);
947 v_2 = v_2.clone() + v.slice(s![i, .., ..]).to_owned() * Complex::new(dir_2[[i]], 0.0);
948 v_3 = v_3.clone() + v.slice(s![i, .., ..]).to_owned() * Complex::new(dir_3[[i]], 0.0);
949 }
950 let mut U0 = Array2::<f64>::zeros((self.nsta(), self.nsta()));
952 for i in 0..self.nsta() {
953 for j in 0..self.nsta() {
954 if (band[[i]] - band[[j]]).abs() < 1e-5 {
955 U0[[i, j]] = 0.0;
956 } else {
957 U0[[i, j]] = 1.0 / (band[[i]] - band[[j]]);
958 }
959 }
960 }
961 let partial_ve_1 = v_1.diag().map(|x| x.re);
967 let partial_ve_2 = v_2.diag().map(|x| x.re);
968 let partial_ve_3 = v_3.diag().map(|x| x.re);
969
970 if self.spin {
972 let mut S: Array2<Complex<f64>> = Array2::eye(self.nsta());
974 let li = Complex::<f64>::new(0.0, 1.0);
975 let pauli: Array2<Complex<f64>> = match spin {
976 0 => Array2::<Complex<f64>>::eye(2),
977 1 => {
978 arr2(&[
979 [0.0 + 0.0 * li, 1.0 + 0.0 * li],
980 [1.0 + 0.0 * li, 0.0 + 0.0 * li],
981 ]) / 2.0
982 }
983 2 => {
984 arr2(&[
985 [0.0 + 0.0 * li, 0.0 - 1.0 * li],
986 [0.0 + 1.0 * li, 0.0 + 0.0 * li],
987 ]) / 2.0
988 }
989 3 => {
990 arr2(&[
991 [1.0 + 0.0 * li, 0.0 + 0.0 * li],
992 [0.0 + 0.0 * li, -1.0 + 0.0 * li],
993 ]) / 2.0
994 }
995 _ => panic!("Wrong, spin should be 0, 1, 2, 3, but you input {}", spin),
996 };
997 let X = kron(&pauli, &Array2::eye(self.norb()));
998 let mut S = Array3::<Complex<f64>>::zeros((self.dim_r(), self.nsta(), self.nsta()));
999 for i in 0..self.dim_r() {
1000 let v0 = J.slice(s![i, .., ..]).to_owned();
1001 let v0 = anti_comm(&X, &v0) / 2.0;
1002 let v0 = evec_conj
1003 .clone()
1004 .dot(&(v0.dot(&evec.clone().reversed_axes()))); S.slice_mut(s![i, .., ..]).assign(&v0);
1006 }
1007 let mut s_1 = Array2::<Complex<f64>>::zeros((self.nsta(), self.nsta())); let mut s_2 = Array2::<Complex<f64>>::zeros((self.nsta(), self.nsta()));
1009 let mut s_3 = Array2::<Complex<f64>>::zeros((self.nsta(), self.nsta()));
1010 for i in 0..self.dim_r() {
1011 s_1 =
1012 s_1.clone() + S.slice(s![i, .., ..]).to_owned() * Complex::new(dir_1[[i]], 0.0);
1013 s_2 =
1014 s_2.clone() + S.slice(s![i, .., ..]).to_owned() * Complex::new(dir_2[[i]], 0.0);
1015 s_3 =
1016 s_3.clone() + S.slice(s![i, .., ..]).to_owned() * Complex::new(dir_3[[i]], 0.0);
1017 }
1018 let G_23: Array1<f64> = {
1019 let A = &v_2 * (U0.map(|x| Complex::<f64>::new(x.powi(3), 0.0)));
1021 let mut G = Array1::<f64>::zeros(self.nsta());
1022 for i in 0..self.nsta() {
1023 G[[i]] = A.slice(s![i, ..]).dot(&v_3.slice(s![.., i])).re * 2.0
1024 }
1025 G
1026 };
1027 let G_13_h: Array1<f64> = {
1028 let A = &s_1 * (U0.map(|x| Complex::<f64>::new(x.powi(3), 0.0)));
1030 let mut G = Array1::<f64>::zeros(self.nsta());
1031 for i in 0..self.nsta() {
1032 G[[i]] = A.slice(s![i, ..]).dot(&v_3.slice(s![.., i])).re * 2.0
1033 }
1034 G
1035 };
1036 let partial_s_1 = s_1.clone().diag().map(|x| x.re);
1038 let partial_s_2 = s_2.clone().diag().map(|x| x.re);
1039 let partial_s_3 = s_3.clone().diag().map(|x| x.re);
1040 let mut partial_s = Array2::<f64>::zeros((self.dim_r(), self.nsta()));
1041 for r in 0..self.dim_r() {
1042 let s0 = S.slice(s![r, .., ..]).to_owned();
1043 partial_s
1044 .slice_mut(s![r, ..])
1045 .assign(&s0.diag().map(|x| x.re)); }
1047 let partial_G: Array1<f64> = {
1049 let mut A = Array1::<Complex<f64>>::zeros(self.nsta()); for i in 0..self.nsta() {
1051 for j in 0..self.nsta() {
1052 A[[i]] += 3.0
1053 * (partial_s_1[[i]] - partial_s_1[[j]])
1054 * v_2[[i, j]]
1055 * v_3[[j, i]]
1056 * U0[[i, j]].powi(4);
1057 }
1058 }
1059 let mut B = Array1::<Complex<f64>>::zeros(self.nsta()); for n in 0..self.nsta() {
1061 for n1 in 0..self.nsta() {
1062 for n2 in 0..self.nsta() {
1063 B[[n]] += s_1[[n, n2]]
1064 * (v_2[[n2, n1]] * v_3[[n1, n]] + v_3[[n2, n1]] * v_2[[n1, n]])
1065 * U0[[n, n1]].powi(3)
1066 * U0[[n, n2]];
1067 }
1068 }
1069 }
1070 let mut C = Array1::<Complex<f64>>::zeros(self.nsta()); for n in 0..self.nsta() {
1072 for n1 in 0..self.nsta() {
1073 for n2 in 0..self.nsta() {
1074 C[[n]] += s_1[[n1, n2]]
1075 * (v_2[[n2, n]] * v_3[[n, n1]] + v_3[[n2, n]] * v_2[[n, n1]])
1076 * U0[[n, n1]].powi(3)
1077 * U0[[n1, n2]];
1078 }
1079 }
1080 }
1081 2.0 * (A - B - C).map(|x| x.re)
1082 };
1083 return (
1086 (partial_s_1 * G_23 - partial_ve_2 * G_13_h),
1087 band,
1088 Some(partial_G),
1089 );
1090 } else {
1091 let G_23: Array1<f64> = {
1094 let A = &v_2 * (U0.map(|x| Complex::<f64>::new(x.powi(3), 0.0)));
1096 let mut G = Array1::<f64>::zeros(self.nsta());
1097 for i in 0..self.nsta() {
1098 G[[i]] = A.slice(s![i, ..]).dot(&v_3.slice(s![.., i])).re * 2.0
1099 }
1100 G
1101 };
1102 let G_13: Array1<f64> = {
1103 let A = &v_1 * (U0.map(|x| Complex::<f64>::new(x.powi(3), 0.0)));
1105 let mut G = Array1::<f64>::zeros(self.nsta());
1106 for i in 0..self.nsta() {
1107 G[[i]] = A.slice(s![i, ..]).dot(&v_3.slice(s![.., i])).re * 2.0
1108 }
1109 G
1110 };
1111 return (partial_ve_1 * G_23 - partial_ve_2 * G_13, band, None);
1112 }
1113 }
1114 pub fn berry_connection_dipole(
1115 &self,
1116 k_vec: &Array2<f64>,
1117 dir_1: &Array1<f64>,
1118 dir_2: &Array1<f64>,
1119 dir_3: &Array1<f64>,
1120 spin: usize,
1121 ) -> (Array2<f64>, Array2<f64>, Option<Array2<f64>>) {
1122 if dir_1.len() != self.dim_r() || dir_2.len() != self.dim_r() || dir_3.len() != self.dim_r()
1124 {
1125 panic!(
1126 "Wrong, the dir_1 or dir_2 you input has wrong length, it must equal to dim_r={}, but you input {},{}",
1127 self.dim_r(),
1128 dir_1.len(),
1129 dir_2.len()
1130 )
1131 }
1132 let nk = k_vec.len_of(Axis(0));
1133
1134 if self.spin {
1135 let ((omega, band), partial_G): ((Vec<_>, Vec<_>), Vec<_>) = k_vec
1136 .axis_iter(Axis(0))
1137 .into_par_iter()
1138 .map(|x| {
1139 let (omega_one, band, partial_G) = self.berry_connection_dipole_onek(
1140 &x.to_owned(),
1141 &dir_1,
1142 &dir_2,
1143 &dir_3,
1144 spin,
1145 );
1146 let partial_G = partial_G.unwrap();
1147 ((omega_one, band), partial_G)
1148 })
1149 .collect();
1150
1151 let omega = Array2::<f64>::from_shape_vec(
1152 (nk, self.nsta()),
1153 omega.into_iter().flatten().collect(),
1154 )
1155 .unwrap();
1156 let band = Array2::<f64>::from_shape_vec(
1157 (nk, self.nsta()),
1158 band.into_iter().flatten().collect(),
1159 )
1160 .unwrap();
1161 let partial_G = Array2::<f64>::from_shape_vec(
1162 (nk, self.nsta()),
1163 partial_G.into_iter().flatten().collect(),
1164 )
1165 .unwrap();
1166
1167 return (omega, band, Some(partial_G));
1168 } else {
1169 let (omega, band): (Vec<_>, Vec<_>) = k_vec
1170 .axis_iter(Axis(0))
1171 .into_par_iter()
1172 .map(|x| {
1173 let (omega_one, band, partial_G) = self.berry_connection_dipole_onek(
1174 &x.to_owned(),
1175 &dir_1,
1176 &dir_2,
1177 &dir_3,
1178 spin,
1179 );
1180 (omega_one, band)
1181 })
1182 .collect();
1183 let omega = Array2::<f64>::from_shape_vec(
1184 (nk, self.nsta()),
1185 omega.into_iter().flatten().collect(),
1186 )
1187 .unwrap();
1188 let band = Array2::<f64>::from_shape_vec(
1189 (nk, self.nsta()),
1190 band.into_iter().flatten().collect(),
1191 )
1192 .unwrap();
1193 return (omega, band, None);
1194 }
1195 }
1196 pub fn Nonlinear_Hall_conductivity_Intrinsic(
1197 &self,
1198 k_mesh: &Array1<usize>,
1199 dir_1: &Array1<f64>,
1200 dir_2: &Array1<f64>,
1201 dir_3: &Array1<f64>,
1202 mu: &Array1<f64>,
1203 T: f64,
1204 spin: usize,
1205 ) -> Result<Array1<f64>> {
1206 let kvec: Array2<f64> = gen_kmesh(&k_mesh)?;
1247 let nk: usize = kvec.len_of(Axis(0));
1248 let (omega, band, mut partial_G): (Array2<f64>, Array2<f64>, Option<Array2<f64>>) =
1249 self.berry_connection_dipole(&kvec, &dir_1, &dir_2, &dir_3, spin);
1250 let omega = omega.into_raw_vec();
1251 let omega = Array1::from(omega);
1252 let band0 = band.clone();
1253 let band = band.into_raw_vec();
1254 let band = Array1::from(band);
1255 let n_e = mu.len();
1256 let mut conductivity = Array1::<f64>::zeros(n_e);
1257 if T != 0.0 {
1258 let beta = 1.0 / T / 8.617e-5;
1259 let use_iter = band.iter().zip(omega.iter()).par_bridge();
1260 conductivity = use_iter
1261 .fold(
1262 || Array1::<f64>::zeros(n_e),
1263 |acc, (energy, omega0)| {
1264 let f = 1.0 / ((beta * (mu - *energy)).mapv(|x| x.exp() + 1.0));
1265 acc + &f * (1.0 - &f) * beta * *omega0
1266 },
1267 )
1268 .reduce(|| Array1::<f64>::zeros(n_e), |acc, x| acc + x);
1269 if self.spin {
1270 let partial_G = partial_G.unwrap();
1271 let conductivity_new: Vec<f64> = mu
1272 .into_par_iter()
1273 .map(|x| {
1274 let f = band0.map(|x0| 1.0 / ((beta * (x - x0)).exp() + 1.0));
1275 let mut omega = Array1::<f64>::zeros(nk);
1276 for i in 0..nk {
1277 omega[[i]] = (partial_G.row(i).to_owned() * f.row(i).to_owned()).sum();
1278 }
1279 omega.sum() / 2.0
1280 })
1281 .collect();
1282 let conductivity_new = Array1::<f64>::from_vec(conductivity_new);
1283 conductivity = conductivity.clone() + conductivity_new;
1284 }
1285 conductivity = conductivity.clone() / (nk as f64) / self.lat.det().unwrap();
1286 } else {
1287 panic!("the code can not support for T=0");
1291 }
1292 Ok(conductivity)
1293 }
1294}
1295impl Model {
1296 pub fn orbital_angular_momentum_onek(&self, kvec: &Array1<f64>) -> Array3<Complex<f64>> {
1301 let li = Complex::<f64>::new(0.0, 1.0);
1307 let (v, hamk) = self.gen_v(kvec, Gauge::Atom);
1308 let (band, evec) = if let Ok((eigvals, eigvecs)) = hamk.eigh(UPLO::Lower) {
1309 (eigvals, eigvecs)
1310 } else {
1311 todo!()
1312 };
1313 let mut L = Array3::zeros((self.dim_r(), self.nsta(), self.nsta()));
1314 let mut U = Array3::zeros((self.nsta(), self.nsta(), self.nsta()));
1316 for (i, e1) in evec.iter().enumerate() {
1317 for (j, e2) in evec.iter().enumerate() {
1318 for (k, e3) in evec.iter().enumerate() {
1319 U[[i, j, k]] = (2.0 * e3 - e1 - e2) / (e1 - e3) / (e2 - e3);
1320 }
1321 }
1322 }
1323 let g_L = 1.0;
1325 for r in 0..self.dim_r() {
1326 for i in 0..self.nsta() {
1327 for j in 0..self.nsta() {
1328 L[[r, i, j]] = -li / 4.0 / g_L / mu_B;
1329 }
1330 }
1331 }
1332 L
1333 }
1334}
1335
1336impl Model {
1337 #[inline(always)]
1349 pub fn optical_geometry_n_onek<S: Data<Elem = f64>>(
1350 &self,
1351 k_vec: &ArrayBase<S, Ix1>,
1352 dir_1: &Array1<f64>,
1353 dir_2: &Array1<f64>,
1354 og: &Array1<f64>,
1355 eta: f64,
1356 ) -> (Array2<Complex<f64>>, Array2<Complex<f64>>, Array1<f64>) {
1357 let li: Complex<f64> = 1.0 * Complex::i();
1364 let (mut v, hamk): (Array3<Complex<f64>>, Array2<Complex<f64>>) =
1367 self.gen_v(&k_vec, Gauge::Atom); let mut J = v.view();
1369
1370 let J = J
1372 .outer_iter()
1373 .zip(dir_1.iter())
1374 .fold(Array2::zeros((self.nsta(), self.nsta())), |acc, (x, d)| {
1375 acc + &x * (*d + 0.0 * li)
1376 });
1377
1378 let v = v
1380 .outer_iter()
1381 .zip(dir_2.iter())
1382 .fold(Array2::zeros((self.nsta(), self.nsta())), |acc, (x, d)| {
1383 acc + &x * (*d + 0.0 * li)
1384 });
1385
1386 let (band, evec) = if let Ok((eigvals, eigvecs)) = hamk.eigh(UPLO::Lower) {
1387 (eigvals, eigvecs)
1388 } else {
1389 todo!()
1390 };
1391 let evec_conj = evec.t();
1392 let evec = evec.mapv(|x| x.conj());
1393
1394 let A1 = J.dot(&evec);
1395 let A1 = &evec_conj.dot(&A1);
1396 let A2 = v.dot(&evec);
1397 let A2 = evec_conj.dot(&A2);
1398 let A2 = A2.reversed_axes();
1399 let AA = A1 * A2;
1400
1401 let Complex { re, im } = AA.view().split_complex();
1402 let re = re.mapv(|x| Complex::new(2.0 * x, 0.0));
1403 let im = im.mapv(|x| Complex::new(0.0, -2.0 * x));
1404
1405 let n_og = og.len();
1406 assert_eq!(
1407 band.len(),
1408 self.nsta(),
1409 "this is strange for band's length is not equal to self.nsta()"
1410 );
1411
1412 let mut U0 = Array2::<Complex<f64>>::zeros((self.nsta(), self.nsta()));
1413 let mut Us = Array2::<Complex<f64>>::zeros((self.nsta(), self.nsta()));
1414
1415 for i in 0..self.nsta() {
1417 for j in 0..self.nsta() {
1418 let a = band[[i]] - band[[j]];
1419 U0[[i, j]] = Complex::new(a, 0.0);
1420 Us[[i, j]] = if a.abs() > 1e-6 {
1421 Complex::new(1.0 / a, 0.0)
1422 } else {
1423 Complex::new(0.0, 0.0)
1424 };
1425 }
1426 }
1427
1428 let mut matric_n = Array2::zeros((n_og, self.nsta()));
1429 let mut omega_n = Array2::zeros((n_og, self.nsta()));
1430
1431 Zip::from(omega_n.outer_iter_mut())
1433 .and(matric_n.outer_iter_mut())
1434 .and(og.view())
1435 .for_each(|mut omega, mut matric, a0| {
1436 let li_eta = a0 + li * eta;
1437 let UU = U0.mapv(|x| (x * x - li_eta * li_eta).finv());
1438 let U1 = &UU * &Us * li_eta;
1439
1440 let o = im
1441 .outer_iter()
1442 .zip(UU.outer_iter())
1443 .map(|(a, b)| a.dot(&b))
1444 .collect();
1445 let m = re
1446 .outer_iter()
1447 .zip(U1.outer_iter())
1448 .map(|(a, b)| a.dot(&b))
1449 .collect();
1450 let o = Array1::from_vec(o);
1451 let m = Array1::from_vec(m);
1452 omega.assign(&o);
1453 matric.assign(&m);
1454 });
1455
1456 (matric_n, omega_n, band)
1457 }
1458
1459 pub fn optical_conductivity(
1460 &self,
1461 k_mesh: &Array1<usize>,
1462 dir_1: &Array1<f64>,
1463 dir_2: &Array1<f64>,
1464 T: f64,
1465 mu: f64,
1466 og: &Array1<f64>,
1467 eta: f64,
1468 ) -> Result<(Array1<Complex<f64>>, Array1<Complex<f64>>)>
1469{
1471 let li: Complex<f64> = 1.0 * Complex::i();
1472 let kvec: Array2<f64> = gen_kmesh(k_mesh)?;
1473 let nk: usize = kvec.len_of(Axis(0));
1474 let n_og = og.len();
1475 let (matric_sum, omega_sum) = kvec
1476 .outer_iter()
1477 .into_par_iter()
1478 .map(|k| {
1479 let (matric_n, omega_n, band) =
1480 self.optical_geometry_n_onek(&k, dir_1, dir_2, og, eta);
1481 let fermi_dirac = if T == 0.0 {
1482 band.mapv(|x| if x > mu { 0.0 } else { 1.0 })
1483 } else {
1484 let beta = 1.0 / T / 8.617e-5;
1485 band.mapv(|x| ((beta * (x - mu)).exp() + 1.0).recip())
1486 };
1487 let fermi_dirac = fermi_dirac.mapv(|x| Complex::new(x, 0.0));
1488 let matric = matric_n.dot(&fermi_dirac);
1489 let omega = omega_n.dot(&fermi_dirac);
1490 (matric, omega)
1491 })
1492 .reduce(
1493 || (Array1::zeros(n_og), Array1::zeros(n_og)),
1494 |(matric_acc, omega_acc), (matric, omega)| (matric_acc + matric, omega_acc + omega),
1495 );
1496 let matric_sum = li * matric_sum / self.lat.det().unwrap() / (nk as f64);
1497 let omega_sum = li * omega_sum / self.lat.det().unwrap() / (nk as f64);
1498 Ok((matric_sum, omega_sum))
1499 }
1500
1501 pub fn optical_conductivity_T(
1502 &self,
1503 k_mesh: &Array1<usize>,
1504 dir_1: &Array1<f64>,
1505 dir_2: &Array1<f64>,
1506 T: &Array1<f64>,
1507 mu: f64,
1508 og: &Array1<f64>,
1509 eta: f64,
1510 ) -> Result<(Array2<Complex<f64>>, Array2<Complex<f64>>)> {
1511 let li: Complex<f64> = 1.0 * Complex::i();
1512 let kvec: Array2<f64> = gen_kmesh(k_mesh)?;
1513 let nk: usize = kvec.len_of(Axis(0));
1514 let n_og = og.len();
1515 let n_T = T.len();
1516 let (matric_sum, omega_sum) = kvec
1517 .outer_iter()
1518 .into_par_iter()
1519 .map(|k| {
1520 let (matric_n, omega_n, band) =
1521 self.optical_geometry_n_onek(&k, dir_1, dir_2, og, eta);
1522 let beta = T.mapv(|x| 1.0 / x / 8.617e-5);
1523 let nsta = band.len();
1524 let n_T = beta.len();
1525 let mut fermi_dirac: Array2<Complex<f64>> = Array2::zeros((nsta, n_T));
1526 Zip::from(fermi_dirac.outer_iter_mut())
1527 .and(band.view())
1528 .for_each(|mut f0, e0| {
1529 let a = beta
1530 .map(|x0| Complex::new(((x0 * (e0 - mu)).exp() + 1.0).recip(), 0.0));
1531 f0.assign(&a);
1532 });
1533 let matric = matric_n.dot(&fermi_dirac);
1534 let omega = omega_n.dot(&fermi_dirac);
1535 (matric, omega)
1536 })
1537 .reduce(
1538 || (Array2::zeros((n_og, n_T)), Array2::zeros((n_og, n_T))),
1539 |(matric_acc, omega_acc), (matric, omega)| (matric_acc + matric, omega_acc + omega),
1540 );
1541 let matric_sum = li * matric_sum / self.lat.det().unwrap() / (nk as f64);
1542 let omega_sum = li * omega_sum / self.lat.det().unwrap() / (nk as f64);
1543 Ok((matric_sum, omega_sum))
1544 }
1545
1546 pub fn optical_conductivity_all_direction(
1551 &self,
1552 k_mesh: &Array1<usize>,
1553 T: f64,
1554 mu: f64,
1555 og: &Array1<f64>,
1556 eta: f64,
1557 ) -> Result<(Array2<Complex<f64>>, Array2<Complex<f64>>)> {
1558 let li: Complex<f64> = 1.0 * Complex::i();
1559 let kvec: Array2<f64> = gen_kmesh(k_mesh)?;
1560 let nk: usize = kvec.len_of(Axis(0));
1561 let n_og = og.len();
1562 let (matric,omega):(Vec<_>,Vec<_>)=kvec.outer_iter().into_par_iter()
1563 .map(|k| {
1564 let (mut v, hamk): (Array3<Complex<f64>>,Array2<Complex<f64>>) = self.gen_v(&k,Gauge::Atom); let (band, evec) = if let Ok((eigvals, eigvecs)) = hamk.eigh(UPLO::Lower) {
1567 (eigvals, eigvecs)
1568 } else {
1569 todo!()
1570 };
1571 let evec_conj=evec.t();
1572 let evec= evec.mapv(|x| x.conj());
1573
1574 let mut A = Array3::zeros((self.dim_r(),self.nsta(),self.nsta()));
1575 Zip::from(A.outer_iter_mut()).and(v.outer_iter()).for_each(|mut a,v| a.assign(&evec_conj.dot(&v.dot(&evec))));
1577
1578 let mut U0=Array2::zeros((self.nsta(),self.nsta()));
1580 let mut Us=Array2::zeros((self.nsta(),self.nsta()));
1581 for i in 0..self.nsta() {
1582 for j in 0..self.nsta() {
1583 let a = band[[i]] - band[[j]];
1584 U0[[i, j]] = Complex::new(a, 0.0);
1585 Us[[i, j]] = if a.abs() > 1e-6 {
1586 Complex::new(1.0 / a, 0.0)
1587 } else {
1588 Complex::new(0.0, 0.0)
1589 };
1590 }
1591 }
1592
1593 let fermi_dirac=if T==0.0{
1594 band.mapv(|x| if x>mu {0.0} else {1.0})
1595 }else{
1596 let beta=1.0/T/8.617e-5;
1597 band.mapv(|x| {((beta*(x-mu)).exp()+1.0).recip()})
1598 };
1599 let fermi_dirac=fermi_dirac.mapv(|x| Complex::new(x,0.0));
1600
1601 let n_og=og.len();
1602 assert_eq!(band.len(), self.nsta(), "this is strange for band's length is not equal to self.nsta()");
1603
1604 let (matric_n,omega_n)=match self.dim_r(){
1605 3=>{
1606 let mut matric_n=Array2::zeros((6,n_og));
1607 let mut omega_n=Array2::zeros((3,n_og));
1608 let A_xx=&A.slice(s![0,..,..])*&A.slice(s![0,..,..]).t();
1609 let A_yy=&A.slice(s![1,..,..])*&A.slice(s![1,..,..]).t();
1610 let A_zz=&A.slice(s![2,..,..])*&A.slice(s![2,..,..]).t();
1611 let A_xy=&A.slice(s![0,..,..])*&A.slice(s![1,..,..]).t();
1612 let A_yz=&A.slice(s![1,..,..])*&A.slice(s![2,..,..]).t();
1613 let A_xz=&A.slice(s![0,..,..])*&A.slice(s![2,..,..]).t();
1614 let re_xx:Array2<Complex<f64>> = Complex::new(2.0,0.0)*A_xx;
1615 let re_yy:Array2<Complex<f64>> = Complex::new(2.0,0.0)*A_yy;
1616 let re_zz:Array2<Complex<f64>> = Complex::new(2.0,0.0)*A_zz;
1617 let Complex { re, im } = A_xy.view().split_complex();
1618 let re_xy:Array2<Complex<f64>> = re.mapv(|x| Complex::new(2.0*x, 0.0));
1619 let im_xy:Array2<Complex<f64>> = im.mapv(|x| Complex::new(0.0, -2.0*x));
1620 let Complex { re, im } = A_yz.view().split_complex();
1621 let re_yz:Array2<Complex<f64>> = re.mapv(|x| Complex::new(2.0*x, 0.0));
1622 let im_yz:Array2<Complex<f64>> = im.mapv(|x| Complex::new(0.0, -2.0*x));
1623 let Complex { re, im } = A_xz.view().split_complex();
1624 let re_xz:Array2<Complex<f64>> = re.mapv(|x| Complex::new(2.0*x, 0.0));
1625 let im_xz:Array2<Complex<f64>> = im.mapv(|x| Complex::new(0.0, -2.0*x));
1626 Zip::from(omega_n.axis_iter_mut(Axis(1)))
1628 .and(matric_n.axis_iter_mut(Axis(1)))
1629 .and(og.view())
1630 .par_for_each(|mut omega, mut matric, a0| {
1631 let li_eta = a0 + li * eta;
1632 let UU = U0.mapv(|x| (x*x - li_eta*li_eta).finv());
1633 let U1:Array2<Complex<f64>> = &UU * &Us * li_eta;
1634
1635 let m = re_xx.outer_iter().zip(U1.outer_iter()).map(|(a, b)| a.dot(&b)).collect();
1636 let m = Array1::from_vec(m).dot(&fermi_dirac);
1637 matric[[0]]=m;
1638 let m = re_yy.outer_iter().zip(U1.outer_iter()).map(|(a, b)| a.dot(&b)).collect();
1639 let m = Array1::from_vec(m).dot(&fermi_dirac);
1640 matric[[1]]=m;
1641 let m = re_zz.outer_iter().zip(U1.outer_iter()).map(|(a, b)| a.dot(&b)).collect();
1642 let m = Array1::from_vec(m).dot(&fermi_dirac);
1643 matric[[2]]=m;
1644
1645 let o = im_xy.outer_iter().zip(UU.outer_iter()).map(|(a, b)| a.dot(&b)).collect();
1646 let m = re_xy.outer_iter().zip(U1.outer_iter()).map(|(a, b)| a.dot(&b)).collect();
1647 let o = Array1::from_vec(o).dot(&fermi_dirac);
1648 let m = Array1::from_vec(m).dot(&fermi_dirac);
1649 omega[[0]]=o;
1650 matric[[3]]=m;
1651 let o = im_yz.outer_iter().zip(UU.outer_iter()).map(|(a, b)| a.dot(&b)).collect();
1652 let m = re_yz.outer_iter().zip(U1.outer_iter()).map(|(a, b)| a.dot(&b)).collect();
1653 let o = Array1::from_vec(o).dot(&fermi_dirac);
1654 let m = Array1::from_vec(m).dot(&fermi_dirac);
1655 omega[[1]]=o;
1656 matric[[4]]=m;
1657 let o = im_xz.outer_iter().zip(UU.outer_iter()).map(|(a, b)| a.dot(&b)).collect();
1658 let m = re_xz.outer_iter().zip(U1.outer_iter()).map(|(a, b)| a.dot(&b)).collect();
1659 let o = Array1::from_vec(o).dot(&fermi_dirac);
1660 let m = Array1::from_vec(m).dot(&fermi_dirac);
1661 omega[[2]]=o;
1662 matric[[5]]=m;
1663 });
1664 (matric_n,omega_n)
1665 },
1666 2=>{
1667 let mut matric_n=Array2::zeros((3,n_og));
1668 let mut omega_n=Array2::zeros((1,n_og));
1669 let A_xx=&A.slice(s![0,..,..])*&(A.slice(s![0,..,..]).reversed_axes());
1670 let A_yy=&A.slice(s![1,..,..])*&(A.slice(s![1,..,..]).reversed_axes());
1671 let A_xy=&A.slice(s![0,..,..])*&(A.slice(s![1,..,..]).reversed_axes());
1672 let re_xx:Array2<Complex<f64>> = Complex::new(2.0,0.0)*A_xx;
1673 let re_yy:Array2<Complex<f64>> = Complex::new(2.0,0.0)*A_yy;
1674 let Complex { re, im } = A_xy.view().split_complex();
1675 let re_xy:Array2<Complex<f64>> = re.mapv(|x| Complex::new(2.0*x, 0.0));
1676 let im_xy:Array2<Complex<f64>> = im.mapv(|x| Complex::new(0.0, -2.0*x));
1677 Zip::from(omega_n.axis_iter_mut(Axis(1)))
1679 .and(matric_n.axis_iter_mut(Axis(1)))
1680 .and(og.view())
1681 .par_for_each(|mut omega, mut matric, a0| {
1682 let li_eta = a0 + li * eta;
1683 let UU = U0.mapv(|x| (x*x - li_eta*li_eta).finv());
1684 let U1:Array2<Complex<f64>> = &UU * &Us * li_eta;
1685
1686 let m = re_xx.outer_iter().zip(U1.outer_iter()).map(|(a, b)| a.dot(&b)).collect();
1687 let m = Array1::from_vec(m).dot(&fermi_dirac);
1688 matric[[0]]=m;
1689 let m = re_yy.outer_iter().zip(U1.outer_iter()).map(|(a, b)| a.dot(&b)).collect();
1690 let m = Array1::from_vec(m).dot(&fermi_dirac);
1691 matric[[1]]=m;
1692
1693 let o = im_xy.outer_iter().zip(UU.outer_iter()).map(|(a, b)| a.dot(&b)).collect();
1694 let m = re_xy.outer_iter().zip(U1.outer_iter()).map(|(a, b)| a.dot(&b)).collect();
1695 let o = Array1::from_vec(o).dot(&fermi_dirac);
1696 let m = Array1::from_vec(m).dot(&fermi_dirac);
1697 omega[[0]]=o;
1698 matric[[2]]=m;
1699 });
1700 (matric_n,omega_n)
1701 },
1702 _=>panic!("Wrong, self.dim_r must be 2 or 3 for using optical_conductivity_all_direction")
1703 };
1704 (matric_n,omega_n)
1705 }).collect();
1706 let (matric_sum, omega_sum) = match self.dim_r() {
1707 3 => {
1708 let omega = omega
1709 .into_iter()
1710 .fold(Array2::zeros((3, n_og)), |omega_acc, omega| {
1711 omega_acc + omega
1712 });
1713 let matric = matric
1714 .into_iter()
1715 .fold(Array2::zeros((6, n_og)), |matric_acc, matric| {
1716 matric_acc + matric
1717 });
1718 (matric, omega)
1719 }
1720 2 => {
1721 let omega = omega
1722 .into_iter()
1723 .fold(Array2::zeros((1, n_og)), |omega_acc, omega| {
1724 omega_acc + omega
1725 });
1726 let matric = matric
1727 .into_iter()
1728 .fold(Array2::zeros((3, n_og)), |matric_acc, matric| {
1729 matric_acc + matric
1730 });
1731 (matric, omega)
1732 }
1733 _ => panic!(
1734 "Wrong, self.dim_r must be 2 or 3 for using optical_conductivity_all_direction"
1735 ),
1736 };
1737 let matric_sum = li * matric_sum / self.lat.det().unwrap() / (nk as f64);
1738 let omega_sum = li * omega_sum / self.lat.det().unwrap() / (nk as f64);
1739 Ok((matric_sum, omega_sum))
1740 }
1741}