8 void Caratheodory_kernel::init(nda::vector_const_view<std::complex<double>> mesh, nda::array_const_view<std::complex<double>, 3> data) {
9 _dim = data.shape()[1];
10 size_t nw = std::count_if(mesh.begin(), mesh.end(), [](
const std::complex<double> &w) { return w.imag() > 0; });
15 auto id = matrix_cplx_mpt::Identity(_dim, _dim);
16 auto val = matrix_cplx_mpt(_dim, _dim);
17 for (
int iw = mesh.shape()[0] - 1, w = 0; iw >= 0; --iw) {
18 if (mesh(iw).imag() < 0.0) {
continue; }
19 _mesh[w] = (complex_mpt(mesh(iw)) - I) / (complex_mpt(mesh(iw)) + I);
20 _Ws[w].resize(_dim, _dim);
21 for (
int i = 0; i < _dim; ++i) {
22 for (
int j = 0; j < _dim; ++j) { val(i, j) = complex_mpt(data(iw, i, j)); }
24 val = (
id - I * val) * (
id + I * val).inverse();
29 for (
int i = _mesh.size() - 1; i > 0; i--) {
32 bool is_Schur_1 =
true;
33 auto sqrt_one_i = sqrt_m(
id - Wi * Wi.adjoint(), is_Schur_1);
34 auto sqrt_two_i = sqrt_m(
id - Wi.adjoint() * Wi, is_Schur_1);
35 auto sqrt_one_i_inv = sqrt_one_i.inverse().eval();
37#pragma omp parallel for num_threads(NEVANLINNA_NUM_THREADS)
38 for (
int j = i - 1; j >= 0; j--) {
41 auto y_ij = complex_mpt{std::abs(zi), 0.} * (zi - zj) / zi / (One - std::conj(zi) * zj);
42 _Ws[j] = sqrt_one_i_inv * (Wj - Wi) * (
id - Wi.adjoint() * Wj).inverse().eval() * sqrt_two_i / y_ij;
44 _sqrt_one[i] = sqrt_one_i;
45 _sqrt_two[i] = sqrt_two_i.inverse();
49 _sqrt_one[0] = sqrt_m(
id - _Ws[0] * _Ws[0].adjoint(), is_Schur);
50 _sqrt_two[0] = sqrt_m(
id - _Ws[0].adjoint() * _Ws[0], is_Schur).inverse();
54 if (_dim == 0) {
throw Nevanlinna_uninitialized_error(
"Empty continuation data. Please run solve(...) first."); }
55 auto id = matrix_cplx_mpt::Identity(_dim, _dim);
56 nda::array<std::complex<double>, 3> results(grid.shape()[0], _dim, _dim);
57#pragma omp parallel num_threads(NEVANLINNA_NUM_THREADS)
59 std::vector<matrix_cplx_mpt> Vs(_mesh.size());
60 std::vector<matrix_cplx_mpt> Fs(_mesh.size());
61 for (
auto i : mpi::chunk(omp_chunk(range(grid.size())))) {
62 auto z = (complex_mpt(grid(i)) - I) / (complex_mpt(grid(i)) + I);
65 Vs[0] = complex_mpt{std::abs(z0), 0.} * (z0 - z) / z0 / (One - std::conj(z0) * z) * id;
66 Fs[0] = (
id + Vs[0] * W0.adjoint()).inverse() * (Vs[0] + W0);
67 for (
int j = 1; j < _mesh.size(); j++) {
71 Vs[j] = complex_mpt{std::abs(zj), 0.} * (zj - z) / zj / (One - std::conj(zj) * z) * _sqrt_one[j] * Fs[j - 1] * _sqrt_two[j];
73 Fs[j] = (
id + Vs[j] * Wj.adjoint()).inverse() * (Vs[j] + Wj);
76 auto val = matrix_cplx_mpt(-I * (
id + Fs[_mesh.size() - 1]).inverse() * (
id - Fs[_mesh.size() - 1]));
77 for (
int n = 0; n < _dim; ++n) {
78 for (
int m = 0; m < _dim; ++m) {
79 results(i, n, m) = std::complex<double>(val(n, m).real().convert_to<double>(), val(n, m).imag().convert_to<double>());
84 results = mpi::all_reduce(results);
99 Pick.block(i * N, j * N, N, N)(n, m) = std::complex<double>(val(n, m).real().convert_to<double>(), val(n, m).imag().convert_to<double>());
106 std::transform(eigenvalues.data(), eigenvalues.data() + eigenvalues.size(), pick_eigenvalues.begin(), [](
const std::complex<double> &r) { return r.real(); });
void init(nda::vector_const_view< std::complex< double > > mesh, nda::array_const_view< std::complex< double >, 3 > data) override
Build the full matrix-valued Caratheodory continuation from Matsubara-frequency input data.